Skip to content

Commit 472fb3d

Browse files
authored
Merge pull request #37 from Quickfall/feat/ctx-support-for-funcargs
feat: Recursive calls and function arguments in local context
2 parents 79b9c73 + fb6dcac commit 472fb3d

7 files changed

Lines changed: 101 additions & 55 deletions

File tree

examples/fib.qf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
func fib(si32 i) si32 {
2+
if(i <= 1_si32) {
3+
ret 1
4+
}
5+
6+
var si32 test = fib(i - 1_si32) + fib(i - 2_si32)
7+
ret test
8+
}

ir/src/conv/control.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn parse_if_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box<A
3030

3131
ir_branches.push(ctx.inkwell_ctx.append_basic_block(func.inkwell_func, "out"));
3232

33-
let first_cond = parse_ir_value(Some(&func.lctx), ctx, cond, None, false)?;
33+
let first_cond = parse_ir_value(Some(&func), ctx, cond, None, false)?;
3434

3535
let bool_type = ctx.type_storage.get(BOOL_TYPE_HASH).unwrap();
3636

@@ -55,7 +55,7 @@ pub fn parse_if_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box<A
5555
ASTTreeNode::IfElseStatement { cond, body } => {
5656
ctx.builder.position_at_end(ir_branches[ind]);
5757

58-
let cond_val = parse_ir_value(Some(&func.lctx), ctx, cond.unwrap(), None, false)?;
58+
let cond_val = parse_ir_value(Some(&func), ctx, cond.unwrap(), None, false)?;
5959

6060
let int_cond_val = match cond_val.obtain(ctx)?.obtain_as_bool() {
6161
Some(v) => *v,
@@ -121,7 +121,7 @@ pub fn parse_for_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box<
121121

122122
let bool_type = ctx.type_storage.get(BOOL_TYPE_HASH).expect("Boolean type wasn't found!");
123123

124-
let cond_val = parse_ir_value(Some(&func.lctx), ctx, cond, None, false)?;
124+
let cond_val = parse_ir_value(Some(&func), ctx, cond, None, false)?;
125125
let cond_int = cond_val.obtain(ctx)?.obtain_as_bool().expect("Cannot cast condition result as int");
126126

127127
ctx.builder.build_conditional_branch(*cond_int, for_body_block, post_block);

ir/src/conv/func.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::rc::Rc;
33
use commons::err::{PositionlessError, PositionlessResult};
44
use parser::{ast::{func, tree::ASTTreeNode}, parse_ast_ctx};
55

6-
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};
6+
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};
77

88
pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> PositionlessResult<Rc<IRFunction>> {
99
if let ASTTreeNode::ShadowFunctionDeclaration { func_name, args, returnType } = *node {
@@ -12,22 +12,22 @@ pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>
1212
None => None
1313
};
1414

15-
let mut arguments: Vec<Rc<IRType>> = vec![];
15+
let mut arguments: Vec<(Rc<IRType>, u64)> = vec![];
1616

1717
for k in args {
1818
let t = match ctx.type_storage.get(k.argument_type) {
1919
Some(v) => v,
2020
None => return Err(PositionlessError::new(&format!("Cannot get type with hash {} for argument {}!", k.argument_type, k.name.val)))
2121
};
2222

23-
arguments.push(t);
23+
arguments.push((t, k.name.hash));
2424
}
2525

26-
let func = IRFunction::create_shadow(ctx, func_name.val.clone(), &ctx.module, return_type, arguments)?;
26+
let func = IRFunction::create_shadow(ctx, func_name.val.clone(), func_name.hash, &ctx.module, return_type, arguments)?;
2727

2828
ctx.add_function(func_name.hash, func)?;
2929

30-
return Ok(ctx.get_funtion(func_name.hash)?);
30+
return Ok(ctx.get_function(func_name.hash)?);
3131
}
3232

3333
return Err(PositionlessError::new("Cannot parse ir shadow funtion decl as the node is incompatible!"));
@@ -40,18 +40,26 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> Po
4040
None => None
4141
};
4242

43-
let mut arguments: Vec<Rc<IRType>> = vec![];
43+
let mut arguments: Vec<(Rc<IRType>, u64)> = vec![];
4444

4545
for k in args {
4646
let t = match ctx.type_storage.get(k.argument_type) {
4747
Some(v) => v,
4848
None => return Err(PositionlessError::new(&format!("Cannot get type with hash {} for argument {}!", k.argument_type, k.name.val)))
4949
};
5050

51-
arguments.push(t);
51+
arguments.push((t, k.name.hash));
5252
}
5353

