Skip to content

Commit

Permalink
biggest refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
DrEden33773 committed Dec 16, 2023
1 parent 9c21c81 commit 704e13e
Show file tree
Hide file tree
Showing 21 changed files with 789 additions and 49 deletions.
21 changes: 21 additions & 0 deletions examples/correct/test.pas
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
9 changes: 9 additions & 0 deletions src/bytecode/advanced.rs
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,
}
70 changes: 70 additions & 0 deletions src/bytecode/basic.rs
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,
}
}
}
45 changes: 2 additions & 43 deletions src/bytecode/mod.rs
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;
83 changes: 83 additions & 0 deletions src/codegen/desc.rs
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,
}
26 changes: 26 additions & 0 deletions src/codegen/mod.rs
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(),
}
}
}
128 changes: 128 additions & 0 deletions src/direct_parser/bnf_frame.rs
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
}
}
}
}
Loading

0 comments on commit 704e13e

Please sign in to comment.