forked from M-Labs/nac3
codegen for simple function call, and various fixes
This commit is contained in:
parent
f205a8282a
commit
3279f7a776
|
@ -232,9 +232,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_expr(&mut self, expr: &Expr<Option<Type>>) -> BasicValueEnum<'ctx> {
|
pub fn gen_expr(&mut self, expr: &Expr<Option<Type>>) -> Option<BasicValueEnum<'ctx>> {
|
||||||
let zero = self.ctx.i32_type().const_int(0, false);
|
let zero = self.ctx.i32_type().const_int(0, false);
|
||||||
match &expr.node {
|
Some(match &expr.node {
|
||||||
ExprKind::Constant { value, .. } => {
|
ExprKind::Constant { value, .. } => {
|
||||||
let ty = expr.custom.unwrap();
|
let ty = expr.custom.unwrap();
|
||||||
self.gen_const(value, ty)
|
self.gen_const(value, ty)
|
||||||
|
@ -254,7 +254,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
ExprKind::List { elts, .. } => {
|
ExprKind::List { elts, .. } => {
|
||||||
// this shall be optimized later for constant primitive lists...
|
// this shall be optimized later for constant primitive lists...
|
||||||
// we should use memcpy for that instead of generating thousands of stores
|
// we should use memcpy for that instead of generating thousands of stores
|
||||||
let elements = elts.iter().map(|x| self.gen_expr(x)).collect_vec();
|
let elements = elts.iter().map(|x| self.gen_expr(x).unwrap()).collect_vec();
|
||||||
let ty = if elements.is_empty() {
|
let ty = if elements.is_empty() {
|
||||||
self.ctx.i32_type().into()
|
self.ctx.i32_type().into()
|
||||||
} else {
|
} else {
|
||||||
|
@ -293,7 +293,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
arr_str_ptr.into()
|
arr_str_ptr.into()
|
||||||
}
|
}
|
||||||
ExprKind::Tuple { elts, .. } => {
|
ExprKind::Tuple { elts, .. } => {
|
||||||
let element_val = elts.iter().map(|x| self.gen_expr(x)).collect_vec();
|
let element_val = elts.iter().map(|x| self.gen_expr(x).unwrap()).collect_vec();
|
||||||
let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec();
|
let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec();
|
||||||
let tuple_ty = self.ctx.struct_type(&element_ty, false);
|
let tuple_ty = self.ctx.struct_type(&element_ty, false);
|
||||||
let tuple_ptr = self.builder.build_alloca(tuple_ty, "tuple");
|
let tuple_ptr = self.builder.build_alloca(tuple_ty, "tuple");
|
||||||
|
@ -311,7 +311,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
ExprKind::Attribute { value, attr, .. } => {
|
ExprKind::Attribute { value, attr, .. } => {
|
||||||
// note that we would handle class methods directly in calls
|
// note that we would handle class methods directly in calls
|
||||||
let index = self.get_attr_index(value.custom.unwrap(), attr);
|
let index = self.get_attr_index(value.custom.unwrap(), attr);
|
||||||
let val = self.gen_expr(value);
|
let val = self.gen_expr(value).unwrap();
|
||||||
let ptr = if let BasicValueEnum::PointerValue(v) = val {
|
let ptr = if let BasicValueEnum::PointerValue(v) = val {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
|
@ -327,7 +327,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
}
|
}
|
||||||
ExprKind::BoolOp { op, values } => {
|
ExprKind::BoolOp { op, values } => {
|
||||||
// requires conditional branches for short-circuiting...
|
// requires conditional branches for short-circuiting...
|
||||||
let left = if let BasicValueEnum::IntValue(left) = self.gen_expr(&values[0]) {
|
let left =
|
||||||
|
if let BasicValueEnum::IntValue(left) = self.gen_expr(&values[0]).unwrap() {
|
||||||
left
|
left
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -343,7 +344,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
let a = self.ctx.bool_type().const_int(1, false);
|
let a = self.ctx.bool_type().const_int(1, false);
|
||||||
self.builder.build_unconditional_branch(cont_bb);
|
self.builder.build_unconditional_branch(cont_bb);
|
||||||
self.builder.position_at_end(b_bb);
|
self.builder.position_at_end(b_bb);
|
||||||
let b = if let BasicValueEnum::IntValue(b) = self.gen_expr(&values[1]) {
|
let b = if let BasicValueEnum::IntValue(b) =
|
||||||
|
self.gen_expr(&values[1]).unwrap()
|
||||||
|
{
|
||||||
b
|
b
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -353,7 +356,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
}
|
}
|
||||||
Boolop::And => {
|
Boolop::And => {
|
||||||
self.builder.position_at_end(a_bb);
|
self.builder.position_at_end(a_bb);
|
||||||
let a = if let BasicValueEnum::IntValue(a) = self.gen_expr(&values[1]) {
|
let a = if let BasicValueEnum::IntValue(a) =
|
||||||
|
self.gen_expr(&values[1]).unwrap()
|
||||||
|
{
|
||||||
a
|
a
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -373,8 +378,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
ExprKind::BinOp { op, left, right } => {
|
ExprKind::BinOp { op, left, right } => {
|
||||||
let ty1 = self.unifier.get_representative(left.custom.unwrap());
|
let ty1 = self.unifier.get_representative(left.custom.unwrap());
|
||||||
let ty2 = self.unifier.get_representative(right.custom.unwrap());
|
let ty2 = self.unifier.get_representative(right.custom.unwrap());
|
||||||
let left = self.gen_expr(left);
|
let left = self.gen_expr(left).unwrap();
|
||||||
let right = self.gen_expr(right);
|
let right = self.gen_expr(right).unwrap();
|
||||||
|
|
||||||
// we can directly compare the types, because we've got their representatives
|
// we can directly compare the types, because we've got their representatives
|
||||||
// which would be unchanged until further unification, which we would never do
|
// which would be unchanged until further unification, which we would never do
|
||||||
|
@ -389,7 +394,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
}
|
}
|
||||||
ExprKind::UnaryOp { op, operand } => {
|
ExprKind::UnaryOp { op, operand } => {
|
||||||
let ty = self.unifier.get_representative(operand.custom.unwrap());
|
let ty = self.unifier.get_representative(operand.custom.unwrap());
|
||||||
let val = self.gen_expr(operand);
|
let val = self.gen_expr(operand).unwrap();
|
||||||
if ty == self.primitives.bool {
|
if ty == self.primitives.bool {
|
||||||
let val =
|
let val =
|
||||||
if let BasicValueEnum::IntValue(val) = val { val } else { unreachable!() };
|
if let BasicValueEnum::IntValue(val) = val { val } else { unreachable!() };
|
||||||
|
@ -454,7 +459,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
let (lhs, rhs) = if let (
|
let (lhs, rhs) = if let (
|
||||||
BasicValueEnum::IntValue(lhs),
|
BasicValueEnum::IntValue(lhs),
|
||||||
BasicValueEnum::IntValue(rhs),
|
BasicValueEnum::IntValue(rhs),
|
||||||
) = (self.gen_expr(lhs), self.gen_expr(rhs))
|
) =
|
||||||
|
(self.gen_expr(lhs).unwrap(), self.gen_expr(rhs).unwrap())
|
||||||
{
|
{
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
} else {
|
} else {
|
||||||
|
@ -474,7 +480,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
let (lhs, rhs) = if let (
|
let (lhs, rhs) = if let (
|
||||||
BasicValueEnum::FloatValue(lhs),
|
BasicValueEnum::FloatValue(lhs),
|
||||||
BasicValueEnum::FloatValue(rhs),
|
BasicValueEnum::FloatValue(rhs),
|
||||||
) = (self.gen_expr(lhs), self.gen_expr(rhs))
|
) =
|
||||||
|
(self.gen_expr(lhs).unwrap(), self.gen_expr(rhs).unwrap())
|
||||||
{
|
{
|
||||||
(lhs, rhs)
|
(lhs, rhs)
|
||||||
} else {
|
} else {
|
||||||
|
@ -499,7 +506,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
.into() // as there should be at least 1 element, it should never be none
|
.into() // as there should be at least 1 element, it should never be none
|
||||||
}
|
}
|
||||||
ExprKind::IfExp { test, body, orelse } => {
|
ExprKind::IfExp { test, body, orelse } => {
|
||||||
let test = if let BasicValueEnum::IntValue(test) = self.gen_expr(test) {
|
let test = if let BasicValueEnum::IntValue(test) = self.gen_expr(test).unwrap() {
|
||||||
test
|
test
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
|
@ -511,17 +518,40 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
let cont_bb = self.ctx.append_basic_block(current, "cont");
|
let cont_bb = self.ctx.append_basic_block(current, "cont");
|
||||||
self.builder.build_conditional_branch(test, then_bb, else_bb);
|
self.builder.build_conditional_branch(test, then_bb, else_bb);
|
||||||
self.builder.position_at_end(then_bb);
|
self.builder.position_at_end(then_bb);
|
||||||
let a = self.gen_expr(body);
|
let a = self.gen_expr(body).unwrap();
|
||||||
self.builder.build_unconditional_branch(cont_bb);
|
self.builder.build_unconditional_branch(cont_bb);
|
||||||
self.builder.position_at_end(else_bb);
|
self.builder.position_at_end(else_bb);
|
||||||
let b = self.gen_expr(orelse);
|
let b = self.gen_expr(orelse).unwrap();
|
||||||
self.builder.build_unconditional_branch(cont_bb);
|
self.builder.build_unconditional_branch(cont_bb);
|
||||||
self.builder.position_at_end(cont_bb);
|
self.builder.position_at_end(cont_bb);
|
||||||
let phi = self.builder.build_phi(a.get_type(), "ifexpr");
|
let phi = self.builder.build_phi(a.get_type(), "ifexpr");
|
||||||
phi.add_incoming(&[(&a, then_bb), (&b, else_bb)]);
|
phi.add_incoming(&[(&a, then_bb), (&b, else_bb)]);
|
||||||
phi.as_basic_value()
|
phi.as_basic_value()
|
||||||
}
|
}
|
||||||
|
ExprKind::Call { func, args, keywords } => {
|
||||||
|
if let ExprKind::Name { id, .. } = &func.as_ref().node {
|
||||||
|
// TODO: handle primitive casts
|
||||||
|
let fun = self.resolver.get_identifier_def(&id).expect("Unknown identifier");
|
||||||
|
let ret = expr.custom.unwrap();
|
||||||
|
let mut params =
|
||||||
|
args.iter().map(|arg| (None, self.gen_expr(arg).unwrap())).collect_vec();
|
||||||
|
let kw_iter = keywords.iter().map(|kw| {
|
||||||
|
(
|
||||||
|
Some(kw.node.arg.as_ref().unwrap().clone()),
|
||||||
|
self.gen_expr(&kw.node.value).unwrap(),
|
||||||
|
)
|
||||||
|
});
|
||||||
|
params.extend(kw_iter);
|
||||||
|
let signature = self
|
||||||
|
.unifier
|
||||||
|
.get_call_signature(*self.calls.get(&expr.location.into()).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
return self.gen_call(None, (&signature, fun), params, ret);
|
||||||
|
} else {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@ use crate::{
|
||||||
symbol_resolver::SymbolResolver,
|
symbol_resolver::SymbolResolver,
|
||||||
top_level::{TopLevelContext, TopLevelDef},
|
top_level::{TopLevelContext, TopLevelDef},
|
||||||
typecheck::{
|
typecheck::{
|
||||||
type_inferencer::PrimitiveStore,
|
type_inferencer::{CodeLocation, PrimitiveStore},
|
||||||
typedef::{FunSignature, Type, TypeEnum, Unifier},
|
typedef::{CallId, FunSignature, Type, TypeEnum, Unifier},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crossbeam::channel::{unbounded, Receiver, Sender};
|
use crossbeam::channel::{unbounded, Receiver, Sender};
|
||||||
|
@ -42,6 +42,7 @@ pub struct CodeGenContext<'ctx, 'a> {
|
||||||
pub var_assignment: HashMap<String, PointerValue<'ctx>>,
|
pub var_assignment: HashMap<String, PointerValue<'ctx>>,
|
||||||
pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
|
pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
|
||||||
pub primitives: PrimitiveStore,
|
pub primitives: PrimitiveStore,
|
||||||
|
pub calls: HashMap<CodeLocation, CallId>,
|
||||||
// stores the alloca for variables
|
// stores the alloca for variables
|
||||||
pub init_bb: BasicBlock<'ctx>,
|
pub init_bb: BasicBlock<'ctx>,
|
||||||
// where continue and break should go to respectively
|
// where continue and break should go to respectively
|
||||||
|
@ -186,6 +187,7 @@ pub struct CodeGenTask {
|
||||||
pub symbol_name: String,
|
pub symbol_name: String,
|
||||||
pub signature: FunSignature,
|
pub signature: FunSignature,
|
||||||
pub body: Vec<Stmt<Option<Type>>>,
|
pub body: Vec<Stmt<Option<Type>>>,
|
||||||
|
pub calls: HashMap<CodeLocation, CallId>,
|
||||||
pub unifier_index: usize,
|
pub unifier_index: usize,
|
||||||
pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
||||||
}
|
}
|
||||||
|
@ -323,6 +325,7 @@ pub fn gen_func<'ctx>(
|
||||||
ctx: &context,
|
ctx: &context,
|
||||||
resolver: task.resolver,
|
resolver: task.resolver,
|
||||||
top_level: top_level_ctx.as_ref(),
|
top_level: top_level_ctx.as_ref(),
|
||||||
|
calls: task.calls,
|
||||||
loop_bb: None,
|
loop_bb: None,
|
||||||
var_assignment,
|
var_assignment,
|
||||||
type_cache,
|
type_cache,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
}
|
}
|
||||||
ExprKind::Attribute { value, attr, .. } => {
|
ExprKind::Attribute { value, attr, .. } => {
|
||||||
let index = self.get_attr_index(value.custom.unwrap(), attr);
|
let index = self.get_attr_index(value.custom.unwrap(), attr);
|
||||||
let val = self.gen_expr(value);
|
let val = self.gen_expr(value).unwrap();
|
||||||
let ptr = if let BasicValueEnum::PointerValue(v) = val {
|
let ptr = if let BasicValueEnum::PointerValue(v) = val {
|
||||||
v
|
v
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,33 +68,82 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn gen_stmt(&mut self, stmt: &Stmt<Option<Type>>) {
|
// return true if it contains terminator
|
||||||
|
pub fn gen_stmt(&mut self, stmt: &Stmt<Option<Type>>) -> bool {
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::Expr { value } => {
|
StmtKind::Expr { value } => {
|
||||||
self.gen_expr(&value);
|
self.gen_expr(&value);
|
||||||
}
|
}
|
||||||
StmtKind::Return { value } => {
|
StmtKind::Return { value } => {
|
||||||
let value = value.as_ref().map(|v| self.gen_expr(&v));
|
let value = value.as_ref().map(|v| self.gen_expr(&v).unwrap());
|
||||||
let value = value.as_ref().map(|v| v as &dyn BasicValue);
|
let value = value.as_ref().map(|v| v as &dyn BasicValue);
|
||||||
self.builder.build_return(value);
|
self.builder.build_return(value);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
StmtKind::AnnAssign { target, value, .. } => {
|
StmtKind::AnnAssign { target, value, .. } => {
|
||||||
if let Some(value) = value {
|
if let Some(value) = value {
|
||||||
let value = self.gen_expr(&value);
|
let value = self.gen_expr(&value).unwrap();
|
||||||
self.gen_assignment(target, value);
|
self.gen_assignment(target, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Assign { targets, value, .. } => {
|
StmtKind::Assign { targets, value, .. } => {
|
||||||
let value = self.gen_expr(&value);
|
let value = self.gen_expr(&value).unwrap();
|
||||||
for target in targets.iter() {
|
for target in targets.iter() {
|
||||||
self.gen_assignment(target, value);
|
self.gen_assignment(target, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::Continue => {
|
StmtKind::Continue => {
|
||||||
self.builder.build_unconditional_branch(self.loop_bb.unwrap().0);
|
self.builder.build_unconditional_branch(self.loop_bb.unwrap().0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
StmtKind::Break => {
|
StmtKind::Break => {
|
||||||
self.builder.build_unconditional_branch(self.loop_bb.unwrap().1);
|
self.builder.build_unconditional_branch(self.loop_bb.unwrap().1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
StmtKind::If { test, body, orelse } => {
|
||||||
|
let current = self.builder.get_insert_block().unwrap().get_parent().unwrap();
|
||||||
|
let test_bb = self.ctx.append_basic_block(current, "test");
|
||||||
|
let body_bb = self.ctx.append_basic_block(current, "body");
|
||||||
|
let cont_bb = self.ctx.append_basic_block(current, "cont");
|
||||||
|
// if there is no orelse, we just go to cont_bb
|
||||||
|
let orelse_bb = if orelse.is_empty() {
|
||||||
|
cont_bb
|
||||||
|
} else {
|
||||||
|
self.ctx.append_basic_block(current, "orelse")
|
||||||
|
};
|
||||||
|
self.builder.build_unconditional_branch(test_bb);
|
||||||
|
self.builder.position_at_end(test_bb);
|
||||||
|
let test = self.gen_expr(test).unwrap();
|
||||||
|
if let BasicValueEnum::IntValue(test) = test {
|
||||||
|
self.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
self.builder.position_at_end(body_bb);
|
||||||
|
let mut exited = false;
|
||||||
|
for stmt in body.iter() {
|
||||||
|
exited = self.gen_stmt(stmt);
|
||||||
|
if exited {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !exited {
|
||||||
|
self.builder.build_unconditional_branch(cont_bb);
|
||||||
|
}
|
||||||
|
if !orelse.is_empty() {
|
||||||
|
exited = false;
|
||||||
|
self.builder.position_at_end(orelse_bb);
|
||||||
|
for stmt in orelse.iter() {
|
||||||
|
exited = self.gen_stmt(stmt);
|
||||||
|
if exited {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !exited {
|
||||||
|
self.builder.build_unconditional_branch(cont_bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.builder.position_at_end(cont_bb);
|
||||||
}
|
}
|
||||||
StmtKind::While { test, body, orelse } => {
|
StmtKind::While { test, body, orelse } => {
|
||||||
let current = self.builder.get_insert_block().unwrap().get_parent().unwrap();
|
let current = self.builder.get_insert_block().unwrap().get_parent().unwrap();
|
||||||
|
@ -111,7 +160,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
let loop_bb = self.loop_bb.replace((test_bb, cont_bb));
|
let loop_bb = self.loop_bb.replace((test_bb, cont_bb));
|
||||||
self.builder.build_unconditional_branch(test_bb);
|
self.builder.build_unconditional_branch(test_bb);
|
||||||
self.builder.position_at_end(test_bb);
|
self.builder.position_at_end(test_bb);
|
||||||
let test = self.gen_expr(test);
|
let test = self.gen_expr(test).unwrap();
|
||||||
if let BasicValueEnum::IntValue(test) = test {
|
if let BasicValueEnum::IntValue(test) = test {
|
||||||
self.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
self.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
||||||
} else {
|
} else {
|
||||||
|
@ -132,7 +181,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||||
self.builder.position_at_end(cont_bb);
|
self.builder.position_at_end(cont_bb);
|
||||||
self.loop_bb = loop_bb;
|
self.loop_bb = loop_bb;
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!("{:?}", stmt),
|
||||||
}
|
};
|
||||||
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,7 @@ fn test_primitives() {
|
||||||
body: statements,
|
body: statements,
|
||||||
unifier_index: 0,
|
unifier_index: 0,
|
||||||
resolver: env.function_data.resolver.clone(),
|
resolver: env.function_data.resolver.clone(),
|
||||||
|
calls: Default::default(),
|
||||||
signature,
|
signature,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#![warn(clippy::all)]
|
#![warn(clippy::all)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod codegen;
|
pub mod codegen;
|
||||||
mod location;
|
pub mod location;
|
||||||
mod symbol_resolver;
|
pub mod symbol_resolver;
|
||||||
mod top_level;
|
pub mod top_level;
|
||||||
mod typecheck;
|
pub mod typecheck;
|
||||||
|
|
|
@ -97,6 +97,7 @@ impl TypeEnum {
|
||||||
|
|
||||||
pub type SharedUnifier = Arc<Mutex<(UnificationTable<TypeEnum>, u32, Vec<Call>)>>;
|
pub type SharedUnifier = Arc<Mutex<(UnificationTable<TypeEnum>, u32, Vec<Call>)>>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Unifier {
|
pub struct Unifier {
|
||||||
unification_table: UnificationTable<Rc<TypeEnum>>,
|
unification_table: UnificationTable<Rc<TypeEnum>>,
|
||||||
calls: Vec<Rc<Call>>,
|
calls: Vec<Rc<Call>>,
|
||||||
|
@ -153,6 +154,15 @@ impl Unifier {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_call_signature(&mut self, id: CallId) -> Option<FunSignature> {
|
||||||
|
let fun = self.calls.get(id.0).unwrap().fun.borrow().unwrap();
|
||||||
|
if let TypeEnum::TFunc(sign) = &*self.get_ty(fun) {
|
||||||
|
Some(sign.borrow().clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_representative(&mut self, ty: Type) -> Type {
|
pub fn get_representative(&mut self, ty: Type) -> Type {
|
||||||
self.unification_table.get_representative(ty)
|
self.unification_table.get_representative(ty)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::rc::Rc;
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
|
||||||
pub struct UnificationKey(usize);
|
pub struct UnificationKey(usize);
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct UnificationTable<V> {
|
pub struct UnificationTable<V> {
|
||||||
parents: Vec<usize>,
|
parents: Vec<usize>,
|
||||||
ranks: Vec<u32>,
|
ranks: Vec<u32>,
|
||||||
|
|
Loading…
Reference in New Issue