54-
let mut func = IRFunction::create(ctx, func_name.val, &ctx.module, return_type, arguments)?;
54+
let mut func = IRFunction::create(ctx, func_name.val,func_name.hash, &ctx.module, return_type, arguments)?;
55+
56+
let mut ind = 0;
57+
for argument in &func.args {
58+
let val = func.get_nth_arg(ind)?;
59+
60+
func.lctx.add_argument(argument.1, IRValue::new(val, argument.0.clone()))?;
61+
ind += 1;
62+
}
5563

5664
func.prepare_body_filling(ctx);
5765
parse_ir_body(ctx, &mut func, body, true)?;
@@ -63,9 +71,9 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> Po
6371
};
6472
}
6573

66-
ctx.add_function(func_name.hash, func);
74+
ctx.add_function(func_name.hash, func)?;
6775

68-
return ctx.get_funtion(func_name.hash);
76+
return ctx.get_function(func_name.hash);
6977
}
7078

7179
return Err(PositionlessError::new("Given node in parse_ir_function_decl wasn't a function decl!"));
@@ -83,21 +91,28 @@ pub fn parse_ir_body(ctx: &IRContext, func: &mut IRFunction, nodes: Vec<Box<ASTT
8391
return Ok(true);
8492
}
8593

86-
pub fn parse_ir_function_call(ctx: &IRContext, lctx: &IRLocalContext, node: Box<ASTTreeNode>, owner: Option<IRPointer>, grab_result: bool) -> PositionlessResult<Option<IRValueRef>> {
87-
if let ASTTreeNode::FunctionCall { func, args } = *node {
94+
pub fn parse_ir_function_call(ctx: &IRContext, f: &IRFunction, node: Box<ASTTreeNode>, owner: Option<IRPointer>, grab_result: bool) -> PositionlessResult<Option<IRValueRef>> {
95+
if let ASTTreeNode::FunctionCall { func: ff, args } = *node {
8896
let mut arguments = vec![];
8997

9098
if owner.as_ref().is_some() {
9199
arguments.push(IRValueRef::from_pointer(owner.as_ref().unwrap().clone()));
92100
}
93101

94102
for v in args {
95-
arguments.push(parse_ir_value(Some(lctx), ctx, v, None, false)?);
103+
arguments.push(parse_ir_value(Some(&f), ctx, v, None, false)?);
96104
}
97105

98-
let func = ctx.get_funtion(func.hash)?;
99106

100-
let ret =func.call(ctx, arguments, grab_result)?;
107+
let ret;
108+
109+
if ff.hash == f.hash {
110+
ret = f.call(ctx, arguments, grab_result)?;
111+
} else {
112+
let func = ctx.get_function(ff.hash)?;
113+
114+
ret = func.call(ctx, arguments, grab_result)?;
115+
}
101116

102117
if !grab_result || ret.is_none() {
103118
return Ok(None);
@@ -120,7 +135,7 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod
120135
println!("Var name: {}", var_name.val.clone());
121136

122137
let initial = if let Some(v) = value {
123-
Some(parse_ir_value(Some(&func.lctx), ctx, v, None, true)?)
138+
Some(parse_ir_value(Some(&func), ctx, v, None, true)?)
124139
} else {
125140
None
126141
};
@@ -135,19 +150,19 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod
135150
},
136151

137152
ASTTreeNode::StructLRFunction { .. } => {
138-
parse_ir_value(Some(&func.lctx), ctx, node, None, false)?;
153+
parse_ir_value(Some(&func), ctx, node, None, false)?;
139154

140155
return Ok(true)
141156
},
142157

143158
ASTTreeNode::StructLRVariable { .. } => {
144-
parse_ir_value(Some(&func.lctx), ctx, node, None, false)?;
159+
parse_ir_value(Some(&func), ctx, node, None, false)?;
145160

146161
return Ok(true)
147162
},
148163

149164
ASTTreeNode::FunctionCall { .. } => {
150-
parse_ir_function_call(ctx, &func.lctx, node, None, false)?;
165+
parse_ir_function_call(ctx, &func, node, None, false)?;
151166

152167
return Ok(true)
153168
},
@@ -159,7 +174,7 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod
159174
return Ok(true);
160175
}
161176

162-
let val = parse_ir_value(Some(&func.lctx), ctx, val.unwrap(), None, true)?;
177+
let val = parse_ir_value(Some(&func), ctx, val.unwrap(), None, true)?;
163178

164179
ctx.builder.build_return(Some(&val.obtain(ctx)?.obtain().inner));
165180

@@ -179,7 +194,7 @@ pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, nod
179194
return Err(PositionlessError::new("Cannot use a math expression in IR body if it is not assignments!"))
180195
}
181196

182-
parse_ir_value(Some(&func.lctx), ctx, node, None, false)?;
197+
parse_ir_value(Some(&func), ctx, node, None, false)?;
183198
return Ok(true);
184199
}
185200

ir/src/conv/val.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,16 @@ pub fn get_variable_ref(lctx: &IRLocalContext, ctx: &IRContext, hash: u64) -> Po
1616

1717
match lctx.get_variable(hash) {
1818
Ok(v) => return Ok(IRValueRef::from_pointer(IRPointer::clone(v))),
19-
Err(_) => return Err(PositionlessError::new(&format!("Cannot find variable with hash {} in the current context", hash)))
19+
Err(_) => {}
2020
};
21+
22+
match lctx.get_argument(hash) {
23+
Ok(v) => return Ok(IRValueRef::from_val(IRValue::clone(v))),
24+
Err(_) => return Err(PositionlessError::new(&format!("Cannot find variable with hash {} in the current context", hash)))
25+
}
2126
}
2227

