Add return mechanism to dvm code, and related fixes to dmc.

This commit is contained in:
Jesse Brault 2026-03-08 13:33:06 -05:00
parent 2e33936842
commit ec7bf650b2
7 changed files with 56 additions and 12 deletions

View File

@ -107,7 +107,9 @@ fn main() {
"main",
vec![],
);
println!("{:?}", result);
if let Some(value) = result {
println!("{}", value);
}
}
fn check_and_report_diagnostics(

View File

@ -32,9 +32,14 @@ impl ExpressionStatement {
self.expression.type_check(symbol_table)
}
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable, is_last: bool) {
pub fn to_ir(
&self,
builder: &mut IrBuilder,
symbol_table: &SymbolTable,
should_return_value: bool,
) {
let ir_expression = self.expression.to_ir(builder, symbol_table);
if ir_expression.is_some() && is_last {
if ir_expression.is_some() && should_return_value {
builder
.current_block_mut()
.add_statement(IrStatement::Return(IrReturn::new(ir_expression)));

View File

@ -171,17 +171,22 @@ impl Function {
}
let entry_block_id = builder.new_block();
let return_type_info = self
.function_symbol
.as_ref()
.unwrap()
.borrow()
.return_type();
let should_return_value = !matches!(return_type_info, TypeInfo::Void);
for (i, statement) in self.statements.iter().enumerate() {
let is_last = i == self.statements.len() - 1;
statement.to_ir(&mut builder, symbol_table, is_last);
statement.to_ir(&mut builder, symbol_table, should_return_value && is_last);
}
builder.finish_block();
let return_type_info = self
.return_type
.as_ref()
.map(|return_type| return_type.to_type_info())
.unwrap_or(TypeInfo::Void);
let entry_block = builder.get_block(entry_block_id).clone();
IrFunction::new(
self.function_symbol.as_ref().unwrap().clone(),

View File

@ -37,13 +37,18 @@ impl Statement {
}
}
pub fn to_ir(&self, builder: &mut IrBuilder, symbol_table: &SymbolTable, is_last: bool) {
pub fn to_ir(
&self,
builder: &mut IrBuilder,
symbol_table: &SymbolTable,
should_return_value: bool,
) {
match self {
Statement::Let(let_statement) => {
let_statement.to_ir(builder, symbol_table);
}
Statement::Expression(expression_statement) => {
expression_statement.to_ir(builder, symbol_table, is_last);
expression_statement.to_ir(builder, symbol_table, should_return_value);
}
}
}

View File

@ -244,6 +244,9 @@ pub fn call<'a>(
Value::Null,
);
// container for final return value
let mut return_value: Option<Value> = None;
while call_stack.maybe_top().is_some()
&& call_stack.top().ip() < call_stack.top().instructions().len()
{
@ -486,6 +489,10 @@ pub fn call<'a>(
// n.b. callee
caller.stack_mut().push(return_value);
}
} else {
// callee is the bottommost frame ("main" or whatever was called)
// set the return value
return_value = callee.take_return_value();
}
// do not increment ip of the caller; this was done above BEFORE the call
}
@ -499,5 +506,5 @@ pub fn call<'a>(
}
}
}
None // todo: returning results from main functions
return_value
}

View File

@ -1,3 +1,4 @@
use std::fmt::{Display, Formatter};
use std::rc::Rc;
#[derive(Clone, Debug)]
@ -28,3 +29,19 @@ impl Value {
}
}
}
impl Display for Value {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Value::Int(i) => {
write!(f, "{}", i)
}
Value::String(s) => {
write!(f, "{}", s)
}
Value::Null => {
write!(f, "Null")
}
}
}
}

3
examples/main_return.dm Normal file
View File

@ -0,0 +1,3 @@
fn main() -> Int
42
end