Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions examples/fib.qf
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 3 additions & 3 deletions ir/src/conv/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub fn parse_if_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box<A

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

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

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

Expand All @@ -55,7 +55,7 @@ pub fn parse_if_statement_ir(func: &mut IRFunction, ctx: &IRContext, node: Box<A
ASTTreeNode::IfElseStatement { cond, body } => {
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,
Expand Down Expand Up @@ -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);
Expand Down
57 changes: 36 additions & 21 deletions ir/src/conv/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ASTTreeNode>) -> PositionlessResult<Rc<IRFunction>> {
if let ASTTreeNode::ShadowFunctionDeclaration { func_name, args, returnType } = *node {
Expand All @@ -12,22 +12,22 @@ pub fn parse_ir_shadow_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>
None => None
};

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

for k in args {
let t = match ctx.type_storage.get(k.argument_type) {
Some(v) => v,
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)?;
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!"));
Expand All @@ -40,18 +40,26 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> Po
None => None
};

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

for k in args {
let t = match ctx.type_storage.get(k.argument_type) {
Some(v) => v,
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 func = IRFunction::create(ctx, func_name.val,func_name.hash, &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)?;
Expand All @@ -63,9 +71,9 @@ pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> Po
};
}

ctx.add_function(func_name.hash, func);
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!"));
Expand All @@ -83,21 +91,28 @@ pub fn parse_ir_body(ctx: &IRContext, func: &mut IRFunction, nodes: Vec<Box<ASTT
return Ok(true);
}

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

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

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 ret =func.call(ctx, arguments, grab_result)?;
let ret;

if ff.hash == f.hash {
ret = f.call(ctx, arguments, grab_result)?;
} else {
let func = ctx.get_function(ff.hash)?;

ret = func.call(ctx, arguments, grab_result)?;
}

if !grab_result || ret.is_none() {
return Ok(None);
Expand All @@ -120,7 +135,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
};
Expand All @@ -135,19 +150,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)
},
Expand All @@ -159,7 +174,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));

Expand All @@ -179,7 +194,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);
}

Expand Down
33 changes: 19 additions & 14 deletions ir/src/conv/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ 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<ASTTreeNode>, left: Option<IRPointer>, in_var: bool) -> PositionlessResult<IRValueRef> {
pub fn parse_ir_value<'a>(f: Option<&IRFunction>, ctx: &IRContext, node: Box<ASTTreeNode>, left: Option<IRPointer>, in_var: bool) -> PositionlessResult<IRValueRef> {
match node.as_ref() {
ASTTreeNode::IntegerLit { val: v, hash} => {
let t = ctx.type_storage.get(*hash);
Expand Down Expand Up @@ -62,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!"));
Expand All @@ -83,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();

Expand Down Expand Up @@ -113,16 +118,16 @@ 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())?;

return Ok(IRValueRef::from_val(cmp));
},

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)?))
Expand All @@ -132,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!"))
Expand Down
23 changes: 20 additions & 3 deletions ir/src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<Rc<IRFunction>> {
pub fn get_function(&self, hash: u64) -> PositionlessResult<Rc<IRFunction>> {
return match self.functions.get(&SelfHash { hash }) {
Some(v) => Ok(v.clone()),
None => Err(PositionlessError::new(&format!("Invalid function name! Got hash {}", hash)))
Expand All @@ -93,12 +93,13 @@ pub struct LocalIRVariable {
/// Holds anything held and created in the given body (eg: vars).
pub struct IRLocalContext {
pub vars: HashedMap<LocalIRVariable>,
pub arguments: HashedMap<IRValue>,
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
Expand All @@ -111,13 +112,29 @@ impl IRLocalContext {
return Ok(true);
}

pub fn add_argument(&mut self, hash: u64, val: IRValue) -> PositionlessResult<bool> {
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),
None => return Err(PositionlessError::new(&format!("Invalid variable hash {}", hash)))
};
}

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;
}
Expand Down
Loading