diff --git a/dmc-lib/src/asm/mod.rs b/dmc-lib/src/asm/mod.rs index 996d136..b3359bb 100644 --- a/dmc-lib/src/asm/mod.rs +++ b/dmc-lib/src/asm/mod.rs @@ -31,7 +31,7 @@ mod smoke_tests { fn multiple_statements() { let asm_functions = assemble( " - extern fn println() + extern fn println() -> Void fn main() let x = 42 println(x) diff --git a/dmc-lib/src/ast/expression_statement.rs b/dmc-lib/src/ast/expression_statement.rs index 473cd0c..4474c24 100644 --- a/dmc-lib/src/ast/expression_statement.rs +++ b/dmc-lib/src/ast/expression_statement.rs @@ -3,8 +3,11 @@ use crate::ast::assemble_context::AssembleContext; use crate::ast::expression::Expression; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::symbol::FunctionSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; +use std::cell::RefCell; +use std::rc::Rc; pub struct ExpressionStatement { expression: Box, @@ -38,6 +41,7 @@ impl ExpressionStatement { context: &mut AssembleContext, symbol_table: &SymbolTable, constants_table: &mut ConstantsTable, + outer_function_symbol: &Rc>, is_last: bool, ) { match self.expression.as_ref() { @@ -57,7 +61,15 @@ impl ExpressionStatement { } } Expression::Additive(additive) => { - additive.assemble(context, symbol_table, constants_table); + let result_register = additive.assemble(context, symbol_table, constants_table); + if is_last + && !matches!(outer_function_symbol.borrow().return_type(), TypeInfo::Void) + { + // set return value + context.instruction(AsmInstruction::SetReturnValue(SetReturnValue::new( + result_register, + ))); + } } _ => unreachable!(), } diff --git a/dmc-lib/src/ast/function.rs b/dmc-lib/src/ast/function.rs index e7df7f4..61cc40e 100644 --- a/dmc-lib/src/ast/function.rs +++ b/dmc-lib/src/ast/function.rs @@ -9,7 +9,9 @@ use crate::source_range::SourceRange; use crate::symbol::FunctionSymbol; use crate::symbol_table::{SymbolInsertError, SymbolTable}; use crate::type_info::TypeInfo; +use std::cell::RefCell; use std::ops::Neg; +use std::rc::Rc; pub struct Function { declared_name: String, @@ -17,6 +19,7 @@ pub struct Function { parameters: Vec, return_type: Option, statements: Vec, + function_symbol: Option>>, } impl Function { @@ -33,6 +36,7 @@ impl Function { parameters, return_type, statements, + function_symbol: None, } } @@ -77,6 +81,9 @@ impl Function { } }; + // save function symbol for later + self.function_symbol = Some(function_symbol.clone()); + // handle parameters symbol_table.push_scope(&format!("parameter_scope({})", self.declared_name)); let mut parameter_symbols = vec![]; @@ -159,9 +166,19 @@ impl Function { ) { context.new_function(&self.declared_name, &self.declared_name_source_range); context.new_block(&format!("{}_enter", self.declared_name)); + let function_symbol = self + .function_symbol + .as_ref() + .expect("function_symbol not initialized; did you type check yet?"); for (i, statement) in self.statements.iter().enumerate() { let is_last = i == self.statements.len() - 1; - statement.assemble(context, symbol_table, constants_table, is_last); + statement.assemble( + context, + symbol_table, + constants_table, + function_symbol, + is_last, + ); } // return context.instruction(AsmInstruction::Return(Return::new(self.parameters.len()))); diff --git a/dmc-lib/src/ast/let_statement.rs b/dmc-lib/src/ast/let_statement.rs index 4cccf68..f9a6ad9 100644 --- a/dmc-lib/src/ast/let_statement.rs +++ b/dmc-lib/src/ast/let_statement.rs @@ -43,10 +43,8 @@ impl LetStatement { pub fn gather_declared_names(&mut self, symbol_table: &mut SymbolTable) -> Vec { let mut diagnostics = vec![]; self.initializer_mut().gather_declared_names(symbol_table); - let insert_result = symbol_table.insert_variable_symbol(VariableSymbol::new( - self.declared_name(), - self.initializer().type_info().clone(), - )); + let insert_result = + symbol_table.insert_variable_symbol(VariableSymbol::new(self.declared_name())); if let Err(symbol_insert_error) = insert_result { match symbol_insert_error { SymbolInsertError::AlreadyDeclared(already_declared) => { @@ -70,9 +68,17 @@ impl LetStatement { } pub fn type_check(&mut self, symbol_table: &SymbolTable) -> Vec { - let mut diagnostics = vec![]; - diagnostics.append(&mut self.initializer.type_check(symbol_table)); - diagnostics + let initializer_diagnostics = self.initializer.type_check(symbol_table); + if !initializer_diagnostics.is_empty() { + return initializer_diagnostics; + } + let initializer_type_info = self.initializer.type_info(); + let variable_symbol = + symbol_table.get_variable_symbol(self.scope_id.unwrap(), &self.declared_name); + variable_symbol + .borrow_mut() + .set_type_info(initializer_type_info); + vec![] } pub fn assemble( diff --git a/dmc-lib/src/ast/statement.rs b/dmc-lib/src/ast/statement.rs index 86d37f3..807bf36 100644 --- a/dmc-lib/src/ast/statement.rs +++ b/dmc-lib/src/ast/statement.rs @@ -3,7 +3,10 @@ use crate::ast::expression_statement::ExpressionStatement; use crate::ast::let_statement::LetStatement; use crate::constants_table::ConstantsTable; use crate::diagnostic::Diagnostic; +use crate::symbol::FunctionSymbol; use crate::symbol_table::SymbolTable; +use std::cell::RefCell; +use std::rc::Rc; pub enum Statement { Let(LetStatement), @@ -43,6 +46,7 @@ impl Statement { context: &mut AssembleContext, symbol_table: &SymbolTable, constants_table: &mut ConstantsTable, + outer_function_symbol: &Rc>, is_last: bool, ) { match self { @@ -50,7 +54,13 @@ impl Statement { let_statement.assemble(context, symbol_table, constants_table); } Statement::Expression(expression_statement) => { - expression_statement.assemble(context, symbol_table, constants_table, is_last); + expression_statement.assemble( + context, + symbol_table, + constants_table, + outer_function_symbol, + is_last, + ); } } } diff --git a/dmc-lib/src/symbol.rs b/dmc-lib/src/symbol.rs index 1f990ed..5f87e31 100644 --- a/dmc-lib/src/symbol.rs +++ b/dmc-lib/src/symbol.rs @@ -82,15 +82,15 @@ impl ParameterSymbol { pub struct VariableSymbol { name: Rc, - type_info: TypeInfo, + type_info: Option, register: Option, } impl VariableSymbol { - pub fn new(name: &str, type_info: TypeInfo) -> Self { + pub fn new(name: &str) -> Self { Self { name: name.into(), - type_info, + type_info: None, register: None, } } @@ -103,8 +103,14 @@ impl VariableSymbol { self.name.clone() } + pub fn set_type_info(&mut self, type_info: TypeInfo) { + self.type_info = Some(type_info); + } + pub fn type_info(&self) -> &TypeInfo { - &self.type_info + self.type_info + .as_ref() + .expect("TypeInfo not initialized. Did you type check?") } pub fn set_register(&mut self, register: usize) { diff --git a/dvm-lib/src/vm/mod.rs b/dvm-lib/src/vm/mod.rs index a1cd40c..c3cc771 100644 --- a/dvm-lib/src/vm/mod.rs +++ b/dvm-lib/src/vm/mod.rs @@ -180,6 +180,11 @@ pub fn call<'a>( function_name: &str, arguments: Vec, ) -> Option { + // check if DVM_DEBUG is enabled + let debug = std::env::var("DVM_DEBUG") + .map(|s| s.eq("1")) + .unwrap_or(false); + let function = context .functions .get(function_name) @@ -203,7 +208,9 @@ pub fn call<'a>( && call_stack.top().ip() < call_stack.top().instructions().len() { let instruction = &call_stack.top().instructions()[call_stack.top().ip()]; - // println!("{}", instruction); + if debug { + println!("{}", instruction); + } match instruction { /* Move instructions */ @@ -361,13 +368,14 @@ pub fn call<'a>( } Instruction::Return(caller_pop_count) => { - call_stack.pop(); // pop this frame + let mut callee = call_stack.pop(); // pop this frame let maybe_caller = call_stack.maybe_top_mut(); if let Some(caller) = maybe_caller { for _ in 0..*caller_pop_count { caller.stack_mut().pop(); } - if let Some(return_value) = caller.take_return_value() { + if let Some(return_value) = callee.take_return_value() { + // n.b. callee caller.stack_mut().push(return_value); } } @@ -375,11 +383,13 @@ pub fn call<'a>( } } - // if let Some(top) = call_stack.maybe_top() { - // println!(" stack: {:?}", top.stack()); - // println!(" registers: {:?}", registers); - // println!(" rv: {:?}", top.return_value()); - // } + if debug { + if let Some(top) = call_stack.maybe_top() { + println!(" stack: {:?}", top.stack()); + println!(" registers: {:?}", registers); + println!(" rv: {:?}", top.return_value()); + } + } } None // todo: returning results from main functions } diff --git a/examples/call.dm b/examples/call.dm index 5228904..0aa5ea2 100644 --- a/examples/call.dm +++ b/examples/call.dm @@ -1,12 +1,11 @@ extern fn println(message: Any) -> Void -fn add(a: Int, b: Int) -> Void - println(a + b) +fn add(a: Int, b: Int) -> Int + a + b end fn main() - let x = 1 + 2 + 3 - add(x, 1) - add(x, 2) - add(21, 21) + let y = add(1, 2) + println(y) + println(add(3, add(4, 5))) end \ No newline at end of file