From e1c4c0ec9fd6e004d5aa8bb5aa31a5111c696bcd Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 24 Feb 2026 00:06:46 +0100 Subject: [PATCH 1/3] feat: added IR support for function argument usage --- ir/src/conv/func.rs | 22 +++++++++++++++------- ir/src/conv/val.rs | 7 ++++++- ir/src/ctx.rs | 21 +++++++++++++++++++-- ir/src/irstruct/funcs.rs | 16 ++++++++-------- ir/src/refs.rs | 4 ++-- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/ir/src/conv/func.rs b/ir/src/conv/func.rs index 0a52fe6..01a3e8a 100644 --- a/ir/src/conv/func.rs +++ b/ir/src/conv/func.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use commons::err::{PositionlessError, PositionlessResult}; use parser::{ast::{func, tree::ASTTreeNode}, parse_ast_ctx}; -use crate::{conv::{control::{parse_for_statement_ir, parse_if_statement_ir}, val::parse_ir_value}, ctx::{IRContext, IRLocalContext}, irstruct::{funcs::IRFunction, ptr::IRPointer}, refs::IRValueRef, types::typing::IRType}; +use crate::{conv::{control::{parse_for_statement_ir, parse_if_statement_ir}, val::parse_ir_value}, ctx::{IRContext, IRLocalContext}, irstruct::{funcs::IRFunction, ptr::IRPointer}, refs::IRValueRef, types::typing::IRType, values::IRValue}; pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box) -> PositionlessResult> { if let ASTTreeNode::ShadowFunctionDeclaration { func_name, args, returnType } = *node { @@ -12,7 +12,7 @@ pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box None => None }; - let mut arguments: Vec> = vec![]; + let mut arguments: Vec<(Rc, u64)> = vec![]; for k in args { let t = match ctx.type_storage.get(k.argument_type) { @@ -20,7 +20,7 @@ pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box None => return Err(PositionlessError::new(&format!("Cannot get type with hash {} for argument {}!", k.argument_type, k.name.val))) }; - arguments.push(t); + arguments.push((t, k.name.hash)); } let func = IRFunction::create_shadow(ctx, func_name.val.clone(), &ctx.module, return_type, arguments)?; @@ -40,7 +40,7 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box) -> Po None => None }; - let mut arguments: Vec> = vec![]; + let mut arguments: Vec<(Rc, u64)> = vec![]; for k in args { let t = match ctx.type_storage.get(k.argument_type) { @@ -48,11 +48,19 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box) -> Po None => return Err(PositionlessError::new(&format!("Cannot get type with hash {} for argument {}!", k.argument_type, k.name.val))) }; - arguments.push(t); + arguments.push((t, k.name.hash)); } let mut func = IRFunction::create(ctx, func_name.val, &ctx.module, return_type, arguments)?; + let mut ind = 0; + for argument in &func.args { + let val = func.get_nth_arg(ind)?; + + func.lctx.add_argument(argument.1, IRValue::new(val, argument.0.clone()))?; + ind += 1; + } + func.prepare_body_filling(ctx); parse_ir_body(ctx, &mut func, body, true)?; @@ -63,7 +71,7 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box) -> Po }; } - ctx.add_function(func_name.hash, func); + ctx.add_function(func_name.hash, func)?; return ctx.get_funtion(func_name.hash); } @@ -97,7 +105,7 @@ pub fn parse_ir_function_call(ctx: &IRContext, lctx: &IRLocalContext, node: Box< let func = ctx.get_funtion(func.hash)?; - let ret =func.call(ctx, arguments, grab_result)?; + let ret = func.call(ctx, arguments, grab_result)?; if !grab_result || ret.is_none() { return Ok(None); diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index d3f40c5..9345951 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -16,8 +16,13 @@ pub fn get_variable_ref(lctx: &IRLocalContext, ctx: &IRContext, hash: u64) -> Po match lctx.get_variable(hash) { Ok(v) => return Ok(IRValueRef::from_pointer(IRPointer::clone(v))), - Err(_) => return Err(PositionlessError::new(&format!("Cannot find variable with hash {} in the current context", hash))) + Err(_) => {} }; + + match lctx.get_argument(hash) { + Ok(v) => return Ok(IRValueRef::from_val(IRValue::clone(v))), + Err(_) => return Err(PositionlessError::new(&format!("Cannot find variable with hash {} in the current context", hash))) + } } pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: Box, left: Option, in_var: bool) -> PositionlessResult { diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 20dcdae..086e194 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap, mem::transmute, ops::{Add, Deref, DerefMut}, rc: use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap}; use inkwell::{AddressSpace, builder::Builder, context::Context, module::Module, types::{PointerType, VoidType}}; -use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage, utils::{LateInit, SelfHash}}; +use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage, utils::{LateInit, SelfHash}, values::IRValue}; /// The global IR context. /// Basically holds anything related to the current IR compilation (eg: functions, types, global vars) @@ -93,12 +93,13 @@ pub struct LocalIRVariable { /// Holds anything held and created in the given body (eg: vars). pub struct IRLocalContext { pub vars: HashedMap, + pub arguments: HashedMap, pub current_depth: i64, // Starts at 0 where 0 is function body } impl IRLocalContext { pub fn new() -> Self { - return IRLocalContext { vars: HashedMap::new(0), current_depth: 0 } + return IRLocalContext { vars: HashedMap::new(0), arguments: HashedMap::new(0), current_depth: 0 } } /// Attempts to add a variable in the current local context. Will return an error if the operation is impossible @@ -111,6 +112,15 @@ impl IRLocalContext { return Ok(true); } + pub fn add_argument(&mut self, hash: u64, val: IRValue) -> PositionlessResult { + if self.arguments.get(hash).is_some() { + return Err(PositionlessError::new(&format!("Argument named {} is already present in the current scope!", hash))) + } + + self.arguments.put(hash, val); + return Ok(true); + } + pub fn get_variable(&self, hash: u64) -> PositionlessResult<&IRPointer> { return match self.vars.get(hash) { Some(v) => Ok(&v.ptr), @@ -118,6 +128,13 @@ impl IRLocalContext { }; } + pub fn get_argument(&self, hash: u64) -> PositionlessResult<&IRValue> { + return match self.arguments.get(hash) { + Some(v) => Ok(v), + None => return Err(PositionlessError::new(&format!("Invalid argument hash {}", hash))) + } + } + pub fn increment_body_depth(&mut self) { self.current_depth += 1; } diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 18b205d..8c400f1 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -11,7 +11,7 @@ pub struct IRFunction { pub inkwell_func: FunctionValue<'static>, pub ret_type: Option>, - args: Vec>, + pub args: Vec<(Rc, u64)>, name: String, pub lctx: IRLocalContext, @@ -20,22 +20,22 @@ pub struct IRFunction { } impl IRFunction { - pub fn new(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec>) -> Self { + pub fn new(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec<(Rc, u64)>) -> Self { let block = ctx.inkwell_ctx.append_basic_block(func, "entry"); return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, entry: Some(unsafe { transmute(block) }), lctx: IRLocalContext::new().into() } } - pub fn new_shadow(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec>) -> Self { + pub fn new_shadow(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec<(Rc, u64)>) -> Self { return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, entry: None, lctx: IRLocalContext::new().into() } } - pub fn create_shadow(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec>) -> PositionlessResult { + pub fn create_shadow(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec<(Rc, u64)>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { - kargs.push(*k.get_inkwell_base_metadatatype()?); + kargs.push(*k.0.get_inkwell_base_metadatatype()?); } let t = match &ret_type { @@ -48,11 +48,11 @@ impl IRFunction { return Ok(IRFunction::new_shadow(ctx, name, func, ret_type, args)); } - pub fn create(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec>) -> PositionlessResult { + pub fn create(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec<(Rc, u64)>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { - kargs.push(*k.get_inkwell_base_metadatatype()?); + kargs.push(*k.0.get_inkwell_base_metadatatype()?); } let t = match &ret_type { @@ -117,7 +117,7 @@ impl IRFunction { } pub fn get_nth_arg_int(&self, ind: u32) -> PositionlessResult { - if !self.args[ind as usize].is_numeric_type() { + if !self.args[ind as usize].0.is_numeric_type() { return Err(PositionlessError::new("Tried getting nth argument but given argument's type isn't numeric!")); } diff --git a/ir/src/refs.rs b/ir/src/refs.rs index 29dfe05..bfd0e58 100644 --- a/ir/src/refs.rs +++ b/ir/src/refs.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use commons::err::{PositionlessError, PositionlessResult}; use inkwell::{builder::Builder, types::{AnyTypeEnum, BasicTypeEnum}, values::PointerValue}; -use crate::{ctx::IRContext, irstruct::{ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::{IRType, OwnedPointerValue}, values::IRValue}; +use crate::{ctx::IRContext, irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::typing::{IRType, OwnedPointerValue}, values::IRValue}; pub enum IRValueRefKind { Ptr(Rc, IRPointer), @@ -52,7 +52,7 @@ impl IRValueRef { IRValueRefKind::Global(t, global) => { Ok(IRValue::new(global.as_val()?, t.clone())) - }, + } _ => return Err(PositionlessError::new("Cannot use obtain on said IR value type!")) } From c14e9b62b60a26fb7ca2b1421dea2e5e4fb80344 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 24 Feb 2026 00:28:13 +0100 Subject: [PATCH 2/3] feat: added hash in IRFunction & changed to pass IRFunction instead of raw IRLocalContext --- ir/src/conv/control.rs | 6 +++--- ir/src/conv/func.rs | 26 +++++++++++++------------- ir/src/conv/val.rs | 26 +++++++++++++------------- ir/src/ctx.rs | 2 +- ir/src/irstruct/funcs.rs | 17 +++++++++-------- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/ir/src/conv/control.rs b/ir/src/conv/control.rs index 67e80d6..66fca53 100644 --- a/ir/src/conv/control.rs +++ b/ir/src/conv/control.rs @@ -30,7 +30,7 @@ pub fn parse_if_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box { ctx.builder.position_at_end(ir_branches[ind]); - let cond_val = parse_ir_value(Some(&func.lctx), ctx, cond.unwrap(), None, false)?; + let cond_val = parse_ir_value(Some(&func), ctx, cond.unwrap(), None, false)?; let int_cond_val = match cond_val.obtain(ctx)?.obtain_as_bool() { Some(v) => *v, @@ -121,7 +121,7 @@ pub fn parse_for_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box< let bool_type = ctx.type_storage.get(BOOL_TYPE_HASH).expect("Boolean type wasn't found!"); - let cond_val = parse_ir_value(Some(&func.lctx), ctx, cond, None, false)?; + let cond_val = parse_ir_value(Some(&func), ctx, cond, None, false)?; let cond_int = cond_val.obtain(ctx)?.obtain_as_bool().expect("Cannot cast condition result as int"); ctx.builder.build_conditional_branch(*cond_int, for_body_block, post_block); diff --git a/ir/src/conv/func.rs b/ir/src/conv/func.rs index 01a3e8a..efe642f 100644 --- a/ir/src/conv/func.rs +++ b/ir/src/conv/func.rs @@ -23,11 +23,11 @@ pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box arguments.push((t, k.name.hash)); } - let func = IRFunction::create_shadow(ctx, func_name.val.clone(), &ctx.module, return_type, arguments)?; + let func = IRFunction::create_shadow(ctx, func_name.val.clone(), func_name.hash, &ctx.module, return_type, arguments)?; ctx.add_function(func_name.hash, func)?; - return Ok(ctx.get_funtion(func_name.hash)?); + return Ok(ctx.get_function(func_name.hash)?); } return Err(PositionlessError::new("Cannot parse ir shadow funtion decl as the node is incompatible!")); @@ -51,7 +51,7 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box) -> Po arguments.push((t, k.name.hash)); } - let mut func = IRFunction::create(ctx, func_name.val, &ctx.module, return_type, arguments)?; + let mut func = IRFunction::create(ctx, func_name.val,func_name.hash, &ctx.module, return_type, arguments)?; let mut ind = 0; for argument in &func.args { @@ -73,7 +73,7 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box) -> Po ctx.add_function(func_name.hash, func)?; - return ctx.get_funtion(func_name.hash); + return ctx.get_function(func_name.hash); } return Err(PositionlessError::new("Given node in parse_ir_function_decl wasn't a function decl!")); @@ -91,7 +91,7 @@ pub fn parse_ir_body(ctx: &IRContext, func: &mut IRFunction, nodes: Vec, owner: Option, grab_result: bool) -> PositionlessResult> { +pub fn parse_ir_function_call(ctx: &IRContext, f: &IRFunction, node: Box, owner: Option, grab_result: bool) -> PositionlessResult> { if let ASTTreeNode::FunctionCall { func, args } = *node { let mut arguments = vec![]; @@ -100,10 +100,10 @@ pub fn parse_ir_function_call(ctx: &IRContext, lctx: &IRLocalContext, node: Box< } for v in args { - arguments.push(parse_ir_value(Some(lctx), ctx, v, None, false)?); + arguments.push(parse_ir_value(Some(&f), ctx, v, None, false)?); } - let func = ctx.get_funtion(func.hash)?; + let func = ctx.get_function(func.hash)?; let ret = func.call(ctx, arguments, grab_result)?; @@ -128,7 +128,7 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod println!("Var name: {}", var_name.val.clone()); let initial = if let Some(v) = value { - Some(parse_ir_value(Some(&func.lctx), ctx, v, None, true)?) + Some(parse_ir_value(Some(&func), ctx, v, None, true)?) } else { None }; @@ -143,19 +143,19 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod }, ASTTreeNode::StructLRFunction { .. } => { - parse_ir_value(Some(&func.lctx), ctx, node, None, false)?; + parse_ir_value(Some(&func), ctx, node, None, false)?; return Ok(true) }, ASTTreeNode::StructLRVariable { .. } => { - parse_ir_value(Some(&func.lctx), ctx, node, None, false)?; + parse_ir_value(Some(&func), ctx, node, None, false)?; return Ok(true) }, ASTTreeNode::FunctionCall { .. } => { - parse_ir_function_call(ctx, &func.lctx, node, None, false)?; + parse_ir_function_call(ctx, &func, node, None, false)?; return Ok(true) }, @@ -167,7 +167,7 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod return Ok(true); } - let val = parse_ir_value(Some(&func.lctx), ctx, val.unwrap(), None, true)?; + let val = parse_ir_value(Some(&func), ctx, val.unwrap(), None, true)?; ctx.builder.build_return(Some(&val.obtain(ctx)?.obtain().inner)); @@ -187,7 +187,7 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod return Err(PositionlessError::new("Cannot use a math expression in IR body if it is not assignments!")) } - parse_ir_value(Some(&func.lctx), ctx, node, None, false)?; + parse_ir_value(Some(&func), ctx, node, None, false)?; return Ok(true); } diff --git a/ir/src/conv/val.rs b/ir/src/conv/val.rs index 9345951..25e4cea 100644 --- a/ir/src/conv/val.rs +++ b/ir/src/conv/val.rs @@ -25,7 +25,7 @@ pub fn get_variable_ref(lctx: &IRLocalContext, ctx: &IRContext, hash: u64) -> Po } } -pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: Box, left: Option, in_var: bool) -> PositionlessResult { +pub fn parse_ir_value<'a>(f: Option<&IRFunction>, ctx: &IRContext, node: Box, left: Option, in_var: bool) -> PositionlessResult { match node.as_ref() { ASTTreeNode::IntegerLit { val: v, hash} => { let t = ctx.type_storage.get(*hash); @@ -67,18 +67,18 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: return Ok(IRValueRef::from_pointer(ptr)); } - let var = get_variable_ref(&lctx.unwrap(), ctx, e.hash)?; + let var = get_variable_ref(&f.unwrap().lctx, ctx, e.hash)?; return Ok(var); }, ASTTreeNode::FunctionCall { func, args } => { - if lctx.is_none() { + if f.is_none() { return Err(PositionlessError::new("Cannot use function calls outside of a function!")) } - let k = parse_ir_function_call(ctx, lctx.unwrap(), node, left, in_var)?; + let k = parse_ir_function_call(ctx, f.unwrap(), node, left, in_var)?; if k.is_none() { return Err(PositionlessError::new("Function call returns void! cannot use as a value!")); @@ -88,8 +88,8 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: }, ASTTreeNode::MathResult { lval, rval, operator, assigns } => { - let left = parse_ir_value(lctx, ctx, lval.clone(), None, in_var)?; - let right = parse_ir_value(lctx, ctx, rval.clone(), None, in_var)?; + let left = parse_ir_value(f, ctx, lval.clone(), None, in_var)?; + let right = parse_ir_value(f, ctx, rval.clone(), None, in_var)?; let t = left.get_type(); @@ -118,8 +118,8 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: }, ASTTreeNode::OperatorBasedConditionMember { lval, rval, operator } => { - let l_val = parse_ir_value(lctx, ctx, lval.clone(), None, in_var)?; - let r_val = parse_ir_value(lctx, ctx, rval.clone(), None, in_var)?; + let l_val = parse_ir_value(f, ctx, lval.clone(), None, in_var)?; + let r_val = parse_ir_value(f, ctx, rval.clone(), None, in_var)?; let cmp = make_bool_cmp_int(ctx, l_val, r_val, operator.clone())?; @@ -127,7 +127,7 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: }, ASTTreeNode::BooleanBasedConditionMember { val, negate } => { - let v = parse_ir_value(lctx, ctx, val.clone(), None, in_var)?; + let v = parse_ir_value(f, ctx, val.clone(), None, in_var)?; if *negate { return Ok(IRValueRef::from_val(make_bool_xor(ctx, v)?)) @@ -137,17 +137,17 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: } ASTTreeNode::StructLRFunction { l, r } => { - let l_val = parse_ir_value(lctx, ctx, l.clone(), None, in_var)?; + let l_val = parse_ir_value(f, ctx, l.clone(), None, in_var)?; let l_ptr = l_val.as_pointer()?; - return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr), in_var); + return parse_ir_value(f, ctx, r.clone(), Some(l_ptr), in_var); }, ASTTreeNode::StructLRVariable { l, r } => { - let l_val = parse_ir_value(lctx, ctx, l.clone(), None, in_var)?; + let l_val = parse_ir_value(f, ctx, l.clone(), None, in_var)?; let l_ptr = l_val.as_pointer()?; - return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr), in_var); + return parse_ir_value(f, ctx, r.clone(), Some(l_ptr), in_var); } _ => return Err(PositionlessError::new("The given node cannot be parsed as a value!")) diff --git a/ir/src/ctx.rs b/ir/src/ctx.rs index 086e194..61bf206 100644 --- a/ir/src/ctx.rs +++ b/ir/src/ctx.rs @@ -66,7 +66,7 @@ impl IRContext { return self.functions.get(&SelfHash { hash }).is_some() || self.static_vars.get(&SelfHash {hash}).is_some() || self.type_storage.get(hash).is_some(); } - pub fn get_funtion(&self, hash: u64) -> PositionlessResult> { + pub fn get_function(&self, hash: u64) -> PositionlessResult> { return match self.functions.get(&SelfHash { hash }) { Some(v) => Ok(v.clone()), None => Err(PositionlessError::new(&format!("Invalid function name! Got hash {}", hash))) diff --git a/ir/src/irstruct/funcs.rs b/ir/src/irstruct/funcs.rs index 8c400f1..1c54b4a 100644 --- a/ir/src/irstruct/funcs.rs +++ b/ir/src/irstruct/funcs.rs @@ -13,6 +13,7 @@ pub struct IRFunction { pub ret_type: Option>, pub args: Vec<(Rc, u64)>, name: String, + pub hash: u64, pub lctx: IRLocalContext, @@ -20,18 +21,18 @@ pub struct IRFunction { } impl IRFunction { - pub fn new(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec<(Rc, u64)>) -> Self { + pub fn new(ctx: &IRContext, name: String, hash: u64, func: FunctionValue, ret_type: Option>, args: Vec<(Rc, u64)>) -> Self { let block = ctx.inkwell_ctx.append_basic_block(func, "entry"); - return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, entry: Some(unsafe { transmute(block) }), lctx: IRLocalContext::new().into() } + return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, hash, entry: Some(unsafe { transmute(block) }), lctx: IRLocalContext::new().into() } } - pub fn new_shadow(ctx: &IRContext, name: String, func: FunctionValue, ret_type: Option>, args: Vec<(Rc, u64)>) -> Self { - return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, entry: None, lctx: IRLocalContext::new().into() } + pub fn new_shadow(ctx: &IRContext, name: String, hash: u64, func: FunctionValue, ret_type: Option>, args: Vec<(Rc, u64)>) -> Self { + return IRFunction { owned: ctx.inkwell_ctx.clone(), inkwell_func: unsafe { transmute(func)}, ret_type, args, name, hash, entry: None, lctx: IRLocalContext::new().into() } } - pub fn create_shadow(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec<(Rc, u64)>) -> PositionlessResult { + pub fn create_shadow(ctx: &IRContext, name: String, hash: u64, module: &Module, ret_type: Option>, args: Vec<(Rc, u64)>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { @@ -45,10 +46,10 @@ impl IRFunction { let func = module.add_function(&name, t, None); - return Ok(IRFunction::new_shadow(ctx, name, func, ret_type, args)); + return Ok(IRFunction::new_shadow(ctx, name, hash, func, ret_type, args)); } - pub fn create(ctx: &IRContext, name: String, module: &Module, ret_type: Option>, args: Vec<(Rc, u64)>) -> PositionlessResult { + pub fn create(ctx: &IRContext, name: String, hash: u64, module: &Module, ret_type: Option>, args: Vec<(Rc, u64)>) -> PositionlessResult { let mut kargs = vec![]; for k in &args { @@ -62,7 +63,7 @@ impl IRFunction { let func = module.add_function(&name, t, None); - return Ok(IRFunction::new(ctx, name, func, ret_type, args)); + return Ok(IRFunction::new(ctx, name, hash, func, ret_type, args)); } pub fn call(&self, ctx: &IRContext, args: Vec, grab_return: bool) -> PositionlessResult> { From fb6dcace5f981af19f443f6da746d6f1002bb9db Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 24 Feb 2026 00:32:11 +0100 Subject: [PATCH 3/3] feat: added support for recursive calls --- examples/fib.qf | 8 ++++++++ ir/src/conv/func.rs | 13 ++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 examples/fib.qf diff --git a/examples/fib.qf b/examples/fib.qf new file mode 100644 index 0000000..cdb2a91 --- /dev/null +++ b/examples/fib.qf @@ -0,0 +1,8 @@ +func fib(si32 i) si32 { + if(i <= 1_si32) { + ret 1 + } + + var si32 test = fib(i - 1_si32) + fib(i - 2_si32) + ret test +} \ No newline at end of file diff --git a/ir/src/conv/func.rs b/ir/src/conv/func.rs index efe642f..220a5cd 100644 --- a/ir/src/conv/func.rs +++ b/ir/src/conv/func.rs @@ -92,7 +92,7 @@ pub fn parse_ir_body(ctx: &IRContext, func: &mut IRFunction, nodes: Vec, owner: Option, grab_result: bool) -> PositionlessResult> { - if let ASTTreeNode::FunctionCall { func, args } = *node { + if let ASTTreeNode::FunctionCall { func: ff, args } = *node { let mut arguments = vec![]; if owner.as_ref().is_some() { @@ -103,9 +103,16 @@ pub fn parse_ir_function_call(ctx: &IRContext, f: &IRFunction, node: Box