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
49 changes: 41 additions & 8 deletions compiler/astoir_hir/src/ctx.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! The context definitions for the AstoIR HIR layer.

use std::{collections::HashMap};
use std::collections::{HashMap, HashSet};

use astoir_typing::{complete::{ComplexType}, storage::TypeStorage};
use compiler_errors::{IR_ALREADY_EXISTING_ELEM, IR_FIND_ELEMENT, IR_OUTSIDE_ERA_HIGHER, IR_OUTSIDE_ERA_LOWER, errs::{BaseResult, base::BaseError}};
Expand Down Expand Up @@ -62,14 +62,14 @@ impl HIRBranchedContext {
}

/// Introduces a new variable in the current branch era.
pub fn introduce_variable(&mut self, hash: u64, t: ComplexType) -> BaseResult<usize> {
pub fn introduce_variable(&mut self, hash: u64, t: ComplexType, has_default: bool) -> BaseResult<usize> {
let identity = SelfHash { hash };

if self.hash_to_ind.contains_key(&identity) {
return Err(BaseError::err(IR_ALREADY_EXISTING_ELEM!().to_string()));
}

let var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch, variable_type: t };
let var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch, variable_type: t, has_default, introduced_values: HashSet::new() };
self.variables.push(var);

let ind: usize = self.current_element_index;
Expand All @@ -80,6 +80,18 @@ impl HIRBranchedContext {
return Ok(ind);
}

pub fn introduce_variable_assign(&mut self, ind: usize) -> bool {
let var = &mut self.variables[ind];

if var.has_default {
return true;
}

var.introduced_values.insert(self.current_branch);

return true;
}

