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
6 changes: 4 additions & 2 deletions examples/sample.qf
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
static staticstr bobby = "Hellossssss"

func test() {

shadowfunc printf(ptr str_pointer)

func main() {
printf(bobby)
}
81 changes: 77 additions & 4 deletions ir/src/conv/func.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,39 @@
use std::rc::Rc;

use commons::err::{PositionlessError, PositionlessResult};
use parser::ast::tree::ASTTreeNode;
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, 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};

pub fn parse_ir_function_decl<'a>(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> PositionlessResult<Rc<IRFunction>> {
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 {
let return_type = match returnType {
Some(h) => ctx.type_storage.get(h),
None => None
};

let mut arguments: Vec<Rc<IRType>> = 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);
}

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

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

return Ok(ctx.get_funtion(func_name.hash)?);
}

return Err(PositionlessError::new("Cannot parse ir shadow funtion decl as the node is incompatible!"));
}

pub fn parse_ir_function_decl(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> PositionlessResult<Rc<IRFunction>> {
if let ASTTreeNode::FunctionDeclaration { func_name, args, body, returnType } = *node {
let return_type = match returnType {
Some(h) => ctx.type_storage.get(h),
Expand Down Expand Up @@ -55,7 +83,33 @@ pub fn parse_ir_body(ctx: &IRContext, func: &mut IRFunction, nodes: Vec<Box<ASTT
return Ok(true);
}

pub fn parse_ir_function_body_member<'a>(ctx: &IRContext, func: &mut IRFunction, node: Box<ASTTreeNode>) -> PositionlessResult<bool> {
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 {
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)?);
}

let func = ctx.get_funtion(func.hash)?;

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

if !grab_result || ret.is_none() {
return Ok(None);
}

return Ok(Some(IRValueRef::from_pointer(ret.unwrap())));
}

return Err(PositionlessError::new("Cannot parse ir function call as the node is not a function call"))
}

