Add some security checks, typecheck for condition to be a boolean
This commit is contained in:
parent
a366d22470
commit
9b68ecb614
@ -1,6 +1,6 @@
|
||||
// Main
|
||||
fn main() -> i32 {
|
||||
return fibonacci(3);
|
||||
return (fibonacci(3) < 5) + 5;
|
||||
}
|
||||
|
||||
// Fibonacci
|
||||
|
@ -183,6 +183,7 @@ impl mir::Expression {
|
||||
pub fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>) -> Option<InstructionValue> {
|
||||
match &self.0 {
|
||||
mir::ExprKind::Variable(varref) => {
|
||||
varref.0.is_known().expect("variable type unknown");
|
||||
let v = scope
|
||||
.stack_values
|
||||
.get(&varref.1)
|
||||
@ -191,6 +192,17 @@ impl mir::Expression {
|
||||
}
|
||||
mir::ExprKind::Literal(lit) => Some(lit.as_const(&mut scope.block)),
|
||||
mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => {
|
||||
lhs_exp
|
||||
.return_type()
|
||||
.expect("No ret type in lhs?")
|
||||
.is_known()
|
||||
.expect("lhs ret type is unknown");
|
||||
rhs_exp
|
||||
.return_type()
|
||||
.expect("No ret type in rhs?")
|
||||
.is_known()
|
||||
.expect("rhs ret type is unknown");
|
||||
|
||||
let lhs = lhs_exp.codegen(scope).expect("lhs has no return value");
|
||||
let rhs = rhs_exp.codegen(scope).expect("rhs has no return value");
|
||||
Some(match binop {
|
||||
@ -202,16 +214,17 @@ impl mir::Expression {
|
||||
}
|
||||
mir::BinaryOperator::Mult => todo!(),
|
||||
mir::BinaryOperator::And => todo!(),
|
||||
mir::BinaryOperator::Logic(l) => {
|
||||
let ret_type = lhs_exp.return_type().expect("No ret type in lhs?");
|
||||
scope
|
||||
.block
|
||||
.build(InstructionKind::ICmp(l.int_predicate(), lhs, rhs))
|
||||
.unwrap()
|
||||
}
|
||||
mir::BinaryOperator::Logic(l) => scope
|
||||
.block
|
||||
.build(InstructionKind::ICmp(l.int_predicate(), lhs, rhs))
|
||||
.unwrap(),
|
||||
})
|
||||
}
|
||||
mir::ExprKind::FunctionCall(call) => {
|
||||
call.return_type
|
||||
.is_known()
|
||||
.expect("function return type unknown");
|
||||
|
||||
let params = call
|
||||
.parameters
|
||||
.iter()
|
||||
@ -293,6 +306,7 @@ impl TypeKind {
|
||||
match &self {
|
||||
TypeKind::I32 => Type::I32,
|
||||
TypeKind::I16 => Type::I16,
|
||||
TypeKind::Bool => Type::Bool,
|
||||
TypeKind::Void => panic!("Void not a supported type"),
|
||||
TypeKind::Vague(_) => panic!("Tried to compile a vague type!"),
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ pub enum TypeKind {
|
||||
I32,
|
||||
#[error("i16")]
|
||||
I16,
|
||||
#[error("bool")]
|
||||
Bool,
|
||||
#[error("void")]
|
||||
Void,
|
||||
#[error(transparent)]
|
||||
@ -51,12 +53,35 @@ pub enum VagueType {
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
pub fn is_known(&self) -> Result<TypeKind, VagueType> {
|
||||
if let TypeKind::Vague(vague) = self {
|
||||
Err(*vague)
|
||||
} else {
|
||||
Ok(*self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeKind {
|
||||
pub fn signed(&self) -> bool {
|
||||
match self {
|
||||
TypeKind::Void => false,
|
||||
TypeKind::Vague(_) => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_maths(&self) -> bool {
|
||||
use TypeKind::*;
|
||||
match &self {
|
||||
I32 => true,
|
||||
I16 => true,
|
||||
Bool => true,
|
||||
Vague(_) => false,
|
||||
Void => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -171,12 +171,10 @@ impl FunctionDefinition {
|
||||
}
|
||||
|
||||
let return_type = self.return_type.clone();
|
||||
dbg!(&return_type);
|
||||
let inferred = match &self.kind {
|
||||
FunctionDefinitionKind::Local(block, _) => block.typecheck(state, scope),
|
||||
FunctionDefinitionKind::Extern => Ok(Vague(Unknown)),
|
||||
};
|
||||
dbg!(&inferred);
|
||||
|
||||
match inferred {
|
||||
Ok(t) => try_collapse(&return_type, &t)
|
||||
@ -295,7 +293,8 @@ impl Expression {
|
||||
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
||||
// TODO make sure cond_res is Boolean here
|
||||
let cond_res = cond.typecheck(state, scope);
|
||||
state.ok(cond_res, cond.1);
|
||||
let cond_t = state.or_else(cond_res, Vague(Unknown), cond.1);
|
||||
state.ok(cond_t.collapse_into(&Bool), cond.1);
|
||||
|
||||
let lhs_res = lhs.typecheck(state, scope);
|
||||
let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.meta);
|
||||
@ -314,11 +313,7 @@ impl Expression {
|
||||
|
||||
impl TypeKind {
|
||||
fn assert_known(&self) -> Result<TypeKind, ErrorKind> {
|
||||
if let Vague(vague) = self {
|
||||
Err(ErrorKind::TypeIsVague(*vague))
|
||||
} else {
|
||||
Ok(*self)
|
||||
}
|
||||
self.is_known().map_err(ErrorKind::TypeIsVague)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user