/// Determines if the element with the given index is still alive in the current branch.
pub fn is_alive(&self, ind: usize) -> bool {
let start_branch = self.variables[ind].introduced_in_era;
Expand All @@ -88,15 +100,17 @@ impl HIRBranchedContext {
return false;
}

if !self.ending_eras.contains_key(&start_branch) {
return self.is_era_alive(start_branch);
}

pub fn is_era_alive(&self, era: usize) -> bool {
if !self.ending_eras.contains_key(&era) {
// If the era hasn't ended yet, (the ending era isn't added for branch start_branch)
// this means that the variable is still alive and we are still inside of the branch start_branch
return true;
}

let end = self.ending_eras[&start_branch];

return end <= self.current_branch;
return false;
}

pub fn is_dropped_before(&self, ind: usize) -> bool {
Expand All @@ -109,6 +123,22 @@ impl HIRBranchedContext {
return self.ending_eras[&start_branch] < self.current_branch;
}

pub fn has_variable_value(&self, ind: usize) -> bool {
let var = &self.variables[ind];

if var.has_default {
return true;
}

for era in var.introduced_values.iter() {
if self.is_era_alive(*era) {
return true;
}
}

return false;
}

pub fn get_ending_era(&self, ind: usize) -> usize {
return self.ending_eras[&self.variables[ind].introduced_in_era];
}
Expand Down Expand Up @@ -140,7 +170,10 @@ impl HIRBranchedContext {
#[derive(Debug)]
pub struct HIRBranchedVariable {
pub introduced_in_era: usize,
pub variable_type: ComplexType
pub variable_type: ComplexType,

pub has_default: bool,
pub introduced_values: HashSet<usize> // TODO: try to potentially reduce this
}

#[derive(Debug)]
Expand Down
9 changes: 9 additions & 0 deletions compiler/astoir_hir/src/nodes.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The nodes inside of the AstoIR HIR.

use astoir_typing::{complete::{ComplexType, ConcreteType}, hashes::{BOOLEAN_TYPE, STATIC_STR}, structs::StructTypeContainer};
use compiler_errors::errs::{BaseResult, base::BaseError};
use lexer::toks::{comp::ComparingOperator, math::MathOperator};

use crate::{ctx::{HIRBranchedContext, HIRContext}, structs::{HIRIfBranch, StructLRUStep}};
Expand Down Expand Up @@ -47,6 +48,14 @@ impl HIRNode {

return false;
}

pub fn as_variable_reference(&self) -> BaseResult<(usize, bool)> {
if let HIRNode::VariableReference { index, is_static } = self {
return Ok((*index, *is_static))
}

return Err(BaseError::err("Tried using as_variable_reference on a non var ref".to_string()))
}

pub fn get_node_type(&self, context: &HIRContext, curr_ctx: &HIRBranchedContext) -> Option<ComplexType> {
match self {
Expand Down
2 changes: 1 addition & 1 deletion compiler/astoir_hir_lowering/src/func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub fn lower_ast_function_declaration(context: &mut HIRContext, node: Box<ASTTre
let branch = curr_ctx.start_branch();

for arg in &arguments {
match curr_ctx.introduce_variable(arg.0, arg.1.clone()) {
match curr_ctx.introduce_variable(arg.0, arg.1.clone(), true) {
Ok(_) => {},
Err(e) => return Err(CompilerError::from_base(e, &node.start, &node.end))
}
Expand Down
3 changes: 2 additions & 1 deletion compiler/astoir_hir_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}};
use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::HIRNode};
use compiler_errors::{IR_INVALID_NODE_TYPE, IR_TYPE_WRONG_KIND, errs::{CompilerResult, ErrorKind, normal::CompilerError}};

use crate::{control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, values::lower_ast_value, var::lower_ast_variable_declaration};
use crate::{control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}};

pub mod literals;
pub mod var;
Expand All @@ -18,6 +18,7 @@ pub fn lower_ast_body_node(context: &mut HIRContext, curr_ctx: &mut HIRBranchedC
match node.kind.clone() {
ASTTreeNodeKind::VarDeclaration { .. } => return lower_ast_variable_declaration(context, curr_ctx, node),
ASTTreeNodeKind::FunctionCall { .. } => return lower_ast_function_call(context, curr_ctx, node),
ASTTreeNodeKind::VarValueChange { .. } => return lower_ast_variable_assign(context, curr_ctx, node),

ASTTreeNodeKind::MathResult { .. } => return lower_ast_math_operation(context, curr_ctx, node, true),

Expand Down
2 changes: 1 addition & 1 deletion compiler/astoir_hir_lowering/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ pub fn lower_ast_value(context: &HIRContext, curr_ctx: &HIRBranchedContext, node
},

ASTTreeNodeKind::VariableReference(_) => {
return lower_ast_variable_reference(context, curr_ctx, node)
return lower_ast_variable_reference(context, curr_ctx, node, true)
},

_ => make_invalid_type_err!(node)
Expand Down
32 changes: 29 additions & 3 deletions compiler/astoir_hir_lowering/src/var.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}};
use astoir_hir::{ctx::{HIRBranchedContext, HIRContext, VariableKind, get_variable}, nodes::HIRNode};
use compiler_errors::{IR_INVALID_NODE_TYPE, IR_VALUE_TYPE_TRANSMUTE, errs::{CompilerResult, ErrorKind, normal::CompilerError}};
use compiler_errors::{IR_INVALID_NODE_TYPE, IR_VALUE_TYPE_TRANSMUTE, VARIABLE_REQ_VALUE, errs::{CompilerResult, ErrorKind, normal::CompilerError}};

use crate::{types::lower_ast_type, values::lower_ast_value};

Expand All @@ -11,7 +11,7 @@ pub fn lower_ast_variable_declaration(context: &HIRContext, curr_ctx: &mut HIRBr
Err(e) => return Err(CompilerError::from_base(e, &node.start, &node.end))
};

let name_ind = match curr_ctx.introduce_variable(var_name.hash, lowered.clone()) {
let name_ind = match curr_ctx.introduce_variable(var_name.hash, lowered.clone(), value.is_some()) {
Ok(v) => v,
Err(e) => return Err(CompilerError::from_base(e, &node.start, &node.end))
};
Expand All @@ -38,7 +38,7 @@ pub fn lower_ast_variable_declaration(context: &HIRContext, curr_ctx: &mut HIRBr
return Err(CompilerError::from_ast(ErrorKind::Error, IR_INVALID_NODE_TYPE!().to_string(), &node.start, &node.end))
}

pub fn lower_ast_variable_reference(context: &HIRContext, curr_ctx: &HIRBranchedContext, node: Box<ASTTreeNode>) -> CompilerResult<Box<HIRNode>> {
pub fn lower_ast_variable_reference(context: &HIRContext, curr_ctx: &HIRBranchedContext, node: Box<ASTTreeNode>, requires_value: bool) -> CompilerResult<Box<HIRNode>> {
if let ASTTreeNodeKind::VariableReference(str) = node.kind.clone() {
let var = match get_variable(context, curr_ctx, str.hash) {
Ok(v) => v,
Expand All @@ -49,8 +49,34 @@ pub fn lower_ast_variable_reference(context: &HIRContext, curr_ctx: &HIRBranched
return Ok(Box::new(HIRNode::VariableReference { index: var.2, is_static: true }))
}

if requires_value {
if !curr_ctx.has_variable_value(var.2) {
return Err(CompilerError::from_ast(ErrorKind::Error, VARIABLE_REQ_VALUE!().to_string(), &node.start, &node.end))
}
}

return Ok(Box::new(HIRNode::VariableReference { index: var.2, is_static: false }))
}

return Err(CompilerError::from_ast(ErrorKind::Error, IR_INVALID_NODE_TYPE!().to_string(), &node.start, &node.end))
}

pub fn lower_ast_variable_assign(context: &HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box<ASTTreeNode>) -> CompilerResult<Box<HIRNode>> {
if let ASTTreeNodeKind::VarValueChange { var, value } = node.kind.clone() {
let value = lower_ast_value(context, curr_ctx, value)?;
let variable_reference = lower_ast_variable_reference(context, curr_ctx, var, false)?;

let var = match variable_reference.as_variable_reference() {
Ok(v) => v,
Err(e) => return Err(CompilerError::from_base(e, &node.start, &node.end))
};

if !var.1 {
curr_ctx.introduce_variable_assign(var.0);
}

return Ok(Box::new(HIRNode::VarAssigment { variable: var.0, val: value }))
}

return Err(CompilerError::from_ast(ErrorKind::Error, IR_INVALID_NODE_TYPE!().to_string(), &node.start, &node.end))
}
7 changes: 7 additions & 0 deletions compiler/compiler_errors/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ macro_rules! IR_REQ_VARIABLE_ASSIGN {
};
}

#[macro_export]
macro_rules! VARIABLE_REQ_VALUE {
() => {
"The variable doesn't have any value here! Every variable must have a value at every point where it is used."
};
}

#[macro_export]
macro_rules! IR_VALUE_TYPE_TRANSMUTE {
() => {
Expand Down
1 change: 1 addition & 0 deletions compiler/compiler_errors/src/errs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct ErrorStorage {

pub fn dump_errors() {
ERR_STORAGE.with_borrow(|f| {

for err in &f.errs {
println!("{}", err.err);

Expand Down
8 changes: 5 additions & 3 deletions compiler/compiler_main/src/cmds/astoir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,18 @@ pub fn parse_astoir_command(arguments: Vec<String>) {

for i in 3..arguments.len() {
let lexer = lexer_parse_file(&arguments[i]).unwrap();
let ast = parse_ast_ctx(&lexer).unwrap();
let ast = parse_ast_ctx(&lexer);

dump_errors();

match level {
IRLevel::HIR => {
let ctx = run_astoir_hir(ast).unwrap();
let ctx = run_astoir_hir(ast.unwrap());
let res_path = arguments[i].clone() + ".qfhir";

dump_errors();

fs::write(res_path, format!("{:#?}", ctx)).unwrap()
fs::write(res_path, format!("{:#?}", ctx.unwrap())).unwrap()
}
}
}
Expand Down
13 changes: 0 additions & 13 deletions examples/test.qf

This file was deleted.