-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c21c81
commit 704e13e
Showing
21 changed files
with
789 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
program Test; | ||
const a := 5; | ||
var j, sum, x; | ||
|
||
procedure Clojure(x); | ||
var j; | ||
begin | ||
j := 1; | ||
sum := 0; | ||
while j <= x do begin | ||
sum := sum + j; | ||
j := j + 1 | ||
end; | ||
write(sum) | ||
end | ||
|
||
begin | ||
read(x, j); | ||
call Clojure(j + 5); | ||
write(j) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum ByteCode {} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub struct TraceableByteCode { | ||
pub(crate) bytecode: ByteCode, | ||
pub(crate) line_num: usize, | ||
pub(crate) col_num: usize, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
use crate::lexer::Lexer; | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum UnaryOpCode { | ||
SetPositive, | ||
SetNegative, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum BinaryOpCode { | ||
// arithmetic | ||
Add, | ||
Sub, | ||
Mul, | ||
Div, | ||
// comparative | ||
CmpEq, | ||
CmpNe, | ||
CmpGt, | ||
CmpGe, | ||
CmpLt, | ||
CmpLe, | ||
// assign | ||
Assign, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum OpCode { | ||
Unary(UnaryOpCode), | ||
Binary(BinaryOpCode), | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum ByteCode { | ||
LoadConst { constant: i64 }, | ||
Operation { op_code: OpCode }, | ||
LoadVar { layer_dif: usize, offset: usize }, | ||
SetVar { layer_dif: usize, offset: usize }, | ||
Call { layer_dif: usize, offset: usize }, | ||
IncreaseSp { increment: usize }, | ||
JumpTo { offset: usize }, | ||
JumpIf { offset: usize }, | ||
ReadToVar { layer_dif: usize, offset: usize }, | ||
WriteTop, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub struct TraceableByteCode { | ||
pub(crate) bytecode: ByteCode, | ||
pub(crate) line_num: usize, | ||
pub(crate) col_num: usize, | ||
} | ||
|
||
impl TraceableByteCode { | ||
pub fn new(bytecode: ByteCode, line_num: usize, col_num: usize) -> Self { | ||
Self { | ||
bytecode, | ||
line_num, | ||
col_num, | ||
} | ||
} | ||
|
||
pub fn new_with_lexer_ref(bytecode: ByteCode, lexer_ref: &Lexer) -> Self { | ||
Self { | ||
bytecode, | ||
line_num: lexer_ref.line_num, | ||
col_num: lexer_ref.col_num, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,2 @@ | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum UnaryOpCode { | ||
SetPositive, | ||
SetNegative, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum BinaryOpCode { | ||
// arithmetic | ||
Add, | ||
Sub, | ||
Mul, | ||
Div, | ||
// comparative | ||
CmpEq, | ||
CmpNe, | ||
CmpGt, | ||
CmpGe, | ||
CmpLt, | ||
CmpLe, | ||
// assign | ||
Assign, | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum OpCode { | ||
Unary(UnaryOpCode), | ||
Binary(BinaryOpCode), | ||
} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum ByteCode { | ||
LoadConst { constant: i64 }, | ||
Operation { op_code: OpCode }, | ||
LoadVar { layer_dif: usize, offset: usize }, | ||
SetVar { layer_dif: usize, offset: usize }, | ||
Call { layer_dif: usize, offset: usize }, | ||
IncreaseSp { increment: usize }, | ||
JumpTo { offset: usize }, | ||
JumpIf { offset: usize }, | ||
ReadToVar { layer_dif: usize, offset: usize }, | ||
WriteTop, | ||
} | ||
pub mod advanced; | ||
pub mod basic; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
use crate::{bytecode::advanced::TraceableByteCode, value::Value}; | ||
|
||
pub(super) type FnBc2u8 = fn(u8, u8) -> TraceableByteCode; | ||
pub(super) type FnBc3u8 = fn(u8, u8, u8) -> TraceableByteCode; | ||
pub(super) type FnBcBool = fn(u8, u8, bool) -> TraceableByteCode; | ||
|
||
/// Expression description, inner layer between source code and byte code | ||
#[derive(Debug, PartialEq, Clone)] | ||
pub(super) enum ExprDesc { | ||
// Constants | ||
Nil, | ||
Integer(i64), | ||
|
||
// Variables | ||
Local(usize), | ||
UpValue(usize), | ||
|
||
// Closure Call | ||
Closure(usize), | ||
Call(usize, usize), | ||
VarArgs, | ||
|
||
// Arithmetic Operators | ||
UnaryOp { | ||
opcode: FnBc2u8, | ||
operand: usize, | ||
}, | ||
BinaryOp { | ||
opcode: FnBc3u8, | ||
l_operand: usize, | ||
r_operand: usize, | ||
}, | ||
|
||
// Relational Operators | ||
Compare { | ||
opcode: FnBcBool, | ||
l_operand: usize, | ||
r_operand: usize, | ||
true_list: Vec<usize>, | ||
false_list: Vec<usize>, | ||
}, | ||
} | ||
|
||
// see discharge_const() | ||
#[derive(Debug, Clone)] | ||
pub(super) enum ConstStack { | ||
Const(usize), | ||
Stack(usize), | ||
} | ||
|
||
/// Index of locals/up_values in upper functions | ||
#[derive(Debug, Clone)] | ||
pub(super) enum UpIndex { | ||
Local(usize), | ||
UpValue(usize), | ||
} | ||
|
||
/// Activation record for `procedure` (aka. `closure`) | ||
#[derive(Debug, Default, Clone)] | ||
pub struct ActivationRecord { | ||
pub(crate) has_var_args: bool, | ||
pub(crate) n_param: usize, | ||
pub(crate) constants: Vec<Value>, | ||
pub(crate) up_indexes: Vec<UpIndex>, | ||
pub(crate) byte_codes: Vec<TraceableByteCode>, | ||
} | ||
|
||
/// Level of inner functions, used for matching up_value | ||
#[derive(Debug, Default, Clone)] | ||
pub(super) struct Level { | ||
/// (name, referred_as_up_value) | ||
pub(super) locals: Vec<(String, bool)>, | ||
/// (name, index_of_up_value) | ||
pub(super) up_values: Vec<(String, UpIndex)>, | ||
} | ||
|
||
/// Mark both goto and label | ||
#[derive(Debug)] | ||
pub(super) struct GotoLabel { | ||
pub(super) name: String, | ||
pub(super) i_code: usize, | ||
pub(super) n_var: usize, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
pub mod desc; | ||
|
||
use self::desc::ActivationRecord; | ||
use crate::{ast::ProgramExpr, lexer::Lexer}; | ||
|
||
pub struct TreeWalkCodeGenerator<'a> { | ||
/// Marking original code (for better error handling) | ||
lexer: Lexer<'a>, | ||
/// The only legal entrance ast_node | ||
ast_entry: Box<ProgramExpr>, | ||
/// Aka. stack pointer | ||
sp: usize, | ||
/// Aka. activation_record | ||
ar: ActivationRecord, | ||
} | ||
|
||
impl<'a> TreeWalkCodeGenerator<'a> { | ||
pub fn new(ctx: &'a str, ast_entry: Box<ProgramExpr>) -> Self { | ||
Self { | ||
lexer: Lexer::new(ctx), | ||
ast_entry, | ||
sp: 0, | ||
ar: ActivationRecord::default(), | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
use super::{desc::ExprDesc, *}; | ||
|
||
#[allow(unused)] | ||
impl<'a> DirectParser<'a> { | ||
/// ```bnf | ||
/// <prog> -> program <id> ; <block> | ||
fn program(&mut self) { | ||
self.consume_next(Token::Program); | ||
let id = self.id(); | ||
self.consume_next(Token::Semicolon); | ||
} | ||
|
||
/// ```bnf | ||
/// <block> -> [<const-decl>][<var-decl>][<proc>]<body> | ||
fn block(&mut self) {} | ||
|
||
/// ```bnf | ||
/// <const-decl> -> const <const> {, <const>} ; | ||
fn const_decl(&mut self) {} | ||
|
||
/// ```bnf | ||
/// <var-decl> -> var <id> {, <id>} ; | ||
fn var_decl(&mut self) {} | ||
|
||
/// ```bnf | ||
/// <proc> -> procedure <id> ([<id> {, <id>}]) ; <block> {; <proc>} | ||
fn proc(&mut self) {} | ||
|
||
/// ```bnf | ||
/// <body> -> begin <statement> {; <statement>} end | ||
fn body(&mut self) {} | ||
|
||
/// ```bnf | ||
/// <statement> -> <id> := <exp> | ||
/// | if <l-exp> then <statement> [else <statement>] | ||
/// | while <l-exp> do <statement> | ||
/// | call <id> ([<exp> {, <exp>}]) | ||
/// | read (<id> {, <id>}) | ||
/// | write (<exp> {, <exp>}) | ||
/// | <body> | ||
/// | read (<id> {, <id>}) | ||
/// | write (<exp> {, <exp>}) | ||
fn statement(&mut self) {} | ||
|
||
/// ```bnf | ||
/// <l-exp> -> <exp> <lop> <exp> | odd <exp> | ||
pub(super) fn l_exp(&mut self) -> ExprDesc { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <exp> -> [+|-] <term> {<aop> <term>} | ||
fn exp(&mut self) -> ExprDesc { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <term> -> <factor> {<mop> <factor>} | ||
fn term(&mut self) -> ExprDesc { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <factor> -> <id> | <integer> | (<exp>) | ||
fn factor(&mut self) -> ExprDesc { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <lop> -> = | <> | < | <= | > | >= | ||
fn lop(&mut self) -> Option<Token> { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <aop> -> + | - | ||
fn aop(&mut self) -> Option<Token> { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <mop> -> * | / | ||
fn mop(&mut self) -> Option<Token> { | ||
unimplemented!() | ||
} | ||
|
||
/// ```bnf | ||
/// <id> -> @letter { @letter | @digit } | ||
fn id(&mut self) -> Option<String> { | ||
match self.consume_next_identifier() { | ||
Ok(id) => id.into(), | ||
Err(is_lexical_err) => { | ||
if is_lexical_err { | ||
while let Some(Token::LexicalError(_)) = self.ctx.lexer.peek() { | ||
self.consume_next_identifier().unwrap_err(); | ||
} | ||
} | ||
let err = CompileErrorBuilder::syntax_error_template() | ||
.with_lexer_ref(&self.ctx.lexer) | ||
.with_info("Expected <id> field, but not found!".to_string()) | ||
.build(); | ||
eprintln!("{}", err); | ||
None | ||
} | ||
} | ||
} | ||
|
||
/// ```bnf | ||
/// <integer> -> @digit { @digit } | ||
fn integer(&mut self) -> Option<i64> { | ||
match self.consume_next_integer() { | ||
Ok(integer) => integer.into(), | ||
Err(is_lexical_err) => { | ||
if is_lexical_err { | ||
while let Some(Token::LexicalError(_)) = self.ctx.lexer.peek() { | ||
self.consume_next_integer().unwrap_err(); | ||
} | ||
} | ||
let err = CompileErrorBuilder::syntax_error_template() | ||
.with_lexer_ref(&self.ctx.lexer) | ||
.with_info("Expected <integer> field, but not found!".to_string()) | ||
.build(); | ||
eprintln!("{}", err); | ||
None | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.