pub fn parse_ir_function_body_member(ctx: &IRContext, func: &mut IRFunction, node: Box<ASTTreeNode>) -> PositionlessResult<bool> {
match *node {
ASTTreeNode::VarDeclaration { var_name, var_type, value } => {
let var_t = match ctx.type_storage.get(var_type) {
Expand All @@ -80,6 +134,25 @@ pub fn parse_ir_function_body_member<'a>(ctx: &IRContext, func: &mut IRFunction,
return Ok(true);
},

ASTTreeNode::StructLRFunction { .. } => {
parse_ir_value(Some(&func.lctx), ctx, node, None, false)?;

return Ok(true)
},

ASTTreeNode::StructLRVariable { .. } => {
parse_ir_value(Some(&func.lctx), ctx, node, None, false)?;

return Ok(true)
},

ASTTreeNode::FunctionCall { .. } => {
parse_ir_function_call(ctx, &func.lctx, node, None, false)?;

return Ok(true)

}

ASTTreeNode::IfStatement { .. } => {
return parse_if_statement_ir(func, ctx, node);
},
Expand Down
8 changes: 7 additions & 1 deletion ir/src/conv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use commons::err::{PositionlessError, PositionlessResult};
use parser::ast::tree::ASTTreeNode;

use crate::{conv::{func::parse_ir_function_decl, structs::parse_ir_struct_decl, val::parse_ir_value}, ctx::IRContext, irstruct::staticvars::IRStaticVariable, types::STATICSTR_TYPE_HASH};
use crate::{conv::{func::{parse_ir_function_decl, parse_ir_shadow_function_decl}, structs::parse_ir_struct_decl, val::parse_ir_value}, ctx::IRContext, irstruct::staticvars::IRStaticVariable, types::STATICSTR_TYPE_HASH};

pub mod val;
pub mod func;
Expand Down Expand Up @@ -46,6 +46,12 @@ pub fn parse_ir_node_toplevel(ctx: &mut IRContext, node: Box<ASTTreeNode>) -> Po
return Ok(true);
},

ASTTreeNode::ShadowFunctionDeclaration { .. } => {
parse_ir_shadow_function_decl(ctx, node)?;

return Ok(true);
}

ASTTreeNode::StructLayoutDeclaration { .. } => {
parse_ir_struct_decl(ctx, node)?;

Expand Down
54 changes: 18 additions & 36 deletions ir/src/conv/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use commons::err::{PositionlessError, PositionlessResult};
use inkwell::values::BasicValue;
use parser::ast::tree::ASTTreeNode;

use crate::{bools::{make_bool_cmp_int, make_bool_xor}, ctx::{IRContext, IRLocalContext}, irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, math::make_math_operation, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH, typing::OwnedValueEnum}, values::IRValue};
use crate::{bools::{make_bool_cmp_int, make_bool_xor}, conv::func::parse_ir_function_call, ctx::{IRContext, IRLocalContext}, irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, math::make_math_operation, refs::IRValueRef, types::{POINTER_TYPE_HASH, SIGNED64_TYPE_HASH, typing::OwnedValueEnum}, values::IRValue};

pub fn get_variable_ref(lctx: &IRLocalContext, ctx: &IRContext, hash: u64) -> PositionlessResult<IRValueRef> {
match ctx.get_variable(hash) {
Expand All @@ -20,7 +20,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<ASTTreeNode>, left: Option<IRPointer>, in_var_decl: bool) -> PositionlessResult<IRValueRef> {
pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node: Box<ASTTreeNode>, left: Option<IRPointer>, in_var: bool) -> PositionlessResult<IRValueRef> {
match node.as_ref() {
ASTTreeNode::IntegerLit(v) => {
let t = ctx.type_storage.get(SIGNED64_TYPE_HASH);
Expand All @@ -40,7 +40,7 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node:
}


if in_var_decl {
if in_var {
return Ok(IRValueRef::from_tempstr(v.clone()))
}

Expand All @@ -64,41 +64,23 @@ pub fn parse_ir_value<'a>(lctx: Option<&IRLocalContext>, ctx: &IRContext, node:
},

ASTTreeNode::FunctionCall { func, args } => {
let mut arguments = vec![];

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

for arg in &args[0..args.len()] {
arguments.push(parse_ir_value(lctx, ctx, arg.clone(), None, in_var_decl)?);
if lctx.is_none() {
return Err(PositionlessError::new("Cannot use function calls outside of a function!"))
}

let res: Option<IRPointer>;

if left.is_some() {
let t = left.as_ref().unwrap().t.clone();
let descriptor = t.get_structured_type_descriptor()?;

let f = descriptor.get_function(func.hash)?;

res = f.call(ctx, arguments, true)?;
} else {
let f = ctx.get_funtion(func.hash)?;

res = f.call(ctx, arguments, true)?;
}
let k = parse_ir_function_call(ctx, lctx.unwrap(), node, left, in_var)?;

if res.is_none() {
return Err(PositionlessError::new(&format!("Cannot use the result of function {} as a value as it is void!", func.val)));
if k.is_none() {
return Err(PositionlessError::new("Function call returns void! cannot use as a value!"));
}

return Ok(IRValueRef::from_pointer(res.unwrap()));
return Ok(k.unwrap());
},

ASTTreeNode::MathResult { lval, rval, operator, assigns } => {
let left = parse_ir_value(lctx, ctx, lval.clone(), None, in_var_decl)?;
let right = parse_ir_value(lctx, ctx, rval.clone(), None, in_var_decl)?;
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 t = left.get_type();

Expand Down Expand Up @@ -127,16 +109,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_decl)?;
let r_val = parse_ir_value(lctx, ctx, rval.clone(), None, in_var_decl)?;
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 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_decl)?;
let v = parse_ir_value(lctx, ctx, val.clone(), None, in_var)?;

if *negate {
return Ok(IRValueRef::from_val(make_bool_xor(ctx, v)?))
Expand All @@ -146,17 +128,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_decl)?;
let l_val = parse_ir_value(lctx, 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_decl);
return parse_ir_value(lctx, 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_decl)?;
let l_val = parse_ir_value(lctx, 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_decl);
return parse_ir_value(lctx, ctx, r.clone(), Some(l_ptr), in_var);
}

_ => return Err(PositionlessError::new("The given node cannot be parsed as a value!"))
Expand Down
24 changes: 12 additions & 12 deletions ir/src/ctx.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
//! IR context related code

use std::{mem::transmute, ops::{Add, Deref, DerefMut}, rc::Rc};
use std::{collections::HashMap, mem::transmute, ops::{Add, Deref, DerefMut}, rc::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};
use crate::{irstruct::{funcs::IRFunction, ptr::IRPointer, staticvars::IRStaticVariable}, types::storage::IRTypeStorage, utils::{LateInit, SelfHash}};

/// The global IR context.
/// Basically holds anything related to the current IR compilation (eg: functions, types, global vars)
Expand All @@ -19,8 +19,8 @@ pub struct IRContext {

pub type_storage: LateInit<IRTypeStorage>,

pub functions: HashedMap<Rc<IRFunction>>,
pub static_vars: HashedMap<Rc<IRStaticVariable>>
pub functions: HashMap<SelfHash, Rc<IRFunction>>,
pub static_vars: HashMap<SelfHash, Rc<IRStaticVariable>>
}

impl IRContext {
Expand All @@ -34,8 +34,8 @@ impl IRContext {
inkwell_ctx: ctx.clone(),
builder: unsafe { transmute::<Builder, Builder<'static>>(ctx.create_builder()) },
ptr_type,
functions: HashedMap::new(0),
static_vars: HashedMap::new(0),
functions: HashMap::new(),
static_vars: HashMap::new(),
type_storage: LateInit::new(),
void_type,
module
Expand All @@ -51,25 +51,25 @@ impl IRContext {
return Err(PositionlessError::new("There already is an element named like this!"));
}

self.static_vars.put(hash, Rc::new(var));
self.static_vars.insert(SelfHash { hash }, Rc::new(var));
return Ok(true);
}

pub fn get_variable(&self, hash: u64) -> PositionlessResult<Rc<IRStaticVariable>> {
return match self.static_vars.get(hash) {
return match self.static_vars.get(&SelfHash { hash }) {
Some(v) => Ok(v.clone()),
None => return Err(PositionlessError::new("Invalid variable name"))
};
}

pub fn is_key_taken(&self, hash: u64) -> bool {
return self.functions.get(hash).is_some() || self.static_vars.get(hash).is_some() || self.type_storage.get(hash).is_some();
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>> {
return match self.functions.get(hash) {
return match self.functions.get(&SelfHash { hash }) {
Some(v) => Ok(v.clone()),
None => Err(PositionlessError::new("Invalid function name!"))
None => Err(PositionlessError::new(&format!("Invalid function name! Got hash {}", hash)))
}
}

Expand All @@ -78,7 +78,7 @@ impl IRContext {
return Err(PositionlessError::new("There already is an element named like this!"));
}

self.functions.put(hash, Rc::new(func));
self.functions.insert(SelfHash { hash }, Rc::new(func));
return Ok(true);
}

Expand Down
2 changes: 2 additions & 0 deletions lexer/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use commons::Position;

use crate::{LexerParseResult, LexerParsingError, token::{LexerToken, LexerTokenType}, toks::{comp::ComparingOperator, math::MathOperator}};

const SHADOWFUNC_KEYWORD_HASH: u64 = 8856473617513302734;
const FUNC_KEYWORD_HASH: u64 = 17439195341824537259;
const RET_KEYWORD_HASH: u64 = 9222097151127739705;
const VAR_KEYWORD_HASH: u64 = 10000921911505692860;
Expand Down Expand Up @@ -278,6 +279,7 @@ fn parse_keyword(str: &String, ind: &mut usize, start_pos: Position) -> LexerTok

let token_type = match hash {
FUNC_KEYWORD_HASH => LexerTokenType::Function,
SHADOWFUNC_KEYWORD_HASH => LexerTokenType::ShadowFunction,
RET_KEYWORD_HASH => LexerTokenType::Return,
STRUCT_KEYWORD_HASH => LexerTokenType::Struct,
LAYOUT_KEYWORD_HASH => LexerTokenType::Layout,
Expand Down
1 change: 1 addition & 0 deletions lexer/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::{LexerParseResult, LexerParsingError, toks::{comp::ComparingOperator,
pub enum LexerTokenType {
/// Represent the func keyword
Function,
ShadowFunction,

Var,
Struct,
Expand Down
6 changes: 5 additions & 1 deletion parser/src/ast/func/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ pub fn parse_function_call(tokens: &Vec<LexerToken>, ind: &mut usize) -> Positio

while tokens[*ind].tok_type != LexerTokenType::ParenClose {
vals.push(parse_ast_value(tokens, ind)?);


if tokens[*ind].tok_type == LexerTokenType::ParenClose {
break;
}

tokens[*ind].expects(LexerTokenType::Comma)?;

*ind += 1;
Expand Down
Loading