Implement a bunch of intrinsic binops

This commit is contained in:
Sofia 2025-07-25 18:48:16 +03:00
parent 7ba3204803
commit 63f48f7df9
6 changed files with 228 additions and 334 deletions

View File

@ -0,0 +1 @@
max_width = 120

View File

@ -1,98 +1,161 @@
use std::marker::PhantomData;
use reid_lib::{builder::InstructionValue, Instr};
use reid_lib::{builder::InstructionValue, CmpPredicate, Instr};
use crate::{
codegen::{ErrorKind, StackValueKind},
mir::{BinaryOperator, BinopDefinition, FunctionDefinition, FunctionDefinitionKind, TypeKind},
mir::{BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, FunctionDefinitionKind, TypeKind},
};
use super::scope::{Scope, StackValue};
const INTEGERS: [TypeKind; 10] = [
TypeKind::U8,
TypeKind::U16,
TypeKind::U32,
TypeKind::U64,
TypeKind::U128,
TypeKind::I8,
TypeKind::I16,
TypeKind::I32,
TypeKind::I64,
TypeKind::I128,
];
const FLOATS: [TypeKind; 7] = [
TypeKind::F16,
TypeKind::F32,
TypeKind::F32B,
TypeKind::F64,
TypeKind::F80,
TypeKind::F128,
TypeKind::F128PPC,
];
pub fn form_intrinsics() -> Vec<FunctionDefinition> {
let intrinsics = Vec::new();
intrinsics
}
fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
BinopDefinition {
lhs: ("lhs".to_owned(), ty.clone()),
op,
rhs: ("rhs".to_owned(), ty.clone()),
return_type: ty.clone(),
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))),
meta: Default::default(),
}
}
fn boolean_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
BinopDefinition {
lhs: ("lhs".to_owned(), ty.clone()),
op,
rhs: ("rhs".to_owned(), ty.clone()),
return_type: TypeKind::Bool,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicBooleanInstr(fun))),
meta: Default::default(),
}
}
pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
let mut intrinsics = Vec::new();
intrinsics.push(BinopDefinition {
lhs: ("lhs".to_owned(), TypeKind::U32),
op: BinaryOperator::Add,
rhs: ("rhs".to_owned(), TypeKind::U32),
return_type: TypeKind::U32,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(
|scope, lhs, rhs| scope.block.build(Instr::Add(lhs, rhs)).unwrap(),
))),
meta: Default::default(),
});
use BinaryOperator::*;
intrinsics.push(BinopDefinition {
lhs: ("lhs".to_owned(), TypeKind::U16),
op: BinaryOperator::Add,
rhs: ("rhs".to_owned(), TypeKind::U16),
return_type: TypeKind::U16,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(
|scope, lhs, rhs| scope.block.build(Instr::Add(lhs, rhs)).unwrap(),
))),
meta: Default::default(),
});
intrinsics.push(BinopDefinition {
lhs: ("lhs".to_owned(), TypeKind::U32),
op: BinaryOperator::Mult,
rhs: ("rhs".to_owned(), TypeKind::U32),
return_type: TypeKind::U32,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(
|scope, lhs, rhs| scope.block.build(Instr::Mul(lhs, rhs)).unwrap(),
))),
meta: Default::default(),
});
intrinsics.push(BinopDefinition {
lhs: ("lhs".to_owned(), TypeKind::U16),
op: BinaryOperator::Mult,
rhs: ("rhs".to_owned(), TypeKind::U16),
return_type: TypeKind::U16,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(
|scope, lhs, rhs| scope.block.build(Instr::Mul(lhs, rhs)).unwrap(),
))),
meta: Default::default(),
});
intrinsics.push(BinopDefinition {
lhs: ("lhs".to_owned(), TypeKind::U32),
op: BinaryOperator::Minus,
rhs: ("rhs".to_owned(), TypeKind::U32),
return_type: TypeKind::U32,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(
|scope, lhs, rhs| scope.block.build(Instr::Sub(lhs, rhs)).unwrap(),
))),
meta: Default::default(),
});
intrinsics.push(BinopDefinition {
lhs: ("lhs".to_owned(), TypeKind::U16),
op: BinaryOperator::Minus,
rhs: ("rhs".to_owned(), TypeKind::U16),
return_type: TypeKind::U16,
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(
|scope, lhs, rhs| scope.block.build(Instr::Sub(lhs, rhs)).unwrap(),
))),
meta: Default::default(),
});
for ty in INTEGERS {
intrinsics.push(simple_binop_def(Add, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::Add(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(Mult, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::Mul(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(Minus, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::Sub(lhs, rhs)).unwrap()
}));
if ty.signed() {
intrinsics.push(simple_binop_def(Div, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::SDiv(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(Mod, &ty, |scope, lhs, rhs| {
let div = scope.block.build(Instr::SDiv(lhs, rhs)).unwrap();
let mul = scope.block.build(Instr::Mul(rhs, div)).unwrap();
scope.block.build(Instr::Sub(lhs, mul)).unwrap()
}));
} else {
intrinsics.push(simple_binop_def(Div, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::UDiv(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(Mod, &ty, |scope, lhs, rhs| {
let div = scope.block.build(Instr::UDiv(lhs, rhs)).unwrap();
let mul = scope.block.build(Instr::Mul(rhs, div)).unwrap();
scope.block.build(Instr::Sub(lhs, mul)).unwrap()
}));
}
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GT), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::GT, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::GE, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LT), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::LT, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::LE, lhs, rhs)).unwrap()
}));
}
for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) {
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::EQ, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::NE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::NE, lhs, rhs)).unwrap()
}));
}
for ty in FLOATS {
intrinsics.push(simple_binop_def(BinaryOperator::Add, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FAdd(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(BinaryOperator::Mult, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FMul(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(BinaryOperator::Minus, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FSub(lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FCmp(CmpPredicate::EQ, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::NE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FCmp(CmpPredicate::NE, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GT), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FCmp(CmpPredicate::GT, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::GE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FCmp(CmpPredicate::GE, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LT), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FCmp(CmpPredicate::LT, lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::FCmp(CmpPredicate::LE, lhs, rhs)).unwrap()
}));
}
intrinsics
}
pub trait IntrinsicFunction: std::fmt::Debug {
fn codegen<'ctx, 'a>(
&self,
scope: &mut Scope<'ctx, 'a>,
params: &[&StackValue],
) -> Result<StackValue, ErrorKind>;
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[&StackValue]) -> Result<StackValue, ErrorKind>;
}
#[derive(Clone)]
@ -113,11 +176,7 @@ impl<T: Clone> IntrinsicFunction for IntrinsicSimpleInstr<T>
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
fn codegen<'b, 'c>(
&self,
scope: &mut Scope<'b, 'c>,
params: &[&StackValue],
) -> Result<StackValue, ErrorKind> {
fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[&StackValue]) -> Result<StackValue, ErrorKind> {
let lhs = params.get(0).unwrap();
let rhs = params.get(1).unwrap();
let instr = self.clone().0(scope, lhs.instr(), rhs.instr());
@ -125,6 +184,32 @@ where
}
}
#[derive(Clone)]
pub struct IntrinsicBooleanInstr<T>(T)
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue;
impl<T> std::fmt::Debug for IntrinsicBooleanInstr<T>
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("IntrinsicBooleanInstr").finish()
}
}
impl<T: Clone> IntrinsicFunction for IntrinsicBooleanInstr<T>
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[&StackValue]) -> Result<StackValue, ErrorKind> {
let lhs = params.get(0).unwrap();
let rhs = params.get(1).unwrap();
let instr = self.clone().0(scope, lhs.instr(), rhs.instr());
Ok(StackValue(StackValueKind::Literal(instr), TypeKind::Bool))
}
}
// impl IntrinsicFunction for IntrinsicIAdd {
// fn codegen<'ctx, 'a>(
// &self,

