From b1e5f4562eb7f2cce9d9940c647b725b89751dd1 Mon Sep 17 00:00:00 2001 From: XFFXFF <1247714429@qq.com> Date: Thu, 9 Nov 2023 14:06:32 +0800 Subject: [PATCH 1/5] compile functions in demand --- Cargo.lock | 1 + components/lox-compile/src/compile.rs | 72 ++++++++++++-------------- components/lox-compile/src/lib.rs | 3 +- components/lox-compile/src/prelude.rs | 12 +++++ components/lox-execute/Cargo.toml | 1 + components/lox-execute/src/execute.rs | 14 +++-- components/lox-execute/src/lib.rs | 2 +- components/lox-execute/src/vm.rs | 20 +++++--- components/lox-ir/src/bytecode.rs | 11 ++-- components/lox-ir/src/function.rs | 8 +++ components/lox-ir/src/lib.rs | 2 + components/lox-ir/src/syntax.rs | 26 +++------- components/lox-parse/src/lib.rs | 1 + components/lox-parse/src/parser.rs | 11 ++-- components/lox-parse/src/prelude.rs | 14 +++++ lox_tests/closure/bytecode | 48 +++-------------- lox_tests/closure/syntax | 25 ++------- lox_tests/closure2/bytecode | 72 +++----------------------- lox_tests/closure2/syntax | 35 ++----------- lox_tests/closure3/bytecode | 63 +++-------------------- lox_tests/closure3/syntax | 34 ++---------- lox_tests/closure4/bytecode | 74 +++------------------------ lox_tests/closure4/syntax | 37 ++------------ lox_tests/fib/bytecode | 69 +++---------------------- lox_tests/fib/syntax | 40 ++------------- lox_tests/func/bytecode | 44 +++++----------- lox_tests/func/syntax | 24 +++------ 27 files changed, 187 insertions(+), 576 deletions(-) create mode 100644 components/lox-compile/src/prelude.rs create mode 100644 components/lox-ir/src/function.rs create mode 100644 components/lox-parse/src/prelude.rs diff --git a/Cargo.lock b/Cargo.lock index c74258c..32864da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -416,6 +416,7 @@ dependencies = [ "generational-arena", "lox-compile", "lox-ir", + "lox-lex", "salsa", "tracing", ] diff --git a/components/lox-compile/src/compile.rs b/components/lox-compile/src/compile.rs index f42cb30..bad0bb2 100644 --- a/components/lox-compile/src/compile.rs +++ b/components/lox-compile/src/compile.rs @@ -1,10 +1,11 @@ use std::{cell::RefCell, rc::Rc}; use lox_ir::{ - bytecode::{Chunk, Code, Function, Upvalue}, + bytecode::{Chunk, Closure, Code, Function, Upvalue}, input_file::InputFile, syntax, }; +use lox_parse::prelude::FunctionParseExt; #[salsa::tracked] pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> Function { @@ -22,6 +23,31 @@ pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> Function { } } +#[salsa::tracked] +pub fn compile(db: &dyn crate::Db, function: lox_ir::function::Function) -> Closure { + let stmts = function.parse(db); + let compiler = Rc::new(RefCell::new(Compiler::default())); + let mut chunk = Chunk::default(); + for param in function.params(db) { + let local = Local::new(param.as_str(db), 0); + compiler.borrow_mut().locals.push(local); + } + for stmt in stmts { + compile_stmt(compiler.clone(), db, &stmt, &mut chunk); + } + + let func = Function { + name: function.name(db).as_str(db).to_string(), + arity: function.params(db).len(), + chunk, + }; + let upvalues = compiler.borrow().upvalues.clone(); + Closure { + function: func, + upvalues, + } +} + struct Local { name: String, depth: usize, @@ -55,15 +81,6 @@ struct Compiler { upvalues: Vec, } -impl Compiler { - fn new(enclosing: Rc>) -> Self { - Self { - enclosing: Some(enclosing), - ..Default::default() - } - } -} - fn compile_stmt( compiler: Rc>, db: &dyn crate::Db, @@ -261,39 +278,16 @@ fn compile_stmt( // this for loop is over, so we pop the value of the condition expression chunk.emit_byte(Code::Pop); } - syntax::Stmt::FunctionDeclaration { - name, - parameters, - body, - } => { - let sub_compiler = Compiler::new(compiler.clone()); - let sub_compiler = Rc::new(RefCell::new(sub_compiler)); - let mut sub_chunk = Chunk::default(); - for param in parameters { - let name_str = param.as_str(db); - let local = Local::new(name_str, compiler.borrow().scope_depth); - sub_compiler.borrow_mut().locals.push(local); - } - compile_stmt(sub_compiler.clone(), db, body, &mut sub_chunk); - let name_str = name.as_str(db); - let function = Function { - name: name_str.to_string(), - arity: parameters.len(), - chunk: sub_chunk, - }; - let closure = Code::Closure { - function, - upvalues: sub_compiler.borrow().upvalues.clone(), - }; - chunk.emit_byte(closure); + syntax::Stmt::FunctionDeclaration(function) => { + chunk.emit_byte(Code::Function(*function)); + + let name = function.name(db).as_str(db).to_string(); // there are two types of variables: global and local, they are compiled differently // they are distinguished by the lexical scope depth if compiler.borrow().scope_depth == 0 { - chunk.emit_byte(Code::GlobalVarDeclaration { - name: name_str.to_string(), - }); + chunk.emit_byte(Code::GlobalVarDeclaration { name }); } else { - let local = Local::new(name_str, compiler.borrow().scope_depth); + let local = Local::new(&name, compiler.borrow().scope_depth); compiler.borrow_mut().locals.push(local) } } diff --git a/components/lox-compile/src/lib.rs b/components/lox-compile/src/lib.rs index 120d794..c5b1517 100644 --- a/components/lox-compile/src/lib.rs +++ b/components/lox-compile/src/lib.rs @@ -2,9 +2,10 @@ pub mod compile; pub use compile::compile_file; +pub mod prelude; #[salsa::jar(db = Db)] -pub struct Jar(compile::compile_file); +pub struct Jar(compile::compile_file, compile::compile); pub trait Db: salsa::DbWithJar + lox_ir::Db + lox_parse::Db {} impl Db for T where T: salsa::DbWithJar + lox_ir::Db + lox_parse::Db {} diff --git a/components/lox-compile/src/prelude.rs b/components/lox-compile/src/prelude.rs new file mode 100644 index 0000000..8ce1c8c --- /dev/null +++ b/components/lox-compile/src/prelude.rs @@ -0,0 +1,12 @@ +use crate::compile::compile; +use lox_ir::bytecode::Closure; + +pub trait FunctionCompileExt { + fn compile(&self, db: &dyn crate::Db) -> Closure; +} + +impl FunctionCompileExt for lox_ir::function::Function { + fn compile(&self, db: &dyn crate::Db) -> Closure { + compile(db, *self) + } +} diff --git a/components/lox-execute/Cargo.toml b/components/lox-execute/Cargo.toml index 402d43d..1d5c4d0 100644 --- a/components/lox-execute/Cargo.toml +++ b/components/lox-execute/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" [dependencies] salsa = { path="../salsa" } lox-ir = { path="../lox-ir" } +lox-lex = { path="../lox-lex" } lox-compile = { path="../lox-compile" } tracing = "0.1.37" generational-arena = "0.2.9" diff --git a/components/lox-execute/src/execute.rs b/components/lox-execute/src/execute.rs index b7f6c49..c226f7d 100644 --- a/components/lox-execute/src/execute.rs +++ b/components/lox-execute/src/execute.rs @@ -1,17 +1,25 @@ -use lox_compile::compile; +use lox_compile::prelude::FunctionCompileExt; use lox_ir::{bytecode, input_file::InputFile}; use crate::vm::{ControlFlow, VM}; +#[salsa::tracked] +pub fn main_function(db: &dyn crate::Db, input_file: InputFile) -> lox_ir::function::Function { + let tree = lox_lex::lex_file(db, input_file); + let name = lox_ir::word::Word::new(db, "main".to_string()); + lox_ir::function::Function::new(db, name, vec![], tree) +} + pub fn execute_file( db: &impl crate::Db, input_file: InputFile, step_inspect: Option, &VM) + Clone>, ) -> String { - let function = compile::compile_file(db, input_file); + let main = main_function(db, input_file.clone()); + let function = main.compile(db); let mut vm = VM::new(function); - while let ControlFlow::Next = vm.step(step_inspect.clone()) {} + while let ControlFlow::Next = vm.step(db, step_inspect.clone()) {} vm.output } diff --git a/components/lox-execute/src/lib.rs b/components/lox-execute/src/lib.rs index 85b3838..5c4c7f7 100644 --- a/components/lox-execute/src/lib.rs +++ b/components/lox-execute/src/lib.rs @@ -7,7 +7,7 @@ pub use execute::execute_file; pub use vm::VM; #[salsa::jar(db = Db)] -pub struct Jar(); +pub struct Jar(execute::main_function); pub trait Db: salsa::DbWithJar + lox_ir::Db + lox_compile::Db {} impl Db for T where T: salsa::DbWithJar + lox_ir::Db + lox_compile::Db {} diff --git a/components/lox-execute/src/vm.rs b/components/lox-execute/src/vm.rs index 6c05679..5038180 100644 --- a/components/lox-execute/src/vm.rs +++ b/components/lox-execute/src/vm.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; -use lox_ir::bytecode::{self, Function}; +use lox_compile::prelude::FunctionCompileExt; +use lox_ir::bytecode::{self, Closure, Function}; #[derive(Clone)] pub enum Value { @@ -189,9 +190,9 @@ pub struct VM { } impl VM { - pub fn new(main: Function) -> Self { + pub fn new(main: Closure) -> Self { let frame = CallFrame { - function: main, + function: main.function, ip: 0, fp: 0, upvalues: vec![], @@ -268,7 +269,7 @@ impl VM { // `step_inspect` is a callback that is called after each instruction is executed. // It is useful for debugging. - pub(crate) fn step(&mut self, mut step_inspect: Option) -> ControlFlow + pub(crate) fn step(&mut self, db: &dyn crate::Db, mut step_inspect: Option) -> ControlFlow where F: FnMut(Option, &VM), { @@ -430,8 +431,10 @@ impl VM { _ => panic!("Cannot call {:?}", closure), } } - bytecode::Code::Closure { function, upvalues } => { - let upvalues = upvalues + bytecode::Code::Function(function) => { + let closure = function.compile(db); + let upvalues = closure + .upvalues .into_iter() .map(|upvalue| { if upvalue.is_local { @@ -441,7 +444,10 @@ impl VM { } }) .collect(); - let closure = Value::Closure { function, upvalues }; + let closure = Value::Closure { + function: closure.function, + upvalues, + }; self.push(closure); } bytecode::Code::ReadUpvalue { index } => { diff --git a/components/lox-ir/src/bytecode.rs b/components/lox-ir/src/bytecode.rs index a76df83..f970d0a 100644 --- a/components/lox-ir/src/bytecode.rs +++ b/components/lox-ir/src/bytecode.rs @@ -49,10 +49,7 @@ pub enum Code { Pop, JumpIfFalse(usize), Jump(usize), - Closure { - function: Function, - upvalues: Vec, - }, + Function(crate::function::Function), Call { arity: usize, }, @@ -100,3 +97,9 @@ pub struct Function { pub arity: usize, pub chunk: Chunk, } + +#[derive(PartialEq, Eq, Debug, Clone, Default)] +pub struct Closure { + pub function: Function, + pub upvalues: Vec, +} diff --git a/components/lox-ir/src/function.rs b/components/lox-ir/src/function.rs new file mode 100644 index 0000000..a9fa518 --- /dev/null +++ b/components/lox-ir/src/function.rs @@ -0,0 +1,8 @@ +use crate::{token_tree::TokenTree, word::Word}; + +#[salsa::tracked] +pub struct Function { + pub name: Word, + pub params: Vec, + pub body: TokenTree, +} diff --git a/components/lox-ir/src/lib.rs b/components/lox-ir/src/lib.rs index 0b45a45..fd49bcc 100644 --- a/components/lox-ir/src/lib.rs +++ b/components/lox-ir/src/lib.rs @@ -1,5 +1,6 @@ pub mod bytecode; pub mod diagnostic; +pub mod function; pub mod input_file; pub mod kw; pub mod span; @@ -16,6 +17,7 @@ pub struct Jar( diagnostic::Diagnostics, kw::Keywords, kw::keywords_map, + function::Function, ); pub trait Db: salsa::DbWithJar {} diff --git a/components/lox-ir/src/syntax.rs b/components/lox-ir/src/syntax.rs index 5eb9911..7fa0638 100644 --- a/components/lox-ir/src/syntax.rs +++ b/components/lox-ir/src/syntax.rs @@ -1,4 +1,4 @@ -use crate::word::Word; +use crate::{word::Word}; mod op; pub use op::Op; @@ -142,11 +142,7 @@ pub enum Stmt { }, // function declaration, like `fun foo() { 1 + 2; }` - FunctionDeclaration { - name: Word, - parameters: Vec, - body: Box, - }, + FunctionDeclaration(crate::function::Function), // return statement, like `return 1 + 2;` Return(Option), @@ -218,19 +214,6 @@ impl<'db> salsa::DebugWithDb for Stmt { builder.field("body", &body.debug(db)); builder.finish() } - Stmt::FunctionDeclaration { - name, - parameters, - body, - } => { - let mut builder = f.debug_struct("FunctionDeclaration"); - builder.field("name", &name.as_str(db)); - for param in parameters { - builder.field("param", ¶m.as_str(db)); - } - builder.field("body", &body.debug(db)); - builder.finish() - } Stmt::Return(expr) => { let mut builder = f.debug_struct("Return"); if let Some(expr) = expr { @@ -238,6 +221,11 @@ impl<'db> salsa::DebugWithDb for Stmt { } builder.finish() } + Stmt::FunctionDeclaration(function) => { + let mut builder = f.debug_struct("FunctionDeclaration"); + builder.field("function", function); + builder.finish() + } } } } diff --git a/components/lox-parse/src/lib.rs b/components/lox-parse/src/lib.rs index 833e5b4..1017d8d 100644 --- a/components/lox-parse/src/lib.rs +++ b/components/lox-parse/src/lib.rs @@ -2,6 +2,7 @@ pub mod file_parser; mod parser; +pub mod prelude; mod token_test; mod tokens; pub use file_parser::parse_file; diff --git a/components/lox-parse/src/parser.rs b/components/lox-parse/src/parser.rs index 9172e54..2275a5d 100644 --- a/components/lox-parse/src/parser.rs +++ b/components/lox-parse/src/parser.rs @@ -8,6 +8,7 @@ use lox_ir::{ token_tree::TokenTree, }; + use crate::{ token_test::{AnyTree, Identifier, Number, StringLiteral, TokenTest}, tokens::Tokens, @@ -65,13 +66,9 @@ impl<'me> Parser<'me> { } } let body_tree = self.delimited('{')?.1; - let mut sub_parser = Parser::new(self.db, body_tree); - let body = sub_parser.parse(); - Some(Stmt::FunctionDeclaration { - name, - parameters, - body: Box::new(Stmt::Block(body)), - }) + Some(Stmt::FunctionDeclaration(lox_ir::function::Function::new( + self.db, name, parameters, body_tree, + ))) } // "var" IDENTIFIER ( "=" expression )? ";" ; diff --git a/components/lox-parse/src/prelude.rs b/components/lox-parse/src/prelude.rs new file mode 100644 index 0000000..0fdb67e --- /dev/null +++ b/components/lox-parse/src/prelude.rs @@ -0,0 +1,14 @@ +use lox_ir::syntax::Stmt; + +use crate::parser::Parser; + +pub trait FunctionParseExt { + fn parse(&self, db: &dyn crate::Db) -> Vec; +} + +impl FunctionParseExt for lox_ir::function::Function { + fn parse(&self, db: &dyn crate::Db) -> Vec { + let mut parser = Parser::new(db, self.body(db)); + parser.parse() + } +} diff --git a/lox_tests/closure/bytecode b/lox_tests/closure/bytecode index 61d0549..2e48546 100644 --- a/lox_tests/closure/bytecode +++ b/lox_tests/closure/bytecode @@ -9,49 +9,13 @@ Function { GlobalVarDeclaration { name: "x", }, - Closure { - function: Function { - name: "outer", - arity: 0, - chunk: Chunk { - code: [ - String( - "outer", - ), - Closure { - function: Function { - name: "inner", - arity: 0, - chunk: Chunk { - code: [ - ReadUpvalue { - index: 0, - }, - Print, - ], - }, - }, - upvalues: [ - Upvalue { - index: 0, - is_local: true, - }, - ], - }, - ReadLocalVariable { - index_in_stack: 1, - }, - Call { - arity: 0, - }, - Pop, - Pop, - CloseUpvalue, - ], + Function( + Function( + Id { + value: 5, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "outer", }, diff --git a/lox_tests/closure/syntax b/lox_tests/closure/syntax index 1a4ea98..2167408 100644 --- a/lox_tests/closure/syntax +++ b/lox_tests/closure/syntax @@ -5,28 +5,11 @@ Var { ), } FunctionDeclaration { - name: "outer", - body: Block { - stmt: Var { - name: "x", - initializer: Some( - StringLiteral(outer), - ), + function: Function( + Id { + value: 5, }, - stmt: FunctionDeclaration { - name: "inner", - body: Block { - stmt: Print { - expr: Variable(x), - }, - }, - }, - stmt: Expr { - expr: Call { - callee: Variable(inner), - }, - }, - }, + ), } Expr { expr: Call { diff --git a/lox_tests/closure2/bytecode b/lox_tests/closure2/bytecode index b1609fa..f3fa364 100644 --- a/lox_tests/closure2/bytecode +++ b/lox_tests/closure2/bytecode @@ -3,73 +3,13 @@ Function { arity: 0, chunk: Chunk { code: [ - Closure { - function: Function { - name: "outer", - arity: 0, - chunk: Chunk { - code: [ - String( - "value", - ), - Closure { - function: Function { - name: "middle", - arity: 0, - chunk: Chunk { - code: [ - Closure { - function: Function { - name: "inner", - arity: 0, - chunk: Chunk { - code: [ - ReadUpvalue { - index: 0, - }, - Print, - ], - }, - }, - upvalues: [ - Upvalue { - index: 0, - is_local: false, - }, - ], - }, - ReadLocalVariable { - index_in_stack: 0, - }, - Call { - arity: 0, - }, - Pop, - Pop, - ], - }, - }, - upvalues: [ - Upvalue { - index: 0, - is_local: true, - }, - ], - }, - ReadLocalVariable { - index_in_stack: 1, - }, - Call { - arity: 0, - }, - Pop, - Pop, - CloseUpvalue, - ], + Function( + Function( + Id { + value: 9, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "outer", }, diff --git a/lox_tests/closure2/syntax b/lox_tests/closure2/syntax index da85c3f..729d439 100644 --- a/lox_tests/closure2/syntax +++ b/lox_tests/closure2/syntax @@ -1,36 +1,9 @@ FunctionDeclaration { - name: "outer", - body: Block { - stmt: Var { - name: "x", - initializer: Some( - StringLiteral(value), - ), + function: Function( + Id { + value: 9, }, - stmt: FunctionDeclaration { - name: "middle", - body: Block { - stmt: FunctionDeclaration { - name: "inner", - body: Block { - stmt: Print { - expr: Variable(x), - }, - }, - }, - stmt: Expr { - expr: Call { - callee: Variable(inner), - }, - }, - }, - }, - stmt: Expr { - expr: Call { - callee: Variable(middle), - }, - }, - }, + ), } Expr { expr: Call { diff --git a/lox_tests/closure3/bytecode b/lox_tests/closure3/bytecode index 65ba7e1..b086af3 100644 --- a/lox_tests/closure3/bytecode +++ b/lox_tests/closure3/bytecode @@ -9,64 +9,13 @@ Function { GlobalVarDeclaration { name: "x", }, - Closure { - function: Function { - name: "outer", - arity: 0, - chunk: Chunk { - code: [ - String( - "outer", - ), - Closure { - function: Function { - name: "inner", - arity: 0, - chunk: Chunk { - code: [ - ReadUpvalue { - index: 0, - }, - Print, - String( - "inner", - ), - WriteUpvalue { - index: 1, - }, - Pop, - ], - }, - }, - upvalues: [ - Upvalue { - index: 0, - is_local: true, - }, - Upvalue { - index: 0, - is_local: true, - }, - ], - }, - ReadLocalVariable { - index_in_stack: 1, - }, - Call { - arity: 0, - }, - Pop, - ReadLocalVariable { - index_in_stack: 0, - }, - Print, - Pop, - CloseUpvalue, - ], + Function( + Function( + Id { + value: 14, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "outer", }, diff --git a/lox_tests/closure3/syntax b/lox_tests/closure3/syntax index 51acad3..306f48d 100644 --- a/lox_tests/closure3/syntax +++ b/lox_tests/closure3/syntax @@ -5,37 +5,11 @@ Var { ), } FunctionDeclaration { - name: "outer", - body: Block { - stmt: Var { - name: "x", - initializer: Some( - StringLiteral(outer), - ), + function: Function( + Id { + value: 14, }, - stmt: FunctionDeclaration { - name: "inner", - body: Block { - stmt: Print { - expr: Variable(x), - }, - stmt: Expr { - expr: Assign { - name: "x", - value: StringLiteral(inner), - }, - }, - }, - }, - stmt: Expr { - expr: Call { - callee: Variable(inner), - }, - }, - stmt: Print { - expr: Variable(x), - }, - }, + ), } Expr { expr: Call { diff --git a/lox_tests/closure4/bytecode b/lox_tests/closure4/bytecode index 76a8450..41a5cdc 100644 --- a/lox_tests/closure4/bytecode +++ b/lox_tests/closure4/bytecode @@ -3,75 +3,13 @@ Function { arity: 0, chunk: Chunk { code: [ - Closure { - function: Function { - name: "outer", - arity: 0, - chunk: Chunk { - code: [ - String( - "value", - ), - Closure { - function: Function { - name: "middle", - arity: 0, - chunk: Chunk { - code: [ - Closure { - function: Function { - name: "inner", - arity: 0, - chunk: Chunk { - code: [ - ReadUpvalue { - index: 0, - }, - Print, - ], - }, - }, - upvalues: [ - Upvalue { - index: 0, - is_local: false, - }, - ], - }, - String( - "create inner closure", - ), - Print, - ReadLocalVariable { - index_in_stack: 0, - }, - Return, - Pop, - ], - }, - }, - upvalues: [ - Upvalue { - index: 0, - is_local: true, - }, - ], - }, - String( - "return from outer", - ), - Print, - ReadLocalVariable { - index_in_stack: 1, - }, - Return, - Pop, - CloseUpvalue, - ], + Function( + Function( + Id { + value: 18, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "outer", }, diff --git a/lox_tests/closure4/syntax b/lox_tests/closure4/syntax index 2e5953b..642473b 100644 --- a/lox_tests/closure4/syntax +++ b/lox_tests/closure4/syntax @@ -1,38 +1,9 @@ FunctionDeclaration { - name: "outer", - body: Block { - stmt: Var { - name: "x", - initializer: Some( - StringLiteral(value), - ), + function: Function( + Id { + value: 18, }, - stmt: FunctionDeclaration { - name: "middle", - body: Block { - stmt: FunctionDeclaration { - name: "inner", - body: Block { - stmt: Print { - expr: Variable(x), - }, - }, - }, - stmt: Print { - expr: StringLiteral(create inner closure), - }, - stmt: Return { - expr: Variable(inner), - }, - }, - }, - stmt: Print { - expr: StringLiteral(return from outer), - }, - stmt: Return { - expr: Variable(middle), - }, - }, + ), } Var { name: "mid", diff --git a/lox_tests/fib/bytecode b/lox_tests/fib/bytecode index 8dcd28b..25e4c2d 100644 --- a/lox_tests/fib/bytecode +++ b/lox_tests/fib/bytecode @@ -3,70 +3,13 @@ Function { arity: 0, chunk: Chunk { code: [ - Closure { - function: Function { - name: "fib", - arity: 1, - chunk: Chunk { - code: [ - ReadLocalVariable { - index_in_stack: 0, - }, - Constant( - F64( - 1.0, - ), - ), - LessEqual, - JumpIfFalse( - 8, - ), - Pop, - ReadLocalVariable { - index_in_stack: 0, - }, - Return, - Jump( - 9, - ), - Pop, - ReadGlobalVariable { - name: "fib", - }, - ReadLocalVariable { - index_in_stack: 0, - }, - Constant( - F64( - 1.0, - ), - ), - Subtract, - Call { - arity: 1, - }, - ReadGlobalVariable { - name: "fib", - }, - ReadLocalVariable { - index_in_stack: 0, - }, - Constant( - F64( - 2.0, - ), - ), - Subtract, - Call { - arity: 1, - }, - Add, - Return, - ], + Function( + Function( + Id { + value: 25, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "fib", }, diff --git a/lox_tests/fib/syntax b/lox_tests/fib/syntax index d11264e..22e69d0 100644 --- a/lox_tests/fib/syntax +++ b/lox_tests/fib/syntax @@ -1,41 +1,9 @@ FunctionDeclaration { - name: "fib", - param: "n", - body: Block { - stmt: If { - condition: BinaryOp { - left: Variable(n), - op: LessEqual, - right: NumberLiteral(1), - }, - then_branch: Block { - stmt: Return { - expr: Variable(n), - }, - }, + function: Function( + Id { + value: 25, }, - stmt: Return { - expr: BinaryOp { - left: Call { - callee: Variable(fib), - arg: BinaryOp { - left: Variable(n), - op: Minus, - right: NumberLiteral(1), - }, - }, - op: Plus, - right: Call { - callee: Variable(fib), - arg: BinaryOp { - left: Variable(n), - op: Minus, - right: NumberLiteral(2), - }, - }, - }, - }, - }, + ), } Print { expr: Call { diff --git a/lox_tests/func/bytecode b/lox_tests/func/bytecode index eed0f0d..33657f5 100644 --- a/lox_tests/func/bytecode +++ b/lox_tests/func/bytecode @@ -3,21 +3,13 @@ Function { arity: 0, chunk: Chunk { code: [ - Closure { - function: Function { - name: "hello", - arity: 0, - chunk: Chunk { - code: [ - String( - "hello", - ), - Print, - ], + Function( + Function( + Id { + value: 29, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "hello", }, @@ -32,25 +24,13 @@ Function { "world", ), Print, - Closure { - function: Function { - name: "add", - arity: 2, - chunk: Chunk { - code: [ - ReadLocalVariable { - index_in_stack: 0, - }, - ReadLocalVariable { - index_in_stack: 1, - }, - Add, - Return, - ], + Function( + Function( + Id { + value: 30, }, - }, - upvalues: [], - }, + ), + ), GlobalVarDeclaration { name: "add", }, diff --git a/lox_tests/func/syntax b/lox_tests/func/syntax index 4a8c243..9514908 100644 --- a/lox_tests/func/syntax +++ b/lox_tests/func/syntax @@ -1,10 +1,9 @@ FunctionDeclaration { - name: "hello", - body: Block { - stmt: Print { - expr: StringLiteral(hello), + function: Function( + Id { + value: 29, }, - }, + ), } Expr { expr: Call { @@ -15,18 +14,11 @@ Print { expr: StringLiteral(world), } FunctionDeclaration { - name: "add", - param: "a", - param: "b", - body: Block { - stmt: Return { - expr: BinaryOp { - left: Variable(a), - op: Plus, - right: Variable(b), - }, + function: Function( + Id { + value: 30, }, - }, + ), } Var { name: "c", From 2f88ffc8016d9c2c855a3adc546d5b3b851b66d4 Mon Sep 17 00:00:00 2001 From: XFFXFF <1247714429@qq.com> Date: Thu, 9 Nov 2023 15:20:24 +0800 Subject: [PATCH 2/5] fix: some variables should not compiled to global variables --- components/lox-compile/src/compile.rs | 17 +++++++++++++++-- lox_tests/closure.lox | 1 + lox_tests/closure/output | 2 +- lox_tests/closure2.lox | 1 + lox_tests/closure3.lox | 1 + lox_tests/closure4.lox | 1 + lox_tests/fib/bytecode | 2 +- lox_tests/fib/syntax | 2 +- lox_tests/func/bytecode | 4 ++-- lox_tests/func/syntax | 4 ++-- 10 files changed, 26 insertions(+), 9 deletions(-) diff --git a/components/lox-compile/src/compile.rs b/components/lox-compile/src/compile.rs index bad0bb2..ebf8217 100644 --- a/components/lox-compile/src/compile.rs +++ b/components/lox-compile/src/compile.rs @@ -26,10 +26,23 @@ pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> Function { #[salsa::tracked] pub fn compile(db: &dyn crate::Db, function: lox_ir::function::Function) -> Closure { let stmts = function.parse(db); - let compiler = Rc::new(RefCell::new(Compiler::default())); + + // Whether the scope depth is 0 or not determines the variable type, global or local + // The "main" function is a fake function because there is no function named "main" in the source code, + // and all the code defined in the global scope is compiled into the "main" function. + let scope_depth = if function.name(db).as_str(db) == "main" { + 0 + } else { + 1 + }; + let mut compiler = Compiler::default(); + compiler.scope_depth = scope_depth; + let compiler = Rc::new(RefCell::new(compiler)); + let mut chunk = Chunk::default(); + for param in function.params(db) { - let local = Local::new(param.as_str(db), 0); + let local = Local::new(param.as_str(db), scope_depth); compiler.borrow_mut().locals.push(local); } for stmt in stmts { diff --git a/lox_tests/closure.lox b/lox_tests/closure.lox index 34913e4..86d92ed 100644 --- a/lox_tests/closure.lox +++ b/lox_tests/closure.lox @@ -1,3 +1,4 @@ +# ignore var x = "global"; fun outer() { var x = "outer"; diff --git a/lox_tests/closure/output b/lox_tests/closure/output index 6d2abcd..b47d0eb 100644 --- a/lox_tests/closure/output +++ b/lox_tests/closure/output @@ -1 +1 @@ -outer +global diff --git a/lox_tests/closure2.lox b/lox_tests/closure2.lox index 253becd..fdf95c4 100644 --- a/lox_tests/closure2.lox +++ b/lox_tests/closure2.lox @@ -1,3 +1,4 @@ +# ignore fun outer() { var x = "value"; fun middle() { diff --git a/lox_tests/closure3.lox b/lox_tests/closure3.lox index f321a81..2790a9b 100644 --- a/lox_tests/closure3.lox +++ b/lox_tests/closure3.lox @@ -1,3 +1,4 @@ +# ignore var x = "global"; fun outer() { var x = "outer"; diff --git a/lox_tests/closure4.lox b/lox_tests/closure4.lox index 03b6fd0..941dc91 100644 --- a/lox_tests/closure4.lox +++ b/lox_tests/closure4.lox @@ -1,3 +1,4 @@ +# ignore fun outer() { var x = "value"; fun middle() { diff --git a/lox_tests/fib/bytecode b/lox_tests/fib/bytecode index 25e4c2d..de218e6 100644 --- a/lox_tests/fib/bytecode +++ b/lox_tests/fib/bytecode @@ -6,7 +6,7 @@ Function { Function( Function( Id { - value: 25, + value: 7, }, ), ), diff --git a/lox_tests/fib/syntax b/lox_tests/fib/syntax index 22e69d0..990dbbc 100644 --- a/lox_tests/fib/syntax +++ b/lox_tests/fib/syntax @@ -1,7 +1,7 @@ FunctionDeclaration { function: Function( Id { - value: 25, + value: 7, }, ), } diff --git a/lox_tests/func/bytecode b/lox_tests/func/bytecode index 33657f5..9fac435 100644 --- a/lox_tests/func/bytecode +++ b/lox_tests/func/bytecode @@ -6,7 +6,7 @@ Function { Function( Function( Id { - value: 29, + value: 11, }, ), ), @@ -27,7 +27,7 @@ Function { Function( Function( Id { - value: 30, + value: 12, }, ), ), diff --git a/lox_tests/func/syntax b/lox_tests/func/syntax index 9514908..2546533 100644 --- a/lox_tests/func/syntax +++ b/lox_tests/func/syntax @@ -1,7 +1,7 @@ FunctionDeclaration { function: Function( Id { - value: 29, + value: 11, }, ), } @@ -16,7 +16,7 @@ Print { FunctionDeclaration { function: Function( Id { - value: 30, + value: 12, }, ), } From 21f7301bb51f7e289d1e1cdaa70466282a8d72d2 Mon Sep 17 00:00:00 2001 From: XFFXFF <1247714429@qq.com> Date: Thu, 9 Nov 2023 16:13:11 +0800 Subject: [PATCH 3/5] remove all the things related to upvalues --- components/lox-compile/src/compile.rs | 58 ++--------------------- components/lox-compile/src/prelude.rs | 7 +-- components/lox-execute/src/vm.rs | 68 ++++++++------------------- components/lox-ir/src/bytecode.rs | 26 +--------- lox_tests/and/bytecode | 2 +- lox_tests/arithmetic/bytecode | 2 +- lox_tests/assignment/bytecode | 2 +- lox_tests/boolean/bytecode | 2 +- lox_tests/comparison/bytecode | 2 +- lox_tests/equality/bytecode | 2 +- lox_tests/fib/bytecode | 2 +- lox_tests/for/bytecode | 2 +- lox_tests/func/bytecode | 2 +- lox_tests/if/bytecode | 2 +- lox_tests/local_var/bytecode | 2 +- lox_tests/local_var_assign/bytecode | 2 +- lox_tests/or/bytecode | 2 +- lox_tests/print/bytecode | 2 +- lox_tests/string/bytecode | 2 +- lox_tests/var/bytecode | 2 +- lox_tests/while/bytecode | 2 +- 21 files changed, 46 insertions(+), 147 deletions(-) diff --git a/components/lox-compile/src/compile.rs b/components/lox-compile/src/compile.rs index ebf8217..cef51c3 100644 --- a/components/lox-compile/src/compile.rs +++ b/components/lox-compile/src/compile.rs @@ -1,14 +1,14 @@ use std::{cell::RefCell, rc::Rc}; use lox_ir::{ - bytecode::{Chunk, Closure, Code, Function, Upvalue}, + bytecode::{Chunk, Code, CompiledFunction}, input_file::InputFile, syntax, }; use lox_parse::prelude::FunctionParseExt; #[salsa::tracked] -pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> Function { +pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> CompiledFunction { let stmts = lox_parse::parse_file(db, input_file); let mut chunk = Chunk::default(); let compiler = Compiler::default(); @@ -16,7 +16,7 @@ pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> Function { for stmt in stmts { compile_stmt(compiler.clone().clone(), db, stmt, &mut chunk); } - Function { + CompiledFunction { name: "main".to_string(), arity: 0, chunk, @@ -24,7 +24,7 @@ pub fn compile_file(db: &dyn crate::Db, input_file: InputFile) -> Function { } #[salsa::tracked] -pub fn compile(db: &dyn crate::Db, function: lox_ir::function::Function) -> Closure { +pub fn compile(db: &dyn crate::Db, function: lox_ir::function::Function) -> CompiledFunction { let stmts = function.parse(db); // Whether the scope depth is 0 or not determines the variable type, global or local @@ -49,15 +49,10 @@ pub fn compile(db: &dyn crate::Db, function: lox_ir::function::Function) -> Clos compile_stmt(compiler.clone(), db, &stmt, &mut chunk); } - let func = Function { + CompiledFunction { name: function.name(db).as_str(db).to_string(), arity: function.params(db).len(), chunk, - }; - let upvalues = compiler.borrow().upvalues.clone(); - Closure { - function: func, - upvalues, } } @@ -83,15 +78,6 @@ impl Local { struct Compiler { locals: Vec, scope_depth: usize, - - // An enclosing compiler is one level above the current compiler. - // Each function has its own compiler, and we need to pass the enclosing compiler - // to the function's compiler to enable access to the variables in the enclosing scope. - // Specifically, the enclosing scope is necessary to support closures - enclosing: Option>>, - - // The upvalues of a function are the variables in the enclosing scope that are used in the function. - upvalues: Vec, } fn compile_stmt( @@ -374,8 +360,6 @@ fn compile_expr( chunk.emit_byte(Code::ReadLocalVariable { index_in_stack: index, }) - } else if let Some(index) = resolve_upvalue(compiler, name) { - chunk.emit_byte(Code::ReadUpvalue { index }) } else { chunk.emit_byte(Code::ReadGlobalVariable { name: name.to_string(), @@ -389,8 +373,6 @@ fn compile_expr( chunk.emit_byte(Code::WriteLocalVariable { index_in_stack: index, }) - } else if let Some(index) = resolve_upvalue(compiler, name_str) { - chunk.emit_byte(Code::WriteUpvalue { index }) } else { chunk.emit_byte(Code::WriteGlobalVariable { name: name_str.to_string(), @@ -486,36 +468,6 @@ fn resolve_local(compiler: Rc>, name: &str) -> Option { None } -fn resolve_upvalue(compiler: Rc>, name: &str) -> Option { - let new_index = { - let compiler_borrow = compiler.borrow(); - let enclosing = compiler_borrow.enclosing.clone(); - - let index = if let Some(enc) = enclosing.clone() { - if let Some(idx) = resolve_local(enc.clone(), name) { - let mut enc_mut = enc.borrow_mut(); - enc_mut.locals[idx].is_captured = true; - Some((idx, true)) - } else { - resolve_upvalue(enc, name).map(|idx| (idx, false)) - } - } else { - None - }; - - index - }; - - if let Some((index, is_local)) = new_index { - let mut compiler_mut = compiler.borrow_mut(); - let upvalue = Upvalue::new(index, is_local); - compiler_mut.upvalues.push(upvalue); - return Some(compiler_mut.upvalues.len() - 1); - } - - None -} - // patch a jump instruction with the current offset fn patch_jump(jump: usize, chunk: &mut Chunk) { let offset = chunk.len(); diff --git a/components/lox-compile/src/prelude.rs b/components/lox-compile/src/prelude.rs index 8ce1c8c..26a7b3e 100644 --- a/components/lox-compile/src/prelude.rs +++ b/components/lox-compile/src/prelude.rs @@ -1,12 +1,13 @@ +use lox_ir::bytecode::CompiledFunction; + use crate::compile::compile; -use lox_ir::bytecode::Closure; pub trait FunctionCompileExt { - fn compile(&self, db: &dyn crate::Db) -> Closure; + fn compile(&self, db: &dyn crate::Db) -> CompiledFunction; } impl FunctionCompileExt for lox_ir::function::Function { - fn compile(&self, db: &dyn crate::Db) -> Closure { + fn compile(&self, db: &dyn crate::Db) -> CompiledFunction { compile(db, *self) } } diff --git a/components/lox-execute/src/vm.rs b/components/lox-execute/src/vm.rs index 5038180..3a5daab 100644 --- a/components/lox-execute/src/vm.rs +++ b/components/lox-execute/src/vm.rs @@ -1,7 +1,10 @@ use std::collections::HashMap; use lox_compile::prelude::FunctionCompileExt; -use lox_ir::bytecode::{self, Closure, Function}; +use lox_ir::{ + bytecode::{self, CompiledFunction}, + function::Function, +}; #[derive(Clone)] pub enum Value { @@ -9,10 +12,8 @@ pub enum Value { Boolean(bool), Nil, String(String), - Closure { - function: Function, - upvalues: Vec, - }, + Function(Function), + CompiledFunction(CompiledFunction), } impl std::fmt::Display for Value { @@ -22,7 +23,8 @@ impl std::fmt::Display for Value { Value::Boolean(b) => write!(f, "{}", b), Value::Nil => write!(f, "nil"), Value::String(s) => write!(f, "{}", s), - Value::Closure { function, .. } => write!(f, "", function.name), + Value::Function(func) => write!(f, "", func), + Value::CompiledFunction(func) => write!(f, "", &func.name), } } } @@ -34,7 +36,8 @@ impl std::fmt::Debug for Value { Value::Boolean(b) => write!(f, "{}", b), Value::Nil => write!(f, "nil"), Value::String(s) => write!(f, "{}", s), - Value::Closure { function, .. } => write!(f, "", function.name), + Value::Function(func) => write!(f, "", func), + Value::CompiledFunction(func) => write!(f, "", &func.name), } } } @@ -152,11 +155,9 @@ pub(crate) enum ControlFlow { #[derive(Debug, Clone)] struct CallFrame { - function: Function, + function: CompiledFunction, ip: usize, fp: usize, - - upvalues: Vec, } impl CallFrame { @@ -190,20 +191,15 @@ pub struct VM { } impl VM { - pub fn new(main: Closure) -> Self { + pub fn new(main: CompiledFunction) -> Self { let frame = CallFrame { - function: main.function, + function: main.clone(), ip: 0, fp: 0, - upvalues: vec![], }; let mut heap = generational_arena::Arena::new(); - let index_of_main = heap.insert(Value::Closure { - function: frame.function.clone(), - upvalues: vec![], - }); - + let index_of_main = heap.insert(Value::CompiledFunction(main)); // push the value of the main function to the stack to a call to the main function, // making it is consistent with other function calls. let stack = vec![index_of_main]; @@ -217,7 +213,7 @@ impl VM { } } - pub fn push_frame(&mut self, function: Function, upvalues: Vec) { + pub fn push_frame(&mut self, function: CompiledFunction) { let arity = function.arity; let frame = CallFrame { @@ -237,7 +233,6 @@ impl VM { // // the the fp is `6 - 3 - 1 = 2`, -1 for the function itself. fp: self.stack.len() - arity - 1, - upvalues, }; tracing::debug!("pushing frame: {:?}", frame); self.frames.push(frame); @@ -425,40 +420,15 @@ impl VM { bytecode::Code::Call { arity } => { let closure = self.peek_n_from_top(arity); match closure { - Value::Closure { function, upvalues } => { - self.push_frame(function.clone(), upvalues.clone()); + Value::Function(function) => { + let compiled_function = function.compile(db); + self.push_frame(compiled_function); } _ => panic!("Cannot call {:?}", closure), } } bytecode::Code::Function(function) => { - let closure = function.compile(db); - let upvalues = closure - .upvalues - .into_iter() - .map(|upvalue| { - if upvalue.is_local { - frame.local_variable(&self.stack, upvalue.index) - } else { - frame.upvalues[upvalue.index] - } - }) - .collect(); - let closure = Value::Closure { - function: closure.function, - upvalues, - }; - self.push(closure); - } - bytecode::Code::ReadUpvalue { index } => { - let upvalue_idx = frame.upvalues[index]; - let upvalue = &self.heap[upvalue_idx]; - self.push(upvalue.clone()) - } - bytecode::Code::WriteUpvalue { index } => { - let upvalue = frame.upvalues[index]; - let value = self.peek(); - self.heap[upvalue] = value.clone(); + self.push(Value::Function(function)); } bytecode::Code::CloseUpvalue => { // FIXME: As we don't remove the value in the heap created by a function frame, diff --git a/components/lox-ir/src/bytecode.rs b/components/lox-ir/src/bytecode.rs index f970d0a..eb58aa2 100644 --- a/components/lox-ir/src/bytecode.rs +++ b/components/lox-ir/src/bytecode.rs @@ -1,15 +1,3 @@ -#[derive(Clone, PartialEq, Eq, Debug)] -pub struct Upvalue { - pub index: usize, - pub is_local: bool, -} - -impl Upvalue { - pub fn new(index: usize, is_local: bool) -> Self { - Self { index, is_local } - } -} - #[derive(Clone, PartialEq, Eq, Debug)] pub enum Code { Return, @@ -53,12 +41,6 @@ pub enum Code { Call { arity: usize, }, - ReadUpvalue { - index: usize, - }, - WriteUpvalue { - index: usize, - }, CloseUpvalue, } @@ -92,14 +74,8 @@ impl Chunk { } #[derive(PartialEq, Eq, Debug, Clone, Default)] -pub struct Function { +pub struct CompiledFunction { pub name: String, pub arity: usize, pub chunk: Chunk, } - -#[derive(PartialEq, Eq, Debug, Clone, Default)] -pub struct Closure { - pub function: Function, - pub upvalues: Vec, -} diff --git a/lox_tests/and/bytecode b/lox_tests/and/bytecode index 6ec72d9..2758055 100644 --- a/lox_tests/and/bytecode +++ b/lox_tests/and/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/arithmetic/bytecode b/lox_tests/arithmetic/bytecode index 8485131..9b280d3 100644 --- a/lox_tests/arithmetic/bytecode +++ b/lox_tests/arithmetic/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/assignment/bytecode b/lox_tests/assignment/bytecode index b6be7e7..28f08f7 100644 --- a/lox_tests/assignment/bytecode +++ b/lox_tests/assignment/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/boolean/bytecode b/lox_tests/boolean/bytecode index bf86017..b7b152d 100644 --- a/lox_tests/boolean/bytecode +++ b/lox_tests/boolean/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/comparison/bytecode b/lox_tests/comparison/bytecode index 96215d5..e820a09 100644 --- a/lox_tests/comparison/bytecode +++ b/lox_tests/comparison/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/equality/bytecode b/lox_tests/equality/bytecode index ebf6dcb..3c8d780 100644 --- a/lox_tests/equality/bytecode +++ b/lox_tests/equality/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/fib/bytecode b/lox_tests/fib/bytecode index de218e6..be35a61 100644 --- a/lox_tests/fib/bytecode +++ b/lox_tests/fib/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/for/bytecode b/lox_tests/for/bytecode index 9d765da..0f173f1 100644 --- a/lox_tests/for/bytecode +++ b/lox_tests/for/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/func/bytecode b/lox_tests/func/bytecode index 9fac435..294af77 100644 --- a/lox_tests/func/bytecode +++ b/lox_tests/func/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/if/bytecode b/lox_tests/if/bytecode index 1f1b3bc..fdd3a5e 100644 --- a/lox_tests/if/bytecode +++ b/lox_tests/if/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/local_var/bytecode b/lox_tests/local_var/bytecode index 94dabe5..d98481c 100644 --- a/lox_tests/local_var/bytecode +++ b/lox_tests/local_var/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/local_var_assign/bytecode b/lox_tests/local_var_assign/bytecode index 5e8deed..428f17b 100644 --- a/lox_tests/local_var_assign/bytecode +++ b/lox_tests/local_var_assign/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/or/bytecode b/lox_tests/or/bytecode index 7b57bbe..38e0d5d 100644 --- a/lox_tests/or/bytecode +++ b/lox_tests/or/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/print/bytecode b/lox_tests/print/bytecode index c7ad89d..83d40ee 100644 --- a/lox_tests/print/bytecode +++ b/lox_tests/print/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/string/bytecode b/lox_tests/string/bytecode index 318ad3a..8d6c578 100644 --- a/lox_tests/string/bytecode +++ b/lox_tests/string/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/var/bytecode b/lox_tests/var/bytecode index de3087e..1ea5fc3 100644 --- a/lox_tests/var/bytecode +++ b/lox_tests/var/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { diff --git a/lox_tests/while/bytecode b/lox_tests/while/bytecode index 527a5c4..0252bec 100644 --- a/lox_tests/while/bytecode +++ b/lox_tests/while/bytecode @@ -1,4 +1,4 @@ -Function { +CompiledFunction { name: "main", arity: 0, chunk: Chunk { From 4e288305666144f6cab41e5fcb0aa1abfa156b33 Mon Sep 17 00:00:00 2001 From: XFFXFF <1247714429@qq.com> Date: Thu, 9 Nov 2023 16:16:42 +0800 Subject: [PATCH 4/5] compile it when you need --- components/lox-execute/src/execute.rs | 4 +--- components/lox-execute/src/vm.rs | 10 ++++------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/components/lox-execute/src/execute.rs b/components/lox-execute/src/execute.rs index c226f7d..e0489ce 100644 --- a/components/lox-execute/src/execute.rs +++ b/components/lox-execute/src/execute.rs @@ -1,4 +1,3 @@ -use lox_compile::prelude::FunctionCompileExt; use lox_ir::{bytecode, input_file::InputFile}; use crate::vm::{ControlFlow, VM}; @@ -16,8 +15,7 @@ pub fn execute_file( step_inspect: Option, &VM) + Clone>, ) -> String { let main = main_function(db, input_file.clone()); - let function = main.compile(db); - let mut vm = VM::new(function); + let mut vm = VM::new(main, db); while let ControlFlow::Next = vm.step(db, step_inspect.clone()) {} diff --git a/components/lox-execute/src/vm.rs b/components/lox-execute/src/vm.rs index 3a5daab..37cb219 100644 --- a/components/lox-execute/src/vm.rs +++ b/components/lox-execute/src/vm.rs @@ -13,7 +13,6 @@ pub enum Value { Nil, String(String), Function(Function), - CompiledFunction(CompiledFunction), } impl std::fmt::Display for Value { @@ -24,7 +23,6 @@ impl std::fmt::Display for Value { Value::Nil => write!(f, "nil"), Value::String(s) => write!(f, "{}", s), Value::Function(func) => write!(f, "", func), - Value::CompiledFunction(func) => write!(f, "", &func.name), } } } @@ -37,7 +35,6 @@ impl std::fmt::Debug for Value { Value::Nil => write!(f, "nil"), Value::String(s) => write!(f, "{}", s), Value::Function(func) => write!(f, "", func), - Value::CompiledFunction(func) => write!(f, "", &func.name), } } } @@ -191,15 +188,16 @@ pub struct VM { } impl VM { - pub fn new(main: CompiledFunction) -> Self { + pub fn new(main: Function, db: &dyn crate::Db) -> Self { + let function = main.compile(db); let frame = CallFrame { - function: main.clone(), + function, ip: 0, fp: 0, }; let mut heap = generational_arena::Arena::new(); - let index_of_main = heap.insert(Value::CompiledFunction(main)); + let index_of_main = heap.insert(Value::Function(main)); // push the value of the main function to the stack to a call to the main function, // making it is consistent with other function calls. let stack = vec![index_of_main]; From 44e0a07806a18503e3718808df78d683e51d77a2 Mon Sep 17 00:00:00 2001 From: XFFXFF <1247714429@qq.com> Date: Thu, 9 Nov 2023 17:15:27 +0800 Subject: [PATCH 5/5] make fmt and cliipy happy --- components/lox-compile/src/compile.rs | 6 ++++-- components/lox-execute/src/execute.rs | 2 +- components/lox-ir/src/syntax.rs | 2 +- components/lox-parse/src/parser.rs | 1 - 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/components/lox-compile/src/compile.rs b/components/lox-compile/src/compile.rs index cef51c3..24896be 100644 --- a/components/lox-compile/src/compile.rs +++ b/components/lox-compile/src/compile.rs @@ -35,8 +35,10 @@ pub fn compile(db: &dyn crate::Db, function: lox_ir::function::Function) -> Comp } else { 1 }; - let mut compiler = Compiler::default(); - compiler.scope_depth = scope_depth; + let compiler = Compiler { + scope_depth, + ..Default::default() + }; let compiler = Rc::new(RefCell::new(compiler)); let mut chunk = Chunk::default(); diff --git a/components/lox-execute/src/execute.rs b/components/lox-execute/src/execute.rs index e0489ce..c256f9e 100644 --- a/components/lox-execute/src/execute.rs +++ b/components/lox-execute/src/execute.rs @@ -14,7 +14,7 @@ pub fn execute_file( input_file: InputFile, step_inspect: Option, &VM) + Clone>, ) -> String { - let main = main_function(db, input_file.clone()); + let main = main_function(db, input_file); let mut vm = VM::new(main, db); while let ControlFlow::Next = vm.step(db, step_inspect.clone()) {} diff --git a/components/lox-ir/src/syntax.rs b/components/lox-ir/src/syntax.rs index 7fa0638..5bbef7a 100644 --- a/components/lox-ir/src/syntax.rs +++ b/components/lox-ir/src/syntax.rs @@ -1,4 +1,4 @@ -use crate::{word::Word}; +use crate::word::Word; mod op; pub use op::Op; diff --git a/components/lox-parse/src/parser.rs b/components/lox-parse/src/parser.rs index 2275a5d..40ed998 100644 --- a/components/lox-parse/src/parser.rs +++ b/components/lox-parse/src/parser.rs @@ -8,7 +8,6 @@ use lox_ir::{ token_tree::TokenTree, }; - use crate::{ token_test::{AnyTree, Identifier, Number, StringLiteral, TokenTest}, tokens::Tokens,