if else type analysis

This commit is contained in:
Edgar 2023-06-03 12:43:12 +02:00
parent c568cf08e9
commit 10cc3ae591
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
4 changed files with 39 additions and 10 deletions

View file

@ -5,12 +5,29 @@ A toy language I'm making to learn LLVM and compilers.
Syntax is subject to change any time right now. It has a rusty style for now. Syntax is subject to change any time right now. It has a rusty style for now.
``` ```
fn add(a: i64, b: i64) -> i64 { struct Hello {
return a + b; x: i32,
y: i32,
} }
fn main() { fn test(x: Hello) {
let x = 2 + 3; return;
let y = add(x, 4);
} }
fn works(x: i64) -> i64 {
let z = 0;
if 2 == x {
z = x * 2;
} else {
z = x * 3;
}
return z;
}
fn main() -> i64 {
let y: i64 = 2;
let z = y;
return works(z);
}
``` ```

View file

@ -8,8 +8,8 @@ fn test(x: Hello) {
} }
fn works(x: i64) -> i64 { fn works(x: i64) -> i64 {
let z: i64 = 0; let z = 0;
if x == 2 { if 2 == x {
z = x * 2; z = x * 2;
} else { } else {
z = x * 3; z = x * 3;

View file

@ -489,10 +489,11 @@ impl<'ctx> CodeGen<'ctx> {
let (lhs, lhs_type) = self let (lhs, lhs_type) = self
.compile_expression(lhs, variables, types)? .compile_expression(lhs, variables, types)?
.expect("should have result"); .expect("should have result");
let (rhs, _rhs_type) = self let (rhs, rhs_type) = self
.compile_expression(rhs, variables, types)? .compile_expression(rhs, variables, types)?
.expect("should have result"); .expect("should have result");
assert_eq!(lhs_type, rhs_type);
let lhs = lhs.into_int_value(); let lhs = lhs.into_int_value();
let rhs = rhs.into_int_value(); let rhs = rhs.into_int_value();

View file

@ -10,6 +10,10 @@ pub fn type_inference(ast: &mut ast::Program) {
let ret_type = function.return_type.clone(); let ret_type = function.return_type.clone();
let mut var_cache: HashMap<String, TypeExp> = HashMap::new(); let mut var_cache: HashMap<String, TypeExp> = HashMap::new();
for arg in &function.params {
var_cache.insert(arg.ident.clone(), arg.type_exp.clone());
}
if let Some(ret_type) = &ret_type { if let Some(ret_type) = &ret_type {
let ret_type_exp = fn_return_type(function); let ret_type_exp = fn_return_type(function);
@ -175,6 +179,7 @@ fn set_exp_types_from_cache(
if let Some(value_type) = value_type { if let Some(value_type) = value_type {
// todo: check types matches? // todo: check types matches?
var_cache.insert(name, value_type.clone()); var_cache.insert(name, value_type.clone());
*env = Some(value_type.clone());
} else if var_cache.contains_key(&name) { } else if var_cache.contains_key(&name) {
*value_type = var_cache.get(&name).cloned(); *value_type = var_cache.get(&name).cloned();
if env.is_none() { if env.is_none() {
@ -183,10 +188,16 @@ fn set_exp_types_from_cache(
} }
} }
Expression::BinaryOp(lhs, op, rhs) => match op { Expression::BinaryOp(lhs, op, rhs) => match op {
ast::OpCode::Eq | ast::OpCode::Ne => {} ast::OpCode::Eq | ast::OpCode::Ne => {
set_exp_types_from_cache(lhs, var_cache, env);
set_exp_types_from_cache(rhs, var_cache, env);
set_exp_types_from_cache(lhs, var_cache, env);
*env = Some(TypeExp::Boolean);
}
_ => { _ => {
set_exp_types_from_cache(lhs, var_cache, env); set_exp_types_from_cache(lhs, var_cache, env);
set_exp_types_from_cache(rhs, var_cache, env); set_exp_types_from_cache(rhs, var_cache, env);
set_exp_types_from_cache(lhs, var_cache, env); // needed in case 2 == x
} }
}, },
Expression::Literal(lit) => match lit { Expression::Literal(lit) => match lit {
@ -241,7 +252,7 @@ fn set_expression_type(
} }
} }
Expression::BinaryOp(lhs, op, rhs) => match op { Expression::BinaryOp(lhs, op, rhs) => match op {
ast::OpCode::Eq | ast::OpCode::Ne => {} // ast::OpCode::Eq | ast::OpCode::Ne => {}
_ => { _ => {
set_expression_type(lhs, expected_type, var_cache); set_expression_type(lhs, expected_type, var_cache);
set_expression_type(rhs, expected_type, var_cache); set_expression_type(rhs, expected_type, var_cache);