View File

@ -98,11 +98,7 @@ pub fn compile_module<'map>(
let mut statements = Vec::new();
while !matches!(token_stream.peek().unwrap_or(Token::Eof), Token::Eof) {
let statement = ReidError::from_parser(
token_stream.parse::<TopLevelStatement>(),
map.clone(),
module_id,
)?;
let statement = ReidError::from_parser(token_stream.parse::<TopLevelStatement>(), map.clone(), module_id)?;
statements.push(statement);
}
@ -189,8 +185,6 @@ pub fn perform_all_passes<'map>(
println!("{}", &context);
#[cfg(debug_assertions)]
dbg!(&state);
dbg!("asd!");
thread::sleep(Duration::from_millis(100));
if !state.errors.is_empty() {
return Err(ReidError::from_kind(

View File

@ -56,10 +56,7 @@ impl<'t> Pass for TypeCheck<'t> {
}
if let Some(_) = defmap.insert(&typedef.name, typedef) {
state.ok::<_, Infallible>(
Err(ErrorKind::DuplicateTypeName(name.clone())),
meta.clone(),
);
state.ok::<_, Infallible>(Err(ErrorKind::DuplicateTypeName(name.clone())), meta.clone());
}
}
@ -94,10 +91,7 @@ fn check_typedefs_for_recursion<'a, 'b>(
if let TypeKind::CustomType(CustomTypeKey(name, _)) = field_ty {
if seen.contains(name) {
state.ok::<_, Infallible>(
Err(ErrorKind::RecursiveTypeDefinition(
typedef.name.clone(),
name.clone(),
)),
Err(ErrorKind::RecursiveTypeDefinition(typedef.name.clone(), name.clone())),
typedef.meta,
);
} else {
@ -113,11 +107,7 @@ fn check_typedefs_for_recursion<'a, 'b>(
}
impl BinopDefinition {
fn typecheck(
&mut self,
typerefs: &TypeRefs,
state: &mut TypecheckPassState,
) -> Result<TypeKind, ErrorKind> {
fn typecheck(&mut self, typerefs: &TypeRefs, state: &mut TypecheckPassState) -> Result<TypeKind, ErrorKind> {
for param in vec![&self.lhs, &self.rhs] {
let param_t = state.or_else(
param.1.assert_known(typerefs, state),
@ -141,29 +131,21 @@ impl BinopDefinition {
let return_type = self.return_type.clone().assert_known(typerefs, state)?;
state.scope.return_type_hint = Some(self.return_type.clone());
let inferred =
self.fn_kind
.typecheck(&typerefs, &mut state.inner(), Some(return_type.clone()));
let inferred = self
.fn_kind
.typecheck(&typerefs, &mut state.inner(), Some(return_type.clone()));
match inferred {
Ok(t) => return_type
.narrow_into(&t.1)
.or(Err(ErrorKind::ReturnTypeMismatch(return_type, t.1))),
Err(e) => Ok(state.or_else(
Err(e),
return_type,
self.block_meta().unwrap_or(self.signature()),
)),
Err(e) => Ok(state.or_else(Err(e), return_type, self.block_meta().unwrap_or(self.signature()))),
}
}
}
impl FunctionDefinition {
fn typecheck(
&mut self,
typerefs: &TypeRefs,
state: &mut TypecheckPassState,
) -> Result<TypeKind, ErrorKind> {
fn typecheck(&mut self, typerefs: &TypeRefs, state: &mut TypecheckPassState) -> Result<TypeKind, ErrorKind> {
for param in &self.parameters {
let param_t = state.or_else(
param.1.assert_known(typerefs, state),
@ -185,9 +167,7 @@ impl FunctionDefinition {
}
let return_type = self.return_type.clone().assert_known(typerefs, state)?;
let inferred = self
.kind
.typecheck(typerefs, state, Some(self.return_type.clone()));
let inferred = self.kind.typecheck(typerefs, state, Some(self.return_type.clone()));
match inferred {
Ok(t) => return_type
@ -210,12 +190,8 @@ impl FunctionDefinitionKind {
state.scope.return_type_hint = hint.clone();
block.typecheck(&mut state.inner(), &typerefs, hint.as_ref())
}
FunctionDefinitionKind::Extern(_) => {
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
}
FunctionDefinitionKind::Intrinsic(..) => {
Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)))
}
FunctionDefinitionKind::Extern(_) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))),
FunctionDefinitionKind::Intrinsic(..) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))),
}
}
}
@ -293,9 +269,7 @@ impl Block {
mutable: *mutable,
},
)
.or(Err(ErrorKind::VariableAlreadyDefined(
variable_reference.1.clone(),
)));
.or(Err(ErrorKind::VariableAlreadyDefined(variable_reference.1.clone())));
state.ok(res, variable_reference.2);
None
}
@ -344,26 +318,16 @@ impl Block {
StmtKind::Expression(expression) => {
let res = expression.typecheck(&mut state, &typerefs, None);
state.or_else(res, TypeKind::Void, expression.1);
if let Ok((kind, _)) =
expression.return_type(typerefs, state.module_id.unwrap())
{
if let Ok((kind, _)) = expression.return_type(typerefs, state.module_id.unwrap()) {
Some((kind, expression))
} else {
None
}
}
StmtKind::While(WhileStatement {
condition,
block,
meta,
}) => {
let condition_ty =
condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?;
StmtKind::While(WhileStatement { condition, block, meta }) => {
let condition_ty = condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?;
if condition_ty.assert_known(typerefs, &state)? != TypeKind::Bool {
state.note_errors(
&vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)],
*meta,
);
state.note_errors(&vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)], *meta);
}
block.typecheck(&mut state, typerefs, None)?;
@ -453,93 +417,23 @@ impl Expression {
let rhs_res = rhs.typecheck(state, &typerefs, None);
let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
if let Some(binop) = state
.scope
.binops
if let Some(binop) = typerefs
.binop_types
.find(&pass::ScopeBinopKey {
params: (lhs_type.clone(), rhs_type.clone()),
operator: *op,
})
.map(|v| (v.1.clone()))
{
dbg!(&lhs, &rhs);
dbg!(&lhs_type.resolve_ref(typerefs));
dbg!(&rhs_type.resolve_ref(typerefs));
lhs.typecheck(state, &typerefs, Some(&binop.hands.0))?;
rhs.typecheck(state, &typerefs, Some(&binop.hands.1))?;
Ok(binop.narrow(&lhs_type, &rhs_type).unwrap().2)
} else {
Err(ErrorKind::InvalidBinop(*op, lhs_type, rhs_type))
dbg!(&op, &lhs, &rhs);
dbg!(&lhs_type);
dbg!(&rhs_type);
panic!()
}
// let cloned = state.scope.binops.clone();
// let mut iter = cloned.iter();
// let operator = loop {
// let Some((_, binop)) = iter.next() else {
// break None;
// };
// if binop.operator != *op {
// continue;
// }
// if let Some(hint_t) = hint_t {
// if binop.return_ty == *hint_t {
// if let Some(_) = TypeKind::narrow_to_binop(&lhs_type, &rhs_type, binop)
// {
// break Some(binop);
// }
// } else {
// continue;
// }
// }
// if let Some(_) = TypeKind::narrow_to_binop(&lhs_type, &rhs_type, binop) {
// break Some(binop);
// }
// };
// if let Some(operator) = operator {
// // Re-typecheck with found operator hints
// let (lhs_ty, rhs_ty) = TypeKind::try_collapse_two(
// (&lhs_type, &rhs_type),
// (&operator.hands.0, &operator.hands.1),
// )
// .unwrap();
// let lhs_res = lhs.typecheck(state, &typerefs, Some(&lhs_ty));
// let rhs_res = rhs.typecheck(state, &typerefs, Some(&rhs_ty));
// state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
// state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
// Ok(operator.return_ty.clone())
// } else {
// // Re-typecheck with typical everyday binop
// let lhs_res = lhs.typecheck(
// state,
// &typerefs,
// hint_t.and_then(|t| t.simple_binop_hint(op)).as_ref(),
// );
// let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1);
// let rhs_res = rhs.typecheck(state, &typerefs, Some(&lhs_type));
// let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1);
// let both_t = lhs_type.narrow_into(&rhs_type)?;
// if *op == BinaryOperator::Minus && !lhs_type.signed() {
// if let (Some(lhs_val), Some(rhs_val)) = (lhs.num_value()?, rhs.num_value()?)
// {
// if lhs_val < rhs_val {
// return Err(ErrorKind::NegativeUnsignedValue(lhs_type));
// }
// }
// }
// if let Some(collapsed) = state.ok(rhs_type.narrow_into(&rhs_type), self.1) {
// // Try to coerce both sides again with collapsed type
// lhs.typecheck(state, &typerefs, Some(&collapsed)).ok();
// rhs.typecheck(state, &typerefs, Some(&collapsed)).ok();
// }
// both_t
// .simple_binop_type(op)
// .ok_or(ErrorKind::InvalidBinop(*op, lhs_type, rhs_type))
// }
}
ExprKind::FunctionCall(function_call) => {
let true_function = state
@ -571,21 +465,16 @@ impl Expression {
.into_iter()
.chain(iter::repeat(TypeKind::Vague(Vague::Unknown)));
for (param, true_param_t) in
function_call.parameters.iter_mut().zip(true_params_iter)
{
for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) {
// Typecheck every param separately
let param_res = param.typecheck(state, &typerefs, Some(&true_param_t));
let param_t =
state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1);
let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1);
state.ok(param_t.narrow_into(&true_param_t), param.1);
}
// Make sure function return type is the same as the claimed
// return type
let ret_t = f
.ret
.narrow_into(&function_call.return_type.resolve_ref(typerefs))?;
let ret_t = f.ret.narrow_into(&function_call.return_type.resolve_ref(typerefs))?;
// Update typing to be more accurate
function_call.return_type = ret_t.clone();
Ok(ret_t.resolve_ref(typerefs))
@ -604,8 +493,7 @@ impl Expression {
let then_ret_t = state.or_else(then_res, TypeKind::Vague(Vague::Unknown), lhs.1);
let else_ret_t = if let Some(else_expr) = rhs.as_mut() {
let res = else_expr.typecheck(state, &typerefs, hint_t);
let else_ret_t =
state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1);
let else_ret_t = state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1);
else_ret_t
} else {
@ -682,10 +570,7 @@ impl Expression {
for other in iter {
state.ok(first.narrow_into(other), self.1);
}
Ok(TypeKind::Array(
Box::new(first.clone()),
expressions.len() as u64,
))
Ok(TypeKind::Array(Box::new(first.clone()), expressions.len() as u64))
} else {
Ok(TypeKind::Array(Box::new(TypeKind::Void), 0))
}
@ -705,8 +590,7 @@ impl Expression {
// Typecheck expression
let expr_res = expression.typecheck(state, typerefs, Some(&expected_ty));
let expr_ty =
state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1);
let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1);
if let TypeKind::CustomType(key) = expr_ty {
let struct_type = state
@ -742,18 +626,14 @@ impl Expression {
let expected_ty = state.or_else(
struct_def
.get_field_ty(field_name)
.ok_or(ErrorKind::NoSuchField(format!(
"{}.{}",
struct_name, field_name
))),
.ok_or(ErrorKind::NoSuchField(format!("{}.{}", struct_name, field_name))),
&TypeKind::Vague(VagueType::Unknown),
field_expr.1,
);
// Typecheck the actual expression
let expr_res = field_expr.typecheck(state, typerefs, Some(expected_ty));
let expr_ty =
state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), field_expr.1);
let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), field_expr.1);
// Make sure both are the same type, report error if not
state.ok(expr_ty.narrow_into(&expr_ty), field_expr.1);
@ -829,7 +709,6 @@ impl Literal {
/// Try to coerce this literal, ie. convert it to a more specific type in
/// regards to the given hint if any.
fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> {
dbg!(&self, &hint);
if let Some(hint) = &hint {
use Literal as L;
use VagueLiteral as VagueL;

View File

@ -12,9 +12,8 @@ use std::{
use crate::{
mir::{
BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition,
FunctionDefinitionKind, IfExpression, Module, ReturnKind, StmtKind, TypeKind,
WhileStatement,
BinopDefinition, Block, CustomTypeKey, ExprKind, Expression, FunctionDefinition, FunctionDefinitionKind,
IfExpression, Module, ReturnKind, StmtKind, TypeKind, WhileStatement,
},
util::try_all,
};
@ -46,10 +45,7 @@ impl<'t> Pass for TypeInference<'t> {
for function in &mut module.functions {
if let Some(kind) = seen_functions.get(&function.name) {
state.note_errors(
&vec![ErrorKind::FunctionAlreadyDefined(
function.name.clone(),
*kind,
)],
&vec![ErrorKind::FunctionAlreadyDefined(function.name.clone(), *kind)],
function.signature(),
);
} else {
@ -70,8 +66,7 @@ impl<'t> Pass for TypeInference<'t> {
params: (binop.lhs.1.clone(), binop.rhs.1.clone()),
operator: binop.op,
};
if seen_binops.contains(&binop_key)
|| (binop.lhs == binop.rhs && binop.lhs.1.category().is_simple_maths())
if seen_binops.contains(&binop_key) || (binop.lhs == binop.rhs && binop.lhs.1.category().is_simple_maths())
{
state.note_errors(
&vec![ErrorKind::BinaryOpAlreadyDefined(
@ -100,18 +95,10 @@ impl<'t> Pass for TypeInference<'t> {
}
impl BinopDefinition {
fn infer_types(
&mut self,
type_refs: &TypeRefs,
state: &mut TypecheckPassState,
) -> Result<(), ErrorKind> {
fn infer_types(&mut self, type_refs: &TypeRefs, state: &mut TypecheckPassState) -> Result<(), ErrorKind> {
let scope_hints = ScopeTypeRefs::from(type_refs);
let lhs_ty = state.or_else(
self.lhs.1.assert_unvague(),
Vague(Unknown),
self.signature(),
);
let lhs_ty = state.or_else(self.lhs.1.assert_unvague(), Vague(Unknown), self.signature());
state.ok(
scope_hints
.new_var(self.lhs.0.clone(), false, &lhs_ty)
@ -119,11 +106,7 @@ impl BinopDefinition {
self.signature(),
);
let rhs_ty = state.or_else(
self.rhs.1.assert_unvague(),
Vague(Unknown),
self.signature(),
);
let rhs_ty = state.or_else(self.rhs.1.assert_unvague(), Vague(Unknown), self.signature());
state.ok(
scope_hints
@ -132,9 +115,9 @@ impl BinopDefinition {
self.signature(),
);
let ret_ty =
self.fn_kind
.infer_types(state, &scope_hints, Some(self.return_type.clone()))?;
let ret_ty = self
.fn_kind
.infer_types(state, &scope_hints, Some(self.return_type.clone()))?;
if let Some(mut ret_ty) = ret_ty {
ret_ty.narrow(&scope_hints.from_type(&self.return_type).unwrap());
}
@ -144,11 +127,7 @@ impl BinopDefinition {
}
impl FunctionDefinition {
fn infer_types(
&mut self,
type_refs: &TypeRefs,
state: &mut TypecheckPassState,
) -> Result<(), ErrorKind> {
fn infer_types(&mut self, type_refs: &TypeRefs, state: &mut TypecheckPassState) -> Result<(), ErrorKind> {
let scope_refs = ScopeTypeRefs::from(type_refs);
for param in &self.parameters {
let param_t = state.or_else(param.1.assert_unvague(), Vague(Unknown), self.signature());
@ -221,8 +200,7 @@ impl Block {
match &mut statement.0 {
StmtKind::Let(var, mutable, expr) => {
// Get the TypeRef for this variable declaration
let mut var_ref =
state.ok(inner_refs.new_var(var.1.clone(), *mutable, &var.0), var.2);
let mut var_ref = state.ok(inner_refs.new_var(var.1.clone(), *mutable, &var.0), var.2);
// If ok, update the MIR type to this TypeRef
if let Some(var_ref) = &var_ref {
@ -235,9 +213,7 @@ impl Block {
// Try to narrow the variable type declaration with the
// expression
if let (Some(var_ref), Some(expr_ty_ref)) =
(var_ref.as_mut(), expr_ty_ref.as_mut())
{
if let (Some(var_ref), Some(expr_ty_ref)) = (var_ref.as_mut(), expr_ty_ref.as_mut()) {
var_ref.narrow(&expr_ty_ref);
}
}
@ -260,9 +236,7 @@ impl Block {
let expr_res = expr.infer_types(&mut state, &inner_refs);
state.ok(expr_res, expr.1);
}
StmtKind::While(WhileStatement {
condition, block, ..
}) => {
StmtKind::While(WhileStatement { condition, block, .. }) => {
condition.infer_types(&mut state, &inner_refs)?;
block.infer_types(&mut state, &inner_refs)?;
}
@ -336,11 +310,7 @@ impl Expression {
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
Ok(type_refs.from_binop(*op, &lhs_ref, &rhs_ref))
} else {
Err(ErrorKind::InvalidBinop(
*op,
lhs_ref.resolve_deep().unwrap(),
rhs_ref.resolve_deep().unwrap(),
))
panic!();
}
}
ExprKind::FunctionCall(function_call) => {
@ -357,9 +327,7 @@ impl Expression {
// many were provided)
let true_params_iter = fn_call.params.iter().chain(iter::repeat(&Vague(Unknown)));
for (param_expr, param_t) in
function_call.parameters.iter_mut().zip(true_params_iter)
{
for (param_expr, param_t) in function_call.parameters.iter_mut().zip(true_params_iter) {
let expr_res = param_expr.infer_types(state, type_refs);
if let Some(mut param_ref) = state.ok(expr_res, param_expr.1) {
param_ref.narrow(&mut type_refs.from_type(param_t).unwrap());
@ -390,12 +358,10 @@ impl Expression {
// Narrow LHS to the same type as RHS and return it's return type
if let (Some(mut lhs_hints), Some(mut rhs_hints)) = (lhs_hints, rhs_hints) {
lhs_hints
.narrow(&mut rhs_hints)
.ok_or(ErrorKind::TypesIncompatible(
lhs_hints.resolve_deep().unwrap(),
rhs_hints.resolve_deep().unwrap(),
))
lhs_hints.narrow(&mut rhs_hints).ok_or(ErrorKind::TypesIncompatible(
lhs_hints.resolve_deep().unwrap(),
rhs_hints.resolve_deep().unwrap(),
))
} else {
// Failed to retrieve types from either
Ok(type_refs.from_type(&Vague(Unknown)).unwrap())
@ -451,15 +417,10 @@ impl Expression {
}
Ok(type_refs
.from_type(&Array(
Box::new(first.as_type()),
expressions.len() as u64,
))
.from_type(&Array(Box::new(first.as_type()), expressions.len() as u64))
.unwrap())
} else {
Ok(type_refs
.from_type(&Array(Box::new(TypeKind::Void), 0))
.unwrap())
Ok(type_refs.from_type(&Array(Box::new(TypeKind::Void), 0)).unwrap())
}
}
Err(errors) => {
@ -503,10 +464,7 @@ impl Expression {
let expected_struct_ty = state
.scope
.get_struct_type(&type_key)
.ok_or(ErrorKind::NoSuchType(
struct_name.clone(),
state.module_id.unwrap(),
))?
.ok_or(ErrorKind::NoSuchType(struct_name.clone(), state.module_id.unwrap()))?
.clone();
for field in fields {
if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) {
@ -516,17 +474,12 @@ impl Expression {
}
} else {
state.ok::<_, Infallible>(
Err(ErrorKind::NoSuchField(format!(
"{}.{}",
struct_name, field.0
))),
Err(ErrorKind::NoSuchField(format!("{}.{}", struct_name, field.0))),
field.1 .1,
);
}
}
Ok(type_refs
.from_type(&TypeKind::CustomType(type_key.clone()))
.unwrap())
Ok(type_refs.from_type(&TypeKind::CustomType(type_key.clone())).unwrap())
}
ExprKind::Borrow(var, mutable) => {
// Find variable type

View File

@ -15,10 +15,7 @@ use super::{
};
#[derive(Clone)]
pub struct TypeRef<'scope>(
pub(super) TypeIdRef,
pub(super) &'scope ScopeTypeRefs<'scope>,
);
pub struct TypeRef<'scope>(pub(super) TypeIdRef, pub(super) &'scope ScopeTypeRefs<'scope>);
impl<'scope> TypeRef<'scope> {
/// Resolve current type in a weak manner, not resolving any Arrays or
@ -99,7 +96,7 @@ pub struct TypeRefs {
pub(super) hints: RefCell<Vec<TypeRefKind>>,
/// Indirect ID-references, referring to hints-vec
pub(super) type_refs: RefCell<Vec<TypeIdRef>>,
binop_types: BinopMap,
pub(super) binop_types: BinopMap,
}
impl std::fmt::Display for TypeRefs {
@ -132,9 +129,7 @@ impl TypeRefs {
let idx = self.hints.borrow().len();
let typecell = Rc::new(RefCell::new(idx));
self.type_refs.borrow_mut().push(typecell.clone());
self.hints
.borrow_mut()
.push(TypeRefKind::Direct(ty.clone()));
self.hints.borrow_mut().push(TypeRefKind::Direct(ty.clone()));
typecell
}
@ -183,11 +178,7 @@ impl TypeRefs {
pub fn retrieve_wide_type(&self, idx: usize) -> Option<TypeKind> {
let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() };
self.hints
.borrow()
.get(inner_idx)
.cloned()
.map(|t| t.widen(self))
self.hints.borrow().get(inner_idx).cloned().map(|t| t.widen(self))
}
}
@ -218,9 +209,7 @@ impl<'outer> ScopeTypeRefs<'outer> {
return Err(ErrorKind::VariableAlreadyDefined(name));
}
let type_ref = self.from_type(&initial_ty).unwrap();
self.variables
.borrow_mut()
.insert(name, (mutable, type_ref.0.clone()));
self.variables.borrow_mut().insert(name, (mutable, type_ref.0.clone()));
Ok(type_ref)
}
@ -233,8 +222,7 @@ impl<'outer> ScopeTypeRefs<'outer> {
TypeKind::Vague(_) => self.types.new(ty),
TypeKind::Array(elem_ty, length) => {
let elem_ty = self.from_type(elem_ty)?;
self.types
.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length))
self.types.new(&TypeKind::Array(Box::new(elem_ty.as_type()), *length))
}
TypeKind::Borrow(ty, mutable) => {
let inner_ty = self.from_type(ty)?;
@ -252,12 +240,7 @@ impl<'outer> ScopeTypeRefs<'outer> {
Some(TypeRef(idx, self))
}
pub fn from_binop(
&'outer self,
op: BinaryOperator,
lhs: &TypeRef,
rhs: &TypeRef,
) -> TypeRef<'outer> {
pub fn from_binop(&'outer self, op: BinaryOperator, lhs: &TypeRef, rhs: &TypeRef) -> TypeRef<'outer> {
TypeRef(self.types.binop(op, lhs, rhs), self)
}
@ -276,10 +259,9 @@ impl<'outer> ScopeTypeRefs<'outer> {
.iter()
.filter(|b| b.1.operator == *op && b.1.return_ty == *ty);
for binop in binops {
if let (Ok(lhs_narrow), Ok(rhs_narrow)) = (
lhs.narrow_into(&binop.1.hands.0),
rhs.narrow_into(&binop.1.hands.1),
) {
if let (Ok(lhs_narrow), Ok(rhs_narrow)) =
(lhs.narrow_into(&binop.1.hands.0), rhs.narrow_into(&binop.1.hands.1))
{
*lhs = lhs_narrow;
*rhs = rhs_narrow
}