Add return mechanism to dvm code, and related fixes to dmc.
This commit is contained in:
parent
2e33936842
commit
ec7bf650b2
@ -107,7 +107,9 @@ fn main() {
|
|||||||
"main",
|
"main",
|
||||||
vec![],
|
vec![],
|
||||||
);
|
);
|
||||||
println!("{:?}", result);
|
if let Some(value) = result {
|
||||||
|
println!("{}", value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_and_report_diagnostics(
|
fn check_and_report_diagnostics(
|
||||||
|
|||||||
@ -32,9 +32,14 @@ impl ExpressionStatement {
|
|||||||
self.expression.type_check(symbol_table)
|
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);
|
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
|
builder
|
||||||
.current_block_mut()
|
.current_block_mut()
|
||||||
.add_statement(IrStatement::Return(IrReturn::new(ir_expression)));
|
.add_statement(IrStatement::Return(IrReturn::new(ir_expression)));
|
||||||
|
|||||||
@ -171,17 +171,22 @@ impl Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let entry_block_id = builder.new_block();
|
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() {
|
for (i, statement) in self.statements.iter().enumerate() {
|
||||||
let is_last = i == self.statements.len() - 1;
|
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();
|
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();
|
let entry_block = builder.get_block(entry_block_id).clone();
|
||||||
IrFunction::new(
|
IrFunction::new(
|
||||||
self.function_symbol.as_ref().unwrap().clone(),
|
self.function_symbol.as_ref().unwrap().clone(),
|
||||||
|
|||||||
@ -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 {
|
match self {
|
||||||
Statement::Let(let_statement) => {
|
Statement::Let(let_statement) => {
|
||||||
let_statement.to_ir(builder, symbol_table);
|
let_statement.to_ir(builder, symbol_table);
|
||||||
}
|
}
|
||||||
Statement::Expression(expression_statement) => {
|
Statement::Expression(expression_statement) => {
|
||||||
expression_statement.to_ir(builder, symbol_table, is_last);
|
expression_statement.to_ir(builder, symbol_table, should_return_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -244,6 +244,9 @@ pub fn call<'a>(
|
|||||||
Value::Null,
|
Value::Null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// container for final return value
|
||||||
|
let mut return_value: Option<Value> = None;
|
||||||
|
|
||||||
while call_stack.maybe_top().is_some()
|
while call_stack.maybe_top().is_some()
|
||||||
&& call_stack.top().ip() < call_stack.top().instructions().len()
|
&& call_stack.top().ip() < call_stack.top().instructions().len()
|
||||||
{
|
{
|
||||||
@ -486,6 +489,10 @@ pub fn call<'a>(
|
|||||||
// n.b. callee
|
// n.b. callee
|
||||||
caller.stack_mut().push(return_value);
|
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
|
// 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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use std::fmt::{Display, Formatter};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[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
3
examples/main_return.dm
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() -> Int
|
||||||
|
42
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue
Block a user