implemented if

This commit is contained in:
2021-11-01 09:21:36 +01:00
parent 02b8ff860b
commit d0ee844d8c
7 changed files with 297 additions and 150 deletions

View File

@@ -85,7 +85,7 @@ pub fn tc_script(script: &mut ast::Script, source: &str) -> Result<()> {
}
}
tc_block(&mut context, &mut f.body)?;
tc_expression(&mut context, &mut f.body)?;
}
result
@@ -98,19 +98,6 @@ struct Context<'a> {
block_stack: Vec<String>,
}
fn tc_block(context: &mut Context, block: &mut ast::Block) -> Result<()> {
let mut result = Ok(());
for stmt in &mut block.statements {
if tc_expression(context, stmt).is_err() {
result = Err(());
}
}
if let Some(ref mut expr) = block.final_expression {
tc_expression(context, expr)?;
}
result
}
fn report_duplicate_definition(
msg: &str,
span: &Span,
@@ -195,6 +182,20 @@ fn unknown_variable(span: &Span, source: &str) -> Result<()> {
fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()> {
expr.type_ = match expr.expr {
ast::Expr::Block {
ref mut statements,
ref mut final_expression
} => {
for stmt in statements {
tc_expression(context, stmt)?;
}
if let Some(final_expression) = final_expression {
tc_expression(context, final_expression)?;
final_expression.type_
} else {
None
}
}
ast::Expr::Let {
ref mut value,
ref mut type_,
@@ -254,6 +255,10 @@ fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()
}
None
}
ast::Expr::Peek(ref mut mem_location) => {
tc_mem_location(context, mem_location)?;
Some(I32)
}
ast::Expr::Poke {
ref mut mem_location,
ref mut value,
@@ -346,9 +351,9 @@ fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()
ref mut block,
} => {
context.block_stack.push(label.clone());
tc_block(context, block)?;
tc_expression(context, block)?;
context.block_stack.pop();
block.final_expression.as_ref().and_then(|e| e.type_)
block.type_
}
ast::Expr::BranchIf {
ref mut condition,
@@ -474,6 +479,25 @@ fn tc_expression(context: &mut Context, expr: &mut ast::Expression) -> Result<()
}
if_true.type_
}
ast::Expr::If {
ref mut condition,
ref mut if_true,
ref mut if_false
} => {
tc_expression(context, condition)?;
tc_expression(context, if_true)?;
if let Some(ref mut if_false) = if_false {
tc_expression(context, if_false)?;
if if_true.type_ != if_false.type_ {
// TODO: report type mismatch?
None
} else {
if_true.type_
}
} else {
None
}
}
ast::Expr::Error => unreachable!(),
};
Ok(())