Add intrinsic associated functions
This commit is contained in:
parent
0613fc5c53
commit
537167fe4f
@ -22,6 +22,7 @@ fn main() -> u32 {
|
||||
let otus = Otus { field: 17 };
|
||||
print(from_str("otus: ") + Otus::test(&otus) as u64);
|
||||
print(from_str("i32: ") + i32::test(54) as u64);
|
||||
print(from_str("sizeof i32: ") + i32::sizeof());
|
||||
|
||||
return Otus::test(&otus);
|
||||
}
|
||||
|
@ -36,6 +36,20 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> {
|
||||
intrinsics
|
||||
}
|
||||
|
||||
pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> {
|
||||
match name {
|
||||
"sizeof" => Some(FunctionDefinition {
|
||||
name: "sizeof".to_owned(),
|
||||
is_pub: true,
|
||||
is_imported: false,
|
||||
return_type: TypeKind::U64,
|
||||
parameters: Vec::new(),
|
||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))),
|
||||
}),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
|
||||
where
|
||||
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
|
||||
@ -167,28 +181,33 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
|
||||
}
|
||||
|
||||
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>;
|
||||
}
|
||||
|
||||
macro_rules! intrinsic_debug {
|
||||
($kind:ty, $name:literal) => {
|
||||
impl<T> std::fmt::Debug for $kind
|
||||
where
|
||||
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple($name).finish()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IntrinsicSimpleInstr<T>(T)
|
||||
where
|
||||
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue;
|
||||
|
||||
impl<T> std::fmt::Debug for IntrinsicSimpleInstr<T>
|
||||
where
|
||||
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("IntrinsicSimpleInstr").finish()
|
||||
}
|
||||
}
|
||||
intrinsic_debug!(IntrinsicSimpleInstr<T>, "IntrinsicSimpleInstr");
|
||||
|
||||
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());
|
||||
@ -200,21 +219,13 @@ where
|
||||
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()
|
||||
}
|
||||
}
|
||||
intrinsic_debug!(IntrinsicBooleanInstr<T>, "IntrinsicBooleanInstr");
|
||||
|
||||
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> {
|
||||
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());
|
||||
@ -222,6 +233,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IntrinsicSizeOf(TypeKind);
|
||||
impl std::fmt::Debug for IntrinsicSizeOf {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("IntrinsicSizeOf").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntrinsicFunction for IntrinsicSizeOf {
|
||||
fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> {
|
||||
let instr = scope
|
||||
.block
|
||||
.build(Instr::Constant(reid_lib::ConstValue::U64(self.0.size_of())))
|
||||
.unwrap();
|
||||
Ok(StackValue(StackValueKind::Literal(instr), self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
// impl IntrinsicFunction for IntrinsicIAdd {
|
||||
// fn codegen<'ctx, 'a>(
|
||||
// &self,
|
||||
|
@ -211,7 +211,7 @@ impl mir::Module {
|
||||
};
|
||||
|
||||
if let Some(func) = func {
|
||||
functions.insert(function.name.clone(), func);
|
||||
functions.insert(function.name.clone(), ScopeFunctionKind::UserGenerated(func));
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +251,10 @@ impl mir::Module {
|
||||
};
|
||||
|
||||
if let Some(func) = func {
|
||||
associated_functions.insert(AssociatedFunctionKey(ty.clone(), function.name.clone()), func);
|
||||
associated_functions.insert(
|
||||
AssociatedFunctionKey(ty.clone(), function.name.clone()),
|
||||
ScopeFunctionKind::UserGenerated(func),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,22 +335,20 @@ impl mir::Module {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
StackBinopFunctionKind::UserGenerated(ir_function)
|
||||
}
|
||||
FunctionDefinitionKind::Extern(imported) => {
|
||||
StackBinopFunctionKind::UserGenerated(module.function(
|
||||
&binop_fn_name,
|
||||
binop.return_type.get_type(&type_values),
|
||||
vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)],
|
||||
FunctionFlags {
|
||||
is_extern: true,
|
||||
is_imported: *imported,
|
||||
..FunctionFlags::default()
|
||||
},
|
||||
))
|
||||
ScopeFunctionKind::UserGenerated(ir_function)
|
||||
}
|
||||
FunctionDefinitionKind::Extern(imported) => ScopeFunctionKind::UserGenerated(module.function(
|
||||
&binop_fn_name,
|
||||
binop.return_type.get_type(&type_values),
|
||||
vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)],
|
||||
FunctionFlags {
|
||||
is_extern: true,
|
||||
is_imported: *imported,
|
||||
..FunctionFlags::default()
|
||||
},
|
||||
)),
|
||||
FunctionDefinitionKind::Intrinsic(intrinsic_function) => {
|
||||
StackBinopFunctionKind::Intrinsic(intrinsic_function)
|
||||
ScopeFunctionKind::Intrinsic(intrinsic_function)
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -355,111 +356,118 @@ impl mir::Module {
|
||||
}
|
||||
|
||||
for mir_function in &self.functions {
|
||||
let function = functions.get(&mir_function.name).unwrap();
|
||||
let mut entry = function.block("entry");
|
||||
if let ScopeFunctionKind::UserGenerated(function) = functions.get(&mir_function.name).unwrap() {
|
||||
let mut entry = function.block("entry");
|
||||
|
||||
let allocator = Allocator::from(
|
||||
&mir_function.kind,
|
||||
&mir_function.parameters,
|
||||
&mut AllocatorScope {
|
||||
block: &mut entry,
|
||||
type_values: &type_values,
|
||||
},
|
||||
);
|
||||
|
||||
let mut scope = Scope {
|
||||
context,
|
||||
modules: &modules,
|
||||
tokens,
|
||||
module: &module,
|
||||
module_id: self.module_id,
|
||||
function,
|
||||
block: entry,
|
||||
assoc_functions: &associated_functions,
|
||||
functions: &functions,
|
||||
types: &types,
|
||||
type_values: &type_values,
|
||||
stack_values: HashMap::new(),
|
||||
debug: Some(Debug {
|
||||
info: &debug,
|
||||
scope: compile_unit,
|
||||
types: &debug_types,
|
||||
}),
|
||||
binops: &binops,
|
||||
allocator: Rc::new(RefCell::new(allocator)),
|
||||
};
|
||||
|
||||
mir_function
|
||||
.kind
|
||||
.codegen(
|
||||
mir_function.name.clone(),
|
||||
mir_function.is_pub,
|
||||
&mut scope,
|
||||
let allocator = Allocator::from(
|
||||
&mir_function.kind,
|
||||
&mir_function.parameters,
|
||||
&mir_function.return_type,
|
||||
&function,
|
||||
match &mir_function.kind {
|
||||
FunctionDefinitionKind::Local(..) => mir_function.signature().into_debug(tokens, compile_unit),
|
||||
FunctionDefinitionKind::Extern(_) => None,
|
||||
FunctionDefinitionKind::Intrinsic(_) => None,
|
||||
&mut AllocatorScope {
|
||||
block: &mut entry,
|
||||
type_values: &type_values,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
);
|
||||
|
||||
let mut scope = Scope {
|
||||
context,
|
||||
modules: &modules,
|
||||
tokens,
|
||||
module: &module,
|
||||
module_id: self.module_id,
|
||||
function,
|
||||
block: entry,
|
||||
assoc_functions: &associated_functions,
|
||||
functions: &functions,
|
||||
types: &types,
|
||||
type_values: &type_values,
|
||||
stack_values: HashMap::new(),
|
||||
debug: Some(Debug {
|
||||
info: &debug,
|
||||
scope: compile_unit,
|
||||
types: &debug_types,
|
||||
}),
|
||||
binops: &binops,
|
||||
allocator: Rc::new(RefCell::new(allocator)),
|
||||
};
|
||||
|
||||
mir_function
|
||||
.kind
|
||||
.codegen(
|
||||
mir_function.name.clone(),
|
||||
mir_function.is_pub,
|
||||
&mut scope,
|
||||
&mir_function.parameters,
|
||||
&mir_function.return_type,
|
||||
&function,
|
||||
match &mir_function.kind {
|
||||
FunctionDefinitionKind::Local(..) => {
|
||||
mir_function.signature().into_debug(tokens, compile_unit)
|
||||
}
|
||||
FunctionDefinitionKind::Extern(_) => None,
|
||||
FunctionDefinitionKind::Intrinsic(_) => None,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
for (ty, mir_function) in &self.associated_functions {
|
||||
let function = associated_functions
|
||||
if let ScopeFunctionKind::UserGenerated(function) = associated_functions
|
||||
.get(&AssociatedFunctionKey(ty.clone(), mir_function.name.clone()))
|
||||
.unwrap();
|
||||
let mut entry = function.block("entry");
|
||||
.unwrap()
|
||||
{
|
||||
let mut entry = function.block("entry");
|
||||
|
||||
let allocator = Allocator::from(
|
||||
&mir_function.kind,
|
||||
&mir_function.parameters,
|
||||
&mut AllocatorScope {
|
||||
block: &mut entry,
|
||||
type_values: &type_values,
|
||||
},
|
||||
);
|
||||
|
||||
let mut scope = Scope {
|
||||
context,
|
||||
modules: &modules,
|
||||
tokens,
|
||||
module: &module,
|
||||
module_id: self.module_id,
|
||||
function,
|
||||
block: entry,
|
||||
assoc_functions: &associated_functions,
|
||||
functions: &functions,
|
||||
types: &types,
|
||||
type_values: &type_values,
|
||||
stack_values: HashMap::new(),
|
||||
debug: Some(Debug {
|
||||
info: &debug,
|
||||
scope: compile_unit,
|
||||
types: &debug_types,
|
||||
}),
|
||||
binops: &binops,
|
||||
allocator: Rc::new(RefCell::new(allocator)),
|
||||
};
|
||||
|
||||
mir_function
|
||||
.kind
|
||||
.codegen(
|
||||
mir_function.name.clone(),
|
||||
mir_function.is_pub,
|
||||
&mut scope,
|
||||
let allocator = Allocator::from(
|
||||
&mir_function.kind,
|
||||
&mir_function.parameters,
|
||||
&mir_function.return_type,
|
||||
&function,
|
||||
match &mir_function.kind {
|
||||
FunctionDefinitionKind::Local(..) => mir_function.signature().into_debug(tokens, compile_unit),
|
||||
FunctionDefinitionKind::Extern(_) => None,
|
||||
FunctionDefinitionKind::Intrinsic(_) => None,
|
||||
&mut AllocatorScope {
|
||||
block: &mut entry,
|
||||
type_values: &type_values,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
);
|
||||
|
||||
let mut scope = Scope {
|
||||
context,
|
||||
modules: &modules,
|
||||
tokens,
|
||||
module: &module,
|
||||
module_id: self.module_id,
|
||||
function,
|
||||
block: entry,
|
||||
assoc_functions: &associated_functions,
|
||||
functions: &functions,
|
||||
types: &types,
|
||||
type_values: &type_values,
|
||||
stack_values: HashMap::new(),
|
||||
debug: Some(Debug {
|
||||
info: &debug,
|
||||
scope: compile_unit,
|
||||
types: &debug_types,
|
||||
}),
|
||||
binops: &binops,
|
||||
allocator: Rc::new(RefCell::new(allocator)),
|
||||
};
|
||||
|
||||
mir_function
|
||||
.kind
|
||||
.codegen(
|
||||
mir_function.name.clone(),
|
||||
mir_function.is_pub,
|
||||
&mut scope,
|
||||
&mir_function.parameters,
|
||||
&mir_function.return_type,
|
||||
&function,
|
||||
match &mir_function.kind {
|
||||
FunctionDefinitionKind::Local(..) => {
|
||||
mir_function.signature().into_debug(tokens, compile_unit)
|
||||
}
|
||||
FunctionDefinitionKind::Extern(_) => None,
|
||||
FunctionDefinitionKind::Intrinsic(_) => None,
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ModuleCodegen { module })
|
||||
@ -821,7 +829,7 @@ impl mir::Expression {
|
||||
});
|
||||
|
||||
if let Some(operation) = operation {
|
||||
let a = operation.codegen(&lhs_val, &rhs_val, scope)?;
|
||||
let a = operation.codegen(lhs_val.clone(), rhs_val.clone(), scope)?;
|
||||
Some(a)
|
||||
} else {
|
||||
let lhs_type = lhs_exp.return_type(&Default::default(), scope.module_id).unwrap().1;
|
||||
@ -906,19 +914,19 @@ impl mir::Expression {
|
||||
.map(|v| v.unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let param_instrs = params.iter().map(|e| e.instr()).collect();
|
||||
let callee = scope.functions.get(&call.name).expect("function not found!");
|
||||
|
||||
let val = scope
|
||||
.block
|
||||
.build_named(call.name.clone(), Instr::FunctionCall(callee.value(), param_instrs))
|
||||
.unwrap();
|
||||
|
||||
if let Some(debug) = &scope.debug {
|
||||
let location = call.meta.into_debug(scope.tokens, debug.scope).unwrap();
|
||||
let location_val = debug.info.location(&debug.scope, location);
|
||||
val.with_location(&mut scope.block, location_val);
|
||||
}
|
||||
let val = callee.codegen(
|
||||
&call.name,
|
||||
params.as_slice(),
|
||||
&call.return_type,
|
||||
if let Some(debug) = &scope.debug {
|
||||
call.meta.into_debug(scope.tokens, debug.scope)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
scope,
|
||||
)?;
|
||||
|
||||
let ptr = if ret_type_kind != TypeKind::Void {
|
||||
let ptr = scope
|
||||
@ -927,7 +935,7 @@ impl mir::Expression {
|
||||
.unwrap();
|
||||
scope
|
||||
.block
|
||||
.build_named(format!("{}.store", call.name), Instr::Store(ptr, val))
|
||||
.build_named(format!("{}.store", call.name), Instr::Store(ptr, val.instr()))
|
||||
.unwrap();
|
||||
|
||||
Some(ptr)
|
||||
@ -1332,31 +1340,38 @@ impl mir::Expression {
|
||||
.map(|v| v.unwrap())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let param_instrs = params.iter().map(|e| e.instr()).collect();
|
||||
let assoc_key = AssociatedFunctionKey(ty.clone(), call.name.clone());
|
||||
let intrinsic = get_intrinsic_assoc_func(&ty, &call.name);
|
||||
let intrinsic_owned = intrinsic.map(|func_def| {
|
||||
let FunctionDefinitionKind::Intrinsic(intrinsic) = func_def.kind else {
|
||||
panic!();
|
||||
};
|
||||
ScopeFunctionKind::IntrinsicOwned(intrinsic)
|
||||
});
|
||||
let callee = scope
|
||||
.assoc_functions
|
||||
.get(&AssociatedFunctionKey(ty.clone(), call.name.clone()))
|
||||
.expect("function not found!");
|
||||
.get(&assoc_key)
|
||||
.or(intrinsic_owned.as_ref())
|
||||
.expect(&format!("Function {} does not exist!", call_name));
|
||||
|
||||
let val = scope
|
||||
.block
|
||||
.build_named(&call_name, Instr::FunctionCall(callee.value(), param_instrs))
|
||||
let location = if let Some(debug) = &scope.debug {
|
||||
call.meta.into_debug(scope.tokens, debug.scope)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let val = callee
|
||||
.codegen(&call_name, params.as_slice(), &call.return_type, location, scope)
|
||||
.unwrap();
|
||||
|
||||
if let Some(debug) = &scope.debug {
|
||||
let location = call.meta.into_debug(scope.tokens, debug.scope).unwrap();
|
||||
let location_val = debug.info.location(&debug.scope, location);
|
||||
val.with_location(&mut scope.block, location_val);
|
||||
}
|
||||
|
||||
let ptr = if ret_type_kind != TypeKind::Void {
|
||||
let ptr = scope
|
||||
.block
|
||||
.build_named(&call_name, Instr::Alloca(ret_type.clone()))
|
||||
.build_named(&call.name, Instr::Alloca(ret_type.clone()))
|
||||
.unwrap();
|
||||
scope
|
||||
.block
|
||||
.build_named(format!("{}.store", call_name), Instr::Store(ptr, val))
|
||||
.build_named(format!("{}.store", call_name), Instr::Store(ptr, val.instr()))
|
||||
.unwrap();
|
||||
|
||||
Some(ptr)
|
||||
|
@ -2,7 +2,7 @@ use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
|
||||
|
||||
use reid_lib::{
|
||||
builder::{InstructionValue, TypeValue},
|
||||
debug_information::{DebugInformation, DebugProgramValue, DebugTypeValue},
|
||||
debug_information::{DebugInformation, DebugLocation, DebugProgramValue, DebugTypeValue},
|
||||
Block, Context, Function, Instr, Module,
|
||||
};
|
||||
|
||||
@ -26,8 +26,8 @@ pub struct Scope<'ctx, 'scope> {
|
||||
pub(super) block: Block<'ctx>,
|
||||
pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>,
|
||||
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
|
||||
pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, Function<'ctx>>,
|
||||
pub(super) functions: &'scope HashMap<String, Function<'ctx>>,
|
||||
pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, ScopeFunctionKind<'ctx>>,
|
||||
pub(super) functions: &'scope HashMap<String, ScopeFunctionKind<'ctx>>,
|
||||
pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>,
|
||||
pub(super) stack_values: HashMap<String, StackValue>,
|
||||
pub(super) debug: Option<Debug<'ctx>>,
|
||||
@ -131,19 +131,20 @@ impl StackValueKind {
|
||||
pub struct StackBinopDefinition<'ctx> {
|
||||
pub(super) parameters: ((String, TypeKind), (String, TypeKind)),
|
||||
pub(super) return_ty: TypeKind,
|
||||
pub(super) kind: StackBinopFunctionKind<'ctx>,
|
||||
pub(super) kind: ScopeFunctionKind<'ctx>,
|
||||
}
|
||||
|
||||
pub enum StackBinopFunctionKind<'ctx> {
|
||||
pub enum ScopeFunctionKind<'ctx> {
|
||||
UserGenerated(Function<'ctx>),
|
||||
Intrinsic(&'ctx Box<dyn IntrinsicFunction>),
|
||||
IntrinsicOwned(Box<dyn IntrinsicFunction>),
|
||||
}
|
||||
|
||||
impl<'ctx> StackBinopDefinition<'ctx> {
|
||||
pub fn codegen<'a>(
|
||||
&self,
|
||||
lhs: &StackValue,
|
||||
rhs: &StackValue,
|
||||
lhs: StackValue,
|
||||
rhs: StackValue,
|
||||
scope: &mut Scope<'ctx, 'a>,
|
||||
) -> Result<StackValue, ErrorKind> {
|
||||
let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 {
|
||||
@ -151,15 +152,43 @@ impl<'ctx> StackBinopDefinition<'ctx> {
|
||||
} else {
|
||||
(rhs, lhs)
|
||||
};
|
||||
match &self.kind {
|
||||
StackBinopFunctionKind::UserGenerated(ir) => {
|
||||
let instr = scope
|
||||
let name = format!(
|
||||
"binop.{}.{}.{}.call",
|
||||
self.parameters.0 .1, self.parameters.1 .1, self.return_ty
|
||||
);
|
||||
self.kind.codegen(&name, &[lhs, rhs], &self.return_ty, None, scope)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> ScopeFunctionKind<'ctx> {
|
||||
pub fn codegen<'a>(
|
||||
&self,
|
||||
name: &str,
|
||||
params: &[StackValue],
|
||||
return_ty: &TypeKind,
|
||||
location: Option<DebugLocation>,
|
||||
scope: &mut Scope<'ctx, 'a>,
|
||||
) -> Result<StackValue, ErrorKind> {
|
||||
match self {
|
||||
ScopeFunctionKind::UserGenerated(function) => {
|
||||
let val = scope
|
||||
.block
|
||||
.build(Instr::FunctionCall(ir.value(), vec![lhs.instr(), rhs.instr()]))
|
||||
.build_named(
|
||||
name,
|
||||
Instr::FunctionCall(function.value(), params.iter().map(|p| p.instr()).collect()),
|
||||
)
|
||||
.unwrap();
|
||||
Ok(StackValue(StackValueKind::Immutable(instr), self.return_ty.clone()))
|
||||
|
||||
if let Some(debug) = &scope.debug {
|
||||
if let Some(location) = location {
|
||||
let location_val = debug.info.location(&debug.scope, location);
|
||||
val.with_location(&mut scope.block, location_val);
|
||||
}
|
||||
}
|
||||
Ok(StackValue(StackValueKind::Immutable(val), return_ty.clone()))
|
||||
}
|
||||
StackBinopFunctionKind::Intrinsic(fun) => fun.codegen(scope, &[&lhs, &rhs]),
|
||||
ScopeFunctionKind::Intrinsic(fun) => fun.codegen(scope, params),
|
||||
ScopeFunctionKind::IntrinsicOwned(fun) => fun.codegen(scope, params),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use std::collections::HashMap;
|
||||
use std::convert::Infallible;
|
||||
use std::error::Error as STDError;
|
||||
|
||||
use crate::codegen::intrinsics::form_intrinsic_binops;
|
||||
use crate::codegen::intrinsics::{form_intrinsic_binops, get_intrinsic_assoc_func};
|
||||
use crate::error_raporting::ReidError;
|
||||
|
||||
use super::*;
|
||||
@ -169,6 +169,24 @@ impl<Data: Clone + Default> Scope<Data> {
|
||||
.find(|(key, def)| key.0 == typekey.0 && def.importer == Some(typekey.1))
|
||||
.map(|(_, v)| v))
|
||||
}
|
||||
|
||||
pub fn get_associated_function(&mut self, key: &AssociatedFunctionKey) -> Option<ScopeFunction> {
|
||||
let func = self.associated_functions.get(key);
|
||||
if let Some(func) = func {
|
||||
Some(func.clone())
|
||||
} else if let Some(func) = get_intrinsic_assoc_func(&key.0, &key.1) {
|
||||
self.associated_functions.set(
|
||||
key.clone(),
|
||||
ScopeFunction {
|
||||
ret: func.return_type,
|
||||
params: func.parameters.iter().map(|(_, p)| p.clone()).collect(),
|
||||
},
|
||||
);
|
||||
self.associated_functions.get(key).cloned()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -732,12 +732,10 @@ impl Expression {
|
||||
ExprKind::AssociatedFunctionCall(type_kind, function_call) => {
|
||||
let true_function = state
|
||||
.scope
|
||||
.associated_functions
|
||||
.get(&pass::AssociatedFunctionKey(
|
||||
.get_associated_function(&pass::AssociatedFunctionKey(
|
||||
type_kind.clone(),
|
||||
function_call.name.clone(),
|
||||
))
|
||||
.cloned()
|
||||
.ok_or(ErrorKind::FunctionNotDefined(function_call.name.clone()));
|
||||
|
||||
if let Some(f) = state.ok(true_function, self.1) {
|
||||
|
@ -598,8 +598,7 @@ impl Expression {
|
||||
// Get function definition and types
|
||||
let fn_call = state
|
||||
.scope
|
||||
.associated_functions
|
||||
.get(&AssociatedFunctionKey(type_kind.clone(), function_call.name.clone()))
|
||||
.get_associated_function(&AssociatedFunctionKey(type_kind.clone(), function_call.name.clone()))
|
||||
.ok_or(ErrorKind::AssocFunctionNotDefined(
|
||||
function_call.name.clone(),
|
||||
type_kind.clone(),
|
||||
|
Loading…
Reference in New Issue
Block a user