23-
pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: Box<ASTTreeNode>, left: Option<IRPointer>, in_var: bool) -> PositionlessResult<IRValueRef> {
28+
pub fn parse_ir_value<'a>(f: Option<&IRFunction>, ctx: &IRContext, node: Box<ASTTreeNode>, left: Option<IRPointer>, in_var: bool) -> PositionlessResult<IRValueRef> {
2429
match node.as_ref() {
2530
ASTTreeNode::IntegerLit { val: v, hash} => {
2631
let t = ctx.type_storage.get(*hash);
@@ -62,18 +67,18 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node:
6267
return Ok(IRValueRef::from_pointer(ptr));
6368
}
6469

65-
let var = get_variable_ref(&lctx.unwrap(), ctx, e.hash)?;
70+
let var = get_variable_ref(&f.unwrap().lctx, ctx, e.hash)?;
6671

6772
return Ok(var);
6873
},
6974

7075
ASTTreeNode::FunctionCall { func, args } => {
7176

72-
if lctx.is_none() {
77+
if f.is_none() {
7378
return Err(PositionlessError::new("Cannot use function calls outside of a function!"))
7479
}
7580

76-
let k = parse_ir_function_call(ctx, lctx.unwrap(), node, left, in_var)?;
81+
let k = parse_ir_function_call(ctx, f.unwrap(), node, left, in_var)?;
7782

7883
if k.is_none() {
7984
return Err(PositionlessError::new("Function call returns void! cannot use as a value!"));
@@ -83,8 +88,8 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node:
8388
},
8489

8590
ASTTreeNode::MathResult { lval, rval, operator, assigns } => {
86-
let left = parse_ir_value(lctx, ctx, lval.clone(), None, in_var)?;
87-
let right = parse_ir_value(lctx, ctx, rval.clone(), None, in_var)?;
91+
let left = parse_ir_value(f, ctx, lval.clone(), None, in_var)?;
92+
let right = parse_ir_value(f, ctx, rval.clone(), None, in_var)?;
8893

8994
let t = left.get_type();
9095

@@ -113,16 +118,16 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node:
113118
},
114119

115120
ASTTreeNode::OperatorBasedConditionMember { lval, rval, operator } => {
116-
let l_val = parse_ir_value(lctx, ctx, lval.clone(), None, in_var)?;
117-
let r_val = parse_ir_value(lctx, ctx, rval.clone(), None, in_var)?;
121+
let l_val = parse_ir_value(f, ctx, lval.clone(), None, in_var)?;
122+
let r_val = parse_ir_value(f, ctx, rval.clone(), None, in_var)?;
118123

119124
let cmp = make_bool_cmp_int(ctx, l_val, r_val, operator.clone())?;
120125

121126
return Ok(IRValueRef::from_val(cmp));
122127
},
123128

124129
ASTTreeNode::BooleanBasedConditionMember { val, negate } => {
125-
let v = parse_ir_value(lctx, ctx, val.clone(), None, in_var)?;
130+
let v = parse_ir_value(f, ctx, val.clone(), None, in_var)?;
126131

127132
if *negate {
128133
return Ok(IRValueRef::from_val(make_bool_xor(ctx, v)?))
@@ -132,17 +137,17 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node:
132137
}
133138

134139
ASTTreeNode::StructLRFunction { l, r } => {
135-
let l_val = parse_ir_value(lctx, ctx, l.clone(), None, in_var)?;
140+
let l_val = parse_ir_value(f, ctx, l.clone(), None, in_var)?;
136141
let l_ptr = l_val.as_pointer()?;
137142

138-
return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr), in_var);
143+
return parse_ir_value(f, ctx, r.clone(), Some(l_ptr), in_var);
139144
},
140145

141146
ASTTreeNode::StructLRVariable { l, r } => {
142-
let l_val = parse_ir_value(lctx, ctx, l.clone(), None, in_var)?;
147+
let l_val = parse_ir_value(f, ctx, l.clone(), None, in_var)?;
143148
let l_ptr = l_val.as_pointer()?;
144149

145-
return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr), in_var);
150+
return parse_ir_value(f, ctx, r.clone(), Some(l_ptr), in_var);
146151
}
147152

