diff --git a/src/bytecode/advanced.rs b/src/bytecode/advanced.rs deleted file mode 100644 index 56e2fb7..0000000 --- a/src/bytecode/advanced.rs +++ /dev/null @@ -1,120 +0,0 @@ -#[derive(Debug, Clone, Copy)] -pub enum ByteCode { - // local variable - LoadConst(u8, u16), - LoadNil(u8, u8), - LoadBool(u8, bool), - LoadInt(u8, i16), - Move(u8, u8), - - // up_values - GetUpvalue(u8, u8), - SetUpvalue(u8, u8), - SetUpvalueConst(u8, u8), - Close(u8), - - // table - NewTable(u8, u8, u8), - SetTable(u8, u8, u8), - SetField(u8, u8, u8), - SetInt(u8, u8, u8), - SetTableConst(u8, u8, u8), - SetFieldConst(u8, u8, u8), - SetIntConst(u8, u8, u8), - SetList(u8, u8), - GetTable(u8, u8, u8), - GetField(u8, u8, u8), - GetInt(u8, u8, u8), - GetFieldSelf(u8, u8, u8), - - // upvalue table, covers global variables - SetUpField(u8, u8, u8), - SetUpFieldConst(u8, u8, u8), - GetUpField(u8, u8, u8), - - // condition structures - Jump(i16), - TestAndJump(u8, i16), - TestOrJump(u8, i16), - TestAndSetJump(u8, u8, u8), - TestOrSetJump(u8, u8, u8), - - // for-loop - ForPrepare(u8, u16), - ForLoop(u8, u16), - ForCallLoop(u8, u8, u8), - - // function call - Closure(u8, u16), - Call(u8, u8, u8), - CallSet(u8, u8, u8), - TailCall(u8, u8), - Return0, - Return(u8, u8), - VarArgs(u8, u8), - - // unary ops - Neg(u8, u8), - Not(u8, u8), - BitNot(u8, u8), - Len(u8, u8), - - // binary ops - Add(u8, u8, u8), - AddConst(u8, u8, u8), - AddInt(u8, u8, u8), - Sub(u8, u8, u8), - SubInt(u8, u8, u8), - SubConst(u8, u8, u8), - Mul(u8, u8, u8), - MulInt(u8, u8, u8), - MulConst(u8, u8, u8), - Mod(u8, u8, u8), - ModInt(u8, u8, u8), - ModConst(u8, u8, u8), - Div(u8, u8, u8), - DivInt(u8, u8, u8), - DivConst(u8, u8, u8), - Idiv(u8, u8, u8), - IdivInt(u8, u8, u8), - IdivConst(u8, u8, u8), - Pow(u8, u8, u8), - PowInt(u8, u8, u8), - PowConst(u8, u8, u8), - BitAnd(u8, u8, u8), - BitAndInt(u8, u8, u8), - BitAndConst(u8, u8, u8), - BitXor(u8, u8, u8), - BitXorInt(u8, u8, u8), - BitXorConst(u8, u8, u8), - BitOr(u8, u8, u8), - BitOrInt(u8, u8, u8), - BitOrConst(u8, u8, u8), - ShiftL(u8, u8, u8), - ShiftLInt(u8, u8, u8), - ShiftLConst(u8, u8, u8), - ShiftR(u8, u8, u8), - ShiftRInt(u8, u8, u8), - ShiftRConst(u8, u8, u8), - - Equal(u8, u8, bool), - EqualInt(u8, u8, bool), - EqualConst(u8, u8, bool), - NotEq(u8, u8, bool), - NotEqInt(u8, u8, bool), - NotEqConst(u8, u8, bool), - LesEq(u8, u8, bool), - LesEqInt(u8, u8, bool), - LesEqConst(u8, u8, bool), - GreEq(u8, u8, bool), - GreEqInt(u8, u8, bool), - GreEqConst(u8, u8, bool), - Less(u8, u8, bool), - LessInt(u8, u8, bool), - LessConst(u8, u8, bool), - Greater(u8, u8, bool), - GreaterInt(u8, u8, bool), - GreaterConst(u8, u8, bool), - - SetFalseSkip(u8), -} diff --git a/src/bytecode/basic.rs b/src/bytecode/basic.rs deleted file mode 100644 index 267b04f..0000000 --- a/src/bytecode/basic.rs +++ /dev/null @@ -1,29 +0,0 @@ -#[derive(Debug, Clone, Copy)] -pub enum OpCode { - // arithmetic - Add, - Sub, - Mul, - Div, - // comparative - CmpEq, - CmpNe, - CmpGt, - CmpGe, - CmpLt, - CmpLe, -} - -#[derive(Debug, Clone, Copy)] -pub enum ByteCode { - LIT, - OPR, - LOD, - STO, - CAL, - INT, - JMP, - JPC, - RED, - WRT, -} diff --git a/src/bytecode/mod.rs b/src/bytecode/mod.rs deleted file mode 100644 index 696d603..0000000 --- a/src/bytecode/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod advanced; diff --git a/src/codegen/desc.rs b/src/codegen/desc.rs deleted file mode 100644 index f6bf01a..0000000 --- a/src/codegen/desc.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::{bytecode::advanced::ByteCode, error::compile_error::CompileError, value::Value}; - -pub(super) type FnBc2u8 = fn(u8, u8) -> ByteCode; -pub(super) type FnBc3u8 = fn(u8, u8, u8) -> ByteCode; -pub(super) type FnBcBool = fn(u8, u8, bool) -> ByteCode; - -/// Expression description, inner layer between source code and byte code -#[derive(Debug, PartialEq, Clone)] -pub(super) enum ExprDesc { - // Constants - Nil, - Integer(i64), - Boolean(bool), - String(String), - - // Variables - Local(usize), - UpValue(usize), - - // function Call - Function(usize), - Closure(usize), - Call(usize, usize), - VarArgs, - - // table index - Index(usize, usize), - IndexField(usize, usize), - IndexInt(usize, u8), - IndexUpField(usize, usize), // covers global variables - - // Arithmetic Operators - UnaryOp { - op: FnBc2u8, - operand: usize, - }, - BinaryOp { - op: FnBc3u8, - l_operand: usize, - r_operand: usize, - }, - - // binary logical operators: 'and', 'or' - Test { - condition: Box, - true_list: Vec, - false_list: Vec, - }, - - // Relational Operators - Compare { - op: FnBcBool, - l_operand: usize, - r_operand: usize, - true_list: Vec, - false_list: Vec, - }, -} - -impl From for ExprDesc { - fn from(v: String) -> Self { - Self::String(v) - } -} - -impl From for ExprDesc { - fn from(v: bool) -> Self { - Self::Boolean(v) - } -} - -impl From for ExprDesc { - fn from(v: i64) -> Self { - Self::Integer(v) - } -} - -impl From<()> for ExprDesc { - fn from(_: ()) -> Self { - Self::Nil - } -} - -// 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(super) has_var_args: bool, - pub(super) n_param: usize, - pub(super) constants: Vec, - pub(super) up_indexes: Vec, - pub(super) byte_codes: Vec, -} - -/// 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) upvalues: 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, -} diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs deleted file mode 100644 index b15e9b0..0000000 --- a/src/codegen/mod.rs +++ /dev/null @@ -1,540 +0,0 @@ -#![allow(unused)] - -pub mod desc; - -use std::{ops::Deref, rc::Rc}; - -use self::desc::{ActivationRecord, ConstStack, ExprDesc, Level}; -use crate::{ - ast::{ - AstExpr, BlockExpr, ConstDeclExpr, ExpExpr, LExpExpr, ProcExpr, ProgramExpr, StatementExpr, - VarDeclExpr, - }, - bytecode::advanced::ByteCode, - codegen::desc::UpIndex, - error::compile_error::CompileError, - lexer::Lexer, - value::Value, -}; - -struct CodegenContext { - /// Levels of current context - levels: Vec, -} - -impl CodegenContext { - fn new() -> Self { - Self { levels: vec![] } - } -} - -/// - l_ctx: ctx's *lifetime* -/// - l_lex: ctx.lexer's *lifetime* -/// -/// l_lex `is longer than` l_ctx -pub struct TreeWalkCodeGenerator<'l_ctx> { - /// Marking original code (for better error handling) - ctx: &'l_ctx mut CodegenContext, - /// The only legal entrance ast_node - curr_ast: AstExpr, - /// Aka. stack pointer - sp: usize, - /// Aka. activation_record - ar: ActivationRecord, -} - -impl<'a> TreeWalkCodeGenerator<'a> { - fn program(&mut self) { - let n_var = self.local_num(); - self.program_scope(); - self.local_expire(n_var); - } - - fn program_scope(&mut self) {} - - fn block(&mut self, expr: &BlockExpr) {} - - fn const_decl(&mut self, expr: &ConstDeclExpr) {} - - fn var_decl(&mut self, expr: &VarDeclExpr) {} - - fn proc(&mut self, expr: &ProcExpr) { - self.func_def(expr) - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - /// ```bnf - /// -> procedure ([ {, }]) ; {; } - fn func_def(&mut self, expr: &ProcExpr) { - let name = expr.id.as_ref().0.to_owned(); - let name_info = expr.id.as_ref().1; - let mut name_desc = self.simple_name(name); - - let body = self.func_body(expr); - } - - // () / (id) / (id, id, ...) - fn func_body(&mut self, expr: &ProcExpr) -> ExprDesc { - // parameter list - let mut has_var_args = false; - let mut params = expr - .args - .iter() - .map(|id| id.0.to_owned()) - .collect::>(); - - // body(block) - // BUG - let ar = chunk(self.ctx, has_var_args, params, &expr.block); - - let has_upvalue = !ar.up_indexes.is_empty(); - let i_const = self.add_const(Value::PL0Function(Rc::new(ar))); - if has_upvalue { - ExprDesc::Closure(i_const) - } else { - ExprDesc::Function(i_const) - } - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - fn l_exp(&mut self, expr: &LExpExpr) -> ExprDesc { - fn is_odd(i: i64) -> bool { - i % 2 == 1 - }; - match expr { - LExpExpr::Exp { l_exp, lop, r_exp } => { - todo!() - } - LExpExpr::Odd { exp } => { - todo!() - } - } - } - - fn exp(&mut self, expr: &ExpExpr) -> ExprDesc { - unimplemented!() - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - /// ```bnf - /// - /// -> := - /// | if then [else ] - /// | while do - /// | call ([ {, }]) - /// | - /// | read ( {, }) - /// | write ( {, }) - fn stat(&mut self, expr: &StatementExpr) { - match expr { - StatementExpr::Id { id, exp } => todo!(), - StatementExpr::If { .. } => self.if_stat(expr), - StatementExpr::While { .. } => self.while_stat(expr), - StatementExpr::Call { id, args } => todo!(), - StatementExpr::Body { body } => todo!(), - StatementExpr::Read { id_list } => todo!(), - StatementExpr::Write { exps } => todo!(), - } - } - - /// ```bnf - /// -> - fn body_stat(&mut self) {} - - /// ```bnf - /// while do - fn while_stat(&mut self, expr: &StatementExpr) { - if let StatementExpr::While { l_exp, statement } = expr.to_owned() { - let i_start = self.ar.byte_codes.len(); - - let condition = self.l_exp(&l_exp); - let false_list = self.test_or_jump(condition); - - self.stat(&statement); - - // jump back - let i_end = self.ar.byte_codes.len(); - - self - .ar - .byte_codes - .push(ByteCode::Jump(-((i_end - i_start) as i16) - 1)); - - self.fix_test_list(false_list); - } - } - - /// ```bnf - /// if then [else ] - fn if_stat(&mut self, expr: &StatementExpr) { - if let StatementExpr::If { - l_exp, - then_statement, - else_statement, - } = expr.to_owned() - { - let mut jmp_ends = vec![]; - self.do_if_block(&mut jmp_ends, expr); - - if let Some(expr) = else_statement { - self.stat(&expr) - } - - let i_end = self.ar.byte_codes.len() - 1; - for i in jmp_ends { - self.ar.byte_codes[i] = ByteCode::Jump((i_end - 1) as i16); - } - } - } - - fn do_if_block(&mut self, jmp_ends: &mut Vec, expr: &StatementExpr) { - if let StatementExpr::If { - l_exp, - then_statement, - else_statement, - } = expr.to_owned() - { - let condition = self.l_exp(&l_exp); - let false_list = self.test_or_jump(condition); - - if else_statement.is_some() { - self.ar.byte_codes.push(ByteCode::Jump(0)); - jmp_ends.push(self.ar.byte_codes.len() - 1); - } - - self.fix_test_list(false_list); - } - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - // match the name as `local`, `upvalue`, or `global` - fn simple_name(&mut self, name: String) -> ExprDesc { - let mut level_iter = self.ctx.levels.iter_mut().rev(); - - // search from locals and upvalues in current level - let level = level_iter.next().unwrap(); - // search from `locals` - if let Some(i) = level.locals.iter().rposition(|v| v.0 == name) { - // search reversely, so new variable covers old one with same name - return ExprDesc::Local(i); - } - // search from `upvalues` - if let Some(i) = level.upvalues.iter().position(|v| v.0 == name) { - return ExprDesc::UpValue(i); - } - - // search in upper levels - for (depth, level) in level_iter.enumerate() { - if let Some(i) = level.locals.iter().rposition(|v| v.0 == name) { - level.locals[i].1 = true; // mark it referred as upvalue - return self.create_upvalue(name, UpIndex::Local(i), depth); - } - if let Some(i) = level.upvalues.iter().position(|v| v.0 == name) { - return self.create_upvalue(name, UpIndex::UpValue(i), depth); - } - } - - // not matched as local or upvalue, so global variable, by _ENV[name] - let i_name = self.add_const(name); - match self.simple_name("_ENV".into()) { - ExprDesc::Local(i) => ExprDesc::IndexField(i, i_name), - ExprDesc::UpValue(i) => ExprDesc::IndexUpField(i, i_name), - _ => panic!("not here"), // because "_ENV" must exist! - } - } - - fn create_upvalue(&mut self, name: String, mut up_idx: UpIndex, depth: usize) -> ExprDesc { - let levels = &mut self.ctx.levels; - let last = levels.len() - 1; - - // create upvalue in middle levels, if any - for Level { upvalues, .. } in levels[last - depth..last].iter_mut() { - upvalues.push((name.clone(), up_idx)); - up_idx = UpIndex::UpValue(upvalues.len() - 1); - } - - // create upvalue in current level - let upvalues = &mut levels[last].upvalues; - upvalues.push((name, up_idx)); - ExprDesc::UpValue(upvalues.len() - 1) - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - /// add the value to constants - fn add_const(&mut self, c: impl Into) -> usize { - let c = c.into(); - let constants = &mut self.ar.constants; - constants - .iter() - .position(|v| v.same(&c)) - .unwrap_or_else(|| { - constants.push(c); - constants.len() - 1 - }) - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - /// discharge @desc into the top of stack, if need - fn discharge_any(&mut self, desc: ExprDesc) -> usize { - let dst = if let &ExprDesc::Call(i_func, _) = &desc { - i_func - } else { - self.sp - }; - self.discharge_if_need(dst, desc) - } - - /// discharge @desc into @dst, if need - fn discharge_if_need(&mut self, dst: usize, desc: ExprDesc) -> usize { - if let ExprDesc::Local(i) = desc { - i // no need - } else { - self.discharge(dst, desc); - dst - } - } - - /// discharge @desc into @dst, and update `self.sp = dst+1`` - fn discharge(&mut self, dst: usize, desc: ExprDesc) { - let code = match desc { - ExprDesc::Nil => ByteCode::LoadNil(dst as u8, 1), - ExprDesc::Boolean(b) => ByteCode::LoadBool(dst as u8, b), - ExprDesc::Integer(i) => { - if let Ok(i) = i16::try_from(i) { - ByteCode::LoadInt(dst as u8, i) - } else { - ByteCode::LoadConst(dst as u8, self.add_const(i) as u16) - } - } - ExprDesc::String(s) => ByteCode::LoadConst(dst as u8, self.add_const(s) as u16), - ExprDesc::Local(src) => { - if dst != src { - ByteCode::Move(dst as u8, src as u8) - } else { - return; - } - } - ExprDesc::UpValue(src) => ByteCode::GetUpvalue(dst as u8, src as u8), - ExprDesc::VarArgs => ByteCode::VarArgs(dst as u8, 1), - ExprDesc::Call(i_func, n_arg_plus) => { - ByteCode::CallSet(dst as u8, i_func as u8, n_arg_plus as u8) - } - ExprDesc::UnaryOp { op, operand } => op(dst as u8, operand as u8), - ExprDesc::BinaryOp { - op, - l_operand, - r_operand, - } => op(dst as u8, l_operand as u8, r_operand as u8), - ExprDesc::Test { - condition, - true_list, - false_list, - } => { - // fix TestSet list after discharging - self.discharge(dst, *condition); - self.fix_test_set_list(true_list, dst); - self.fix_test_set_list(false_list, dst); - return; - } - ExprDesc::Compare { - op, - l_operand, - r_operand, - true_list, - false_list, - } => { - self - .ar - .byte_codes - .push(op(l_operand as u8, r_operand as u8, false)); - - // terminate false_list to SetFalseSkip - self.fix_test_list(false_list); - self.ar.byte_codes.push(ByteCode::SetFalseSkip(dst as u8)); - - // terminate true_list to LoadBool (true) - self.fix_test_list(true_list); - ByteCode::LoadBool(dst as u8, true) - } - _ => todo!(), - }; - self.ar.byte_codes.push(code); - self.sp = dst + 1; - } - - /// For constant types, add @desc to constants - /// - /// Otherwise, discharge @desc into stack - fn discharge_const(&mut self, desc: ExprDesc) -> ConstStack { - match desc { - ExprDesc::Nil => ConstStack::Const(self.add_const(())), - ExprDesc::Boolean(b) => ConstStack::Const(self.add_const(b)), - ExprDesc::Integer(i) => ConstStack::Const(self.add_const(i)), - ExprDesc::String(s) => ConstStack::Const(self.add_const(s)), - ExprDesc::Function(f) => ConstStack::Const(f), - _ => todo!(), - } - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - /// Generate a TestOrJump: test @condition or jump to somewhere unknown. - /// - /// Link the new code to previous false-list if any. - /// - /// Close true_list if any. - /// - /// Return false_list to be fixed later in fix_test_list() - fn test_or_jump(&mut self, condition: ExprDesc) -> Vec { - let (code, true_list, mut false_list) = match condition { - ExprDesc::Boolean(true) | ExprDesc::Integer(_) | ExprDesc::String(_) => { - // always true, no need to test or jump - return Vec::new(); - } - ExprDesc::Compare { - op, - l_operand, - r_operand, - true_list, - false_list, - } => { - self - .ar - .byte_codes - .push(op(l_operand as u8, r_operand as u8, true)); - (ByteCode::Jump(0), Some(true_list), false_list) - } - _ => { - let i_condition = self.discharge_any(condition); - (ByteCode::TestOrJump(i_condition as u8, 0), None, vec![]) - } - }; - unimplemented!() - } - - /// fix TestAndJump/TestOrJump list to jump to current place - fn fix_test_list(&mut self, list: Vec) { - let here = self.ar.byte_codes.len(); - self.fix_test_list_to(list, here); - } - - /// fix TestAndJump/TestOrJump list to jump to $to - fn fix_test_list_to(&mut self, list: Vec, to: usize) { - for i in list { - let jmp = (to as isize - i as isize - 1) as i16; - let code = match self.ar.byte_codes[i] { - ByteCode::Jump(0) => ByteCode::Jump(jmp), - ByteCode::TestOrJump(i_condition, 0) => ByteCode::TestOrJump(i_condition, jmp), - ByteCode::TestAndJump(i_condition, 0) => ByteCode::TestAndJump(i_condition, jmp), - _ => panic!("invalid test"), - }; - self.ar.byte_codes[i] = code; - } - } - - // fix TestAndJump/TestOrJump list to TestAndSetJump/TestOrSetJump - fn fix_test_set_list(&mut self, list: Vec, dst: usize) { - let here = self.ar.byte_codes.len(); - let dst = dst as u8; - for i in list.into_iter() { - let jmp = here - i - 1; // should not be negative - let code = match self.ar.byte_codes[i] { - ByteCode::Jump(0) => ByteCode::Jump(jmp as i16), - ByteCode::TestOrJump(i_condition, 0) => { - if i_condition == dst { - ByteCode::TestOrJump(i_condition, jmp as i16) - } else { - ByteCode::TestOrSetJump(dst, i_condition, jmp as u8) - } - } - ByteCode::TestAndJump(i_condition, 0) => { - if i_condition == dst { - ByteCode::TestAndJump(i_condition, jmp as i16) - } else { - ByteCode::TestAndSetJump(dst, i_condition, jmp as u8) - } - } - _ => panic!("invalid Test"), - }; - self.ar.byte_codes[i] = code; - } - } -} - -impl<'a> TreeWalkCodeGenerator<'a> { - /// generate Close if any local variable in [from..] referred as upvalue - fn local_check_close(&mut self, from: usize) { - let mut vars = self.ctx.levels.last().unwrap().locals[from..].iter(); - if vars.any(|(_, referred_as_up_value)| *referred_as_up_value) { - self.ar.byte_codes.push(ByteCode::Close(from as u8)); - } - } - - fn local_expire(&mut self, from: usize) { - // drop locals - let mut vars = self.ctx.levels.last_mut().unwrap().locals.drain(from..); - // generate Close if any dropped local variable referred as upvalue - if vars.any(|(name, referred_as_up_value)| referred_as_up_value) { - self.ar.byte_codes.push(ByteCode::Close(from as u8)); - } - } - - fn local_new(&mut self, name: String) { - self - .ctx - .levels - .last_mut() - .unwrap() - .locals - .push((name, false)); - } - - fn local_num(&self) -> usize { - self.ctx.levels.last().unwrap().locals.len() - } -} - -fn chunk + Clone>( - ctx: &mut CodegenContext, - has_var_args: bool, - params: Vec, - ast_entry: &T, -) -> ActivationRecord { - // prepare - let ar = ActivationRecord { - has_var_args, - n_param: params.len(), - ..Default::default() - }; - ctx.levels.push(Level { - locals: params.into_iter().map(|p| (p, false)).collect(), - upvalues: vec![], - }); - let generator = TreeWalkCodeGenerator { - ctx, - curr_ast: ast_entry.to_owned().into(), - ar, - sp: 0, - }; - - // generate - todo!(); - - // clear - let TreeWalkCodeGenerator { mut ar, ctx, .. } = generator; - let level = ctx.levels.pop().unwrap(); - ar.up_indexes = level.upvalues.into_iter().map(|(_, i)| i).collect(); - - ar -} - -pub fn load(lexer_ref: &Lexer, ast_entry: Box) -> ActivationRecord { - let mut ctx = CodegenContext { levels: vec![] }; - chunk(&mut ctx, false, vec!["_ENV".into()], &ast_entry) -} diff --git a/src/lib.rs b/src/lib.rs index b0bff6d..927c395 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,6 @@ use once_cell::sync::Lazy; pub mod ast; -pub mod bytecode; -pub mod codegen; pub mod error; pub mod lexer; pub mod optimizer; @@ -12,7 +10,6 @@ pub mod pest_parser; pub mod symbol_table; pub mod translator; pub mod util; -pub mod value; pub mod vm; pub static SEP: Lazy = Lazy::new(|| "=".repeat(70)); diff --git a/src/util/mod.rs b/src/util/mod.rs index e9626a2..f17a697 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,16 +1 @@ -use std::cmp::Ordering; - -use crate::value::Value; - pub mod bnf; - -pub fn set_vec(vec: &mut Vec, i: usize, value: Value) { - match i.cmp(&vec.len()) { - Ordering::Less => vec[i] = value, - Ordering::Equal => vec.push(value), - Ordering::Greater => { - vec.resize(i, Value::Nil); - vec.push(value); - } - } -} diff --git a/src/vm/advanced.rs b/src/vm/advanced.rs deleted file mode 100644 index 5c5e479..0000000 --- a/src/vm/advanced.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::{cell::RefCell, rc::Rc}; - -use crate::value::{Table, Value}; - -use super::lib::io::{lib_read, lib_write}; - -pub struct VMFrame { - /// Data stack (hold `Value` data) - stack: Vec, - /// Stack base of current field/function - base: usize, -} - -impl<'a> VMFrame { - pub fn get_top(&self) -> usize { - self.stack.len() - self.base - } - - pub fn get>(&'a self, i: usize) -> T { - (&self.stack[self.base + i - 1]).into() - } - - pub fn set>(&mut self, i: usize, v: T) { - self.stack[self.base + i - 1] = v.into(); - } - - pub fn push(&mut self, v: impl Into) { - self.stack.push(v.into()); - } -} - -impl VMFrame { - pub fn new() -> Self { - let array = vec![]; - let table = vec![ - ("write".into(), Value::RustFunction(lib_write)), - ("read".into(), Value::RustFunction(lib_read)), - ] - .into_iter() - .collect(); - let env = Table::new_with(array, table); - Self { - stack: vec![().into(), Rc::new(RefCell::new(env)).into()], // unused entry function & `ENV` table - base: 1, // always equals to entry function, even not used - } - } -} - -impl Default for VMFrame { - fn default() -> Self { - Self::new() - } -} diff --git a/src/vm/lib/io.rs b/src/vm/lib/io.rs deleted file mode 100644 index 941710d..0000000 --- a/src/vm/lib/io.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::{value::Value, vm::advanced::VMFrame}; - -pub(crate) fn lib_write(state: &mut VMFrame) -> i32 { - for i in 1..=state.get_top() { - if i != 1 { - print!(" "); - } - print!("{}", state.get::<&Value>(i)); - } - println!(); - 0 -} - -pub(crate) fn lib_read(state: &mut VMFrame) -> i32 { - let mut input = String::new(); - std::io::stdin().read_line(&mut input).unwrap(); - let input: Vec = input - .split_whitespace() - .map(|x| x.parse::().unwrap()) - .collect(); - for i in 1..=state.get_top() { - state.set::(i, input[i - 1].into()); - } - 0 -} diff --git a/src/vm/lib/mod.rs b/src/vm/lib/mod.rs index af514a1..8b13789 100644 --- a/src/vm/lib/mod.rs +++ b/src/vm/lib/mod.rs @@ -1 +1 @@ -pub mod io; + diff --git a/src/vm/mod.rs b/src/vm/mod.rs index f2e952d..350873c 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -1,38 +1,6 @@ #![allow(unused)] -use crate::{codegen::desc::ActivationRecord, value::Value}; use std::{cell::RefCell, rc::Rc}; -pub mod advanced; pub mod basic; pub mod lib; - -#[derive(Debug)] -pub enum UpValue { - Open(usize), - Closed(Value), -} - -impl UpValue { - fn get<'a>(&'a self, stack: &'a [Value]) -> &'a Value { - match self { - UpValue::Open(i) => &stack[*i], - UpValue::Closed(v) => v, - } - } - - fn set(&mut self, stack: &mut [Value], value: Value) { - match self { - UpValue::Open(i) => stack[*i] = value, - UpValue::Closed(v) => *v = value, - } - } -} - -#[derive(Debug)] -pub struct PL0Closure { - /// Current closure's activation_record - ar: Rc, - /// Current closure's up_value list - up_values: Vec>>, -}