148153
_ => return Err(PositionlessError::new("The given node cannot be parsed as a value!"))

ir/src/ctx.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{collections::HashMap, mem::transmute, ops::{Add, Deref, DerefMut}, rc:
55
use commons::{err::{PositionlessError, PositionlessResult}, utils::map::HashedMap};
66
use inkwell::{AddressSpace, builder::Builder, context::Context, module::Module, types::{PointerType, VoidType}};
77

8-
use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage, utils::{LateInit, SelfHash}};
8+
use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage, utils::{LateInit, SelfHash}, values::IRValue};
99

1010
/// The global IR context.
1111
/// Basically holds anything related to the current IR compilation (eg: functions, types, global vars)
@@ -66,7 +66,7 @@ impl IRContext {
6666
return self.functions.get(&SelfHash { hash }).is_some() || self.static_vars.get(&SelfHash {hash}).is_some() || self.type_storage.get(hash).is_some();
6767
}
6868

69-
pub fn get_funtion(&self, hash: u64) -> PositionlessResult<Rc<IRFunction>> {
69+
pub fn get_function(&self, hash: u64) -> PositionlessResult<Rc<IRFunction>> {
7070
return match self.functions.get(&SelfHash { hash }) {
7171
Some(v) => Ok(v.clone()),
7272
None => Err(PositionlessError::new(&format!("Invalid function name! Got hash {}", hash)))
@@ -93,12 +93,13 @@ pub struct LocalIRVariable {
9393
/// Holds anything held and created in the given body (eg: vars).
9494
pub struct IRLocalContext {
9595
pub vars: HashedMap<LocalIRVariable>,
96+
pub arguments: HashedMap<IRValue>,
9697
pub current_depth: i64, // Starts at 0 where 0 is function body
9798
}
9899

99100
impl IRLocalContext {
100101
pub fn new() -> Self {
101-
return IRLocalContext { vars: HashedMap::new(0), current_depth: 0 }
102+
return IRLocalContext { vars: HashedMap::new(0), arguments: HashedMap::new(0), current_depth: 0 }
102103
}
103104

104105
/// Attempts to add a variable in the current local context. Will return an error if the operation is impossible
@@ -111,13 +112,29 @@ impl IRLocalContext {
111112
return Ok(true);
112113
}
113114

115+
pub fn add_argument(&mut self, hash: u64, val: IRValue) -> PositionlessResult<bool> {
116+
if self.arguments.get(hash).is_some() {
117+
return Err(PositionlessError::new(&format!("Argument named {} is already present in the current scope!", hash)))
118+
}
119+
120+
self.arguments.put(hash, val);
121+
return Ok(true);
122+
}
123+
114124
pub fn get_variable(&self, hash: u64) -> PositionlessResult<&IRPointer> {
115125
return match self.vars.get(hash) {
116126
Some(v) => Ok(&v.ptr),
117127
None => return Err(PositionlessError::new(&format!("Invalid variable hash {}", hash)))
118128
};
119129
}
120130

131+
pub fn get_argument(&self, hash: u64) -> PositionlessResult<&IRValue> {
132+
return match self.arguments.get(hash) {
133+
Some(v) => Ok(v),
134+
None => return Err(PositionlessError::new(&format!("Invalid argument hash {}", hash)))
135+
}
136+
}
137+
121138
pub fn increment_body_depth(&mut self) {
122139
self.current_depth += 1;
123140
}

0 commit comments

Comments
 (0)