From a8255f355df04c1fc55c0cecbd0e2f4ff56f941a Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Fri, 10 Apr 2026 00:01:42 +0200 Subject: [PATCH 01/60] chore: updated the readmes --- CONTRIBUTING.MD | 4 ++-- README.md | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD index c566105..a0270a6 100644 --- a/CONTRIBUTING.MD +++ b/CONTRIBUTING.MD @@ -14,7 +14,7 @@ git clone https://github.com/Quickfall/quickfall ``` You will need the following installed in order to compile & use Quickfall: -- Rust 1.91.1 -- LLVM 21.1 +- Rust 1.94.1 +- LLVM 22.1 You can then build the project by using the `cargo` Rust tool. \ No newline at end of file diff --git a/README.md b/README.md index ba489f0..fed3dc0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,8 @@ Quickfall is a programming language focusing on allowing everyone to build fast Quickfall aims to give the performance of extremely fast languages like C while giving the safety of Rust and also being reliable. What Quickfall focuses on: -- **Speed**: Quickfall focuses on runtime speed which means that every single compile time safety check can be simply disabled either globally or for a single element. On recent benchmarks, Quickfall has surpassed C in terms of runtime speed by up to 25%! +- **Speed**: Quickfall focuses on runtime speed which means that every single compile time safety check can be simply disabled either globally or for a single element. +- **Feature filled**: Quickfall gives multiple useful features to build reliable software such as enums or arbitrary size types - **Strict syntax**: Quickfall enforces a strict syntax to avoid mistakes or error prone code - **Safety**: Quickfall enforces strict safety features on compile time and optional ones on runtime that can be easily disabled to allow for the highest safety or speed depending on the build -- **Thread safety**: Quickfall gives tools to enforce thread safety mostly on compile time such as the *thread markers* to identify and restrict variables to only certain threads +- **Mutlipurpose**: Quickfall can both be used to build low level and high level software with different level of tools. From 41264a0b0d00a689ebb20a464eddef42a430e094 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Fri, 10 Apr 2026 00:30:14 +0200 Subject: [PATCH 02/60] feat: added use statement AST --- compiler/ast/src/tree.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 0ceb502..1fbce9c 100644 --- a/compiler/ast/src/tree.rs +++ b/compiler/ast/src/tree.rs @@ -29,6 +29,8 @@ pub enum ASTTreeNodeKind { IntegerLit { val: i128, hash: u64 }, StringLit(String), + UseStatement { shards: Vec, use_clauses: Vec }, + ThisStructParam, UnwrapCondition { original: Box, target_type: ASTType, unsafe_unwrap: bool, target_var: Option }, @@ -166,6 +168,7 @@ impl Display for ASTTreeNode { impl Display for ASTTreeNodeKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { + Self::UseStatement { .. } => "use statement", Self::UnwrapCondition { .. } | Self::UnwrapValue { .. } => "unwrap", Self::IntegerLit { .. } => "integer literal", Self::StringLit(_) => "string literal", From 7684b3c05d910ae9c374d97335dd5cbfff9b82e3 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:21:42 +0200 Subject: [PATCH 03/60] feat: added use statement handling in parser context --- compiler/ast/src/ctx.rs | 3 +- compiler/ast/src/tree.rs | 2 +- compiler/ast_parser/src/lib.rs | 8 ++++- compiler/ast_parser/src/use_statements.rs | 42 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 compiler/ast_parser/src/use_statements.rs diff --git a/compiler/ast/src/ctx.rs b/compiler/ast/src/ctx.rs index 02a4d99..0b5ed02 100644 --- a/compiler/ast/src/ctx.rs +++ b/compiler/ast/src/ctx.rs @@ -5,12 +5,13 @@ use crate::tree::ASTTreeNode; #[derive(Debug)] pub struct ParserCtx { pub map: HashMap>, + pub uses: Vec>, pub iter_order: Vec } impl ParserCtx { pub fn new() -> Self { - return ParserCtx { map: HashMap::new(), iter_order: Vec::new() } + return ParserCtx { map: HashMap::new(), iter_order: Vec::new(), uses: vec![] } } pub fn insert(&mut self, name: String, node: Box) -> bool { diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 1fbce9c..387d1ab 100644 --- a/compiler/ast/src/tree.rs +++ b/compiler/ast/src/tree.rs @@ -29,7 +29,7 @@ pub enum ASTTreeNodeKind { IntegerLit { val: i128, hash: u64 }, StringLit(String), - UseStatement { shards: Vec, use_clauses: Vec }, + UseStatement { shards: Vec, use_clauses: Vec }, ThisStructParam, diff --git a/compiler/ast_parser/src/lib.rs b/compiler/ast_parser/src/lib.rs index 7bddedf..6be0672 100644 --- a/compiler/ast_parser/src/lib.rs +++ b/compiler/ast_parser/src/lib.rs @@ -2,7 +2,7 @@ //! The parser for the Quickfall AST //! -use ast::ctx::ParserCtx; +use ast::{ctx::ParserCtx, tree::ASTTreeNodeKind}; use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; use lexer::token::{LexerToken, LexerTokenType}; @@ -19,6 +19,7 @@ pub mod variables; pub mod types; pub mod arrays; pub mod unwraps; +pub mod use_statements; pub fn parse_ast_ctx(tokens: &Vec) -> DiagnosticResult { let mut ind = 0; @@ -28,6 +29,11 @@ pub fn parse_ast_ctx(tokens: &Vec) -> DiagnosticResult { while tokens[ind].tok_type != LexerTokenType::EndOfFile { let node = parse_ast_node(tokens, &mut ind)?; + if let ASTTreeNodeKind::UseStatement { .. } = node.kind { + ctx.uses.push(node); + continue; + } + if !node.kind.is_tree_permissible() { return Err(make_unexpected_simple_error(&*node, &node).into()) } diff --git a/compiler/ast_parser/src/use_statements.rs b/compiler/ast_parser/src/use_statements.rs new file mode 100644 index 0000000..3059458 --- /dev/null +++ b/compiler/ast_parser/src/use_statements.rs @@ -0,0 +1,42 @@ +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; +use compiler_utils::hash::HashedString; +use diagnostics::DiagnosticResult; +use lexer::token::{LexerToken, LexerTokenType}; + +pub fn parse_use_statement(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); + + *ind += 1; + + let mut steps = vec![]; + let mut uses = vec![]; + + while tokens[*ind].is_keyword() { + let kwd = tokens[*ind].expects_keyword()?; + *ind += 1; + + steps.push(HashedString::new(kwd.0)); + + tokens[*ind].expects(LexerTokenType::Collon)?; + *ind += 1; + } + + tokens[*ind].expects(LexerTokenType::ArrayOpen)?; + + while tokens[*ind].is_keyword() { + let kwd = tokens[*ind].expects_keyword()?; + *ind += 1; + + uses.push(HashedString::new(kwd.0)); + + if tokens[*ind].tok_type == LexerTokenType::ArrayClose { + break; + } + + tokens[*ind].expects(LexerTokenType::Comma)?; + } + + *ind += 1; + + return Ok((Box::new(ASTTreeNode::new(ASTTreeNodeKind::UseStatement { shards: steps, use_clauses: uses }, start, tokens[*ind].get_end_pos())))) +} \ No newline at end of file From d8a9e2d976e30771d9e90ab7f78c705a80725858 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:36:06 +0200 Subject: [PATCH 04/60] feat: added basic handling for use statements --- Cargo.lock | 2 ++ compiler/astoir_hir_lowering/Cargo.toml | 4 ++- compiler/astoir_hir_lowering/src/lib.rs | 7 ++++- compiler/astoir_hir_lowering/src/uses.rs | 34 ++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 compiler/astoir_hir_lowering/src/uses.rs diff --git a/Cargo.lock b/Cargo.lock index 4f8edcd..5009a10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,10 +56,12 @@ name = "astoir_hir_lowering" version = "0.1.0" dependencies = [ "ast", + "ast_parser", "astoir_hir", "compiler_typing", "compiler_utils", "diagnostics", + "lexer", ] [[package]] diff --git a/compiler/astoir_hir_lowering/Cargo.toml b/compiler/astoir_hir_lowering/Cargo.toml index c3a60e4..2d35609 100644 --- a/compiler/astoir_hir_lowering/Cargo.toml +++ b/compiler/astoir_hir_lowering/Cargo.toml @@ -8,4 +8,6 @@ astoir_hir = { path = "../astoir_hir" } compiler_typing = { path = "../compiler_typing" } ast = { path = "../ast" } diagnostics = { path = "../diagnostics" } -compiler_utils = { path = "../compiler_utils" } \ No newline at end of file +compiler_utils = { path = "../compiler_utils" } +lexer = { path = "../lexer" } +ast_parser = { path = "../ast_parser" } \ No newline at end of file diff --git a/compiler/astoir_hir_lowering/src/lib.rs b/compiler/astoir_hir_lowering/src/lib.rs index b0df1df..e0deed9 100644 --- a/compiler/astoir_hir_lowering/src/lib.rs +++ b/compiler/astoir_hir_lowering/src/lib.rs @@ -2,7 +2,7 @@ use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos}; -use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, enums::lower_ast_enum, 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}}; +use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, enums::lower_ast_enum, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, uses::handle_ast_use_statement, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}}; pub mod literals; pub mod var; @@ -16,6 +16,7 @@ pub mod structs; pub mod arrays; pub mod unwraps; pub mod enums; +pub mod uses; pub fn lower_ast_body_node(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { move_current_diagnostic_pos(node.get_pos()); @@ -106,6 +107,10 @@ pub fn lower_ast_toplevel(context: &mut HIRContext, node: Box) -> D pub fn lower_ast(ctx: ParserCtx) -> DiagnosticResult { let mut hir_ctx = HIRContext::new(); + for u in ctx.uses { + handle_ast_use_statement(&mut hir_ctx, u)?; + } + for s in ctx.iter_order { let k = ctx.map[&s].clone(); diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs new file mode 100644 index 0000000..dc10a3b --- /dev/null +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -0,0 +1,34 @@ +use std::path::{MAIN_SEPARATOR_STR}; + +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; +use ast_parser::parse_ast_ctx; +use astoir_hir::{ctx::HIRContext}; +use diagnostics::{MaybeDiagnostic}; +use lexer::lexer::lexer_parse_file; + +use crate::{lower_ast_toplevel}; + +pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box) -> MaybeDiagnostic { + if let ASTTreeNodeKind::UseStatement { shards, use_clauses } = node.kind.clone() { + let mut path = ".".to_string(); + + for shard in shards { + path += &MAIN_SEPARATOR_STR .to_owned(); + path += &shard.val; + } + + path += &".qf"; + + let lexer = lexer_parse_file(&path)?; + let ast = parse_ast_ctx(&lexer)?; + + for clause in use_clauses { + if ast.map.contains_key(&clause.val) { + lower_ast_toplevel(context, ast.map[&clause.val].clone())?; + } + } + + } + + panic!("Invalid node") +} \ No newline at end of file From dbbd56a1302e1d222a331b0c662846c0734fc359 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Fri, 10 Apr 2026 01:50:11 +0200 Subject: [PATCH 05/60] feat: got use statements working --- compiler/ast_parser/src/parser.rs | 6 +++++- compiler/ast_parser/src/use_statements.rs | 1 + compiler/astoir_hir_lowering/src/uses.rs | 9 ++++++--- compiler/diagnostics/src/builders.rs | 6 +++++- compiler/diagnostics/src/errors.rs | 3 ++- compiler/lexer/src/lexer.rs | 2 ++ compiler/lexer/src/token.rs | 3 +++ 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/compiler/ast_parser/src/parser.rs b/compiler/ast_parser/src/parser.rs index 58e0028..1fbf7c8 100644 --- a/compiler/ast_parser/src/parser.rs +++ b/compiler/ast_parser/src/parser.rs @@ -3,7 +3,7 @@ use compiler_utils::hash::HashedString; use diagnostics::{DiagnosticResult, builders::{make_unexpected_simple_error, make_unused_variable}}; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{control::{for_loop::parse_for_loop, if_else::parse_if_statement, while_block::parse_while_block}, functions::{parse_function_call, parse_function_declaraction, returns::parse_function_return_statement, shadow::parse_shadow_function_declaration}, structs::{enums::parse_enum_declaration, parse_type_declaration}, value::parse_ast_value_post_l, variables::{decl::parse_variable_declaration, static_decl::parse_static_variable_declaration}}; +use crate::{control::{for_loop::parse_for_loop, if_else::parse_if_statement, while_block::parse_while_block}, functions::{parse_function_call, parse_function_declaraction, returns::parse_function_return_statement, shadow::parse_shadow_function_declaration}, structs::{enums::parse_enum_declaration, parse_type_declaration}, use_statements::parse_use_statement, value::parse_ast_value_post_l, variables::{decl::parse_variable_declaration, static_decl::parse_static_variable_declaration}}; /// Parses an AST node outside of any other node. /// @@ -38,6 +38,10 @@ pub fn parse_ast_node(tokens: &Vec, ind: &mut usize) -> DiagnosticRe return parse_enum_declaration(tokens, ind); }, + LexerTokenType::Use => { + return parse_use_statement(tokens, ind); + } + _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) } } diff --git a/compiler/ast_parser/src/use_statements.rs b/compiler/ast_parser/src/use_statements.rs index 3059458..3266281 100644 --- a/compiler/ast_parser/src/use_statements.rs +++ b/compiler/ast_parser/src/use_statements.rs @@ -22,6 +22,7 @@ pub fn parse_use_statement(tokens: &Vec, ind: &mut usize) -> Diagnos } tokens[*ind].expects(LexerTokenType::ArrayOpen)?; + *ind += 1; while tokens[*ind].is_keyword() { let kwd = tokens[*ind].expects_keyword()?; diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index dc10a3b..95d8205 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -3,7 +3,7 @@ use std::path::{MAIN_SEPARATOR_STR}; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use ast_parser::parse_ast_ctx; use astoir_hir::{ctx::HIRContext}; -use diagnostics::{MaybeDiagnostic}; +use diagnostics::{MaybeDiagnostic, builders::make_use_not_found}; use lexer::lexer::lexer_parse_file; use crate::{lower_ast_toplevel}; @@ -23,11 +23,14 @@ pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box let ast = parse_ast_ctx(&lexer)?; for clause in use_clauses { - if ast.map.contains_key(&clause.val) { - lower_ast_toplevel(context, ast.map[&clause.val].clone())?; + if !ast.map.contains_key(&clause.val) { + return Err(make_use_not_found(&*node, &clause.val, &path).into()) } + + lower_ast_toplevel(context, ast.map[&clause.val].clone())?; } + return Ok(()) } panic!("Invalid node") diff --git a/compiler/diagnostics/src/builders.rs b/compiler/diagnostics/src/builders.rs index 7333a0c..36edf54 100644 --- a/compiler/diagnostics/src/builders.rs +++ b/compiler/diagnostics/src/builders.rs @@ -1,6 +1,6 @@ use std::{fmt::Display}; -use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; +use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, NOT_FOUND_USE, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; pub fn make_expected_simple_error(origin: &K, expected: &E, got: &G) -> Diagnostic { origin.make_simple_diagnostic(EXPECTED_TOKEN.0, Level::Error, format!("expected {} but got {}", expected, got), None, vec![], vec![], vec![]) @@ -184,4 +184,8 @@ pub fn make_req_type_kind(origin: &K, t: &T pub fn make_type_not_partof(origin: &K, a: &A, b: &B) -> Diagnostic { origin.make_simple_diagnostic(TYPE_NOT_PART.0, Level::Error, format!("type {} is not part of type {}", a, b), None, vec![], vec![], vec![]) +} + +pub fn make_use_not_found(origin: &K, element: &E, path: &P) -> Diagnostic { + origin.make_simple_diagnostic(NOT_FOUND_USE.0, Level::Error, format!("element {} was not found in {}", element, path), None, vec![], vec![], vec![]) } \ No newline at end of file diff --git a/compiler/diagnostics/src/errors.rs b/compiler/diagnostics/src/errors.rs index ac2c27d..d337b1d 100644 --- a/compiler/diagnostics/src/errors.rs +++ b/compiler/diagnostics/src/errors.rs @@ -40,4 +40,5 @@ declare_error!(IR_INSTRUCTION_HELD_VAL, 29, "cannot extract held value from inst // Misc declare_error!(INVALID_TYPE_REQ, 30, "this operation requires a {} type"); -declare_error!(TYPE_NOT_PART, 31, "type {} is not part of type {}"); \ No newline at end of file +declare_error!(TYPE_NOT_PART, 31, "type {} is not part of type {}"); +declare_error!(NOT_FOUND_USE, 32, "element {} was not found in {}"); \ No newline at end of file diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index c13537d..7730959 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -30,6 +30,7 @@ const NEW_KEYWORD_HASH: u64 = hash!("new"); const UNWRAP_KEYWORD_HASH: u64 = hash!("unwrap"); const UNWRAP_UNSAFE_KEYWORD_HASH: u64 = hash!("unsafe_unwrap"); const ENUM_KEYWORD_HASH: u64 = hash!("enum"); +const USE_KEYWORD_HASH: u64 = hash!("use"); /// Parses a file into a set of lexer tokens. /// @@ -375,6 +376,7 @@ fn parse_keyword(str: &String, ind: &mut usize, start_pos: Position) -> LexerTok UNWRAP_KEYWORD_HASH => LexerTokenType::Unwrap, UNWRAP_UNSAFE_KEYWORD_HASH => LexerTokenType::UnwrapUnsafe, ENUM_KEYWORD_HASH => LexerTokenType::Enum, + USE_KEYWORD_HASH => LexerTokenType::Use, _ => LexerTokenType::Keyword(slice.to_string(), hash) }; diff --git a/compiler/lexer/src/token.rs b/compiler/lexer/src/token.rs index c3a1a35..f700669 100644 --- a/compiler/lexer/src/token.rs +++ b/compiler/lexer/src/token.rs @@ -22,6 +22,8 @@ pub enum LexerTokenType { Unwrap, UnwrapUnsafe, + Use, + Var, Struct, Layout, @@ -226,6 +228,7 @@ impl Display for LexerTokenType { Self::True => "true", Self::While => "while", Self::Unwrap => "unwrap", + Self::Use => "use", Self::UnwrapUnsafe => "unsafe_unwrap" }; From 385f340e337c43c63cd596435122e60736bbb08c Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 13 Apr 2026 23:10:32 +0200 Subject: [PATCH 06/60] push --- compiler/ast_parser/src/parser.rs | 2 +- compiler/ast_parser/src/use_statements.rs | 1 + compiler/astoir_hir_lowering/src/uses.rs | 45 ++++++++++++++++++++++- compiler/astoir_mir_lowering/src/vars.rs | 9 +++++ compiler/lexer/src/lexer.rs | 2 +- 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/compiler/ast_parser/src/parser.rs b/compiler/ast_parser/src/parser.rs index 1fbf7c8..08586a0 100644 --- a/compiler/ast_parser/src/parser.rs +++ b/compiler/ast_parser/src/parser.rs @@ -47,7 +47,7 @@ pub fn parse_ast_node(tokens: &Vec, ind: &mut usize) -> DiagnosticRe } /// Parses an AST node inside of another compatible node (functions, control bodies) -pub fn parse_ast_node_in_body(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { +pub fn parse_ast_node_in_body(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { match &tokens[*ind].tok_type { LexerTokenType::Var => { diff --git a/compiler/ast_parser/src/use_statements.rs b/compiler/ast_parser/src/use_statements.rs index 3266281..e14f326 100644 --- a/compiler/ast_parser/src/use_statements.rs +++ b/compiler/ast_parser/src/use_statements.rs @@ -35,6 +35,7 @@ pub fn parse_use_statement(tokens: &Vec, ind: &mut usize) -> Diagnos } tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; } *ind += 1; diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 95d8205..6b7a7fe 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -6,7 +6,38 @@ use astoir_hir::{ctx::HIRContext}; use diagnostics::{MaybeDiagnostic, builders::make_use_not_found}; use lexer::lexer::lexer_parse_file; -use crate::{lower_ast_toplevel}; +use crate::{lower_ast_toplevel, types::lower_ast_type}; + +pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Box) -> MaybeDiagnostic { + if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, body: _, return_type, requires_this: _ } = node.kind.clone() { + let ret_type; + + if return_type.is_some() { + let lower = lower_ast_type(context, return_type.unwrap(), &*node)?; + + ret_type = Some(lower) + } else { + ret_type = None; + } + + let mut arguments = vec![]; + let mut types = vec![]; + + for arg in args { + types.push(arg.argument_type.clone()); + let t = lower_ast_type(context, arg.argument_type, &*node)?; + + arguments.push((arg.name.hash, t)); + } + + context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); + context.function_contexts.push(None); + + return Ok(()) + } + + panic!("Invalid node") +} pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box) -> MaybeDiagnostic { if let ASTTreeNodeKind::UseStatement { shards, use_clauses } = node.kind.clone() { @@ -27,7 +58,17 @@ pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box return Err(make_use_not_found(&*node, &clause.val, &path).into()) } - lower_ast_toplevel(context, ast.map[&clause.val].clone())?; + let n = ast.map[&clause.val].clone(); + + match n.kind { + ASTTreeNodeKind::FunctionDeclaration { .. } => { + handle_ast_use_statement_function_decl(context, n.clone())?; + } + _ => { + println!(" --> {:#?}", n); + lower_ast_toplevel(context, n.clone())?; + } + }; } return Ok(()) diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index fc6ab3f..dd1816e 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -10,6 +10,15 @@ use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; pub fn lower_hir_variable_declaration(block_id: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { if let HIRNodeKind::VarDeclaration { variable, var_type, default_val } = node.clone().kind { let func = ctx.mir_ctx.block_to_func[&block_id]; + + println!("Func {}", func); + + for i in 0..ctx.hir_ctx.function_contexts.len() { + println!("Func {}: {:#?}", i, ctx.hir_ctx.function_contexts[i]) + } + + + let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); if local_ctx.is_eligible_for_ssa(variable) { diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index 7730959..8c6d965 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -208,7 +208,7 @@ fn parse_math_operator(contents: &String, ind: &mut usize, start_pos: Position) *ind += 1; if contents.chars().nth(*ind).unwrap() != '=' { - return Ok(LexerToken::make_single_sized(start_pos, LexerTokenType::Asterisk)); + return Ok(LexerToken::make_single_sized(start_pos, LexerTokenType::EqualSign)); } let assigns = match contents.chars().nth(*ind) { From dfd421eec511866e19de0189e699d3b96e551e69 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 13 Apr 2026 23:48:36 +0200 Subject: [PATCH 07/60] feat: made function work --- compiler/astoir_hir_lowering/src/uses.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 6b7a7fe..38d5f55 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -2,7 +2,7 @@ use std::path::{MAIN_SEPARATOR_STR}; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use ast_parser::parse_ast_ctx; -use astoir_hir::{ctx::HIRContext}; +use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}}; use diagnostics::{MaybeDiagnostic, builders::make_use_not_found}; use lexer::lexer::lexer_parse_file; @@ -30,9 +30,14 @@ pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Bo arguments.push((arg.name.hash, t)); } - context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); + let func_name = context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); context.function_contexts.push(None); + // Fabricate shadow func statement to satisfy functions_declarations + + let node = HIRNode::new(HIRNodeKind::ShadowFunctionDeclaration { func_name, arguments, return_type: ret_type }, &node.start, &node.end); + context.function_declarations.push(Some(Box::new(node))); + return Ok(()) } @@ -65,7 +70,6 @@ pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box handle_ast_use_statement_function_decl(context, n.clone())?; } _ => { - println!(" --> {:#?}", n); lower_ast_toplevel(context, n.clone())?; } }; From a6a5aa617a5ad46f7482745ac840a2882c997926 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:05:50 +0200 Subject: [PATCH 08/60] feat: made using use functions easier with auto type importing --- compiler/astoir_hir_lowering/src/uses.rs | 92 +++++++++++++++++++++--- compiler/astoir_mir_lowering/src/vars.rs | 8 --- 2 files changed, 82 insertions(+), 18 deletions(-) diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 38d5f55..6c3d7a0 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -1,19 +1,21 @@ use std::path::{MAIN_SEPARATOR_STR}; -use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; +use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType}; use ast_parser::parse_ast_ctx; use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}}; -use diagnostics::{MaybeDiagnostic, builders::make_use_not_found}; +use compiler_typing::{raw::RawType, tree::Type}; +use compiler_utils::hash::HashedString; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_cannot_find_type, make_diff_type_specifiers, make_req_type_kind, make_use_not_found}}; use lexer::lexer::lexer_parse_file; -use crate::{lower_ast_toplevel, types::lower_ast_type}; +use crate::{lower_ast_toplevel, structs::lower_ast_struct_declaration, types::{lower_ast_type, lower_ast_type_struct, lower_sized_base_type}, values::lower_ast_value}; -pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Box) -> MaybeDiagnostic { +pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Box, ctx: &ParserCtx) -> MaybeDiagnostic { if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, body: _, return_type, requires_this: _ } = node.kind.clone() { let ret_type; if return_type.is_some() { - let lower = lower_ast_type(context, return_type.unwrap(), &*node)?; + let lower = lower_ast_type_use_statement(context, return_type.unwrap(), &*node, ctx)?; ret_type = Some(lower) } else { @@ -25,10 +27,10 @@ pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Bo for arg in args { types.push(arg.argument_type.clone()); - let t = lower_ast_type(context, arg.argument_type, &*node)?; + let t = lower_ast_type_use_statement(context, arg.argument_type, &*node, ctx)?; arguments.push((arg.name.hash, t)); - } + } let func_name = context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); context.function_contexts.push(None); @@ -36,7 +38,7 @@ pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Bo // Fabricate shadow func statement to satisfy functions_declarations let node = HIRNode::new(HIRNodeKind::ShadowFunctionDeclaration { func_name, arguments, return_type: ret_type }, &node.start, &node.end); - context.function_declarations.push(Some(Box::new(node))); + context.function_declarations.push(Some(Box::new(node))); return Ok(()) } @@ -67,7 +69,7 @@ pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box match n.kind { ASTTreeNodeKind::FunctionDeclaration { .. } => { - handle_ast_use_statement_function_decl(context, n.clone())?; + handle_ast_use_statement_function_decl(context, n.clone(), &ast)?; } _ => { lower_ast_toplevel(context, n.clone())?; @@ -79,4 +81,74 @@ pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box } panic!("Invalid node") -} \ No newline at end of file +} + +pub fn gather_type_use(context: &mut HIRContext, val: HashedString, origin: &K, pass: bool, ctx: &ParserCtx) -> DiagnosticResult { + match context.type_storage.get_type(val.hash) { + Ok(v) => return Ok(v), + Err(_) => { + if pass { + if ctx.map.contains_key(&val.val) { + lower_ast_struct_declaration(context, ctx.map[&val.val].clone())?; + + return gather_type_use(context, val, origin, false, ctx); + } + } + + return Err(make_cannot_find_type(origin, &val.val).into()) + } + } +} + +pub fn lower_ast_type_use_statement(context: &mut HIRContext, t: ASTType, origin: &K, ctx: &ParserCtx) -> DiagnosticResult { + return match t { + ASTType::Generic(type_id, type_params, size_params, specifier) => { + let val = HashedString::new(type_id.clone()); + let hash = val.hash; + + let mut t = gather_type_use(context, val, origin, true, ctx)?; + + if specifier.is_some() { + let container = match t { + RawType::Enum(v) => v, + _ => return Err(make_req_type_kind(origin, &"enum".to_string()).into()) + }; + + t = container.get_entry(HashedString::new(specifier.unwrap()))? + } + + if t.get_type_params_count(&context.type_storage) != type_params.len() { + return Err(make_diff_type_specifiers(origin, &type_params.len(), &t.get_type_params_count(&context.type_storage)).into()) + } + + let mut t_params = vec![]; + + for type_param in type_params { + t_params.push(Box::new(lower_ast_type(context, *type_param, origin)?)); + } + + let res = Type::Generic(t.clone(), t_params, size_params); + + if t.is_sized() { + let lower = lower_sized_base_type(context, &res, origin)?; + + if context.type_storage.type_to_ind.contains_key(&lower) { + return Ok(Type::Generic(t, vec![], vec![])); + } else { + let ind = match context.type_storage.append_with_hash(hash, lower) { + Ok(v) => v, + Err(_) => panic!("Generic lowering type cannot be found on type_to_hash") + }; + + return Ok(Type::Generic(context.type_storage.types.vals[ind].clone(), vec![], vec![])) + } + } + + return Ok(res); + }, + + ASTType::Pointer(array, inner) => Ok(Type::Pointer(array, Box::new(lower_ast_type(context, *inner, origin)?))), + ASTType::Reference(inner) => Ok(Type::Reference(Box::new(lower_ast_type(context, *inner, origin)?))), + ASTType::Array(size, inner) => Ok(Type::Array(size, Box::new(lower_ast_type(context, *inner, origin)?))) + }; +} diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index dd1816e..391ffb2 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -10,15 +10,7 @@ use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; pub fn lower_hir_variable_declaration(block_id: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { if let HIRNodeKind::VarDeclaration { variable, var_type, default_val } = node.clone().kind { let func = ctx.mir_ctx.block_to_func[&block_id]; - - println!("Func {}", func); - for i in 0..ctx.hir_ctx.function_contexts.len() { - println!("Func {}: {:#?}", i, ctx.hir_ctx.function_contexts[i]) - } - - - let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); if local_ctx.is_eligible_for_ssa(variable) { From 40482a605d448563374b2e9479b4447d62e57b54 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:13:06 +0200 Subject: [PATCH 09/60] feat: update workflow --- .github/workflows/rust.yml | 5 +++++ compiler/astoir_hir_lowering/src/bools.rs | 2 +- compiler/astoir_hir_lowering/src/structs.rs | 8 ++++---- compiler/astoir_hir_lowering/src/types.rs | 2 +- compiler/astoir_hir_lowering/src/uses.rs | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8564c7b..74b2828 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -12,6 +12,11 @@ jobs: runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install LLVM + run: sudo apt install llvm + steps: - uses: actions/checkout@v4 - name: Build diff --git a/compiler/astoir_hir_lowering/src/bools.rs b/compiler/astoir_hir_lowering/src/bools.rs index b88d345..16c97e3 100644 --- a/compiler/astoir_hir_lowering/src/bools.rs +++ b/compiler/astoir_hir_lowering/src/bools.rs @@ -1,6 +1,6 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; -use compiler_typing::{raw::RawType, storage::BOOLEAN_TYPE, tree::Type}; +use compiler_typing::{raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult}; use crate::values::lower_ast_value; diff --git a/compiler/astoir_hir_lowering/src/structs.rs b/compiler/astoir_hir_lowering/src/structs.rs index 242b078..4380d57 100644 --- a/compiler/astoir_hir_lowering/src/structs.rs +++ b/compiler/astoir_hir_lowering/src/structs.rs @@ -2,11 +2,11 @@ use std::collections::HashMap; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, structs::HIRStructContainer}; -use compiler_typing::{raw::RawType, structs::RawStructTypeContainer, tree::Type}; -use compiler_utils::{hash::{HashedString, SelfHash}, utils::indexed::IndexStorage}; -use diagnostics::{DiagnosticResult, builders::{make_already_in_scope, make_cannot_find_type, make_struct_init_missing_field, make_struct_missing_field}}; +use compiler_typing::{raw::RawType, structs::RawStructTypeContainer}; +use compiler_utils::utils::indexed::IndexStorage; +use diagnostics::{DiagnosticResult, builders::make_already_in_scope}; -use crate::{lower_ast_body, types::{lower_ast_type, lower_ast_type_struct}, values::lower_ast_value}; +use crate::{lower_ast_body, types::lower_ast_type_struct, values::lower_ast_value}; fn lower_ast_struct_member(context: &mut HIRContext, node: Box, container: &mut RawStructTypeContainer) -> DiagnosticResult { if let ASTTreeNodeKind::StructFieldMember { name, member_type } = node.kind.clone() { diff --git a/compiler/astoir_hir_lowering/src/types.rs b/compiler/astoir_hir_lowering/src/types.rs index ad9c149..4a807f7 100644 --- a/compiler/astoir_hir_lowering/src/types.rs +++ b/compiler/astoir_hir_lowering/src/types.rs @@ -1,6 +1,6 @@ use ast::types::ASTType; use astoir_hir::ctx::HIRContext; -use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, tree::Type}; +use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, tree::Type}; use compiler_utils::hash::HashedString; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_type, make_diff_size_specifiers, make_diff_type_specifiers, make_req_type_kind}}; diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 6c3d7a0..5dd1652 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -8,7 +8,7 @@ use compiler_utils::hash::HashedString; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_cannot_find_type, make_diff_type_specifiers, make_req_type_kind, make_use_not_found}}; use lexer::lexer::lexer_parse_file; -use crate::{lower_ast_toplevel, structs::lower_ast_struct_declaration, types::{lower_ast_type, lower_ast_type_struct, lower_sized_base_type}, values::lower_ast_value}; +use crate::{lower_ast_toplevel, structs::lower_ast_struct_declaration, types::{lower_ast_type, lower_sized_base_type}}; pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Box, ctx: &ParserCtx) -> MaybeDiagnostic { if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, body: _, return_type, requires_this: _ } = node.kind.clone() { From 5510645ac0d64dd76f89cbc3d7d3918d2a351738 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:17:53 +0200 Subject: [PATCH 10/60] feat: added llvm as an optional package --- compiler/compiler_main/Cargo.toml | 7 +++-- compiler/compiler_main/src/cmds/astoir.rs | 32 ++++++++++++++++------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/compiler/compiler_main/Cargo.toml b/compiler/compiler_main/Cargo.toml index 09a0f99..cf79b94 100644 --- a/compiler/compiler_main/Cargo.toml +++ b/compiler/compiler_main/Cargo.toml @@ -8,6 +8,9 @@ astoir = { path = "../astoir" } ast = { path = "../ast" } ast_parser = { path = "../ast_parser" } lexer = { path = "../lexer" } -llvm_ir_bridge = { path = "../llvm_ir_bridge" } +llvm_ir_bridge = { path = "../llvm_ir_bridge", optional = true } diagnostics = { path = "../diagnostics" } -compiler_utils = { path = "../compiler_utils"} \ No newline at end of file +compiler_utils = { path = "../compiler_utils" } + +[features] +llvm = ["llvm_ir_bridge"] \ No newline at end of file diff --git a/compiler/compiler_main/src/cmds/astoir.rs b/compiler/compiler_main/src/cmds/astoir.rs index 697e989..4cbe4e1 100644 --- a/compiler/compiler_main/src/cmds/astoir.rs +++ b/compiler/compiler_main/src/cmds/astoir.rs @@ -4,6 +4,10 @@ use ast_parser::parse_ast_ctx; use astoir::{IRLevel, run_astoir_hir, run_astoir_mir}; use diagnostics::{DiagnosticResult, dump_diagnostics}; use lexer::lexer::lexer_parse_file; + +use std::process::exit; + +#[cfg(feature = "llvm_ir_bridge")] use llvm_ir_bridge::bridge_llvm; pub fn parse_astoir_command(arguments: Vec) { @@ -43,16 +47,24 @@ pub fn parse_astoir_command(arguments: Vec) { }, IRLevel::LLVM => { - let ctx = run_astoir_mir(ast.unwrap()); - let res_path = arguments[i].clone() + ".llvm"; - - dump_diagnostics(); - - let ctx = bridge_llvm(&ctx.unwrap()); - - dump_diagnostics(); - - ctx.module.print_to_file(res_path); + #[cfg(feature = "llvm_ir_bridge")] { + let ctx = run_astoir_mir(ast.unwrap()); + let res_path = arguments[i].clone() + ".llvm"; + + dump_diagnostics(); + + let ctx = bridge_llvm(&ctx.unwrap()); + + dump_diagnostics(); + + ctx.module.print_to_file(res_path); + } + + #[cfg(not(feature = "llvm_ir_bridge"))] { + println!("LLVM target is not bundled!"); + + exit(0); + } } } } From d83934e425351e3b5880e207fe0c47f3dfbf12da Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:31:34 +0200 Subject: [PATCH 11/60] chore: removed all of the warnings --- compiler/ast_parser/src/structs/enums.rs | 4 ++-- compiler/ast_parser/src/use_statements.rs | 2 +- compiler/astoir_hir/src/nodes.rs | 2 +- compiler/astoir_hir_lowering/src/enums.rs | 2 +- compiler/astoir_mir/src/builder.rs | 2 +- compiler/astoir_mir_lowering/src/casts.rs | 2 +- compiler/astoir_mir_lowering/src/introductions.rs | 2 +- compiler/astoir_mir_lowering/src/lib.rs | 2 +- compiler/astoir_mir_lowering/src/type_tools.rs | 8 +++----- compiler/compiler_main/Cargo.toml | 2 +- compiler/compiler_main/src/cmds/astoir.rs | 6 +++--- compiler/compiler_typing/src/bounds/traits.rs | 8 ++++---- compiler/compiler_typing/src/enums.rs | 2 +- compiler/compiler_typing/src/tree.rs | 4 ++-- compiler/diagnostics/src/diagnostic.rs | 10 ++++++---- compiler/diagnostics/src/lib.rs | 2 +- compiler/llvm_ir_bridge/src/lib.rs | 4 ++-- 17 files changed, 32 insertions(+), 32 deletions(-) diff --git a/compiler/ast_parser/src/structs/enums.rs b/compiler/ast_parser/src/structs/enums.rs index c6780bc..8aa4ab7 100644 --- a/compiler/ast_parser/src/structs/enums.rs +++ b/compiler/ast_parser/src/structs/enums.rs @@ -1,9 +1,9 @@ use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult, diagnostic::Diagnostic}; +use diagnostics::{DiagnosticResult}; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::{parse_type_generic, parse_type_parameters_declaration}}; +use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::{parse_type_parameters_declaration}}; pub fn parse_enum_entry(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { let start = tokens[*ind].pos.clone(); diff --git a/compiler/ast_parser/src/use_statements.rs b/compiler/ast_parser/src/use_statements.rs index e14f326..e8b3e3b 100644 --- a/compiler/ast_parser/src/use_statements.rs +++ b/compiler/ast_parser/src/use_statements.rs @@ -40,5 +40,5 @@ pub fn parse_use_statement(tokens: &Vec, ind: &mut usize) -> Diagnos *ind += 1; - return Ok((Box::new(ASTTreeNode::new(ASTTreeNodeKind::UseStatement { shards: steps, use_clauses: uses }, start, tokens[*ind].get_end_pos())))) + return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::UseStatement { shards: steps, use_clauses: uses }, start, tokens[*ind].get_end_pos()))) } \ No newline at end of file diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index a32a7c6..3e366e1 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use compiler_typing::{enums::{RawEnumEntryContainer, RawEnumTypeContainer}, raw::RawType, references::TypeReference, storage::{BOOLEAN_TYPE, STATIC_STR}, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type}; +use compiler_typing::{enums::{RawEnumTypeContainer}, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type}; use compiler_utils::{Position, hash::SelfHash}; use diagnostics::{DiagnosticSpanOrigin, builders::{make_diff_type, make_diff_type_val}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic}; use lexer::toks::{comp::ComparingOperator, math::MathOperator}; diff --git a/compiler/astoir_hir_lowering/src/enums.rs b/compiler/astoir_hir_lowering/src/enums.rs index d3c1d21..5ee4a79 100644 --- a/compiler/astoir_hir_lowering/src/enums.rs +++ b/compiler/astoir_hir_lowering/src/enums.rs @@ -29,7 +29,7 @@ pub fn lower_ast_enum_entry(context: &mut HIRContext, node: Box, co } pub fn lower_ast_enum(context: &mut HIRContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::EnumDeclaration { name, entries, functions, type_params } = node.kind.clone() { + if let ASTTreeNodeKind::EnumDeclaration { name, entries, functions: _, type_params } = node.kind.clone() { let mut container = RawEnumTypeContainer::new(context.type_storage.types.vals.len(), type_params); for entry in entries { diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 297fddf..188073f 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -1,7 +1,7 @@ //! Utility functions to build instructions and more use compiler_typing::{SizedType, raw::RawType, storage::TypeStorage, tree::Type}; -use diagnostics::{DiagnosticResult, MaybeDiagnostic, diagnostic::Diagnostic, unsure_panic}; +use diagnostics::{DiagnosticResult, MaybeDiagnostic, unsure_panic}; use crate::{blocks::{hints::MIRValueHint, refer::MIRBlockReference}, ctx::MIRContext, insts::MIRInstruction, vals::{arrays::MIRArrayValue, base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue, structs::MIRStructValue}}; diff --git a/compiler/astoir_mir_lowering/src/casts.rs b/compiler/astoir_mir_lowering/src/casts.rs index a2a2136..385b237 100644 --- a/compiler/astoir_mir_lowering/src/casts.rs +++ b/compiler/astoir_mir_lowering/src/casts.rs @@ -5,7 +5,7 @@ use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; pub fn lower_cast(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::CastValue { intentional, value, old_type, new_type } = node.kind.clone() { + if let HIRNodeKind::CastValue { intentional: _, value, old_type, new_type } = node.kind.clone() { let value = lower_hir_value(block, value, ctx)?; let old_type = lower_hir_type(ctx, old_type)?; diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index 756a0ee..9e54e53 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -13,7 +13,7 @@ pub fn handle_var_introduction_queue(block: MIRBlockReference, node: Box(block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { +pub fn is_enum_value_of_kind(_block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { let enum_type = match ctx.mir_ctx.ssa_hints.get_hint(val.get_ssa_index()).get_type().as_generic_lowered_safe(origin)? { RawType::Enum(v) => v, RawType::LoweredStruct(_, container) => { @@ -48,7 +46,7 @@ pub fn is_enum_value_of_kind(block: MIRBlockReference, return build_comp_eq(&mut ctx.mir_ctx, hint_val, hint_true); } -pub fn cast_to_enum_child(block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { +pub fn cast_to_enum_child(_block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { let enum_type = match ctx.mir_ctx.ssa_hints.get_hint(val.get_ssa_index()).get_type().as_generic_lowered_safe(origin)? { RawType::Enum(v) => v, RawType::LoweredStruct(_, container) => { @@ -107,7 +105,7 @@ pub fn lower_hir_unwrap_cond(block: MIRBlockReference, node: Box, ctx: } pub fn lower_hir_unwrap_value(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::UnwrapValue { original, new_type, unsafe_unwrap } = node.kind.clone() { + if let HIRNodeKind::UnwrapValue { original, new_type, unsafe_unwrap: _ } = node.kind.clone() { let original = lower_hir_value(block, original, ctx)?; let new_type = lower_hir_type(ctx, new_type)?; diff --git a/compiler/compiler_main/Cargo.toml b/compiler/compiler_main/Cargo.toml index cf79b94..c2a0b92 100644 --- a/compiler/compiler_main/Cargo.toml +++ b/compiler/compiler_main/Cargo.toml @@ -8,7 +8,7 @@ astoir = { path = "../astoir" } ast = { path = "../ast" } ast_parser = { path = "../ast_parser" } lexer = { path = "../lexer" } -llvm_ir_bridge = { path = "../llvm_ir_bridge", optional = true } +llvm_ir_bridge = { path = "../llvm_ir_bridge", optional = true, default-features = false} diagnostics = { path = "../diagnostics" } compiler_utils = { path = "../compiler_utils" } diff --git a/compiler/compiler_main/src/cmds/astoir.rs b/compiler/compiler_main/src/cmds/astoir.rs index 4cbe4e1..130dca8 100644 --- a/compiler/compiler_main/src/cmds/astoir.rs +++ b/compiler/compiler_main/src/cmds/astoir.rs @@ -43,7 +43,7 @@ pub fn parse_astoir_command(arguments: Vec) { dump_diagnostics(); - fs::write(res_path, format!("{}", ctx.unwrap())); + let _ = fs::write(res_path, format!("{}", ctx.unwrap())); }, IRLevel::LLVM => { @@ -57,7 +57,7 @@ pub fn parse_astoir_command(arguments: Vec) { dump_diagnostics(); - ctx.module.print_to_file(res_path); + let _ = ctx.module.print_to_file(res_path); } #[cfg(not(feature = "llvm_ir_bridge"))] { @@ -79,7 +79,7 @@ fn parse_astoir_level(str: &String) -> DiagnosticResult { _ => { println!("Invalid level"); - std::process::exit(0); + exit(0); } }; diff --git a/compiler/compiler_typing/src/bounds/traits.rs b/compiler/compiler_typing/src/bounds/traits.rs index 31806c8..b24b48a 100644 --- a/compiler/compiler_typing/src/bounds/traits.rs +++ b/compiler/compiler_typing/src/bounds/traits.rs @@ -24,7 +24,7 @@ use std::fmt::Display; use compiler_utils::hash; use diagnostics::{MaybeDiagnostic, builders::make_bound_trait}; -use crate::{storage::TypeStorage, tree::Type}; +use crate::{tree::Type}; pub const TRAIT_NUMERIC: u64 = hash!("numeric"); pub const TRAIT_SIGNED: u64 = hash!("signed"); @@ -81,17 +81,17 @@ pub struct TraitBound { } impl TraitBound { - pub fn check(&self, t: &Type, storage: &TypeStorage) -> MaybeDiagnostic { + pub fn check(&self, t: &Type) -> MaybeDiagnostic { for member in &self.members { match member { TraitBoundMember::Select(tt) => { - if !t.as_generic(storage).has_trait(tt.clone(), t) { + if !t.as_generic().has_trait(tt.clone(), t) { return Err(make_bound_trait(tt, t).into()) } }, TraitBoundMember::Exclude(tt) => { - if t.as_generic(storage).has_trait(tt.clone(), t) { + if t.as_generic().has_trait(tt.clone(), t) { return Err(make_bound_trait(&format!("~{}", tt), t).into()) } } diff --git a/compiler/compiler_typing/src/enums.rs b/compiler/compiler_typing/src/enums.rs index a60590b..efa4874 100644 --- a/compiler/compiler_typing/src/enums.rs +++ b/compiler/compiler_typing/src/enums.rs @@ -1,6 +1,6 @@ //! Declarations for enum-kind types. -use std::{collections::HashMap, f32::consts::E}; +use std::{collections::HashMap}; use compiler_utils::{hash::{HashedString}, utils::indexed::IndexStorage}; use diagnostics::{DiagnosticResult, builders::{make_cannot_find_type_field, make_cannot_find_type_function, make_cannot_find_type_pos, make_enum_parent_fields}}; diff --git a/compiler/compiler_typing/src/tree.rs b/compiler/compiler_typing/src/tree.rs index 3f32eba..67e306d 100644 --- a/compiler/compiler_typing/src/tree.rs +++ b/compiler/compiler_typing/src/tree.rs @@ -4,7 +4,7 @@ use std::fmt::Display; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_req_type_kind, unsure_panic}; -use crate::{RawTypeReference, SizedType, StructuredType, TypedFunction, raw::RawType, references::TypeReference, storage::{TypeStorage}, utils::get_pointer_size}; +use crate::{SizedType, StructuredType, TypedFunction, raw::RawType, references::TypeReference, storage::{TypeStorage}, utils::get_pointer_size}; #[derive(Clone, PartialEq, Debug, Eq, Hash)] /// The node-based typing system of Quickfall. Allows for very specific types. @@ -133,7 +133,7 @@ impl Type { } } - pub fn as_generic(&self, storage: &TypeStorage) -> RawType { + pub fn as_generic(&self) -> RawType { match self { Self::GenericLowered(a) => return a.clone(), Self::Generic(a, _, _) => { diff --git a/compiler/diagnostics/src/diagnostic.rs b/compiler/diagnostics/src/diagnostic.rs index a354fe4..301255b 100644 --- a/compiler/diagnostics/src/diagnostic.rs +++ b/compiler/diagnostics/src/diagnostic.rs @@ -86,11 +86,13 @@ impl Diagnostic { } } - pub fn maybe_display_backtrace(&self, fmt: &mut std::fmt::Formatter<'_>) { + pub fn maybe_display_backtrace(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if cfg!(debug_assertions) { - writeln!(fmt, "Internally captured in:"); - writeln!(fmt, "{}", self.backtrace.as_ref().unwrap()); + writeln!(fmt, "Internally captured in:")?; + writeln!(fmt, "{}", self.backtrace.as_ref().unwrap())?; } + + Ok(()) } pub fn new(level: Level, decl: (usize, &str), primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { @@ -247,7 +249,7 @@ impl Display for Diagnostic { ind += 1; } - self.maybe_display_backtrace(f); + self.maybe_display_backtrace(f)?; Ok(()) } diff --git a/compiler/diagnostics/src/lib.rs b/compiler/diagnostics/src/lib.rs index ff8f8c7..88b5521 100644 --- a/compiler/diagnostics/src/lib.rs +++ b/compiler/diagnostics/src/lib.rs @@ -24,7 +24,7 @@ thread_local! { #[macro_export] macro_rules! unsure_panic { ($msg: expr) => { { - diagnostics::builders::make_unsure_panic(&$msg.to_string()); + _ = diagnostics::builders::make_unsure_panic(&$msg.to_string()); diagnostics::dump_diagnostics(); panic!($msg); } diff --git a/compiler/llvm_ir_bridge/src/lib.rs b/compiler/llvm_ir_bridge/src/lib.rs index ff69e9e..6d59925 100644 --- a/compiler/llvm_ir_bridge/src/lib.rs +++ b/compiler/llvm_ir_bridge/src/lib.rs @@ -30,7 +30,7 @@ macro_rules! llvm_to_base { ($exp:expr) => { match $exp { Ok(v) => v, - Err(e) => panic!("inkwell function failed") + Err(_) => panic!("inkwell function failed") } }; } @@ -40,7 +40,7 @@ macro_rules! llvm_to_base_returnless { ($exp:expr) => { match $exp { Ok(_) => {}, - Err(e) => panic!("inkwell function failed") + Err(_) => panic!("inkwell function failed") } }; } \ No newline at end of file From 1a96ccceee6f221a4d6a340c04f1758e4d221c71 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:32:48 +0200 Subject: [PATCH 12/60] chore: updated the github workflow --- .github/workflows/rust.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 74b2828..cab2824 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,4 +1,4 @@ -name: Rust +name: Compile (No bridges) on: pull_request: @@ -12,12 +12,7 @@ jobs: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install LLVM - run: sudo apt install llvm - steps: - uses: actions/checkout@v4 - name: Build - run: cargo build --verbose + run: cargo build -p compiler_main From 47d3b9aa7da723e603a4aa53e10d9c28c465e145 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:42:51 +0200 Subject: [PATCH 13/60] feat: added compiler_diagbacktraces feature to enable backtraces on diagnostics --- compiler/diagnostics/Cargo.toml | 5 ++- compiler/diagnostics/src/diagnostic.rs | 54 +++++++++++++------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/compiler/diagnostics/Cargo.toml b/compiler/diagnostics/Cargo.toml index a1661bb..09f99b2 100644 --- a/compiler/diagnostics/Cargo.toml +++ b/compiler/diagnostics/Cargo.toml @@ -5,4 +5,7 @@ edition = "2024" [dependencies] compiler_utils = { path = "../compiler_utils" } -colored = "3.1.1" \ No newline at end of file +colored = "3.1.1" + +[features] +compiler_diagbacktraces = [] \ No newline at end of file diff --git a/compiler/diagnostics/src/diagnostic.rs b/compiler/diagnostics/src/diagnostic.rs index 301255b..dec8efd 100644 --- a/compiler/diagnostics/src/diagnostic.rs +++ b/compiler/diagnostics/src/diagnostic.rs @@ -1,6 +1,9 @@ //! The core of diagnostics -use std::{backtrace::Backtrace, fmt::Display, fs, io::Error}; +#[cfg(feature = "compiler_diagbacktraces")] +use std::backtrace::Backtrace; + +use std::{fmt::Display, fs, io::Error}; use colored::{ColoredString, Colorize}; use compiler_utils::Position; @@ -68,47 +71,43 @@ pub struct Diagnostic { pub note: Vec, pub help: Vec, - pub backtrace: Option + #[cfg(feature = "compiler_diagbacktraces")] + pub backtrace: Backtrace } impl Clone for Diagnostic { fn clone(&self) -> Self { - Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone(), backtrace: Diagnostic::capture_backtrace() } + #[cfg(feature = "compiler_diagbacktraces")] + return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone(), backtrace: Diagnostic::capture_backtrace() }; + + #[cfg(not(feature = "compiler_diagbacktraces"))] + return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone() }; } } impl Diagnostic { - pub fn capture_backtrace() -> Option { - if cfg!(debug_assertions) { - Some(Backtrace::capture()) - } else { - None - } - } - - pub fn maybe_display_backtrace(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if cfg!(debug_assertions) { - writeln!(fmt, "Internally captured in:")?; - writeln!(fmt, "{}", self.backtrace.as_ref().unwrap())?; - } - - Ok(()) - } - pub fn new(level: Level, decl: (usize, &str), primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { - let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help, backtrace: Diagnostic::capture_backtrace() }; + #[cfg(feature = "compiler_diagbacktraces")] + let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help, backtrace: Backtrace::capture() }; + #[cfg(not(feature = "compiler_diagbacktraces"))] + let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help }; + d.push_to_storage(); - d + return d } pub fn new_base(level: Level, code: usize, message: String, primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { - let d = Diagnostic { level, code, message, primary_span, spans, note, help, backtrace: Diagnostic::capture_backtrace() }; + #[cfg(feature = "compiler_diagbacktraces")] + let d = Diagnostic { level, code, message, primary_span, spans, note, help, backtrace: Backtrace::capture() }; + + #[cfg(not(feature = "compiler_diagbacktraces"))] + let d = Diagnostic { level, code, message, primary_span, spans, note, help }; d.push_to_storage(); - d + return d } fn push_to_storage(&self) { @@ -249,8 +248,11 @@ impl Display for Diagnostic { ind += 1; } - self.maybe_display_backtrace(f)?; - + #[cfg(feature = "compiler_diagbacktraces")] { + writeln!(f, "Internally captured in:")?; + writeln!(f, "{}", self.backtrace)?; + } + Ok(()) } } \ No newline at end of file From 6804a21804a48441104b7c5aa83a80e430f33618 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:50:47 +0200 Subject: [PATCH 14/60] feat: made diagbacktraces feature automatically enable rust backtraces when used --- compiler/compiler_main/Cargo.toml | 3 ++- compiler/diagnostics/src/diagnostic.rs | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/compiler/compiler_main/Cargo.toml b/compiler/compiler_main/Cargo.toml index c2a0b92..5db68fb 100644 --- a/compiler/compiler_main/Cargo.toml +++ b/compiler/compiler_main/Cargo.toml @@ -13,4 +13,5 @@ diagnostics = { path = "../diagnostics" } compiler_utils = { path = "../compiler_utils" } [features] -llvm = ["llvm_ir_bridge"] \ No newline at end of file +llvm = ["llvm_ir_bridge"] +diagbacktraces = ["diagnostics/compiler_diagbacktraces"] \ No newline at end of file diff --git a/compiler/diagnostics/src/diagnostic.rs b/compiler/diagnostics/src/diagnostic.rs index dec8efd..ce8c98e 100644 --- a/compiler/diagnostics/src/diagnostic.rs +++ b/compiler/diagnostics/src/diagnostic.rs @@ -77,8 +77,12 @@ pub struct Diagnostic { impl Clone for Diagnostic { fn clone(&self) -> Self { - #[cfg(feature = "compiler_diagbacktraces")] - return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone(), backtrace: Diagnostic::capture_backtrace() }; + #[cfg(feature = "compiler_diagbacktraces")] + unsafe { std::env::set_var("RUST_BACKTRACE", "1"); } + + #[cfg(feature = "compiler_diagbacktraces")] + return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone(), backtrace: Backtrace::capture() }; + #[cfg(not(feature = "compiler_diagbacktraces"))] return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone() }; @@ -87,9 +91,13 @@ impl Clone for Diagnostic { impl Diagnostic { pub fn new(level: Level, decl: (usize, &str), primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { - #[cfg(feature = "compiler_diagbacktraces")] + #[cfg(feature = "compiler_diagbacktraces")] + unsafe { std::env::set_var("RUST_BACKTRACE", "1"); } + + #[cfg(feature = "compiler_diagbacktraces")] let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help, backtrace: Backtrace::capture() }; + #[cfg(not(feature = "compiler_diagbacktraces"))] let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help }; @@ -99,8 +107,12 @@ impl Diagnostic { } pub fn new_base(level: Level, code: usize, message: String, primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { - #[cfg(feature = "compiler_diagbacktraces")] + #[cfg(feature = "compiler_diagbacktraces")] + unsafe { std::env::set_var("RUST_BACKTRACE", "1"); } + + #[cfg(feature = "compiler_diagbacktraces")] let d = Diagnostic { level, code, message, primary_span, spans, note, help, backtrace: Backtrace::capture() }; + #[cfg(not(feature = "compiler_diagbacktraces"))] let d = Diagnostic { level, code, message, primary_span, spans, note, help }; From b7a6e4f85fa14ae06aa9493c4484b16b7c823513 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 00:59:08 +0200 Subject: [PATCH 15/60] =?UTF-8?q?feat:=20removed=20op=C3=83erator=20parsin?= =?UTF-8?q?g=20from=20lexer=20for=20more=20parsing=20freedom?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/ast/src/lib.rs | 1 + compiler/ast/src/operators.rs | 21 ++++++ compiler/lexer/src/lexer.rs | 111 ++------------------------------ compiler/lexer/src/lib.rs | 3 +- compiler/lexer/src/token.rs | 49 +++----------- compiler/lexer/src/toks/comp.rs | 12 ---- compiler/lexer/src/toks/math.rs | 10 --- compiler/lexer/src/toks/mod.rs | 2 - 8 files changed, 35 insertions(+), 174 deletions(-) create mode 100644 compiler/ast/src/operators.rs delete mode 100644 compiler/lexer/src/toks/comp.rs delete mode 100644 compiler/lexer/src/toks/math.rs delete mode 100644 compiler/lexer/src/toks/mod.rs diff --git a/compiler/ast/src/lib.rs b/compiler/ast/src/lib.rs index e81ff1a..688dee0 100644 --- a/compiler/ast/src/lib.rs +++ b/compiler/ast/src/lib.rs @@ -5,3 +5,4 @@ pub mod tree; pub mod ctx; pub mod types; +pub mod operators; \ No newline at end of file diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs new file mode 100644 index 0000000..e88de57 --- /dev/null +++ b/compiler/ast/src/operators.rs @@ -0,0 +1,21 @@ +//! Operator related utils + +/// The different math operators +#[derive(Debug, PartialEq, Clone)] +pub enum MathOperator { + ADD, + SUBSTRACT, + MULTIPLY, + DIVIDE +} + +/// The different comparing operators +#[derive(Debug, PartialEq, Clone)] +pub enum ComparingOperator { + Equal, // A == B + NotEqual, // A != B + Higher, // A > B + HigherEqual, // A >= B + Lower, // A < B + LowerEqual // A <= B +} \ No newline at end of file diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index 8c6d965..cea6193 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -9,7 +9,7 @@ use diagnostics::DiagnosticResult; use diagnostics::builders::{make_unexpected_simple_error_outside}; use diagnostics::diagnostic::SpanPosition; -use crate::{token::{LexerToken, LexerTokenType}, toks::{comp::ComparingOperator, math::MathOperator}}; +use crate::{token::{LexerToken, LexerTokenType}}; const SHADOWFUNC_KEYWORD_HASH: u64 = hash!("shadowfunc"); const FUNC_KEYWORD_HASH: u64 = hash!("func"); @@ -81,27 +81,6 @@ pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> continue; } - if c == '+' || c == '-' || c == '*' || c == '/' { - let col = i - last_line_break; - - tokens.push(parse_math_operator(&contents, &mut i, Position::new(file_path.to_string(), line, col))?); - - continue; - } - - if c == '=' || c == '>' || c == '<' { - let col = i - last_line_break; - - let parse = parse_comp_operator(&contents, &mut i, Position::new(file_path.to_string(), line, col)); - - if parse.is_some() { - tokens.push(parse.unwrap()); - continue; - } - - i -= 2; // Try parsing operator as normal token. - } - if c == '/' { let cc = contents.chars().nth(i + 1).unwrap(); if cc == '/' { @@ -140,6 +119,9 @@ pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> '>' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::AngelBracketClose)), '*' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Asterisk)), ':' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Collon)), + '+' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Plus)), + '-' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Minus)), + '/' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Divide)), _ => continue } @@ -194,91 +176,6 @@ fn parse_global_comment(contents: &String, ind: &mut usize, start_pos: Position) return Ok(LexerToken::new(start_pos, end - start, LexerTokenType::GlobalComment(slice.to_string()))) } -fn parse_math_operator(contents: &String, ind: &mut usize, start_pos: Position) -> DiagnosticResult { - let operator_char = contents.chars().nth(*ind).unwrap(); - - let operator = match operator_char { - '+' => MathOperator::ADD, - '-' => MathOperator::SUBSTRACT, - '*' => MathOperator::MULTIPLY, - '/' => MathOperator::DIVIDE, - _ => return Err(make_unexpected_simple_error_outside(&operator_char, SpanPosition::from_pos(start_pos.clone(), start_pos.col + 1)).into()) - }; - - *ind += 1; - - if contents.chars().nth(*ind).unwrap() != '=' { - return Ok(LexerToken::make_single_sized(start_pos, LexerTokenType::EqualSign)); - } - - let assigns = match contents.chars().nth(*ind) { - Some(v) => { - if v != ' ' && v != '=' { - return Err(make_unexpected_simple_error_outside(&v, SpanPosition::from_pos(start_pos.clone(), start_pos.col + 2).into()).into()) - } - - v == '=' - } - None => false - }; - - if assigns { - *ind += 1; - } - - let mut increment_count = 1; - - if assigns { - increment_count += 1; - } - - return Ok(LexerToken::new(start_pos, increment_count, LexerTokenType::MathOperator(operator, assigns))); - -} - -fn parse_comp_operator(contents: &String, ind: &mut usize, start_pos: Position) -> Option { - let first_char = contents.chars().nth(*ind).unwrap(); - *ind += 1; - let second_char = contents.chars().nth(*ind).unwrap(); - - *ind += 1; - - if second_char != '=' && second_char != ' ' { - return None; - } - - match first_char { - '=' => { - if second_char != '=' { - return None; - } - - return Some(LexerToken::new(start_pos, 2, LexerTokenType::ComparingOperator(ComparingOperator::Equal))); - }, - - '>' => { - if second_char == '=' { - return Some(LexerToken::new(start_pos, 2, LexerTokenType::ComparingOperator(ComparingOperator::HigherEqual))); - } - - return Some(LexerToken::new(start_pos, 2, LexerTokenType::ComparingOperator(ComparingOperator::Higher))); - }, - - '<' => { - if second_char == '=' { - return Some(LexerToken::new(start_pos, 2, LexerTokenType::ComparingOperator(ComparingOperator::LowerEqual))); - } - - return Some(LexerToken::new(start_pos, 2, LexerTokenType::ComparingOperator(ComparingOperator::Lower))); - }, - - _ => { - return None; - } - } - -} - fn parse_number_token(str: &String, ind: &mut usize, start_pos: Position) -> DiagnosticResult { let start = *ind + 1; let mut end: usize = start; diff --git a/compiler/lexer/src/lib.rs b/compiler/lexer/src/lib.rs index 8459f9e..baff5a2 100644 --- a/compiler/lexer/src/lib.rs +++ b/compiler/lexer/src/lib.rs @@ -4,5 +4,4 @@ //! pub mod token; -pub mod lexer; -pub mod toks; +pub mod lexer; \ No newline at end of file diff --git a/compiler/lexer/src/token.rs b/compiler/lexer/src/token.rs index f700669..6a0f2fc 100644 --- a/compiler/lexer/src/token.rs +++ b/compiler/lexer/src/token.rs @@ -7,8 +7,6 @@ use std::fmt::Display; use compiler_utils::{Position}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_expected_simple_error, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}}; -use crate::{toks::{comp::ComparingOperator, math::MathOperator}}; - /// The token type for the lexer #[derive(PartialEq, Debug)] pub enum LexerTokenType { @@ -37,13 +35,6 @@ pub enum LexerTokenType { New, - /// 0: the operator - /// 1: does the operator affect the original variable! - MathOperator(MathOperator, bool), - - ComparingOperator(ComparingOperator), - - /// Represent the ret keyword Return, @@ -65,6 +56,10 @@ pub enum LexerTokenType { Ampersand, Collon, + Plus, + Minus, + Divide, + BracketOpen, BracketClose, @@ -113,21 +108,6 @@ impl LexerToken { return Ok(()); } - pub fn is_angel_bracket_close(&self) -> bool { - match &self.tok_type { - LexerTokenType::AngelBracketClose => true, - LexerTokenType::ComparingOperator(op) => { - if op == &ComparingOperator::Higher { - return true - } - - return false - }, - - _ => return false - } - } - pub fn expects_int_lit(&self) -> DiagnosticResult<(i128, u64)> { match &self.tok_type { LexerTokenType::IntLit(v, h) => return Ok((*v, *h)), @@ -135,20 +115,6 @@ impl LexerToken { }; } - pub fn expects_comp_operator(&self) -> DiagnosticResult { - match &self.tok_type { - LexerTokenType::ComparingOperator(op) => return Ok(op.clone()), - _ => return Err(make_expected_simple_error(self, &"comparing operator".to_string(), &self.tok_type).into()) - }; - } - - pub fn expects_math_operator(&self) -> DiagnosticResult<(MathOperator, bool)> { - match &self.tok_type { - LexerTokenType::MathOperator(a, b) => return Ok((a.clone(), *b)), - _ => return Err(make_expected_simple_error(self, &"math operator".to_string(), &self.tok_type).into()) - }; - } - pub fn expects_string_lit(&self) -> DiagnosticResult { match &self.tok_type { LexerTokenType::StringLit(v) => return Ok(v.to_string()), @@ -199,7 +165,6 @@ impl Display for LexerTokenType { Self::BracketOpen => "{", Self::Comma => ",", Self::Comment(_) => "comment", - Self::ComparingOperator(_) => "comparing operator", Self::Dot => ".", Self::Else => "else", Self::EndOfFile => "end of file", @@ -214,7 +179,6 @@ impl Display for LexerTokenType { Self::Keyword(_, _) => "keyword", Self::Lay => "lay", Self::Layout => "layout", - Self::MathOperator(_, _) => "math operator", Self::New => "new", Self::ParenClose => ")", Self::ParenOpen => "(", @@ -229,7 +193,10 @@ impl Display for LexerTokenType { Self::While => "while", Self::Unwrap => "unwrap", Self::Use => "use", - Self::UnwrapUnsafe => "unsafe_unwrap" + Self::UnwrapUnsafe => "unsafe_unwrap", + Self::Plus => "+", + Self::Minus => "-", + Self::Divide => "/" }; write!(f, "{}", s)?; diff --git a/compiler/lexer/src/toks/comp.rs b/compiler/lexer/src/toks/comp.rs deleted file mode 100644 index d8df3d0..0000000 --- a/compiler/lexer/src/toks/comp.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! Comparing token related utils - -/// The different comparing tokens -#[derive(Debug, PartialEq, Clone)] -pub enum ComparingOperator { - Equal, // A == B - NotEqual, // A != B - Higher, // A > B - HigherEqual, // A >= B - Lower, // A < B - LowerEqual // A <= B -} \ No newline at end of file diff --git a/compiler/lexer/src/toks/math.rs b/compiler/lexer/src/toks/math.rs deleted file mode 100644 index 0621019..0000000 --- a/compiler/lexer/src/toks/math.rs +++ /dev/null @@ -1,10 +0,0 @@ -///! Maths token related utils - -/// The different operators -#[derive(Debug, PartialEq, Clone)] -pub enum MathOperator { - ADD, - SUBSTRACT, - MULTIPLY, - DIVIDE -} \ No newline at end of file diff --git a/compiler/lexer/src/toks/mod.rs b/compiler/lexer/src/toks/mod.rs deleted file mode 100644 index 1854b67..0000000 --- a/compiler/lexer/src/toks/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod math; -pub mod comp; \ No newline at end of file From fde3e0207cba4bf22af6b0cf268707e8e68bf429 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:10:05 +0200 Subject: [PATCH 16/60] feat: added AST side operator parsing --- compiler/ast/src/operators.rs | 68 +++++++++++++++++++++++++++++++++++ compiler/ast/src/tree.rs | 3 +- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index e88de57..c4e73c9 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -1,5 +1,8 @@ //! Operator related utils +use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; +use lexer::token::{LexerToken, LexerTokenType}; + /// The different math operators #[derive(Debug, PartialEq, Clone)] pub enum MathOperator { @@ -18,4 +21,69 @@ pub enum ComparingOperator { HigherEqual, // A >= B Lower, // A < B LowerEqual // A <= B +} + +pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult<(MathOperator, bool)> { + let op = match tokens[*ind].tok_type { + LexerTokenType::Plus => MathOperator::ADD, + LexerTokenType::Minus => MathOperator::SUBSTRACT, + LexerTokenType::Asterisk => MathOperator::MULTIPLY, + LexerTokenType::Divide => MathOperator::DIVIDE, + + _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) + }; + + *ind += 1; + + let assigns = match tokens[*ind].tok_type { + LexerTokenType::EqualSign => true, + _ => false + }; + + *ind += 1; + + return Ok((op, assigns)) +} + +pub fn parse_compare_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { + let eq = match tokens[*ind + 1].tok_type { + LexerTokenType::EqualSign => true, + _ => false + }; + + let op = match tokens[*ind].tok_type { + LexerTokenType::EqualSign => { + tokens[*ind + 1].expects(LexerTokenType::EqualSign)?; + + ComparingOperator::Equal + }, + + LexerTokenType::ExclamationMark => { + tokens[*ind + 1].expects(LexerTokenType::EqualSign)?; + + ComparingOperator::NotEqual + }, + + LexerTokenType::AngelBracketOpen => { + if eq { + ComparingOperator::LowerEqual + } else { + ComparingOperator::Lower + } + }, + + LexerTokenType::AngelBracketClose => { + if eq { + ComparingOperator::HigherEqual + } else { + ComparingOperator::Higher + } + }, + + _ => { + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) + } + }; + + return Ok(op); } \ No newline at end of file diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 387d1ab..8d771ad 100644 --- a/compiler/ast/src/tree.rs +++ b/compiler/ast/src/tree.rs @@ -7,9 +7,8 @@ use std::{collections::HashMap, fmt::Display}; use compiler_typing::TypeParameterContainer; use compiler_utils::{Position, hash::{HashedString, SelfHash}}; use diagnostics::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}}; -use lexer::{toks::{comp::ComparingOperator, math::MathOperator}}; -use crate::types::ASTType; +use crate::{operators::{ComparingOperator, MathOperator}, types::ASTType}; #[derive(Debug, PartialEq, Clone)] pub struct FunctionDeclarationArgument { From 1beab3f15e974c42dd42a0d57e6437d42f7ba6e2 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:21:54 +0200 Subject: [PATCH 17/60] feat: fully migrated operators to AST --- Cargo.lock | 1 - compiler/ast/src/operators.rs | 21 +--------------- compiler/ast/src/tree.rs | 4 +-- compiler/ast_parser/src/comp.rs | 16 ++++++++++++ compiler/ast_parser/src/lib.rs | 1 + compiler/ast_parser/src/math.rs | 4 +-- compiler/ast_parser/src/types.rs | 4 +-- compiler/ast_parser/src/value.rs | 25 ++++++------------- compiler/astoir_hir/src/nodes.rs | 3 +-- compiler/astoir_mir_lowering/Cargo.toml | 1 - compiler/astoir_mir_lowering/src/math.rs | 2 +- .../src/values/booleans.rs | 2 +- compiler/compiler_utils/src/lib.rs | 1 + compiler/compiler_utils/src/operators.rs | 21 ++++++++++++++++ 14 files changed, 57 insertions(+), 49 deletions(-) create mode 100644 compiler/ast_parser/src/comp.rs create mode 100644 compiler/compiler_utils/src/operators.rs diff --git a/Cargo.lock b/Cargo.lock index 5009a10..a5fa4b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,7 +82,6 @@ dependencies = [ "compiler_typing", "compiler_utils", "diagnostics", - "lexer", ] [[package]] diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index c4e73c9..ff92cf5 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -1,28 +1,9 @@ //! Operator related utils +use compiler_utils::operators::{ComparingOperator, MathOperator}; use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; use lexer::token::{LexerToken, LexerTokenType}; -/// The different math operators -#[derive(Debug, PartialEq, Clone)] -pub enum MathOperator { - ADD, - SUBSTRACT, - MULTIPLY, - DIVIDE -} - -/// The different comparing operators -#[derive(Debug, PartialEq, Clone)] -pub enum ComparingOperator { - Equal, // A == B - NotEqual, // A != B - Higher, // A > B - HigherEqual, // A >= B - Lower, // A < B - LowerEqual // A <= B -} - pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult<(MathOperator, bool)> { let op = match tokens[*ind].tok_type { LexerTokenType::Plus => MathOperator::ADD, diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 8d771ad..307a8c0 100644 --- a/compiler/ast/src/tree.rs +++ b/compiler/ast/src/tree.rs @@ -5,10 +5,10 @@ use std::{collections::HashMap, fmt::Display}; use compiler_typing::TypeParameterContainer; -use compiler_utils::{Position, hash::{HashedString, SelfHash}}; +use compiler_utils::{Position, hash::{HashedString, SelfHash}, operators::{ComparingOperator, MathOperator}}; use diagnostics::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}}; -use crate::{operators::{ComparingOperator, MathOperator}, types::ASTType}; +use crate::types::ASTType; #[derive(Debug, PartialEq, Clone)] pub struct FunctionDeclarationArgument { diff --git a/compiler/ast_parser/src/comp.rs b/compiler/ast_parser/src/comp.rs new file mode 100644 index 0000000..b129c83 --- /dev/null +++ b/compiler/ast_parser/src/comp.rs @@ -0,0 +1,16 @@ +use ast::{operators::parse_compare_operator, tree::{ASTTreeNode, ASTTreeNodeKind}}; +use diagnostics::DiagnosticResult; +use lexer::token::LexerToken; + +use crate::value::parse_ast_value; + +pub fn parse_ast_compare(tokens: &Vec, ind: &mut usize, original: Box) -> DiagnosticResult> { + let operator = parse_compare_operator(tokens, ind)?; + + let right_val = parse_ast_value(tokens, ind)?; + + let start_pos = original.start.clone(); + let end_pos = right_val.end.clone(); + + return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::OperatorBasedConditionMember { lval: original, rval: right_val, operator }, start_pos, end_pos))) +} \ No newline at end of file diff --git a/compiler/ast_parser/src/lib.rs b/compiler/ast_parser/src/lib.rs index 6be0672..b96b63f 100644 --- a/compiler/ast_parser/src/lib.rs +++ b/compiler/ast_parser/src/lib.rs @@ -20,6 +20,7 @@ pub mod types; pub mod arrays; pub mod unwraps; pub mod use_statements; +pub mod comp; pub fn parse_ast_ctx(tokens: &Vec) -> DiagnosticResult { let mut ind = 0; diff --git a/compiler/ast_parser/src/math.rs b/compiler/ast_parser/src/math.rs index fe33f4b..c00a5fa 100644 --- a/compiler/ast_parser/src/math.rs +++ b/compiler/ast_parser/src/math.rs @@ -1,11 +1,11 @@ use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, diagnostic::Level, errors::MATH_OPERATION_ASSIGNS}; use lexer::token::LexerToken; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::{operators::parse_math_operator, tree::{ASTTreeNode, ASTTreeNodeKind}}; use crate::value::parse_ast_value; pub fn parse_math_operation(tokens: &Vec, ind: &mut usize, original: Box, restricts_to_assigns: bool) -> DiagnosticResult> { - let oper = tokens[*ind].expects_math_operator()?; + let oper = parse_math_operator(tokens, ind)?; if !oper.1 && restricts_to_assigns { return Err(tokens[*ind].make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec!["consider assigning this to variable".to_string()], vec!["add = at the end of the operator".to_string()]).into()) diff --git a/compiler/ast_parser/src/types.rs b/compiler/ast_parser/src/types.rs index cdea242..7f89348 100644 --- a/compiler/ast_parser/src/types.rs +++ b/compiler/ast_parser/src/types.rs @@ -47,7 +47,7 @@ pub fn parse_type_type_parameters(tokens: &Vec, ind: &mut usize) -> types.push(parsed_type); - if tokens[*ind].is_angel_bracket_close() { + if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { break; } @@ -206,7 +206,7 @@ pub fn parse_type_parameters_declaration(tokens: &Vec, ind: &mut usi *ind += 1; - if tokens[*ind].is_angel_bracket_close() { + if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { break; } diff --git a/compiler/ast_parser/src/value.rs b/compiler/ast_parser/src/value.rs index 42beefd..bef950b 100644 --- a/compiler/ast_parser/src/value.rs +++ b/compiler/ast_parser/src/value.rs @@ -1,10 +1,10 @@ use compiler_utils::{Position, hash::HashedString}; -use ast::{make_node, tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::{make_node, operators::parse_compare_operator, tree::{ASTTreeNode, ASTTreeNodeKind}}; use diagnostics::{DiagnosticResult, builders::{make_expected_simple_error, make_unexpected_simple_error}}; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{arrays::parse_array_access, functions::parse_function_call, structs::val::parse_struct_initialize, unwraps::{parse_unwrap_condition, parse_unwrap_value}}; +use crate::{arrays::parse_array_access, comp::parse_ast_compare, functions::parse_function_call, structs::val::parse_struct_initialize, unwraps::{parse_unwrap_condition, parse_unwrap_value}}; use crate::literals::{parse_integer_literal, parse_string_literal}; use crate::math::parse_math_operation; @@ -78,7 +78,7 @@ pub fn parse_ast_value_dotacess_chain_member(tokens: &Vec, ind: &mut /// pub fn parse_ast_value_post_l(tokens: &Vec, ind: &mut usize, original: DiagnosticResult>, invoked_on_body: bool) -> DiagnosticResult> { match &tokens[*ind].tok_type { - LexerTokenType::MathOperator(_, _) => { + LexerTokenType::Plus | LexerTokenType::Minus | LexerTokenType::Asterisk | LexerTokenType::Divide => { let o = &original?; let k = Box::new(ASTTreeNode::clone(o.as_ref())); @@ -92,6 +92,10 @@ pub fn parse_ast_value_post_l(tokens: &Vec, ind: &mut usize, origina }, LexerTokenType::EqualSign => { + if tokens[*ind + 1].tok_type == LexerTokenType::EqualSign { + return parse_ast_compare(tokens, ind, original.clone()?); + } + *ind += 1; if let Ok(v) = original.as_ref() { @@ -118,20 +122,7 @@ pub fn parse_ast_value_post_l(tokens: &Vec, ind: &mut usize, origina return Ok(Box::new(ASTTreeNode::new(kind, start, end))); }, - LexerTokenType::ComparingOperator(op) => { - let operator = op.clone(); - - let o = &original?; - let k = Box::new(ASTTreeNode::clone(o.as_ref())); - - *ind += 1; - let right_val = parse_ast_value(tokens, ind)?; - - let start_pos = k.start.clone(); - let end_pos = right_val.end.clone(); - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::OperatorBasedConditionMember { lval: k, rval: right_val, operator }, start_pos, end_pos))); - }, + LexerTokenType::ExclamationMark | LexerTokenType::AngelBracketOpen | LexerTokenType::AngelBracketClose => return parse_ast_compare(tokens, ind, original.clone()?), _ => return original } diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index 3e366e1..9544a52 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -3,9 +3,8 @@ use std::collections::HashMap; use compiler_typing::{enums::{RawEnumTypeContainer}, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type}; -use compiler_utils::{Position, hash::SelfHash}; +use compiler_utils::{Position, hash::SelfHash, operators::{ComparingOperator, MathOperator}}; use diagnostics::{DiagnosticSpanOrigin, builders::{make_diff_type, make_diff_type_val}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic}; -use lexer::toks::{comp::ComparingOperator, math::MathOperator}; use crate::{ctx::{HIRBranchedContext, HIRContext}, resolve::resolve_to_type, structs::{HIRIfBranch, StructLRUStep}}; diff --git a/compiler/astoir_mir_lowering/Cargo.toml b/compiler/astoir_mir_lowering/Cargo.toml index 0fd841b..82661b5 100644 --- a/compiler/astoir_mir_lowering/Cargo.toml +++ b/compiler/astoir_mir_lowering/Cargo.toml @@ -7,6 +7,5 @@ edition = "2024" astoir_mir = {path = "../astoir_mir"} astoir_hir = {path = "../astoir_hir"} diagnostics = { path = "../diagnostics" } -lexer = {path = "../lexer"} compiler_typing = { path = "../compiler_typing" } compiler_utils = { path = "../compiler_utils" } \ No newline at end of file diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index 4f68fc5..3c78662 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -1,8 +1,8 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; use astoir_mir::{blocks::{refer::MIRBlockReference}, builder::{build_float_add, build_float_div, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mul, build_int_sub}, vals::base::BaseMIRValue}; use compiler_typing::raw::RawType; +use compiler_utils::operators::MathOperator; use diagnostics::{DiagnosticResult, builders::make_math_operation_req_assign, unsure_panic}; -use lexer::toks::math::MathOperator; use crate::{MIRLoweringContext, values::lower_hir_value, vars::lower_hir_variable_reference}; diff --git a/compiler/astoir_mir_lowering/src/values/booleans.rs b/compiler/astoir_mir_lowering/src/values/booleans.rs index 54e81a9..4898435 100644 --- a/compiler/astoir_mir_lowering/src/values/booleans.rs +++ b/compiler/astoir_mir_lowering/src/values/booleans.rs @@ -1,7 +1,7 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; use astoir_mir::{blocks::{refer::MIRBlockReference}, builder::{build_bitwise_not, build_comp_eq, build_comp_ge, build_comp_gt, build_comp_le, build_comp_lt, build_comp_neg}, vals::int::MIRIntValue}; +use compiler_utils::operators::ComparingOperator; use diagnostics::DiagnosticResult; -use lexer::toks::comp::ComparingOperator; use crate::{MIRLoweringContext, values::lower_hir_value}; diff --git a/compiler/compiler_utils/src/lib.rs b/compiler/compiler_utils/src/lib.rs index 2cf4462..976aa53 100644 --- a/compiler/compiler_utils/src/lib.rs +++ b/compiler/compiler_utils/src/lib.rs @@ -3,6 +3,7 @@ use std::{fs, io::Error}; pub mod utils; pub mod hash; +pub mod operators; #[derive(Debug, Clone, PartialEq)] pub struct Position { diff --git a/compiler/compiler_utils/src/operators.rs b/compiler/compiler_utils/src/operators.rs new file mode 100644 index 0000000..31c7156 --- /dev/null +++ b/compiler/compiler_utils/src/operators.rs @@ -0,0 +1,21 @@ +//! Operator utilities + +/// The different math operators +#[derive(Debug, PartialEq, Clone)] +pub enum MathOperator { + ADD, + SUBSTRACT, + MULTIPLY, + DIVIDE +} + +/// The different comparing operators +#[derive(Debug, PartialEq, Clone)] +pub enum ComparingOperator { + Equal, // A == B + NotEqual, // A != B + Higher, // A > B + HigherEqual, // A >= B + Lower, // A < B + LowerEqual // A <= B +} From 2561e9c7302008500434f15e549aca846a5eac83 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:28:57 +0200 Subject: [PATCH 18/60] feat: added new MathOperator struct instead of two seperate fields --- compiler/ast/src/operators.rs | 14 +++++----- compiler/ast/src/tree.rs | 2 +- compiler/ast_parser/src/math.rs | 4 +-- compiler/ast_parser/src/value.rs | 2 +- compiler/astoir_hir/src/nodes.rs | 4 +-- compiler/astoir_hir_lowering/src/math.rs | 6 ++--- compiler/astoir_mir_lowering/src/body.rs | 4 +-- compiler/astoir_mir_lowering/src/math.rs | 34 ++++++++++++------------ compiler/compiler_utils/src/operators.rs | 20 +++++++++----- 9 files changed, 49 insertions(+), 41 deletions(-) diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index ff92cf5..542cef2 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -1,15 +1,15 @@ //! Operator related utils -use compiler_utils::operators::{ComparingOperator, MathOperator}; +use compiler_utils::operators::{ComparingOperator, MathOperator, MathOperatorType}; use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; use lexer::token::{LexerToken, LexerTokenType}; -pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult<(MathOperator, bool)> { +pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { let op = match tokens[*ind].tok_type { - LexerTokenType::Plus => MathOperator::ADD, - LexerTokenType::Minus => MathOperator::SUBSTRACT, - LexerTokenType::Asterisk => MathOperator::MULTIPLY, - LexerTokenType::Divide => MathOperator::DIVIDE, + LexerTokenType::Plus => MathOperatorType::Add, + LexerTokenType::Minus => MathOperatorType::Subtract, + LexerTokenType::Asterisk => MathOperatorType::Multiply, + LexerTokenType::Divide => MathOperatorType::Divide, _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) }; @@ -23,7 +23,7 @@ pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> Diagnos *ind += 1; - return Ok((op, assigns)) + return Ok(MathOperator { operator: op, assigns, fast: false }); } pub fn parse_compare_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 307a8c0..09f0c7a 100644 --- a/compiler/ast/src/tree.rs +++ b/compiler/ast/src/tree.rs @@ -38,7 +38,7 @@ pub enum ASTTreeNodeKind { OperatorBasedConditionMember { lval: Box, rval: Box, operator: ComparingOperator }, BooleanBasedConditionMember { val: Box, negate: bool }, - MathResult { lval: Box, rval: Box, operator: MathOperator, assigns: bool }, + MathResult { lval: Box, rval: Box, operator: MathOperator }, VariableReference(HashedString), diff --git a/compiler/ast_parser/src/math.rs b/compiler/ast_parser/src/math.rs index c00a5fa..bb7469d 100644 --- a/compiler/ast_parser/src/math.rs +++ b/compiler/ast_parser/src/math.rs @@ -7,7 +7,7 @@ use crate::value::parse_ast_value; pub fn parse_math_operation(tokens: &Vec, ind: &mut usize, original: Box, restricts_to_assigns: bool) -> DiagnosticResult> { let oper = parse_math_operator(tokens, ind)?; - if !oper.1 && restricts_to_assigns { + if !oper.assigns && restricts_to_assigns { return Err(tokens[*ind].make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec!["consider assigning this to variable".to_string()], vec!["add = at the end of the operator".to_string()]).into()) } @@ -18,5 +18,5 @@ pub fn parse_math_operation(tokens: &Vec, ind: &mut usize, original: let start = original.start.clone(); let end = right_member.end.clone(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::MathResult { lval: original, rval: right_member, operator: oper.0, assigns: oper.1 }, start, end))) + return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::MathResult { lval: original, rval: right_member, operator: oper }, start, end))) } \ No newline at end of file diff --git a/compiler/ast_parser/src/value.rs b/compiler/ast_parser/src/value.rs index bef950b..f176559 100644 --- a/compiler/ast_parser/src/value.rs +++ b/compiler/ast_parser/src/value.rs @@ -1,6 +1,6 @@ use compiler_utils::{Position, hash::HashedString}; -use ast::{make_node, operators::parse_compare_operator, tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::{make_node, tree::{ASTTreeNode, ASTTreeNodeKind}}; use diagnostics::{DiagnosticResult, builders::{make_expected_simple_error, make_unexpected_simple_error}}; use lexer::token::{LexerToken, LexerTokenType}; diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index 9544a52..9de521c 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -50,7 +50,7 @@ pub enum HIRNodeKind { VarAssigment { variable: usize, val: Box }, - MathOperation { left: Box, right: Box, operation: MathOperator, assignment: bool }, + MathOperation { left: Box, right: Box, operation: MathOperator }, UnwrapCondition { original: Box, new_type: Type, new_var: Option, unsafe_unwrap: bool }, UnwrapValue { original: Box, new_type: Type, unsafe_unwrap: bool }, @@ -247,7 +247,7 @@ impl HIRNode { return Some(last.clone()) }, - HIRNodeKind::MathOperation { left, right: _, operation: _, assignment: _ } => { + HIRNodeKind::MathOperation { left, right: _, operation: _ } => { return left.get_node_type(context, curr_ctx) }, diff --git a/compiler/astoir_hir_lowering/src/math.rs b/compiler/astoir_hir_lowering/src/math.rs index 0280b4d..8a8a4b5 100644 --- a/compiler/astoir_hir_lowering/src/math.rs +++ b/compiler/astoir_hir_lowering/src/math.rs @@ -5,8 +5,8 @@ use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, diagnostic::Level, err use crate::values::lower_ast_value; pub fn lower_ast_math_operation(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box, enforce_assign: bool) -> DiagnosticResult> { - if let ASTTreeNodeKind::MathResult { lval, rval, operator, assigns } = node.kind.clone() { - if enforce_assign && !assigns { + if let ASTTreeNodeKind::MathResult { lval, rval, operator } = node.kind.clone() { + if enforce_assign && !operator.assigns { return Err(node.make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec!["consider assigning this to variable".to_string()], vec!["add = at the end of the operator".to_string()]).into()) } @@ -14,7 +14,7 @@ pub fn lower_ast_math_operation(context: &mut HIRContext, curr_ctx: &mut HIRBran let right = Box::new(lower_ast_value(context, curr_ctx, rval)?.use_as(context, curr_ctx, left.get_node_type(context, curr_ctx).unwrap(), &*node, None)?); - return Ok(Box::new(HIRNode::new(HIRNodeKind::MathOperation { left, right, operation: operator, assignment: assigns }, &node.start, &node.end))) + return Ok(Box::new(HIRNode::new(HIRNodeKind::MathOperation { left, right, operation: operator }, &node.start, &node.end))) } panic!("Invalid node type") diff --git a/compiler/astoir_mir_lowering/src/body.rs b/compiler/astoir_mir_lowering/src/body.rs index d43af45..96b93d3 100644 --- a/compiler/astoir_mir_lowering/src/body.rs +++ b/compiler/astoir_mir_lowering/src/body.rs @@ -15,8 +15,8 @@ pub fn lower_hir_body_member(block: MIRBlockReference, node: Box, ctx: return match node.kind.clone() { HIRNodeKind::VarAssigment { .. } => lower_hir_variable_assignment(block, node, ctx), HIRNodeKind::VarDeclaration { .. } => lower_hir_variable_declaration(block, node, ctx), - HIRNodeKind::MathOperation { left: _, right: _, operation: _, assignment } => { - if !assignment { + HIRNodeKind::MathOperation { left: _, right: _, operation } => { + if !operation.assigns { return Err(make_math_operation_req_assign(&*node).into()) } diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index 3c78662..b942504 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -1,20 +1,20 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; use astoir_mir::{blocks::{refer::MIRBlockReference}, builder::{build_float_add, build_float_div, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mul, build_int_sub}, vals::base::BaseMIRValue}; use compiler_typing::raw::RawType; -use compiler_utils::operators::MathOperator; +use compiler_utils::operators::{MathOperator, MathOperatorType}; use diagnostics::{DiagnosticResult, builders::make_math_operation_req_assign, unsure_panic}; use crate::{MIRLoweringContext, values::lower_hir_value, vars::lower_hir_variable_reference}; pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::MathOperation { left, right, operation, assignment } = node.clone().kind { - if assignment && !left.is_variable_reference() { + if let HIRNodeKind::MathOperation { left, right, operation } = node.clone().kind { + if operation.assigns && !left.is_variable_reference() { return Err(make_math_operation_req_assign(&*node).into()) } let ptr; - if assignment { + if operation.assigns { ptr = Some(lower_hir_variable_reference(block, &left, ctx)?); } else { ptr = None @@ -25,13 +25,13 @@ pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box, ct let val = match left_val.vtype.get_generic(&ctx.hir_ctx.type_storage) { - RawType::Integer(_, _) | RawType::FixedPoint(_, _, _) => lower_hir_math_operation_int(left_val, right_val, operation, ctx)?, - RawType::Floating(_, _) => lower_hir_math_operation_float(left_val, right_val, operation, ctx)?, + RawType::Integer(_, _) | RawType::FixedPoint(_, _, _) => lower_hir_math_operation_int(left_val, right_val, operation.clone(), ctx)?, + RawType::Floating(_, _) => lower_hir_math_operation_float(left_val, right_val, operation.clone(), ctx)?, _ => unsure_panic!("Cannot use lower_hir_math_operator on this given value kind!") }; - if assignment { + if operation.assigns { let v = ptr.unwrap(); v.write(block, &mut ctx.mir_ctx, val.clone(), &ctx.hir_ctx.type_storage)?; @@ -49,11 +49,11 @@ pub fn lower_hir_math_operation_int(left: BaseMIRValue, right: BaseMIRValue, ope let signed = left.signed; - let res = match operator { - MathOperator::ADD => build_int_add(&mut ctx.mir_ctx, left, right, signed)?, - MathOperator::SUBSTRACT => build_int_sub(&mut ctx.mir_ctx, left, right, signed)?, - MathOperator::MULTIPLY => build_int_mul(&mut ctx.mir_ctx, left, right, signed)?, - MathOperator::DIVIDE => build_int_div(&mut ctx.mir_ctx, left, right, signed)? + let res = match operator.operator { + MathOperatorType::Add => build_int_add(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Subtract => build_int_sub(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed)? }; return Ok(res.into()); @@ -65,11 +65,11 @@ pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, o let signed = left.signed; - let res = match operator { - MathOperator::ADD => build_float_add(&mut ctx.mir_ctx, left, right, signed)?, - MathOperator::SUBSTRACT => build_float_sub(&mut ctx.mir_ctx, left, right, signed)?, - MathOperator::MULTIPLY => build_float_mul(&mut ctx.mir_ctx, left, right, signed)?, - MathOperator::DIVIDE => build_float_div(&mut ctx.mir_ctx, left, right, signed)? + let res = match operator.operator { + MathOperatorType::Add => build_float_add(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Subtract => build_float_sub(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Multiply => build_float_mul(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed)? }; return Ok(res.into()); diff --git a/compiler/compiler_utils/src/operators.rs b/compiler/compiler_utils/src/operators.rs index 31c7156..dc80dee 100644 --- a/compiler/compiler_utils/src/operators.rs +++ b/compiler/compiler_utils/src/operators.rs @@ -1,12 +1,20 @@ //! Operator utilities -/// The different math operators +/// The different math operator types #[derive(Debug, PartialEq, Clone)] -pub enum MathOperator { - ADD, - SUBSTRACT, - MULTIPLY, - DIVIDE +pub enum MathOperatorType { + Add, + Subtract, + Multiply, + Divide +} + +/// Represents an actual math operator +#[derive(Debug, PartialEq, Clone)] +pub struct MathOperator { + pub operator: MathOperatorType, + pub assigns: bool, + pub fast: bool } /// The different comparing operators From 562b66f6d8ca4b504c39f4856a9f62ac32a1b11c Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:31:15 +0200 Subject: [PATCH 19/60] feat: added tidle token --- compiler/lexer/src/lexer.rs | 1 + compiler/lexer/src/token.rs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index cea6193..38f5fed 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -122,6 +122,7 @@ pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> '+' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Plus)), '-' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Minus)), '/' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Divide)), + '~' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Tidle)), _ => continue } diff --git a/compiler/lexer/src/token.rs b/compiler/lexer/src/token.rs index 6a0f2fc..11162c0 100644 --- a/compiler/lexer/src/token.rs +++ b/compiler/lexer/src/token.rs @@ -59,6 +59,7 @@ pub enum LexerTokenType { Plus, Minus, Divide, + Tidle, BracketOpen, BracketClose, @@ -196,7 +197,8 @@ impl Display for LexerTokenType { Self::UnwrapUnsafe => "unsafe_unwrap", Self::Plus => "+", Self::Minus => "-", - Self::Divide => "/" + Self::Divide => "/", + Self::Tidle => "~" }; write!(f, "{}", s)?; From 14963c83a625549656d0dfc1c72a739e071d2b37 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:32:03 +0200 Subject: [PATCH 20/60] feat: added fast parsing --- compiler/ast/src/operators.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index 542cef2..89565fa 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -23,7 +23,14 @@ pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> Diagnos *ind += 1; - return Ok(MathOperator { operator: op, assigns, fast: false }); + let fast = match tokens[*ind].tok_type { + LexerTokenType::Tidle => true, + _ => false + }; + + *ind += 1; + + return Ok(MathOperator { operator: op, assigns, fast }); } pub fn parse_compare_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { From b46a36cf3b14e0d5ef73133b5e3a59feb4e45d1a Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:36:45 +0200 Subject: [PATCH 21/60] feat: added shifting operators parsing --- compiler/ast/src/operators.rs | 20 ++++++++++++++++++-- compiler/astoir_mir_lowering/src/math.rs | 2 +- compiler/compiler_utils/src/operators.rs | 4 +++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index 89565fa..c1df7e6 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -8,8 +8,24 @@ pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> Diagnos let op = match tokens[*ind].tok_type { LexerTokenType::Plus => MathOperatorType::Add, LexerTokenType::Minus => MathOperatorType::Subtract, - LexerTokenType::Asterisk => MathOperatorType::Multiply, - LexerTokenType::Divide => MathOperatorType::Divide, + LexerTokenType::Asterisk => { + if tokens[*ind + 1].tok_type == LexerTokenType::Asterisk { + *ind += 1; + + MathOperatorType::ShiftLeft + } else { + MathOperatorType::Multiply + } + } + LexerTokenType::Divide => { + if tokens[*ind + 1].tok_type == LexerTokenType::Divide { + *ind += 1; + + MathOperatorType::ShiftRight + } else { + MathOperatorType::Divide + } + } _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) }; diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index b942504..24609a4 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -53,7 +53,7 @@ pub fn lower_hir_math_operation_int(left: BaseMIRValue, right: BaseMIRValue, ope MathOperatorType::Add => build_int_add(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Subtract => build_int_sub(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed)? + MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed)?, }; return Ok(res.into()); diff --git a/compiler/compiler_utils/src/operators.rs b/compiler/compiler_utils/src/operators.rs index dc80dee..d6d8adf 100644 --- a/compiler/compiler_utils/src/operators.rs +++ b/compiler/compiler_utils/src/operators.rs @@ -6,7 +6,9 @@ pub enum MathOperatorType { Add, Subtract, Multiply, - Divide + Divide, + ShiftLeft, + ShiftRight } /// Represents an actual math operator From 4cf4391958f724b57343b95e5412ae6e9b6458d9 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:40:49 +0200 Subject: [PATCH 22/60] feat: added MIR bridge support --- compiler/astoir_mir/src/builder.rs | 12 ++++++++++++ compiler/astoir_mir_lowering/src/math.rs | 14 +++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 188073f..2b8322b 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -121,6 +121,18 @@ pub fn build_int_div(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue return res.as_int(); } +pub fn build_int_shift_left(ctx: &mut MIRContext, left: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { + let res = ctx.append_inst(MIRInstruction::ShiftLeft { a: left, shift }).get()?; + + return res.as_int(); +} + +pub fn build_int_shift_right(ctx: &mut MIRContext, left: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { + let res = ctx.append_inst(MIRInstruction::ShiftRight { a: left, shift }).get()?; + + return res.as_int(); +} + pub fn build_int_neg(ctx: &mut MIRContext, val: MIRIntValue) -> DiagnosticResult { let res = ctx.append_inst(MIRInstruction::IntegerNeg { val }).get()?; diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index 24609a4..181e9cd 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -1,8 +1,8 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::{refer::MIRBlockReference}, builder::{build_float_add, build_float_div, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mul, build_int_sub}, vals::base::BaseMIRValue}; +use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_float_add, build_float_div, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mul, build_int_sub, build_shift_left, build_shift_right}, vals::base::BaseMIRValue}; use compiler_typing::raw::RawType; use compiler_utils::operators::{MathOperator, MathOperatorType}; -use diagnostics::{DiagnosticResult, builders::make_math_operation_req_assign, unsure_panic}; +use diagnostics::{DiagnosticResult, builders::{make_math_operation_req_assign, make_req_type_kind}, unsure_panic}; use crate::{MIRLoweringContext, values::lower_hir_value, vars::lower_hir_variable_reference}; @@ -26,7 +26,7 @@ pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box, ct let val = match left_val.vtype.get_generic(&ctx.hir_ctx.type_storage) { RawType::Integer(_, _) | RawType::FixedPoint(_, _, _) => lower_hir_math_operation_int(left_val, right_val, operation.clone(), ctx)?, - RawType::Floating(_, _) => lower_hir_math_operation_float(left_val, right_val, operation.clone(), ctx)?, + RawType::Floating(_, _) => lower_hir_math_operation_float(left_val, right_val, operation.clone(), ctx, &*node)?, _ => unsure_panic!("Cannot use lower_hir_math_operator on this given value kind!") }; @@ -54,12 +54,14 @@ pub fn lower_hir_math_operation_int(left: BaseMIRValue, right: BaseMIRValue, ope MathOperatorType::Subtract => build_int_sub(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::ShiftLeft => build_shift_left(&mut ctx.mir_ctx, left, right)?, + MathOperatorType::ShiftRight => build_shift_right(&mut ctx.mir_ctx, left, right)? }; return Ok(res.into()); } -pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, operator: MathOperator, ctx: &mut MIRLoweringContext) -> DiagnosticResult { +pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, operator: MathOperator, ctx: &mut MIRLoweringContext, node: &HIRNode) -> DiagnosticResult { let left = left.as_float()?; let right = right.as_float()?; @@ -69,7 +71,9 @@ pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, o MathOperatorType::Add => build_float_add(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Subtract => build_float_sub(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Multiply => build_float_mul(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed)? + MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed)?, + + _ => return Err(make_req_type_kind(node, &"integer".to_string()).into()) }; return Ok(res.into()); From a9223e7b531c68a31b3ee3bf0cf3ec2f30df5aa3 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:43:17 +0200 Subject: [PATCH 23/60] feat: added modulo operator --- compiler/ast/src/operators.rs | 1 + compiler/compiler_utils/src/operators.rs | 3 ++- compiler/lexer/src/lexer.rs | 1 + compiler/lexer/src/token.rs | 4 +++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index c1df7e6..3a33dfc 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -7,6 +7,7 @@ use lexer::token::{LexerToken, LexerTokenType}; pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { let op = match tokens[*ind].tok_type { LexerTokenType::Plus => MathOperatorType::Add, + LexerTokenType::PercentSign => MathOperatorType::Modulo, LexerTokenType::Minus => MathOperatorType::Subtract, LexerTokenType::Asterisk => { if tokens[*ind + 1].tok_type == LexerTokenType::Asterisk { diff --git a/compiler/compiler_utils/src/operators.rs b/compiler/compiler_utils/src/operators.rs index d6d8adf..4a3a4a3 100644 --- a/compiler/compiler_utils/src/operators.rs +++ b/compiler/compiler_utils/src/operators.rs @@ -8,7 +8,8 @@ pub enum MathOperatorType { Multiply, Divide, ShiftLeft, - ShiftRight + ShiftRight, + Modulo } /// Represents an actual math operator diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index 38f5fed..e724251 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -123,6 +123,7 @@ pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> '-' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Minus)), '/' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Divide)), '~' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Tidle)), + '%' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::PercentSign)), _ => continue } diff --git a/compiler/lexer/src/token.rs b/compiler/lexer/src/token.rs index 11162c0..6574fd3 100644 --- a/compiler/lexer/src/token.rs +++ b/compiler/lexer/src/token.rs @@ -60,6 +60,7 @@ pub enum LexerTokenType { Minus, Divide, Tidle, + PercentSign, BracketOpen, BracketClose, @@ -198,7 +199,8 @@ impl Display for LexerTokenType { Self::Plus => "+", Self::Minus => "-", Self::Divide => "/", - Self::Tidle => "~" + Self::Tidle => "~", + Self::PercentSign => "%" }; write!(f, "{}", s)?; From fcf5366b112eade0b4458233eaca13e235570755 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:49:28 +0200 Subject: [PATCH 24/60] feat: added mod operator --- compiler/astoir_mir/src/builder.rs | 19 +++++++++++++++++++ compiler/astoir_mir/src/insts/mod.rs | 2 ++ compiler/astoir_mir_lowering/src/math.rs | 6 ++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 2b8322b..22ed201 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -121,6 +121,16 @@ pub fn build_int_div(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue return res.as_int(); } +pub fn build_int_mod(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using imod on different sized integers"); + } + + let res = ctx.append_inst(MIRInstruction::IntegerMod { signed, left, right }).get()?; + + return res.as_int(); +} + pub fn build_int_shift_left(ctx: &mut MIRContext, left: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { let res = ctx.append_inst(MIRInstruction::ShiftLeft { a: left, shift }).get()?; @@ -181,6 +191,15 @@ pub fn build_float_div(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloa return res.as_float(); } +pub fn build_float_mod(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using fmod on different sized integers"); + } + + let res = ctx.append_inst(MIRInstruction::FloatMod { signed, left, right }).get()?; + + return res.as_float(); +} pub fn build_float_neg(ctx: &mut MIRContext, val: MIRFloatValue) -> DiagnosticResult { let res = ctx.append_inst(MIRInstruction::FloatNeg { val }).get()?; diff --git a/compiler/astoir_mir/src/insts/mod.rs b/compiler/astoir_mir/src/insts/mod.rs index dbb271a..d3ec5c2 100644 --- a/compiler/astoir_mir/src/insts/mod.rs +++ b/compiler/astoir_mir/src/insts/mod.rs @@ -34,6 +34,7 @@ pub enum MIRInstruction { FloatSub { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, FloatMul { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, FloatDiv { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, + FloatMod { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, FloatNeg { val: MIRFloatValue }, // Bitwise (int typed) @@ -230,6 +231,7 @@ impl Display for MIRInstruction { Self::FloatSub { signed, left, right } => writeln!(f, "fsub s{} {} {}", signed, left, right)?, Self::FloatMul { signed, left, right } => writeln!(f, "fmul s{} {} {}", signed, left, right)?, Self::FloatDiv { signed, left, right } => writeln!(f, "fdiv s{} {} {}", signed, left, right)?, + Self::FloatMod { signed, left, right } => writeln!(f, "fmod s{} {} {}", signed, left, right)?, Self::FloatNeg { val } => writeln!(f, "fneg {}", val)?, Self::BitwiseAnd { a, b } => writeln!(f, "and {} {}", a, b)?, diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index 181e9cd..3c625ef 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -1,5 +1,5 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_float_add, build_float_div, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mul, build_int_sub, build_shift_left, build_shift_right}, vals::base::BaseMIRValue}; +use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_float_add, build_float_div, build_float_mod, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mod, build_int_mul, build_int_sub, build_shift_left, build_shift_right}, vals::base::BaseMIRValue}; use compiler_typing::raw::RawType; use compiler_utils::operators::{MathOperator, MathOperatorType}; use diagnostics::{DiagnosticResult, builders::{make_math_operation_req_assign, make_req_type_kind}, unsure_panic}; @@ -55,7 +55,8 @@ pub fn lower_hir_math_operation_int(left: BaseMIRValue, right: BaseMIRValue, ope MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::ShiftLeft => build_shift_left(&mut ctx.mir_ctx, left, right)?, - MathOperatorType::ShiftRight => build_shift_right(&mut ctx.mir_ctx, left, right)? + MathOperatorType::ShiftRight => build_shift_right(&mut ctx.mir_ctx, left, right)?, + MathOperatorType::Modulo => build_int_mod(&mut ctx.mir_ctx, left, right, signed)? }; return Ok(res.into()); @@ -72,6 +73,7 @@ pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, o MathOperatorType::Subtract => build_float_sub(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Multiply => build_float_mul(&mut ctx.mir_ctx, left, right, signed)?, MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Modulo => build_float_mod(&mut ctx.mir_ctx, left, right, signed)?, _ => return Err(make_req_type_kind(node, &"integer".to_string()).into()) }; From 2370907ffa610500f27ca661689b64734a1a38fd Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 01:53:17 +0200 Subject: [PATCH 25/60] feat: added mod operator in LLVM bridge --- compiler/llvm_ir_bridge/src/insts.rs | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/compiler/llvm_ir_bridge/src/insts.rs b/compiler/llvm_ir_bridge/src/insts.rs index b9fb59e..3cb6af0 100644 --- a/compiler/llvm_ir_bridge/src/insts.rs +++ b/compiler/llvm_ir_bridge/src/insts.rs @@ -86,6 +86,24 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize Some(res.into()) }, + MIRInstruction::IntegerMod { signed, left, right } => { + let left: BaseMIRValue = MIRIntValue::into(left); + let right: BaseMIRValue = MIRIntValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static>; + + if signed { + res = llvm_to_base!(bridge.builder.build_int_signed_rem(l.into_int_value(), r.into_int_value(), "")) + } else { + res = llvm_to_base!(bridge.builder.build_int_unsigned_rem(l.into_int_value(), r.into_int_value(), "")) + } + + Some(res.into()) + } + MIRInstruction::FloatAdd { signed: _, left, right } => { let left: BaseMIRValue = MIRFloatValue::into(left); let right: BaseMIRValue = MIRFloatValue::into(right); @@ -134,6 +152,18 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize Some(res.into()) }, + MIRInstruction::FloatMod { signed: _, left, right } => { + let left: BaseMIRValue = MIRFloatValue::into(left); + let right: BaseMIRValue = MIRFloatValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_rem(l.into_float_value(), r.into_float_value(), "")); + + Some(res.into()) + } + MIRInstruction::BitwiseAnd { a, b } => { let left: BaseMIRValue = MIRIntValue::into(a); let right: BaseMIRValue = MIRIntValue::into(b); From a820db905459c9d500aab05113ba3a9d04585363 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 11:48:17 +0200 Subject: [PATCH 26/60] feat: added fast math flags on MIR instructions --- compiler/astoir_mir/src/builder.rs | 40 ++++++++-------- compiler/astoir_mir/src/insts/mod.rs | 58 ++++++++++++------------ compiler/astoir_mir_lowering/src/math.rs | 20 ++++---- 3 files changed, 59 insertions(+), 59 deletions(-) diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 22ed201..7dad142 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -81,52 +81,52 @@ pub fn build_upcast_float(ctx: &mut MIRContext, val: MIRFloatValue, size: usize) return res.as_float(); } -pub fn build_int_add(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool) -> DiagnosticResult { +pub fn build_int_add(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using iadd on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::IntegerAdd { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::IntegerAdd { signed, fast, left, right }).get()?; return res.as_int(); } -pub fn build_int_sub(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool) -> DiagnosticResult { +pub fn build_int_sub(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using isub on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::IntegerSub { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::IntegerSub { signed, fast, left, right }).get()?; return res.as_int(); } -pub fn build_int_mul(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool) -> DiagnosticResult { +pub fn build_int_mul(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using imul on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::IntegerMul { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::IntegerMul { signed, fast, left, right }).get()?; return res.as_int(); } -pub fn build_int_div(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool) -> DiagnosticResult { +pub fn build_int_div(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using idiv on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::IntegerDiv { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::IntegerDiv { signed, fast, left, right }).get()?; return res.as_int(); } -pub fn build_int_mod(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool) -> DiagnosticResult { +pub fn build_int_mod(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using imod on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::IntegerMod { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::IntegerMod { signed, fast, left, right }).get()?; return res.as_int(); } @@ -149,54 +149,54 @@ pub fn build_int_neg(ctx: &mut MIRContext, val: MIRIntValue) -> DiagnosticResult return res.as_int(); } -pub fn build_float_add(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool) -> DiagnosticResult { +pub fn build_float_add(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using fadd on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::FloatAdd { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::FloatAdd { signed, fast, left, right }).get()?; return res.as_float(); } -pub fn build_float_sub(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool) -> DiagnosticResult { +pub fn build_float_sub(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using fsub on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::FloatSub { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::FloatSub { signed, fast, left, right }).get()?; return res.as_float(); } -pub fn build_float_mul(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool) -> DiagnosticResult { +pub fn build_float_mul(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using fmul on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::FloatMul { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::FloatMul { signed, fast, left, right }).get()?; return res.as_float(); } -pub fn build_float_div(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool) -> DiagnosticResult { +pub fn build_float_div(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using fdiv on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::FloatDiv { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::FloatDiv { signed, fast, left, right }).get()?; return res.as_float(); } -pub fn build_float_mod(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool) -> DiagnosticResult { +pub fn build_float_mod(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { if left.size != right.size { unsure_panic!("Tried using fmod on different sized integers"); } - let res = ctx.append_inst(MIRInstruction::FloatMod { signed, left, right }).get()?; + let res = ctx.append_inst(MIRInstruction::FloatMod { signed, fast, left, right }).get()?; return res.as_float(); } diff --git a/compiler/astoir_mir/src/insts/mod.rs b/compiler/astoir_mir/src/insts/mod.rs index d3ec5c2..066b776 100644 --- a/compiler/astoir_mir/src/insts/mod.rs +++ b/compiler/astoir_mir/src/insts/mod.rs @@ -23,18 +23,18 @@ pub enum MIRInstruction { UpcastFloat { val: MIRFloatValue, size: usize }, // Arithmetrics - IntegerAdd { signed: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerSub { signed: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerMul { signed: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerDiv { signed: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerMod { signed: bool, left: MIRIntValue, right: MIRIntValue }, + IntegerAdd { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, + IntegerSub { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, + IntegerMul { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, + IntegerDiv { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, + IntegerMod { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, IntegerNeg { val: MIRIntValue }, - FloatAdd { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatSub { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatMul { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatDiv { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatMod { signed: bool, left: MIRFloatValue, right: MIRFloatValue }, + FloatAdd { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, + FloatSub { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, + FloatMul { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, + FloatDiv { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, + FloatMod { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, FloatNeg { val: MIRFloatValue }, // Bitwise (int typed) @@ -139,17 +139,17 @@ impl MIRInstruction { Self::DowncastFloat { val, size } => return Type::GenericLowered(RawType::Floating(*size, val.signed)), Self::UpcastFloat { val, size } => return Type::GenericLowered(RawType::Floating(*size, val.signed)), - Self::IntegerAdd { signed, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerSub { signed, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerMul { signed, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerDiv { signed, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerMod { signed, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerAdd { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerSub { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerMul { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerDiv { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerMod { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), Self::IntegerNeg { val } => return Type::GenericLowered(RawType::Integer(val.size, true)), - Self::FloatAdd { signed, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatSub { signed, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatMul { signed, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatDiv { signed, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatAdd { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatSub { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatMul { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatDiv { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), Self::FloatNeg { val } => return Type::GenericLowered(RawType::Floating(val.size, true)), Self::BitwiseAnd { a, b: _ } => return Type::GenericLowered(RawType::Integer(a.size, a.signed)), @@ -220,18 +220,18 @@ impl Display for MIRInstruction { Self::UpcastInteger { val, size } => writeln!(f, "uintcast {} {}", val, size)?, Self::UpcastFloat { val, size } => writeln!(f, "ufcast {} {}", val, size)?, - Self::IntegerAdd { signed, left, right } => writeln!(f, "iadd s{} {} {}", signed, left, right)?, - Self::IntegerSub { signed, left, right } => writeln!(f, "isub s{} {} {}", signed, left, right)?, - Self::IntegerMul { signed, left, right } => writeln!(f, "imul s{} {} {}", signed, left, right)?, - Self::IntegerDiv { signed, left, right } => writeln!(f, "idiv s{} {} {}", signed, left, right)?, - Self::IntegerMod { signed, left, right } => writeln!(f, "imod s{} {} {}", signed, left, right)?, + Self::IntegerAdd { signed, fast, left, right } => writeln!(f, "iadd s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerSub { signed, fast, left, right } => writeln!(f, "isub s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerMul { signed, fast, left, right } => writeln!(f, "imul s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerDiv { signed, fast, left, right } => writeln!(f, "idiv s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerMod { signed, fast, left, right } => writeln!(f, "imod s{} f{} {} {}", signed, fast, left, right)?, Self::IntegerNeg { val } => writeln!(f, "ineg {}", val)?, - Self::FloatAdd { signed, left, right } => writeln!(f, "fadd s{} {} {}", signed, left, right)?, - Self::FloatSub { signed, left, right } => writeln!(f, "fsub s{} {} {}", signed, left, right)?, - Self::FloatMul { signed, left, right } => writeln!(f, "fmul s{} {} {}", signed, left, right)?, - Self::FloatDiv { signed, left, right } => writeln!(f, "fdiv s{} {} {}", signed, left, right)?, - Self::FloatMod { signed, left, right } => writeln!(f, "fmod s{} {} {}", signed, left, right)?, + Self::FloatAdd { signed, fast, left, right } => writeln!(f, "fadd s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatSub { signed, fast, left, right } => writeln!(f, "fsub s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatMul { signed, fast, left, right } => writeln!(f, "fmul s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatDiv { signed, fast, left, right } => writeln!(f, "fdiv s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatMod { signed, fast, left, right } => writeln!(f, "fmod s{} f{} {} {}", signed, fast, left, right)?, Self::FloatNeg { val } => writeln!(f, "fneg {}", val)?, Self::BitwiseAnd { a, b } => writeln!(f, "and {} {}", a, b)?, diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index 3c625ef..de846e2 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -50,13 +50,13 @@ pub fn lower_hir_math_operation_int(left: BaseMIRValue, right: BaseMIRValue, ope let signed = left.signed; let res = match operator.operator { - MathOperatorType::Add => build_int_add(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Subtract => build_int_sub(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Add => build_int_add(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Subtract => build_int_sub(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, MathOperatorType::ShiftLeft => build_shift_left(&mut ctx.mir_ctx, left, right)?, MathOperatorType::ShiftRight => build_shift_right(&mut ctx.mir_ctx, left, right)?, - MathOperatorType::Modulo => build_int_mod(&mut ctx.mir_ctx, left, right, signed)? + MathOperatorType::Modulo => build_int_mod(&mut ctx.mir_ctx, left, right, signed, operator.fast)? }; return Ok(res.into()); @@ -69,11 +69,11 @@ pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, o let signed = left.signed; let res = match operator.operator { - MathOperatorType::Add => build_float_add(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Subtract => build_float_sub(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Multiply => build_float_mul(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed)?, - MathOperatorType::Modulo => build_float_mod(&mut ctx.mir_ctx, left, right, signed)?, + MathOperatorType::Add => build_float_add(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Subtract => build_float_sub(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Multiply => build_float_mul(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, + MathOperatorType::Modulo => build_float_mod(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, _ => return Err(make_req_type_kind(node, &"integer".to_string()).into()) }; From 434c1bd7874ac5261a731e0e2244b4e725153563 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:10:02 +0200 Subject: [PATCH 27/60] feat: added fast math to llvm bridge --- compiler/ast/src/operators.rs | 8 +++- compiler/ast_parser/src/math.rs | 4 +- compiler/llvm_ir_bridge/src/insts.rs | 66 ++++++++++++++++++++++------ 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index 3a33dfc..6faf312 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -38,14 +38,18 @@ pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> Diagnos _ => false }; - *ind += 1; + if assigns { + *ind += 1; + } let fast = match tokens[*ind].tok_type { LexerTokenType::Tidle => true, _ => false }; - *ind += 1; + if fast { + *ind += 1; + } return Ok(MathOperator { operator: op, assigns, fast }); } diff --git a/compiler/ast_parser/src/math.rs b/compiler/ast_parser/src/math.rs index bb7469d..ad6664d 100644 --- a/compiler/ast_parser/src/math.rs +++ b/compiler/ast_parser/src/math.rs @@ -10,8 +10,8 @@ pub fn parse_math_operation(tokens: &Vec, ind: &mut usize, original: if !oper.assigns && restricts_to_assigns { return Err(tokens[*ind].make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec!["consider assigning this to variable".to_string()], vec!["add = at the end of the operator".to_string()]).into()) } - - *ind += 1; + + println!("{:#?}", tokens[*ind].tok_type); let right_member = parse_ast_value(tokens, ind)?; diff --git a/compiler/llvm_ir_bridge/src/insts.rs b/compiler/llvm_ir_bridge/src/insts.rs index 3cb6af0..cb41af9 100644 --- a/compiler/llvm_ir_bridge/src/insts.rs +++ b/compiler/llvm_ir_bridge/src/insts.rs @@ -1,6 +1,6 @@ -use astoir_mir::{blocks::MIRBlockHeldInstruction, ctx::MIRContext, insts::MIRInstruction, vals::{base::BaseMIRValue, float::{MIRFloatValue}, int::MIRIntValue, ptr::MIRPointerValue}}; +use astoir_mir::{blocks::MIRBlockHeldInstruction, ctx::MIRContext, insts::{MIRInstruction}, vals::{base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}}; use compiler_typing::{raw::RawType}; -use inkwell::{IntPredicate, module::Linkage, types::{BasicType, BasicTypeEnum, StringRadix}, values::{BasicValue, BasicValueEnum, FloatValue, IntValue}}; +use inkwell::{IntPredicate, module::Linkage, types::{BasicType, BasicTypeEnum, StringRadix}, values::{BasicValue, BasicValueEnum, FastMathFlags, FloatValue, IntValue}}; use crate::{ctx::LLVMBridgeContext, llvm_to_base, llvm_to_base_returnless, utils::LLVMBasicValue}; @@ -32,19 +32,23 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize None } - MIRInstruction::IntegerAdd { signed: _, left, right } => { + MIRInstruction::IntegerAdd { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRIntValue::into(left); let right: BaseMIRValue = MIRIntValue::into(right); let l = bridge.values[&left.get_ssa_index()].clone(); let r = bridge.values[&right.get_ssa_index()].clone(); - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_add(l.into_int_value(), r.into_int_value(), "")); + let res = llvm_to_base!(bridge.builder.build_int_add(l.into_int_value(), r.into_int_value(), "")); + + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } Some(res.into()) }, - MIRInstruction::IntegerSub { signed: _, left, right } => { + MIRInstruction::IntegerSub { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRIntValue::into(left); let right: BaseMIRValue = MIRIntValue::into(right); @@ -53,10 +57,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_sub(l.into_int_value(), r.into_int_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::IntegerMul { signed: _, left, right } => { + MIRInstruction::IntegerMul { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRIntValue::into(left); let right: BaseMIRValue = MIRIntValue::into(right); @@ -65,10 +73,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_mul(l.into_int_value(), r.into_int_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::IntegerDiv { signed, left, right } => { + MIRInstruction::IntegerDiv { signed, fast, left, right } => { let left: BaseMIRValue = MIRIntValue::into(left); let right: BaseMIRValue = MIRIntValue::into(right); @@ -83,10 +95,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize res = llvm_to_base!(bridge.builder.build_int_unsigned_div(l.into_int_value(), r.into_int_value(), "")) } + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::IntegerMod { signed, left, right } => { + MIRInstruction::IntegerMod { signed, fast, left, right } => { let left: BaseMIRValue = MIRIntValue::into(left); let right: BaseMIRValue = MIRIntValue::into(right); @@ -101,10 +117,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize res = llvm_to_base!(bridge.builder.build_int_unsigned_rem(l.into_int_value(), r.into_int_value(), "")) } + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) } - MIRInstruction::FloatAdd { signed: _, left, right } => { + MIRInstruction::FloatAdd { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRFloatValue::into(left); let right: BaseMIRValue = MIRFloatValue::into(right); @@ -113,10 +133,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_add(l.into_float_value(), r.into_float_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::FloatSub { signed: _, left, right } => { + MIRInstruction::FloatSub { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRFloatValue::into(left); let right: BaseMIRValue = MIRFloatValue::into(right); @@ -125,10 +149,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_sub(l.into_float_value(), r.into_float_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::FloatMul { signed: _, left, right } => { + MIRInstruction::FloatMul { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRFloatValue::into(left); let right: BaseMIRValue = MIRFloatValue::into(right); @@ -137,10 +165,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_mul(l.into_float_value(), r.into_float_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::FloatDiv { signed: _, left, right } => { + MIRInstruction::FloatDiv { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRFloatValue::into(left); let right: BaseMIRValue = MIRFloatValue::into(right); @@ -149,10 +181,14 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_div(l.into_float_value(), r.into_float_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) }, - MIRInstruction::FloatMod { signed: _, left, right } => { + MIRInstruction::FloatMod { signed: _, fast, left, right } => { let left: BaseMIRValue = MIRFloatValue::into(left); let right: BaseMIRValue = MIRFloatValue::into(right); @@ -161,6 +197,10 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_rem(l.into_float_value(), r.into_float_value(), "")); + if fast { + llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + } + Some(res.into()) } From a19bfd6f26a76ce3ff09615d2893825280183b8e Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:16:07 +0200 Subject: [PATCH 28/60] feat: added int fastmath --- compiler/llvm_ir_bridge/src/insts.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/compiler/llvm_ir_bridge/src/insts.rs b/compiler/llvm_ir_bridge/src/insts.rs index cb41af9..4776f66 100644 --- a/compiler/llvm_ir_bridge/src/insts.rs +++ b/compiler/llvm_ir_bridge/src/insts.rs @@ -42,7 +42,10 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res = llvm_to_base!(bridge.builder.build_int_add(l.into_int_value(), r.into_int_value(), "")); if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); } Some(res.into()) @@ -58,7 +61,10 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_sub(l.into_int_value(), r.into_int_value(), "")); if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); } Some(res.into()) @@ -74,7 +80,10 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_mul(l.into_int_value(), r.into_int_value(), "")); if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); } Some(res.into()) @@ -96,9 +105,12 @@ pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize } if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } + let res2 = res.as_instruction_value().unwrap(); + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_exact_flag(true)); + } Some(res.into()) }, From 2a422554abda458882a36b0a56f431d467988b12 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:11:17 +0200 Subject: [PATCH 29/60] feat: added field usage count tracking --- compiler/astoir_hir/src/ctx.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index f273396..57e1228 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -69,7 +69,7 @@ impl HIRBranchedContext { return Err(()); } - let mut var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch + 1, variable_type: t, has_default, introduced_values: HashSet::new(), requires_address: false, mutation_count: 0 }; + let mut var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch + 1, variable_type: t, has_default, introduced_values: HashSet::new(), requires_address: false, mutation_count: 0, usage_count: 0 }; if has_default { var.mutation_count += 1; @@ -93,7 +93,7 @@ impl HIRBranchedContext { return Err(()); } - let mut var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch, variable_type: t, has_default, introduced_values: HashSet::new(), requires_address: false, mutation_count: 0 }; + let mut var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch, variable_type: t, has_default, introduced_values: HashSet::new(), requires_address: false, mutation_count: 0, usage_count: 0}; if has_default { var.mutation_count += 1; @@ -183,7 +183,7 @@ impl HIRBranchedContext { } /// Obtains the variable index from the hash if it's available, otherwise returns an error explaining why it failed - pub fn obtain(&self, hash: u64, origin: &K) -> DiagnosticResult { + pub fn obtain(&mut self, hash: u64, origin: &K) -> DiagnosticResult { let identity = SelfHash { hash }; match self.hash_to_ind.get(&identity) { @@ -199,6 +199,8 @@ impl HIRBranchedContext { panic!("Dropped unalived variable") } + self.variables[ind].usage_count += 1; + return Ok(ind) } } @@ -216,7 +218,9 @@ impl HIRBranchedContext { pub struct HIRBranchedVariable { pub introduced_in_era: usize, pub variable_type: Type, - + + pub usage_count: usize, + pub requires_address: bool, /// The amount of times the variable has been changed @@ -255,7 +259,7 @@ impl HIRContext { } } -pub fn get_variable(context: &HIRContext, curr_ctx: &HIRBranchedContext, hash: u64, origin: &K) -> DiagnosticResult<(VariableKind, Type, usize)> { +pub fn get_variable(context: &HIRContext, curr_ctx: &mut HIRBranchedContext, hash: u64, origin: &K) -> DiagnosticResult<(VariableKind, Type, usize)> { if curr_ctx.hash_to_ind.contains_key(&SelfHash { hash }) { let ind = curr_ctx.obtain(hash, origin)?; From 37595c36affd551dbcbdb3e3dcc7fe8861c732cb Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 14 Apr 2026 13:34:10 +0200 Subject: [PATCH 30/60] feat: added global scope storage --- compiler/astoir_hir/src/lib.rs | 3 +- compiler/astoir_hir/src/storage.rs | 90 ++++++++++++++++++++++++++++ compiler/diagnostics/src/builders.rs | 6 +- compiler/diagnostics/src/errors.rs | 3 +- 4 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 compiler/astoir_hir/src/storage.rs diff --git a/compiler/astoir_hir/src/lib.rs b/compiler/astoir_hir/src/lib.rs index aff66fe..eccf903 100644 --- a/compiler/astoir_hir/src/lib.rs +++ b/compiler/astoir_hir/src/lib.rs @@ -4,4 +4,5 @@ pub mod ctx; pub mod nodes; pub mod structs; -pub mod resolve; \ No newline at end of file +pub mod resolve; +pub mod storage; \ No newline at end of file diff --git a/compiler/astoir_hir/src/storage.rs b/compiler/astoir_hir/src/storage.rs new file mode 100644 index 0000000..1c2f1e7 --- /dev/null +++ b/compiler/astoir_hir/src/storage.rs @@ -0,0 +1,90 @@ +//! The global HIR storage, basically stores types, functions, and more + +use std::{collections::{HashMap, btree_map::Entry}, hash::Hash}; + +use compiler_typing::tree::Type; +use compiler_utils::{hash::SelfHash}; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find}}; + +use crate::{ctx::HIRFunction, nodes::HIRNode}; + +pub type GlobalStorageIdentifier = usize; + +#[derive(Clone)] +pub enum GlobalStorageEntryType { + Function(HIRFunction, Box), + ImplLessFunction(HIRFunction), + StaticVariable(Type), + + StructFunction(HIRFunction, Box, GlobalStorageIdentifier), + + Type(Type) +} + +/// Represents a key to a global storage entry. Potentially allows for namespaces later on +pub struct EntryKey { + pub name_hash: u64 +} + +impl Hash for EntryKey { + fn hash(&self, state: &mut H) { + state.write_u64(self.name_hash); + } +} + +impl PartialEq for EntryKey { + fn eq(&self, other: &Self) -> bool { + self.name_hash == other.name_hash + } +} + +impl Eq for EntryKey {} + +pub struct GlobalStorageEntry { + pub entry_type: GlobalStorageEntryType, + pub parent_index: usize +} + +pub struct GlobalScopeStorage { + pub entry_to_ind: HashMap, + pub entries: Vec, +} + +/// The global storage for every element inside of the scope. +/// +/// This stores the following: +/// - Functions (with or without implementations) +/// - Static variables +/// - Struct functions +/// - Types +/// +/// # Safety +/// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. +impl GlobalScopeStorage { + pub fn new() -> Self { + GlobalScopeStorage { entry_to_ind: HashMap::new(), entries: vec![] } + } + + pub fn append(&mut self, name: EntryKey, entry: GlobalStorageEntryType, origin: &K) -> MaybeDiagnostic { + if self.entry_to_ind.contains_key(&name) { + return Err(make_already_in_scope(origin, &name.name_hash).into()) + } + + let parent_index = self.entries.len(); + + let entry = GlobalStorageEntry { entry_type: entry, parent_index }; + + self.entries.push(entry); + self.entry_to_ind.insert(name, parent_index); + + Ok(()) + } + + pub fn get_base(&mut self, name: EntryKey, origin: &K) -> DiagnosticResult { + if !self.entry_to_ind.contains_key(&name) { + return Err(make_cannot_find(origin, &name.name_hash).into()); + } + + return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) + } +} \ No newline at end of file diff --git a/compiler/diagnostics/src/builders.rs b/compiler/diagnostics/src/builders.rs index 36edf54..956fa2d 100644 --- a/compiler/diagnostics/src/builders.rs +++ b/compiler/diagnostics/src/builders.rs @@ -1,6 +1,6 @@ use std::{fmt::Display}; -use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, NOT_FOUND_USE, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; +use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, CANNOT_FIND, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, NOT_FOUND_USE, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; pub fn make_expected_simple_error(origin: &K, expected: &E, got: &G) -> Diagnostic { origin.make_simple_diagnostic(EXPECTED_TOKEN.0, Level::Error, format!("expected {} but got {}", expected, got), None, vec![], vec![], vec![]) @@ -188,4 +188,8 @@ pub fn make_type_not_partof(ori pub fn make_use_not_found(origin: &K, element: &E, path: &P) -> Diagnostic { origin.make_simple_diagnostic(NOT_FOUND_USE.0, Level::Error, format!("element {} was not found in {}", element, path), None, vec![], vec![], vec![]) +} + +pub fn make_cannot_find(origin: &K, element: &P) -> Diagnostic { + origin.make_simple_diagnostic(CANNOT_FIND.0, Level::Error, format!("cannot find {} in the current scope", element), None, vec![], vec![], vec![]) } \ No newline at end of file diff --git a/compiler/diagnostics/src/errors.rs b/compiler/diagnostics/src/errors.rs index d337b1d..c15c071 100644 --- a/compiler/diagnostics/src/errors.rs +++ b/compiler/diagnostics/src/errors.rs @@ -41,4 +41,5 @@ declare_error!(IR_INSTRUCTION_HELD_VAL, 29, "cannot extract held value from inst // Misc declare_error!(INVALID_TYPE_REQ, 30, "this operation requires a {} type"); declare_error!(TYPE_NOT_PART, 31, "type {} is not part of type {}"); -declare_error!(NOT_FOUND_USE, 32, "element {} was not found in {}"); \ No newline at end of file +declare_error!(NOT_FOUND_USE, 32, "element {} was not found in {}"); +declare_error!(CANNOT_FIND, 33, "cannot find {} in the current scope"); \ No newline at end of file From f6ddd985f696a285af9c5d0be2c7af53d08f0e0a Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 16 Apr 2026 00:42:31 +0200 Subject: [PATCH 31/60] feat: added Display to entries --- compiler/astoir_hir/src/storage.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/astoir_hir/src/storage.rs b/compiler/astoir_hir/src/storage.rs index 1c2f1e7..4218528 100644 --- a/compiler/astoir_hir/src/storage.rs +++ b/compiler/astoir_hir/src/storage.rs @@ -1,9 +1,8 @@ //! The global HIR storage, basically stores types, functions, and more -use std::{collections::{HashMap, btree_map::Entry}, hash::Hash}; +use std::{collections::HashMap, fmt::Display, hash::Hash}; use compiler_typing::tree::Type; -use compiler_utils::{hash::SelfHash}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find}}; use crate::{ctx::HIRFunction, nodes::HIRNode}; @@ -87,4 +86,20 @@ impl GlobalScopeStorage { return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) } +} + +impl Display for GlobalStorageEntryType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Function(_, _) => "function", + Self::ImplLessFunction(_) => "function", + Self::StructFunction(_, _, _) => "function", + Self::StaticVariable(_) => "static variable", + Self::Type(_) => "type" + }; + + write!(f, "{}", s)?; + + Ok(()) + } } \ No newline at end of file From 239cae06249ed1f3823ecc33e3f51376fcc31471 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 16 Apr 2026 00:56:47 +0200 Subject: [PATCH 32/60] feat: added getters to the GlobalScopeStorage to enforce entry type --- compiler/astoir_hir/src/storage.rs | 81 +++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/compiler/astoir_hir/src/storage.rs b/compiler/astoir_hir/src/storage.rs index 4218528..4bb0bb4 100644 --- a/compiler/astoir_hir/src/storage.rs +++ b/compiler/astoir_hir/src/storage.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, fmt::Display, hash::Hash}; use compiler_typing::tree::Type; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find}}; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}}; use crate::{ctx::HIRFunction, nodes::HIRNode}; @@ -79,13 +79,90 @@ impl GlobalScopeStorage { Ok(()) } - pub fn get_base(&mut self, name: EntryKey, origin: &K) -> DiagnosticResult { + pub fn get_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { if !self.entry_to_ind.contains_key(&name) { return Err(make_cannot_find(origin, &name.name_hash).into()); } return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) } + + pub fn get_type(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Type(t) => Ok(t.clone()), + _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()) + }; + } + + pub fn get_static_variable(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), + _ => Err(make_expected_simple_error(origin, &"static variable".to_string(), &base).into()) + }; + } + + pub fn get_function_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(hir, _) => Ok(hir.clone()), + GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + GlobalStorageEntryType::StructFunction(hir, _, _) => Ok(hir.clone()), + + _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()) + }; + } + + pub fn get_function_impl(&self, name: EntryKey, origin: &K) -> DiagnosticResult> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(_, i) => Ok(i.clone()), + GlobalStorageEntryType::StructFunction(_, i, _) => Ok(i.clone()), + + _ => Err(make_expected_simple_error(origin, &"function with implementation", &base).into()) + }; + } + + pub fn get_implless_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + + _ => Err(make_expected_simple_error(origin, &"function without implementation", &base).into()) + } + } + + pub fn get_exact_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(HIRFunction, Box)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(hir, i) => Ok((hir.clone(), i.clone())), + + _ => Err(make_expected_simple_error(origin, &"function", &base).into()) + } + } + + pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(HIRFunction, Box, Type)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StructFunction(hir, i, o) => { + if let GlobalStorageEntryType::Type(t) = self.entries[o].entry_type.clone() { + Ok((hir, i, t)) + } else { + Err(make_expected_simple_error(origin, &"type", &self.entries[0].entry_type).into()) + } + }, + + _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()) + } + } } impl Display for GlobalStorageEntryType { From 50217ba39cd36799aba0b32b3f8eb5d58b598e95 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 16 Apr 2026 00:58:10 +0200 Subject: [PATCH 33/60] feat: added new prelude crate --- Cargo.lock | 4 ++++ Cargo.toml | 2 +- compiler/prelude/Cargo.toml | 6 ++++++ compiler/prelude/README.md | 3 +++ compiler/prelude/src/lib.rs | 0 5 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 compiler/prelude/Cargo.toml create mode 100644 compiler/prelude/README.md create mode 100644 compiler/prelude/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a5fa4b4..90cfa8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,6 +240,10 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prelude" +version = "0.1.0" + [[package]] name = "proc-macro2" version = "1.0.106" diff --git a/Cargo.toml b/Cargo.toml index 293ace9..3b65f4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["compiler/ast", "compiler/ast_parser", "compiler/astoir", "compiler/astoir_hir", "compiler/astoir_hir_lowering", "compiler/astoir_mir", "compiler/compiler_typing", "compiler/astoir_mir_lowering", "compiler/compiler_main", "compiler/compiler_utils", "compiler/llvm_ir_bridge", "compiler/diagnostics"] +members = ["compiler/ast", "compiler/ast_parser", "compiler/astoir", "compiler/astoir_hir", "compiler/astoir_hir_lowering", "compiler/astoir_mir", "compiler/compiler_typing", "compiler/astoir_mir_lowering", "compiler/compiler_main", "compiler/compiler_utils", "compiler/llvm_ir_bridge", "compiler/diagnostics", "compiler/prelude"] diff --git a/compiler/prelude/Cargo.toml b/compiler/prelude/Cargo.toml new file mode 100644 index 0000000..33526a1 --- /dev/null +++ b/compiler/prelude/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "prelude" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/compiler/prelude/README.md b/compiler/prelude/README.md new file mode 100644 index 0000000..423f475 --- /dev/null +++ b/compiler/prelude/README.md @@ -0,0 +1,3 @@ +# Prelude + +The prelude is the crate where every basic thing of the language is defined, that includes types or default functions diff --git a/compiler/prelude/src/lib.rs b/compiler/prelude/src/lib.rs new file mode 100644 index 0000000..e69de29 From 5faa32642e963aaecf25d2ea491c74c79859bbac Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 16 Apr 2026 01:00:57 +0200 Subject: [PATCH 34/60] feat: added prelude apply on HIR --- Cargo.lock | 6 ++++++ compiler/astoir_hir_lowering/Cargo.toml | 3 ++- compiler/astoir_hir_lowering/src/lib.rs | 2 ++ compiler/prelude/Cargo.toml | 3 +++ compiler/prelude/src/lib.rs | 8 ++++++++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 90cfa8f..e0e4fb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,6 +62,7 @@ dependencies = [ "compiler_utils", "diagnostics", "lexer", + "prelude", ] [[package]] @@ -243,6 +244,11 @@ dependencies = [ [[package]] name = "prelude" version = "0.1.0" +dependencies = [ + "astoir_hir", + "compiler_typing", + "diagnostics", +] [[package]] name = "proc-macro2" diff --git a/compiler/astoir_hir_lowering/Cargo.toml b/compiler/astoir_hir_lowering/Cargo.toml index 2d35609..5a6b8da 100644 --- a/compiler/astoir_hir_lowering/Cargo.toml +++ b/compiler/astoir_hir_lowering/Cargo.toml @@ -10,4 +10,5 @@ ast = { path = "../ast" } diagnostics = { path = "../diagnostics" } compiler_utils = { path = "../compiler_utils" } lexer = { path = "../lexer" } -ast_parser = { path = "../ast_parser" } \ No newline at end of file +ast_parser = { path = "../ast_parser" } +prelude = { path = "../prelude" } \ No newline at end of file diff --git a/compiler/astoir_hir_lowering/src/lib.rs b/compiler/astoir_hir_lowering/src/lib.rs index e0deed9..784d1d3 100644 --- a/compiler/astoir_hir_lowering/src/lib.rs +++ b/compiler/astoir_hir_lowering/src/lib.rs @@ -1,6 +1,7 @@ use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos}; +use prelude::apply_prelude; use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, enums::lower_ast_enum, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, uses::handle_ast_use_statement, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}}; @@ -106,6 +107,7 @@ pub fn lower_ast_toplevel(context: &mut HIRContext, node: Box) -> D pub fn lower_ast(ctx: ParserCtx) -> DiagnosticResult { let mut hir_ctx = HIRContext::new(); + apply_prelude(&mut hir_ctx)?; for u in ctx.uses { handle_ast_use_statement(&mut hir_ctx, u)?; diff --git a/compiler/prelude/Cargo.toml b/compiler/prelude/Cargo.toml index 33526a1..36738a4 100644 --- a/compiler/prelude/Cargo.toml +++ b/compiler/prelude/Cargo.toml @@ -4,3 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] +compiler_typing = { path = "../compiler_typing" } +diagnostics = { path = "../diagnostics" } +astoir_hir = { path = "../astoir_hir" } diff --git a/compiler/prelude/src/lib.rs b/compiler/prelude/src/lib.rs index e69de29..29561c2 100644 --- a/compiler/prelude/src/lib.rs +++ b/compiler/prelude/src/lib.rs @@ -0,0 +1,8 @@ +//! The prelude is the environment in where the defaults of the language are loaded + +use astoir_hir::ctx::HIRContext; +use diagnostics::MaybeDiagnostic; + +pub fn apply_prelude(hir: &mut HIRContext) -> MaybeDiagnostic { + unimplemented!() +} \ No newline at end of file From aeafba10902c8def34c24d451320ec449f212637 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:16:46 +0200 Subject: [PATCH 35/60] feat: added sample types in prelude --- Cargo.lock | 1 + compiler/astoir_hir/src/ctx.rs | 7 +- compiler/astoir_hir/src/storage.rs | 13 +-- compiler/prelude/Cargo.toml | 1 + compiler/prelude/src/lib.rs | 10 ++- compiler/prelude/src/types.rs | 127 +++++++++++++++++++++++++++++ 6 files changed, 148 insertions(+), 11 deletions(-) create mode 100644 compiler/prelude/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index e0e4fb7..a9f019e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -247,6 +247,7 @@ version = "0.1.0" dependencies = [ "astoir_hir", "compiler_typing", + "compiler_utils", "diagnostics", ] diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index 57e1228..e73b8e0 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -6,7 +6,7 @@ use compiler_typing::{storage::TypeStorage, tree::Type}; use compiler_utils::{hash::SelfHash, utils::indexed::IndexStorage}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_func, make_cannot_find_var, make_doesnt_exist_in_era}}; -use crate::{nodes::HIRNode, structs::HIRStructContainer}; +use crate::{nodes::HIRNode, storage::GlobalScopeStorage, structs::HIRStructContainer}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); @@ -237,7 +237,8 @@ pub struct HIRContext { pub function_contexts: Vec>, pub static_variables: IndexStorage, pub struct_func_impls: HashMap, - pub type_storage: TypeStorage + pub type_storage: TypeStorage, + pub global_scope: GlobalScopeStorage } #[derive(PartialEq)] @@ -248,7 +249,7 @@ pub enum VariableKind { impl HIRContext { pub fn new() -> Self { - return HIRContext { functions: IndexStorage::new(), static_variables: IndexStorage::new(), type_storage: TypeStorage::new().unwrap(), function_contexts: vec![], function_declarations: vec![], struct_func_impls: HashMap::new() } + return HIRContext { functions: IndexStorage::new(), static_variables: IndexStorage::new(), type_storage: TypeStorage::new().unwrap(), function_contexts: vec![], function_declarations: vec![], struct_func_impls: HashMap::new(), global_scope: GlobalScopeStorage::new() } } pub fn translate_function(&self, func_hash: u64, origin: &K) -> DiagnosticResult { diff --git a/compiler/astoir_hir/src/storage.rs b/compiler/astoir_hir/src/storage.rs index 4bb0bb4..e4f8821 100644 --- a/compiler/astoir_hir/src/storage.rs +++ b/compiler/astoir_hir/src/storage.rs @@ -2,14 +2,14 @@ use std::{collections::HashMap, fmt::Display, hash::Hash}; -use compiler_typing::tree::Type; +use compiler_typing::{raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}}; use crate::{ctx::HIRFunction, nodes::HIRNode}; pub type GlobalStorageIdentifier = usize; -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum GlobalStorageEntryType { Function(HIRFunction, Box), ImplLessFunction(HIRFunction), @@ -17,10 +17,11 @@ pub enum GlobalStorageEntryType { StructFunction(HIRFunction, Box, GlobalStorageIdentifier), - Type(Type) + Type(RawType) } /// Represents a key to a global storage entry. Potentially allows for namespaces later on +#[derive(Debug)] pub struct EntryKey { pub name_hash: u64 } @@ -39,11 +40,13 @@ impl PartialEq for EntryKey { impl Eq for EntryKey {} +#[derive(Debug)] pub struct GlobalStorageEntry { pub entry_type: GlobalStorageEntryType, pub parent_index: usize } +#[derive(Debug)] pub struct GlobalScopeStorage { pub entry_to_ind: HashMap, pub entries: Vec, @@ -87,7 +90,7 @@ impl GlobalScopeStorage { return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) } - pub fn get_type(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + pub fn get_type(&self, name: EntryKey, origin: &K) -> DiagnosticResult { let base = self.get_base(name, origin)?; return match base { @@ -148,7 +151,7 @@ impl GlobalScopeStorage { } } - pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(HIRFunction, Box, Type)> { + pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(HIRFunction, Box, RawType)> { let base = self.get_base(name, origin)?; return match base { diff --git a/compiler/prelude/Cargo.toml b/compiler/prelude/Cargo.toml index 36738a4..3eee720 100644 --- a/compiler/prelude/Cargo.toml +++ b/compiler/prelude/Cargo.toml @@ -5,5 +5,6 @@ edition = "2024" [dependencies] compiler_typing = { path = "../compiler_typing" } +compiler_utils = { path = "../compiler_utils" } diagnostics = { path = "../diagnostics" } astoir_hir = { path = "../astoir_hir" } diff --git a/compiler/prelude/src/lib.rs b/compiler/prelude/src/lib.rs index 29561c2..3abf84b 100644 --- a/compiler/prelude/src/lib.rs +++ b/compiler/prelude/src/lib.rs @@ -1,8 +1,12 @@ //! The prelude is the environment in where the defaults of the language are loaded use astoir_hir::ctx::HIRContext; -use diagnostics::MaybeDiagnostic; +use diagnostics::{DiagnosticSpanOrigin, MaybeDiagnostic}; -pub fn apply_prelude(hir: &mut HIRContext) -> MaybeDiagnostic { - unimplemented!() +use crate::types::apply_prelude_types; + +pub mod types; + +pub fn apply_prelude(hir: &mut HIRContext, origin: &K) -> MaybeDiagnostic { + apply_prelude_types(hir, origin) } \ No newline at end of file diff --git a/compiler/prelude/src/types.rs b/compiler/prelude/src/types.rs new file mode 100644 index 0000000..33ded04 --- /dev/null +++ b/compiler/prelude/src/types.rs @@ -0,0 +1,127 @@ +use astoir_hir::{ctx::HIRContext, storage::{EntryKey, GlobalStorageEntryType}}; +use compiler_typing::{TypeParameterContainer, enums::RawEnumTypeContainer, raw::RawType, references::TypeReference}; +use compiler_utils::hash; +use compiler_utils::hash::{HashedString}; +use diagnostics::{DiagnosticSpanOrigin, MaybeDiagnostic}; + +pub const SIGNED_INTEGER_8: u64 = hash!("s8"); +pub const SIGNED_INTEGER_16: u64 = hash!("s16"); +pub const SIGNED_INTEGER_32: u64 = hash!("s32"); +pub const SIGNED_INTEGER_64: u64 = hash!("s64"); +pub const SIGNED_INTEGER_128: u64 = hash!("s128"); +pub const SIGNED_INTEGER: u64 = hash!("s"); + +pub const UNSIGNED_INTEGER_8: u64 = hash!("u8"); +pub const UNSIGNED_INTEGER_16: u64 = hash!("u16"); +pub const UNSIGNED_INTEGER_32: u64 = hash!("u32"); +pub const UNSIGNED_INTEGER_64: u64 = hash!("u64"); +pub const UNSIGNED_INTEGER_128: u64 = hash!("u128"); +pub const UNSIGNED_INTEGER: u64 = hash!("u"); + +pub const SIGNED_FLOATING_POINT_8: u64 = hash!("f8"); +pub const SIGNED_FLOATING_POINT_16: u64 = hash!("f16"); +pub const SIGNED_FLOATING_POINT_32: u64 = hash!("f32"); +pub const SIGNED_FLOATING_POINT_64: u64 = hash!("f64"); +pub const SIGNED_FLOATING_POINT_80: u64 = hash!("f80"); +pub const SIGNED_FLOATING_POINT_128: u64 = hash!("f128"); +pub const SIGNED_FLOATING_POINT: u64 = hash!("f"); + +pub const SIGNED_FIXED_POINT_8: u64 = hash!("x8"); +pub const SIGNED_FIXED_POINT_16: u64 = hash!("x16"); +pub const SIGNED_FIXED_POINT_32: u64 = hash!("x32"); +pub const SIGNED_FIXED_POINT_64: u64 = hash!("x64"); +pub const SIGNED_FIXED_POINT_128: u64 = hash!("x128"); +pub const SIGNED_FIXED_POINT: u64 = hash!("x"); + +pub const UNSIGNED_FLOATING_POINT_8: u64 = hash!("uf8"); +pub const UNSIGNED_FLOATING_POINT_16: u64 = hash!("uf16"); +pub const UNSIGNED_FLOATING_POINT_32: u64 = hash!("uf32"); +pub const UNSIGNED_FLOATING_POINT_64: u64 = hash!("uf64"); +pub const UNSIGNED_FLOATING_POINT_80: u64 = hash!("uf80"); +pub const UNSIGNED_FLOATING_POINT_128: u64 = hash!("uf128"); +pub const UNSIGNED_FLOATING_POINT: u64 = hash!("uf"); + +pub const UNSIGNED_FIXED_POINT_8: u64 = hash!("ux8"); +pub const UNSIGNED_FIXED_POINT_16: u64 = hash!("ux16"); +pub const UNSIGNED_FIXED_POINT_32: u64 = hash!("ux32"); +pub const UNSIGNED_FIXED_POINT_64: u64 = hash!("ux64"); +pub const UNSIGNED_FIXED_POINT_128: u64 = hash!("ux128"); +pub const UNSIGNED_FIXED_POINT: u64 = hash!("ux"); + +pub const STATIC_STR: u64 = hash!("staticstr"); + +pub const POINTER_TYPE: u64 = hash!("ptr"); +pub const BOOLEAN_TYPE: u64 = hash!("bool"); + +/// Experimental +pub const RESULT_TYPE: u64 = hash!("result"); + +pub fn register_prelude_type(hir: &mut HIRContext, hash: u64, t: RawType, origin: &K) -> MaybeDiagnostic { + hir.global_scope.append(EntryKey { name_hash: hash }, GlobalStorageEntryType::Type(t), origin) +} + +pub fn apply_prelude_types(hir: &mut HIRContext, origin: &K) -> MaybeDiagnostic { + register_prelude_type(hir, SIGNED_INTEGER, RawType::SizedInteger(true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_8, RawType::Integer(8, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_16, RawType::Integer(16, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_32, RawType::Integer(32, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_64, RawType::Integer(64, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_128, RawType::Integer(128, true), origin)?; + + register_prelude_type(hir, UNSIGNED_INTEGER, RawType::SizedInteger(false), origin)?; + register_prelude_type(hir, UNSIGNED_INTEGER_8, RawType::Integer(8, false), origin)?; + register_prelude_type(hir, UNSIGNED_INTEGER_16, RawType::Integer(16, false), origin)?; + register_prelude_type(hir, UNSIGNED_INTEGER_32, RawType::Integer(32, false), origin)?; + register_prelude_type(hir, UNSIGNED_INTEGER_64, RawType::Integer(64, false), origin)?; + register_prelude_type(hir, UNSIGNED_INTEGER_128, RawType::Integer(128, false), origin)?; + + register_prelude_type(hir, SIGNED_FLOATING_POINT, RawType::SizedFloating(true), origin)?; + register_prelude_type(hir, SIGNED_FLOATING_POINT_8, RawType::Floating(8, true), origin)?; + register_prelude_type(hir, SIGNED_FLOATING_POINT_16, RawType::Floating(16, true), origin)?; + register_prelude_type(hir, SIGNED_FLOATING_POINT_32, RawType::Floating(32, true), origin)?; + register_prelude_type(hir, SIGNED_FLOATING_POINT_64, RawType::Floating(64, true), origin)?; + register_prelude_type(hir, SIGNED_FLOATING_POINT_128, RawType::Floating(128, true), origin)?; + + register_prelude_type(hir, UNSIGNED_FLOATING_POINT, RawType::SizedFloating(false), origin)?; + register_prelude_type(hir, UNSIGNED_FLOATING_POINT_8, RawType::Floating(8, false), origin)?; + register_prelude_type(hir, UNSIGNED_FLOATING_POINT_16, RawType::Floating(16, false), origin)?; + register_prelude_type(hir, UNSIGNED_FLOATING_POINT_32, RawType::Floating(32, false), origin)?; + register_prelude_type(hir, UNSIGNED_FLOATING_POINT_64, RawType::Floating(64, false), origin)?; + register_prelude_type(hir, UNSIGNED_FLOATING_POINT_128, RawType::Floating(128, false), origin)?; + + + register_prelude_type(hir, SIGNED_FIXED_POINT, RawType::SizedFixedPoint(true), origin)?; + register_prelude_type(hir, SIGNED_FIXED_POINT_8, RawType::FixedPoint(4, 4, true), origin)?; + register_prelude_type(hir, SIGNED_FIXED_POINT_16, RawType::FixedPoint(8, 8, true), origin)?; + register_prelude_type(hir, SIGNED_FIXED_POINT_32, RawType::FixedPoint(16, 16, true), origin)?; + register_prelude_type(hir, SIGNED_FIXED_POINT_64, RawType::FixedPoint(64, 64, true), origin)?; + register_prelude_type(hir, SIGNED_FIXED_POINT_128, RawType::FixedPoint(128, 128, true), origin)?; + + register_prelude_type(hir, UNSIGNED_FIXED_POINT, RawType::SizedFixedPoint(true), origin)?; + register_prelude_type(hir, UNSIGNED_FIXED_POINT_8, RawType::FixedPoint(4, 4, true), origin)?; + register_prelude_type(hir, UNSIGNED_FIXED_POINT_16, RawType::FixedPoint(8, 8, true), origin)?; + register_prelude_type(hir, UNSIGNED_FIXED_POINT_32, RawType::FixedPoint(16, 16, true), origin)?; + register_prelude_type(hir, UNSIGNED_FIXED_POINT_64, RawType::FixedPoint(64, 64, true), origin)?; + register_prelude_type(hir, UNSIGNED_FIXED_POINT_128, RawType::FixedPoint(128, 128, true), origin)?; + + register_prelude_type(hir, BOOLEAN_TYPE, RawType::Boolean, origin)?; + register_prelude_type(hir, STATIC_STR, RawType::StaticString, origin)?; + register_prelude_type(hir, POINTER_TYPE, RawType::Pointer, origin)?; + + // result + { + let mut type_params = TypeParameterContainer::new(); + + type_params.insert(HashedString::new("V".to_string()), 0); + type_params.insert(HashedString::new("E".to_string()), 1); + + let mut result_enum = RawEnumTypeContainer::new(hir.global_scope.entries.len(), type_params); + + result_enum.append_entry(HashedString::new("value".to_string()), vec![(hash!("val"), TypeReference::make_unresolved(0))]); + result_enum.append_entry(HashedString::new("error".to_string()), vec![(hash!("err"), TypeReference::make_unresolved(1))]); + + register_prelude_type(hir, RESULT_TYPE, RawType::Enum(result_enum), origin)?; + } + + Ok(()) +} \ No newline at end of file From 73587f15d370b85b2fb18977913e62dd2b5ecec8 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Sun, 19 Apr 2026 15:17:31 +0200 Subject: [PATCH 36/60] chore: added dummy origin for prelude applying --- compiler/astoir_hir_lowering/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/astoir_hir_lowering/src/lib.rs b/compiler/astoir_hir_lowering/src/lib.rs index 784d1d3..744a624 100644 --- a/compiler/astoir_hir_lowering/src/lib.rs +++ b/compiler/astoir_hir_lowering/src/lib.rs @@ -107,7 +107,7 @@ pub fn lower_ast_toplevel(context: &mut HIRContext, node: Box) -> D pub fn lower_ast(ctx: ParserCtx) -> DiagnosticResult { let mut hir_ctx = HIRContext::new(); - apply_prelude(&mut hir_ctx)?; + apply_prelude(&mut hir_ctx, &*ctx.map[&ctx.iter_order[0]])?; for u in ctx.uses { handle_ast_use_statement(&mut hir_ctx, u)?; From a1e27cffac9834bf8db2074146f0ff7afbec7449 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:38:40 +0200 Subject: [PATCH 37/60] chore: added global scope crate --- Cargo.lock | 4 ++++ Cargo.toml | 2 +- compiler/compiler_global_scope/Cargo.toml | 6 ++++++ compiler/compiler_global_scope/src/main.rs | 3 +++ 4 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 compiler/compiler_global_scope/Cargo.toml create mode 100644 compiler/compiler_global_scope/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index a9f019e..5cdc38f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,6 +116,10 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "compiler_global_scope" +version = "0.1.0" + [[package]] name = "compiler_main" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 3b65f4b..03da646 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["compiler/ast", "compiler/ast_parser", "compiler/astoir", "compiler/astoir_hir", "compiler/astoir_hir_lowering", "compiler/astoir_mir", "compiler/compiler_typing", "compiler/astoir_mir_lowering", "compiler/compiler_main", "compiler/compiler_utils", "compiler/llvm_ir_bridge", "compiler/diagnostics", "compiler/prelude"] +members = ["compiler/ast", "compiler/ast_parser", "compiler/astoir", "compiler/astoir_hir", "compiler/astoir_hir_lowering", "compiler/astoir_mir", "compiler/compiler_typing", "compiler/astoir_mir_lowering", "compiler/compiler_main", "compiler/compiler_utils", "compiler/llvm_ir_bridge", "compiler/diagnostics", "compiler/prelude", "compiler/compiler_global_scope"] diff --git a/compiler/compiler_global_scope/Cargo.toml b/compiler/compiler_global_scope/Cargo.toml new file mode 100644 index 0000000..6405f36 --- /dev/null +++ b/compiler/compiler_global_scope/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "compiler_global_scope" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/compiler/compiler_global_scope/src/main.rs b/compiler/compiler_global_scope/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/compiler/compiler_global_scope/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} From 7deb23cf23474e4afb5a9a300326e6e929f8b94b Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:46:02 +0200 Subject: [PATCH 38/60] feat: added global scope storage definition --- Cargo.lock | 3 + compiler/compiler_global_scope/Cargo.toml | 1 + compiler/compiler_global_scope/src/entry.rs | 38 ++++++ compiler/compiler_global_scope/src/key.rs | 21 +++ compiler/compiler_global_scope/src/lib.rs | 134 ++++++++++++++++++++ compiler/compiler_global_scope/src/main.rs | 3 - 6 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 compiler/compiler_global_scope/src/entry.rs create mode 100644 compiler/compiler_global_scope/src/key.rs create mode 100644 compiler/compiler_global_scope/src/lib.rs delete mode 100644 compiler/compiler_global_scope/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 5cdc38f..a029fb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,6 +119,9 @@ dependencies = [ [[package]] name = "compiler_global_scope" version = "0.1.0" +dependencies = [ + "diagnostics", +] [[package]] name = "compiler_main" diff --git a/compiler/compiler_global_scope/Cargo.toml b/compiler/compiler_global_scope/Cargo.toml index 6405f36..1d95971 100644 --- a/compiler/compiler_global_scope/Cargo.toml +++ b/compiler/compiler_global_scope/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" edition = "2024" [dependencies] +diagnostics = { path = "../diagnostics" } \ No newline at end of file diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs new file mode 100644 index 0000000..198c7bc --- /dev/null +++ b/compiler/compiler_global_scope/src/entry.rs @@ -0,0 +1,38 @@ +//! Definitions for entries + +use std::fmt::Display; + +use crate::{GlobalStorageIdentifier}; + +#[derive(Clone, Debug)] +pub enum GlobalStorageEntryType { + Function(F, I), + ImplLessFunction(F), + StaticVariable(T), + + StructFunction(F, I, GlobalStorageIdentifier), + + Type(R) +} + +#[derive(Debug)] +pub struct GlobalStorageEntry { + pub entry_type: GlobalStorageEntryType, + pub parent_index: usize +} + +impl Display for GlobalStorageEntryType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Function(_, _) => "function", + Self::ImplLessFunction(_) => "function", + Self::StructFunction(_, _, _) => "function", + Self::StaticVariable(_) => "static variable", + Self::Type(_) => "type" + }; + + write!(f, "{}", s)?; + + Ok(()) + } +} \ No newline at end of file diff --git a/compiler/compiler_global_scope/src/key.rs b/compiler/compiler_global_scope/src/key.rs new file mode 100644 index 0000000..73f7cb3 --- /dev/null +++ b/compiler/compiler_global_scope/src/key.rs @@ -0,0 +1,21 @@ +use std::hash::Hash; + +/// Represents a key to a global storage entry. Potentially allows for namespaces later on +#[derive(Debug)] +pub struct EntryKey { + pub name_hash: u64 +} + +impl Hash for EntryKey { + fn hash(&self, state: &mut H) { + state.write_u64(self.name_hash); + } +} + +impl PartialEq for EntryKey { + fn eq(&self, other: &Self) -> bool { + self.name_hash == other.name_hash + } +} + +impl Eq for EntryKey {} \ No newline at end of file diff --git a/compiler/compiler_global_scope/src/lib.rs b/compiler/compiler_global_scope/src/lib.rs new file mode 100644 index 0000000..6b6b446 --- /dev/null +++ b/compiler/compiler_global_scope/src/lib.rs @@ -0,0 +1,134 @@ +use std::collections::HashMap; + +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}}; + +use crate::{entry::{GlobalStorageEntry, GlobalStorageEntryType}, key::EntryKey}; + +pub mod entry; +pub mod key; + +pub type GlobalStorageIdentifier = usize; + + +#[derive(Debug)] +pub struct GlobalScopeStorage { + pub entry_to_ind: HashMap, + pub entries: Vec>, +} + + +/// The global storage for every element inside of the scope. +/// +/// This stores the following: +/// - Functions (with or without implementations) +/// - Static variables +/// - Struct functions +/// - Types +/// +/// # Safety +/// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. +impl GlobalScopeStorage { + pub fn new() -> Self { + GlobalScopeStorage { entry_to_ind: HashMap::new(), entries: vec![] } + } + + pub fn append(&mut self, name: EntryKey, entry: GlobalStorageEntryType, origin: &K) -> MaybeDiagnostic { + if self.entry_to_ind.contains_key(&name) { + return Err(make_already_in_scope(origin, &name.name_hash).into()) + } + + let parent_index = self.entries.len(); + + let entry = GlobalStorageEntry { entry_type: entry, parent_index }; + + self.entries.push(entry); + self.entry_to_ind.insert(name, parent_index); + + Ok(()) + } + + pub fn get_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult> { + if !self.entry_to_ind.contains_key(&name) { + return Err(make_cannot_find(origin, &name.name_hash).into()); + } + + return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) + } + + pub fn get_type(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Type(t) => Ok(t.clone()), + _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()) + }; + } + + pub fn get_static_variable(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), + _ => Err(make_expected_simple_error(origin, &"static variable".to_string(), &base).into()) + }; + } + + pub fn get_function_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(hir, _) => Ok(hir.clone()), + GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + GlobalStorageEntryType::StructFunction(hir, _, _) => Ok(hir.clone()), + + _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()) + }; + } + + pub fn get_function_impl(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(_, i) => Ok(i.clone()), + GlobalStorageEntryType::StructFunction(_, i, _) => Ok(i.clone()), + + _ => Err(make_expected_simple_error(origin, &"function with implementation", &base).into()) + }; + } + + pub fn get_implless_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + + _ => Err(make_expected_simple_error(origin, &"function without implementation", &base).into()) + } + } + + pub fn get_exact_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(F, I)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(hir, i) => Ok((hir.clone(), i.clone())), + + _ => Err(make_expected_simple_error(origin, &"function", &base).into()) + } + } + + pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(F, I, R)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StructFunction(hir, i, o) => { + if let GlobalStorageEntryType::Type(t) = self.entries[o].entry_type.clone() { + Ok((hir, i, t)) + } else { + Err(make_expected_simple_error(origin, &"type", &self.entries[0].entry_type).into()) + } + }, + + _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()) + } + } +} diff --git a/compiler/compiler_global_scope/src/main.rs b/compiler/compiler_global_scope/src/main.rs deleted file mode 100644 index e7a11a9..0000000 --- a/compiler/compiler_global_scope/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} From 2ae03b45ffd2e206fac2d3eda628a5a65393c7f2 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:47:36 +0200 Subject: [PATCH 39/60] feat: added binding in compiler_typing --- Cargo.lock | 1 + compiler/compiler_typing/Cargo.toml | 3 ++- compiler/compiler_typing/src/lib.rs | 5 ++++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a029fb1..263cedb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,6 +140,7 @@ dependencies = [ name = "compiler_typing" version = "0.1.0" dependencies = [ + "compiler_global_scope", "compiler_utils", "diagnostics", ] diff --git a/compiler/compiler_typing/Cargo.toml b/compiler/compiler_typing/Cargo.toml index 6c59dd5..b5a9109 100644 --- a/compiler/compiler_typing/Cargo.toml +++ b/compiler/compiler_typing/Cargo.toml @@ -5,4 +5,5 @@ edition = "2024" [dependencies] compiler_utils = { path = "../compiler_utils" } -diagnostics = { path = "../diagnostics" } \ No newline at end of file +compiler_global_scope = { path = "../compiler_global_scope" } +diagnostics = { path = "../diagnostics" } diff --git a/compiler/compiler_typing/src/lib.rs b/compiler/compiler_typing/src/lib.rs index e5be3c5..a003dab 100644 --- a/compiler/compiler_typing/src/lib.rs +++ b/compiler/compiler_typing/src/lib.rs @@ -2,10 +2,11 @@ use std::collections::HashMap; +use compiler_global_scope::GlobalScopeStorage; use compiler_utils::{hash::HashedString}; use diagnostics::DiagnosticResult; -use crate::{references::TypeReference, storage::TypeStorage, tree::Type}; +use crate::{raw::RawType, references::TypeReference, storage::TypeStorage, tree::Type}; pub mod tree; pub mod raw; @@ -17,6 +18,8 @@ pub mod storage; pub mod transmutation; pub mod bounds; +pub type TypedGlobalScope = GlobalScopeStorage; + /// A function contained within a type. pub type TypedFunction = (Vec<(u64, TypeReference)>, Option); pub type TypedResolvedFunction = (Vec<(u64, Type)>, Option); From c9ecc433e906c2de4de8e74187087f5c77c9e660 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 22:08:53 +0200 Subject: [PATCH 40/60] feat: changed to use indexes for non type items --- compiler/compiler_global_scope/src/entry.rs | 26 ++++++------ compiler/compiler_global_scope/src/lib.rs | 45 +++++++++++---------- 2 files changed, 38 insertions(+), 33 deletions(-) diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs index 198c7bc..7318e02 100644 --- a/compiler/compiler_global_scope/src/entry.rs +++ b/compiler/compiler_global_scope/src/entry.rs @@ -2,33 +2,35 @@ use std::fmt::Display; -use crate::{GlobalStorageIdentifier}; +use crate::GlobalStorageIdentifier; #[derive(Clone, Debug)] -pub enum GlobalStorageEntryType { - Function(F, I), - ImplLessFunction(F), +pub enum GlobalStorageEntryType { + Function { descriptor_ind: usize, impl_ind: usize }, + ImplLessFunction(usize), + StructFunction { descriptor_ind: usize, impl_ind: usize, struct_type: GlobalStorageIdentifier }, + StaticVariable(T), - StructFunction(F, I, GlobalStorageIdentifier), - + TypeAlias(T), Type(R) } #[derive(Debug)] -pub struct GlobalStorageEntry { - pub entry_type: GlobalStorageEntryType, +pub struct GlobalStorageEntry { + pub entry_type: GlobalStorageEntryType, pub parent_index: usize } -impl Display for GlobalStorageEntryType { +impl Display for GlobalStorageEntryType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { - Self::Function(_, _) => "function", + Self::Function { .. } => "function", Self::ImplLessFunction(_) => "function", - Self::StructFunction(_, _, _) => "function", + Self::StructFunction { .. } => "function", Self::StaticVariable(_) => "static variable", - Self::Type(_) => "type" + Self::Type(_) => "type", + Self::TypeAlias(_) => "type (alias)" }; write!(f, "{}", s)?; diff --git a/compiler/compiler_global_scope/src/lib.rs b/compiler/compiler_global_scope/src/lib.rs index 6b6b446..b8ab3b0 100644 --- a/compiler/compiler_global_scope/src/lib.rs +++ b/compiler/compiler_global_scope/src/lib.rs @@ -11,9 +11,12 @@ pub type GlobalStorageIdentifier = usize; #[derive(Debug)] -pub struct GlobalScopeStorage { +pub struct GlobalScopeStorage { pub entry_to_ind: HashMap, - pub entries: Vec>, + pub entries: Vec>, + + pub descriptor_counter: usize, + pub impl_counter: usize } @@ -27,12 +30,12 @@ pub struct GlobalScopeStorage { /// /// # Safety /// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. -impl GlobalScopeStorage { +impl GlobalScopeStorage { pub fn new() -> Self { - GlobalScopeStorage { entry_to_ind: HashMap::new(), entries: vec![] } + GlobalScopeStorage { entry_to_ind: HashMap::new(), entries: vec![], descriptor_counter: 0, impl_counter: 0 } } - pub fn append(&mut self, name: EntryKey, entry: GlobalStorageEntryType, origin: &K) -> MaybeDiagnostic { + pub fn append(&mut self, name: EntryKey, entry: GlobalStorageEntryType, origin: &K) -> MaybeDiagnostic { if self.entry_to_ind.contains_key(&name) { return Err(make_already_in_scope(origin, &name.name_hash).into()) } @@ -47,7 +50,7 @@ impl GlobalScopeStorage { Ok(()) } - pub fn get_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult> { + pub fn get_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult> { if !self.entry_to_ind.contains_key(&name) { return Err(make_cannot_find(origin, &name.name_hash).into()); } @@ -73,56 +76,56 @@ impl GlobalScopeStorage { }; } - pub fn get_function_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + pub fn get_function_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { let base = self.get_base(name, origin)?; return match base { - GlobalStorageEntryType::Function(hir, _) => Ok(hir.clone()), - GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), - GlobalStorageEntryType::StructFunction(hir, _, _) => Ok(hir.clone()), + GlobalStorageEntryType::Function { descriptor_ind, impl_ind: _ } => Ok(descriptor_ind), + GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), + GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind: _, struct_type: _} => Ok(descriptor_ind), _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()) }; } - pub fn get_function_impl(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + pub fn get_function_impl(&self, name: EntryKey, origin: &K) -> DiagnosticResult { let base = self.get_base(name, origin)?; return match base { - GlobalStorageEntryType::Function(_, i) => Ok(i.clone()), - GlobalStorageEntryType::StructFunction(_, i, _) => Ok(i.clone()), + GlobalStorageEntryType::Function { descriptor_ind: _, impl_ind } => Ok(impl_ind), + GlobalStorageEntryType::StructFunction { descriptor_ind: _, impl_ind, struct_type: _ } => Ok(impl_ind), _ => Err(make_expected_simple_error(origin, &"function with implementation", &base).into()) }; } - pub fn get_implless_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult { + pub fn get_implless_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult { let base = self.get_base(name, origin)?; return match base { - GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), _ => Err(make_expected_simple_error(origin, &"function without implementation", &base).into()) } } - pub fn get_exact_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(F, I)> { + pub fn get_exact_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(usize, usize)> { let base = self.get_base(name, origin)?; return match base { - GlobalStorageEntryType::Function(hir, i) => Ok((hir.clone(), i.clone())), + GlobalStorageEntryType::Function { descriptor_ind, impl_ind} => Ok((descriptor_ind, impl_ind)), _ => Err(make_expected_simple_error(origin, &"function", &base).into()) } } - pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(F, I, R)> { + pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(usize, usize, R)> { let base = self.get_base(name, origin)?; return match base { - GlobalStorageEntryType::StructFunction(hir, i, o) => { - if let GlobalStorageEntryType::Type(t) = self.entries[o].entry_type.clone() { - Ok((hir, i, t)) + GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind, struct_type } => { + if let GlobalStorageEntryType::Type(t) = self.entries[struct_type].entry_type.clone() { + Ok((descriptor_ind, impl_ind, t)) } else { Err(make_expected_simple_error(origin, &"type", &self.entries[0].entry_type).into()) } From fb8bfdc41637d1e6a71e37a7545246f238b4de00 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 22:25:35 +0200 Subject: [PATCH 41/60] feat: added util conversion functions on GlobalStorageEntry --- compiler/compiler_global_scope/src/entry.rs | 52 +++++++++++++++++++++ compiler/compiler_typing/src/lib.rs | 16 +++---- compiler/compiler_typing/src/raw.rs | 8 ++-- compiler/compiler_typing/src/storage.rs | 1 + 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs index 7318e02..c430b90 100644 --- a/compiler/compiler_global_scope/src/entry.rs +++ b/compiler/compiler_global_scope/src/entry.rs @@ -2,6 +2,8 @@ use std::fmt::Display; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_expected_simple_error}; + use crate::GlobalStorageIdentifier; #[derive(Clone, Debug)] @@ -16,6 +18,56 @@ pub enum GlobalStorageEntryType { Type(R) } +impl GlobalStorageEntry { + pub fn as_function(&self, origin: &K) -> DiagnosticResult<(usize, usize)> { + match self.entry_type { + GlobalStorageEntryType::Function { descriptor_ind, impl_ind } => Ok((descriptor_ind, impl_ind)), + + _ => Err(make_expected_simple_error(origin, &"function".to_string(), &self.entry_type).into()) + } + } + + pub fn as_implless_function(&self, origin: &K) -> DiagnosticResult { + match self.entry_type { + GlobalStorageEntryType::ImplLessFunction(ind) => Ok(ind), + + _ => Err(make_expected_simple_error(origin, &"implless function".to_string(), &self.entry_type).into()) + } + } + + pub fn as_struct_function(&self, origin: &K) -> DiagnosticResult<(usize, usize, GlobalStorageIdentifier)> { + match self.entry_type { + GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind, struct_type } => Ok((descriptor_ind, impl_ind, struct_type)), + + _ => Err(make_expected_simple_error(origin, &"struct function".to_string(), &self.entry_type).into()) + } + } + + pub fn as_static_variable(&self, origin: &K) -> DiagnosticResult { + match &self.entry_type { + GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), + + _ => Err(make_expected_simple_error(origin, &"static variable".to_string(), &self.entry_type).into()) + } + } + + pub fn as_type_alias(&self, origin: &K) -> DiagnosticResult { + match &self.entry_type { + GlobalStorageEntryType::TypeAlias(t) => Ok(t.clone()), + + _ => Err(make_expected_simple_error(origin, &"type alias".to_string(), &self.entry_type).into()) + } + } + + pub fn as_type(&self, origin: &K) -> DiagnosticResult { + match &self.entry_type { + GlobalStorageEntryType::Type(t) => Ok(t.clone()), + + _ => Err(make_expected_simple_error(origin, &"type".to_string(), &self.entry_type).into()) + } + } +} + #[derive(Debug)] pub struct GlobalStorageEntry { pub entry_type: GlobalStorageEntryType, diff --git a/compiler/compiler_typing/src/lib.rs b/compiler/compiler_typing/src/lib.rs index a003dab..1e005d4 100644 --- a/compiler/compiler_typing/src/lib.rs +++ b/compiler/compiler_typing/src/lib.rs @@ -18,7 +18,7 @@ pub mod storage; pub mod transmutation; pub mod bounds; -pub type TypedGlobalScope = GlobalScopeStorage; +pub type TypedGlobalScope = GlobalScopeStorage; /// A function contained within a type. pub type TypedFunction = (Vec<(u64, TypeReference)>, Option); @@ -31,7 +31,7 @@ pub type RawTypeReference = usize; /// Represents a basic type that has a size. pub trait SizedType { /// Obtains the size of the type. The `compacted_size` parameter determines if the compacted size should be returned or not - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize; + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize; } /// Represents a type that contains type parameters @@ -46,20 +46,20 @@ pub trait TypeParamType { /// Represents types that can contain functions and more pub trait StructuredType { #[must_use = "Must set the diagnostic position beforehand"] - fn get_function(&self, hash: u64, storage: &TypeStorage) -> DiagnosticResult; + fn get_function(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; #[must_use = "Must set the diagnostic position beforehand"] - fn get_function_hash(&self, hash: u64, storage: &TypeStorage) -> DiagnosticResult; + fn get_function_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; #[must_use = "Must set the diagnostic position beforehand"] - fn get_field(&self, hash: u64, storage: &TypeStorage) -> DiagnosticResult; + fn get_field(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; #[must_use = "Must set the diagnostic position beforehand"] - fn get_field_hash(&self, hash: u64, storage: &TypeStorage) -> DiagnosticResult; + fn get_field_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; #[must_use = "Must set the diagnostic position beforehand"] - fn get_fields(&self, storage: &TypeStorage) -> Vec; + fn get_fields(&self, storage: &TypedGlobalScope) -> Vec; #[must_use = "Must set the diagnostic position beforehand"] - fn get_functions(&self, storage: &TypeStorage) -> Vec; + fn get_functions(&self, storage: &TypedGlobalScope) -> Vec; } \ No newline at end of file diff --git a/compiler/compiler_typing/src/raw.rs b/compiler/compiler_typing/src/raw.rs index 35eb545..feb0862 100644 --- a/compiler/compiler_typing/src/raw.rs +++ b/compiler/compiler_typing/src/raw.rs @@ -2,7 +2,7 @@ use std::{fmt::Display, hash::Hash}; -use crate::{SizedType, bounds::traits::Trait, enums::{RawEnumEntryContainer, RawEnumTypeContainer}, storage::TypeStorage, structs::{LoweredStructTypeContainer, RawStructTypeContainer}, tree::Type, utils::get_pointer_size}; +use crate::{SizedType, TypedGlobalScope, bounds::traits::Trait, enums::{RawEnumEntryContainer, RawEnumTypeContainer}, storage::TypeStorage, structs::{LoweredStructTypeContainer, RawStructTypeContainer}, tree::Type, utils::get_pointer_size}; /// The raw types. Are also named generics #[derive(Clone, Debug, PartialEq, Eq)] @@ -37,10 +37,10 @@ impl RawType { return RawType::Integer(bits, false) } - pub fn get_type_params_count(&self, storage: &TypeStorage) -> usize { + pub fn get_type_params_count(&self, storage: &TypedGlobalScope) -> usize { match self { RawType::Enum(container) => container.type_params.len(), - RawType::EnumEntry(container) => storage.types.vals[container.parent].get_type_params_count(storage), + RawType::EnumEntry(container), RawType::Struct(_, container) => container.type_params.len(), _ => 0 @@ -180,7 +180,7 @@ impl RawType { } impl SizedType for RawType { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize { + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { match self { RawType::Integer(size, _) => *size, RawType::Floating(size, _) => *size, diff --git a/compiler/compiler_typing/src/storage.rs b/compiler/compiler_typing/src/storage.rs index 66d6028..3130fa6 100644 --- a/compiler/compiler_typing/src/storage.rs +++ b/compiler/compiler_typing/src/storage.rs @@ -58,6 +58,7 @@ pub const BOOLEAN_TYPE: u64 = hash!("bool"); pub const RESULT_TYPE: u64 = hash!("result"); #[derive(Debug)] +#[deprecated = "Deprecated to use global scope"] pub struct TypeStorage { pub types: IndexStorage, pub type_to_ind: HashMap From 0e62c744508ee7e29273717f637cb94816a5a471 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 22:50:28 +0200 Subject: [PATCH 42/60] chore: formatted everything using rustfmt --- compiler/ast/src/ctx.rs | 37 +- compiler/ast/src/lib.rs | 6 +- compiler/ast/src/operators.rs | 192 ++- compiler/ast/src/tree.rs | 500 ++++-- compiler/ast/src/types.rs | 60 +- compiler/ast_parser/src/arrays.rs | 27 +- compiler/ast_parser/src/comp.rs | 31 +- compiler/ast_parser/src/control/for_loop.rs | 55 +- compiler/ast_parser/src/control/if_else.rs | 145 +- compiler/ast_parser/src/control/mod.rs | 2 +- .../ast_parser/src/control/while_block.rs | 33 +- .../ast_parser/src/functions/arguments.rs | 75 +- compiler/ast_parser/src/functions/mod.rs | 137 +- compiler/ast_parser/src/functions/returns.rs | 21 +- compiler/ast_parser/src/functions/shadow.rs | 63 +- compiler/ast_parser/src/lib.rs | 42 +- compiler/ast_parser/src/literals.rs | 37 +- compiler/ast_parser/src/math.rs | 56 +- compiler/ast_parser/src/parser.rs | 193 ++- compiler/ast_parser/src/structs/enums.rs | 140 +- compiler/ast_parser/src/structs/members.rs | 28 +- compiler/ast_parser/src/structs/mod.rs | 71 +- compiler/ast_parser/src/structs/val.rs | 58 +- compiler/ast_parser/src/types.rs | 338 ++-- compiler/ast_parser/src/unwraps.rs | 99 +- compiler/ast_parser/src/use_statements.rs | 66 +- compiler/ast_parser/src/value.rs | 519 +++--- compiler/ast_parser/src/variables/decl.rs | 51 +- compiler/ast_parser/src/variables/mod.rs | 2 +- .../ast_parser/src/variables/static_decl.rs | 39 +- compiler/astoir/src/lib.rs | 14 +- compiler/astoir_hir/src/ctx.rs | 488 +++--- compiler/astoir_hir/src/lib.rs | 6 +- compiler/astoir_hir/src/nodes.rs | 734 +++++--- compiler/astoir_hir/src/resolve.rs | 90 +- compiler/astoir_hir/src/storage.rs | 330 ++-- compiler/astoir_hir/src/structs.rs | 26 +- compiler/astoir_hir_lowering/src/arrays.rs | 92 +- compiler/astoir_hir_lowering/src/bools.rs | 89 +- compiler/astoir_hir_lowering/src/control.rs | 205 ++- compiler/astoir_hir_lowering/src/enums.rs | 92 +- compiler/astoir_hir_lowering/src/func.rs | 278 ++-- compiler/astoir_hir_lowering/src/lib.rs | 229 ++- compiler/astoir_hir_lowering/src/literals.rs | 49 +- compiler/astoir_hir_lowering/src/math.rs | 65 +- compiler/astoir_hir_lowering/src/structs.rs | 244 ++- compiler/astoir_hir_lowering/src/types.rs | 228 +-- compiler/astoir_hir_lowering/src/unwraps.rs | 94 +- compiler/astoir_hir_lowering/src/uses.rs | 355 ++-- compiler/astoir_hir_lowering/src/values.rs | 478 +++--- compiler/astoir_hir_lowering/src/var.rs | 195 ++- compiler/astoir_mir/src/blocks/hints.rs | 175 +- compiler/astoir_mir/src/blocks/mod.rs | 318 ++-- compiler/astoir_mir/src/blocks/refer.rs | 2 +- compiler/astoir_mir/src/builder.rs | 1313 ++++++++++----- compiler/astoir_mir/src/ctx.rs | 218 +-- compiler/astoir_mir/src/funcs.rs | 129 +- compiler/astoir_mir/src/inst_writer.rs | 26 +- compiler/astoir_mir/src/insts/mod.rs | 995 +++++++---- compiler/astoir_mir/src/insts/val.rs | 24 +- compiler/astoir_mir/src/lib.rs | 12 +- compiler/astoir_mir/src/vals/arrays.rs | 32 +- compiler/astoir_mir/src/vals/base.rs | 75 +- compiler/astoir_mir/src/vals/consts.rs | 6 +- compiler/astoir_mir/src/vals/float.rs | 43 +- compiler/astoir_mir/src/vals/int.rs | 54 +- compiler/astoir_mir/src/vals/mod.rs | 34 +- compiler/astoir_mir/src/vals/ptr.rs | 37 +- compiler/astoir_mir/src/vals/refer.rs | 218 +-- compiler/astoir_mir/src/vals/structs.rs | 35 +- compiler/astoir_mir_lowering/src/arrays.rs | 75 +- compiler/astoir_mir_lowering/src/body.rs | 112 +- compiler/astoir_mir_lowering/src/casts.rs | 60 +- .../src/control/forloop.rs | 73 +- .../src/control/ifstatement.rs | 161 +- .../astoir_mir_lowering/src/control/mod.rs | 2 +- compiler/astoir_mir_lowering/src/funcs.rs | 157 +- .../astoir_mir_lowering/src/introductions.rs | 85 +- compiler/astoir_mir_lowering/src/lib.rs | 282 ++-- compiler/astoir_mir_lowering/src/lru.rs | 84 +- compiler/astoir_mir_lowering/src/math.rs | 204 ++- .../astoir_mir_lowering/src/type_tools.rs | 292 ++-- .../src/values/booleans.rs | 78 +- .../astoir_mir_lowering/src/values/consts.rs | 62 +- .../astoir_mir_lowering/src/values/mod.rs | 148 +- .../astoir_mir_lowering/src/values/structs.rs | 91 +- compiler/astoir_mir_lowering/src/vars.rs | 166 +- compiler/compiler_global_scope/src/entry.rs | 249 ++- compiler/compiler_global_scope/src/key.rs | 16 +- compiler/compiler_global_scope/src/lib.rs | 308 ++-- compiler/compiler_main/Cargo.toml | 4 +- compiler/compiler_main/src/cmds/astoir.rs | 138 +- compiler/compiler_main/src/cmds/mod.rs | 2 +- compiler/compiler_main/src/main.rs | 30 +- compiler/compiler_typing/src/bounds/mod.rs | 2 +- compiler/compiler_typing/src/bounds/normal.rs | 82 +- compiler/compiler_typing/src/bounds/traits.rs | 98 +- compiler/compiler_typing/src/enums.rs | 368 ++-- compiler/compiler_typing/src/lib.rs | 61 +- compiler/compiler_typing/src/raw.rs | 611 +++---- compiler/compiler_typing/src/references.rs | 85 +- compiler/compiler_typing/src/storage.rs | 162 -- compiler/compiler_typing/src/structs.rs | 201 +-- .../src/transmutation/array.rs | 22 +- .../compiler_typing/src/transmutation/mod.rs | 96 +- compiler/compiler_typing/src/tree.rs | 563 ++++--- compiler/compiler_typing/src/utils.rs | 16 +- compiler/compiler_utils/src/hash.rs | 73 +- compiler/compiler_utils/src/lib.rs | 46 +- compiler/compiler_utils/src/operators.rs | 32 +- compiler/compiler_utils/src/utils/indexed.rs | 47 +- compiler/compiler_utils/src/utils/map.rs | 96 +- compiler/compiler_utils/src/utils/mod.rs | 2 +- compiler/compiler_utils/src/utils/num.rs | 20 +- compiler/diagnostics/src/builders.rs | 697 ++++++-- compiler/diagnostics/src/diagnostic.rs | 492 +++--- compiler/diagnostics/src/errors.rs | 98 +- compiler/diagnostics/src/infos.rs | 18 +- compiler/diagnostics/src/lib.rs | 78 +- compiler/diagnostics/src/warnings.rs | 30 +- compiler/lexer/Cargo.toml | 2 +- compiler/lexer/src/lexer.rs | 355 ++-- compiler/lexer/src/lib.rs | 8 +- compiler/lexer/src/token.rs | 378 +++-- compiler/llvm_ir_bridge/Cargo.toml | 6 +- compiler/llvm_ir_bridge/src/blocks.rs | 55 +- compiler/llvm_ir_bridge/src/ctx.rs | 54 +- compiler/llvm_ir_bridge/src/funcs.rs | 58 +- compiler/llvm_ir_bridge/src/insts.rs | 1481 ++++++++++------- compiler/llvm_ir_bridge/src/lib.rs | 46 +- compiler/llvm_ir_bridge/src/types.rs | 165 +- compiler/llvm_ir_bridge/src/utils.rs | 90 +- compiler/prelude/src/lib.rs | 4 +- compiler/prelude/src/types.rs | 303 +++- 134 files changed, 12953 insertions(+), 8277 deletions(-) delete mode 100644 compiler/compiler_typing/src/storage.rs diff --git a/compiler/ast/src/ctx.rs b/compiler/ast/src/ctx.rs index 0b5ed02..20a8b3c 100644 --- a/compiler/ast/src/ctx.rs +++ b/compiler/ast/src/ctx.rs @@ -1,28 +1,31 @@ -use std::{collections::HashMap}; +use std::collections::HashMap; use crate::tree::ASTTreeNode; #[derive(Debug)] pub struct ParserCtx { - pub map: HashMap>, - pub uses: Vec>, - pub iter_order: Vec + pub map: HashMap>, + pub uses: Vec>, + pub iter_order: Vec, } impl ParserCtx { - pub fn new() -> Self { - return ParserCtx { map: HashMap::new(), iter_order: Vec::new(), uses: vec![] } - } + pub fn new() -> Self { + return ParserCtx { + map: HashMap::new(), + iter_order: Vec::new(), + uses: vec![], + }; + } - pub fn insert(&mut self, name: String, node: Box) -> bool { - if !node.kind.is_tree_permissible() { - return false; - } + pub fn insert(&mut self, name: String, node: Box) -> bool { + if !node.kind.is_tree_permissible() { + return false; + } - self.iter_order.push(name.clone()); + self.iter_order.push(name.clone()); - self.map.insert(name, node); - return true; - } - -} \ No newline at end of file + self.map.insert(name, node); + return true; + } +} diff --git a/compiler/ast/src/lib.rs b/compiler/ast/src/lib.rs index 688dee0..3725aee 100644 --- a/compiler/ast/src/lib.rs +++ b/compiler/ast/src/lib.rs @@ -1,8 +1,8 @@ //! //! The AST module of Quickfall. Contains all of the AST code required for the Quickfall language. -//! +//! -pub mod tree; pub mod ctx; +pub mod operators; +pub mod tree; pub mod types; -pub mod operators; \ No newline at end of file diff --git a/compiler/ast/src/operators.rs b/compiler/ast/src/operators.rs index 6faf312..6da2475 100644 --- a/compiler/ast/src/operators.rs +++ b/compiler/ast/src/operators.rs @@ -4,95 +4,107 @@ use compiler_utils::operators::{ComparingOperator, MathOperator, MathOperatorTyp use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; use lexer::token::{LexerToken, LexerTokenType}; -pub fn parse_math_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { - let op = match tokens[*ind].tok_type { - LexerTokenType::Plus => MathOperatorType::Add, - LexerTokenType::PercentSign => MathOperatorType::Modulo, - LexerTokenType::Minus => MathOperatorType::Subtract, - LexerTokenType::Asterisk => { - if tokens[*ind + 1].tok_type == LexerTokenType::Asterisk { - *ind += 1; - - MathOperatorType::ShiftLeft - } else { - MathOperatorType::Multiply - } - } - LexerTokenType::Divide => { - if tokens[*ind + 1].tok_type == LexerTokenType::Divide { - *ind += 1; - - MathOperatorType::ShiftRight - } else { - MathOperatorType::Divide - } - } - - _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) - }; - - *ind += 1; - - let assigns = match tokens[*ind].tok_type { - LexerTokenType::EqualSign => true, - _ => false - }; - - if assigns { - *ind += 1; - } - - let fast = match tokens[*ind].tok_type { - LexerTokenType::Tidle => true, - _ => false - }; - - if fast { - *ind += 1; - } - - return Ok(MathOperator { operator: op, assigns, fast }); +pub fn parse_math_operator( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult { + let op = match tokens[*ind].tok_type { + LexerTokenType::Plus => MathOperatorType::Add, + LexerTokenType::PercentSign => MathOperatorType::Modulo, + LexerTokenType::Minus => MathOperatorType::Subtract, + LexerTokenType::Asterisk => { + if tokens[*ind + 1].tok_type == LexerTokenType::Asterisk { + *ind += 1; + + MathOperatorType::ShiftLeft + } else { + MathOperatorType::Multiply + } + } + LexerTokenType::Divide => { + if tokens[*ind + 1].tok_type == LexerTokenType::Divide { + *ind += 1; + + MathOperatorType::ShiftRight + } else { + MathOperatorType::Divide + } + } + + _ => { + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); + } + }; + + *ind += 1; + + let assigns = match tokens[*ind].tok_type { + LexerTokenType::EqualSign => true, + _ => false, + }; + + if assigns { + *ind += 1; + } + + let fast = match tokens[*ind].tok_type { + LexerTokenType::Tidle => true, + _ => false, + }; + + if fast { + *ind += 1; + } + + return Ok(MathOperator { + operator: op, + assigns, + fast, + }); } -pub fn parse_compare_operator(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { - let eq = match tokens[*ind + 1].tok_type { - LexerTokenType::EqualSign => true, - _ => false - }; - - let op = match tokens[*ind].tok_type { - LexerTokenType::EqualSign => { - tokens[*ind + 1].expects(LexerTokenType::EqualSign)?; - - ComparingOperator::Equal - }, - - LexerTokenType::ExclamationMark => { - tokens[*ind + 1].expects(LexerTokenType::EqualSign)?; - - ComparingOperator::NotEqual - }, - - LexerTokenType::AngelBracketOpen => { - if eq { - ComparingOperator::LowerEqual - } else { - ComparingOperator::Lower - } - }, - - LexerTokenType::AngelBracketClose => { - if eq { - ComparingOperator::HigherEqual - } else { - ComparingOperator::Higher - } - }, - - _ => { - return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) - } - }; - - return Ok(op); -} \ No newline at end of file +pub fn parse_compare_operator( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult { + let eq = match tokens[*ind + 1].tok_type { + LexerTokenType::EqualSign => true, + _ => false, + }; + + let op = match tokens[*ind].tok_type { + LexerTokenType::EqualSign => { + tokens[*ind + 1].expects(LexerTokenType::EqualSign)?; + + ComparingOperator::Equal + } + + LexerTokenType::ExclamationMark => { + tokens[*ind + 1].expects(LexerTokenType::EqualSign)?; + + ComparingOperator::NotEqual + } + + LexerTokenType::AngelBracketOpen => { + if eq { + ComparingOperator::LowerEqual + } else { + ComparingOperator::Lower + } + } + + LexerTokenType::AngelBracketClose => { + if eq { + ComparingOperator::HigherEqual + } else { + ComparingOperator::Higher + } + } + + _ => { + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); + } + }; + + return Ok(op); +} diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 09f0c7a..dc0e678 100644 --- a/compiler/ast/src/tree.rs +++ b/compiler/ast/src/tree.rs @@ -1,215 +1,389 @@ //! //! AST tree related definitions. -//! +//! use std::{collections::HashMap, fmt::Display}; use compiler_typing::TypeParameterContainer; -use compiler_utils::{Position, hash::{HashedString, SelfHash}, operators::{ComparingOperator, MathOperator}}; -use diagnostics::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}}; +use compiler_utils::{ + Position, + hash::{HashedString, SelfHash}, + operators::{ComparingOperator, MathOperator}, +}; +use diagnostics::{ + DiagnosticSpanOrigin, + diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, +}; use crate::types::ASTType; #[derive(Debug, PartialEq, Clone)] pub struct FunctionDeclarationArgument { pub name: HashedString, - pub argument_type: ASTType + pub argument_type: ASTType, } impl FunctionDeclarationArgument { pub fn new(name: String, arg_type: ASTType) -> Self { - FunctionDeclarationArgument { name: HashedString::new(name), argument_type: arg_type } + FunctionDeclarationArgument { + name: HashedString::new(name), + argument_type: arg_type, + } } } /// The main AST node type in the AST parsing system. #[derive(Debug, PartialEq, Clone)] pub enum ASTTreeNodeKind { - IntegerLit { val: i128, hash: u64 }, + IntegerLit { + val: i128, + hash: u64, + }, StringLit(String), - UseStatement { shards: Vec, use_clauses: Vec }, - - ThisStructParam, - - UnwrapCondition { original: Box, target_type: ASTType, unsafe_unwrap: bool, target_var: Option }, - UnwrapValue { original: Box, target_type: ASTType, unsafe_unwrap: bool }, - - OperatorBasedConditionMember { lval: Box, rval: Box, operator: ComparingOperator }, - BooleanBasedConditionMember { val: Box, negate: bool }, - - MathResult { lval: Box, rval: Box, operator: MathOperator }, - - VariableReference(HashedString), - - PointerGrab(Box), - ReferenceGrab(Box), - - StructInitializer { map: HashMap> }, - ArrayVariableInitializerValueSameValue { size: usize, v: Box }, - ArrayVariableInitializerValue { vals: Vec> }, - - ArrayIndexAccess { val: Box, index: Box }, - ArrayIndexModifiy { array: Box, index: Box, val: Box }, - - EnumDeclaration { name: HashedString, entries: Vec>, functions: Vec>, type_params: TypeParameterContainer }, - EnumEntryDeclaration { name: HashedString, fields: Vec> }, - - StructLayoutDeclaration { name: HashedString, layout: bool, members: Vec>, type_params: TypeParameterContainer }, - StructFieldMember { name: HashedString, member_type: ASTType }, - - VarDeclaration { var_name: HashedString, var_type: ASTType, value: Option> }, - VarValueChange { var: Box, value: Box }, - VarIncrement { var: Box, increment_by: Option> }, // Default is by 1 - - IfStatement { cond: Box, body: Vec>, branches: Vec>, depth: usize }, - IfElseStatement { cond: Option>, body: Vec> }, - ElseStatement { body: Vec> }, - - ReturnStatement { val: Option> }, - - StaticVariableDeclaration { name: HashedString, var_type: ASTType, val: Box }, - - WhileBlock { cond: Box, body: Vec> }, - ForBlock { initial_state: Box, cond: Box, increment: Box, body: Vec> }, + UseStatement { + shards: Vec, + use_clauses: Vec, + }, + + ThisStructParam, + + UnwrapCondition { + original: Box, + target_type: ASTType, + unsafe_unwrap: bool, + target_var: Option, + }, + UnwrapValue { + original: Box, + target_type: ASTType, + unsafe_unwrap: bool, + }, + + OperatorBasedConditionMember { + lval: Box, + rval: Box, + operator: ComparingOperator, + }, + BooleanBasedConditionMember { + val: Box, + negate: bool, + }, + + MathResult { + lval: Box, + rval: Box, + operator: MathOperator, + }, + + VariableReference(HashedString), + + PointerGrab(Box), + ReferenceGrab(Box), + + StructInitializer { + map: HashMap>, + }, + ArrayVariableInitializerValueSameValue { + size: usize, + v: Box, + }, + ArrayVariableInitializerValue { + vals: Vec>, + }, + + ArrayIndexAccess { + val: Box, + index: Box, + }, + ArrayIndexModifiy { + array: Box, + index: Box, + val: Box, + }, + + EnumDeclaration { + name: HashedString, + entries: Vec>, + functions: Vec>, + type_params: TypeParameterContainer, + }, + EnumEntryDeclaration { + name: HashedString, + fields: Vec>, + }, + + StructLayoutDeclaration { + name: HashedString, + layout: bool, + members: Vec>, + type_params: TypeParameterContainer, + }, + StructFieldMember { + name: HashedString, + member_type: ASTType, + }, + + VarDeclaration { + var_name: HashedString, + var_type: ASTType, + value: Option>, + }, + VarValueChange { + var: Box, + value: Box, + }, + VarIncrement { + var: Box, + increment_by: Option>, + }, // Default is by 1 + + IfStatement { + cond: Box, + body: Vec>, + branches: Vec>, + depth: usize, + }, + IfElseStatement { + cond: Option>, + body: Vec>, + }, + ElseStatement { + body: Vec>, + }, + + ReturnStatement { + val: Option>, + }, + + StaticVariableDeclaration { + name: HashedString, + var_type: ASTType, + val: Box, + }, + + WhileBlock { + cond: Box, + body: Vec>, + }, + ForBlock { + initial_state: Box, + cond: Box, + increment: Box, + body: Vec>, + }, + + FunctionCall { + func: HashedString, + args: Vec>, + }, + FunctionDeclaration { + func_name: HashedString, + args: Vec, + body: Vec>, + return_type: Option, + requires_this: bool, + }, + + ShadowFunctionDeclaration { + func_name: HashedString, + args: Vec, + return_type: Option, + }, + + StructLRVariable { + l: Box, + r: Box, + }, + StructLRFunction { + l: Box, + r: Box, + }, +} - FunctionCall { func: HashedString, args: Vec> }, - FunctionDeclaration { func_name: HashedString, args: Vec, body: Vec>, return_type: Option, requires_this: bool }, +impl ASTTreeNodeKind { + pub fn is_function_call(&self) -> bool { + return matches!( + self, + ASTTreeNodeKind::FunctionCall { .. } | ASTTreeNodeKind::StructLRFunction { .. } + ); + } - ShadowFunctionDeclaration { func_name: HashedString, args: Vec, return_type: Option }, + pub fn is_var_access(&self) -> bool { + return matches!( + self, + ASTTreeNodeKind::VariableReference { .. } | ASTTreeNodeKind::StructLRVariable { .. } + ); + } - StructLRVariable { l: Box, r: Box,}, - StructLRFunction { l: Box, r: Box, } -} + pub fn is_tree_permissible(&self) -> bool { + return matches!( + self, + ASTTreeNodeKind::FunctionDeclaration { .. } + | ASTTreeNodeKind::EnumDeclaration { .. } + | ASTTreeNodeKind::StaticVariableDeclaration { .. } + | ASTTreeNodeKind::ShadowFunctionDeclaration { .. } + | ASTTreeNodeKind::StructLayoutDeclaration { .. } + ); + } -impl ASTTreeNodeKind { - pub fn is_function_call(&self) -> bool { - return matches!(self, ASTTreeNodeKind::FunctionCall { .. } | ASTTreeNodeKind::StructLRFunction { .. } ) - } - - pub fn is_var_access(&self) -> bool { - return matches!(self, ASTTreeNodeKind::VariableReference { .. } | ASTTreeNodeKind::StructLRVariable { .. }) - } - - pub fn is_tree_permissible(&self) -> bool { - return matches!(self, ASTTreeNodeKind::FunctionDeclaration { .. } | ASTTreeNodeKind::EnumDeclaration { .. } | ASTTreeNodeKind::StaticVariableDeclaration { .. } | ASTTreeNodeKind::ShadowFunctionDeclaration { .. }| ASTTreeNodeKind::StructLayoutDeclaration { .. }) - } - - pub fn get_tree_name(&self) -> Option { - match self { - ASTTreeNodeKind::FunctionDeclaration { func_name, args: _, body: _, return_type: _ , requires_this: _} => { - return Some(HashedString::new(func_name.val.to_string())); - }, - - ASTTreeNodeKind::ShadowFunctionDeclaration { func_name, args: _, return_type: _ } => { - return Some(HashedString::new(func_name.val.to_string())) - } - - ASTTreeNodeKind::StaticVariableDeclaration { name, var_type: _, val: _ } => { - return Some(HashedString::new(name.val.clone())); - }, - - ASTTreeNodeKind::StructLayoutDeclaration { name, layout: _, members: _, type_params: _ } => { - return Some(HashedString::new(name.val.to_string())); - }, - - ASTTreeNodeKind::VarDeclaration { var_name, var_type: _, value: _ } => { - return Some(HashedString::new(var_name.val.to_string())); - }, - - ASTTreeNodeKind::EnumDeclaration { name, entries: _, functions: _, type_params: _ } => { - return Some(name.clone()) - } - - _ => return None - } - } + pub fn get_tree_name(&self) -> Option { + match self { + ASTTreeNodeKind::FunctionDeclaration { + func_name, + args: _, + body: _, + return_type: _, + requires_this: _, + } => { + return Some(HashedString::new(func_name.val.to_string())); + } + + ASTTreeNodeKind::ShadowFunctionDeclaration { + func_name, + args: _, + return_type: _, + } => return Some(HashedString::new(func_name.val.to_string())), + + ASTTreeNodeKind::StaticVariableDeclaration { + name, + var_type: _, + val: _, + } => { + return Some(HashedString::new(name.val.clone())); + } + + ASTTreeNodeKind::StructLayoutDeclaration { + name, + layout: _, + members: _, + type_params: _, + } => { + return Some(HashedString::new(name.val.to_string())); + } + + ASTTreeNodeKind::VarDeclaration { + var_name, + var_type: _, + value: _, + } => { + return Some(HashedString::new(var_name.val.to_string())); + } + + ASTTreeNodeKind::EnumDeclaration { + name, + entries: _, + functions: _, + type_params: _, + } => return Some(name.clone()), + + _ => return None, + } + } } /// The complete AST tree node. Contains positions and more. #[derive(Debug, PartialEq, Clone)] pub struct ASTTreeNode { - pub kind: ASTTreeNodeKind, - pub start: Position, - pub end: Position + pub kind: ASTTreeNodeKind, + pub start: Position, + pub end: Position, } impl ASTTreeNode { - pub fn new(kind: ASTTreeNodeKind, start: Position, end: Position) -> Self { - return ASTTreeNode { kind, start, end } - } + pub fn new(kind: ASTTreeNodeKind, start: Position, end: Position) -> Self { + return ASTTreeNode { kind, start, end }; + } } impl DiagnosticSpanOrigin for ASTTreeNode { - fn make_span(&self, kind: diagnostics::diagnostic::SpanKind, msg: Option) -> diagnostics::diagnostic::Span { - Span { start: SpanPosition::from_pos2(self.start.clone(), self.end.clone()), label: msg, kind } - } - - fn get_pos(&self) -> SpanPosition { - SpanPosition::from_pos2(self.start.clone(), self.end.clone()) - } + fn make_span( + &self, + kind: diagnostics::diagnostic::SpanKind, + msg: Option, + ) -> diagnostics::diagnostic::Span { + Span { + start: SpanPosition::from_pos2(self.start.clone(), self.end.clone()), + label: msg, + kind, + } + } - fn make_simple_diagnostic(&self, code: usize, level: diagnostics::diagnostic::Level, message: String, primary_span_msg: Option, spans: Vec, notes: Vec, help: Vec) -> diagnostics::diagnostic::Diagnostic { - let primary = self.make_span(SpanKind::Primary, primary_span_msg); + fn get_pos(&self) -> SpanPosition { + SpanPosition::from_pos2(self.start.clone(), self.end.clone()) + } - Diagnostic::new_base(level, code, message, primary, spans, notes, help) - } + fn make_simple_diagnostic( + &self, + code: usize, + level: diagnostics::diagnostic::Level, + message: String, + primary_span_msg: Option, + spans: Vec, + notes: Vec, + help: Vec, + ) -> diagnostics::diagnostic::Diagnostic { + let primary = self.make_span(SpanKind::Primary, primary_span_msg); + + Diagnostic::new_base(level, code, message, primary, spans, notes, help) + } } impl Display for ASTTreeNode { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.kind)?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.kind)?; - Ok(()) - } + Ok(()) + } } impl Display for ASTTreeNodeKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::UseStatement { .. } => "use statement", - Self::UnwrapCondition { .. } | Self::UnwrapValue { .. } => "unwrap", - Self::IntegerLit { .. } => "integer literal", - Self::StringLit(_) => "string literal", - Self::ThisStructParam => "this reference", - Self::OperatorBasedConditionMember { .. } => "operator condition", - Self::BooleanBasedConditionMember { .. } => "boolean condition", - Self::MathResult { .. } => "math operation", - Self::VariableReference(_) => "variable reference", - Self::PointerGrab(_) => "pointer grabbing", - Self::ReferenceGrab(_) => "reference", - Self::StructInitializer { .. } => "struct value initializer", - Self::ArrayVariableInitializerValue { .. } | Self::ArrayVariableInitializerValueSameValue { .. } => "array value initializer", - Self::ArrayIndexAccess { .. } | Self::ArrayIndexModifiy { .. } => "index access", - Self::VarDeclaration { .. } => "variable declaration", - Self::VarValueChange { .. } => "variable assignment", - Self::VarIncrement { .. } => "variable incrementation", - Self::IfStatement { .. } => "if statement", - Self::ElseStatement { .. } => "else statement", - Self::IfElseStatement { .. } => "if else statement", - Self::ReturnStatement { .. } => "return statement", - Self::StaticVariableDeclaration { .. } => "static variable declaration", - Self::WhileBlock { .. } => "while block", - Self::ForBlock { .. } => "for block", - Self::FunctionCall { .. } => "function call", - Self::FunctionDeclaration { .. } => "function declaration", - Self::ShadowFunctionDeclaration { .. } => "shadow function declaration", - Self::StructLRFunction { .. } => "struct LRU function usage", - Self::StructLRVariable { .. } => "struct LRU variable usage", - Self::StructLayoutDeclaration { .. } => "struct / layout declaration", - Self::StructFieldMember { .. } => "struct field", - Self::EnumDeclaration { .. } => "enum declaration", - Self::EnumEntryDeclaration { .. } => "enum entry declaration", - }; - - write!(f, "{}", s)?; - Ok(()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::UseStatement { .. } => "use statement", + Self::UnwrapCondition { .. } | Self::UnwrapValue { .. } => "unwrap", + Self::IntegerLit { .. } => "integer literal", + Self::StringLit(_) => "string literal", + Self::ThisStructParam => "this reference", + Self::OperatorBasedConditionMember { .. } => "operator condition", + Self::BooleanBasedConditionMember { .. } => "boolean condition", + Self::MathResult { .. } => "math operation", + Self::VariableReference(_) => "variable reference", + Self::PointerGrab(_) => "pointer grabbing", + Self::ReferenceGrab(_) => "reference", + Self::StructInitializer { .. } => "struct value initializer", + Self::ArrayVariableInitializerValue { .. } + | Self::ArrayVariableInitializerValueSameValue { .. } => "array value initializer", + Self::ArrayIndexAccess { .. } | Self::ArrayIndexModifiy { .. } => "index access", + Self::VarDeclaration { .. } => "variable declaration", + Self::VarValueChange { .. } => "variable assignment", + Self::VarIncrement { .. } => "variable incrementation", + Self::IfStatement { .. } => "if statement", + Self::ElseStatement { .. } => "else statement", + Self::IfElseStatement { .. } => "if else statement", + Self::ReturnStatement { .. } => "return statement", + Self::StaticVariableDeclaration { .. } => "static variable declaration", + Self::WhileBlock { .. } => "while block", + Self::ForBlock { .. } => "for block", + Self::FunctionCall { .. } => "function call", + Self::FunctionDeclaration { .. } => "function declaration", + Self::ShadowFunctionDeclaration { .. } => "shadow function declaration", + Self::StructLRFunction { .. } => "struct LRU function usage", + Self::StructLRVariable { .. } => "struct LRU variable usage", + Self::StructLayoutDeclaration { .. } => "struct / layout declaration", + Self::StructFieldMember { .. } => "struct field", + Self::EnumDeclaration { .. } => "enum declaration", + Self::EnumEntryDeclaration { .. } => "enum entry declaration", + }; + + write!(f, "{}", s)?; + Ok(()) + } } #[macro_export] macro_rules! make_node { - ($kind:expr, $s:expr, $e:expr) => { - Box::new(ASTTreeNode::new($kind, $s.pos.clone(), $e.get_end_pos())) - }; -} \ No newline at end of file + ($kind:expr, $s:expr, $e:expr) => { + Box::new(ASTTreeNode::new($kind, $s.pos.clone(), $e.get_end_pos())) + }; +} diff --git a/compiler/ast/src/types.rs b/compiler/ast/src/types.rs index 1abbe12..2543be6 100644 --- a/compiler/ast/src/types.rs +++ b/compiler/ast/src/types.rs @@ -2,45 +2,45 @@ #[derive(Debug, PartialEq, Clone)] #[deprecated(note = "Will be replaced by compiler_typing")] pub struct CompleteType { - pub base_type: u64, - pub sizes: Vec, - pub types: Vec, + pub base_type: u64, + pub sizes: Vec, + pub types: Vec, - pub pointer: bool, - pub pointer_array: bool, - pub array_sz: usize + pub pointer: bool, + pub pointer_array: bool, + pub array_sz: usize, } /// The node-based typing system of Quickfall. Allows for very specific types. Only used for AST since types aren't resolved #[derive(Clone, Debug, PartialEq)] pub enum ASTType { - /// A generic type node. Represents a classic type. - /// 0: The raw type name - /// 1: The type parameters - /// 2: The size specifiers - /// 3: enum specifier - Generic(String, Vec>, Vec, Option), // Potential lowering to base-sized + /// A generic type node. Represents a classic type. + /// 0: The raw type name + /// 1: The type parameters + /// 2: The size specifiers + /// 3: enum specifier + Generic(String, Vec>, Vec, Option), // Potential lowering to base-sized - /// A pointer type node. Represents a pointer version - /// 0: Is the pointer a poiner of arrays - /// 1: Inner type - Pointer(bool, Box), + /// A pointer type node. Represents a pointer version + /// 0: Is the pointer a poiner of arrays + /// 1: Inner type + Pointer(bool, Box), - Reference(Box), + Reference(Box), - /// An array type node. Represents an array version - /// 0: The size of the array - /// 1: Inner type - Array(usize, Box) + /// An array type node. Represents an array version + /// 0: The size of the array + /// 1: Inner type + Array(usize, Box), } impl ASTType { - pub fn get_generic_name(&self) -> String { - match self { - Self::Generic(s, _, _, _) => s.clone(), - Self::Pointer(_, inner) => inner.get_generic_name(), - Self::Reference(inner) => inner.get_generic_name(), - Self::Array(_, inner) => inner.get_generic_name() - } - } -} \ No newline at end of file + pub fn get_generic_name(&self) -> String { + match self { + Self::Generic(s, _, _, _) => s.clone(), + Self::Pointer(_, inner) => inner.get_generic_name(), + Self::Reference(inner) => inner.get_generic_name(), + Self::Array(_, inner) => inner.get_generic_name(), + } + } +} diff --git a/compiler/ast_parser/src/arrays.rs b/compiler/ast_parser/src/arrays.rs index 520f699..a6d8b3c 100644 --- a/compiler/ast_parser/src/arrays.rs +++ b/compiler/ast_parser/src/arrays.rs @@ -4,16 +4,27 @@ use lexer::token::{LexerToken, LexerTokenType}; use crate::value::parse_ast_value; -pub fn parse_array_access(tokens: &Vec, ind: &mut usize, original: Box) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_array_access( + tokens: &Vec, + ind: &mut usize, + original: Box, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let index = parse_ast_value(tokens, ind)?; + let index = parse_ast_value(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::ArrayClose)?; + tokens[*ind].expects(LexerTokenType::ArrayClose)?; - *ind += 1; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ArrayIndexAccess { val: original, index }, start, tokens[*ind].get_end_pos()))) -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ArrayIndexAccess { + val: original, + index, + }, + start, + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/comp.rs b/compiler/ast_parser/src/comp.rs index b129c83..2ac5ca9 100644 --- a/compiler/ast_parser/src/comp.rs +++ b/compiler/ast_parser/src/comp.rs @@ -1,16 +1,31 @@ -use ast::{operators::parse_compare_operator, tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::{ + operators::parse_compare_operator, + tree::{ASTTreeNode, ASTTreeNodeKind}, +}; use diagnostics::DiagnosticResult; use lexer::token::LexerToken; use crate::value::parse_ast_value; -pub fn parse_ast_compare(tokens: &Vec, ind: &mut usize, original: Box) -> DiagnosticResult> { - let operator = parse_compare_operator(tokens, ind)?; +pub fn parse_ast_compare( + tokens: &Vec, + ind: &mut usize, + original: Box, +) -> DiagnosticResult> { + let operator = parse_compare_operator(tokens, ind)?; - let right_val = parse_ast_value(tokens, ind)?; + let right_val = parse_ast_value(tokens, ind)?; - let start_pos = original.start.clone(); - let end_pos = right_val.end.clone(); + let start_pos = original.start.clone(); + let end_pos = right_val.end.clone(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::OperatorBasedConditionMember { lval: original, rval: right_val, operator }, start_pos, end_pos))) -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::OperatorBasedConditionMember { + lval: original, + rval: right_val, + operator, + }, + start_pos, + end_pos, + ))); +} diff --git a/compiler/ast_parser/src/control/for_loop.rs b/compiler/ast_parser/src/control/for_loop.rs index 370f21a..3ff2c66 100644 --- a/compiler/ast_parser/src/control/for_loop.rs +++ b/compiler/ast_parser/src/control/for_loop.rs @@ -1,37 +1,52 @@ use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use crate::{functions::parse_node_body, parser::parse_ast_node_in_body, value::parse_ast_value, variables::decl::parse_variable_declaration}; +use crate::{ + functions::parse_node_body, parser::parse_ast_node_in_body, value::parse_ast_value, + variables::decl::parse_variable_declaration, +}; -pub fn parse_for_loop(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_for_loop( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - tokens[*ind].expects(LexerTokenType::ParenOpen)?; + tokens[*ind].expects(LexerTokenType::ParenOpen)?; - let initial = parse_variable_declaration(tokens, ind)?; + let initial = parse_variable_declaration(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::Comma)?; + tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; - let cond = parse_ast_value(tokens, ind)?; + *ind += 1; + let cond = parse_ast_value(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; - let increment = parse_ast_node_in_body(tokens, ind)?; + let increment = parse_ast_node_in_body(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::ParenClose)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::ParenClose)?; + *ind += 1; - tokens[*ind].expects(LexerTokenType::BracketOpen)?; + tokens[*ind].expects(LexerTokenType::BracketOpen)?; - let body = parse_node_body(tokens, ind)?; + let body = parse_node_body(tokens, ind)?; - let end = tokens[*ind - 1].get_end_pos(); + let end = tokens[*ind - 1].get_end_pos(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ForBlock { initial_state: initial, cond, increment, body }, start, end))); -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ForBlock { + initial_state: initial, + cond, + increment, + body, + }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/control/if_else.rs b/compiler/ast_parser/src/control/if_else.rs index 0b7121f..e22b0ac 100644 --- a/compiler/ast_parser/src/control/if_else.rs +++ b/compiler/ast_parser/src/control/if_else.rs @@ -1,86 +1,113 @@ //! //! Parsing for if and else statements -//! +//! use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use crate::{functions::parse_node_body, value::{parse_ast_condition_if_statement_value}}; +use crate::{functions::parse_node_body, value::parse_ast_condition_if_statement_value}; -pub fn parse_condition_member(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - tokens[*ind].expects(LexerTokenType::ParenOpen)?; +pub fn parse_condition_member( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + tokens[*ind].expects(LexerTokenType::ParenOpen)?; - *ind += 1; - let cond = parse_ast_condition_if_statement_value(tokens, ind)?; + *ind += 1; + let cond = parse_ast_condition_if_statement_value(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::ParenClose)?; + tokens[*ind].expects(LexerTokenType::ParenClose)?; - *ind += 1; + *ind += 1; - return Ok(cond); + return Ok(cond); } -pub fn parse_if_statement(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); - *ind += 1; - - let cond = parse_condition_member(tokens, ind)?; - - tokens[*ind].expects(LexerTokenType::BracketOpen)?; - - let body = match parse_node_body(tokens, ind) { - Ok(v) => v, - Err(e) => return Err(e) - }; - - let mut depth = 1; - let mut branches: Vec> = vec![]; - - if tokens[*ind].tok_type == LexerTokenType::Else { - - parse_else_statement(tokens, ind, &mut depth, &mut branches)?; - } - - let end = tokens[*ind].get_end_pos(); - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::IfStatement { cond, body, branches, depth }, start, end))); +pub fn parse_if_statement( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); + *ind += 1; + + let cond = parse_condition_member(tokens, ind)?; + + tokens[*ind].expects(LexerTokenType::BracketOpen)?; + + let body = match parse_node_body(tokens, ind) { + Ok(v) => v, + Err(e) => return Err(e), + }; + + let mut depth = 1; + let mut branches: Vec> = vec![]; + + if tokens[*ind].tok_type == LexerTokenType::Else { + parse_else_statement(tokens, ind, &mut depth, &mut branches)?; + } + + let end = tokens[*ind].get_end_pos(); + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::IfStatement { + cond, + body, + branches, + depth, + }, + start, + end, + ))); } -pub fn parse_else_statement(tokens: &Vec, ind: &mut usize, depth: &mut usize, branches: &mut Vec>) -> DiagnosticResult { - let start = tokens[*ind].pos.clone(); +pub fn parse_else_statement( + tokens: &Vec, + ind: &mut usize, + depth: &mut usize, + branches: &mut Vec>, +) -> DiagnosticResult { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let mut cond = None; + let mut cond = None; - *depth += 1; + *depth += 1; - if tokens[*ind].tok_type == LexerTokenType::If { - *ind += 1; - cond = Some(parse_condition_member(tokens, ind)?); - } + if tokens[*ind].tok_type == LexerTokenType::If { + *ind += 1; + cond = Some(parse_condition_member(tokens, ind)?); + } - tokens[*ind].expects(LexerTokenType::BracketOpen)?; + tokens[*ind].expects(LexerTokenType::BracketOpen)?; - let body = match parse_node_body(tokens, ind) { - Ok(v) => v, - Err(e) => return Err(e) - }; + let body = match parse_node_body(tokens, ind) { + Ok(v) => v, + Err(e) => return Err(e), + }; - let end = tokens[*ind].get_end_pos(); + let end = tokens[*ind].get_end_pos(); - if cond.is_some() { - branches.push(Box::new(ASTTreeNode::new(ASTTreeNodeKind::IfElseStatement { cond, body }, start, end))); + if cond.is_some() { + branches.push(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::IfElseStatement { cond, body }, + start, + end, + ))); - if tokens[*ind].tok_type == LexerTokenType::Else { - parse_else_statement(tokens, ind, depth, branches)?; - } + if tokens[*ind].tok_type == LexerTokenType::Else { + parse_else_statement(tokens, ind, depth, branches)?; + } - return Ok(true); - } + return Ok(true); + } - branches.push(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ElseStatement { body }, start, end))); - return Ok(true); -} \ No newline at end of file + branches.push(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ElseStatement { body }, + start, + end, + ))); + return Ok(true); +} diff --git a/compiler/ast_parser/src/control/mod.rs b/compiler/ast_parser/src/control/mod.rs index 9b05368..012ff5b 100644 --- a/compiler/ast_parser/src/control/mod.rs +++ b/compiler/ast_parser/src/control/mod.rs @@ -1,3 +1,3 @@ +pub mod for_loop; pub mod if_else; pub mod while_block; -pub mod for_loop; \ No newline at end of file diff --git a/compiler/ast_parser/src/control/while_block.rs b/compiler/ast_parser/src/control/while_block.rs index 210c8ce..1145c39 100644 --- a/compiler/ast_parser/src/control/while_block.rs +++ b/compiler/ast_parser/src/control/while_block.rs @@ -1,25 +1,32 @@ use diagnostics::DiagnosticResult; use lexer::token::LexerToken; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use crate::{control::if_else::parse_condition_member, functions::parse_node_body}; -pub fn parse_while_block(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_while_block( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let cond = parse_condition_member(tokens, ind)?; + let cond = parse_condition_member(tokens, ind)?; - tokens[*ind].expects(lexer::token::LexerTokenType::BracketOpen)?; + tokens[*ind].expects(lexer::token::LexerTokenType::BracketOpen)?; - let body = match parse_node_body(tokens, ind) { - Ok(v) => v, - Err(e) => return Err(e) - }; + let body = match parse_node_body(tokens, ind) { + Ok(v) => v, + Err(e) => return Err(e), + }; - let end = tokens[*ind - 1].get_end_pos().clone(); + let end = tokens[*ind - 1].get_end_pos().clone(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::WhileBlock { cond, body }, start, end))); -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::WhileBlock { cond, body }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/functions/arguments.rs b/compiler/ast_parser/src/functions/arguments.rs index 47f722a..2a01800 100644 --- a/compiler/ast_parser/src/functions/arguments.rs +++ b/compiler/ast_parser/src/functions/arguments.rs @@ -1,54 +1,61 @@ //! Module for parsing arguments -use ast::{tree::FunctionDeclarationArgument, types::{ASTType}}; +use ast::{tree::FunctionDeclarationArgument, types::ASTType}; use compiler_utils::hash::HashedString; use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; use lexer::token::{LexerToken, LexerTokenType}; use crate::types::parse_type; -pub fn parse_function_arguments(tokens: &Vec, ind: &mut usize, struct_type: Option) -> DiagnosticResult<(Vec, bool)> { - *ind += 1; +pub fn parse_function_arguments( + tokens: &Vec, + ind: &mut usize, + struct_type: Option, +) -> DiagnosticResult<(Vec, bool)> { + *ind += 1; - let mut depends_on_this: bool = false; - let mut args: Vec = Vec::new(); - - while *ind < tokens.len() { - - if tokens[*ind].tok_type == LexerTokenType::ParenClose { - break; - } + let mut depends_on_this: bool = false; + let mut args: Vec = Vec::new(); - if tokens[*ind].tok_type == LexerTokenType::This { - if struct_type.is_none() || !args.is_empty() { - return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); - } + while *ind < tokens.len() { + if tokens[*ind].tok_type == LexerTokenType::ParenClose { + break; + } - depends_on_this = true; + if tokens[*ind].tok_type == LexerTokenType::This { + if struct_type.is_none() || !args.is_empty() { + return Err( + make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into(), + ); + } - *ind += 1; + depends_on_this = true; - args.push(FunctionDeclarationArgument { name: HashedString::new("this".to_string()), argument_type: struct_type.clone().unwrap() }) - } else { - let var_type = parse_type(tokens, ind)?; + *ind += 1; - let var_name = tokens[*ind].expects_keyword()?; - - args.push(FunctionDeclarationArgument::new(var_name.0, var_type)); - - *ind += 1; - } + args.push(FunctionDeclarationArgument { + name: HashedString::new("this".to_string()), + argument_type: struct_type.clone().unwrap(), + }) + } else { + let var_type = parse_type(tokens, ind)?; - if tokens[*ind].tok_type == LexerTokenType::ParenClose { - break; - } + let var_name = tokens[*ind].expects_keyword()?; - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + args.push(FunctionDeclarationArgument::new(var_name.0, var_type)); - } + *ind += 1; + } - tokens[*ind].expects(LexerTokenType::ParenClose)?; + if tokens[*ind].tok_type == LexerTokenType::ParenClose { + break; + } - Ok((args, depends_on_this)) + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; + } + + tokens[*ind].expects(LexerTokenType::ParenClose)?; + + Ok((args, depends_on_this)) } diff --git a/compiler/ast_parser/src/functions/mod.rs b/compiler/ast_parser/src/functions/mod.rs index 2a9b701..67413bc 100644 --- a/compiler/ast_parser/src/functions/mod.rs +++ b/compiler/ast_parser/src/functions/mod.rs @@ -1,97 +1,128 @@ //! Parser module for functions -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}, types::{ASTType}}; +use ast::{ + tree::{ASTTreeNode, ASTTreeNodeKind}, + types::ASTType, +}; use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{functions::arguments::parse_function_arguments, parser::parse_ast_node_in_body, types::parse_type, value::parse_ast_value}; +use crate::{ + functions::arguments::parse_function_arguments, parser::parse_ast_node_in_body, + types::parse_type, value::parse_ast_value, +}; -pub mod shadow; pub mod arguments; pub mod returns; +pub mod shadow; -pub fn parse_function_declaraction(tokens: &Vec, ind: &mut usize, struct_type: Option) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_function_declaraction( + tokens: &Vec, + ind: &mut usize, + struct_type: Option, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; - let function_name = tokens[*ind].expects_keyword()?; + *ind += 1; + let function_name = tokens[*ind].expects_keyword()?; - *ind += 1; - tokens[*ind].expects(LexerTokenType::ParenOpen)?; + *ind += 1; + tokens[*ind].expects(LexerTokenType::ParenOpen)?; - let args = parse_function_arguments(tokens, ind, struct_type)?; + let args = parse_function_arguments(tokens, ind, struct_type)?; - *ind += 1; + *ind += 1; - let mut ret_type = None; + let mut ret_type = None; - if tokens[*ind].is_keyword() { - ret_type = Some(parse_type(tokens, ind)?); - //*ind += 1; - } + if tokens[*ind].is_keyword() { + ret_type = Some(parse_type(tokens, ind)?); + //*ind += 1; + } - tokens[*ind].expects(LexerTokenType::BracketOpen)?; + tokens[*ind].expects(LexerTokenType::BracketOpen)?; - let body = parse_node_body(tokens, ind)?; + let body = parse_node_body(tokens, ind)?; - let end = tokens[*ind - 1].get_end_pos(); + let end = tokens[*ind - 1].get_end_pos(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::FunctionDeclaration { func_name: HashedString::new(function_name.0), args: args.0, body, return_type: ret_type, requires_this: args.1 }, start, end))); + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::FunctionDeclaration { + func_name: HashedString::new(function_name.0), + args: args.0, + body, + return_type: ret_type, + requires_this: args.1, + }, + start, + end, + ))); } -pub fn parse_function_call(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_function_call( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - let func = HashedString::new(tokens[*ind].expects_keyword()?.0); + let func = HashedString::new(tokens[*ind].expects_keyword()?.0); - *ind += 1; + *ind += 1; - tokens[*ind].expects(LexerTokenType::ParenOpen)?; + tokens[*ind].expects(LexerTokenType::ParenOpen)?; - *ind += 1; + *ind += 1; + + let mut vals: Vec> = Vec::new(); - let mut vals: Vec> = Vec::new(); - - while tokens[*ind].tok_type != LexerTokenType::ParenClose { - vals.push(parse_ast_value(tokens, ind)?); + while tokens[*ind].tok_type != LexerTokenType::ParenClose { + vals.push(parse_ast_value(tokens, ind)?); - if tokens[*ind].tok_type == LexerTokenType::ParenClose { - break; - } + if tokens[*ind].tok_type == LexerTokenType::ParenClose { + break; + } - tokens[*ind].expects(LexerTokenType::Comma)?; + tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; - } + *ind += 1; + } - let end = tokens[*ind].get_end_pos().clone(); + let end = tokens[*ind].get_end_pos().clone(); - *ind += 1; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::FunctionCall { func , args: vals }, start, end))) + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::FunctionCall { func, args: vals }, + start, + end, + ))); } -pub fn parse_node_body(tokens: &Vec, ind: &mut usize) -> DiagnosticResult>> { +pub fn parse_node_body( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult>> { *ind += 1; let mut tok: &LexerToken = &tokens[*ind]; let mut body: Vec> = Vec::new(); - let mut stock = 1; + let mut stock = 1; - while tok.tok_type != LexerTokenType::EndOfFile && tok.tok_type != LexerTokenType::BracketClose { - if tok.tok_type == LexerTokenType::BracketClose { - stock -= 1; - } + while tok.tok_type != LexerTokenType::EndOfFile && tok.tok_type != LexerTokenType::BracketClose + { + if tok.tok_type == LexerTokenType::BracketClose { + stock -= 1; + } - if stock == 0 { - break; - } + if stock == 0 { + break; + } - if tok.tok_type == LexerTokenType::BracketOpen { - stock += 1; - } + if tok.tok_type == LexerTokenType::BracketOpen { + stock += 1; + } let n = parse_ast_node_in_body(tokens, ind)?; @@ -100,7 +131,7 @@ pub fn parse_node_body(tokens: &Vec, ind: &mut usize) -> DiagnosticR tok = &tokens[*ind]; } - *ind += 1; + *ind += 1; return Ok(body); -} \ No newline at end of file +} diff --git a/compiler/ast_parser/src/functions/returns.rs b/compiler/ast_parser/src/functions/returns.rs index 1b1174f..efb55aa 100644 --- a/compiler/ast_parser/src/functions/returns.rs +++ b/compiler/ast_parser/src/functions/returns.rs @@ -6,14 +6,21 @@ use lexer::token::LexerToken; use crate::value::parse_ast_value; -pub fn parse_function_return_statement(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_function_return_statement( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let val = parse_ast_value(tokens, ind)?; + let val = parse_ast_value(tokens, ind)?; - let end = tokens[*ind].get_end_pos(); + let end = tokens[*ind].get_end_pos(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ReturnStatement { val: Some(val) }, start, end))) -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ReturnStatement { val: Some(val) }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/functions/shadow.rs b/compiler/ast_parser/src/functions/shadow.rs index 1747d1f..c7edaa4 100644 --- a/compiler/ast_parser/src/functions/shadow.rs +++ b/compiler/ast_parser/src/functions/shadow.rs @@ -7,29 +7,40 @@ use lexer::token::{LexerToken, LexerTokenType}; use crate::{functions::arguments::parse_function_arguments, types::parse_type}; -pub fn parse_shadow_function_declaration(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); - - *ind += 1; - let function_name = tokens[*ind].expects_keyword()?; - - *ind += 1; - tokens[*ind].expects(LexerTokenType::ParenOpen)?; - - let args = parse_function_arguments(tokens, ind, None)?; - - *ind += 1; - - let mut ret_type = None; - let end; - - if tokens[*ind].is_keyword() { - ret_type = Some(parse_type(tokens, ind)?); - - end = tokens[*ind].get_end_pos().clone(); - } else { - end = tokens[*ind - 1].get_end_pos().clone(); - } - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ShadowFunctionDeclaration { func_name: HashedString::new(function_name.0), args: args.0, return_type: ret_type }, start, end))) -} \ No newline at end of file +pub fn parse_shadow_function_declaration( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); + + *ind += 1; + let function_name = tokens[*ind].expects_keyword()?; + + *ind += 1; + tokens[*ind].expects(LexerTokenType::ParenOpen)?; + + let args = parse_function_arguments(tokens, ind, None)?; + + *ind += 1; + + let mut ret_type = None; + let end; + + if tokens[*ind].is_keyword() { + ret_type = Some(parse_type(tokens, ind)?); + + end = tokens[*ind].get_end_pos().clone(); + } else { + end = tokens[*ind - 1].get_end_pos().clone(); + } + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ShadowFunctionDeclaration { + func_name: HashedString::new(function_name.0), + args: args.0, + return_type: ret_type, + }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/lib.rs b/compiler/ast_parser/src/lib.rs index b96b63f..f0379bf 100644 --- a/compiler/ast_parser/src/lib.rs +++ b/compiler/ast_parser/src/lib.rs @@ -8,39 +8,39 @@ use lexer::token::{LexerToken, LexerTokenType}; use crate::parser::parse_ast_node; -pub mod parser; +pub mod arrays; +pub mod comp; +pub mod control; pub mod functions; -pub mod value; +pub mod literals; pub mod math; +pub mod parser; pub mod structs; -pub mod literals; -pub mod control; -pub mod variables; pub mod types; -pub mod arrays; pub mod unwraps; pub mod use_statements; -pub mod comp; +pub mod value; +pub mod variables; pub fn parse_ast_ctx(tokens: &Vec) -> DiagnosticResult { - let mut ind = 0; + let mut ind = 0; - let mut ctx = ParserCtx::new(); + let mut ctx = ParserCtx::new(); - while tokens[ind].tok_type != LexerTokenType::EndOfFile { - let node = parse_ast_node(tokens, &mut ind)?; + while tokens[ind].tok_type != LexerTokenType::EndOfFile { + let node = parse_ast_node(tokens, &mut ind)?; - if let ASTTreeNodeKind::UseStatement { .. } = node.kind { - ctx.uses.push(node); - continue; - } + if let ASTTreeNodeKind::UseStatement { .. } = node.kind { + ctx.uses.push(node); + continue; + } - if !node.kind.is_tree_permissible() { - return Err(make_unexpected_simple_error(&*node, &node).into()) - } + if !node.kind.is_tree_permissible() { + return Err(make_unexpected_simple_error(&*node, &node).into()); + } - ctx.insert(node.kind.get_tree_name().unwrap().val, node); - } + ctx.insert(node.kind.get_tree_name().unwrap().val, node); + } - return Ok(ctx); + return Ok(ctx); } diff --git a/compiler/ast_parser/src/literals.rs b/compiler/ast_parser/src/literals.rs index 1e67c72..c81225b 100644 --- a/compiler/ast_parser/src/literals.rs +++ b/compiler/ast_parser/src/literals.rs @@ -1,20 +1,37 @@ //! AST parsing for number & string literals use diagnostics::DiagnosticResult; -use lexer::token::{LexerToken}; +use lexer::token::LexerToken; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -pub fn parse_integer_literal(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let val = tokens[*ind].expects_int_lit()?; - *ind += 1; +pub fn parse_integer_literal( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let val = tokens[*ind].expects_int_lit()?; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::IntegerLit { val: val.0, hash: val.1 }, tokens[*ind].pos.clone(), tokens[*ind].get_end_pos()))); + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::IntegerLit { + val: val.0, + hash: val.1, + }, + tokens[*ind].pos.clone(), + tokens[*ind].get_end_pos(), + ))); } -pub fn parse_string_literal(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let val = tokens[*ind].expects_string_lit()?; - *ind += 1; +pub fn parse_string_literal( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let val = tokens[*ind].expects_string_lit()?; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StringLit(val), tokens[*ind].pos.clone(), tokens[*ind].get_end_pos()))); -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StringLit(val), + tokens[*ind].pos.clone(), + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/math.rs b/compiler/ast_parser/src/math.rs index ad6664d..92d4e23 100644 --- a/compiler/ast_parser/src/math.rs +++ b/compiler/ast_parser/src/math.rs @@ -1,22 +1,50 @@ -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, diagnostic::Level, errors::MATH_OPERATION_ASSIGNS}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, diagnostic::Level, errors::MATH_OPERATION_ASSIGNS, +}; use lexer::token::LexerToken; -use ast::{operators::parse_math_operator, tree::{ASTTreeNode, ASTTreeNodeKind}}; use crate::value::parse_ast_value; +use ast::{ + operators::parse_math_operator, + tree::{ASTTreeNode, ASTTreeNodeKind}, +}; -pub fn parse_math_operation(tokens: &Vec, ind: &mut usize, original: Box, restricts_to_assigns: bool) -> DiagnosticResult> { - let oper = parse_math_operator(tokens, ind)?; +pub fn parse_math_operation( + tokens: &Vec, + ind: &mut usize, + original: Box, + restricts_to_assigns: bool, +) -> DiagnosticResult> { + let oper = parse_math_operator(tokens, ind)?; - if !oper.assigns && restricts_to_assigns { - return Err(tokens[*ind].make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec!["consider assigning this to variable".to_string()], vec!["add = at the end of the operator".to_string()]).into()) - } - - println!("{:#?}", tokens[*ind].tok_type); + if !oper.assigns && restricts_to_assigns { + return Err(tokens[*ind] + .make_simple_diagnostic( + MATH_OPERATION_ASSIGNS.0, + Level::Error, + MATH_OPERATION_ASSIGNS.1.to_string(), + None, + vec![], + vec!["consider assigning this to variable".to_string()], + vec!["add = at the end of the operator".to_string()], + ) + .into()); + } - let right_member = parse_ast_value(tokens, ind)?; + println!("{:#?}", tokens[*ind].tok_type); - let start = original.start.clone(); - let end = right_member.end.clone(); + let right_member = parse_ast_value(tokens, ind)?; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::MathResult { lval: original, rval: right_member, operator: oper }, start, end))) -} \ No newline at end of file + let start = original.start.clone(); + let end = right_member.end.clone(); + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::MathResult { + lval: original, + rval: right_member, + operator: oper, + }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/parser.rs b/compiler/ast_parser/src/parser.rs index 08586a0..84f207d 100644 --- a/compiler/ast_parser/src/parser.rs +++ b/compiler/ast_parser/src/parser.rs @@ -1,94 +1,125 @@ -use ast::{make_node, tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::{ + make_node, + tree::{ASTTreeNode, ASTTreeNodeKind}, +}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult, builders::{make_unexpected_simple_error, make_unused_variable}}; +use diagnostics::{ + DiagnosticResult, + builders::{make_unexpected_simple_error, make_unused_variable}, +}; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{control::{for_loop::parse_for_loop, if_else::parse_if_statement, while_block::parse_while_block}, functions::{parse_function_call, parse_function_declaraction, returns::parse_function_return_statement, shadow::parse_shadow_function_declaration}, structs::{enums::parse_enum_declaration, parse_type_declaration}, use_statements::parse_use_statement, value::parse_ast_value_post_l, variables::{decl::parse_variable_declaration, static_decl::parse_static_variable_declaration}}; +use crate::{ + control::{ + for_loop::parse_for_loop, if_else::parse_if_statement, while_block::parse_while_block, + }, + functions::{ + parse_function_call, parse_function_declaraction, returns::parse_function_return_statement, + shadow::parse_shadow_function_declaration, + }, + structs::{enums::parse_enum_declaration, parse_type_declaration}, + use_statements::parse_use_statement, + value::parse_ast_value_post_l, + variables::{decl::parse_variable_declaration, static_decl::parse_static_variable_declaration}, +}; /// Parses an AST node outside of any other node. -/// +/// /// # Examples /// `parse_ast_node` is used to parse: /// - Function declarations /// - Struct declarations /// - Layout declarations -pub fn parse_ast_node(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - LexerTokenType::Function => { - return parse_function_declaraction(tokens, ind, None); - }, - - LexerTokenType::ShadowFunction => { - return parse_shadow_function_declaration(tokens, ind); - } - - LexerTokenType::Struct => { - return parse_type_declaration(tokens, ind, false); - }, - - LexerTokenType::Static => { - return parse_static_variable_declaration(tokens, ind); - } - - LexerTokenType::Layout => { - return parse_type_declaration(tokens, ind, true); - }, - - LexerTokenType::Enum => { - return parse_enum_declaration(tokens, ind); - }, - - LexerTokenType::Use => { - return parse_use_statement(tokens, ind); - } - - _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) - } +pub fn parse_ast_node( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Function => { + return parse_function_declaraction(tokens, ind, None); + } + + LexerTokenType::ShadowFunction => { + return parse_shadow_function_declaration(tokens, ind); + } + + LexerTokenType::Struct => { + return parse_type_declaration(tokens, ind, false); + } + + LexerTokenType::Static => { + return parse_static_variable_declaration(tokens, ind); + } + + LexerTokenType::Layout => { + return parse_type_declaration(tokens, ind, true); + } + + LexerTokenType::Enum => { + return parse_enum_declaration(tokens, ind); + } + + LexerTokenType::Use => { + return parse_use_statement(tokens, ind); + } + + _ => { + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); + } + } } /// Parses an AST node inside of another compatible node (functions, control bodies) -pub fn parse_ast_node_in_body(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - - LexerTokenType::Var => { - return parse_variable_declaration(tokens, ind); - }, - - LexerTokenType::If => { - return parse_if_statement(tokens, ind); - }, - - LexerTokenType::While => { - return parse_while_block(tokens, ind); - }, - - LexerTokenType::For => { - return parse_for_loop(tokens, ind); - }, - - LexerTokenType::Return => { - return parse_function_return_statement(tokens, ind); - } - - LexerTokenType::Keyword(str, _) => { - if tokens[*ind + 1].tok_type == LexerTokenType::ParenOpen { - let call = parse_function_call(tokens, ind); - return parse_ast_value_post_l(tokens, ind, call, true); - } - - let n = Ok(make_node!(ASTTreeNodeKind::VariableReference(HashedString::new(str.clone())), &tokens[*ind], &tokens[*ind])); - - *ind += 1; - - let new = parse_ast_value_post_l(tokens, ind, n, true)?; - - if new.kind.is_var_access() { - return Err(make_unused_variable(&*new, &"access".to_string()).into()) - } - - return Ok(new); - }, - - _ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) - } -} \ No newline at end of file +pub fn parse_ast_node_in_body( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Var => { + return parse_variable_declaration(tokens, ind); + } + + LexerTokenType::If => { + return parse_if_statement(tokens, ind); + } + + LexerTokenType::While => { + return parse_while_block(tokens, ind); + } + + LexerTokenType::For => { + return parse_for_loop(tokens, ind); + } + + LexerTokenType::Return => { + return parse_function_return_statement(tokens, ind); + } + + LexerTokenType::Keyword(str, _) => { + if tokens[*ind + 1].tok_type == LexerTokenType::ParenOpen { + let call = parse_function_call(tokens, ind); + return parse_ast_value_post_l(tokens, ind, call, true); + } + + let n = Ok(make_node!( + ASTTreeNodeKind::VariableReference(HashedString::new(str.clone())), + &tokens[*ind], + &tokens[*ind] + )); + + *ind += 1; + + let new = parse_ast_value_post_l(tokens, ind, n, true)?; + + if new.kind.is_var_access() { + return Err(make_unused_variable(&*new, &"access".to_string()).into()); + } + + return Ok(new); + } + + _ => { + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); + } + } +} diff --git a/compiler/ast_parser/src/structs/enums.rs b/compiler/ast_parser/src/structs/enums.rs index 8aa4ab7..60447fd 100644 --- a/compiler/ast_parser/src/structs/enums.rs +++ b/compiler/ast_parser/src/structs/enums.rs @@ -1,68 +1,100 @@ -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType}; +use ast::{ + tree::{ASTTreeNode, ASTTreeNodeKind}, + types::ASTType, +}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult}; +use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::{parse_type_parameters_declaration}}; +use crate::{ + functions::parse_function_declaraction, structs::members::parse_types_field_member, + types::parse_type_parameters_declaration, +}; -pub fn parse_enum_entry(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_enum_entry( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - let name = tokens[*ind].expects_keyword()?; - *ind += 1; + let name = tokens[*ind].expects_keyword()?; + *ind += 1; - let mut fields = vec![]; + let mut fields = vec![]; - tokens[*ind].expects(LexerTokenType::ParenOpen)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::ParenOpen)?; + *ind += 1; - loop { - fields.push(parse_types_field_member(tokens, ind)?); + loop { + fields.push(parse_types_field_member(tokens, ind)?); - if tokens[*ind].tok_type == LexerTokenType::ParenClose { - break; - } + if tokens[*ind].tok_type == LexerTokenType::ParenClose { + break; + } - tokens[*ind].expects(LexerTokenType::Comma)?; - } + tokens[*ind].expects(LexerTokenType::Comma)?; + } - *ind += 1; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::EnumEntryDeclaration { name: HashedString::new(name.0), fields }, start, tokens[*ind].get_end_pos()))) + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::EnumEntryDeclaration { + name: HashedString::new(name.0), + fields, + }, + start, + tokens[*ind].get_end_pos(), + ))); } -pub fn parse_enum_declaration(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); - - *ind += 1; - - let name = tokens[*ind].expects_keyword()?; - *ind += 1; - - let t = parse_type_parameters_declaration(tokens, ind)?; - - tokens[*ind].expects(LexerTokenType::BracketOpen)?; - *ind += 1; - - let mut entries = vec![]; - let mut functions = vec![]; - - let temp_type = ASTType::Generic(name.0.clone(), vec![], vec![], None); - - loop { - if tokens[*ind].is_keyword() { - entries.push(parse_enum_entry(tokens, ind)?); - } else { - tokens[*ind].expects(LexerTokenType::Function)?; - - functions.push(parse_function_declaraction(tokens, ind, Some(temp_type.clone()))?) - } - - if tokens[*ind].tok_type == LexerTokenType::BracketClose { - break; - } - } - *ind += 1; - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::EnumDeclaration { name: HashedString::new(name.0), entries, functions, type_params: t }, start, tokens[*ind].get_end_pos()))) -} \ No newline at end of file +pub fn parse_enum_declaration( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); + + *ind += 1; + + let name = tokens[*ind].expects_keyword()?; + *ind += 1; + + let t = parse_type_parameters_declaration(tokens, ind)?; + + tokens[*ind].expects(LexerTokenType::BracketOpen)?; + *ind += 1; + + let mut entries = vec![]; + let mut functions = vec![]; + + let temp_type = ASTType::Generic(name.0.clone(), vec![], vec![], None); + + loop { + if tokens[*ind].is_keyword() { + entries.push(parse_enum_entry(tokens, ind)?); + } else { + tokens[*ind].expects(LexerTokenType::Function)?; + + functions.push(parse_function_declaraction( + tokens, + ind, + Some(temp_type.clone()), + )?) + } + + if tokens[*ind].tok_type == LexerTokenType::BracketClose { + break; + } + } + *ind += 1; + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::EnumDeclaration { + name: HashedString::new(name.0), + entries, + functions, + type_params: t, + }, + start, + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/structs/members.rs b/compiler/ast_parser/src/structs/members.rs index 4e54026..9b68fd3 100644 --- a/compiler/ast_parser/src/structs/members.rs +++ b/compiler/ast_parser/src/structs/members.rs @@ -1,21 +1,31 @@ use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; -use lexer::token::{LexerToken}; +use lexer::token::LexerToken; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use crate::types::parse_type; /// Parses a struct/layout member (field) -pub fn parse_types_field_member(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); - let member_type = parse_type(tokens, ind)?; +pub fn parse_types_field_member( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); + let member_type = parse_type(tokens, ind)?; - let field_name = tokens[*ind].expects_keyword()?; + let field_name = tokens[*ind].expects_keyword()?; - let end = tokens[*ind].get_end_pos().clone(); + let end = tokens[*ind].get_end_pos().clone(); - *ind += 1; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructFieldMember { name: HashedString::new(field_name.0), member_type }, start, end))) -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StructFieldMember { + name: HashedString::new(field_name.0), + member_type, + }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/structs/mod.rs b/compiler/ast_parser/src/structs/mod.rs index 0fda9ee..18d80cd 100644 --- a/compiler/ast_parser/src/structs/mod.rs +++ b/compiler/ast_parser/src/structs/mod.rs @@ -2,44 +2,67 @@ use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}, types::{ASTType}}; +use ast::{ + tree::{ASTTreeNode, ASTTreeNodeKind}, + types::ASTType, +}; -use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::parse_type_parameters_declaration}; +use crate::{ + functions::parse_function_declaraction, structs::members::parse_types_field_member, + types::parse_type_parameters_declaration, +}; +pub mod enums; pub mod members; pub mod val; -pub mod enums; -pub fn parse_type_declaration(tokens: &Vec, ind: &mut usize, layout: bool) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_type_declaration( + tokens: &Vec, + ind: &mut usize, + layout: bool, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let type_name = tokens[*ind].expects_keyword()?; + let type_name = tokens[*ind].expects_keyword()?; - *ind += 1; + *ind += 1; - let type_params = parse_type_parameters_declaration(tokens, ind)?; + let type_params = parse_type_parameters_declaration(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::BracketOpen)?; + tokens[*ind].expects(LexerTokenType::BracketOpen)?; - *ind += 1; + *ind += 1; - let mut members: Vec> = Vec::new(); + let mut members: Vec> = Vec::new(); - let temp_type = ASTType::Generic(type_name.0.clone(), vec![], vec![], None); + let temp_type = ASTType::Generic(type_name.0.clone(), vec![], vec![], None); - while tokens[*ind].tok_type != LexerTokenType::BracketClose { - if tokens[*ind].tok_type == LexerTokenType::Function { - members.push(parse_function_declaraction(tokens, ind, Some(temp_type.clone()))?); - } else { - members.push(parse_types_field_member(tokens, ind)?); - } - } + while tokens[*ind].tok_type != LexerTokenType::BracketClose { + if tokens[*ind].tok_type == LexerTokenType::Function { + members.push(parse_function_declaraction( + tokens, + ind, + Some(temp_type.clone()), + )?); + } else { + members.push(parse_types_field_member(tokens, ind)?); + } + } - let end = tokens[*ind].get_end_pos().clone(); + let end = tokens[*ind].get_end_pos().clone(); - *ind += 1; + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructLayoutDeclaration { name: HashedString::new(type_name.0), layout, members, type_params }, start, end))); -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StructLayoutDeclaration { + name: HashedString::new(type_name.0), + layout, + members, + type_params, + }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/structs/val.rs b/compiler/ast_parser/src/structs/val.rs index 244b987..c44a61f 100644 --- a/compiler/ast_parser/src/structs/val.rs +++ b/compiler/ast_parser/src/structs/val.rs @@ -5,39 +5,49 @@ use compiler_utils::hash::{HashedString, SelfHash}; use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{value::parse_ast_value}; +use crate::value::parse_ast_value; -pub fn parse_struct_initialize(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_struct_initialize( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let mut map: HashMap> = HashMap::new(); + let mut map: HashMap> = HashMap::new(); - while tokens[*ind].is_keyword() { - let field_name = tokens[*ind].expects_keyword()?; - *ind += 1; + while tokens[*ind].is_keyword() { + let field_name = tokens[*ind].expects_keyword()?; + *ind += 1; - tokens[*ind].expects(LexerTokenType::Collon)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Collon)?; + *ind += 1; + let value = parse_ast_value(tokens, ind)?; - let value = parse_ast_value(tokens, ind)?; + map.insert( + SelfHash { + hash: HashedString::new(field_name.0).hash, + }, + value, + ); + //*ind += 1; - map.insert(SelfHash { hash: HashedString::new(field_name.0).hash }, value); + if tokens[*ind].tok_type == LexerTokenType::BracketClose { + break; + } - //*ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; + } - if tokens[*ind].tok_type == LexerTokenType::BracketClose { - break; - } + *ind += 1; - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; - } - - *ind += 1; - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructInitializer { map }, start, tokens[*ind].get_end_pos()))) -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StructInitializer { map }, + start, + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/types.rs b/compiler/ast_parser/src/types.rs index 7f89348..8dcd24c 100644 --- a/compiler/ast_parser/src/types.rs +++ b/compiler/ast_parser/src/types.rs @@ -1,220 +1,250 @@ //! Parsing for type related features -use ast::{types::ASTType}; +use ast::types::ASTType; use compiler_typing::TypeParameterContainer; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult, builders::{make_expected_single_simple_error, make_unexpected_simple_error}}; -use lexer::{token::{LexerToken, LexerTokenType}}; +use diagnostics::{ + DiagnosticResult, + builders::{make_expected_single_simple_error, make_unexpected_simple_error}, +}; +use lexer::token::{LexerToken, LexerTokenType}; #[derive(Clone, Debug)] pub enum ParsingASTTypeMember { - Generic(String, Vec>, Vec, Option), - Pointer(bool), - Reference, - Array(usize) + Generic(String, Vec>, Vec, Option), + Pointer(bool), + Reference, + Array(usize), } /// Parses the type size specifiers -pub fn parse_type_size_specifiers(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - if tokens[*ind].tok_type != LexerTokenType::Dot { - return Ok(vec![]); - } +pub fn parse_type_size_specifiers( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + if tokens[*ind].tok_type != LexerTokenType::Dot { + return Ok(vec![]); + } - let mut sizes = vec![]; + let mut sizes = vec![]; - while tokens[*ind].tok_type == LexerTokenType::Dot { - *ind += 1; + while tokens[*ind].tok_type == LexerTokenType::Dot { + *ind += 1; - sizes.push(tokens[*ind].expects_int_lit()?.0 as usize); + sizes.push(tokens[*ind].expects_int_lit()?.0 as usize); - *ind += 1; - } + *ind += 1; + } - return Ok(sizes); + return Ok(sizes); } -pub fn parse_type_type_parameters(tokens: &Vec, ind: &mut usize) -> DiagnosticResult>> { - if tokens[*ind].tok_type != LexerTokenType::AngelBracketOpen { - return Ok(vec![]); - } +pub fn parse_type_type_parameters( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult>> { + if tokens[*ind].tok_type != LexerTokenType::AngelBracketOpen { + return Ok(vec![]); + } - let mut types = vec![]; + let mut types = vec![]; - *ind += 1; + *ind += 1; - loop { - let parsed_type = Box::new(parse_type(tokens, ind)?); + loop { + let parsed_type = Box::new(parse_type(tokens, ind)?); - types.push(parsed_type); + types.push(parsed_type); - if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { - break; - } + if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { + break; + } - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; - } + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; + } - *ind += 1; + *ind += 1; - return Ok(types) + return Ok(types); } - -pub fn parse_type_generic(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { - let type_name = tokens[*ind].expects_keyword()?; - *ind += 1; +pub fn parse_type_generic( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult { + let type_name = tokens[*ind].expects_keyword()?; - let specifier; + *ind += 1; - if tokens[*ind].tok_type == LexerTokenType::Collon { - *ind += 1; + let specifier; - tokens[*ind].expects(LexerTokenType::Collon)?; - *ind += 1; - - specifier = Some(tokens[*ind].expects_keyword()?.0); - *ind += 1; - } else { - specifier = None; - } + if tokens[*ind].tok_type == LexerTokenType::Collon { + *ind += 1; - let sizes = parse_type_size_specifiers(tokens, ind)?; - let types = parse_type_type_parameters(tokens, ind)?; + tokens[*ind].expects(LexerTokenType::Collon)?; + *ind += 1; - return Ok(ParsingASTTypeMember::Generic(type_name.0, types, sizes, specifier)) + specifier = Some(tokens[*ind].expects_keyword()?.0); + *ind += 1; + } else { + specifier = None; + } + + let sizes = parse_type_size_specifiers(tokens, ind)?; + let types = parse_type_type_parameters(tokens, ind)?; + + return Ok(ParsingASTTypeMember::Generic( + type_name.0, + types, + sizes, + specifier, + )); } -pub fn parse_type_member(tokens: &Vec, ind: &mut usize, took_generic: bool) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - LexerTokenType::Keyword(_, _) => { - if took_generic { - return Ok(None) - } +pub fn parse_type_member( + tokens: &Vec, + ind: &mut usize, + took_generic: bool, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Keyword(_, _) => { + if took_generic { + return Ok(None); + } + + return Ok(Some(parse_type_generic(tokens, ind)?)); + } - return Ok(Some(parse_type_generic(tokens, ind)?)) - }, + LexerTokenType::ParenOpen => { + *ind += 1; - LexerTokenType::ParenOpen => { - *ind += 1; - - let res = parse_type_member(tokens, ind, took_generic)?; - *ind += 1; + let res = parse_type_member(tokens, ind, took_generic)?; + *ind += 1; - tokens[*ind].expects(LexerTokenType::ParenClose)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::ParenClose)?; + *ind += 1; - return Ok(res); - } + return Ok(res); + } - LexerTokenType::Ampersand => { - *ind += 1; + LexerTokenType::Ampersand => { + *ind += 1; - return Ok(Some(ParsingASTTypeMember::Reference)); - } + return Ok(Some(ParsingASTTypeMember::Reference)); + } - LexerTokenType::Asterisk => { - *ind += 1; + LexerTokenType::Asterisk => { + *ind += 1; - if tokens[*ind].tok_type == LexerTokenType::ArrayOpen { - *ind += 1; + if tokens[*ind].tok_type == LexerTokenType::ArrayOpen { + *ind += 1; - tokens[*ind].expects(LexerTokenType::ArrayClose)?; + tokens[*ind].expects(LexerTokenType::ArrayClose)?; - *ind += 1; + *ind += 1; - return Ok(Some(ParsingASTTypeMember::Pointer(true))) - } + return Ok(Some(ParsingASTTypeMember::Pointer(true))); + } - return Ok(Some(ParsingASTTypeMember::Pointer(false))) - }, + return Ok(Some(ParsingASTTypeMember::Pointer(false))); + } - LexerTokenType::ArrayOpen => { - *ind += 1; - - let size = tokens[*ind].expects_int_lit()?; + LexerTokenType::ArrayOpen => { + *ind += 1; - *ind += 1; + let size = tokens[*ind].expects_int_lit()?; - tokens[*ind].expects(LexerTokenType::ArrayClose)?; + *ind += 1; - *ind += 1; + tokens[*ind].expects(LexerTokenType::ArrayClose)?; - return Ok(Some(ParsingASTTypeMember::Array(size.0 as usize))) - }, + *ind += 1; - _ => { - if took_generic { - return Ok(None); - } + return Ok(Some(ParsingASTTypeMember::Array(size.0 as usize))); + } - return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) - } - } + _ => { + if took_generic { + return Ok(None); + } + + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); + } + } } pub fn parse_type(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { - let mut members = vec![]; - let mut took_generic = false; - - loop { - let parsed_member = parse_type_member(tokens, ind, took_generic)?; - - if let Some(value) = parsed_member { - if let ParsingASTTypeMember::Generic(_, _, _, _) = &value { - took_generic = true; - } - - members.push(value); - } else { - break; - } - } - - let mut child = None; - - for i in 0..members.len() { - let converted_member = match members[i].clone() { - ParsingASTTypeMember::Generic(t, types, sizes, specifier) => ASTType::Generic(t, types, sizes, specifier), - ParsingASTTypeMember::Pointer(array) => ASTType::Pointer(array, child.unwrap()), - ParsingASTTypeMember::Reference => ASTType::Reference(child.unwrap()), - ParsingASTTypeMember::Array(size) => ASTType::Array(size, child.unwrap()) - }; - - child = Some(Box::new(converted_member)); - } - - return match child { - Some(v) => Ok(*v), - None => return Err(make_expected_single_simple_error(&tokens[*ind], &"type".to_string()).into()) - }; + let mut members = vec![]; + let mut took_generic = false; + + loop { + let parsed_member = parse_type_member(tokens, ind, took_generic)?; + + if let Some(value) = parsed_member { + if let ParsingASTTypeMember::Generic(_, _, _, _) = &value { + took_generic = true; + } + + members.push(value); + } else { + break; + } + } + + let mut child = None; + + for i in 0..members.len() { + let converted_member = match members[i].clone() { + ParsingASTTypeMember::Generic(t, types, sizes, specifier) => { + ASTType::Generic(t, types, sizes, specifier) + } + ParsingASTTypeMember::Pointer(array) => ASTType::Pointer(array, child.unwrap()), + ParsingASTTypeMember::Reference => ASTType::Reference(child.unwrap()), + ParsingASTTypeMember::Array(size) => ASTType::Array(size, child.unwrap()), + }; + + child = Some(Box::new(converted_member)); + } + + return match child { + Some(v) => Ok(*v), + None => { + return Err( + make_expected_single_simple_error(&tokens[*ind], &"type".to_string()).into(), + ); + } + }; } -pub fn parse_type_parameters_declaration(tokens: &Vec, ind: &mut usize) -> DiagnosticResult { - if tokens[*ind].tok_type != LexerTokenType::AngelBracketOpen { - return Ok(TypeParameterContainer::new()); - } +pub fn parse_type_parameters_declaration( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult { + if tokens[*ind].tok_type != LexerTokenType::AngelBracketOpen { + return Ok(TypeParameterContainer::new()); + } + + let mut container = TypeParameterContainer::new(); - let mut container = TypeParameterContainer::new(); + *ind += 1; - *ind += 1; + while tokens[*ind].is_keyword() { + let param = tokens[*ind].expects_keyword()?; - while tokens[*ind].is_keyword() { - let param = tokens[*ind].expects_keyword()?; + container.insert(HashedString::new(param.0), container.len()); - container.insert(HashedString::new(param.0), container.len()); + *ind += 1; - *ind += 1; - - if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { - break; - } + if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { + break; + } - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; - } + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; + } - *ind += 1; + *ind += 1; - return Ok(container); -} \ No newline at end of file + return Ok(container); +} diff --git a/compiler/ast_parser/src/unwraps.rs b/compiler/ast_parser/src/unwraps.rs index 70893b4..06eb19f 100644 --- a/compiler/ast_parser/src/unwraps.rs +++ b/compiler/ast_parser/src/unwraps.rs @@ -1,63 +1,86 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult}; +use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; use crate::{types::parse_type, value::parse_ast_value}; -pub fn parse_unwrap_condition(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_unwrap_condition( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - let unsafe_unwrap = tokens[*ind].tok_type == LexerTokenType::UnwrapUnsafe; - *ind += 1; + let unsafe_unwrap = tokens[*ind].tok_type == LexerTokenType::UnwrapUnsafe; + *ind += 1; - tokens[*ind].expects(LexerTokenType::AngelBracketOpen)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::AngelBracketOpen)?; + *ind += 1; - let original = parse_ast_value(tokens, ind)?; + let original = parse_ast_value(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; - let new_type = parse_type(tokens, ind)?; + let new_type = parse_type(tokens, ind)?; - let new_var: Option; - if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { - new_var = None; - } else { - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + let new_var: Option; + if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose { + new_var = None; + } else { + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; - let kwd = tokens[*ind].expects_keyword()?; + let kwd = tokens[*ind].expects_keyword()?; - new_var = Some(HashedString::new(kwd.0)); + new_var = Some(HashedString::new(kwd.0)); - *ind += 1; - tokens[*ind].expects(LexerTokenType::AngelBracketClose)?; - } + *ind += 1; + tokens[*ind].expects(LexerTokenType::AngelBracketClose)?; + } - *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::UnwrapCondition { original, target_type: new_type, unsafe_unwrap, target_var: new_var }, start, tokens[*ind].get_end_pos()))) + *ind += 1; + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::UnwrapCondition { + original, + target_type: new_type, + unsafe_unwrap, + target_var: new_var, + }, + start, + tokens[*ind].get_end_pos(), + ))); } -pub fn parse_unwrap_value(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_unwrap_value( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - let unsafe_unwrap = tokens[*ind].tok_type == LexerTokenType::UnwrapUnsafe; - *ind += 1; + let unsafe_unwrap = tokens[*ind].tok_type == LexerTokenType::UnwrapUnsafe; + *ind += 1; - tokens[*ind].expects(LexerTokenType::AngelBracketOpen)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::AngelBracketOpen)?; + *ind += 1; - let original = parse_ast_value(tokens, ind)?; + let original = parse_ast_value(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; - let new_type = parse_type(tokens, ind)?; + let new_type = parse_type(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::AngelBracketClose)?; + tokens[*ind].expects(LexerTokenType::AngelBracketClose)?; - *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::UnwrapValue { original, target_type: new_type, unsafe_unwrap }, start, tokens[*ind].get_end_pos()))) -} \ No newline at end of file + *ind += 1; + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::UnwrapValue { + original, + target_type: new_type, + unsafe_unwrap, + }, + start, + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/use_statements.rs b/compiler/ast_parser/src/use_statements.rs index e8b3e3b..2032763 100644 --- a/compiler/ast_parser/src/use_statements.rs +++ b/compiler/ast_parser/src/use_statements.rs @@ -3,42 +3,52 @@ use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -pub fn parse_use_statement(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_use_statement( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let mut steps = vec![]; - let mut uses = vec![]; + let mut steps = vec![]; + let mut uses = vec![]; - while tokens[*ind].is_keyword() { - let kwd = tokens[*ind].expects_keyword()?; - *ind += 1; + while tokens[*ind].is_keyword() { + let kwd = tokens[*ind].expects_keyword()?; + *ind += 1; - steps.push(HashedString::new(kwd.0)); - - tokens[*ind].expects(LexerTokenType::Collon)?; - *ind += 1; - } + steps.push(HashedString::new(kwd.0)); - tokens[*ind].expects(LexerTokenType::ArrayOpen)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Collon)?; + *ind += 1; + } - while tokens[*ind].is_keyword() { - let kwd = tokens[*ind].expects_keyword()?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::ArrayOpen)?; + *ind += 1; - uses.push(HashedString::new(kwd.0)); + while tokens[*ind].is_keyword() { + let kwd = tokens[*ind].expects_keyword()?; + *ind += 1; - if tokens[*ind].tok_type == LexerTokenType::ArrayClose { - break; - } + uses.push(HashedString::new(kwd.0)); - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; - } + if tokens[*ind].tok_type == LexerTokenType::ArrayClose { + break; + } - *ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; + } - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::UseStatement { shards: steps, use_clauses: uses }, start, tokens[*ind].get_end_pos()))) -} \ No newline at end of file + *ind += 1; + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::UseStatement { + shards: steps, + use_clauses: uses, + }, + start, + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/value.rs b/compiler/ast_parser/src/value.rs index f176559..1e453cf 100644 --- a/compiler/ast_parser/src/value.rs +++ b/compiler/ast_parser/src/value.rs @@ -1,73 +1,111 @@ use compiler_utils::{Position, hash::HashedString}; -use ast::{make_node, tree::{ASTTreeNode, ASTTreeNodeKind}}; -use diagnostics::{DiagnosticResult, builders::{make_expected_simple_error, make_unexpected_simple_error}}; +use ast::{ + make_node, + tree::{ASTTreeNode, ASTTreeNodeKind}, +}; +use diagnostics::{ + DiagnosticResult, + builders::{make_expected_simple_error, make_unexpected_simple_error}, +}; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{arrays::parse_array_access, comp::parse_ast_compare, functions::parse_function_call, structs::val::parse_struct_initialize, unwraps::{parse_unwrap_condition, parse_unwrap_value}}; use crate::literals::{parse_integer_literal, parse_string_literal}; use crate::math::parse_math_operation; - -pub fn parse_ast_value_dotacess(tokens: &Vec, ind: &mut usize, original: DiagnosticResult>) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - LexerTokenType::Dot => { - let original = original?; - if !original.kind.is_function_call() && !original.kind.is_var_access() { - return Err(make_unexpected_simple_error(&tokens[*ind], &original).into()); - } - - *ind += 1; - let r = parse_ast_value_dotacess_chain_member(tokens, ind, Ok(original))?; - - if tokens[*ind].tok_type == LexerTokenType::Dot { - return parse_ast_value_dotacess(tokens, ind, Ok(r)); // Continue the chain until finished - } - - return Ok(r); - }, - - _ => return original - } +use crate::{ + arrays::parse_array_access, + comp::parse_ast_compare, + functions::parse_function_call, + structs::val::parse_struct_initialize, + unwraps::{parse_unwrap_condition, parse_unwrap_value}, +}; + +pub fn parse_ast_value_dotacess( + tokens: &Vec, + ind: &mut usize, + original: DiagnosticResult>, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Dot => { + let original = original?; + if !original.kind.is_function_call() && !original.kind.is_var_access() { + return Err(make_unexpected_simple_error(&tokens[*ind], &original).into()); + } + + *ind += 1; + let r = parse_ast_value_dotacess_chain_member(tokens, ind, Ok(original))?; + + if tokens[*ind].tok_type == LexerTokenType::Dot { + return parse_ast_value_dotacess(tokens, ind, Ok(r)); // Continue the chain until finished + } + + return Ok(r); + } + + _ => return original, + } } -pub fn parse_ast_value_dotacess_chain_member(tokens: &Vec, ind: &mut usize, original: DiagnosticResult>) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - LexerTokenType::Keyword(s, _) => { - if tokens[*ind + 1].tok_type == LexerTokenType::ParenOpen { - let r_member = parse_function_call(tokens, ind)?; - let start = original.as_ref().unwrap().start.clone(); - let end = r_member.end.clone(); - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructLRFunction { l: original?, r: r_member }, start, end))) - } - - let start = original.clone()?.start.clone(); - let end = tokens[*ind].get_end_pos(); - - let r_member = Box::new(ASTTreeNode::new(ASTTreeNodeKind::VariableReference(HashedString::new(s.clone())), start.clone(), end)); - - *ind += 1; - - let end_r = r_member.end.clone(); - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructLRVariable { l: original?, r: r_member }, start, end_r))); - }, - - _ => return original - }; +pub fn parse_ast_value_dotacess_chain_member( + tokens: &Vec, + ind: &mut usize, + original: DiagnosticResult>, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Keyword(s, _) => { + if tokens[*ind + 1].tok_type == LexerTokenType::ParenOpen { + let r_member = parse_function_call(tokens, ind)?; + let start = original.as_ref().unwrap().start.clone(); + let end = r_member.end.clone(); + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StructLRFunction { + l: original?, + r: r_member, + }, + start, + end, + ))); + } + + let start = original.clone()?.start.clone(); + let end = tokens[*ind].get_end_pos(); + + let r_member = Box::new(ASTTreeNode::new( + ASTTreeNodeKind::VariableReference(HashedString::new(s.clone())), + start.clone(), + end, + )); + + *ind += 1; + + let end_r = r_member.end.clone(); + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StructLRVariable { + l: original?, + r: r_member, + }, + start, + end_r, + ))); + } + + _ => return original, + }; } /// Parses the post side of an AST node that can and WILL be intrepreted as a value. -/// +/// /// This function should only be called by `parse_ast_value` -/// -/// # Parsing Layout +/// +/// # Parsing Layout /// The `parse_ast_value` function only parses the post side of the expression (noted L) if expression is: /// `R (pre) expression L (post) expression` -/// +/// /// This layout allows us to seperate parsing from things like variable references, functions calls or even literals and /// treat them as the same while parsing other elements such as math operations or conditions! -/// +/// /// # Possible node results /// `parse_ast_value_post_l` can possibly return the following node types: /// - original type @@ -75,77 +113,101 @@ pub fn parse_ast_value_dotacess_chain_member(tokens: &Vec, ind: &mut /// - math operation /// - comparing /// - boolean negation -/// -pub fn parse_ast_value_post_l(tokens: &Vec, ind: &mut usize, original: DiagnosticResult>, invoked_on_body: bool) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - LexerTokenType::Plus | LexerTokenType::Minus | LexerTokenType::Asterisk | LexerTokenType::Divide => { - let o = &original?; - let k = Box::new(ASTTreeNode::clone(o.as_ref())); - - return Ok(parse_math_operation(tokens, ind, k, invoked_on_body)?); - }, - - LexerTokenType::ArrayOpen => { - let k = parse_array_access(tokens, ind, original?)?; - - return parse_ast_value_post_l(tokens, ind, Ok(k), invoked_on_body) - }, - - LexerTokenType::EqualSign => { - if tokens[*ind + 1].tok_type == LexerTokenType::EqualSign { - return parse_ast_compare(tokens, ind, original.clone()?); - } - - *ind += 1; - - if let Ok(v) = original.as_ref() { - if let ASTTreeNodeKind::ArrayIndexAccess { val, index } = &v.kind { - let start = original.clone()?.start.clone(); - - let right_val = parse_ast_value(tokens, ind)?; - - let end = right_val.end.clone(); - - let kind = ASTTreeNodeKind::ArrayIndexModifiy { array: val.clone(), index: index.clone(), val: right_val }; - - return Ok(Box::new(ASTTreeNode::new(kind, start, end))); - } - } - - let start = original.clone()?.start.clone(); - - let right_val = parse_ast_value(tokens, ind)?; - - let end = right_val.end.clone(); - - let kind = ASTTreeNodeKind::VarValueChange { var: original?, value: right_val }; - return Ok(Box::new(ASTTreeNode::new(kind, start, end))); - }, - - LexerTokenType::ExclamationMark | LexerTokenType::AngelBracketOpen | LexerTokenType::AngelBracketClose => return parse_ast_compare(tokens, ind, original.clone()?), - - _ => return original - } +/// +pub fn parse_ast_value_post_l( + tokens: &Vec, + ind: &mut usize, + original: DiagnosticResult>, + invoked_on_body: bool, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Plus + | LexerTokenType::Minus + | LexerTokenType::Asterisk + | LexerTokenType::Divide => { + let o = &original?; + let k = Box::new(ASTTreeNode::clone(o.as_ref())); + + return Ok(parse_math_operation(tokens, ind, k, invoked_on_body)?); + } + + LexerTokenType::ArrayOpen => { + let k = parse_array_access(tokens, ind, original?)?; + + return parse_ast_value_post_l(tokens, ind, Ok(k), invoked_on_body); + } + + LexerTokenType::EqualSign => { + if tokens[*ind + 1].tok_type == LexerTokenType::EqualSign { + return parse_ast_compare(tokens, ind, original.clone()?); + } + + *ind += 1; + + if let Ok(v) = original.as_ref() { + if let ASTTreeNodeKind::ArrayIndexAccess { val, index } = &v.kind { + let start = original.clone()?.start.clone(); + + let right_val = parse_ast_value(tokens, ind)?; + + let end = right_val.end.clone(); + + let kind = ASTTreeNodeKind::ArrayIndexModifiy { + array: val.clone(), + index: index.clone(), + val: right_val, + }; + + return Ok(Box::new(ASTTreeNode::new(kind, start, end))); + } + } + + let start = original.clone()?.start.clone(); + + let right_val = parse_ast_value(tokens, ind)?; + + let end = right_val.end.clone(); + + let kind = ASTTreeNodeKind::VarValueChange { + var: original?, + value: right_val, + }; + return Ok(Box::new(ASTTreeNode::new(kind, start, end))); + } + + LexerTokenType::ExclamationMark + | LexerTokenType::AngelBracketOpen + | LexerTokenType::AngelBracketClose => { + return parse_ast_compare(tokens, ind, original.clone()?); + } + + _ => return original, + } } -pub fn parse_ast_condition_if_statement_value(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - LexerTokenType::Unwrap | LexerTokenType::UnwrapUnsafe => parse_unwrap_condition(tokens, ind), - _ => parse_ast_value(tokens, ind) - } +pub fn parse_ast_condition_if_statement_value( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::Unwrap | LexerTokenType::UnwrapUnsafe => { + parse_unwrap_condition(tokens, ind) + } + _ => parse_ast_value(tokens, ind), + } } /// Parses an AST node that can and WILL be intrepreted as a value -/// -/// # Parsing Layout +/// +/// # Parsing Layout /// The `parse_ast_value` function only parses the pre side of the expression (noted R) if expression is: /// `R (pre) expression L (post) expression` -/// +/// /// This layout allows us to seperate parsing from things like variable references, functions calls or even literals and /// treat them as the same while parsing other elements such as math operations or conditions! -/// +/// /// This function will call `parse_ast_value_post_l` to parse the L part of the expression. -/// +/// /// # Recognized Nodes /// Possible nodes recognized as values include: /// - Function calls @@ -153,115 +215,162 @@ pub fn parse_ast_condition_if_statement_value(tokens: &Vec, ind: &mu /// - Math operation results (both with or without value changing) /// - Boolean negation result /// - Boolean compare result -pub fn parse_ast_value(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - match &tokens[*ind].tok_type { - - LexerTokenType::ExclamationMark => { - *ind += 1; - let ast = parse_ast_value(tokens, ind)?; - - if ast.kind.is_function_call() || ast.kind.is_var_access() { - let end = ast.end.clone(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::BooleanBasedConditionMember { val: ast, negate: true }, Position::clone(&tokens[*ind].pos), end))) - } - - return Err(make_expected_simple_error(&tokens[*ind], &"function call or variable access".to_string(),&ast).into()); - }, - - LexerTokenType::ArrayOpen => { - return parse_ast_array_init(tokens, ind); - } - - LexerTokenType::Asterisk => return parse_ast_pointer(tokens, ind), - LexerTokenType::Ampersand => return parse_ast_reference(tokens, ind), - - LexerTokenType::IntLit(_, _) => { - let int = parse_integer_literal(tokens, ind); - return parse_ast_value_post_l(tokens, ind, int, false); - }, - - LexerTokenType::StringLit(_) => { - let str = parse_string_literal(tokens, ind); - return parse_ast_value_post_l(tokens, ind, str, false); - }, - - LexerTokenType::BracketOpen => { - return parse_struct_initialize(tokens, ind); - } - - LexerTokenType::Keyword(str, _) => { - if tokens[*ind + 1].tok_type == LexerTokenType::ParenOpen { - let call = parse_function_call(tokens, ind); - return parse_ast_value_post_l(tokens, ind, call, false); - } - - let n = Ok(make_node!(ASTTreeNodeKind::VariableReference(HashedString::new(str.clone())), &tokens[*ind], &tokens[*ind])); - - *ind += 1; - - let chain = parse_ast_value_dotacess(tokens, ind, n); - - return parse_ast_value_post_l(tokens, ind, chain, false); - }, - - LexerTokenType::Unwrap | LexerTokenType::UnwrapUnsafe => parse_unwrap_value(tokens, ind), - - _=> return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()) - } +pub fn parse_ast_value( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + match &tokens[*ind].tok_type { + LexerTokenType::ExclamationMark => { + *ind += 1; + let ast = parse_ast_value(tokens, ind)?; + + if ast.kind.is_function_call() || ast.kind.is_var_access() { + let end = ast.end.clone(); + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::BooleanBasedConditionMember { + val: ast, + negate: true, + }, + Position::clone(&tokens[*ind].pos), + end, + ))); + } + + return Err(make_expected_simple_error( + &tokens[*ind], + &"function call or variable access".to_string(), + &ast, + ) + .into()); + } + + LexerTokenType::ArrayOpen => { + return parse_ast_array_init(tokens, ind); + } + + LexerTokenType::Asterisk => return parse_ast_pointer(tokens, ind), + LexerTokenType::Ampersand => return parse_ast_reference(tokens, ind), + + LexerTokenType::IntLit(_, _) => { + let int = parse_integer_literal(tokens, ind); + return parse_ast_value_post_l(tokens, ind, int, false); + } + + LexerTokenType::StringLit(_) => { + let str = parse_string_literal(tokens, ind); + return parse_ast_value_post_l(tokens, ind, str, false); + } + + LexerTokenType::BracketOpen => { + return parse_struct_initialize(tokens, ind); + } + + LexerTokenType::Keyword(str, _) => { + if tokens[*ind + 1].tok_type == LexerTokenType::ParenOpen { + let call = parse_function_call(tokens, ind); + return parse_ast_value_post_l(tokens, ind, call, false); + } + + let n = Ok(make_node!( + ASTTreeNodeKind::VariableReference(HashedString::new(str.clone())), + &tokens[*ind], + &tokens[*ind] + )); + + *ind += 1; + + let chain = parse_ast_value_dotacess(tokens, ind, n); + + return parse_ast_value_post_l(tokens, ind, chain, false); + } + + LexerTokenType::Unwrap | LexerTokenType::UnwrapUnsafe => parse_unwrap_value(tokens, ind), + + _ => { + return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into()); + } + } } -pub fn parse_ast_array_init(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); - *ind += 1; +pub fn parse_ast_array_init( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); + *ind += 1; - if tokens[*ind + 1].tok_type == LexerTokenType::Comma { - let val = parse_ast_value(tokens, ind)?; + if tokens[*ind + 1].tok_type == LexerTokenType::Comma { + let val = parse_ast_value(tokens, ind)?; - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; - let count = tokens[*ind].expects_int_lit()?; + let count = tokens[*ind].expects_int_lit()?; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { size: count.0 as usize, v: val }, start, tokens[*ind].get_end_pos()))) - } + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { + size: count.0 as usize, + v: val, + }, + start, + tokens[*ind].get_end_pos(), + ))); + } - let mut vals = vec![]; + let mut vals = vec![]; - loop { - let val = parse_ast_value(tokens, ind)?; + loop { + let val = parse_ast_value(tokens, ind)?; - if tokens[*ind].tok_type == LexerTokenType::ArrayClose { - break; - } + if tokens[*ind].tok_type == LexerTokenType::ArrayClose { + break; + } - tokens[*ind].expects(LexerTokenType::Comma)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Comma)?; + *ind += 1; - vals.push(val); - } - - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ArrayVariableInitializerValue { vals }, start, tokens[*ind].get_end_pos()))) + vals.push(val); + } + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ArrayVariableInitializerValue { vals }, + start, + tokens[*ind].get_end_pos(), + ))); } -pub fn parse_ast_pointer(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_ast_pointer( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - tokens[*ind].expects(LexerTokenType::Asterisk)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Asterisk)?; + *ind += 1; - let value = parse_ast_value(tokens, ind)?; + let value = parse_ast_value(tokens, ind)?; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::PointerGrab(value), start, tokens[*ind].get_end_pos()))) + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::PointerGrab(value), + start, + tokens[*ind].get_end_pos(), + ))); } -pub fn parse_ast_reference(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_ast_reference( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - tokens[*ind].expects(LexerTokenType::Ampersand)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::Ampersand)?; + *ind += 1; - let value = parse_ast_value(tokens, ind)?; + let value = parse_ast_value(tokens, ind)?; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ReferenceGrab(value), start, tokens[*ind].get_end_pos()))) -} \ No newline at end of file + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::ReferenceGrab(value), + start, + tokens[*ind].get_end_pos(), + ))); +} diff --git a/compiler/ast_parser/src/variables/decl.rs b/compiler/ast_parser/src/variables/decl.rs index bc40d37..827ee26 100644 --- a/compiler/ast_parser/src/variables/decl.rs +++ b/compiler/ast_parser/src/variables/decl.rs @@ -1,33 +1,44 @@ +use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use compiler_utils::hash::{HashedString}; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use crate::{types::parse_type, value::parse_ast_value}; -pub fn parse_variable_declaration(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start= tokens[*ind].pos.clone(); +pub fn parse_variable_declaration( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let t = parse_type(tokens, ind)?; + let t = parse_type(tokens, ind)?; - let var_name = tokens[*ind].expects_keyword()?; + let var_name = tokens[*ind].expects_keyword()?; - *ind += 1; + *ind += 1; - let mut val: Option> = None; - let end; + let mut val: Option> = None; + let end; - if tokens[*ind].tok_type == LexerTokenType::EqualSign { - *ind += 1; - - val = Some(parse_ast_value(tokens, ind)?); - end = val.as_ref().unwrap().end.clone(); - } else { - end = tokens[*ind - 1].get_end_pos().clone(); - } + if tokens[*ind].tok_type == LexerTokenType::EqualSign { + *ind += 1; - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::VarDeclaration { var_name: HashedString::new(var_name.0), var_type: t, value: val }, start, end))); -} \ No newline at end of file + val = Some(parse_ast_value(tokens, ind)?); + end = val.as_ref().unwrap().end.clone(); + } else { + end = tokens[*ind - 1].get_end_pos().clone(); + } + + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::VarDeclaration { + var_name: HashedString::new(var_name.0), + var_type: t, + value: val, + }, + start, + end, + ))); +} diff --git a/compiler/ast_parser/src/variables/mod.rs b/compiler/ast_parser/src/variables/mod.rs index 3575f29..0e5b696 100644 --- a/compiler/ast_parser/src/variables/mod.rs +++ b/compiler/ast_parser/src/variables/mod.rs @@ -1,4 +1,4 @@ //! AST parsing for variable related elements (variable declarations, modifications, ...) pub mod decl; -pub mod static_decl; \ No newline at end of file +pub mod static_decl; diff --git a/compiler/ast_parser/src/variables/static_decl.rs b/compiler/ast_parser/src/variables/static_decl.rs index 1956625..2990d01 100644 --- a/compiler/ast_parser/src/variables/static_decl.rs +++ b/compiler/ast_parser/src/variables/static_decl.rs @@ -1,27 +1,38 @@ +use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; use lexer::token::{LexerToken, LexerTokenType}; -use compiler_utils::hash::{HashedString}; -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use crate::{types::parse_type, value::parse_ast_value}; -pub fn parse_static_variable_declaration(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { - let start = tokens[*ind].pos.clone(); +pub fn parse_static_variable_declaration( + tokens: &Vec, + ind: &mut usize, +) -> DiagnosticResult> { + let start = tokens[*ind].pos.clone(); - *ind += 1; + *ind += 1; - let var_type = parse_type(tokens, ind)?; - *ind += 1; + let var_type = parse_type(tokens, ind)?; + *ind += 1; - let var_name = tokens[*ind].expects_keyword()?; - *ind += 1; + let var_name = tokens[*ind].expects_keyword()?; + *ind += 1; - tokens[*ind].expects(LexerTokenType::EqualSign)?; - *ind += 1; + tokens[*ind].expects(LexerTokenType::EqualSign)?; + *ind += 1; - let val = parse_ast_value(tokens, ind)?; - let end = val.end.clone(); + let val = parse_ast_value(tokens, ind)?; + let end = val.end.clone(); - return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StaticVariableDeclaration { name: HashedString::new(var_name.0), val, var_type }, start, end))) + return Ok(Box::new(ASTTreeNode::new( + ASTTreeNodeKind::StaticVariableDeclaration { + name: HashedString::new(var_name.0), + val, + var_type, + }, + start, + end, + ))); } diff --git a/compiler/astoir/src/lib.rs b/compiler/astoir/src/lib.rs index 17ecdcc..ef4b676 100644 --- a/compiler/astoir/src/lib.rs +++ b/compiler/astoir/src/lib.rs @@ -6,17 +6,17 @@ use astoir_mir_lowering::lower_hir; use diagnostics::DiagnosticResult; pub enum IRLevel { - HIR, - MIR, - LLVM + HIR, + MIR, + LLVM, } pub fn run_astoir_hir(ctx: ParserCtx) -> DiagnosticResult { - return lower_ast(ctx); + return lower_ast(ctx); } pub fn run_astoir_mir(ctx: ParserCtx) -> DiagnosticResult { - let hir = run_astoir_hir(ctx)?; + let hir = run_astoir_hir(ctx)?; - return lower_hir(hir); -} \ No newline at end of file + return lower_hir(hir); +} diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index e73b8e0..a8a9635 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -1,277 +1,343 @@ //! The context definitions for the AstoIR HIR layer. -use std::{collections::{HashMap, HashSet}}; +use std::collections::{HashMap, HashSet}; use compiler_typing::{storage::TypeStorage, tree::Type}; use compiler_utils::{hash::SelfHash, utils::indexed::IndexStorage}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_func, make_cannot_find_var, make_doesnt_exist_in_era}}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, + builders::{make_cannot_find_func, make_cannot_find_var, make_doesnt_exist_in_era}, +}; use crate::{nodes::HIRNode, storage::GlobalScopeStorage, structs::HIRStructContainer}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); -/// The function HIR context. Contains a mapping from element name hash to element index and other variable information. +/// The function HIR context. Contains a mapping from element name hash to element index and other variable information. /// Uses a branch based system to contain variables. -/// +/// /// # Resolution system /// First, `hash_to_ind` is used to convert any element (like variable) name into an element index. This element index can then be used to quickly retrieve information. -/// +/// /// `HIRBranchedContext` uses a global system to store every local variable of any branch within the function very simply safely. Every stored variable is a `HRBRanchedVariable` which contains the era from when it was created. /// /// # Indexing system /// The branch index system is fairly simple, as soon as a new branch is parsed, we increment one. This allows for branches inside of another branch to have an index higher than the original branch which is easier for the era system! -/// +/// /// # Era system -/// Every variable has a specific branch period called era in which they are allowed to live in. An era can simply be defined as a branch index. -/// +/// Every variable has a specific branch period called era in which they are allowed to live in. An era can simply be defined as a branch index. +/// /// Every branch index stores an end branch index from when it ends (inside of `ending_eras`). This end branch index will be used to calculate when the era of a variable ends. -/// -/// +/// +/// #[derive(Debug, Clone)] pub struct HIRBranchedContext { - pub hash_to_ind: HashMap, // TODO: add a layer system to this so you are able to put multiple variables with the same name. - pub ending_eras: HashMap, + pub hash_to_ind: HashMap, // TODO: add a layer system to this so you are able to put multiple variables with the same name. + pub ending_eras: HashMap, - pub variables: Vec, // index is the resolved indec + pub variables: Vec, // index is the resolved indec - pub current_branch: usize, - pub current_element_index: usize, + pub current_branch: usize, + pub current_element_index: usize, } impl HIRBranchedContext { - pub fn new() -> Self { - HIRBranchedContext { hash_to_ind: HashMap::new(), ending_eras: HashMap::new(), variables: Vec::new(), current_branch: 0, current_element_index: 0 } - } - - /// Starts a new branch by incrementing the `current_branch` by one. Returns the newly started branch's index - pub fn start_branch(&mut self) -> usize { - self.current_branch += 1; - return self.current_branch; - } - - /// Moves to the given branch index. This is unsafe and will not handle anything, should ONLY be used AFTER AST lowering - pub fn move_branch(&mut self, branch: usize) { - self.current_branch = branch; - } - - /// Ends the branch with the given branch index. Must use `start_branch` to start a new branch after. - pub fn end_branch(&mut self, branch: usize) -> usize { - self.ending_eras.insert(branch, self.current_branch); - - return self.current_branch; - } - - /// Introduces a new variable in the next branch era - pub fn introduce_variable_next_era(&mut self, hash: u64, t: Type, has_default: bool) -> Result { - let identity = SelfHash { hash }; - - if self.hash_to_ind.contains_key(&identity) { - return Err(()); - } - - let mut var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch + 1, variable_type: t, has_default, introduced_values: HashSet::new(), requires_address: false, mutation_count: 0, usage_count: 0 }; - - if has_default { - var.mutation_count += 1; - } - - self.variables.push(var); - - let ind: usize = self.current_element_index; - self.current_element_index += 1; - - self.hash_to_ind.insert(identity, ind); - - return Ok(ind); - } - - /// Introduces a new variable in the current branch era. - pub fn introduce_variable(&mut self, hash: u64, t: Type, has_default: bool) -> Result { - let identity = SelfHash { hash }; - - if self.hash_to_ind.contains_key(&identity) { - return Err(()); - } - - let mut var: HIRBranchedVariable = HIRBranchedVariable { introduced_in_era: self.current_branch, variable_type: t, has_default, introduced_values: HashSet::new(), requires_address: false, mutation_count: 0, usage_count: 0}; - - if has_default { - var.mutation_count += 1; - } + pub fn new() -> Self { + HIRBranchedContext { + hash_to_ind: HashMap::new(), + ending_eras: HashMap::new(), + variables: Vec::new(), + current_branch: 0, + current_element_index: 0, + } + } + + /// Starts a new branch by incrementing the `current_branch` by one. Returns the newly started branch's index + pub fn start_branch(&mut self) -> usize { + self.current_branch += 1; + return self.current_branch; + } + + /// Moves to the given branch index. This is unsafe and will not handle anything, should ONLY be used AFTER AST lowering + pub fn move_branch(&mut self, branch: usize) { + self.current_branch = branch; + } + + /// Ends the branch with the given branch index. Must use `start_branch` to start a new branch after. + pub fn end_branch(&mut self, branch: usize) -> usize { + self.ending_eras.insert(branch, self.current_branch); + + return self.current_branch; + } + + /// Introduces a new variable in the next branch era + pub fn introduce_variable_next_era( + &mut self, + hash: u64, + t: Type, + has_default: bool, + ) -> Result { + let identity = SelfHash { hash }; + + if self.hash_to_ind.contains_key(&identity) { + return Err(()); + } + + let mut var: HIRBranchedVariable = HIRBranchedVariable { + introduced_in_era: self.current_branch + 1, + variable_type: t, + has_default, + introduced_values: HashSet::new(), + requires_address: false, + mutation_count: 0, + usage_count: 0, + }; + + if has_default { + var.mutation_count += 1; + } + + self.variables.push(var); + + let ind: usize = self.current_element_index; + self.current_element_index += 1; + + self.hash_to_ind.insert(identity, ind); + + return Ok(ind); + } + + /// Introduces a new variable in the current branch era. + pub fn introduce_variable( + &mut self, + hash: u64, + t: Type, + has_default: bool, + ) -> Result { + let identity = SelfHash { hash }; + + if self.hash_to_ind.contains_key(&identity) { + return Err(()); + } + + let mut var: HIRBranchedVariable = HIRBranchedVariable { + introduced_in_era: self.current_branch, + variable_type: t, + has_default, + introduced_values: HashSet::new(), + requires_address: false, + mutation_count: 0, + usage_count: 0, + }; + + if has_default { + var.mutation_count += 1; + } + + self.variables.push(var); + + let ind: usize = self.current_element_index; + self.current_element_index += 1; + + self.hash_to_ind.insert(identity, ind); + + return Ok(ind); + } + + pub fn introduce_variable_assign(&mut self, ind: usize) -> bool { + let var = &mut self.variables[ind]; + + var.mutation_count += 1; + + if var.has_default { + return true; + } + + var.introduced_values.insert(self.current_branch); + + return true; + } + + pub fn introduce_variable_refer(&mut self, ind: usize) -> bool { + let var = &mut self.variables[ind]; + + var.requires_address = true; - self.variables.push(var); + 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; + + if start_branch > self.current_element_index { + return false; + } + + return self.is_era_alive(start_branch); + } - let ind: usize = self.current_element_index; - self.current_element_index += 1; + 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; + } - self.hash_to_ind.insert(identity, ind); + return false; + } - return Ok(ind); - } + pub fn is_dropped_before(&self, ind: usize) -> bool { + let start_branch: usize = self.variables[ind].introduced_in_era; - pub fn introduce_variable_assign(&mut self, ind: usize) -> bool { - let var = &mut self.variables[ind]; + if !self.ending_eras.contains_key(&start_branch) { + return false; + } - var.mutation_count += 1; + return self.ending_eras[&start_branch] < self.current_branch; + } - if var.has_default { - return true; - } + pub fn has_variable_value(&self, ind: usize) -> bool { + let var = &self.variables[ind]; - var.introduced_values.insert(self.current_branch); + if var.has_default { + return true; + } - return true; - } + for era in var.introduced_values.iter() { + if self.is_era_alive(*era) { + return true; + } + } - pub fn introduce_variable_refer(&mut self, ind: usize) -> bool { - let var = &mut self.variables[ind]; + return false; + } - var.requires_address = true; + pub fn get_ending_era(&self, ind: usize) -> usize { + return self.ending_eras[&self.variables[ind].introduced_in_era]; + } - return true; - } + /// Obtains the variable index from the hash if it's available, otherwise returns an error explaining why it failed + pub fn obtain( + &mut self, + hash: u64, + origin: &K, + ) -> DiagnosticResult { + let identity = SelfHash { hash }; - /// 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; + match self.hash_to_ind.get(&identity) { + None => return Err(make_cannot_find_var(origin, &hash).into()), + Some(ind) => { + let ind = *ind; - if start_branch > self.current_element_index { - return false; - } + if !self.is_alive(ind) { + if self.is_dropped_before(ind) { + return Err(make_doesnt_exist_in_era(origin, &hash).into()); + } - return self.is_era_alive(start_branch); - } + panic!("Dropped unalived variable") + } - 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; - } + self.variables[ind].usage_count += 1; - return false; - } + return Ok(ind); + } + } + } - pub fn is_dropped_before(&self, ind: usize) -> bool { - let start_branch: usize = self.variables[ind].introduced_in_era; + pub fn is_eligible_for_ssa(&self, ind: usize) -> bool { + let var = &self.variables[ind]; - if !self.ending_eras.contains_key(&start_branch) { - return false; - } - - 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]; - } - - /// Obtains the variable index from the hash if it's available, otherwise returns an error explaining why it failed - pub fn obtain(&mut self, hash: u64, origin: &K) -> DiagnosticResult { - let identity = SelfHash { hash }; - - match self.hash_to_ind.get(&identity) { - None => return Err(make_cannot_find_var(origin, &hash).into()), - Some(ind) => { - let ind = *ind; - - if !self.is_alive(ind) { - if self.is_dropped_before(ind) { - return Err(make_doesnt_exist_in_era(origin, &hash).into()) - } - - panic!("Dropped unalived variable") - } - - self.variables[ind].usage_count += 1; - - return Ok(ind) - } - } - } - - pub fn is_eligible_for_ssa(&self, ind: usize) -> bool { - let var = &self.variables[ind]; - - return !var.requires_address && var.mutation_count <= 1 && !var.variable_type.can_use_index_access() && false - } - + return !var.requires_address + && var.mutation_count <= 1 + && !var.variable_type.can_use_index_access() + && false; + } } #[derive(Debug, Clone)] pub struct HIRBranchedVariable { - pub introduced_in_era: usize, - pub variable_type: Type, + pub introduced_in_era: usize, + pub variable_type: Type, - pub usage_count: usize, + pub usage_count: usize, - pub requires_address: bool, + pub requires_address: bool, - /// The amount of times the variable has been changed - pub mutation_count: usize, + /// The amount of times the variable has been changed + pub mutation_count: usize, - pub has_default: bool, - pub introduced_values: HashSet // TODO: try to potentially reduce this + pub has_default: bool, + pub introduced_values: HashSet, // TODO: try to potentially reduce this } #[derive(Debug)] pub struct HIRContext { - pub functions: IndexStorage, - pub function_declarations: Vec>>, - pub function_contexts: Vec>, - pub static_variables: IndexStorage, - pub struct_func_impls: HashMap, - pub type_storage: TypeStorage, - pub global_scope: GlobalScopeStorage + pub functions: IndexStorage, + pub function_declarations: Vec>>, + pub function_contexts: Vec>, + pub static_variables: IndexStorage, + pub struct_func_impls: HashMap, + pub type_storage: TypeStorage, + pub global_scope: GlobalScopeStorage, } #[derive(PartialEq)] pub enum VariableKind { - STATIC, - LOCAL + STATIC, + LOCAL, } impl HIRContext { - pub fn new() -> Self { - return HIRContext { functions: IndexStorage::new(), static_variables: IndexStorage::new(), type_storage: TypeStorage::new().unwrap(), function_contexts: vec![], function_declarations: vec![], struct_func_impls: HashMap::new(), global_scope: GlobalScopeStorage::new() } - } - - pub fn translate_function(&self, func_hash: u64, origin: &K) -> DiagnosticResult { - return match self.functions.get_index(func_hash) { - Some(v) => Ok(v), - None => return Err(make_cannot_find_func(origin, &func_hash).into()) - } - } + pub fn new() -> Self { + return HIRContext { + functions: IndexStorage::new(), + static_variables: IndexStorage::new(), + type_storage: TypeStorage::new().unwrap(), + function_contexts: vec![], + function_declarations: vec![], + struct_func_impls: HashMap::new(), + global_scope: GlobalScopeStorage::new(), + }; + } + + pub fn translate_function( + &self, + func_hash: u64, + origin: &K, + ) -> DiagnosticResult { + return match self.functions.get_index(func_hash) { + Some(v) => Ok(v), + None => return Err(make_cannot_find_func(origin, &func_hash).into()), + }; + } } -pub fn get_variable(context: &HIRContext, curr_ctx: &mut HIRBranchedContext, hash: u64, origin: &K) -> DiagnosticResult<(VariableKind, Type, usize)> { - if curr_ctx.hash_to_ind.contains_key(&SelfHash { hash }) { - let ind = curr_ctx.obtain(hash, origin)?; - - return Ok((VariableKind::LOCAL, curr_ctx.variables[ind].variable_type.clone(), ind)); - } - - match context.static_variables.get_index(hash) { - Some(v) => { - return Ok((VariableKind::STATIC, context.static_variables.vals[v].clone(), v)) - }, - - None => return Err(make_cannot_find_var(origin, &hash).into()) - }; -} \ No newline at end of file +pub fn get_variable( + context: &HIRContext, + curr_ctx: &mut HIRBranchedContext, + hash: u64, + origin: &K, +) -> DiagnosticResult<(VariableKind, Type, usize)> { + if curr_ctx.hash_to_ind.contains_key(&SelfHash { hash }) { + let ind = curr_ctx.obtain(hash, origin)?; + + return Ok(( + VariableKind::LOCAL, + curr_ctx.variables[ind].variable_type.clone(), + ind, + )); + } + + match context.static_variables.get_index(hash) { + Some(v) => { + return Ok(( + VariableKind::STATIC, + context.static_variables.vals[v].clone(), + v, + )); + } + + None => return Err(make_cannot_find_var(origin, &hash).into()), + }; +} diff --git a/compiler/astoir_hir/src/lib.rs b/compiler/astoir_hir/src/lib.rs index eccf903..47ac86a 100644 --- a/compiler/astoir_hir/src/lib.rs +++ b/compiler/astoir_hir/src/lib.rs @@ -1,8 +1,8 @@ -//! The HIR layer of the AstoIR. +//! The HIR layer of the AstoIR. //! The HIR layer represents a near AST where elements are resolved instead of raw name hashes, enforcing that the code works in theory. pub mod ctx; pub mod nodes; -pub mod structs; pub mod resolve; -pub mod storage; \ No newline at end of file +pub mod storage; +pub mod structs; diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index 9de521c..5e17f87 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -1,269 +1,501 @@ -//! The nodes inside of the AstoIR HIR. +//! The nodes inside of the AstoIR HIR. use std::collections::HashMap; -use compiler_typing::{enums::{RawEnumTypeContainer}, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type}; -use compiler_utils::{Position, hash::SelfHash, operators::{ComparingOperator, MathOperator}}; -use diagnostics::{DiagnosticSpanOrigin, builders::{make_diff_type, make_diff_type_val}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic}; - -use crate::{ctx::{HIRBranchedContext, HIRContext}, resolve::resolve_to_type, structs::{HIRIfBranch, StructLRUStep}}; +use compiler_typing::{ + enums::RawEnumTypeContainer, raw::RawType, references::TypeReference, + structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type, +}; +use compiler_utils::{ + Position, + hash::SelfHash, + operators::{ComparingOperator, MathOperator}, +}; +use diagnostics::{ + DiagnosticSpanOrigin, + builders::{make_diff_type, make_diff_type_val}, + diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, + unsure_panic, +}; + +use crate::{ + ctx::{HIRBranchedContext, HIRContext}, + resolve::resolve_to_type, + structs::{HIRIfBranch, StructLRUStep}, +}; #[derive(Debug, Clone)] -pub struct HIRNode { - pub kind: HIRNodeKind, - pub start: Position, - pub end: Position +pub struct HIRNode { + pub kind: HIRNodeKind, + pub start: Position, + pub end: Position, } impl HIRNode { - pub fn new(kind: HIRNodeKind, start: &Position, end: &Position) -> Self { - HIRNode { kind, start: start.clone(), end: end.clone() } - } - - pub fn with(&self, kind: HIRNodeKind) -> Self { - HIRNode { kind, start: self.start.clone(), end: self.end.clone() } - } + pub fn new(kind: HIRNodeKind, start: &Position, end: &Position) -> Self { + HIRNode { + kind, + start: start.clone(), + end: end.clone(), + } + } + + pub fn with(&self, kind: HIRNodeKind) -> Self { + HIRNode { + kind, + start: self.start.clone(), + end: self.end.clone(), + } + } } impl DiagnosticSpanOrigin for HIRNode { - fn make_simple_diagnostic(&self, code: usize, level: diagnostics::diagnostic::Level, message: String, primary_span_msg: Option, spans: Vec, notes: Vec, help: Vec) -> Diagnostic { - let span = self.make_span(SpanKind::Primary, primary_span_msg); - - Diagnostic::new_base(level, code, message, span, spans, notes, help) - } - - fn get_pos(&self) -> SpanPosition { - SpanPosition::from_pos2(self.start.clone(), self.end.clone()) - } - - fn make_span(&self, kind: SpanKind, msg: Option) -> Span { - Span { start: SpanPosition::from_pos2(self.start.clone(), self.end.clone()), label: msg, kind } - } + fn make_simple_diagnostic( + &self, + code: usize, + level: diagnostics::diagnostic::Level, + message: String, + primary_span_msg: Option, + spans: Vec, + notes: Vec, + help: Vec, + ) -> Diagnostic { + let span = self.make_span(SpanKind::Primary, primary_span_msg); + + Diagnostic::new_base(level, code, message, span, spans, notes, help) + } + + fn get_pos(&self) -> SpanPosition { + SpanPosition::from_pos2(self.start.clone(), self.end.clone()) + } + + fn make_span(&self, kind: SpanKind, msg: Option) -> Span { + Span { + start: SpanPosition::from_pos2(self.start.clone(), self.end.clone()), + label: msg, + kind, + } + } } #[derive(Debug, Clone)] pub enum HIRNodeKind { - CastValue { intentional: bool, value: Box, old_type: Type, new_type: Type }, - - VarDeclaration { variable: usize, var_type: Type, default_val: Option> }, - StaticVariableDeclaration { variable: usize, var_type: Type, default_val: Option> }, - - VarAssigment { variable: usize, val: Box }, - - MathOperation { left: Box, right: Box, operation: MathOperator }, - - UnwrapCondition { original: Box, new_type: Type, new_var: Option, unsafe_unwrap: bool }, - UnwrapValue { original: Box, new_type: Type, unsafe_unwrap: bool }, - - VariableReference { index: usize, is_static: bool }, - FunctionReference { index: usize }, - - PointerGrab { val: Box }, - ReferenceGrab { val: Box }, - - StructLRU { steps: Vec, last: Type }, - - EnumParentCast { val: Box, parent: Type }, - - EnumDeclaration { type_name: usize, container: RawEnumTypeContainer }, - - StructDeclaration { type_name: usize, container: RawStructTypeContainer, layout: bool }, - StructFunctionDeclaration { func_name: usize, arguments: Vec<(u64, TypeReference)>, return_type: Option, body: Vec>, ctx: HIRBranchedContext, requires_this: bool }, - - ArrayVariableInitializerValue { vals: Vec> }, - ArrayVariableInitializerValueSameValue { size: usize, val: Box }, - - ArrayIndexAccess { val: Box, index: Box }, - ArrayIndexModify { array: Box, index: Box, new_val : Box }, - - /// Before transmutation - StructInitializer { fields: HashMap> }, - StructInitializerTyped { t: Type, fields: Vec> }, - - FunctionDeclaration { func_name: usize, arguments: Vec<(u64, Type)>, return_type: Option, body: Vec>, ctx: HIRBranchedContext, requires_this: bool }, - - ShadowFunctionDeclaration { func_name: usize, arguments: Vec<(u64, Type)>, return_type: Option }, - - FunctionCall { func_name: usize, arguments: Vec> }, - - WhileBlock { condition: Box, body: Vec> }, - ForBlock { initial_state: Box, condition: Box, incrementation: Box, body: Vec> }, - - IfStatement { branches: Vec }, - - ReturnStatement { value: Option> }, - - IntegerLiteral { value: i128, int_type: Type }, - StringLiteral { value: String }, - - BooleanOperator { left: Box, right: Box, operator: ComparingOperator }, - BooleanCondition { value: Box, negation: bool } + CastValue { + intentional: bool, + value: Box, + old_type: Type, + new_type: Type, + }, + + VarDeclaration { + variable: usize, + var_type: Type, + default_val: Option>, + }, + StaticVariableDeclaration { + variable: usize, + var_type: Type, + default_val: Option>, + }, + + VarAssigment { + variable: usize, + val: Box, + }, + + MathOperation { + left: Box, + right: Box, + operation: MathOperator, + }, + + UnwrapCondition { + original: Box, + new_type: Type, + new_var: Option, + unsafe_unwrap: bool, + }, + UnwrapValue { + original: Box, + new_type: Type, + unsafe_unwrap: bool, + }, + + VariableReference { + index: usize, + is_static: bool, + }, + FunctionReference { + index: usize, + }, + + PointerGrab { + val: Box, + }, + ReferenceGrab { + val: Box, + }, + + StructLRU { + steps: Vec, + last: Type, + }, + + EnumParentCast { + val: Box, + parent: Type, + }, + + EnumDeclaration { + type_name: usize, + container: RawEnumTypeContainer, + }, + + StructDeclaration { + type_name: usize, + container: RawStructTypeContainer, + layout: bool, + }, + StructFunctionDeclaration { + func_name: usize, + arguments: Vec<(u64, TypeReference)>, + return_type: Option, + body: Vec>, + ctx: HIRBranchedContext, + requires_this: bool, + }, + + ArrayVariableInitializerValue { + vals: Vec>, + }, + ArrayVariableInitializerValueSameValue { + size: usize, + val: Box, + }, + + ArrayIndexAccess { + val: Box, + index: Box, + }, + ArrayIndexModify { + array: Box, + index: Box, + new_val: Box, + }, + + /// Before transmutation + StructInitializer { + fields: HashMap>, + }, + StructInitializerTyped { + t: Type, + fields: Vec>, + }, + + FunctionDeclaration { + func_name: usize, + arguments: Vec<(u64, Type)>, + return_type: Option, + body: Vec>, + ctx: HIRBranchedContext, + requires_this: bool, + }, + + ShadowFunctionDeclaration { + func_name: usize, + arguments: Vec<(u64, Type)>, + return_type: Option, + }, + + FunctionCall { + func_name: usize, + arguments: Vec>, + }, + + WhileBlock { + condition: Box, + body: Vec>, + }, + ForBlock { + initial_state: Box, + condition: Box, + incrementation: Box, + body: Vec>, + }, + + IfStatement { + branches: Vec, + }, + + ReturnStatement { + value: Option>, + }, + + IntegerLiteral { + value: i128, + int_type: Type, + }, + StringLiteral { + value: String, + }, + + BooleanOperator { + left: Box, + right: Box, + operator: ComparingOperator, + }, + BooleanCondition { + value: Box, + negation: bool, + }, } impl HIRNode { - pub fn is_variable_reference(&self) -> bool { - if let HIRNodeKind::VariableReference { .. } = self.kind { - return true; - } - - return false; - } - - pub fn get_variable_represent(&self) -> (usize, bool) { - match &self.kind { - HIRNodeKind::VariableReference { index, is_static} => return (*index, *is_static), - HIRNodeKind::ArrayIndexAccess { val, index: _ } => return val.get_variable_represent(), - - _ => unsure_panic!("Used get_variable_represent on a non representing val") - }; - } - - pub fn is_variable_representative(&self) -> bool { - if let HIRNodeKind::ArrayIndexAccess { .. } = self.kind { - return true; - } - - if let HIRNodeKind::VariableReference { .. } = self.kind { - return true; - } - - return false; - } - - pub fn as_variable_reference(&self) -> (usize, bool) { - if let HIRNodeKind::VariableReference { index, is_static } = &self.kind { - return (*index, *is_static) - } - - panic!("Tried using as_variable_reference on a non var ref") - } - - pub fn use_as(&self, context: &HIRContext, curr_ctx: &HIRBranchedContext, t: Type, origin: &K, var_origin: Option<&K>) -> Result { - if self.is_intederminately_typed() { - return Ok(resolve_to_type(Box::new(self.clone()), t.clone(), context, curr_ctx, origin)?.use_as(context, curr_ctx, t, origin, var_origin)?); - } - - let self_type = match self.get_node_type(context, curr_ctx) { - Some(v) => v, - _ => panic!("Tried using a typeless node in use_as: {:#?}", self) - }; - - if self_type == t { - return Ok(self.clone()); - } - - if self_type.can_transmute(&t, &context.type_storage) { - match &self.kind { - HIRNodeKind::IntegerLiteral { value, int_type: _ } => { - return Ok(self.with(HIRNodeKind::IntegerLiteral { value: *value, int_type: t })); - }, - - HIRNodeKind::ArrayVariableInitializerValue { vals } => { - if can_transmute_inner(&self_type, &t, &context.type_storage) { - let mut new_vals = vec![]; - let inner = t.get_inner_type(); - - for val in vals { - new_vals.push(Box::new(val.use_as(context, curr_ctx, *inner.clone(), origin, var_origin)?)); - } - - return Ok(self.with(HIRNodeKind::ArrayVariableInitializerValue { vals: new_vals })) - } - }, - - HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { - if can_transmute_inner(&self_type, &t, &context.type_storage) { - let new_val = Box::new(val.use_as(context, curr_ctx, *t.get_inner_type(), origin, var_origin)?); - - return Ok(self.with(HIRNodeKind::ArrayVariableInitializerValueSameValue { size: *size, val: new_val })) - } - }, - - _ => { - return Ok(self.with(HIRNodeKind::CastValue { intentional: false, old_type: self_type.clone(), value: Box::new(self.clone()), new_type: t })); - } - } - } - - if let Some(v) = var_origin { - return Err(make_diff_type(origin, &"unnamed".to_string(), &t.faulty_lowering_generic(&context.type_storage), &self.get_node_type(context, curr_ctx).unwrap().faulty_lowering_generic(&context.type_storage), v).into()) - } - - return Err(make_diff_type_val(origin, &t.faulty_lowering_generic(&context.type_storage), &self.get_node_type(context, curr_ctx).unwrap().faulty_lowering_generic(&context.type_storage)).into()) - } - - pub fn is_intederminately_typed(&self) -> bool { - match self.kind { - HIRNodeKind::StructInitializer { .. } => true, - - _ => false - } - } - - pub fn get_node_type(&self, context: &HIRContext, curr_ctx: &HIRBranchedContext) -> Option { - match &self.kind { - HIRNodeKind::VariableReference { index, is_static } => { - if *is_static { - return Some(context.static_variables.vals[*index].clone()); - } - - return Some(curr_ctx.variables[*index].variable_type.clone()); - }, - - HIRNodeKind::PointerGrab { val } => { - return Some(Type::Pointer(false, Box::new(val.get_node_type(context, curr_ctx).unwrap()))); - }, - - HIRNodeKind::ReferenceGrab { val } => { - return Some(Type::Reference(Box::new(val.get_node_type(context, curr_ctx).unwrap()))) - } - - HIRNodeKind::UnwrapCondition { .. } => { - return Some(Type::Generic(RawType::Boolean, vec![], vec![])) - }, - - HIRNodeKind::UnwrapValue { original: _, new_type, unsafe_unwrap: _ } => { - return Some(new_type.clone()) - }, - - HIRNodeKind::ArrayIndexAccess { val, index: _ } => { - let t = val.get_node_type(context, curr_ctx).unwrap(); - - return Some(*t.get_inner_type()) - } - - HIRNodeKind::IntegerLiteral { value: _, int_type } => { - return Some(int_type.clone()); - }, - - HIRNodeKind::StringLiteral { value: _ } => { - return Some(Type::Generic(RawType::StaticString, vec![], vec![])) - }, - - HIRNodeKind::ArrayVariableInitializerValue { vals } => return Some(Type::Array(vals.len(), Box::new(vals[0].get_node_type(context, curr_ctx).unwrap()))), - HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => return Some(Type::Array(*size, Box::new(val.get_node_type(context, curr_ctx).unwrap()))), - - HIRNodeKind::StructLRU { steps: _, last } => { - return Some(last.clone()) - }, - - HIRNodeKind::MathOperation { left, right: _, operation: _ } => { - return left.get_node_type(context, curr_ctx) - }, - - HIRNodeKind::BooleanOperator { .. } | HIRNodeKind::BooleanCondition { .. } => { - return Some(Type::Generic(RawType::Boolean, vec![], vec![])) - }, - - HIRNodeKind::StructInitializerTyped { t, fields: _ } => Some(t.clone()), - - HIRNodeKind::FunctionCall { func_name, arguments: _ } => { - let f = context.functions.vals[*func_name].0.clone(); - - return f; - }, - - _ => return None - } - } -} \ No newline at end of file + pub fn is_variable_reference(&self) -> bool { + if let HIRNodeKind::VariableReference { .. } = self.kind { + return true; + } + + return false; + } + + pub fn get_variable_represent(&self) -> (usize, bool) { + match &self.kind { + HIRNodeKind::VariableReference { index, is_static } => return (*index, *is_static), + HIRNodeKind::ArrayIndexAccess { val, index: _ } => return val.get_variable_represent(), + + _ => unsure_panic!("Used get_variable_represent on a non representing val"), + }; + } + + pub fn is_variable_representative(&self) -> bool { + if let HIRNodeKind::ArrayIndexAccess { .. } = self.kind { + return true; + } + + if let HIRNodeKind::VariableReference { .. } = self.kind { + return true; + } + + return false; + } + + pub fn as_variable_reference(&self) -> (usize, bool) { + if let HIRNodeKind::VariableReference { index, is_static } = &self.kind { + return (*index, *is_static); + } + + panic!("Tried using as_variable_reference on a non var ref") + } + + pub fn use_as( + &self, + context: &HIRContext, + curr_ctx: &HIRBranchedContext, + t: Type, + origin: &K, + var_origin: Option<&K>, + ) -> Result { + if self.is_intederminately_typed() { + return Ok(resolve_to_type( + Box::new(self.clone()), + t.clone(), + context, + curr_ctx, + origin, + )? + .use_as(context, curr_ctx, t, origin, var_origin)?); + } + + let self_type = match self.get_node_type(context, curr_ctx) { + Some(v) => v, + _ => panic!("Tried using a typeless node in use_as: {:#?}", self), + }; + + if self_type == t { + return Ok(self.clone()); + } + + if self_type.can_transmute(&t, &context.type_storage) { + match &self.kind { + HIRNodeKind::IntegerLiteral { value, int_type: _ } => { + return Ok(self.with(HIRNodeKind::IntegerLiteral { + value: *value, + int_type: t, + })); + } + + HIRNodeKind::ArrayVariableInitializerValue { vals } => { + if can_transmute_inner(&self_type, &t, &context.type_storage) { + let mut new_vals = vec![]; + let inner = t.get_inner_type(); + + for val in vals { + new_vals.push(Box::new(val.use_as( + context, + curr_ctx, + *inner.clone(), + origin, + var_origin, + )?)); + } + + return Ok(self + .with(HIRNodeKind::ArrayVariableInitializerValue { vals: new_vals })); + } + } + + HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { + if can_transmute_inner(&self_type, &t, &context.type_storage) { + let new_val = Box::new(val.use_as( + context, + curr_ctx, + *t.get_inner_type(), + origin, + var_origin, + )?); + + return Ok( + self.with(HIRNodeKind::ArrayVariableInitializerValueSameValue { + size: *size, + val: new_val, + }), + ); + } + } + + _ => { + return Ok(self.with(HIRNodeKind::CastValue { + intentional: false, + old_type: self_type.clone(), + value: Box::new(self.clone()), + new_type: t, + })); + } + } + } + + if let Some(v) = var_origin { + return Err(make_diff_type( + origin, + &"unnamed".to_string(), + &t.faulty_lowering_generic(&context.type_storage), + &self + .get_node_type(context, curr_ctx) + .unwrap() + .faulty_lowering_generic(&context.type_storage), + v, + ) + .into()); + } + + return Err(make_diff_type_val( + origin, + &t.faulty_lowering_generic(&context.type_storage), + &self + .get_node_type(context, curr_ctx) + .unwrap() + .faulty_lowering_generic(&context.type_storage), + ) + .into()); + } + + pub fn is_intederminately_typed(&self) -> bool { + match self.kind { + HIRNodeKind::StructInitializer { .. } => true, + + _ => false, + } + } + + pub fn get_node_type( + &self, + context: &HIRContext, + curr_ctx: &HIRBranchedContext, + ) -> Option { + match &self.kind { + HIRNodeKind::VariableReference { index, is_static } => { + if *is_static { + return Some(context.static_variables.vals[*index].clone()); + } + + return Some(curr_ctx.variables[*index].variable_type.clone()); + } + + HIRNodeKind::PointerGrab { val } => { + return Some(Type::Pointer( + false, + Box::new(val.get_node_type(context, curr_ctx).unwrap()), + )); + } + + HIRNodeKind::ReferenceGrab { val } => { + return Some(Type::Reference(Box::new( + val.get_node_type(context, curr_ctx).unwrap(), + ))); + } + + HIRNodeKind::UnwrapCondition { .. } => { + return Some(Type::Generic(RawType::Boolean, vec![], vec![])); + } + + HIRNodeKind::UnwrapValue { + original: _, + new_type, + unsafe_unwrap: _, + } => return Some(new_type.clone()), + + HIRNodeKind::ArrayIndexAccess { val, index: _ } => { + let t = val.get_node_type(context, curr_ctx).unwrap(); + + return Some(*t.get_inner_type()); + } + + HIRNodeKind::IntegerLiteral { value: _, int_type } => { + return Some(int_type.clone()); + } + + HIRNodeKind::StringLiteral { value: _ } => { + return Some(Type::Generic(RawType::StaticString, vec![], vec![])); + } + + HIRNodeKind::ArrayVariableInitializerValue { vals } => { + return Some(Type::Array( + vals.len(), + Box::new(vals[0].get_node_type(context, curr_ctx).unwrap()), + )); + } + HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { + return Some(Type::Array( + *size, + Box::new(val.get_node_type(context, curr_ctx).unwrap()), + )); + } + + HIRNodeKind::StructLRU { steps: _, last } => return Some(last.clone()), + + HIRNodeKind::MathOperation { + left, + right: _, + operation: _, + } => return left.get_node_type(context, curr_ctx), + + HIRNodeKind::BooleanOperator { .. } | HIRNodeKind::BooleanCondition { .. } => { + return Some(Type::Generic(RawType::Boolean, vec![], vec![])); + } + + HIRNodeKind::StructInitializerTyped { t, fields: _ } => Some(t.clone()), + + HIRNodeKind::FunctionCall { + func_name, + arguments: _, + } => { + let f = context.functions.vals[*func_name].0.clone(); + + return f; + } + + _ => return None, + } + } +} diff --git a/compiler/astoir_hir/src/resolve.rs b/compiler/astoir_hir/src/resolve.rs index 607c509..a3cf492 100644 --- a/compiler/astoir_hir/src/resolve.rs +++ b/compiler/astoir_hir/src/resolve.rs @@ -2,40 +2,62 @@ use compiler_typing::tree::Type; use compiler_utils::hash::SelfHash; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_req_type_kind, make_struct_init_missing_field}}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, + builders::{make_req_type_kind, make_struct_init_missing_field}, +}; -use crate::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; +use crate::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; /// Resolves incomplete HIR nodes into complete nodes -pub fn resolve_to_type(node: Box, destination: Type, context: &HIRContext, curr_ctx: &HIRBranchedContext, origin: &K) -> DiagnosticResult> { - match node.kind { - HIRNodeKind::StructInitializer { fields } => { - let generic = destination.as_generic_safe(origin)?; - let mut new_fields = vec![]; - - if !generic.is_field_based() { - return Err(make_req_type_kind(origin, &"field-having".to_string()).into()) - } - - for field in destination.get_fields(&context.type_storage) { - let identity = SelfHash { hash: field }; - - if !fields.contains_key(&identity) { - return Err(make_struct_init_missing_field(origin, &destination, &field).into()) - } - - let val = fields[&identity].clone(); - - let field_data = destination.get_field(&context.type_storage, field)?.1.resolve(&destination); - - let val = Box::new(val.use_as(context, curr_ctx, field_data, origin, None)?); - - new_fields.push(val); - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::StructInitializerTyped { t: destination, fields: new_fields }, &node.start, &node.end))) - }, - - _ => panic!("Invalid node") - } -} \ No newline at end of file +pub fn resolve_to_type( + node: Box, + destination: Type, + context: &HIRContext, + curr_ctx: &HIRBranchedContext, + origin: &K, +) -> DiagnosticResult> { + match node.kind { + HIRNodeKind::StructInitializer { fields } => { + let generic = destination.as_generic_safe(origin)?; + let mut new_fields = vec![]; + + if !generic.is_field_based() { + return Err(make_req_type_kind(origin, &"field-having".to_string()).into()); + } + + for field in destination.get_fields(&context.type_storage) { + let identity = SelfHash { hash: field }; + + if !fields.contains_key(&identity) { + return Err(make_struct_init_missing_field(origin, &destination, &field).into()); + } + + let val = fields[&identity].clone(); + + let field_data = destination + .get_field(&context.type_storage, field)? + .1 + .resolve(&destination); + + let val = Box::new(val.use_as(context, curr_ctx, field_data, origin, None)?); + + new_fields.push(val); + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::StructInitializerTyped { + t: destination, + fields: new_fields, + }, + &node.start, + &node.end, + ))); + } + + _ => panic!("Invalid node"), + } +} diff --git a/compiler/astoir_hir/src/storage.rs b/compiler/astoir_hir/src/storage.rs index e4f8821..e133ee4 100644 --- a/compiler/astoir_hir/src/storage.rs +++ b/compiler/astoir_hir/src/storage.rs @@ -3,7 +3,10 @@ use std::{collections::HashMap, fmt::Display, hash::Hash}; use compiler_typing::{raw::RawType, tree::Type}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, + builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}, +}; use crate::{ctx::HIRFunction, nodes::HIRNode}; @@ -11,175 +14,228 @@ pub type GlobalStorageIdentifier = usize; #[derive(Clone, Debug)] pub enum GlobalStorageEntryType { - Function(HIRFunction, Box), - ImplLessFunction(HIRFunction), - StaticVariable(Type), + Function(HIRFunction, Box), + ImplLessFunction(HIRFunction), + StaticVariable(Type), - StructFunction(HIRFunction, Box, GlobalStorageIdentifier), - - Type(RawType) + StructFunction(HIRFunction, Box, GlobalStorageIdentifier), + + Type(RawType), } /// Represents a key to a global storage entry. Potentially allows for namespaces later on #[derive(Debug)] pub struct EntryKey { - pub name_hash: u64 + pub name_hash: u64, } impl Hash for EntryKey { - fn hash(&self, state: &mut H) { - state.write_u64(self.name_hash); - } + fn hash(&self, state: &mut H) { + state.write_u64(self.name_hash); + } } impl PartialEq for EntryKey { - fn eq(&self, other: &Self) -> bool { - self.name_hash == other.name_hash - } + fn eq(&self, other: &Self) -> bool { + self.name_hash == other.name_hash + } } impl Eq for EntryKey {} #[derive(Debug)] pub struct GlobalStorageEntry { - pub entry_type: GlobalStorageEntryType, - pub parent_index: usize + pub entry_type: GlobalStorageEntryType, + pub parent_index: usize, } #[derive(Debug)] pub struct GlobalScopeStorage { - pub entry_to_ind: HashMap, - pub entries: Vec, + pub entry_to_ind: HashMap, + pub entries: Vec, } /// The global storage for every element inside of the scope. -/// +/// /// This stores the following: /// - Functions (with or without implementations) /// - Static variables /// - Struct functions /// - Types -/// +/// /// # Safety /// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. impl GlobalScopeStorage { - pub fn new() -> Self { - GlobalScopeStorage { entry_to_ind: HashMap::new(), entries: vec![] } - } - - pub fn append(&mut self, name: EntryKey, entry: GlobalStorageEntryType, origin: &K) -> MaybeDiagnostic { - if self.entry_to_ind.contains_key(&name) { - return Err(make_already_in_scope(origin, &name.name_hash).into()) - } - - let parent_index = self.entries.len(); - - let entry = GlobalStorageEntry { entry_type: entry, parent_index }; - - self.entries.push(entry); - self.entry_to_ind.insert(name, parent_index); - - Ok(()) - } - - pub fn get_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - if !self.entry_to_ind.contains_key(&name) { - return Err(make_cannot_find(origin, &name.name_hash).into()); - } - - return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) - } - - pub fn get_type(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Type(t) => Ok(t.clone()), - _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()) - }; - } - - pub fn get_static_variable(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), - _ => Err(make_expected_simple_error(origin, &"static variable".to_string(), &base).into()) - }; - } - - pub fn get_function_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function(hir, _) => Ok(hir.clone()), - GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), - GlobalStorageEntryType::StructFunction(hir, _, _) => Ok(hir.clone()), - - _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()) - }; - } - - pub fn get_function_impl(&self, name: EntryKey, origin: &K) -> DiagnosticResult> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function(_, i) => Ok(i.clone()), - GlobalStorageEntryType::StructFunction(_, i, _) => Ok(i.clone()), - - _ => Err(make_expected_simple_error(origin, &"function with implementation", &base).into()) - }; - } - - pub fn get_implless_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), - - _ => Err(make_expected_simple_error(origin, &"function without implementation", &base).into()) - } - } - - pub fn get_exact_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(HIRFunction, Box)> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function(hir, i) => Ok((hir.clone(), i.clone())), - - _ => Err(make_expected_simple_error(origin, &"function", &base).into()) - } - } - - pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(HIRFunction, Box, RawType)> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::StructFunction(hir, i, o) => { - if let GlobalStorageEntryType::Type(t) = self.entries[o].entry_type.clone() { - Ok((hir, i, t)) - } else { - Err(make_expected_simple_error(origin, &"type", &self.entries[0].entry_type).into()) - } - }, - - _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()) - } - } + pub fn new() -> Self { + GlobalScopeStorage { + entry_to_ind: HashMap::new(), + entries: vec![], + } + } + + pub fn append( + &mut self, + name: EntryKey, + entry: GlobalStorageEntryType, + origin: &K, + ) -> MaybeDiagnostic { + if self.entry_to_ind.contains_key(&name) { + return Err(make_already_in_scope(origin, &name.name_hash).into()); + } + + let parent_index = self.entries.len(); + + let entry = GlobalStorageEntry { + entry_type: entry, + parent_index, + }; + + self.entries.push(entry); + self.entry_to_ind.insert(name, parent_index); + + Ok(()) + } + + pub fn get_base( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + if !self.entry_to_ind.contains_key(&name) { + return Err(make_cannot_find(origin, &name.name_hash).into()); + } + + return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()); + } + + pub fn get_type( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Type(t) => Ok(t.clone()), + _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()), + }; + } + + pub fn get_static_variable( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), + _ => Err( + make_expected_simple_error(origin, &"static variable".to_string(), &base).into(), + ), + }; + } + + pub fn get_function_base( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(hir, _) => Ok(hir.clone()), + GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + GlobalStorageEntryType::StructFunction(hir, _, _) => Ok(hir.clone()), + + _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()), + }; + } + + pub fn get_function_impl( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(_, i) => Ok(i.clone()), + GlobalStorageEntryType::StructFunction(_, i, _) => Ok(i.clone()), + + _ => Err( + make_expected_simple_error(origin, &"function with implementation", &base).into(), + ), + }; + } + + pub fn get_implless_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), + + _ => Err( + make_expected_simple_error(origin, &"function without implementation", &base) + .into(), + ), + }; + } + + pub fn get_exact_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult<(HIRFunction, Box)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function(hir, i) => Ok((hir.clone(), i.clone())), + + _ => Err(make_expected_simple_error(origin, &"function", &base).into()), + }; + } + + pub fn get_exact_struct_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult<(HIRFunction, Box, RawType)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StructFunction(hir, i, o) => { + if let GlobalStorageEntryType::Type(t) = self.entries[o].entry_type.clone() { + Ok((hir, i, t)) + } else { + Err( + make_expected_simple_error(origin, &"type", &self.entries[0].entry_type) + .into(), + ) + } + } + + _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()), + }; + } } impl Display for GlobalStorageEntryType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Function(_, _) => "function", - Self::ImplLessFunction(_) => "function", - Self::StructFunction(_, _, _) => "function", - Self::StaticVariable(_) => "static variable", - Self::Type(_) => "type" - }; - - write!(f, "{}", s)?; - - Ok(()) - } -} \ No newline at end of file + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Function(_, _) => "function", + Self::ImplLessFunction(_) => "function", + Self::StructFunction(_, _, _) => "function", + Self::StaticVariable(_) => "static variable", + Self::Type(_) => "type", + }; + + write!(f, "{}", s)?; + + Ok(()) + } +} diff --git a/compiler/astoir_hir/src/structs.rs b/compiler/astoir_hir/src/structs.rs index f0fb144..5c3725a 100644 --- a/compiler/astoir_hir/src/structs.rs +++ b/compiler/astoir_hir/src/structs.rs @@ -4,19 +4,31 @@ use crate::nodes::HIRNode; #[derive(Debug, Clone)] pub enum StructLRUStep { - FunctionCall { func: usize, args: Vec> }, - VariableStep { variable: usize } + FunctionCall { + func: usize, + args: Vec>, + }, + VariableStep { + variable: usize, + }, } #[derive(Debug, Clone)] pub enum HIRIfBranch { - IfBranch { cond: Box, body: Vec> }, - ElseIfBranch { cond: Box, body: Vec> }, - ElseBranch { body: Vec> } + IfBranch { + cond: Box, + body: Vec>, + }, + ElseIfBranch { + cond: Box, + body: Vec>, + }, + ElseBranch { + body: Vec>, + }, } #[derive(Debug)] pub struct HIRStructContainer { - pub function_impls: Vec> + pub function_impls: Vec>, } - diff --git a/compiler/astoir_hir_lowering/src/arrays.rs b/compiler/astoir_hir_lowering/src/arrays.rs index d4308d5..f8691b7 100644 --- a/compiler/astoir_hir_lowering/src/arrays.rs +++ b/compiler/astoir_hir_lowering/src/arrays.rs @@ -1,36 +1,88 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; use compiler_typing::{raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult, builders::make_index_usage}; use crate::{values::lower_ast_value, var::lower_ast_variable_reference}; -pub fn lower_ast_array_index_access(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::ArrayIndexAccess { val, index } = node.clone().kind { - let array = lower_ast_value(context, curr_ctx, val)?; +pub fn lower_ast_array_index_access( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::ArrayIndexAccess { val, index } = node.clone().kind { + let array = lower_ast_value(context, curr_ctx, val)?; - if !array.get_node_type(context, curr_ctx).unwrap().can_use_index_access() { - return Err(make_index_usage(&*node, &array.get_node_type(context, curr_ctx).unwrap()).into()) - } + if !array + .get_node_type(context, curr_ctx) + .unwrap() + .can_use_index_access() + { + return Err( + make_index_usage(&*node, &array.get_node_type(context, curr_ctx).unwrap()).into(), + ); + } - let index = Box::new(lower_ast_value(context, curr_ctx, index)?.use_as(context, curr_ctx, Type::GenericLowered(RawType::Integer(32, false)), &*node, None)?); + let index = Box::new(lower_ast_value(context, curr_ctx, index)?.use_as( + context, + curr_ctx, + Type::GenericLowered(RawType::Integer(32, false)), + &*node, + None, + )?); - return Ok(Box::new(HIRNode::new(HIRNodeKind::ArrayIndexAccess { val: array, index }, &node.start, &node.end))); - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ArrayIndexAccess { val: array, index }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node type") + panic!("Invalid node type") } -pub fn lower_ast_array_modify(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::ArrayIndexModifiy { array, index, val } = node.clone().kind { - let array = lower_ast_variable_reference(context, curr_ctx, array, true)?; +pub fn lower_ast_array_modify( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::ArrayIndexModifiy { array, index, val } = node.clone().kind { + let array = lower_ast_variable_reference(context, curr_ctx, array, true)?; - let index = Box::new(lower_ast_value(context, curr_ctx, index)?.use_as(context, curr_ctx, Type::GenericLowered(RawType::Integer(32, false)), &*node, None)?); + let index = Box::new(lower_ast_value(context, curr_ctx, index)?.use_as( + context, + curr_ctx, + Type::GenericLowered(RawType::Integer(32, false)), + &*node, + None, + )?); - let new_val = Box::new(lower_ast_value(context, curr_ctx, val)?.use_as(context, curr_ctx, *array.get_node_type(context, curr_ctx).unwrap().get_inner_type(), &*node, None)?); + let new_val = Box::new( + lower_ast_value(context, curr_ctx, val)?.use_as( + context, + curr_ctx, + *array + .get_node_type(context, curr_ctx) + .unwrap() + .get_inner_type(), + &*node, + None, + )?, + ); - return Ok(Box::new(HIRNode::new(HIRNodeKind::ArrayIndexModify { array, index, new_val }, &node.start, &node.end))); - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ArrayIndexModify { + array, + index, + new_val, + }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node type") -} \ No newline at end of file + panic!("Invalid node type") +} diff --git a/compiler/astoir_hir_lowering/src/bools.rs b/compiler/astoir_hir_lowering/src/bools.rs index 16c97e3..2a2c4e6 100644 --- a/compiler/astoir_hir_lowering/src/bools.rs +++ b/compiler/astoir_hir_lowering/src/bools.rs @@ -1,36 +1,83 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; use compiler_typing::{raw::RawType, tree::Type}; -use diagnostics::{DiagnosticResult}; +use diagnostics::DiagnosticResult; use crate::values::lower_ast_value; -pub fn lower_ast_boolean_condition(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::BooleanBasedConditionMember { val, negate } = node.kind.clone() { - let hir_value = lower_ast_value(context, curr_ctx, val)?; +pub fn lower_ast_boolean_condition( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::BooleanBasedConditionMember { val, negate } = node.kind.clone() { + let hir_value = lower_ast_value(context, curr_ctx, val)?; - return Ok(Box::new(HIRNode::new(HIRNodeKind::BooleanCondition { value: hir_value, negation: negate }, &node.start, &node.end))); - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::BooleanCondition { + value: hir_value, + negation: negate, + }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node type") + panic!("Invalid node type") } -pub fn lower_ast_operator_condition(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::OperatorBasedConditionMember { lval, rval, operator } = node.kind.clone() { - let left_value = lower_ast_value(context, curr_ctx, lval)?; - - let right_value = Box::new(lower_ast_value(context, curr_ctx, rval)?.use_as(context, curr_ctx, left_value.get_node_type(context, curr_ctx).unwrap(), &*node, None)?); +pub fn lower_ast_operator_condition( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::OperatorBasedConditionMember { + lval, + rval, + operator, + } = node.kind.clone() + { + let left_value = lower_ast_value(context, curr_ctx, lval)?; - return Ok(Box::new(HIRNode::new(HIRNodeKind::BooleanOperator { left: left_value, right: right_value, operator }, &node.start, &node.end))) - } + let right_value = Box::new(lower_ast_value(context, curr_ctx, rval)?.use_as( + context, + curr_ctx, + left_value.get_node_type(context, curr_ctx).unwrap(), + &*node, + None, + )?); - panic!("Invalid node type") + return Ok(Box::new(HIRNode::new( + HIRNodeKind::BooleanOperator { + left: left_value, + right: right_value, + operator, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node type") } -pub fn lower_ast_condition(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - let hir_value = lower_ast_value(context, curr_ctx, node.clone())?; +pub fn lower_ast_condition( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + let hir_value = lower_ast_value(context, curr_ctx, node.clone())?; - let val = hir_value.use_as(context, curr_ctx, Type::Generic(RawType::Boolean, vec![], vec![]), &*node, None)?; + let val = hir_value.use_as( + context, + curr_ctx, + Type::Generic(RawType::Boolean, vec![], vec![]), + &*node, + None, + )?; - return Ok(Box::new(val)); -} \ No newline at end of file + return Ok(Box::new(val)); +} diff --git a/compiler/astoir_hir_lowering/src/control.rs b/compiler/astoir_hir_lowering/src/control.rs index 7507d79..373ac77 100644 --- a/compiler/astoir_hir_lowering/src/control.rs +++ b/compiler/astoir_hir_lowering/src/control.rs @@ -1,82 +1,151 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, structs::HIRIfBranch}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, + structs::HIRIfBranch, +}; use diagnostics::DiagnosticResult; -use crate::{bools::lower_ast_condition, lower_ast_body, math::lower_ast_math_operation, var::lower_ast_variable_declaration}; - -pub fn lower_ast_for_block(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::ForBlock { initial_state, cond, increment, body } = node.kind.clone() { - let branch = curr_ctx.start_branch(); - - let initial = lower_ast_variable_declaration(context, curr_ctx, initial_state)?; - let condition = lower_ast_condition(context, curr_ctx, cond)?; - - let incrementation = lower_ast_math_operation(context, curr_ctx, increment, true)?; - - let body = lower_ast_body(context, curr_ctx, body, false)?; - - curr_ctx.end_branch(branch); - - return Ok(Box::new(HIRNode::new(HIRNodeKind::ForBlock { initial_state:initial, condition, incrementation, body }, &node.start, &node.end))); - } - - panic!("Invalid node passed!"); +use crate::{ + bools::lower_ast_condition, lower_ast_body, math::lower_ast_math_operation, + var::lower_ast_variable_declaration, +}; + +pub fn lower_ast_for_block( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::ForBlock { + initial_state, + cond, + increment, + body, + } = node.kind.clone() + { + let branch = curr_ctx.start_branch(); + + let initial = lower_ast_variable_declaration(context, curr_ctx, initial_state)?; + let condition = lower_ast_condition(context, curr_ctx, cond)?; + + let incrementation = lower_ast_math_operation(context, curr_ctx, increment, true)?; + + let body = lower_ast_body(context, curr_ctx, body, false)?; + + curr_ctx.end_branch(branch); + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ForBlock { + initial_state: initial, + condition, + incrementation, + body, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node passed!"); } -pub fn lower_ast_while_block(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::WhileBlock { cond, body } = node.kind.clone() { - let condition = lower_ast_condition(context, curr_ctx, cond)?; +pub fn lower_ast_while_block( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::WhileBlock { cond, body } = node.kind.clone() { + let condition = lower_ast_condition(context, curr_ctx, cond)?; - let branch = curr_ctx.start_branch(); + let branch = curr_ctx.start_branch(); - let body = lower_ast_body(context, curr_ctx, body, true)?; + let body = lower_ast_body(context, curr_ctx, body, true)?; - curr_ctx.end_branch(branch); + curr_ctx.end_branch(branch); - return Ok(Box::new(HIRNode::new(HIRNodeKind::WhileBlock { condition, body }, &node.start, &node.end))); - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::WhileBlock { condition, body }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node passed!"); + panic!("Invalid node passed!"); } -pub fn lower_ast_if_statement_branch(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult { - match node.kind { - ASTTreeNodeKind::IfElseStatement { cond, body } => { - let condition = lower_ast_condition(context, curr_ctx, cond.unwrap())?; - let body = lower_ast_body(context, curr_ctx, body, true)?; - - return Ok(HIRIfBranch::ElseIfBranch { cond: condition, body }) - }, - - ASTTreeNodeKind::ElseStatement { body } => { - let body = lower_ast_body(context, curr_ctx, body, true)?; - - return Ok(HIRIfBranch::ElseBranch { body }) - }, - - ASTTreeNodeKind::IfStatement { cond, body, branches: _, depth: _} => { - let condition = lower_ast_condition(context, curr_ctx, cond)?; - let body = lower_ast_body(context, curr_ctx, body, true)?; - - return Ok(HIRIfBranch::IfBranch { cond: condition, body }) - }, - - _ => panic!("Invalid node passed!") - } +pub fn lower_ast_if_statement_branch( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult { + match node.kind { + ASTTreeNodeKind::IfElseStatement { cond, body } => { + let condition = lower_ast_condition(context, curr_ctx, cond.unwrap())?; + let body = lower_ast_body(context, curr_ctx, body, true)?; + + return Ok(HIRIfBranch::ElseIfBranch { + cond: condition, + body, + }); + } + + ASTTreeNodeKind::ElseStatement { body } => { + let body = lower_ast_body(context, curr_ctx, body, true)?; + + return Ok(HIRIfBranch::ElseBranch { body }); + } + + ASTTreeNodeKind::IfStatement { + cond, + body, + branches: _, + depth: _, + } => { + let condition = lower_ast_condition(context, curr_ctx, cond)?; + let body = lower_ast_body(context, curr_ctx, body, true)?; + + return Ok(HIRIfBranch::IfBranch { + cond: condition, + body, + }); + } + + _ => panic!("Invalid node passed!"), + } } -pub fn lower_ast_if_statement(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::IfStatement { cond: _, body: _, branches, depth: _ } = node.kind.clone() { - let mut hir_branches = vec![]; - - hir_branches.push(lower_ast_if_statement_branch(context, curr_ctx, node.clone())?); - - for b in branches { - hir_branches.push(lower_ast_if_statement_branch(context, curr_ctx, b)?); - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::IfStatement { branches: hir_branches }, &node.end, &node.start))) - } - - panic!("Invalid node passed!"); -} \ No newline at end of file +pub fn lower_ast_if_statement( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::IfStatement { + cond: _, + body: _, + branches, + depth: _, + } = node.kind.clone() + { + let mut hir_branches = vec![]; + + hir_branches.push(lower_ast_if_statement_branch( + context, + curr_ctx, + node.clone(), + )?); + + for b in branches { + hir_branches.push(lower_ast_if_statement_branch(context, curr_ctx, b)?); + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::IfStatement { + branches: hir_branches, + }, + &node.end, + &node.start, + ))); + } + + panic!("Invalid node passed!"); +} diff --git a/compiler/astoir_hir_lowering/src/enums.rs b/compiler/astoir_hir_lowering/src/enums.rs index 5ee4a79..e51fa51 100644 --- a/compiler/astoir_hir_lowering/src/enums.rs +++ b/compiler/astoir_hir_lowering/src/enums.rs @@ -1,48 +1,74 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}}; -use compiler_typing::{enums::{RawEnumTypeContainer}, raw::RawType}; +use astoir_hir::{ + ctx::HIRContext, + nodes::{HIRNode, HIRNodeKind}, +}; +use compiler_typing::{enums::RawEnumTypeContainer, raw::RawType}; use diagnostics::{DiagnosticResult, MaybeDiagnostic, builders::make_already_in_scope}; -use crate::types::{lower_ast_type_struct}; +use crate::types::lower_ast_type_struct; -pub fn lower_ast_enum_entry(context: &mut HIRContext, node: Box, container: &mut RawEnumTypeContainer) -> MaybeDiagnostic { - if let ASTTreeNodeKind::EnumEntryDeclaration { name, fields } = node.kind.clone() { - let mut hir_fields = vec![]; +pub fn lower_ast_enum_entry( + context: &mut HIRContext, + node: Box, + container: &mut RawEnumTypeContainer, +) -> MaybeDiagnostic { + if let ASTTreeNodeKind::EnumEntryDeclaration { name, fields } = node.kind.clone() { + let mut hir_fields = vec![]; - for f in fields { - if let ASTTreeNodeKind::StructFieldMember { name, member_type } = f.kind { - let t = lower_ast_type_struct(context, member_type, container, &*node)?; + for f in fields { + if let ASTTreeNodeKind::StructFieldMember { name, member_type } = f.kind { + let t = lower_ast_type_struct(context, member_type, container, &*node)?; - hir_fields.push((name.hash, t)); - continue; - } + hir_fields.push((name.hash, t)); + continue; + } - panic!("Invalid field node type!"); - } + panic!("Invalid field node type!"); + } - container.append_entry(name, hir_fields); - return Ok(()) - } + container.append_entry(name, hir_fields); + return Ok(()); + } - - panic!("Invalid node") + panic!("Invalid node") } -pub fn lower_ast_enum(context: &mut HIRContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::EnumDeclaration { name, entries, functions: _, type_params } = node.kind.clone() { - let mut container = RawEnumTypeContainer::new(context.type_storage.types.vals.len(), type_params); +pub fn lower_ast_enum( + context: &mut HIRContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::EnumDeclaration { + name, + entries, + functions: _, + type_params, + } = node.kind.clone() + { + let mut container = + RawEnumTypeContainer::new(context.type_storage.types.vals.len(), type_params); - for entry in entries { - lower_ast_enum_entry(context, entry, &mut container)?; - } + for entry in entries { + lower_ast_enum_entry(context, entry, &mut container)?; + } - let ind = match context.type_storage.append_with_hash(name.hash, RawType::Enum(container.clone())) { - Ok(v) => v, - Err(_) => return Err(make_already_in_scope(&*node, &name.val).into()) - }; + let ind = match context + .type_storage + .append_with_hash(name.hash, RawType::Enum(container.clone())) + { + Ok(v) => v, + Err(_) => return Err(make_already_in_scope(&*node, &name.val).into()), + }; - return Ok(Box::new(HIRNode::new(HIRNodeKind::EnumDeclaration { type_name: ind, container }, &node.start, &node.end))) - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::EnumDeclaration { + type_name: ind, + container, + }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node") -} \ No newline at end of file + panic!("Invalid node") +} diff --git a/compiler/astoir_hir_lowering/src/func.rs b/compiler/astoir_hir_lowering/src/func.rs index 56b31f4..76aa5f4 100644 --- a/compiler/astoir_hir_lowering/src/func.rs +++ b/compiler/astoir_hir_lowering/src/func.rs @@ -1,117 +1,177 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; -use diagnostics::{DiagnosticResult, builders::{make_already_in_scope, make_cannot_find_func}}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; +use diagnostics::{ + DiagnosticResult, + builders::{make_already_in_scope, make_cannot_find_func}, +}; use crate::{lower_ast_body, types::lower_ast_type, values::lower_ast_value}; -pub fn lower_ast_function_call(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::FunctionCall { func, args } = node.kind.clone() { - let f_ind = match context.functions.get_index(func.hash) { - Some(v) => v, - None => return Err(make_cannot_find_func(&*node, &func.hash).into()) - }; - - let func = &context.functions.vals[f_ind].clone(); - let mut hir_args = vec![]; - let mut ind = 0; - - for ast in args { - let hir = lower_ast_value(context, curr_ctx, ast)?; - - let val = hir.use_as(context, curr_ctx, func.1[ind].1.clone(), &*node, None)?; - - hir_args.push(Box::new(val)); - - ind += 1; - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::FunctionCall { func_name: f_ind, arguments: hir_args }, &node.start, &node.end))) - } - - panic!("Invalid node passed!"); +pub fn lower_ast_function_call( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::FunctionCall { func, args } = node.kind.clone() { + let f_ind = match context.functions.get_index(func.hash) { + Some(v) => v, + None => return Err(make_cannot_find_func(&*node, &func.hash).into()), + }; + + let func = &context.functions.vals[f_ind].clone(); + let mut hir_args = vec![]; + let mut ind = 0; + + for ast in args { + let hir = lower_ast_value(context, curr_ctx, ast)?; + + let val = hir.use_as(context, curr_ctx, func.1[ind].1.clone(), &*node, None)?; + + hir_args.push(Box::new(val)); + + ind += 1; + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::FunctionCall { + func_name: f_ind, + arguments: hir_args, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node passed!"); } -pub fn lower_ast_function_declaration(context: &mut HIRContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, body, return_type, requires_this } = node.clone().kind { - let ret_type; - - if return_type.is_some() { - let lower = lower_ast_type(context, return_type.unwrap(), &*node)?; - - ret_type = Some(lower) - } else { - ret_type = None; - } - - let mut arguments = vec![]; - let mut types = vec![]; - - for arg in args { - types.push(arg.argument_type.clone()); - let t = lower_ast_type(context, arg.argument_type, &*node)?; - - arguments.push((arg.name.hash, t)); - } - - let mut curr_ctx = HIRBranchedContext::new(); - - let branch = curr_ctx.start_branch(); - - for arg in &arguments { - match curr_ctx.introduce_variable(arg.0, arg.1.clone(), true) { - Ok(_) => {}, - Err(_) => return Err(make_already_in_scope(&*node, &arg.0).into()) - } - } - - let ind = context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); - - let body = lower_ast_body(context, &mut curr_ctx, body, false)?; - - context.function_contexts.push(Some(curr_ctx.clone())); - - curr_ctx.end_branch(branch); - - for var in 0..curr_ctx.variables.len() { - if curr_ctx.is_eligible_for_ssa(var) { - println!("* Function variable {} is eligible for SSA treatment!", var); - } - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::FunctionDeclaration { func_name: ind, arguments, return_type: ret_type, body, ctx: curr_ctx, requires_this }, &node.start, &node.end))); - } - - panic!("Invalid node passed!"); +pub fn lower_ast_function_declaration( + context: &mut HIRContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::FunctionDeclaration { + func_name, + args, + body, + return_type, + requires_this, + } = node.clone().kind + { + let ret_type; + + if return_type.is_some() { + let lower = lower_ast_type(context, return_type.unwrap(), &*node)?; + + ret_type = Some(lower) + } else { + ret_type = None; + } + + let mut arguments = vec![]; + let mut types = vec![]; + + for arg in args { + types.push(arg.argument_type.clone()); + let t = lower_ast_type(context, arg.argument_type, &*node)?; + + arguments.push((arg.name.hash, t)); + } + + let mut curr_ctx = HIRBranchedContext::new(); + + let branch = curr_ctx.start_branch(); + + for arg in &arguments { + match curr_ctx.introduce_variable(arg.0, arg.1.clone(), true) { + Ok(_) => {} + Err(_) => return Err(make_already_in_scope(&*node, &arg.0).into()), + } + } + + let ind = context.functions.append( + func_name.hash, + (ret_type.clone(), arguments.clone(), func_name.val.clone()), + ); + + let body = lower_ast_body(context, &mut curr_ctx, body, false)?; + + context.function_contexts.push(Some(curr_ctx.clone())); + + curr_ctx.end_branch(branch); + + for var in 0..curr_ctx.variables.len() { + if curr_ctx.is_eligible_for_ssa(var) { + println!("* Function variable {} is eligible for SSA treatment!", var); + } + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::FunctionDeclaration { + func_name: ind, + arguments, + return_type: ret_type, + body, + ctx: curr_ctx, + requires_this, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node passed!"); } -pub fn lower_ast_shadow_function_declaration(context: &mut HIRContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::ShadowFunctionDeclaration { func_name, args, return_type } = node.kind.clone() { - let ret_type; - - if return_type.is_some() { - let lower = lower_ast_type(context, return_type.unwrap(), &*node)?; - - ret_type = Some(lower) - } else { - ret_type = None; - } - - let mut arguments = vec![]; - let mut types = vec![]; - - for arg in args { - types.push(arg.argument_type.clone()); - let t = lower_ast_type(context, arg.argument_type, &*node)?; - - arguments.push((arg.name.hash, t)); - } - - let ind = context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); - - context.function_contexts.push(None); - - return Ok(Box::new(HIRNode::new(HIRNodeKind::ShadowFunctionDeclaration { func_name: ind, arguments, return_type: ret_type }, &node.start, &node.end))) - } - - panic!("Invalid node passed!"); -} \ No newline at end of file +pub fn lower_ast_shadow_function_declaration( + context: &mut HIRContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::ShadowFunctionDeclaration { + func_name, + args, + return_type, + } = node.kind.clone() + { + let ret_type; + + if return_type.is_some() { + let lower = lower_ast_type(context, return_type.unwrap(), &*node)?; + + ret_type = Some(lower) + } else { + ret_type = None; + } + + let mut arguments = vec![]; + let mut types = vec![]; + + for arg in args { + types.push(arg.argument_type.clone()); + let t = lower_ast_type(context, arg.argument_type, &*node)?; + + arguments.push((arg.name.hash, t)); + } + + let ind = context.functions.append( + func_name.hash, + (ret_type.clone(), arguments.clone(), func_name.val.clone()), + ); + + context.function_contexts.push(None); + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ShadowFunctionDeclaration { + func_name: ind, + arguments, + return_type: ret_type, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node passed!"); +} diff --git a/compiler/astoir_hir_lowering/src/lib.rs b/compiler/astoir_hir_lowering/src/lib.rs index 744a624..c434689 100644 --- a/compiler/astoir_hir_lowering/src/lib.rs +++ b/compiler/astoir_hir_lowering/src/lib.rs @@ -1,123 +1,172 @@ -use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; +use ast::{ + ctx::ParserCtx, + tree::{ASTTreeNode, ASTTreeNodeKind}, +}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos}; use prelude::apply_prelude; -use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, enums::lower_ast_enum, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, uses::handle_ast_use_statement, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}}; +use crate::{ + arrays::lower_ast_array_modify, + control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, + enums::lower_ast_enum, + func::{ + lower_ast_function_call, lower_ast_function_declaration, + lower_ast_shadow_function_declaration, + }, + math::lower_ast_math_operation, + structs::lower_ast_struct_declaration, + uses::handle_ast_use_statement, + values::lower_ast_value, + var::{lower_ast_variable_assign, lower_ast_variable_declaration}, +}; -pub mod literals; -pub mod var; -pub mod types; -pub mod values; -pub mod func; -pub mod math; +pub mod arrays; pub mod bools; pub mod control; +pub mod enums; +pub mod func; +pub mod literals; +pub mod math; pub mod structs; -pub mod arrays; +pub mod types; pub mod unwraps; -pub mod enums; pub mod uses; +pub mod values; +pub mod var; -pub fn lower_ast_body_node(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - move_current_diagnostic_pos(node.get_pos()); - 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::ArrayIndexModifiy { .. } => return lower_ast_array_modify(context, curr_ctx, node), - - ASTTreeNodeKind::MathResult { .. } => return lower_ast_math_operation(context, curr_ctx, node, true), - - ASTTreeNodeKind::ReturnStatement { val } => { - let v; - - if val.is_none() { - v = None; - } else { - v = Some(lower_ast_value(context, curr_ctx, val.unwrap())?) - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::ReturnStatement { value: v }, &node.start, &node.end))) - }, - - ASTTreeNodeKind::ForBlock { .. } => return lower_ast_for_block(context, curr_ctx, node), - ASTTreeNodeKind::WhileBlock { .. } => return lower_ast_while_block(context, curr_ctx, node), - ASTTreeNodeKind::IfStatement { .. } => return lower_ast_if_statement(context, curr_ctx, node), - - _ => panic!("Invalid node type") - } +pub fn lower_ast_body_node( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + move_current_diagnostic_pos(node.get_pos()); + 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::ArrayIndexModifiy { .. } => { + return lower_ast_array_modify(context, curr_ctx, node); + } + + ASTTreeNodeKind::MathResult { .. } => { + return lower_ast_math_operation(context, curr_ctx, node, true); + } + + ASTTreeNodeKind::ReturnStatement { val } => { + let v; + + if val.is_none() { + v = None; + } else { + v = Some(lower_ast_value(context, curr_ctx, val.unwrap())?) + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ReturnStatement { value: v }, + &node.start, + &node.end, + ))); + } + + ASTTreeNodeKind::ForBlock { .. } => return lower_ast_for_block(context, curr_ctx, node), + ASTTreeNodeKind::WhileBlock { .. } => { + return lower_ast_while_block(context, curr_ctx, node); + } + ASTTreeNodeKind::IfStatement { .. } => { + return lower_ast_if_statement(context, curr_ctx, node); + } + + _ => panic!("Invalid node type"), + } } -pub fn lower_ast_body(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, nodes: Vec>, introduce_era: bool) -> DiagnosticResult>> { - let mut hir_nodes = vec![]; +pub fn lower_ast_body( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + nodes: Vec>, + introduce_era: bool, +) -> DiagnosticResult>> { + let mut hir_nodes = vec![]; - let branch; + let branch; - if introduce_era { - branch = curr_ctx.start_branch(); - } else { - branch = 0; - } + if introduce_era { + branch = curr_ctx.start_branch(); + } else { + branch = 0; + } - for n in nodes { - hir_nodes.push(lower_ast_body_node(context, curr_ctx, n)?); - } + for n in nodes { + hir_nodes.push(lower_ast_body_node(context, curr_ctx, n)?); + } - if introduce_era { - curr_ctx.end_branch(branch); - } + if introduce_era { + curr_ctx.end_branch(branch); + } - return Ok(hir_nodes); + return Ok(hir_nodes); } -pub fn lower_ast_toplevel(context: &mut HIRContext, node: Box) -> DiagnosticResult { - match node.kind { - ASTTreeNodeKind::FunctionDeclaration { .. } => { - let func_decl = lower_ast_function_declaration(context, node)?; +pub fn lower_ast_toplevel( + context: &mut HIRContext, + node: Box, +) -> DiagnosticResult { + match node.kind { + ASTTreeNodeKind::FunctionDeclaration { .. } => { + let func_decl = lower_ast_function_declaration(context, node)?; + + context.function_declarations.push(Some(func_decl)); - context.function_declarations.push(Some(func_decl)); + return Ok(true); + } - return Ok(true) - }, + ASTTreeNodeKind::ShadowFunctionDeclaration { .. } => { + let func_decl = lower_ast_shadow_function_declaration(context, node)?; - ASTTreeNodeKind::ShadowFunctionDeclaration { .. } => { - let func_decl = lower_ast_shadow_function_declaration(context, node)?; - - context.function_declarations.push(Some(func_decl)); - - return Ok(true); - }, + context.function_declarations.push(Some(func_decl)); - ASTTreeNodeKind::StructLayoutDeclaration { .. } => { - lower_ast_struct_declaration(context, node)?; + return Ok(true); + } - return Ok(true) - }, + ASTTreeNodeKind::StructLayoutDeclaration { .. } => { + lower_ast_struct_declaration(context, node)?; - ASTTreeNodeKind::EnumDeclaration { .. } => { - lower_ast_enum(context, node)?; + return Ok(true); + } - return Ok(true) - } + ASTTreeNodeKind::EnumDeclaration { .. } => { + lower_ast_enum(context, node)?; - _ => panic!("Invalid node type") - } -} + return Ok(true); + } + + _ => panic!("Invalid node type"), + } +} pub fn lower_ast(ctx: ParserCtx) -> DiagnosticResult { - let mut hir_ctx = HIRContext::new(); - apply_prelude(&mut hir_ctx, &*ctx.map[&ctx.iter_order[0]])?; + let mut hir_ctx = HIRContext::new(); + apply_prelude(&mut hir_ctx, &*ctx.map[&ctx.iter_order[0]])?; - for u in ctx.uses { - handle_ast_use_statement(&mut hir_ctx, u)?; - } + for u in ctx.uses { + handle_ast_use_statement(&mut hir_ctx, u)?; + } - for s in ctx.iter_order { - let k = ctx.map[&s].clone(); + for s in ctx.iter_order { + let k = ctx.map[&s].clone(); - lower_ast_toplevel(&mut hir_ctx, k)?; - } + lower_ast_toplevel(&mut hir_ctx, k)?; + } - return Ok(hir_ctx); -} \ No newline at end of file + return Ok(hir_ctx); +} diff --git a/compiler/astoir_hir_lowering/src/literals.rs b/compiler/astoir_hir_lowering/src/literals.rs index 368348e..ff75503 100644 --- a/compiler/astoir_hir_lowering/src/literals.rs +++ b/compiler/astoir_hir_lowering/src/literals.rs @@ -1,23 +1,40 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}}; +use astoir_hir::{ + ctx::HIRContext, + nodes::{HIRNode, HIRNodeKind}, +}; use compiler_typing::tree::Type; use diagnostics::{DiagnosticResult, builders::make_cannot_find_type}; -pub fn lower_ast_literal(context: &HIRContext, node: Box) -> DiagnosticResult> { - match node.kind { - ASTTreeNodeKind::IntegerLit { val, hash } => { - let lit_type = match context.type_storage.get_type(hash) { - Ok(v) => v, - Err(_) => return Err(make_cannot_find_type(&*node, &hash).into()) - }; +pub fn lower_ast_literal( + context: &HIRContext, + node: Box, +) -> DiagnosticResult> { + match node.kind { + ASTTreeNodeKind::IntegerLit { val, hash } => { + let lit_type = match context.type_storage.get_type(hash) { + Ok(v) => v, + Err(_) => return Err(make_cannot_find_type(&*node, &hash).into()), + }; - return Ok(Box::new(HIRNode::new(HIRNodeKind::IntegerLiteral { value: val, int_type: Type::Generic(lit_type, vec![], vec![]) }, &node.start, &node.end))) - }, + return Ok(Box::new(HIRNode::new( + HIRNodeKind::IntegerLiteral { + value: val, + int_type: Type::Generic(lit_type, vec![], vec![]), + }, + &node.start, + &node.end, + ))); + } - ASTTreeNodeKind::StringLit(val) => { - return Ok(Box::new(HIRNode::new(HIRNodeKind::StringLiteral { value: val }, &node.start, &node.end))) - }, + ASTTreeNodeKind::StringLit(val) => { + return Ok(Box::new(HIRNode::new( + HIRNodeKind::StringLiteral { value: val }, + &node.start, + &node.end, + ))); + } - _ => panic!("Invalid note type") - } -} \ No newline at end of file + _ => panic!("Invalid note type"), + } +} diff --git a/compiler/astoir_hir_lowering/src/math.rs b/compiler/astoir_hir_lowering/src/math.rs index 8a8a4b5..bba2270 100644 --- a/compiler/astoir_hir_lowering/src/math.rs +++ b/compiler/astoir_hir_lowering/src/math.rs @@ -1,21 +1,60 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, diagnostic::Level, errors::MATH_OPERATION_ASSIGNS}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, diagnostic::Level, errors::MATH_OPERATION_ASSIGNS, +}; use crate::values::lower_ast_value; -pub fn lower_ast_math_operation(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box, enforce_assign: bool) -> DiagnosticResult> { - if let ASTTreeNodeKind::MathResult { lval, rval, operator } = node.kind.clone() { - if enforce_assign && !operator.assigns { - return Err(node.make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec!["consider assigning this to variable".to_string()], vec!["add = at the end of the operator".to_string()]).into()) - } +pub fn lower_ast_math_operation( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, + enforce_assign: bool, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::MathResult { + lval, + rval, + operator, + } = node.kind.clone() + { + if enforce_assign && !operator.assigns { + return Err(node + .make_simple_diagnostic( + MATH_OPERATION_ASSIGNS.0, + Level::Error, + MATH_OPERATION_ASSIGNS.1.to_string(), + None, + vec![], + vec!["consider assigning this to variable".to_string()], + vec!["add = at the end of the operator".to_string()], + ) + .into()); + } - let left = lower_ast_value(context, curr_ctx, lval)?; + let left = lower_ast_value(context, curr_ctx, lval)?; - let right = Box::new(lower_ast_value(context, curr_ctx, rval)?.use_as(context, curr_ctx, left.get_node_type(context, curr_ctx).unwrap(), &*node, None)?); + let right = Box::new(lower_ast_value(context, curr_ctx, rval)?.use_as( + context, + curr_ctx, + left.get_node_type(context, curr_ctx).unwrap(), + &*node, + None, + )?); - return Ok(Box::new(HIRNode::new(HIRNodeKind::MathOperation { left, right, operation: operator }, &node.start, &node.end))) - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::MathOperation { + left, + right, + operation: operator, + }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node type") -} \ No newline at end of file + panic!("Invalid node type") +} diff --git a/compiler/astoir_hir_lowering/src/structs.rs b/compiler/astoir_hir_lowering/src/structs.rs index 4380d57..d800fea 100644 --- a/compiler/astoir_hir_lowering/src/structs.rs +++ b/compiler/astoir_hir_lowering/src/structs.rs @@ -1,105 +1,173 @@ use std::collections::HashMap; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, structs::HIRStructContainer}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, + structs::HIRStructContainer, +}; use compiler_typing::{raw::RawType, structs::RawStructTypeContainer}; use compiler_utils::utils::indexed::IndexStorage; use diagnostics::{DiagnosticResult, builders::make_already_in_scope}; use crate::{lower_ast_body, types::lower_ast_type_struct, values::lower_ast_value}; -fn lower_ast_struct_member(context: &mut HIRContext, node: Box, container: &mut RawStructTypeContainer) -> DiagnosticResult { - if let ASTTreeNodeKind::StructFieldMember { name, member_type } = node.kind.clone() { - let t = lower_ast_type_struct(context, member_type, container, &*node)?; +fn lower_ast_struct_member( + context: &mut HIRContext, + node: Box, + container: &mut RawStructTypeContainer, +) -> DiagnosticResult { + if let ASTTreeNodeKind::StructFieldMember { name, member_type } = node.kind.clone() { + let t = lower_ast_type_struct(context, member_type, container, &*node)?; - container.fields.append(name.hash, t); - return Ok(true); - } + container.fields.append(name.hash, t); + return Ok(true); + } - panic!("Invalid node type") + panic!("Invalid node type") } -fn lower_ast_struct_function_decl(context: &mut HIRContext, node: Box, container: &mut RawStructTypeContainer) -> DiagnosticResult> { - if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, body, return_type, requires_this } = node.kind.clone() { - let mut arguments = vec![]; - - for arg in args { - let lowered = lower_ast_type_struct(context, arg.argument_type, container, &*node)?; - - arguments.push((arg.name.hash, lowered)); - } - - let ret_type; - - if return_type.is_some() { - let lowered = lower_ast_type_struct(context, return_type.unwrap(), container, &*node)?; - - ret_type = Some(lowered) - } else { - ret_type = None; - } - - let mut curr_ctx = HIRBranchedContext::new(); - let body = lower_ast_body(context, &mut curr_ctx, body, true)?; - - let ind = container.functions.append(func_name.hash, (arguments.clone(), ret_type.clone())); - - return Ok(Box::new(HIRNode::new(HIRNodeKind::StructFunctionDeclaration { func_name: ind, arguments, return_type: ret_type, body, ctx: curr_ctx, requires_this }, &node.start, &node.end))) - } - - panic!("Invalid node type") +fn lower_ast_struct_function_decl( + context: &mut HIRContext, + node: Box, + container: &mut RawStructTypeContainer, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::FunctionDeclaration { + func_name, + args, + body, + return_type, + requires_this, + } = node.kind.clone() + { + let mut arguments = vec![]; + + for arg in args { + let lowered = lower_ast_type_struct(context, arg.argument_type, container, &*node)?; + + arguments.push((arg.name.hash, lowered)); + } + + let ret_type; + + if return_type.is_some() { + let lowered = lower_ast_type_struct(context, return_type.unwrap(), container, &*node)?; + + ret_type = Some(lowered) + } else { + ret_type = None; + } + + let mut curr_ctx = HIRBranchedContext::new(); + let body = lower_ast_body(context, &mut curr_ctx, body, true)?; + + let ind = container + .functions + .append(func_name.hash, (arguments.clone(), ret_type.clone())); + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::StructFunctionDeclaration { + func_name: ind, + arguments, + return_type: ret_type, + body, + ctx: curr_ctx, + requires_this, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node type") } -pub fn lower_ast_struct_declaration(context: &mut HIRContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::StructLayoutDeclaration { name, layout, members, type_params } = node.kind.clone() { - let mut container = RawStructTypeContainer { fields: IndexStorage::new(), functions: IndexStorage::new(), type_params }; - - let mut func_impls = vec![]; - - let base = RawType::Struct(layout, container.clone()); - - let ind = match context.type_storage.append(name.hash, base) { - Ok(v) => v, - Err(_) => return Err(make_already_in_scope(&*node, &name.val).into()) - }; - - for member in members { - match &member.kind { - &ASTTreeNodeKind::StructFieldMember { .. } => { - lower_ast_struct_member(context, member, &mut container)?; - - context.type_storage.types.vals[ind] = RawType::Struct(layout, container.clone()); - }, - &ASTTreeNodeKind::FunctionDeclaration { .. } => { - let body = lower_ast_struct_function_decl(context, member, &mut container)?; - - context.type_storage.types.vals[ind] = RawType::Struct(layout, container.clone()); - - func_impls.push(body); - }, - - _ => panic!("Invalid node type") - }; - } - - context.struct_func_impls.insert(ind, HIRStructContainer { function_impls: func_impls }); - - return Ok(Box::new(HIRNode::new(HIRNodeKind::StructDeclaration { type_name: ind, container, layout }, &node.start, &node.end))); - } - - panic!("Invalid node type") +pub fn lower_ast_struct_declaration( + context: &mut HIRContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::StructLayoutDeclaration { + name, + layout, + members, + type_params, + } = node.kind.clone() + { + let mut container = RawStructTypeContainer { + fields: IndexStorage::new(), + functions: IndexStorage::new(), + type_params, + }; + + let mut func_impls = vec![]; + + let base = RawType::Struct(layout, container.clone()); + + let ind = match context.type_storage.append(name.hash, base) { + Ok(v) => v, + Err(_) => return Err(make_already_in_scope(&*node, &name.val).into()), + }; + + for member in members { + match &member.kind { + &ASTTreeNodeKind::StructFieldMember { .. } => { + lower_ast_struct_member(context, member, &mut container)?; + + context.type_storage.types.vals[ind] = + RawType::Struct(layout, container.clone()); + } + &ASTTreeNodeKind::FunctionDeclaration { .. } => { + let body = lower_ast_struct_function_decl(context, member, &mut container)?; + + context.type_storage.types.vals[ind] = + RawType::Struct(layout, container.clone()); + + func_impls.push(body); + } + + _ => panic!("Invalid node type"), + }; + } + + context.struct_func_impls.insert( + ind, + HIRStructContainer { + function_impls: func_impls, + }, + ); + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::StructDeclaration { + type_name: ind, + container, + layout, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node type") } -pub fn lower_ast_struct_initializer(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::StructInitializer { map } = node.kind.clone() { - let mut new_map = HashMap::new(); - - for (k, v) in map { - new_map.insert(k, lower_ast_value(context, curr_ctx, v)?); - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::StructInitializer { fields: new_map }, &node.start, &node.end))) - } - - panic!("Invalid node type") -} \ No newline at end of file +pub fn lower_ast_struct_initializer( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::StructInitializer { map } = node.kind.clone() { + let mut new_map = HashMap::new(); + + for (k, v) in map { + new_map.insert(k, lower_ast_value(context, curr_ctx, v)?); + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::StructInitializer { fields: new_map }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node type") +} diff --git a/compiler/astoir_hir_lowering/src/types.rs b/compiler/astoir_hir_lowering/src/types.rs index 4a807f7..8186492 100644 --- a/compiler/astoir_hir_lowering/src/types.rs +++ b/compiler/astoir_hir_lowering/src/types.rs @@ -2,103 +2,141 @@ use ast::types::ASTType; use astoir_hir::ctx::HIRContext; use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, tree::Type}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_type, make_diff_size_specifiers, make_diff_type_specifiers, make_req_type_kind}}; - -pub fn lower_ast_type(context: &mut HIRContext, t: ASTType, origin: &K) -> DiagnosticResult { - return match t { - ASTType::Generic(type_id, type_params, size_params, specifier) => { - let hash = HashedString::new(type_id).hash; - - let mut t = match context.type_storage.get_type(hash) { - Ok(v) => v, - Err(_) => return Err(make_cannot_find_type(origin, &hash).into()) - }; - - if specifier.is_some() { - let container = match t { - RawType::Enum(v) => v, - _ => return Err(make_req_type_kind(origin, &"enum".to_string()).into()) - }; - - t = container.get_entry(HashedString::new(specifier.unwrap()))? - } - - if t.get_type_params_count(&context.type_storage) != type_params.len() { - return Err(make_diff_type_specifiers(origin, &type_params.len(), &t.get_type_params_count(&context.type_storage)).into()) - } - - let mut t_params = vec![]; - - for type_param in type_params { - t_params.push(Box::new(lower_ast_type(context, *type_param, origin)?)); - } - - let res = Type::Generic(t.clone(), t_params, size_params); - - if t.is_sized() { - let lower = lower_sized_base_type(context, &res, origin)?; - - if context.type_storage.type_to_ind.contains_key(&lower) { - return Ok(Type::Generic(t, vec![], vec![])); - } else { - let ind = match context.type_storage.append_with_hash(hash, lower) { - Ok(v) => v, - Err(_) => panic!("Generic lowering type cannot be found on type_to_hash") - }; - - return Ok(Type::Generic(context.type_storage.types.vals[ind].clone(), vec![], vec![])) - } - } - - return Ok(res); - }, - - ASTType::Pointer(array, inner) => Ok(Type::Pointer(array, Box::new(lower_ast_type(context, *inner, origin)?))), - ASTType::Reference(inner) => Ok(Type::Reference(Box::new(lower_ast_type(context, *inner, origin)?))), - ASTType::Array(size, inner) => Ok(Type::Array(size, Box::new(lower_ast_type(context, *inner, origin)?))) - }; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, + builders::{ + make_cannot_find_type, make_diff_size_specifiers, make_diff_type_specifiers, + make_req_type_kind, + }, +}; + +pub fn lower_ast_type( + context: &mut HIRContext, + t: ASTType, + origin: &K, +) -> DiagnosticResult { + return match t { + ASTType::Generic(type_id, type_params, size_params, specifier) => { + let hash = HashedString::new(type_id).hash; + + let mut t = match context.type_storage.get_type(hash) { + Ok(v) => v, + Err(_) => return Err(make_cannot_find_type(origin, &hash).into()), + }; + + if specifier.is_some() { + let container = match t { + RawType::Enum(v) => v, + _ => return Err(make_req_type_kind(origin, &"enum".to_string()).into()), + }; + + t = container.get_entry(HashedString::new(specifier.unwrap()))? + } + + if t.get_type_params_count(&context.type_storage) != type_params.len() { + return Err(make_diff_type_specifiers( + origin, + &type_params.len(), + &t.get_type_params_count(&context.type_storage), + ) + .into()); + } + + let mut t_params = vec![]; + + for type_param in type_params { + t_params.push(Box::new(lower_ast_type(context, *type_param, origin)?)); + } + + let res = Type::Generic(t.clone(), t_params, size_params); + + if t.is_sized() { + let lower = lower_sized_base_type(context, &res, origin)?; + + if context.type_storage.type_to_ind.contains_key(&lower) { + return Ok(Type::Generic(t, vec![], vec![])); + } else { + let ind = match context.type_storage.append_with_hash(hash, lower) { + Ok(v) => v, + Err(_) => panic!("Generic lowering type cannot be found on type_to_hash"), + }; + + return Ok(Type::Generic( + context.type_storage.types.vals[ind].clone(), + vec![], + vec![], + )); + } + } + + return Ok(res); + } + + ASTType::Pointer(array, inner) => Ok(Type::Pointer( + array, + Box::new(lower_ast_type(context, *inner, origin)?), + )), + ASTType::Reference(inner) => Ok(Type::Reference(Box::new(lower_ast_type( + context, *inner, origin, + )?))), + ASTType::Array(size, inner) => Ok(Type::Array( + size, + Box::new(lower_ast_type(context, *inner, origin)?), + )), + }; } -pub fn lower_ast_type_struct(context: &mut HIRContext, t: ASTType, container: &T, origin: &K) -> DiagnosticResult { - if let ASTType::Generic(id, _, _, _) = &t { - let key = HashedString::new(id.clone()); +pub fn lower_ast_type_struct( + context: &mut HIRContext, + t: ASTType, + container: &T, + origin: &K, +) -> DiagnosticResult { + if let ASTType::Generic(id, _, _, _) = &t { + let key = HashedString::new(id.clone()); + + if container.has_type_param(&key) { + return Ok(TypeReference::Unresolved( + container.get_type_param_ind(&key), + )); + } + } + + return Ok(TypeReference::Resolved(lower_ast_type(context, t, origin)?)); +} - if container.has_type_param(&key) { - return Ok(TypeReference::Unresolved(container.get_type_param_ind(&key))); - } - } +pub fn lower_sized_base_type( + context: &HIRContext, + t: &Type, + origin: &K, +) -> DiagnosticResult { + let data = t.get_generic_info(); - return Ok(TypeReference::Resolved(lower_ast_type(context, t, origin)?)) -} + match t.get_generic(&context.type_storage) { + RawType::SizedInteger(e) => { + if data.1.len() != 1 { + return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()); + } + + return Ok(RawType::Integer(data.1[0], e)); + } + + RawType::SizedFloating(e) => { + if data.1.len() != 1 { + return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()); + } -pub fn lower_sized_base_type(context: &HIRContext, t: &Type, origin: &K) -> DiagnosticResult { - let data = t.get_generic_info(); - - match t.get_generic(&context.type_storage) { - RawType::SizedInteger(e) => { - if data.1.len() != 1 { - return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()) - } - - return Ok(RawType::Integer(data.1[0], e)) - }, - - RawType::SizedFloating(e) => { - if data.1.len() != 1 { - return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()) - } - - return Ok(RawType::Floating(data.1[0], e)) - }, - - RawType::SizedFixedPoint(e) => { - if data.1.len() != 2 { - return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()) - } - - return Ok(RawType::FixedPoint(data.1[0], data.1[1], e)); - }, - - _ => panic!("This is not a sized type") - } -} \ No newline at end of file + return Ok(RawType::Floating(data.1[0], e)); + } + + RawType::SizedFixedPoint(e) => { + if data.1.len() != 2 { + return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()); + } + + return Ok(RawType::FixedPoint(data.1[0], data.1[1], e)); + } + + _ => panic!("This is not a sized type"), + } +} diff --git a/compiler/astoir_hir_lowering/src/unwraps.rs b/compiler/astoir_hir_lowering/src/unwraps.rs index ddbcbed..50bf516 100644 --- a/compiler/astoir_hir_lowering/src/unwraps.rs +++ b/compiler/astoir_hir_lowering/src/unwraps.rs @@ -1,33 +1,85 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext}, + nodes::{HIRNode, HIRNodeKind}, +}; use diagnostics::DiagnosticResult; use crate::{types::lower_ast_type, values::lower_ast_value, var::lower_ast_variable_reference}; -pub fn lower_ast_condition_unwrap(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::UnwrapCondition { original, target_type, unsafe_unwrap, target_var } = node.clone().kind { - let original = lower_ast_variable_reference(context, curr_ctx, original, true)?; - let target_type = lower_ast_type(context, target_type, &*node)?; - - if target_var.is_none() { - return Ok(Box::new(HIRNode::new(HIRNodeKind::UnwrapCondition { original, new_type: target_type, new_var: None, unsafe_unwrap }, &node.start, &node.end))) - } +pub fn lower_ast_condition_unwrap( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::UnwrapCondition { + original, + target_type, + unsafe_unwrap, + target_var, + } = node.clone().kind + { + let original = lower_ast_variable_reference(context, curr_ctx, original, true)?; + let target_type = lower_ast_type(context, target_type, &*node)?; - let ind = curr_ctx.introduce_variable_next_era(target_var.unwrap().hash, target_type.clone(), true)?; + if target_var.is_none() { + return Ok(Box::new(HIRNode::new( + HIRNodeKind::UnwrapCondition { + original, + new_type: target_type, + new_var: None, + unsafe_unwrap, + }, + &node.start, + &node.end, + ))); + } - return Ok(Box::new(HIRNode::new(HIRNodeKind::UnwrapCondition { original, new_type: target_type, new_var: Some(ind), unsafe_unwrap }, &node.start, &node.end))) - } + let ind = curr_ctx.introduce_variable_next_era( + target_var.unwrap().hash, + target_type.clone(), + true, + )?; - panic!("Invalid node") + return Ok(Box::new(HIRNode::new( + HIRNodeKind::UnwrapCondition { + original, + new_type: target_type, + new_var: Some(ind), + unsafe_unwrap, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node") } -pub fn lower_ast_unwrap_value(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::UnwrapValue { original, target_type, unsafe_unwrap } = node.kind.clone() { - let original = lower_ast_value(context, curr_ctx, original)?; - let target_type = lower_ast_type(context, target_type, &*node)?; +pub fn lower_ast_unwrap_value( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::UnwrapValue { + original, + target_type, + unsafe_unwrap, + } = node.kind.clone() + { + let original = lower_ast_value(context, curr_ctx, original)?; + let target_type = lower_ast_type(context, target_type, &*node)?; - return Ok(Box::new(HIRNode::new(HIRNodeKind::UnwrapValue { original, new_type: target_type, unsafe_unwrap }, &node.start, &node.end))) - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::UnwrapValue { + original, + new_type: target_type, + unsafe_unwrap, + }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node!") -} \ No newline at end of file + panic!("Invalid node!") +} diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 5dd1652..4a6d47e 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -1,154 +1,227 @@ -use std::path::{MAIN_SEPARATOR_STR}; +use std::path::MAIN_SEPARATOR_STR; -use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType}; +use ast::{ + ctx::ParserCtx, + tree::{ASTTreeNode, ASTTreeNodeKind}, + types::ASTType, +}; use ast_parser::parse_ast_ctx; -use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}}; +use astoir_hir::{ + ctx::HIRContext, + nodes::{HIRNode, HIRNodeKind}, +}; use compiler_typing::{raw::RawType, tree::Type}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_cannot_find_type, make_diff_type_specifiers, make_req_type_kind, make_use_not_found}}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, + builders::{ + make_cannot_find_type, make_diff_type_specifiers, make_req_type_kind, make_use_not_found, + }, +}; use lexer::lexer::lexer_parse_file; -use crate::{lower_ast_toplevel, structs::lower_ast_struct_declaration, types::{lower_ast_type, lower_sized_base_type}}; - -pub fn handle_ast_use_statement_function_decl(context: &mut HIRContext, node: Box, ctx: &ParserCtx) -> MaybeDiagnostic { - if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, body: _, return_type, requires_this: _ } = node.kind.clone() { - let ret_type; - - if return_type.is_some() { - let lower = lower_ast_type_use_statement(context, return_type.unwrap(), &*node, ctx)?; - - ret_type = Some(lower) - } else { - ret_type = None; - } - - let mut arguments = vec![]; - let mut types = vec![]; - - for arg in args { - types.push(arg.argument_type.clone()); - let t = lower_ast_type_use_statement(context, arg.argument_type, &*node, ctx)?; - - arguments.push((arg.name.hash, t)); - } - - let func_name = context.functions.append(func_name.hash, (ret_type.clone(), arguments.clone(), func_name.val.clone())); - context.function_contexts.push(None); - - // Fabricate shadow func statement to satisfy functions_declarations - - let node = HIRNode::new(HIRNodeKind::ShadowFunctionDeclaration { func_name, arguments, return_type: ret_type }, &node.start, &node.end); - context.function_declarations.push(Some(Box::new(node))); - - return Ok(()) - } - - panic!("Invalid node") +use crate::{ + lower_ast_toplevel, + structs::lower_ast_struct_declaration, + types::{lower_ast_type, lower_sized_base_type}, +}; + +pub fn handle_ast_use_statement_function_decl( + context: &mut HIRContext, + node: Box, + ctx: &ParserCtx, +) -> MaybeDiagnostic { + if let ASTTreeNodeKind::FunctionDeclaration { + func_name, + args, + body: _, + return_type, + requires_this: _, + } = node.kind.clone() + { + let ret_type; + + if return_type.is_some() { + let lower = lower_ast_type_use_statement(context, return_type.unwrap(), &*node, ctx)?; + + ret_type = Some(lower) + } else { + ret_type = None; + } + + let mut arguments = vec![]; + let mut types = vec![]; + + for arg in args { + types.push(arg.argument_type.clone()); + let t = lower_ast_type_use_statement(context, arg.argument_type, &*node, ctx)?; + + arguments.push((arg.name.hash, t)); + } + + let func_name = context.functions.append( + func_name.hash, + (ret_type.clone(), arguments.clone(), func_name.val.clone()), + ); + context.function_contexts.push(None); + + // Fabricate shadow func statement to satisfy functions_declarations + + let node = HIRNode::new( + HIRNodeKind::ShadowFunctionDeclaration { + func_name, + arguments, + return_type: ret_type, + }, + &node.start, + &node.end, + ); + context.function_declarations.push(Some(Box::new(node))); + + return Ok(()); + } + + panic!("Invalid node") } -pub fn handle_ast_use_statement(context: &mut HIRContext, node: Box) -> MaybeDiagnostic { - if let ASTTreeNodeKind::UseStatement { shards, use_clauses } = node.kind.clone() { - let mut path = ".".to_string(); - - for shard in shards { - path += &MAIN_SEPARATOR_STR .to_owned(); - path += &shard.val; - } - - path += &".qf"; - - let lexer = lexer_parse_file(&path)?; - let ast = parse_ast_ctx(&lexer)?; - - for clause in use_clauses { - if !ast.map.contains_key(&clause.val) { - return Err(make_use_not_found(&*node, &clause.val, &path).into()) - } - - let n = ast.map[&clause.val].clone(); - - match n.kind { - ASTTreeNodeKind::FunctionDeclaration { .. } => { - handle_ast_use_statement_function_decl(context, n.clone(), &ast)?; - } - _ => { - lower_ast_toplevel(context, n.clone())?; - } - }; - } - - return Ok(()) - } - - panic!("Invalid node") +pub fn handle_ast_use_statement( + context: &mut HIRContext, + node: Box, +) -> MaybeDiagnostic { + if let ASTTreeNodeKind::UseStatement { + shards, + use_clauses, + } = node.kind.clone() + { + let mut path = ".".to_string(); + + for shard in shards { + path += &MAIN_SEPARATOR_STR.to_owned(); + path += &shard.val; + } + + path += &".qf"; + + let lexer = lexer_parse_file(&path)?; + let ast = parse_ast_ctx(&lexer)?; + + for clause in use_clauses { + if !ast.map.contains_key(&clause.val) { + return Err(make_use_not_found(&*node, &clause.val, &path).into()); + } + + let n = ast.map[&clause.val].clone(); + + match n.kind { + ASTTreeNodeKind::FunctionDeclaration { .. } => { + handle_ast_use_statement_function_decl(context, n.clone(), &ast)?; + } + _ => { + lower_ast_toplevel(context, n.clone())?; + } + }; + } + + return Ok(()); + } + + panic!("Invalid node") } -pub fn gather_type_use(context: &mut HIRContext, val: HashedString, origin: &K, pass: bool, ctx: &ParserCtx) -> DiagnosticResult { - match context.type_storage.get_type(val.hash) { - Ok(v) => return Ok(v), - Err(_) => { - if pass { - if ctx.map.contains_key(&val.val) { - lower_ast_struct_declaration(context, ctx.map[&val.val].clone())?; - - return gather_type_use(context, val, origin, false, ctx); - } - } - - return Err(make_cannot_find_type(origin, &val.val).into()) - } - } +pub fn gather_type_use( + context: &mut HIRContext, + val: HashedString, + origin: &K, + pass: bool, + ctx: &ParserCtx, +) -> DiagnosticResult { + match context.type_storage.get_type(val.hash) { + Ok(v) => return Ok(v), + Err(_) => { + if pass { + if ctx.map.contains_key(&val.val) { + lower_ast_struct_declaration(context, ctx.map[&val.val].clone())?; + + return gather_type_use(context, val, origin, false, ctx); + } + } + + return Err(make_cannot_find_type(origin, &val.val).into()); + } + } } -pub fn lower_ast_type_use_statement(context: &mut HIRContext, t: ASTType, origin: &K, ctx: &ParserCtx) -> DiagnosticResult { - return match t { - ASTType::Generic(type_id, type_params, size_params, specifier) => { - let val = HashedString::new(type_id.clone()); - let hash = val.hash; - - let mut t = gather_type_use(context, val, origin, true, ctx)?; - - if specifier.is_some() { - let container = match t { - RawType::Enum(v) => v, - _ => return Err(make_req_type_kind(origin, &"enum".to_string()).into()) - }; - - t = container.get_entry(HashedString::new(specifier.unwrap()))? - } - - if t.get_type_params_count(&context.type_storage) != type_params.len() { - return Err(make_diff_type_specifiers(origin, &type_params.len(), &t.get_type_params_count(&context.type_storage)).into()) - } - - let mut t_params = vec![]; - - for type_param in type_params { - t_params.push(Box::new(lower_ast_type(context, *type_param, origin)?)); - } - - let res = Type::Generic(t.clone(), t_params, size_params); - - if t.is_sized() { - let lower = lower_sized_base_type(context, &res, origin)?; - - if context.type_storage.type_to_ind.contains_key(&lower) { - return Ok(Type::Generic(t, vec![], vec![])); - } else { - let ind = match context.type_storage.append_with_hash(hash, lower) { - Ok(v) => v, - Err(_) => panic!("Generic lowering type cannot be found on type_to_hash") - }; - - return Ok(Type::Generic(context.type_storage.types.vals[ind].clone(), vec![], vec![])) - } - } - - return Ok(res); - }, - - ASTType::Pointer(array, inner) => Ok(Type::Pointer(array, Box::new(lower_ast_type(context, *inner, origin)?))), - ASTType::Reference(inner) => Ok(Type::Reference(Box::new(lower_ast_type(context, *inner, origin)?))), - ASTType::Array(size, inner) => Ok(Type::Array(size, Box::new(lower_ast_type(context, *inner, origin)?))) - }; +pub fn lower_ast_type_use_statement( + context: &mut HIRContext, + t: ASTType, + origin: &K, + ctx: &ParserCtx, +) -> DiagnosticResult { + return match t { + ASTType::Generic(type_id, type_params, size_params, specifier) => { + let val = HashedString::new(type_id.clone()); + let hash = val.hash; + + let mut t = gather_type_use(context, val, origin, true, ctx)?; + + if specifier.is_some() { + let container = match t { + RawType::Enum(v) => v, + _ => return Err(make_req_type_kind(origin, &"enum".to_string()).into()), + }; + + t = container.get_entry(HashedString::new(specifier.unwrap()))? + } + + if t.get_type_params_count(&context.type_storage) != type_params.len() { + return Err(make_diff_type_specifiers( + origin, + &type_params.len(), + &t.get_type_params_count(&context.type_storage), + ) + .into()); + } + + let mut t_params = vec![]; + + for type_param in type_params { + t_params.push(Box::new(lower_ast_type(context, *type_param, origin)?)); + } + + let res = Type::Generic(t.clone(), t_params, size_params); + + if t.is_sized() { + let lower = lower_sized_base_type(context, &res, origin)?; + + if context.type_storage.type_to_ind.contains_key(&lower) { + return Ok(Type::Generic(t, vec![], vec![])); + } else { + let ind = match context.type_storage.append_with_hash(hash, lower) { + Ok(v) => v, + Err(_) => panic!("Generic lowering type cannot be found on type_to_hash"), + }; + + return Ok(Type::Generic( + context.type_storage.types.vals[ind].clone(), + vec![], + vec![], + )); + } + } + + return Ok(res); + } + + ASTType::Pointer(array, inner) => Ok(Type::Pointer( + array, + Box::new(lower_ast_type(context, *inner, origin)?), + )), + ASTType::Reference(inner) => Ok(Type::Reference(Box::new(lower_ast_type( + context, *inner, origin, + )?))), + ASTType::Array(size, inner) => Ok(Type::Array( + size, + Box::new(lower_ast_type(context, *inner, origin)?), + )), + }; } diff --git a/compiler/astoir_hir_lowering/src/values.rs b/compiler/astoir_hir_lowering/src/values.rs index 41bfdd0..e52b9ae 100644 --- a/compiler/astoir_hir_lowering/src/values.rs +++ b/compiler/astoir_hir_lowering/src/values.rs @@ -1,237 +1,319 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext, get_variable}, nodes::{HIRNode, HIRNodeKind}, structs::StructLRUStep}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext, get_variable}, + nodes::{HIRNode, HIRNodeKind}, + structs::StructLRUStep, +}; use compiler_typing::tree::Type; -use diagnostics::{DiagnosticResult, builders::{make_cannot_find_func, make_invalid_pointing, make_struct_missing_field, make_struct_missing_func}}; +use diagnostics::{ + DiagnosticResult, + builders::{ + make_cannot_find_func, make_invalid_pointing, make_struct_missing_field, + make_struct_missing_func, + }, +}; + +use crate::{ + arrays::lower_ast_array_index_access, + bools::{lower_ast_boolean_condition, lower_ast_operator_condition}, + func::lower_ast_function_call, + literals::lower_ast_literal, + math::lower_ast_math_operation, + structs::lower_ast_struct_initializer, + unwraps::{lower_ast_condition_unwrap, lower_ast_unwrap_value}, + var::lower_ast_variable_reference, +}; + +pub(crate) fn lower_ast_lru_base( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, + curr_steps: &mut Vec, + curr_type: &mut Option, +) -> DiagnosticResult { + match node.clone().kind { + ASTTreeNodeKind::FunctionCall { func, args } => { + let func_type; + let ind: usize; + + if let Some(curr_type_val) = curr_type { + let res = match curr_type_val.get_function(&context.type_storage, func.hash) { + Ok(v) => v, + Err(_) => { + return Err( + make_struct_missing_func(&*node, curr_type_val, &func.val).into() + ); + } + }; + + let abstract_func = res.1; + + let mut resolved_args = vec![]; + + for arg in abstract_func.0 { + resolved_args.push((arg.0, arg.1.resolve(curr_type_val))); + } + + let resolved_ret; + + if abstract_func.1.is_some() { + resolved_ret = Some(abstract_func.1.unwrap().resolve(curr_type_val)); + } else { + resolved_ret = None; + } + + func_type = (resolved_ret, resolved_args, func.val.clone()); + + ind = res.0; + } else { + ind = match context.functions.get_index(func.hash) { + Some(v) => v, + None => return Err(make_cannot_find_func(&*node, &func.val).into()), + }; + + func_type = context.functions.vals[ind].clone(); + } + + let mut hir_args = vec![]; + let mut iind = 0; + + for a in args { + let lowered = lower_ast_value(context, curr_ctx, a)?; + + let lowered = Box::new(lowered.use_as( + context, + curr_ctx, + func_type.1[iind].1.clone(), + &*node, + None, + )?); + + hir_args.push(lowered); + + iind += 1; + } + + *curr_type = func_type.0.clone(); + + curr_steps.push(StructLRUStep::FunctionCall { + func: ind, + args: hir_args, + }); + + return Ok(true); + } + + ASTTreeNodeKind::VariableReference(str) => { + let var_type; + let ind: usize; + + if let Some(curr_type_val) = curr_type { + let res = match curr_type_val.get_field(&context.type_storage, str.hash) { + Ok(v) => v, + Err(_) => { + return Err( + make_struct_missing_field(&*node, curr_type_val, &str.val).into() + ); + } + }; + + ind = res.0; + var_type = res.1.resolve(curr_type_val); + } else { + let r = get_variable(context, curr_ctx, str.hash, &*node)?; + + ind = r.2; + var_type = r.1; + } + + curr_steps.push(StructLRUStep::VariableStep { variable: ind }); + *curr_type = Some(var_type); + + return Ok(true); + } + + ASTTreeNodeKind::StructLRFunction { l, r } => { + lower_ast_lru_base(context, curr_ctx, l, curr_steps, curr_type)?; + lower_ast_lru_base(context, curr_ctx, r, curr_steps, curr_type)?; -use crate::{arrays::lower_ast_array_index_access, bools::{lower_ast_boolean_condition, lower_ast_operator_condition}, func::lower_ast_function_call, literals::lower_ast_literal, math::lower_ast_math_operation, structs::lower_ast_struct_initializer, unwraps::{lower_ast_condition_unwrap, lower_ast_unwrap_value}, var::lower_ast_variable_reference}; + return Ok(true); + } -pub(crate) fn lower_ast_lru_base(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box, curr_steps: &mut Vec, curr_type: &mut Option) -> DiagnosticResult { - match node.clone().kind { - ASTTreeNodeKind::FunctionCall { func, args } => { - let func_type; - let ind: usize; + ASTTreeNodeKind::StructLRVariable { l, r } => { + lower_ast_lru_base(context, curr_ctx, l, curr_steps, curr_type)?; + lower_ast_lru_base(context, curr_ctx, r, curr_steps, curr_type)?; - if let Some(curr_type_val) = curr_type { - let res = match curr_type_val.get_function(&context.type_storage, func.hash) { - Ok(v) => v, - Err(_) => return Err(make_struct_missing_func(&*node, curr_type_val, &func.val).into()) - }; + return Ok(true); + } - let abstract_func = res.1; - - let mut resolved_args = vec![]; - - for arg in abstract_func.0 { - resolved_args.push((arg.0, arg.1.resolve(curr_type_val))); - } - - let resolved_ret; - - if abstract_func.1.is_some() { - resolved_ret = Some(abstract_func.1.unwrap().resolve(curr_type_val)); - } else { - resolved_ret = None; - } - - func_type = (resolved_ret, resolved_args, func.val.clone()); - - ind = res.0; - - } else { - ind = match context.functions.get_index(func.hash) { - Some(v) => v, - None => return Err(make_cannot_find_func(&*node, &func.val).into()) - }; - - func_type = context.functions.vals[ind].clone(); - } - - let mut hir_args = vec![]; - let mut iind = 0; - - for a in args { - let lowered = lower_ast_value(context, curr_ctx, a)?; - - let lowered = Box::new(lowered.use_as(context, curr_ctx, func_type.1[iind].1.clone(), &*node, None)?); - - hir_args.push(lowered); - - iind += 1; - } - - *curr_type = func_type.0.clone(); - - curr_steps.push(StructLRUStep::FunctionCall { func: ind, args: hir_args }); - - return Ok(true); - }, - - ASTTreeNodeKind::VariableReference(str) => { - let var_type; - let ind: usize; - - if let Some(curr_type_val) = curr_type { - let res = match curr_type_val.get_field(&context.type_storage, str.hash) { - Ok(v) => v, - Err(_) => return Err(make_struct_missing_field(&*node, curr_type_val, &str.val).into()) - }; - - ind = res.0; - var_type = res.1.resolve(curr_type_val); - - } else { - let r = get_variable(context, curr_ctx, str.hash, &*node)?; - - ind = r.2; - var_type = r.1; - } - - curr_steps.push(StructLRUStep::VariableStep { variable: ind }); - *curr_type = Some(var_type); - - return Ok(true) - }, - - ASTTreeNodeKind::StructLRFunction { l, r } => { - lower_ast_lru_base(context, curr_ctx, l, curr_steps, curr_type)?; - lower_ast_lru_base(context, curr_ctx, r, curr_steps, curr_type)?; - - return Ok(true); - }, - - ASTTreeNodeKind::StructLRVariable { l, r } => { - lower_ast_lru_base(context, curr_ctx, l, curr_steps, curr_type)?; - lower_ast_lru_base(context, curr_ctx, r, curr_steps, curr_type)?; - - return Ok(true); - } - - _ => panic!("Invalid node type") - - } + _ => panic!("Invalid node type"), + } } -pub fn lower_ast_lru(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - let mut steps: Vec = vec![]; - let mut curr_type: Option = None; - - lower_ast_lru_base(context, curr_ctx, node.clone(), &mut steps, &mut curr_type)?; - - return Ok(Box::new(HIRNode::new(HIRNodeKind::StructLRU { steps, last: curr_type.unwrap() }, &node.start, &node.end))) +pub fn lower_ast_lru( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + let mut steps: Vec = vec![]; + let mut curr_type: Option = None; + + lower_ast_lru_base(context, curr_ctx, node.clone(), &mut steps, &mut curr_type)?; + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::StructLRU { + steps, + last: curr_type.unwrap(), + }, + &node.start, + &node.end, + ))); } -pub fn lower_ast_value(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - match node.kind { - ASTTreeNodeKind::StructLRFunction { .. } | ASTTreeNodeKind::StructLRVariable { .. } => { - return lower_ast_lru(context, curr_ctx, node); - }, +pub fn lower_ast_value( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + match node.kind { + ASTTreeNodeKind::StructLRFunction { .. } | ASTTreeNodeKind::StructLRVariable { .. } => { + return lower_ast_lru(context, curr_ctx, node); + } - ASTTreeNodeKind::MathResult { .. } => { - return lower_ast_math_operation(context, curr_ctx, node, false) - }, + ASTTreeNodeKind::MathResult { .. } => { + return lower_ast_math_operation(context, curr_ctx, node, false); + } - ASTTreeNodeKind::OperatorBasedConditionMember { .. } => { - return lower_ast_operator_condition(context, curr_ctx, node) - }, + ASTTreeNodeKind::OperatorBasedConditionMember { .. } => { + return lower_ast_operator_condition(context, curr_ctx, node); + } - ASTTreeNodeKind::BooleanBasedConditionMember { .. } => { - return lower_ast_boolean_condition(context, curr_ctx, node) - }, + ASTTreeNodeKind::BooleanBasedConditionMember { .. } => { + return lower_ast_boolean_condition(context, curr_ctx, node); + } - ASTTreeNodeKind::ArrayIndexAccess { .. } => { - return lower_ast_array_index_access(context, curr_ctx, node) - } + ASTTreeNodeKind::ArrayIndexAccess { .. } => { + return lower_ast_array_index_access(context, curr_ctx, node); + } - ASTTreeNodeKind::ArrayVariableInitializerValue { .. } | ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { .. } => { - return lower_ast_array_init(context, curr_ctx, node) - } + ASTTreeNodeKind::ArrayVariableInitializerValue { .. } + | ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { .. } => { + return lower_ast_array_init(context, curr_ctx, node); + } - ASTTreeNodeKind::StructInitializer { .. } => { - return lower_ast_struct_initializer(context, curr_ctx, node) - } + ASTTreeNodeKind::StructInitializer { .. } => { + return lower_ast_struct_initializer(context, curr_ctx, node); + } - ASTTreeNodeKind::IntegerLit { .. } | ASTTreeNodeKind::StringLit(_) => { - return lower_ast_literal(context, node); - }, + ASTTreeNodeKind::IntegerLit { .. } | ASTTreeNodeKind::StringLit(_) => { + return lower_ast_literal(context, node); + } - ASTTreeNodeKind::FunctionCall { .. } => { - return lower_ast_function_call(context, curr_ctx, node); - } + ASTTreeNodeKind::FunctionCall { .. } => { + return lower_ast_function_call(context, curr_ctx, node); + } - ASTTreeNodeKind::VariableReference(_) => { - return lower_ast_variable_reference(context, curr_ctx, node, true) - }, + ASTTreeNodeKind::VariableReference(_) => { + return lower_ast_variable_reference(context, curr_ctx, node, true); + } - ASTTreeNodeKind::PointerGrab(_) => { - return lower_ast_pointer(context, curr_ctx, node) - }, + ASTTreeNodeKind::PointerGrab(_) => return lower_ast_pointer(context, curr_ctx, node), - ASTTreeNodeKind::ReferenceGrab(_) => { - return lower_ast_reference(context, curr_ctx, node) - }, + ASTTreeNodeKind::ReferenceGrab(_) => return lower_ast_reference(context, curr_ctx, node), - ASTTreeNodeKind::UnwrapCondition { .. } => { - return lower_ast_condition_unwrap(context, curr_ctx, node) - }, + ASTTreeNodeKind::UnwrapCondition { .. } => { + return lower_ast_condition_unwrap(context, curr_ctx, node); + } - ASTTreeNodeKind::UnwrapValue { .. } => { - return lower_ast_unwrap_value(context, curr_ctx, node) - }, + ASTTreeNodeKind::UnwrapValue { .. } => { + return lower_ast_unwrap_value(context, curr_ctx, node); + } - _ => panic!("Invalid AST value node") - } + _ => panic!("Invalid AST value node"), + } } -pub fn lower_ast_array_init(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::ArrayVariableInitializerValue { vals } = node.kind.clone() { - let mut values = vec![]; - - for val in vals { - values.push(lower_ast_value(context, curr_ctx, val)?); - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::ArrayVariableInitializerValue { vals: values }, &node.start, &node.end))) - } - - if let ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { size, v } = node.kind { - return Ok(Box::new(HIRNode::new(HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val: lower_ast_value(context, curr_ctx, v)? }, &node.start, &node.end))) - } - - panic!("Invalid node") +pub fn lower_ast_array_init( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::ArrayVariableInitializerValue { vals } = node.kind.clone() { + let mut values = vec![]; + + for val in vals { + values.push(lower_ast_value(context, curr_ctx, val)?); + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ArrayVariableInitializerValue { vals: values }, + &node.start, + &node.end, + ))); + } + + if let ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { size, v } = node.kind { + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ArrayVariableInitializerValueSameValue { + size, + val: lower_ast_value(context, curr_ctx, v)?, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node") } -pub fn lower_ast_pointer(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::PointerGrab(val) = node.kind.clone() { - let val = lower_ast_value(context, curr_ctx, val)?; +pub fn lower_ast_pointer( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::PointerGrab(val) = node.kind.clone() { + let val = lower_ast_value(context, curr_ctx, val)?; - if !val.is_variable_representative() { - return Err(make_invalid_pointing(&*node).into()) - } - - let r = val.get_variable_represent(); + if !val.is_variable_representative() { + return Err(make_invalid_pointing(&*node).into()); + } - curr_ctx.introduce_variable_refer(r.0); + let r = val.get_variable_represent(); - return Ok(Box::new(HIRNode::new(HIRNodeKind::PointerGrab { val }, &node.start, &node.end))) - } + curr_ctx.introduce_variable_refer(r.0); - panic!("Invalid node") + return Ok(Box::new(HIRNode::new( + HIRNodeKind::PointerGrab { val }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node") } -pub fn lower_ast_reference(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::ReferenceGrab(val) = node.kind.clone() { - let val = lower_ast_value(context, curr_ctx, val)?; +pub fn lower_ast_reference( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::ReferenceGrab(val) = node.kind.clone() { + let val = lower_ast_value(context, curr_ctx, val)?; - if !val.is_variable_representative() { - return Err(make_invalid_pointing(&*node).into()) - } + if !val.is_variable_representative() { + return Err(make_invalid_pointing(&*node).into()); + } - let r = val.get_variable_represent(); + let r = val.get_variable_represent(); - curr_ctx.introduce_variable_refer(r.0); + curr_ctx.introduce_variable_refer(r.0); - return Ok(Box::new(HIRNode::new(HIRNodeKind::ReferenceGrab { val }, &node.start, &node.end))) - } + return Ok(Box::new(HIRNode::new( + HIRNodeKind::ReferenceGrab { val }, + &node.start, + &node.end, + ))); + } - panic!("Invalid node") -} \ No newline at end of file + panic!("Invalid node") +} diff --git a/compiler/astoir_hir_lowering/src/var.rs b/compiler/astoir_hir_lowering/src/var.rs index 3c389e1..2e4b970 100644 --- a/compiler/astoir_hir_lowering/src/var.rs +++ b/compiler/astoir_hir_lowering/src/var.rs @@ -1,71 +1,140 @@ -use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}}; -use astoir_hir::{ctx::{HIRBranchedContext, HIRContext, VariableKind, get_variable}, nodes::{HIRNode, HIRNodeKind}}; +use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; +use astoir_hir::{ + ctx::{HIRBranchedContext, HIRContext, VariableKind, get_variable}, + nodes::{HIRNode, HIRNodeKind}, +}; use diagnostics::{DiagnosticResult, builders::make_variable_uninit}; use crate::{arrays::lower_ast_array_index_access, types::lower_ast_type, values::lower_ast_value}; -pub fn lower_ast_variable_declaration(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::VarDeclaration { var_name, var_type, value} = node.kind.clone() { - let lowered = lower_ast_type(context, var_type, &*node)?; - - let name_ind = curr_ctx.introduce_variable(var_name.hash, lowered.clone(), value.is_some())?; - - let default_val; - - if value.is_some() { - let hir_val = Box::new(lower_ast_value(context, curr_ctx, value.unwrap())?.use_as(context, curr_ctx, lowered.clone(), &*node, None)?); - - default_val = Some(hir_val); - } else { - default_val = None; - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::VarDeclaration { variable: name_ind, var_type: lowered, default_val}, &node.start, &node.end))) - } - - panic!("Invalid node passed!"); +pub fn lower_ast_variable_declaration( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::VarDeclaration { + var_name, + var_type, + value, + } = node.kind.clone() + { + let lowered = lower_ast_type(context, var_type, &*node)?; + + let name_ind = + curr_ctx.introduce_variable(var_name.hash, lowered.clone(), value.is_some())?; + + let default_val; + + if value.is_some() { + let hir_val = Box::new(lower_ast_value(context, curr_ctx, value.unwrap())?.use_as( + context, + curr_ctx, + lowered.clone(), + &*node, + None, + )?); + + default_val = Some(hir_val); + } else { + default_val = None; + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::VarDeclaration { + variable: name_ind, + var_type: lowered, + default_val, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node passed!"); } -pub fn lower_ast_variable_reference(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box, requires_value: bool) -> DiagnosticResult> { - if let ASTTreeNodeKind::VariableReference(str) = node.kind.clone() { - let var = get_variable(context, curr_ctx, str.hash, &*node)?; - - if var.0 == VariableKind::STATIC { - return Ok(Box::new(HIRNode::new(HIRNodeKind::VariableReference { index: var.2, is_static: true }, &node.start, &node.end))) - } - - if requires_value { - if !curr_ctx.has_variable_value(var.2) { - return Err(make_variable_uninit(&*node, &str.val).into()) - } - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::VariableReference { index: var.2, is_static: false }, &node.start, &node.end))) - } - - if let ASTTreeNodeKind::ArrayIndexAccess { .. } = node.kind.clone() { - return lower_ast_array_index_access(context, curr_ctx, node) - } - - panic!("Invalid node passed!"); +pub fn lower_ast_variable_reference( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, + requires_value: bool, +) -> DiagnosticResult> { + if let ASTTreeNodeKind::VariableReference(str) = node.kind.clone() { + let var = get_variable(context, curr_ctx, str.hash, &*node)?; + + if var.0 == VariableKind::STATIC { + return Ok(Box::new(HIRNode::new( + HIRNodeKind::VariableReference { + index: var.2, + is_static: true, + }, + &node.start, + &node.end, + ))); + } + + if requires_value { + if !curr_ctx.has_variable_value(var.2) { + return Err(make_variable_uninit(&*node, &str.val).into()); + } + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::VariableReference { + index: var.2, + is_static: false, + }, + &node.start, + &node.end, + ))); + } + + if let ASTTreeNodeKind::ArrayIndexAccess { .. } = node.kind.clone() { + return lower_ast_array_index_access(context, curr_ctx, node); + } + + panic!("Invalid node passed!"); } -pub fn lower_ast_variable_assign(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { - 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.clone(), false)?; - - let value = Box::new(value.use_as(context, curr_ctx, variable_reference.get_node_type(context, curr_ctx).unwrap().get_maybe_containing_type(), &*var, Some(&*node))?); - - let var = variable_reference.as_variable_reference(); - - if !var.1 { - curr_ctx.introduce_variable_assign(var.0); - } - - return Ok(Box::new(HIRNode::new(HIRNodeKind::VarAssigment { variable: var.0, val: value }, &node.start, &node.end))) - } - - panic!("Invalid node passed!"); -} \ No newline at end of file +pub fn lower_ast_variable_assign( + context: &mut HIRContext, + curr_ctx: &mut HIRBranchedContext, + node: Box, +) -> DiagnosticResult> { + 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.clone(), false)?; + + let value = Box::new( + value.use_as( + context, + curr_ctx, + variable_reference + .get_node_type(context, curr_ctx) + .unwrap() + .get_maybe_containing_type(), + &*var, + Some(&*node), + )?, + ); + + let var = variable_reference.as_variable_reference(); + + if !var.1 { + curr_ctx.introduce_variable_assign(var.0); + } + + return Ok(Box::new(HIRNode::new( + HIRNodeKind::VarAssigment { + variable: var.0, + val: value, + }, + &node.start, + &node.end, + ))); + } + + panic!("Invalid node passed!"); +} diff --git a/compiler/astoir_mir/src/blocks/hints.rs b/compiler/astoir_mir/src/blocks/hints.rs index f5a8f39..744e8d5 100644 --- a/compiler/astoir_mir/src/blocks/hints.rs +++ b/compiler/astoir_mir/src/blocks/hints.rs @@ -1,111 +1,108 @@ use compiler_typing::tree::Type; use diagnostics::unsure_panic; -use crate::{vals::consts::MIRConstantValue}; - +use crate::vals::consts::MIRConstantValue; /// A hint on a given value, contains constants or pointer types for example #[derive(Clone, Debug)] pub enum MIRValueHint { - Constant(MIRConstantValue), - Pointer(Type), - Value(Type) + Constant(MIRConstantValue), + Pointer(Type), + Value(Type), } impl MIRValueHint { - pub fn is_determined(&self) -> bool { - if let &MIRValueHint::Constant(_) = self { - return true; - } - - return false; - } - - pub fn is_pointer(&self) -> bool { - if let &MIRValueHint::Pointer(_) = self { - return true; - } - - return false; - } - - pub fn as_const(&self) -> MIRConstantValue { - match self { - MIRValueHint::Constant(e) => e.clone(), - _ => unsure_panic!("cannot use as_const on a non const!") - } - } - - pub fn get_type(&self) -> Type { - match self { - MIRValueHint::Pointer(e) => e.clone(), - MIRValueHint::Value(e) => e.clone(), - _ => unsure_panic!("cannot use get_type on a non typed hint") - } - } - - pub fn as_pointer(&self) -> Type { - match self { - MIRValueHint::Pointer(e) => e.clone(), - _ => unsure_panic!("Cannot use as_pointer on a non pointer!") - } - } - - pub fn as_value(&self) -> Type { - match self { - MIRValueHint::Value(e) => e.clone(), - _ => unsure_panic!("Cannot use as_value on a non value!") - } - } - - pub fn from_ptr(val: Type) -> Self { - return MIRValueHint::Pointer(val) - } - + pub fn is_determined(&self) -> bool { + if let &MIRValueHint::Constant(_) = self { + return true; + } + + return false; + } + + pub fn is_pointer(&self) -> bool { + if let &MIRValueHint::Pointer(_) = self { + return true; + } + + return false; + } + + pub fn as_const(&self) -> MIRConstantValue { + match self { + MIRValueHint::Constant(e) => e.clone(), + _ => unsure_panic!("cannot use as_const on a non const!"), + } + } + + pub fn get_type(&self) -> Type { + match self { + MIRValueHint::Pointer(e) => e.clone(), + MIRValueHint::Value(e) => e.clone(), + _ => unsure_panic!("cannot use get_type on a non typed hint"), + } + } + + pub fn as_pointer(&self) -> Type { + match self { + MIRValueHint::Pointer(e) => e.clone(), + _ => unsure_panic!("Cannot use as_pointer on a non pointer!"), + } + } + + pub fn as_value(&self) -> Type { + match self { + MIRValueHint::Value(e) => e.clone(), + _ => unsure_panic!("Cannot use as_value on a non value!"), + } + } + + pub fn from_ptr(val: Type) -> Self { + return MIRValueHint::Pointer(val); + } } impl Into for MIRConstantValue { - fn into(self) -> MIRValueHint { - return MIRValueHint::Constant(self) - } + fn into(self) -> MIRValueHint { + return MIRValueHint::Constant(self); + } } impl Into for Type { - fn into(self) -> MIRValueHint { - return MIRValueHint::Value(self) - } + fn into(self) -> MIRValueHint { + return MIRValueHint::Value(self); + } } pub struct HintStorage { - pub vec: Vec, + pub vec: Vec, } impl HintStorage { - pub fn new() -> Self { - HintStorage { vec: vec![] } - } - - - /// Introduces a new SSA value hint. Returns the hint index. - /// # Usage - /// Every single SSA value should have a hint on what it is. Furthermore, this hint index will be used to identify the different SSA values instead of raw instruction indexes. - /// - /// # Globality - /// Using hint indexes to represent different SSA values allows us to guarantee that SSA values will work on inner blocks. - pub fn append_hint(&mut self, hint: MIRValueHint) -> usize { - let ind = self.vec.len(); - - self.vec.push(hint); - - return ind; - } - - /// Gets the hint based on the hint index. - pub fn get_hint(&self, hint_ind: usize) -> MIRValueHint { - if self.vec.len() <= hint_ind { - unsure_panic!("invalid hint provided"); - } - - return self.vec[hint_ind].clone() - } -} \ No newline at end of file + pub fn new() -> Self { + HintStorage { vec: vec![] } + } + + /// Introduces a new SSA value hint. Returns the hint index. + /// # Usage + /// Every single SSA value should have a hint on what it is. Furthermore, this hint index will be used to identify the different SSA values instead of raw instruction indexes. + /// + /// # Globality + /// Using hint indexes to represent different SSA values allows us to guarantee that SSA values will work on inner blocks. + pub fn append_hint(&mut self, hint: MIRValueHint) -> usize { + let ind = self.vec.len(); + + self.vec.push(hint); + + return ind; + } + + /// Gets the hint based on the hint index. + pub fn get_hint(&self, hint_ind: usize) -> MIRValueHint { + if self.vec.len() <= hint_ind { + unsure_panic!("invalid hint provided"); + } + + return self.vec[hint_ind].clone(); + } +} diff --git a/compiler/astoir_mir/src/blocks/mod.rs b/compiler/astoir_mir/src/blocks/mod.rs index c5dcf0b..0e1109f 100644 --- a/compiler/astoir_mir/src/blocks/mod.rs +++ b/compiler/astoir_mir/src/blocks/mod.rs @@ -2,196 +2,212 @@ use std::{collections::HashMap, fmt::Display}; use diagnostics::{DiagnosticResult, unsure_panic}; -use crate::{blocks::refer::MIRBlockReference, builder::build_phi, ctx::MIRContext, inst_writer::BlockPosition, insts::MIRInstruction, vals::{base::BaseMIRValue, refer::MIRVariableReference}}; +use crate::{ + blocks::refer::MIRBlockReference, + builder::build_phi, + ctx::MIRContext, + inst_writer::BlockPosition, + insts::MIRInstruction, + vals::{base::BaseMIRValue, refer::MIRVariableReference}, +}; -pub mod refer; pub mod hints; +pub mod refer; /// The type of variable inside of a MIR block. #[derive(Clone, PartialEq)] pub enum MIRBlockVariableType { - /// SSAs, allow for direct register usage. - /// Requires: - /// - Variable's address not being obtained (value never referenced) - SSA, - - /// Pointer value, uses the stack. - /// Should be used incase SSA fails. - Pointer + /// SSAs, allow for direct register usage. + /// Requires: + /// - Variable's address not being obtained (value never referenced) + SSA, + + /// Pointer value, uses the stack. + /// Should be used incase SSA fails. + Pointer, } #[derive(Clone)] pub struct MIRBlockVariableSSAHint { - pub kind: MIRBlockVariableType, - pub hint: Option + pub kind: MIRBlockVariableType, + pub hint: Option, } impl PartialEq for MIRBlockVariableSSAHint { - fn eq(&self, other: &Self) -> bool { - return self.kind == other.kind && self.hint == other.hint; - } + fn eq(&self, other: &Self) -> bool { + return self.kind == other.kind && self.hint == other.hint; + } } #[derive(Clone)] pub enum MIRBlockHeldInstruction { - Valueless(MIRInstruction), - Valued(MIRInstruction, usize) + Valueless(MIRInstruction), + Valued(MIRInstruction, usize), } -impl Into for MIRBlockHeldInstruction { - fn into(self) -> MIRInstruction { - return match self { - Self::Valueless(e) => e, - Self::Valued(e, _) => e - } - } +impl Into for MIRBlockHeldInstruction { + fn into(self) -> MIRInstruction { + return match self { + Self::Valueless(e) => e, + Self::Valued(e, _) => e, + }; + } } impl MIRBlockHeldInstruction { - pub fn as_valuedindex(&self) -> usize { - return match self { - Self::Valued(_, b) => *b, - _ => unsure_panic!("as_valuedindex requires a valued!") - } - } + pub fn as_valuedindex(&self) -> usize { + return match self { + Self::Valued(_, b) => *b, + _ => unsure_panic!("as_valuedindex requires a valued!"), + }; + } } /// Represents a function block or a branch. pub struct MIRBlock { - pub instructions: Vec, + pub instructions: Vec, - /// The block references that will merge into this one - pub merge_blocks: Vec, + /// The block references that will merge into this one + pub merge_blocks: Vec, - pub self_ref: MIRBlockReference, + pub self_ref: MIRBlockReference, - /// Hints for the index of the SSA value for the given variable. Will be the pointer value if the variable is not SSA. - /// The indexes used are the variable indexes and not the SSA indexes. - pub variables: HashMap + /// Hints for the index of the SSA value for the given variable. Will be the pointer value if the variable is not SSA. + /// The indexes used are the variable indexes and not the SSA indexes. + pub variables: HashMap, } impl MIRBlock { - pub fn new(self_ref: MIRBlockReference) -> Self { - MIRBlock { instructions: vec![], variables: HashMap::new(), merge_blocks: vec![], self_ref } - } - - pub fn new_merge(base: MIRBlockReference, ctx: &mut MIRContext, append_to_merge_blocks: bool) -> MIRBlockReference { - let ind = ctx.create_block(ctx.get_func_from_block(base)); - - let variables = ctx.blocks[base].variables.clone(); - - let block = &mut ctx.blocks[ind]; - - for (ind, hint) in variables { - block.variables.insert(ind, hint); - } - - if append_to_merge_blocks { - ctx.blocks[base].merge_blocks.push(ind) - } - - return ind; - } - - pub fn get_variable_ref(&self, var_ind: usize) -> DiagnosticResult { - let var = &self.variables[&var_ind]; - - if var.kind == MIRBlockVariableType::SSA { - return Ok(MIRVariableReference::from(var_ind)); - } - - let unpacked = match &var.hint { - Some(v) => v.clone(), - None => unsure_panic!("missing BaseMIRValue in pointer hint") - }; - - return Ok(MIRVariableReference::from(unpacked.as_ptr()?)); - } - - pub fn append(&mut self, instruction: MIRBlockHeldInstruction, pos: &BlockPosition) { - match pos { - BlockPosition::END => { - self.instructions.push(instruction.clone()); - }, - - BlockPosition::START => { - if self.instructions.is_empty() { - self.instructions.push(instruction.clone()); - } else { - self.instructions.insert(0, instruction.clone()); - } - } - } - } - - /// Resolves changes in SSA handled variables from the different merge blocks. - /// - /// # Behavior - /// First checks inside of every merge blocks for changes of SSA values for variables in the hinting table. - /// Then uses a `phi` instruction to obtain the SSA values in this block. Also automatically updates the variable hints inside of this block. - /// - pub fn resolve_ssa_changes(&mut self, ctx: &mut MIRContext) -> DiagnosticResult { - let mut vals = vec![]; - - for (ind, hint) in self.variables.iter() { - let mut choices: Vec<(MIRBlockReference, BaseMIRValue)> = vec![]; - - for block_ref in &self.merge_blocks { - let block = &ctx.blocks[*block_ref]; - let block_hint = &block.variables[ind]; - - if hint != block_hint && block_hint.hint.is_some() { - choices.push((*block_ref, block_hint.hint.clone().unwrap())); - } - } - - vals.push((*ind, choices)); - } - - ctx.writer.move_end(self.self_ref); - - for val in vals { - let res = build_phi(ctx, val.1)?; - - let mut hint = self.variables[&val.0].clone(); - hint.hint = Some(res); - - self.variables.insert(val.0, hint); - } - - return Ok(true); - } - - pub fn is_empty(&self) -> bool { - return self.instructions.is_empty(); - } + pub fn new(self_ref: MIRBlockReference) -> Self { + MIRBlock { + instructions: vec![], + variables: HashMap::new(), + merge_blocks: vec![], + self_ref, + } + } + + pub fn new_merge( + base: MIRBlockReference, + ctx: &mut MIRContext, + append_to_merge_blocks: bool, + ) -> MIRBlockReference { + let ind = ctx.create_block(ctx.get_func_from_block(base)); + + let variables = ctx.blocks[base].variables.clone(); + + let block = &mut ctx.blocks[ind]; + + for (ind, hint) in variables { + block.variables.insert(ind, hint); + } + + if append_to_merge_blocks { + ctx.blocks[base].merge_blocks.push(ind) + } + + return ind; + } + + pub fn get_variable_ref(&self, var_ind: usize) -> DiagnosticResult { + let var = &self.variables[&var_ind]; + + if var.kind == MIRBlockVariableType::SSA { + return Ok(MIRVariableReference::from(var_ind)); + } + + let unpacked = match &var.hint { + Some(v) => v.clone(), + None => unsure_panic!("missing BaseMIRValue in pointer hint"), + }; + + return Ok(MIRVariableReference::from(unpacked.as_ptr()?)); + } + + pub fn append(&mut self, instruction: MIRBlockHeldInstruction, pos: &BlockPosition) { + match pos { + BlockPosition::END => { + self.instructions.push(instruction.clone()); + } + + BlockPosition::START => { + if self.instructions.is_empty() { + self.instructions.push(instruction.clone()); + } else { + self.instructions.insert(0, instruction.clone()); + } + } + } + } + + /// Resolves changes in SSA handled variables from the different merge blocks. + /// + /// # Behavior + /// First checks inside of every merge blocks for changes of SSA values for variables in the hinting table. + /// Then uses a `phi` instruction to obtain the SSA values in this block. Also automatically updates the variable hints inside of this block. + /// + pub fn resolve_ssa_changes(&mut self, ctx: &mut MIRContext) -> DiagnosticResult { + let mut vals = vec![]; + + for (ind, hint) in self.variables.iter() { + let mut choices: Vec<(MIRBlockReference, BaseMIRValue)> = vec![]; + + for block_ref in &self.merge_blocks { + let block = &ctx.blocks[*block_ref]; + let block_hint = &block.variables[ind]; + + if hint != block_hint && block_hint.hint.is_some() { + choices.push((*block_ref, block_hint.hint.clone().unwrap())); + } + } + + vals.push((*ind, choices)); + } + + ctx.writer.move_end(self.self_ref); + + for val in vals { + let res = build_phi(ctx, val.1)?; + + let mut hint = self.variables[&val.0].clone(); + hint.hint = Some(res); + + self.variables.insert(val.0, hint); + } + + return Ok(true); + } + + pub fn is_empty(&self) -> bool { + return self.instructions.is_empty(); + } } impl Display for MIRBlock { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "%block_{}", self.self_ref)?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "%block_{}", self.self_ref)?; - if !self.merge_blocks.is_empty() { - writeln!(f, "merge_blocks")?; + if !self.merge_blocks.is_empty() { + writeln!(f, "merge_blocks")?; - for block in &self.merge_blocks { - writeln!(f, "- {}", block)?; - } - } + for block in &self.merge_blocks { + writeln!(f, "- {}", block)?; + } + } - for inst in &self.instructions { - write!(f, " {}", inst)?; - } + for inst in &self.instructions { + write!(f, " {}", inst)?; + } - Ok(()) - } + Ok(()) + } } impl Display for MIRBlockHeldInstruction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Valued(a, b) => write!(f, "#{} = {}", *b, a), - Self::Valueless(a) => write!(f, "{}", a) - } - } -} \ No newline at end of file + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Valued(a, b) => write!(f, "#{} = {}", *b, a), + Self::Valueless(a) => write!(f, "{}", a), + } + } +} diff --git a/compiler/astoir_mir/src/blocks/refer.rs b/compiler/astoir_mir/src/blocks/refer.rs index 72858e4..795a242 100644 --- a/compiler/astoir_mir/src/blocks/refer.rs +++ b/compiler/astoir_mir/src/blocks/refer.rs @@ -1 +1 @@ -pub type MIRBlockReference = usize; \ No newline at end of file +pub type MIRBlockReference = usize; diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 7dad142..2da1ef7 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -3,521 +3,924 @@ use compiler_typing::{SizedType, raw::RawType, storage::TypeStorage, tree::Type}; use diagnostics::{DiagnosticResult, MaybeDiagnostic, unsure_panic}; -use crate::{blocks::{hints::MIRValueHint, refer::MIRBlockReference}, ctx::MIRContext, insts::MIRInstruction, vals::{arrays::MIRArrayValue, base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue, structs::MIRStructValue}}; - -pub fn build_stack_alloc(ctx: &mut MIRContext, size: usize, t: Type) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::StackAlloc { alloc_size: size, t: t.clone() }).get()?; - - let hint = ctx.ssa_hints.append_hint(MIRValueHint::Pointer(t)); - - if res.get_ssa_index() != hint { - unsure_panic!("coudln't hint SSA value for pointers! indexes are different"); - } - - return res.as_ptr() +use crate::{ + blocks::{hints::MIRValueHint, refer::MIRBlockReference}, + ctx::MIRContext, + insts::MIRInstruction, + vals::{ + arrays::MIRArrayValue, base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, + ptr::MIRPointerValue, structs::MIRStructValue, + }, +}; + +pub fn build_stack_alloc( + ctx: &mut MIRContext, + size: usize, + t: Type, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::StackAlloc { + alloc_size: size, + t: t.clone(), + }) + .get()?; + + let hint = ctx.ssa_hints.append_hint(MIRValueHint::Pointer(t)); + + if res.get_ssa_index() != hint { + unsure_panic!("coudln't hint SSA value for pointers! indexes are different"); + } + + return res.as_ptr(); } pub fn build_load(ctx: &mut MIRContext, ptr: MIRPointerValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::Load { value: ptr }).get()?; - - return Ok(res); -} - -pub fn build_store(ctx: &mut MIRContext, storage: &TypeStorage, ptr: MIRPointerValue, val: BaseMIRValue) -> DiagnosticResult<()> { - let base: BaseMIRValue = ptr.clone().into(); - - let hint = ctx.ssa_hints.get_hint(base.get_ssa_index()).get_type(); - - if !hint.get_maybe_containing_type().is_truly_eq(&val.vtype) && !hint.is_ptr() { - if hint.get_maybe_containing_type().get_generic(storage).is_enum_parent() && val.vtype.get_generic(storage).is_enum_child() { - return build_store_fallback(ctx, ptr, val.clone(), storage) - } - - unsure_panic!("cannot put this value onto this pointer since it's not the type"); - } - - ctx.append_inst(MIRInstruction::Store { variable: ptr, value: val }); - - return Ok(()) -} - -pub fn build_downcast_int(ctx: &mut MIRContext, val: MIRIntValue, size: usize) -> DiagnosticResult { - if val.size <= size { - unsure_panic!("tried downcasting a smaller int"); - } - - let res = ctx.append_inst(MIRInstruction::DowncastInteger { val, size }).get()?; - - return res.as_int(); -} - -pub fn build_upcast_int(ctx: &mut MIRContext, val: MIRIntValue, size: usize) -> DiagnosticResult { - if val.size >= size { - unsure_panic!("tried upcasting on a higher sized int"); - } - - let res = ctx.append_inst(MIRInstruction::UpcastInteger { val, size }).get()?; - - return res.as_int(); -} - -pub fn build_downcast_float(ctx: &mut MIRContext, val: MIRFloatValue, size: usize) -> DiagnosticResult { - if val.size <= size { - unsure_panic!("tried downcasting on a smaller sized float"); - } - - let res = ctx.append_inst(MIRInstruction::DowncastFloat { val, size }).get()?; - - return res.as_float(); -} - -pub fn build_upcast_float(ctx: &mut MIRContext, val: MIRFloatValue, size: usize) -> DiagnosticResult { - if val.size >= size { - unsure_panic!("tried upcasting on a higher sized float"); - } - - let res = ctx.append_inst(MIRInstruction::UpcastFloat { val, size }).get()?; - - return res.as_float(); -} - -pub fn build_int_add(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using iadd on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::IntegerAdd { signed, fast, left, right }).get()?; - - return res.as_int(); -} - -pub fn build_int_sub(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using isub on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::IntegerSub { signed, fast, left, right }).get()?; - - return res.as_int(); -} - -pub fn build_int_mul(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using imul on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::IntegerMul { signed, fast, left, right }).get()?; - - return res.as_int(); -} - -pub fn build_int_div(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using idiv on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::IntegerDiv { signed, fast, left, right }).get()?; - - return res.as_int(); -} - -pub fn build_int_mod(ctx: &mut MIRContext, left: MIRIntValue, right: MIRIntValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using imod on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::IntegerMod { signed, fast, left, right }).get()?; - - return res.as_int(); -} - -pub fn build_int_shift_left(ctx: &mut MIRContext, left: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::ShiftLeft { a: left, shift }).get()?; + let res = ctx.append_inst(MIRInstruction::Load { value: ptr }).get()?; - return res.as_int(); + return Ok(res); } -pub fn build_int_shift_right(ctx: &mut MIRContext, left: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::ShiftRight { a: left, shift }).get()?; - - return res.as_int(); +pub fn build_store( + ctx: &mut MIRContext, + storage: &TypeStorage, + ptr: MIRPointerValue, + val: BaseMIRValue, +) -> DiagnosticResult<()> { + let base: BaseMIRValue = ptr.clone().into(); + + let hint = ctx.ssa_hints.get_hint(base.get_ssa_index()).get_type(); + + if !hint.get_maybe_containing_type().is_truly_eq(&val.vtype) && !hint.is_ptr() { + if hint + .get_maybe_containing_type() + .get_generic(storage) + .is_enum_parent() + && val.vtype.get_generic(storage).is_enum_child() + { + return build_store_fallback(ctx, ptr, val.clone(), storage); + } + + unsure_panic!("cannot put this value onto this pointer since it's not the type"); + } + + ctx.append_inst(MIRInstruction::Store { + variable: ptr, + value: val, + }); + + return Ok(()); +} + +pub fn build_downcast_int( + ctx: &mut MIRContext, + val: MIRIntValue, + size: usize, +) -> DiagnosticResult { + if val.size <= size { + unsure_panic!("tried downcasting a smaller int"); + } + + let res = ctx + .append_inst(MIRInstruction::DowncastInteger { val, size }) + .get()?; + + return res.as_int(); +} + +pub fn build_upcast_int( + ctx: &mut MIRContext, + val: MIRIntValue, + size: usize, +) -> DiagnosticResult { + if val.size >= size { + unsure_panic!("tried upcasting on a higher sized int"); + } + + let res = ctx + .append_inst(MIRInstruction::UpcastInteger { val, size }) + .get()?; + + return res.as_int(); +} + +pub fn build_downcast_float( + ctx: &mut MIRContext, + val: MIRFloatValue, + size: usize, +) -> DiagnosticResult { + if val.size <= size { + unsure_panic!("tried downcasting on a smaller sized float"); + } + + let res = ctx + .append_inst(MIRInstruction::DowncastFloat { val, size }) + .get()?; + + return res.as_float(); +} + +pub fn build_upcast_float( + ctx: &mut MIRContext, + val: MIRFloatValue, + size: usize, +) -> DiagnosticResult { + if val.size >= size { + unsure_panic!("tried upcasting on a higher sized float"); + } + + let res = ctx + .append_inst(MIRInstruction::UpcastFloat { val, size }) + .get()?; + + return res.as_float(); +} + +pub fn build_int_add( + ctx: &mut MIRContext, + left: MIRIntValue, + right: MIRIntValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using iadd on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::IntegerAdd { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_int_sub( + ctx: &mut MIRContext, + left: MIRIntValue, + right: MIRIntValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using isub on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::IntegerSub { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_int_mul( + ctx: &mut MIRContext, + left: MIRIntValue, + right: MIRIntValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using imul on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::IntegerMul { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_int_div( + ctx: &mut MIRContext, + left: MIRIntValue, + right: MIRIntValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using idiv on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::IntegerDiv { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_int_mod( + ctx: &mut MIRContext, + left: MIRIntValue, + right: MIRIntValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using imod on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::IntegerMod { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_int_shift_left( + ctx: &mut MIRContext, + left: MIRIntValue, + shift: MIRIntValue, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::ShiftLeft { a: left, shift }) + .get()?; + + return res.as_int(); +} + +pub fn build_int_shift_right( + ctx: &mut MIRContext, + left: MIRIntValue, + shift: MIRIntValue, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::ShiftRight { a: left, shift }) + .get()?; + + return res.as_int(); } pub fn build_int_neg(ctx: &mut MIRContext, val: MIRIntValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::IntegerNeg { val }).get()?; - - return res.as_int(); -} - -pub fn build_float_add(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using fadd on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::FloatAdd { signed, fast, left, right }).get()?; - - return res.as_float(); -} - -pub fn build_float_sub(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using fsub on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::FloatSub { signed, fast, left, right }).get()?; - - return res.as_float(); -} - - -pub fn build_float_mul(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using fmul on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::FloatMul { signed, fast, left, right }).get()?; - - return res.as_float(); -} - - -pub fn build_float_div(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using fdiv on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::FloatDiv { signed, fast, left, right }).get()?; - - return res.as_float(); -} - -pub fn build_float_mod(ctx: &mut MIRContext, left: MIRFloatValue, right: MIRFloatValue, signed: bool, fast: bool) -> DiagnosticResult { - if left.size != right.size { - unsure_panic!("Tried using fmod on different sized integers"); - } - - let res = ctx.append_inst(MIRInstruction::FloatMod { signed, fast, left, right }).get()?; - - return res.as_float(); -} - -pub fn build_float_neg(ctx: &mut MIRContext, val: MIRFloatValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::FloatNeg { val }).get()?; - - return res.as_float(); -} - -pub fn build_bitwise_and(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != 1 || b.size != 1 { - unsure_panic!("Tried using and on a non 1 bit value"); - } - - let res = ctx.append_inst(MIRInstruction::BitwiseAnd { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::IntegerNeg { val }).get()?; + + return res.as_int(); +} + +pub fn build_float_add( + ctx: &mut MIRContext, + left: MIRFloatValue, + right: MIRFloatValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using fadd on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::FloatAdd { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_float(); +} + +pub fn build_float_sub( + ctx: &mut MIRContext, + left: MIRFloatValue, + right: MIRFloatValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using fsub on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::FloatSub { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_float(); +} + +pub fn build_float_mul( + ctx: &mut MIRContext, + left: MIRFloatValue, + right: MIRFloatValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using fmul on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::FloatMul { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_float(); +} + +pub fn build_float_div( + ctx: &mut MIRContext, + left: MIRFloatValue, + right: MIRFloatValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using fdiv on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::FloatDiv { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_float(); +} + +pub fn build_float_mod( + ctx: &mut MIRContext, + left: MIRFloatValue, + right: MIRFloatValue, + signed: bool, + fast: bool, +) -> DiagnosticResult { + if left.size != right.size { + unsure_panic!("Tried using fmod on different sized integers"); + } + + let res = ctx + .append_inst(MIRInstruction::FloatMod { + signed, + fast, + left, + right, + }) + .get()?; + + return res.as_float(); +} + +pub fn build_float_neg( + ctx: &mut MIRContext, + val: MIRFloatValue, +) -> DiagnosticResult { + let res = ctx.append_inst(MIRInstruction::FloatNeg { val }).get()?; + + return res.as_float(); +} + +pub fn build_bitwise_and( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != 1 || b.size != 1 { + unsure_panic!("Tried using and on a non 1 bit value"); + } + + let res = ctx.append_inst(MIRInstruction::BitwiseAnd { a, b }).get()?; + + return res.as_int(); +} + +pub fn build_bitwise_or( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != 1 || b.size != 1 { + unsure_panic!("Tried using or on a non 1 bit value"); + } + + let res = ctx.append_inst(MIRInstruction::BitwiseOr { a, b }).get()?; + + return res.as_int(); +} + +pub fn build_bitwise_xor( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != 1 || b.size != 1 { + unsure_panic!("Tried using xor on a non 1 bit value"); + } - return res.as_int(); -} - -pub fn build_bitwise_or(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != 1 || b.size != 1 { - unsure_panic!("Tried using or on a non 1 bit value"); - } - - let res = ctx.append_inst(MIRInstruction::BitwiseOr { a, b }).get()?; - - return res.as_int(); -} + let res = ctx.append_inst(MIRInstruction::BitwiseXor { a, b }).get()?; -pub fn build_bitwise_xor(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != 1 || b.size != 1 { - unsure_panic!("Tried using xor on a non 1 bit value"); - } - - let res = ctx.append_inst(MIRInstruction::BitwiseXor { a, b }).get()?; - - return res.as_int(); + return res.as_int(); } pub fn build_bitwise_not(ctx: &mut MIRContext, a: MIRIntValue) -> DiagnosticResult { - if a.size != 1 { - unsure_panic!("Tried using not on a non 1 bit value"); - } + if a.size != 1 { + unsure_panic!("Tried using not on a non 1 bit value"); + } - let res = ctx.append_inst(MIRInstruction::BitwiseNot { val: a }).get()?; + let res = ctx + .append_inst(MIRInstruction::BitwiseNot { val: a }) + .get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_shift_left(ctx: &mut MIRContext, val: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::ShiftLeft { a: val, shift }).get()?; +pub fn build_shift_left( + ctx: &mut MIRContext, + val: MIRIntValue, + shift: MIRIntValue, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::ShiftLeft { a: val, shift }) + .get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_shift_right(ctx: &mut MIRContext, val: MIRIntValue, shift: MIRIntValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::ShiftRight { a: val, shift }).get()?; +pub fn build_shift_right( + ctx: &mut MIRContext, + val: MIRIntValue, + shift: MIRIntValue, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::ShiftRight { a: val, shift }) + .get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_comp_eq(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != b.size { - unsure_panic!("Tried using cmpeq on different sized integers"); - } +pub fn build_comp_eq( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != b.size { + unsure_panic!("Tried using cmpeq on different sized integers"); + } - let res = ctx.append_inst(MIRInstruction::CompEq { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::CompEq { a, b }).get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_comp_neg(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != b.size { - unsure_panic!("Tried using cmpneg on different sized integers"); - } +pub fn build_comp_neg( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != b.size { + unsure_panic!("Tried using cmpneg on different sized integers"); + } - let res = ctx.append_inst(MIRInstruction::CompNeg { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::CompNeg { a, b }).get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_comp_lt(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != b.size { - unsure_panic!("Tried using cmplt on different sized integers"); - } +pub fn build_comp_lt( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != b.size { + unsure_panic!("Tried using cmplt on different sized integers"); + } - let res = ctx.append_inst(MIRInstruction::CompLt { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::CompLt { a, b }).get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_comp_le(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != b.size { - unsure_panic!("Tried using cmple on different sized integers"); - } +pub fn build_comp_le( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != b.size { + unsure_panic!("Tried using cmple on different sized integers"); + } - let res = ctx.append_inst(MIRInstruction::CompLe { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::CompLe { a, b }).get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_comp_gt(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != b.size { - unsure_panic!("Tried using cmpgt on different sized integers"); - } +pub fn build_comp_gt( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != b.size { + unsure_panic!("Tried using cmpgt on different sized integers"); + } - let res = ctx.append_inst(MIRInstruction::CompGt { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::CompGt { a, b }).get()?; - return res.as_int(); + return res.as_int(); } -pub fn build_comp_ge(ctx: &mut MIRContext, a: MIRIntValue, b: MIRIntValue) -> DiagnosticResult { - if a.size != b.size { - unsure_panic!("Tried using cmpge on different sized integers"); - } +pub fn build_comp_ge( + ctx: &mut MIRContext, + a: MIRIntValue, + b: MIRIntValue, +) -> DiagnosticResult { + if a.size != b.size { + unsure_panic!("Tried using cmpge on different sized integers"); + } - let res = ctx.append_inst(MIRInstruction::CompGe { a, b }).get()?; + let res = ctx.append_inst(MIRInstruction::CompGe { a, b }).get()?; - return res.as_int(); + return res.as_int(); } pub fn build_return(ctx: &mut MIRContext, val: Option) -> DiagnosticResult { - ctx.append_inst(MIRInstruction::Return { val }); - - Ok(true) -} - -pub fn build_unconditional_branch(ctx: &mut MIRContext, branch: MIRBlockReference) -> DiagnosticResult { - ctx.append_inst(MIRInstruction::UnconditionalBranch { branch }); - Ok(true) -} - -pub fn build_conditional_branch(ctx: &mut MIRContext, condition: MIRIntValue, if_branch: MIRBlockReference, else_branch: MIRBlockReference) -> DiagnosticResult { - if condition.size != 1 { - unsure_panic!("provided cond to build_conditional_branch is not a boolean"); - } - - ctx.append_inst(MIRInstruction::ConditionalBranch { cond: condition, if_branch, else_branch }); - Ok(true) -} - -pub fn build_select(ctx: &mut MIRContext, condition: MIRIntValue, if_val: BaseMIRValue, else_val: BaseMIRValue) -> DiagnosticResult { - if condition.size != 1 { - unsure_panic!("provided cond to build_select is not a boolean"); - } - - if if_val.vtype != else_val.vtype { - unsure_panic!("both values do not have the same type"); - } - - return ctx.append_inst(MIRInstruction::Select { cond: condition, if_val, else_val }).get() -} - -pub fn build_field_pointer(ctx: &mut MIRContext, ptr: MIRPointerValue, field: usize) -> DiagnosticResult { - let val = ctx.append_inst(MIRInstruction::FieldPointer { val: ptr.clone(), field }).get()?; - let base: &BaseMIRValue = &ptr.into(); - - let pointer_hint = ctx.ssa_hints.get_hint(base.get_ssa_index()).as_pointer().as_generic_lowered(); - let t; - - if let RawType::LoweredStruct(_, container) = pointer_hint { - t = container.fields.vals[field].clone(); - } else { - unsure_panic!("field pointer hint was not a lowered struct"); - } - - let ind = ctx.ssa_hints.append_hint(MIRValueHint::Pointer(t)); - - if ind != val.get_ssa_index() { - unsure_panic!("couldn't hint SSA value for pointer! indexes are different"); - } - - return val.as_ptr(); -} - -pub fn build_index_pointer(ctx: &mut MIRContext, val: MIRPointerValue, index: MIRIntValue) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::IndexPointer { val: val.clone(), index }).get()?; - let base: BaseMIRValue = MIRPointerValue::into(val); - - let t = base.vtype.get_inner_type(); - - let ind = ctx.ssa_hints.append_hint(MIRValueHint::Pointer(*t)); - - if ind != res.get_ssa_index() { - unsure_panic!("couldn't hint SSA value for pointer! indexes are different"); - } - - res.as_ptr() + ctx.append_inst(MIRInstruction::Return { val }); + + Ok(true) +} + +pub fn build_unconditional_branch( + ctx: &mut MIRContext, + branch: MIRBlockReference, +) -> DiagnosticResult { + ctx.append_inst(MIRInstruction::UnconditionalBranch { branch }); + Ok(true) +} + +pub fn build_conditional_branch( + ctx: &mut MIRContext, + condition: MIRIntValue, + if_branch: MIRBlockReference, + else_branch: MIRBlockReference, +) -> DiagnosticResult { + if condition.size != 1 { + unsure_panic!("provided cond to build_conditional_branch is not a boolean"); + } + + ctx.append_inst(MIRInstruction::ConditionalBranch { + cond: condition, + if_branch, + else_branch, + }); + Ok(true) +} + +pub fn build_select( + ctx: &mut MIRContext, + condition: MIRIntValue, + if_val: BaseMIRValue, + else_val: BaseMIRValue, +) -> DiagnosticResult { + if condition.size != 1 { + unsure_panic!("provided cond to build_select is not a boolean"); + } + + if if_val.vtype != else_val.vtype { + unsure_panic!("both values do not have the same type"); + } + + return ctx + .append_inst(MIRInstruction::Select { + cond: condition, + if_val, + else_val, + }) + .get(); +} + +pub fn build_field_pointer( + ctx: &mut MIRContext, + ptr: MIRPointerValue, + field: usize, +) -> DiagnosticResult { + let val = ctx + .append_inst(MIRInstruction::FieldPointer { + val: ptr.clone(), + field, + }) + .get()?; + let base: &BaseMIRValue = &ptr.into(); + + let pointer_hint = ctx + .ssa_hints + .get_hint(base.get_ssa_index()) + .as_pointer() + .as_generic_lowered(); + let t; + + if let RawType::LoweredStruct(_, container) = pointer_hint { + t = container.fields.vals[field].clone(); + } else { + unsure_panic!("field pointer hint was not a lowered struct"); + } + + let ind = ctx.ssa_hints.append_hint(MIRValueHint::Pointer(t)); + + if ind != val.get_ssa_index() { + unsure_panic!("couldn't hint SSA value for pointer! indexes are different"); + } + + return val.as_ptr(); +} + +pub fn build_index_pointer( + ctx: &mut MIRContext, + val: MIRPointerValue, + index: MIRIntValue, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::IndexPointer { + val: val.clone(), + index, + }) + .get()?; + let base: BaseMIRValue = MIRPointerValue::into(val); + + let t = base.vtype.get_inner_type(); + + let ind = ctx.ssa_hints.append_hint(MIRValueHint::Pointer(*t)); + + if ind != res.get_ssa_index() { + unsure_panic!("couldn't hint SSA value for pointer! indexes are different"); + } + + res.as_ptr() } pub fn build_marker_era_drop(ctx: &mut MIRContext, val: BaseMIRValue) -> DiagnosticResult { - ctx.append_inst(MIRInstruction::MarkerEraDrop { value: val }); - - Ok(true) -} - -pub fn build_signed_int_const(ctx: &mut MIRContext, raw: i128, bitsize: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::IntegerSignedConstant { raw, bitsize }).get()?; - - return res.as_int(); -} - -pub fn build_unsigned_int_const(ctx: &mut MIRContext, raw: u128, bitsize: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::IntegerUnsignedConstant { raw, bitsize }).get()?; - - return res.as_int(); -} - -pub fn build_signed_float_const(ctx: &mut MIRContext, raw: f64, size: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::FloatSignedConstant { raw, size }).get()?; - - return res.as_float(); -} - -pub fn build_unsigned_float_const(ctx: &mut MIRContext, raw: f64, size: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::FloatUnsignedConstant { raw, size }).get()?; - - return res.as_float(); -} - -pub fn build_signed_fixed_const(ctx: &mut MIRContext, raw: f64, number: usize, fraction: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::FixedSignedConstant { raw, number, fraction }).get()?; - - return res.as_int(); -} - -pub fn build_unsigned_fixed_const(ctx: &mut MIRContext, raw: f64, number: usize, fraction: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::FixedUnsignedConstant { raw, number, fraction }).get()?; - - return res.as_int(); -} - -pub fn build_static_string_const(ctx: &mut MIRContext, raw: String) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::StaticStringConstant { raw }).get()?; - - return res.as_ptr(); -} - -pub fn build_static_struct_const(ctx: &mut MIRContext, struct_type: RawType, values: Vec) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::StructInitializerConstant { struct_type, values }).get()?; - - return res.as_struct(); -} - -pub fn build_static_array_const(ctx: &mut MIRContext, values: Vec) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::ArrayInitializerConstant { values }).get()?; - - return res.as_array(); -} - -pub fn build_static_array_one_const(ctx: &mut MIRContext, val: BaseMIRValue, size: usize) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::ArrayInitializerConstantSame { size, val }).get()?; + ctx.append_inst(MIRInstruction::MarkerEraDrop { value: val }); + + Ok(true) +} + +pub fn build_signed_int_const( + ctx: &mut MIRContext, + raw: i128, + bitsize: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::IntegerSignedConstant { raw, bitsize }) + .get()?; + + return res.as_int(); +} + +pub fn build_unsigned_int_const( + ctx: &mut MIRContext, + raw: u128, + bitsize: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::IntegerUnsignedConstant { raw, bitsize }) + .get()?; + + return res.as_int(); +} + +pub fn build_signed_float_const( + ctx: &mut MIRContext, + raw: f64, + size: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::FloatSignedConstant { raw, size }) + .get()?; + + return res.as_float(); +} + +pub fn build_unsigned_float_const( + ctx: &mut MIRContext, + raw: f64, + size: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::FloatUnsignedConstant { raw, size }) + .get()?; + + return res.as_float(); +} + +pub fn build_signed_fixed_const( + ctx: &mut MIRContext, + raw: f64, + number: usize, + fraction: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::FixedSignedConstant { + raw, + number, + fraction, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_unsigned_fixed_const( + ctx: &mut MIRContext, + raw: f64, + number: usize, + fraction: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::FixedUnsignedConstant { + raw, + number, + fraction, + }) + .get()?; + + return res.as_int(); +} + +pub fn build_static_string_const( + ctx: &mut MIRContext, + raw: String, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::StaticStringConstant { raw }) + .get()?; + + return res.as_ptr(); +} + +pub fn build_static_struct_const( + ctx: &mut MIRContext, + struct_type: RawType, + values: Vec, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::StructInitializerConstant { + struct_type, + values, + }) + .get()?; + + return res.as_struct(); +} + +pub fn build_static_array_const( + ctx: &mut MIRContext, + values: Vec, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::ArrayInitializerConstant { values }) + .get()?; + + return res.as_array(); +} + +pub fn build_static_array_one_const( + ctx: &mut MIRContext, + val: BaseMIRValue, + size: usize, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::ArrayInitializerConstantSame { size, val }) + .get()?; + + return res.as_array(); +} + +pub fn build_argument_grab( + ctx: &mut MIRContext, + index: usize, + t: Type, +) -> DiagnosticResult { + let res = ctx + .append_inst(MIRInstruction::FuncArgumentGrab { + ind: index, + argtype: t, + }) + .get()?; + + return Ok(res); +} + +pub fn build_call( + ctx: &mut MIRContext, + func: usize, + ind: usize, + args: Vec, +) -> DiagnosticResult> { + let func = &ctx.functions[func]; + + for (arg, t) in args.iter().zip(func.arguments.iter()) { + if !arg.vtype.is_truly_eq(t) { + println!("{:#?} -> {:#?}", arg.vtype, t); + unsure_panic!("invalid function argument types!"); + } + } + + let res = ctx + .append_inst(MIRInstruction::Call { + function: ind, + arguments: args, + }) + .val; + + return Ok(res); +} + +pub fn build_phi( + ctx: &mut MIRContext, + choices: Vec<(MIRBlockReference, BaseMIRValue)>, +) -> DiagnosticResult { + let t = &choices[0].1.vtype; - return res.as_array(); -} - -pub fn build_argument_grab(ctx: &mut MIRContext, index: usize, t: Type) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::FuncArgumentGrab { ind: index, argtype: t }).get()?; - - return Ok(res); -} - -pub fn build_call(ctx: &mut MIRContext, func: usize, ind: usize, args: Vec) -> DiagnosticResult> { - let func = &ctx.functions[func]; - - for(arg, t) in args.iter().zip(func.arguments.iter()) { - if !arg.vtype.is_truly_eq(t) { - println!("{:#?} -> {:#?}", arg.vtype, t); - unsure_panic!("invalid function argument types!"); - } - } - - let res = ctx.append_inst(MIRInstruction::Call { function: ind, arguments: args }).val; - - return Ok(res); -} - -pub fn build_phi(ctx: &mut MIRContext, choices: Vec<(MIRBlockReference, BaseMIRValue)>) -> DiagnosticResult { - let t = &choices[0].1.vtype; - - for choice in &choices { - if &choice.1.vtype != t { - unsure_panic!("phi node must have same type values"); - } - } - - let res = ctx.append_inst(MIRInstruction::Phi { choices }).get()?; - - return Ok(res); -} - -pub fn build_ir_cast(ctx: &mut MIRContext, val: BaseMIRValue, to: Type) -> DiagnosticResult { - let res = ctx.append_inst(MIRInstruction::IRCast { val, to }).get()?; - - return Ok(res); -} - -pub fn build_memory_copy_unsafe(ctx: &mut MIRContext, src: MIRPointerValue, dest: MIRPointerValue, size: usize) { - ctx.append_inst(MIRInstruction::MemoryCopy { src, dest, sz: size }); + for choice in &choices { + if &choice.1.vtype != t { + unsure_panic!("phi node must have same type values"); + } + } + + let res = ctx.append_inst(MIRInstruction::Phi { choices }).get()?; + + return Ok(res); +} + +pub fn build_ir_cast( + ctx: &mut MIRContext, + val: BaseMIRValue, + to: Type, +) -> DiagnosticResult { + let res = ctx.append_inst(MIRInstruction::IRCast { val, to }).get()?; + + return Ok(res); +} + +pub fn build_memory_copy_unsafe( + ctx: &mut MIRContext, + src: MIRPointerValue, + dest: MIRPointerValue, + size: usize, +) { + ctx.append_inst(MIRInstruction::MemoryCopy { + src, + dest, + sz: size, + }); } /// Fallback to whenever store fails since the type isn't valid. Allows to use unsafe memory copy for enums /// # Behvior -/// If `src` is actually a pointer, simply uses the `unsmemcopy` instruction to copy the memory from `src` to `dest`. +/// If `src` is actually a pointer, simply uses the `unsmemcopy` instruction to copy the memory from `src` to `dest`. /// If not, it first creates a pointer for `src`, storing the value inside and then using the `unsmemcopy` instruction. -pub fn build_store_fallback(ctx: &mut MIRContext, dest: MIRPointerValue, src: BaseMIRValue, storage: &TypeStorage) -> MaybeDiagnostic { - let sz = src.vtype.get_size(&src.vtype, false, storage); +pub fn build_store_fallback( + ctx: &mut MIRContext, + dest: MIRPointerValue, + src: BaseMIRValue, + storage: &TypeStorage, +) -> MaybeDiagnostic { + let sz = src.vtype.get_size(&src.vtype, false, storage); - if src.can_be_pointer() { - let src = src.as_ptr()?; - - ctx.append_inst(MIRInstruction::MemoryCopy { src, dest, sz: sz}); - return Ok(()) - } + if src.can_be_pointer() { + let src = src.as_ptr()?; - let ptr = build_stack_alloc(ctx, sz, src.vtype.clone())?; + ctx.append_inst(MIRInstruction::MemoryCopy { src, dest, sz: sz }); + return Ok(()); + } - build_store(ctx, storage, ptr.clone(), src)?; + let ptr = build_stack_alloc(ctx, sz, src.vtype.clone())?; - ctx.append_inst(MIRInstruction::MemoryCopy { src: ptr, dest, sz }); + build_store(ctx, storage, ptr.clone(), src)?; - Ok(()) -} \ No newline at end of file + ctx.append_inst(MIRInstruction::MemoryCopy { src: ptr, dest, sz }); + + Ok(()) +} diff --git a/compiler/astoir_mir/src/ctx.rs b/compiler/astoir_mir/src/ctx.rs index e0f7883..c20422b 100644 --- a/compiler/astoir_mir/src/ctx.rs +++ b/compiler/astoir_mir/src/ctx.rs @@ -2,141 +2,167 @@ use std::{collections::HashMap, fmt::Display}; use diagnostics::DiagnosticResult; -use crate::{blocks::{MIRBlock, MIRBlockHeldInstruction, hints::{HintStorage, MIRValueHint}, refer::MIRBlockReference}, builder::build_phi, funcs::MIRFunction, inst_writer::{BlockPosition, InstructionWriterPosition}, insts::{MIRInstruction, val::InstructionValue}, vals::base::BaseMIRValue}; - +use crate::{ + blocks::{ + MIRBlock, MIRBlockHeldInstruction, + hints::{HintStorage, MIRValueHint}, + refer::MIRBlockReference, + }, + builder::build_phi, + funcs::MIRFunction, + inst_writer::{BlockPosition, InstructionWriterPosition}, + insts::{MIRInstruction, val::InstructionValue}, + vals::base::BaseMIRValue, +}; pub struct MIRContext { - pub functions: Vec, - pub blocks: Vec, + pub functions: Vec, + pub blocks: Vec, + + pub block_to_func: HashMap, - pub block_to_func: HashMap, - - pub writer: InstructionWriterPosition, + pub writer: InstructionWriterPosition, - pub ssa_hints: HintStorage, + pub ssa_hints: HintStorage, } impl MIRContext { - pub fn new() -> Self { - MIRContext { functions: vec![], ssa_hints: HintStorage::new(), blocks: vec![], writer: InstructionWriterPosition { curr_block: 0, curr_inst: BlockPosition::END }, block_to_func: HashMap::new() } - } + pub fn new() -> Self { + MIRContext { + functions: vec![], + ssa_hints: HintStorage::new(), + blocks: vec![], + writer: InstructionWriterPosition { + curr_block: 0, + curr_inst: BlockPosition::END, + }, + block_to_func: HashMap::new(), + } + } + + pub fn create_block(&mut self, func: usize) -> MIRBlockReference { + let ind = self.blocks.len(); - pub fn create_block(&mut self, func: usize) -> MIRBlockReference { - let ind = self.blocks.len(); + self.blocks.push(MIRBlock::new(ind)); - self.blocks.push(MIRBlock::new(ind)); + self.functions[func].blocks.push(ind); - self.functions[func].blocks.push(ind); + self.block_to_func.insert(ind, func); - self.block_to_func.insert(ind, func); + return ind; + } - return ind; - } + pub fn create_block_handled(&mut self, func: usize) -> MIRBlockReference { + let ind = self.blocks.len(); - pub fn create_block_handled(&mut self, func: usize) -> MIRBlockReference { - let ind = self.blocks.len(); - - self.blocks.push(MIRBlock::new(ind)); + self.blocks.push(MIRBlock::new(ind)); - self.block_to_func.insert(ind, func); + self.block_to_func.insert(ind, func); - return ind; - } + return ind; + } + pub fn get_func_from_block(&self, block: MIRBlockReference) -> usize { + return self.block_to_func[&block]; + } - pub fn get_func_from_block(&self, block: MIRBlockReference) -> usize { - return self.block_to_func[&block]; - } + pub fn append_function(&mut self, func: MIRFunction) -> usize { + let ind = self.functions.len(); - pub fn append_function(&mut self, func: MIRFunction) -> usize { - let ind = self.functions.len(); + self.functions.push(func); - self.functions.push(func); + return ind; + } - return ind; - } + pub fn append_inst(&mut self, inst: MIRInstruction) -> InstructionValue { + if inst.has_return(self) { + let ret = inst.get_return_type(self); - pub fn append_inst(&mut self, inst: MIRInstruction) -> InstructionValue { - if inst.has_return(self) { - let ret = inst.get_return_type(self); + if !inst.should_hint() { + let hint_ind = self.ssa_hints.vec.len(); - if !inst.should_hint() { - let hint_ind = self.ssa_hints.vec.len(); + self.blocks[self.writer.curr_block].append( + MIRBlockHeldInstruction::Valued(inst.clone(), hint_ind), + &self.writer.curr_inst, + ); - self.blocks[self.writer.curr_block].append(MIRBlockHeldInstruction::Valued(inst.clone(), hint_ind), &self.writer.curr_inst); + return InstructionValue::new(Some(BaseMIRValue::new(hint_ind, ret))); + } - return InstructionValue::new(Some(BaseMIRValue::new(hint_ind, ret))) - } + let hint_ind = self.ssa_hints.append_hint(MIRValueHint::Value(ret.clone())); - let hint_ind = self.ssa_hints.append_hint(MIRValueHint::Value(ret.clone())); + self.blocks[self.writer.curr_block].append( + MIRBlockHeldInstruction::Valued(inst.clone(), hint_ind), + &self.writer.curr_inst, + ); - self.blocks[self.writer.curr_block].append(MIRBlockHeldInstruction::Valued(inst.clone(), hint_ind), &self.writer.curr_inst); + return InstructionValue::new(Some(BaseMIRValue::new(hint_ind, ret))); + } - return InstructionValue::new(Some(BaseMIRValue::new(hint_ind, ret))); - } + self.blocks[self.writer.curr_block].append( + MIRBlockHeldInstruction::Valueless(inst.clone()), + &self.writer.curr_inst, + ); - self.blocks[self.writer.curr_block].append(MIRBlockHeldInstruction::Valueless(inst.clone()), &self.writer.curr_inst); + return InstructionValue::new(None); + } - return InstructionValue::new(None); - } + /// Resolve the different SSA values for the given merge blocks + pub fn resolve_ssa(&mut self, block: MIRBlockReference) -> DiagnosticResult { + let mut vals = vec![]; - /// Resolve the different SSA values for the given merge blocks - pub fn resolve_ssa(&mut self, block: MIRBlockReference) -> DiagnosticResult { - let mut vals = vec![]; + let b = &self.blocks[block]; - let b = &self.blocks[block]; + for (ind, hint) in b.variables.iter() { + let mut choices: Vec<(MIRBlockReference, BaseMIRValue)> = vec![]; + let mut capture_initial_phi_val = false; - for (ind, hint) in b.variables.iter() { - let mut choices: Vec<(MIRBlockReference, BaseMIRValue)> = vec![]; - let mut capture_initial_phi_val = false; + for block_ref in &b.merge_blocks { + let block = &self.blocks[*block_ref]; + let block_hint = &block.variables[ind]; - for block_ref in &b.merge_blocks { - let block = &self.blocks[*block_ref]; - let block_hint = &block.variables[ind]; + if hint == block_hint && !capture_initial_phi_val { + choices.push((*block_ref, block_hint.hint.clone().unwrap())); + capture_initial_phi_val = true; + } else if hint != block_hint && block_hint.hint.is_some() { + choices.push((*block_ref, block_hint.hint.clone().unwrap())); + } + } - if hint == block_hint && !capture_initial_phi_val { - choices.push((*block_ref, block_hint.hint.clone().unwrap())); - capture_initial_phi_val = true; - } else if hint != block_hint && block_hint.hint.is_some() { - choices.push((*block_ref, block_hint.hint.clone().unwrap())); - } - } + // Phi here only matters when there are 2+ choices. Else it's just the default + if choices.len() >= 2 { + vals.push((*ind, choices)); + } + } - // Phi here only matters when there are 2+ choices. Else it's just the default - if choices.len() >= 2 { - vals.push((*ind, choices)); - } - } + self.writer.move_end(block); - self.writer.move_end(block); - - for val in vals { - // Only update using PHI if needed and value is merged - if !val.1.is_empty() { - let res = build_phi(self, val.1)?; + for val in vals { + // Only update using PHI if needed and value is merged + if !val.1.is_empty() { + let res = build_phi(self, val.1)?; - let mut hint = self.blocks[block].variables[&val.0].clone(); - hint.hint = Some(res); - - self.blocks[block].variables.insert(val.0, hint); - } - } + let mut hint = self.blocks[block].variables[&val.0].clone(); + hint.hint = Some(res); - return Ok(true); - } + self.blocks[block].variables.insert(val.0, hint); + } + } + return Ok(true); + } } impl Display for MIRContext { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for func in &self.functions { - writeln!(f, "{}", func)?; - } - - for block in &self.blocks { - writeln!(f, "{}", block)?; - } - - Ok(()) - } -} \ No newline at end of file + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for func in &self.functions { + writeln!(f, "{}", func)?; + } + + for block in &self.blocks { + writeln!(f, "{}", block)?; + } + + Ok(()) + } +} diff --git a/compiler/astoir_mir/src/funcs.rs b/compiler/astoir_mir/src/funcs.rs index ee266e3..bd3c7ee 100644 --- a/compiler/astoir_mir/src/funcs.rs +++ b/compiler/astoir_mir/src/funcs.rs @@ -2,70 +2,93 @@ use std::fmt::Display; use compiler_typing::tree::Type; use compiler_utils::hash::HashedString; -use diagnostics::{unsure_panic}; +use diagnostics::unsure_panic; -use crate::{blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::{MIRBlockReference}}, ctx::MIRContext, vals::base::BaseMIRValue}; +use crate::{ + blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::MIRBlockReference}, + ctx::MIRContext, + vals::base::BaseMIRValue, +}; /// Represents a function in the MIR. Owns one or more blocks pub struct MIRFunction { - /// The block storage. index 0 is entry block - pub blocks: Vec, - pub name: HashedString, - - pub id: usize, + /// The block storage. index 0 is entry block + pub blocks: Vec, + pub name: HashedString, - /// This will prevent the function from being usable by normal function calls if true - pub is_from_struct: bool, + pub id: usize, - pub arguments: Vec, - pub return_type: Option + /// This will prevent the function from being usable by normal function calls if true + pub is_from_struct: bool, + + pub arguments: Vec, + pub return_type: Option, } impl MIRFunction { - pub fn new(name: String, arguments: Vec, return_type: Option, is_from_struct: bool, ctx: &MIRContext) -> Self { - return MIRFunction { blocks: vec![], name: HashedString::new(name), arguments, return_type, is_from_struct, id: ctx.functions.len()} - } - - pub fn append_entry_block(&mut self, ctx: &mut MIRContext) -> MIRBlockReference { - if !self.blocks.is_empty() { - unsure_panic!("tried using append_entry_block on a non-empty function block!"); - } - - let reference = ctx.create_block_handled(self.id); - - let block = &mut ctx.blocks[reference]; - - let mut ind = 0; - for arg in &self.arguments { - block.variables.insert(ind, MIRBlockVariableSSAHint { kind: MIRBlockVariableType::SSA, hint: Some(BaseMIRValue::new(ind, arg.clone())) }); - - ind += 1; - } - - self.blocks.push(reference); - - return reference; - } - - pub fn append_block(&mut self, ctx: &mut MIRContext) -> MIRBlockReference { - if self.blocks.is_empty() { - unsure_panic!("tried using append_block on empty function blocks!"); - } - - let reference = ctx.create_block(self.id); - - return reference - } + pub fn new( + name: String, + arguments: Vec, + return_type: Option, + is_from_struct: bool, + ctx: &MIRContext, + ) -> Self { + return MIRFunction { + blocks: vec![], + name: HashedString::new(name), + arguments, + return_type, + is_from_struct, + id: ctx.functions.len(), + }; + } + + pub fn append_entry_block(&mut self, ctx: &mut MIRContext) -> MIRBlockReference { + if !self.blocks.is_empty() { + unsure_panic!("tried using append_entry_block on a non-empty function block!"); + } + + let reference = ctx.create_block_handled(self.id); + + let block = &mut ctx.blocks[reference]; + + let mut ind = 0; + for arg in &self.arguments { + block.variables.insert( + ind, + MIRBlockVariableSSAHint { + kind: MIRBlockVariableType::SSA, + hint: Some(BaseMIRValue::new(ind, arg.clone())), + }, + ); + + ind += 1; + } + + self.blocks.push(reference); + + return reference; + } + + pub fn append_block(&mut self, ctx: &mut MIRContext) -> MIRBlockReference { + if self.blocks.is_empty() { + unsure_panic!("tried using append_block on empty function blocks!"); + } + + let reference = ctx.create_block(self.id); + + return reference; + } } impl Display for MIRFunction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, ".func_{}_struct{}", self.name.val, self.is_from_struct)?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, ".func_{}_struct{}", self.name.val, self.is_from_struct)?; - for block in &self.blocks { - writeln!(f, "- block_{}", block)?; - } + for block in &self.blocks { + writeln!(f, "- block_{}", block)?; + } - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/compiler/astoir_mir/src/inst_writer.rs b/compiler/astoir_mir/src/inst_writer.rs index c3d3822..64d7cd1 100644 --- a/compiler/astoir_mir/src/inst_writer.rs +++ b/compiler/astoir_mir/src/inst_writer.rs @@ -1,28 +1,28 @@ //! A way to avoid Rust borrowing errors by delegating the Instruction appending logic directly to the MIRContext instead of the builder functions -use crate::{blocks::refer::MIRBlockReference}; +use crate::blocks::refer::MIRBlockReference; #[derive(Clone)] pub enum BlockPosition { - START, - END + START, + END, } /// The main instruction. Contains the current position pub struct InstructionWriterPosition { - pub curr_block: MIRBlockReference, - pub curr_inst: BlockPosition + pub curr_block: MIRBlockReference, + pub curr_inst: BlockPosition, } impl InstructionWriterPosition { - pub fn move_start(&mut self, block: MIRBlockReference) { - self.curr_block = block; - self.curr_inst = BlockPosition::START; - } + pub fn move_start(&mut self, block: MIRBlockReference) { + self.curr_block = block; + self.curr_inst = BlockPosition::START; + } - pub fn move_end(&mut self, block: MIRBlockReference) { - self.curr_block = block; + pub fn move_end(&mut self, block: MIRBlockReference) { + self.curr_block = block; - self.curr_inst = BlockPosition::END; - } + self.curr_inst = BlockPosition::END; + } } diff --git a/compiler/astoir_mir/src/insts/mod.rs b/compiler/astoir_mir/src/insts/mod.rs index 066b776..078209d 100644 --- a/compiler/astoir_mir/src/insts/mod.rs +++ b/compiler/astoir_mir/src/insts/mod.rs @@ -1,330 +1,701 @@ -//! The definitions for instructions within the MIR. +//! The definitions for instructions within the MIR. use std::fmt::Display; use compiler_typing::{raw::RawType, tree::Type}; -use crate::{blocks::{refer::MIRBlockReference}, ctx::MIRContext, vals::{base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}}; +use crate::{ + blocks::refer::MIRBlockReference, + ctx::MIRContext, + vals::{base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}, +}; pub mod val; /// An instruction inside of the MIR. #[derive(Clone)] pub enum MIRInstruction { - StackAlloc { alloc_size: usize, t: Type }, - Load { value: MIRPointerValue }, - Store { variable: MIRPointerValue, value: BaseMIRValue }, - - // Number casting - DowncastInteger { val: MIRIntValue, size: usize }, // make size smaller - UpcastInteger { val: MIRIntValue, size: usize }, // make size bigger - - DowncastFloat { val: MIRFloatValue, size: usize }, - UpcastFloat { val: MIRFloatValue, size: usize }, - - // Arithmetrics - IntegerAdd { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerSub { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerMul { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerDiv { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerMod { signed: bool, fast: bool, left: MIRIntValue, right: MIRIntValue }, - IntegerNeg { val: MIRIntValue }, - - FloatAdd { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatSub { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatMul { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatDiv { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatMod { signed: bool, fast: bool, left: MIRFloatValue, right: MIRFloatValue }, - FloatNeg { val: MIRFloatValue }, - - // Bitwise (int typed) - BitwiseAnd { a: MIRIntValue, b: MIRIntValue }, - BitwiseOr { a: MIRIntValue, b: MIRIntValue }, - BitwiseXor { a: MIRIntValue, b: MIRIntValue }, - BitwiseNot { val: MIRIntValue }, - - ShiftLeft { a: MIRIntValue, shift: MIRIntValue }, - ShiftRight { a: MIRIntValue, shift: MIRIntValue }, - - // Comparaison / Logical - CompEq { a: MIRIntValue, b: MIRIntValue }, - CompNeg { a: MIRIntValue, b: MIRIntValue }, - CompLt { a: MIRIntValue, b: MIRIntValue}, // < - CompLe { a: MIRIntValue, b: MIRIntValue}, // <= - CompGt { a: MIRIntValue, b: MIRIntValue }, // > - CompGe { a: MIRIntValue, b: MIRIntValue}, // >= - - // Constants - IntegerSignedConstant { raw: i128, bitsize: usize }, - IntegerUnsignedConstant { raw: u128, bitsize: usize }, - FloatSignedConstant { raw: f64, size: usize }, - FloatUnsignedConstant { raw: f64, size: usize }, - FixedSignedConstant { raw: f64, number: usize, fraction: usize }, - FixedUnsignedConstant { raw: f64, number: usize, fraction: usize }, - StaticStringConstant { raw: String }, - - StructInitializerConstant { struct_type: RawType, values: Vec }, - ArrayInitializerConstant { values: Vec }, - ArrayInitializerConstantSame { size: usize, val: BaseMIRValue }, - - // Control - Return { val: Option }, - UnconditionalBranch { branch: MIRBlockReference }, - ConditionalBranch { cond: MIRIntValue, if_branch: MIRBlockReference, else_branch: MIRBlockReference }, - Phi { choices: Vec<(MIRBlockReference, BaseMIRValue)> }, - Select { cond: MIRIntValue, if_val: BaseMIRValue, else_val: BaseMIRValue }, - - Call { function: usize, arguments: Vec }, - - // Pointer utils - - FieldPointer { val: MIRPointerValue, field: usize }, - IndexPointer { val: MIRPointerValue, index: MIRIntValue }, - PointerAdd { pointer: MIRPointerValue, right: MIRIntValue }, - PointerSub { pointer: MIRPointerValue, right: MIRIntValue }, - - FuncArgumentGrab { ind: usize, argtype: Type }, - - // Memory utils - MemoryCopy { src: MIRPointerValue, dest: MIRPointerValue, sz: usize }, - - /// Indicates to the IR processor that this given value's era is finished and thus we drop the value - MarkerEraDrop { value: BaseMIRValue }, - - /// Indicates a cast that doesn't need any action and is merely here to satisfy the IR strict typing. Must only be used safely - IRCast { val: BaseMIRValue, to: Type }, + StackAlloc { + alloc_size: usize, + t: Type, + }, + Load { + value: MIRPointerValue, + }, + Store { + variable: MIRPointerValue, + value: BaseMIRValue, + }, + + // Number casting + DowncastInteger { + val: MIRIntValue, + size: usize, + }, // make size smaller + UpcastInteger { + val: MIRIntValue, + size: usize, + }, // make size bigger + + DowncastFloat { + val: MIRFloatValue, + size: usize, + }, + UpcastFloat { + val: MIRFloatValue, + size: usize, + }, + + // Arithmetrics + IntegerAdd { + signed: bool, + fast: bool, + left: MIRIntValue, + right: MIRIntValue, + }, + IntegerSub { + signed: bool, + fast: bool, + left: MIRIntValue, + right: MIRIntValue, + }, + IntegerMul { + signed: bool, + fast: bool, + left: MIRIntValue, + right: MIRIntValue, + }, + IntegerDiv { + signed: bool, + fast: bool, + left: MIRIntValue, + right: MIRIntValue, + }, + IntegerMod { + signed: bool, + fast: bool, + left: MIRIntValue, + right: MIRIntValue, + }, + IntegerNeg { + val: MIRIntValue, + }, + + FloatAdd { + signed: bool, + fast: bool, + left: MIRFloatValue, + right: MIRFloatValue, + }, + FloatSub { + signed: bool, + fast: bool, + left: MIRFloatValue, + right: MIRFloatValue, + }, + FloatMul { + signed: bool, + fast: bool, + left: MIRFloatValue, + right: MIRFloatValue, + }, + FloatDiv { + signed: bool, + fast: bool, + left: MIRFloatValue, + right: MIRFloatValue, + }, + FloatMod { + signed: bool, + fast: bool, + left: MIRFloatValue, + right: MIRFloatValue, + }, + FloatNeg { + val: MIRFloatValue, + }, + + // Bitwise (int typed) + BitwiseAnd { + a: MIRIntValue, + b: MIRIntValue, + }, + BitwiseOr { + a: MIRIntValue, + b: MIRIntValue, + }, + BitwiseXor { + a: MIRIntValue, + b: MIRIntValue, + }, + BitwiseNot { + val: MIRIntValue, + }, + + ShiftLeft { + a: MIRIntValue, + shift: MIRIntValue, + }, + ShiftRight { + a: MIRIntValue, + shift: MIRIntValue, + }, + + // Comparaison / Logical + CompEq { + a: MIRIntValue, + b: MIRIntValue, + }, + CompNeg { + a: MIRIntValue, + b: MIRIntValue, + }, + CompLt { + a: MIRIntValue, + b: MIRIntValue, + }, // < + CompLe { + a: MIRIntValue, + b: MIRIntValue, + }, // <= + CompGt { + a: MIRIntValue, + b: MIRIntValue, + }, // > + CompGe { + a: MIRIntValue, + b: MIRIntValue, + }, // >= + + // Constants + IntegerSignedConstant { + raw: i128, + bitsize: usize, + }, + IntegerUnsignedConstant { + raw: u128, + bitsize: usize, + }, + FloatSignedConstant { + raw: f64, + size: usize, + }, + FloatUnsignedConstant { + raw: f64, + size: usize, + }, + FixedSignedConstant { + raw: f64, + number: usize, + fraction: usize, + }, + FixedUnsignedConstant { + raw: f64, + number: usize, + fraction: usize, + }, + StaticStringConstant { + raw: String, + }, + + StructInitializerConstant { + struct_type: RawType, + values: Vec, + }, + ArrayInitializerConstant { + values: Vec, + }, + ArrayInitializerConstantSame { + size: usize, + val: BaseMIRValue, + }, + + // Control + Return { + val: Option, + }, + UnconditionalBranch { + branch: MIRBlockReference, + }, + ConditionalBranch { + cond: MIRIntValue, + if_branch: MIRBlockReference, + else_branch: MIRBlockReference, + }, + Phi { + choices: Vec<(MIRBlockReference, BaseMIRValue)>, + }, + Select { + cond: MIRIntValue, + if_val: BaseMIRValue, + else_val: BaseMIRValue, + }, + + Call { + function: usize, + arguments: Vec, + }, + + // Pointer utils + FieldPointer { + val: MIRPointerValue, + field: usize, + }, + IndexPointer { + val: MIRPointerValue, + index: MIRIntValue, + }, + PointerAdd { + pointer: MIRPointerValue, + right: MIRIntValue, + }, + PointerSub { + pointer: MIRPointerValue, + right: MIRIntValue, + }, + + FuncArgumentGrab { + ind: usize, + argtype: Type, + }, + + // Memory utils + MemoryCopy { + src: MIRPointerValue, + dest: MIRPointerValue, + sz: usize, + }, + + /// Indicates to the IR processor that this given value's era is finished and thus we drop the value + MarkerEraDrop { + value: BaseMIRValue, + }, + + /// Indicates a cast that doesn't need any action and is merely here to satisfy the IR strict typing. Must only be used safely + IRCast { + val: BaseMIRValue, + to: Type, + }, } impl MIRInstruction { - pub fn has_return(&self, ctx: &MIRContext) -> bool { - match self { - Self::MarkerEraDrop { .. } | Self::UnconditionalBranch { .. } | Self::ConditionalBranch { .. } | Self::Return { .. } | Self::Store { .. } | Self::MemoryCopy {.. } => { - return false; - }, - - Self::Call { function, arguments: _ } => { - let func = &ctx.functions[*function]; - - return func.return_type.is_some(); - } - - _ => true - } - } - - pub fn should_hint(&self) -> bool { - return match self { - Self::StackAlloc { .. } => false, - Self::FieldPointer { .. } => false, - Self::IndexPointer { .. } => false, - - _ => true - } - } - - pub fn get_return_type(&self, ctx: &MIRContext) -> Type { - match self { - Self::StackAlloc { .. } => return Type::GenericLowered(RawType::Pointer), - Self::Load { value} => { - let base: BaseMIRValue = value.clone().into(); - - let hint = ctx.ssa_hints.get_hint(base.get_ssa_index()); - - return hint.as_pointer(); - }, - - Self::DowncastInteger { val, size } => return Type::GenericLowered(RawType::Integer(*size, val.signed)), - Self::UpcastInteger { val, size } => return Type::GenericLowered(RawType::Integer(*size, val.signed)), - - Self::DowncastFloat { val, size } => return Type::GenericLowered(RawType::Floating(*size, val.signed)), - Self::UpcastFloat { val, size } => return Type::GenericLowered(RawType::Floating(*size, val.signed)), - - Self::IntegerAdd { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerSub { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerMul { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerDiv { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerMod { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), - Self::IntegerNeg { val } => return Type::GenericLowered(RawType::Integer(val.size, true)), - - Self::FloatAdd { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatSub { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatMul { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatDiv { signed, fast: _, left, right: _ } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), - Self::FloatNeg { val } => return Type::GenericLowered(RawType::Floating(val.size, true)), - - Self::BitwiseAnd { a, b: _ } => return Type::GenericLowered(RawType::Integer(a.size, a.signed)), - Self::BitwiseOr { a, b: _ } => return Type::GenericLowered(RawType::Integer(a.size, a.signed)), - Self::BitwiseXor { a, b: _ } => return Type::GenericLowered(RawType::Integer(a.size, a.signed)), - Self::BitwiseNot { val } => return Type::GenericLowered(RawType::Integer(val.size, val.signed)), - - Self::ShiftLeft { a, shift: _ } => return Type::GenericLowered(RawType::Integer(a.size, a.signed)), - Self::ShiftRight { a, shift: _ } => return Type::GenericLowered(RawType::Integer(a.size, a.signed)), - - Self::CompEq { .. } => return Type::GenericLowered(RawType::Boolean), - Self::CompNeg { .. } => return Type::GenericLowered(RawType::Boolean), - Self::CompLt { .. } => return Type::GenericLowered(RawType::Boolean), - Self::CompLe { .. } => return Type::GenericLowered(RawType::Boolean), - Self::CompGt { .. } => return Type::GenericLowered(RawType::Boolean), - Self::CompGe { .. } => return Type::GenericLowered(RawType::Boolean), - - Self::IntegerSignedConstant { raw: _, bitsize } => return Type::GenericLowered(RawType::Integer(*bitsize, true)), - Self::IntegerUnsignedConstant { raw: _, bitsize } => return Type::GenericLowered(RawType::Integer(*bitsize, false)), - Self::FloatUnsignedConstant { raw: _, size } => return Type::GenericLowered(RawType::Floating(*size, false)), - Self::FloatSignedConstant { raw: _, size } => return Type::GenericLowered(RawType::Floating(*size, true)), - Self::FixedSignedConstant { raw: _, number, fraction } => return Type::GenericLowered(RawType::FixedPoint(*number, *fraction, true)), - Self::FixedUnsignedConstant { raw: _, number, fraction } => return Type::GenericLowered(RawType::FixedPoint(*number, *fraction, false)), - Self::StaticStringConstant { raw: _ } => return Type::GenericLowered(RawType::Pointer), - Self::StructInitializerConstant { struct_type, values: _ } => return Type::GenericLowered(struct_type.clone()), - - Self::ArrayInitializerConstant { values } => return Type::Array(values.len(), Box::new(values[0].vtype.clone())), - Self::ArrayInitializerConstantSame { size, val } => return Type::Array(*size, Box::new(val.vtype.clone())), - - Self::Phi { choices } => { - return choices[0].1.vtype.clone(); - }, - - Self::Select { cond: _, if_val, else_val: _ } => return if_val.vtype.clone(), - - Self::Call { function, arguments: _ } => { - let func = &ctx.functions[*function]; - - return func.return_type.clone().unwrap(); - } - - Self::FieldPointer { .. } => return Type::GenericLowered(RawType::Pointer), - Self::IndexPointer { .. } => return Type::GenericLowered(RawType::Pointer), - - Self::PointerAdd { .. } => return Type::GenericLowered(RawType::Pointer), - Self::PointerSub { .. } => return Type::GenericLowered(RawType::Pointer), - - Self::FuncArgumentGrab { ind: _, argtype } => argtype.clone(), - - Self::IRCast { val: _, to } => to.clone(), - - _ => panic!("Tried using get_return_type on non returning type! {}", self) - } - } + pub fn has_return(&self, ctx: &MIRContext) -> bool { + match self { + Self::MarkerEraDrop { .. } + | Self::UnconditionalBranch { .. } + | Self::ConditionalBranch { .. } + | Self::Return { .. } + | Self::Store { .. } + | Self::MemoryCopy { .. } => { + return false; + } + + Self::Call { + function, + arguments: _, + } => { + let func = &ctx.functions[*function]; + + return func.return_type.is_some(); + } + + _ => true, + } + } + + pub fn should_hint(&self) -> bool { + return match self { + Self::StackAlloc { .. } => false, + Self::FieldPointer { .. } => false, + Self::IndexPointer { .. } => false, + + _ => true, + }; + } + + pub fn get_return_type(&self, ctx: &MIRContext) -> Type { + match self { + Self::StackAlloc { .. } => return Type::GenericLowered(RawType::Pointer), + Self::Load { value } => { + let base: BaseMIRValue = value.clone().into(); + + let hint = ctx.ssa_hints.get_hint(base.get_ssa_index()); + + return hint.as_pointer(); + } + + Self::DowncastInteger { val, size } => { + return Type::GenericLowered(RawType::Integer(*size, val.signed)); + } + Self::UpcastInteger { val, size } => { + return Type::GenericLowered(RawType::Integer(*size, val.signed)); + } + + Self::DowncastFloat { val, size } => { + return Type::GenericLowered(RawType::Floating(*size, val.signed)); + } + Self::UpcastFloat { val, size } => { + return Type::GenericLowered(RawType::Floating(*size, val.signed)); + } + + Self::IntegerAdd { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerSub { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerMul { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerDiv { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerMod { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Integer(left.size, *signed)), + Self::IntegerNeg { val } => { + return Type::GenericLowered(RawType::Integer(val.size, true)); + } + + Self::FloatAdd { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatSub { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatMul { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatDiv { + signed, + fast: _, + left, + right: _, + } => return Type::GenericLowered(RawType::Floating(left.size, *signed)), + Self::FloatNeg { val } => { + return Type::GenericLowered(RawType::Floating(val.size, true)); + } + + Self::BitwiseAnd { a, b: _ } => { + return Type::GenericLowered(RawType::Integer(a.size, a.signed)); + } + Self::BitwiseOr { a, b: _ } => { + return Type::GenericLowered(RawType::Integer(a.size, a.signed)); + } + Self::BitwiseXor { a, b: _ } => { + return Type::GenericLowered(RawType::Integer(a.size, a.signed)); + } + Self::BitwiseNot { val } => { + return Type::GenericLowered(RawType::Integer(val.size, val.signed)); + } + + Self::ShiftLeft { a, shift: _ } => { + return Type::GenericLowered(RawType::Integer(a.size, a.signed)); + } + Self::ShiftRight { a, shift: _ } => { + return Type::GenericLowered(RawType::Integer(a.size, a.signed)); + } + + Self::CompEq { .. } => return Type::GenericLowered(RawType::Boolean), + Self::CompNeg { .. } => return Type::GenericLowered(RawType::Boolean), + Self::CompLt { .. } => return Type::GenericLowered(RawType::Boolean), + Self::CompLe { .. } => return Type::GenericLowered(RawType::Boolean), + Self::CompGt { .. } => return Type::GenericLowered(RawType::Boolean), + Self::CompGe { .. } => return Type::GenericLowered(RawType::Boolean), + + Self::IntegerSignedConstant { raw: _, bitsize } => { + return Type::GenericLowered(RawType::Integer(*bitsize, true)); + } + Self::IntegerUnsignedConstant { raw: _, bitsize } => { + return Type::GenericLowered(RawType::Integer(*bitsize, false)); + } + Self::FloatUnsignedConstant { raw: _, size } => { + return Type::GenericLowered(RawType::Floating(*size, false)); + } + Self::FloatSignedConstant { raw: _, size } => { + return Type::GenericLowered(RawType::Floating(*size, true)); + } + Self::FixedSignedConstant { + raw: _, + number, + fraction, + } => return Type::GenericLowered(RawType::FixedPoint(*number, *fraction, true)), + Self::FixedUnsignedConstant { + raw: _, + number, + fraction, + } => return Type::GenericLowered(RawType::FixedPoint(*number, *fraction, false)), + Self::StaticStringConstant { raw: _ } => return Type::GenericLowered(RawType::Pointer), + Self::StructInitializerConstant { + struct_type, + values: _, + } => return Type::GenericLowered(struct_type.clone()), + + Self::ArrayInitializerConstant { values } => { + return Type::Array(values.len(), Box::new(values[0].vtype.clone())); + } + Self::ArrayInitializerConstantSame { size, val } => { + return Type::Array(*size, Box::new(val.vtype.clone())); + } + + Self::Phi { choices } => { + return choices[0].1.vtype.clone(); + } + + Self::Select { + cond: _, + if_val, + else_val: _, + } => return if_val.vtype.clone(), + + Self::Call { + function, + arguments: _, + } => { + let func = &ctx.functions[*function]; + + return func.return_type.clone().unwrap(); + } + + Self::FieldPointer { .. } => return Type::GenericLowered(RawType::Pointer), + Self::IndexPointer { .. } => return Type::GenericLowered(RawType::Pointer), + + Self::PointerAdd { .. } => return Type::GenericLowered(RawType::Pointer), + Self::PointerSub { .. } => return Type::GenericLowered(RawType::Pointer), + + Self::FuncArgumentGrab { ind: _, argtype } => argtype.clone(), + + Self::IRCast { val: _, to } => to.clone(), + + _ => panic!( + "Tried using get_return_type on non returning type! {}", + self + ), + } + } } impl Display for MIRInstruction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::StackAlloc { alloc_size, t: _ } => writeln!(f, "stkalloc {}", *alloc_size)?, - Self::Load { value } => writeln!(f, "load {}", value)?, - Self::Store { variable, value } => writeln!(f, "store d{} s{}", variable, value)?, - - Self::MemoryCopy { src, dest, sz } => writeln!(f, "unsmemcopy s{} d{} {}b", src, dest, sz)?, - - Self::DowncastInteger { val, size } => writeln!(f, "dintcast {} {}", val, size)?, - Self::DowncastFloat { val, size } => writeln!(f, "dfcast {} {}", val, size)?, - Self::UpcastInteger { val, size } => writeln!(f, "uintcast {} {}", val, size)?, - Self::UpcastFloat { val, size } => writeln!(f, "ufcast {} {}", val, size)?, - - Self::IntegerAdd { signed, fast, left, right } => writeln!(f, "iadd s{} f{} {} {}", signed, fast, left, right)?, - Self::IntegerSub { signed, fast, left, right } => writeln!(f, "isub s{} f{} {} {}", signed, fast, left, right)?, - Self::IntegerMul { signed, fast, left, right } => writeln!(f, "imul s{} f{} {} {}", signed, fast, left, right)?, - Self::IntegerDiv { signed, fast, left, right } => writeln!(f, "idiv s{} f{} {} {}", signed, fast, left, right)?, - Self::IntegerMod { signed, fast, left, right } => writeln!(f, "imod s{} f{} {} {}", signed, fast, left, right)?, - Self::IntegerNeg { val } => writeln!(f, "ineg {}", val)?, - - Self::FloatAdd { signed, fast, left, right } => writeln!(f, "fadd s{} f{} {} {}", signed, fast, left, right)?, - Self::FloatSub { signed, fast, left, right } => writeln!(f, "fsub s{} f{} {} {}", signed, fast, left, right)?, - Self::FloatMul { signed, fast, left, right } => writeln!(f, "fmul s{} f{} {} {}", signed, fast, left, right)?, - Self::FloatDiv { signed, fast, left, right } => writeln!(f, "fdiv s{} f{} {} {}", signed, fast, left, right)?, - Self::FloatMod { signed, fast, left, right } => writeln!(f, "fmod s{} f{} {} {}", signed, fast, left, right)?, - Self::FloatNeg { val } => writeln!(f, "fneg {}", val)?, - - Self::BitwiseAnd { a, b } => writeln!(f, "and {} {}", a, b)?, - Self::BitwiseOr { a, b } => writeln!(f, "or {} {}", a, b)?, - Self::BitwiseXor { a, b } => writeln!(f, "xor {} {}", a, b)?, - Self::BitwiseNot { val } => writeln!(f, "not {}", val)?, - - Self::ShiftLeft { a, shift } => writeln!(f, "shiftl {} {}", a, shift)?, - Self::ShiftRight { a, shift } => writeln!(f, "shiftr {} {}", a, shift)?, - - Self::CompEq { a, b } => writeln!(f, "eq {} {}", a, b)?, - Self::CompNeg { a, b } => writeln!(f, "ne {} {}", a, b)?, - Self::CompLt { a, b } => writeln!(f, "lt {} {}", a, b)?, - Self::CompLe { a, b } => writeln!(f, "le {} {}", a, b)?, - Self::CompGt { a, b } => writeln!(f, "gt {} {}", a, b)?, - Self::CompGe { a, b } => writeln!(f, "ge {} {}", a, b)?, - - Self::IntegerSignedConstant { raw, bitsize } => writeln!(f, "constints {} {}", raw, bitsize)?, - Self::IntegerUnsignedConstant { raw, bitsize } => writeln!(f, "constintu {} {}", raw, bitsize)?, - - Self::FloatSignedConstant { raw, size } => writeln!(f, "constfs {} {}", raw, size)?, - Self::FloatUnsignedConstant { raw, size } => writeln!(f, "constfu {} {}", raw, size)?, - - Self::FixedSignedConstant { raw, number, fraction } => writeln!(f, "constffs {} {} {}", raw, number, fraction)?, - Self::FixedUnsignedConstant { raw, number, fraction } => writeln!(f, "constffu {} {} {}", raw, number, fraction)?, - - Self::StaticStringConstant { raw } => writeln!(f, "conststr {}", raw)?, - - Self::StructInitializerConstant { struct_type: _, values } => { - writeln!(f, "conststructinitrz")?; - - for v in values { - write!(f, " {}", v)?; - } - }, - - Self::ArrayInitializerConstant { values } => { - writeln!(f, "constarrinitrz")?; - - for v in values { - write!(f, " {}", v)?; - } - }, - - Self::ArrayInitializerConstantSame { size, val } => { - writeln!(f, "constarrinitrzsm {} {}", size, val)? - }, - - Self::Return { val } => { - if val.is_some() { - writeln!(f, "ret {}", val.clone().unwrap())?; - } else { - writeln!(f, "ret")?; - } - }, - - Self::UnconditionalBranch { branch } => writeln!(f, "ucondbr {}", branch)?, - Self::ConditionalBranch { cond, if_branch, else_branch } => writeln!(f, "condbr {} {} {}", cond, if_branch, else_branch)?, - - Self::Phi { choices } => { - write!(f, "phi")?; - - for choice in choices { - write!(f, " [b{}, {}]", choice.0, choice.1)?; - } - - write!(f, "\n")?; - }, - - Self::Select { cond, if_val, else_val } => writeln!(f, "select {} {} {}", cond, if_val, else_val)?, - - Self::Call { function, arguments } => { - write!(f, "call {}", function)?; - - for arg in arguments { - write!(f, " {}", arg)?; - } - - write!(f, "\n")?; - }, - - Self::FieldPointer { val, field } => writeln!(f, "fieldptr {} {}", val, field)?, - Self::IndexPointer { val, index } => writeln!(f, "indptr {} {}", val, index)?, - - Self::PointerAdd { pointer, right } => writeln!(f, "ptradd {} {}", pointer, right)?, - Self::PointerSub { pointer, right } => writeln!(f, "ptrsub {} {}", pointer, right)?, - - Self::FuncArgumentGrab { ind, argtype: _ } => writeln!(f, "funcarg {}", ind)?, - - Self::MarkerEraDrop { value } => writeln!(f, ".marker_era_drop {}", value)?, - Self::IRCast { val, to } => writeln!(f, ".ircastzz {} {}", val, to)?, - } - - Ok(()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::StackAlloc { alloc_size, t: _ } => writeln!(f, "stkalloc {}", *alloc_size)?, + Self::Load { value } => writeln!(f, "load {}", value)?, + Self::Store { variable, value } => writeln!(f, "store d{} s{}", variable, value)?, + + Self::MemoryCopy { src, dest, sz } => { + writeln!(f, "unsmemcopy s{} d{} {}b", src, dest, sz)? + } + + Self::DowncastInteger { val, size } => writeln!(f, "dintcast {} {}", val, size)?, + Self::DowncastFloat { val, size } => writeln!(f, "dfcast {} {}", val, size)?, + Self::UpcastInteger { val, size } => writeln!(f, "uintcast {} {}", val, size)?, + Self::UpcastFloat { val, size } => writeln!(f, "ufcast {} {}", val, size)?, + + Self::IntegerAdd { + signed, + fast, + left, + right, + } => writeln!(f, "iadd s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerSub { + signed, + fast, + left, + right, + } => writeln!(f, "isub s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerMul { + signed, + fast, + left, + right, + } => writeln!(f, "imul s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerDiv { + signed, + fast, + left, + right, + } => writeln!(f, "idiv s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerMod { + signed, + fast, + left, + right, + } => writeln!(f, "imod s{} f{} {} {}", signed, fast, left, right)?, + Self::IntegerNeg { val } => writeln!(f, "ineg {}", val)?, + + Self::FloatAdd { + signed, + fast, + left, + right, + } => writeln!(f, "fadd s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatSub { + signed, + fast, + left, + right, + } => writeln!(f, "fsub s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatMul { + signed, + fast, + left, + right, + } => writeln!(f, "fmul s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatDiv { + signed, + fast, + left, + right, + } => writeln!(f, "fdiv s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatMod { + signed, + fast, + left, + right, + } => writeln!(f, "fmod s{} f{} {} {}", signed, fast, left, right)?, + Self::FloatNeg { val } => writeln!(f, "fneg {}", val)?, + + Self::BitwiseAnd { a, b } => writeln!(f, "and {} {}", a, b)?, + Self::BitwiseOr { a, b } => writeln!(f, "or {} {}", a, b)?, + Self::BitwiseXor { a, b } => writeln!(f, "xor {} {}", a, b)?, + Self::BitwiseNot { val } => writeln!(f, "not {}", val)?, + + Self::ShiftLeft { a, shift } => writeln!(f, "shiftl {} {}", a, shift)?, + Self::ShiftRight { a, shift } => writeln!(f, "shiftr {} {}", a, shift)?, + + Self::CompEq { a, b } => writeln!(f, "eq {} {}", a, b)?, + Self::CompNeg { a, b } => writeln!(f, "ne {} {}", a, b)?, + Self::CompLt { a, b } => writeln!(f, "lt {} {}", a, b)?, + Self::CompLe { a, b } => writeln!(f, "le {} {}", a, b)?, + Self::CompGt { a, b } => writeln!(f, "gt {} {}", a, b)?, + Self::CompGe { a, b } => writeln!(f, "ge {} {}", a, b)?, + + Self::IntegerSignedConstant { raw, bitsize } => { + writeln!(f, "constints {} {}", raw, bitsize)? + } + Self::IntegerUnsignedConstant { raw, bitsize } => { + writeln!(f, "constintu {} {}", raw, bitsize)? + } + + Self::FloatSignedConstant { raw, size } => writeln!(f, "constfs {} {}", raw, size)?, + Self::FloatUnsignedConstant { raw, size } => writeln!(f, "constfu {} {}", raw, size)?, + + Self::FixedSignedConstant { + raw, + number, + fraction, + } => writeln!(f, "constffs {} {} {}", raw, number, fraction)?, + Self::FixedUnsignedConstant { + raw, + number, + fraction, + } => writeln!(f, "constffu {} {} {}", raw, number, fraction)?, + + Self::StaticStringConstant { raw } => writeln!(f, "conststr {}", raw)?, + + Self::StructInitializerConstant { + struct_type: _, + values, + } => { + writeln!(f, "conststructinitrz")?; + + for v in values { + write!(f, " {}", v)?; + } + } + + Self::ArrayInitializerConstant { values } => { + writeln!(f, "constarrinitrz")?; + + for v in values { + write!(f, " {}", v)?; + } + } + + Self::ArrayInitializerConstantSame { size, val } => { + writeln!(f, "constarrinitrzsm {} {}", size, val)? + } + + Self::Return { val } => { + if val.is_some() { + writeln!(f, "ret {}", val.clone().unwrap())?; + } else { + writeln!(f, "ret")?; + } + } + + Self::UnconditionalBranch { branch } => writeln!(f, "ucondbr {}", branch)?, + Self::ConditionalBranch { + cond, + if_branch, + else_branch, + } => writeln!(f, "condbr {} {} {}", cond, if_branch, else_branch)?, + + Self::Phi { choices } => { + write!(f, "phi")?; + + for choice in choices { + write!(f, " [b{}, {}]", choice.0, choice.1)?; + } + + write!(f, "\n")?; + } + + Self::Select { + cond, + if_val, + else_val, + } => writeln!(f, "select {} {} {}", cond, if_val, else_val)?, + + Self::Call { + function, + arguments, + } => { + write!(f, "call {}", function)?; + + for arg in arguments { + write!(f, " {}", arg)?; + } + + write!(f, "\n")?; + } + + Self::FieldPointer { val, field } => writeln!(f, "fieldptr {} {}", val, field)?, + Self::IndexPointer { val, index } => writeln!(f, "indptr {} {}", val, index)?, + + Self::PointerAdd { pointer, right } => writeln!(f, "ptradd {} {}", pointer, right)?, + Self::PointerSub { pointer, right } => writeln!(f, "ptrsub {} {}", pointer, right)?, + + Self::FuncArgumentGrab { ind, argtype: _ } => writeln!(f, "funcarg {}", ind)?, + + Self::MarkerEraDrop { value } => writeln!(f, ".marker_era_drop {}", value)?, + Self::IRCast { val, to } => writeln!(f, ".ircastzz {} {}", val, to)?, + } + + Ok(()) + } } diff --git a/compiler/astoir_mir/src/insts/val.rs b/compiler/astoir_mir/src/insts/val.rs index 7749ffe..c971b53 100644 --- a/compiler/astoir_mir/src/insts/val.rs +++ b/compiler/astoir_mir/src/insts/val.rs @@ -3,18 +3,18 @@ use diagnostics::{DiagnosticResult, builders::make_invalid_instruction_held_val} use crate::vals::base::BaseMIRValue; pub struct InstructionValue { - pub val: Option + pub val: Option, } impl InstructionValue { - pub fn new(val: Option) -> Self { - return InstructionValue { val } - } - - pub fn get(self) -> DiagnosticResult { - match self.val { - Some(v) => return Ok(v), - None => return Err(make_invalid_instruction_held_val().into()) - } - } -} \ No newline at end of file + pub fn new(val: Option) -> Self { + return InstructionValue { val }; + } + + pub fn get(self) -> DiagnosticResult { + match self.val { + Some(v) => return Ok(v), + None => return Err(make_invalid_instruction_held_val().into()), + } + } +} diff --git a/compiler/astoir_mir/src/lib.rs b/compiler/astoir_mir/src/lib.rs index ebbe1c8..ee4987c 100644 --- a/compiler/astoir_mir/src/lib.rs +++ b/compiler/astoir_mir/src/lib.rs @@ -1,10 +1,10 @@ -//! The MIR layer of the AstoIR. +//! The MIR layer of the AstoIR. //! The MIR layer represents a block based representation of the program. Uses low level instructions near Assembly -//! -pub mod insts; -pub mod vals; +//! pub mod blocks; pub mod builder; -pub mod funcs; pub mod ctx; -pub mod inst_writer; \ No newline at end of file +pub mod funcs; +pub mod inst_writer; +pub mod insts; +pub mod vals; diff --git a/compiler/astoir_mir/src/vals/arrays.rs b/compiler/astoir_mir/src/vals/arrays.rs index 8ac66b2..ac33123 100644 --- a/compiler/astoir_mir/src/vals/arrays.rs +++ b/compiler/astoir_mir/src/vals/arrays.rs @@ -1,35 +1,35 @@ use std::fmt::Display; -use compiler_typing::{tree::Type}; +use compiler_typing::tree::Type; use diagnostics::{DiagnosticResult, builders::make_invalid_var_type_ir}; use crate::vals::base::BaseMIRValue; pub struct MIRArrayValue { - pub base: BaseMIRValue, - pub size: usize + pub base: BaseMIRValue, + pub size: usize, } impl MIRArrayValue { - pub fn new(base: BaseMIRValue) -> DiagnosticResult { - if let Type::Array(size, _) = base.vtype.clone() { - return Ok(MIRArrayValue { base, size }); - } + pub fn new(base: BaseMIRValue) -> DiagnosticResult { + if let Type::Array(size, _) = base.vtype.clone() { + return Ok(MIRArrayValue { base, size }); + } - return Err(make_invalid_var_type_ir().into()) - } + return Err(make_invalid_var_type_ir().into()); + } } impl Into for MIRArrayValue { - fn into(self) -> BaseMIRValue { - return self.base; - } + fn into(self) -> BaseMIRValue { + return self.base; + } } impl Display for MIRArrayValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.base.get_ssa_index())?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{}", self.base.get_ssa_index())?; - Ok(()) - } + Ok(()) + } } diff --git a/compiler/astoir_mir/src/vals/base.rs b/compiler/astoir_mir/src/vals/base.rs index 1557002..9e64b69 100644 --- a/compiler/astoir_mir/src/vals/base.rs +++ b/compiler/astoir_mir/src/vals/base.rs @@ -3,59 +3,64 @@ use std::fmt::Display; use compiler_typing::{raw::RawType, tree::Type}; use diagnostics::DiagnosticResult; -use crate::vals::{arrays::MIRArrayValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue, structs::MIRStructValue}; +use crate::vals::{ + arrays::MIRArrayValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue, + structs::MIRStructValue, +}; /// Represents a basic value in the MIR. #[derive(Clone, Debug)] pub struct BaseMIRValue { - val_index: usize, - pub vtype: Type + val_index: usize, + pub vtype: Type, } impl BaseMIRValue { - pub fn new(val_index: usize, vtype: Type) -> Self { - return BaseMIRValue { val_index, vtype } - } + pub fn new(val_index: usize, vtype: Type) -> Self { + return BaseMIRValue { val_index, vtype }; + } - pub fn as_int(&self) -> DiagnosticResult { - return Ok(MIRIntValue::new(self.clone())?); - } + pub fn as_int(&self) -> DiagnosticResult { + return Ok(MIRIntValue::new(self.clone())?); + } - pub fn as_float(&self) -> DiagnosticResult { - return Ok(MIRFloatValue::new(self.clone())?) - } + pub fn as_float(&self) -> DiagnosticResult { + return Ok(MIRFloatValue::new(self.clone())?); + } - pub fn as_ptr(&self) -> DiagnosticResult { - return Ok(MIRPointerValue::new(self.clone())?) - } + pub fn as_ptr(&self) -> DiagnosticResult { + return Ok(MIRPointerValue::new(self.clone())?); + } - pub fn as_struct(&self) -> DiagnosticResult { - return Ok(MIRStructValue::new(self.clone())?) - } + pub fn as_struct(&self) -> DiagnosticResult { + return Ok(MIRStructValue::new(self.clone())?); + } - pub fn as_array(&self) -> DiagnosticResult { - return Ok(MIRArrayValue::new(self.clone())?); - } + pub fn as_array(&self) -> DiagnosticResult { + return Ok(MIRArrayValue::new(self.clone())?); + } - pub fn can_be_pointer(&self) -> bool { - return self.vtype.is_technically_pointer() || self.vtype.is_array() || self.vtype.as_generic_lowered() == RawType::Pointer - } + pub fn can_be_pointer(&self) -> bool { + return self.vtype.is_technically_pointer() + || self.vtype.is_array() + || self.vtype.as_generic_lowered() == RawType::Pointer; + } - pub fn get_ssa_index(&self) -> usize { - return self.val_index; - } + pub fn get_ssa_index(&self) -> usize { + return self.val_index; + } } impl PartialEq for BaseMIRValue { - fn eq(&self, other: &Self) -> bool { - return self.val_index == other.val_index && self.vtype == other.vtype; - } + fn eq(&self, other: &Self) -> bool { + return self.val_index == other.val_index && self.vtype == other.vtype; + } } impl Display for BaseMIRValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.val_index)?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{}", self.val_index)?; - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/compiler/astoir_mir/src/vals/consts.rs b/compiler/astoir_mir/src/vals/consts.rs index d40e0a8..bea371e 100644 --- a/compiler/astoir_mir/src/vals/consts.rs +++ b/compiler/astoir_mir/src/vals/consts.rs @@ -1,5 +1,5 @@ #[derive(Clone, Debug)] pub enum MIRConstantValue { - Int(u128), - Float(f64) -} \ No newline at end of file + Int(u128), + Float(f64), +} diff --git a/compiler/astoir_mir/src/vals/float.rs b/compiler/astoir_mir/src/vals/float.rs index a355c7a..7822ba0 100644 --- a/compiler/astoir_mir/src/vals/float.rs +++ b/compiler/astoir_mir/src/vals/float.rs @@ -3,36 +3,39 @@ use std::fmt::Display; use compiler_typing::raw::RawType; use diagnostics::{DiagnosticResult, builders::make_invalid_var_type_ir}; -use crate::vals::base::{BaseMIRValue}; +use crate::vals::base::BaseMIRValue; #[derive(Clone)] pub struct MIRFloatValue { - base: BaseMIRValue, - pub signed: bool, - pub size: usize + base: BaseMIRValue, + pub signed: bool, + pub size: usize, } impl MIRFloatValue { - pub fn new(base: BaseMIRValue) -> DiagnosticResult { - if let RawType::Floating(size, signed) = base.vtype.as_generic_lowered() { - - return Ok(MIRFloatValue { base: base.clone(), size, signed }) - } - - return Err(make_invalid_var_type_ir().into()) - } + pub fn new(base: BaseMIRValue) -> DiagnosticResult { + if let RawType::Floating(size, signed) = base.vtype.as_generic_lowered() { + return Ok(MIRFloatValue { + base: base.clone(), + size, + signed, + }); + } + + return Err(make_invalid_var_type_ir().into()); + } } impl Into for MIRFloatValue { - fn into(self) -> BaseMIRValue { - return self.base; - } + fn into(self) -> BaseMIRValue { + return self.base; + } } impl Display for MIRFloatValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.base.get_ssa_index())?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{}", self.base.get_ssa_index())?; - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/compiler/astoir_mir/src/vals/int.rs b/compiler/astoir_mir/src/vals/int.rs index 01b2c33..8ecb236 100644 --- a/compiler/astoir_mir/src/vals/int.rs +++ b/compiler/astoir_mir/src/vals/int.rs @@ -3,39 +3,47 @@ use std::fmt::Display; use compiler_typing::raw::RawType; use diagnostics::{DiagnosticResult, builders::make_invalid_var_type_ir}; -use crate::vals::base::{BaseMIRValue}; +use crate::vals::base::BaseMIRValue; #[derive(Clone)] pub struct MIRIntValue { - pub base: BaseMIRValue, - pub signed: bool, - pub size: usize, + pub base: BaseMIRValue, + pub signed: bool, + pub size: usize, } impl MIRIntValue { - pub fn new(base: BaseMIRValue) -> DiagnosticResult { - if let RawType::Integer(size, signed) = base.vtype.clone().as_generic_lowered() { - return Ok(MIRIntValue { base: base.clone(), size, signed }) - } - - if let RawType::Boolean = base.vtype.clone().as_generic_lowered() { - return Ok(MIRIntValue { base: base.clone(), signed: false, size: 1 }) - } - - return Err(make_invalid_var_type_ir().into()) - } + pub fn new(base: BaseMIRValue) -> DiagnosticResult { + if let RawType::Integer(size, signed) = base.vtype.clone().as_generic_lowered() { + return Ok(MIRIntValue { + base: base.clone(), + size, + signed, + }); + } + + if let RawType::Boolean = base.vtype.clone().as_generic_lowered() { + return Ok(MIRIntValue { + base: base.clone(), + signed: false, + size: 1, + }); + } + + return Err(make_invalid_var_type_ir().into()); + } } impl Into for MIRIntValue { - fn into(self) -> BaseMIRValue { - return self.base; - } + fn into(self) -> BaseMIRValue { + return self.base; + } } impl Display for MIRIntValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.base.get_ssa_index())?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{}", self.base.get_ssa_index())?; - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/compiler/astoir_mir/src/vals/mod.rs b/compiler/astoir_mir/src/vals/mod.rs index 63ab81b..6b76086 100644 --- a/compiler/astoir_mir/src/vals/mod.rs +++ b/compiler/astoir_mir/src/vals/mod.rs @@ -1,36 +1,36 @@ //! The definitions for every value kind in the MIR. -use crate::{vals::{float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}}; +use crate::vals::{float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}; +pub mod arrays; pub mod base; -pub mod int; +pub mod consts; pub mod float; +pub mod int; pub mod ptr; -pub mod consts; pub mod refer; pub mod structs; -pub mod arrays; pub enum MIRAnyValue { - Int(MIRIntValue), - Float(MIRFloatValue), - Ptr(MIRPointerValue) + Int(MIRIntValue), + Float(MIRFloatValue), + Ptr(MIRPointerValue), } impl From for MIRAnyValue { - fn from(value: MIRIntValue) -> Self { - return MIRAnyValue::Int(value) - } + fn from(value: MIRIntValue) -> Self { + return MIRAnyValue::Int(value); + } } impl From for MIRAnyValue { - fn from(value: MIRFloatValue) -> Self { - return MIRAnyValue::Float(value) - } + fn from(value: MIRFloatValue) -> Self { + return MIRAnyValue::Float(value); + } } impl From for MIRAnyValue { - fn from(value: MIRPointerValue) -> Self { - return MIRAnyValue::Ptr(value) - } -} \ No newline at end of file + fn from(value: MIRPointerValue) -> Self { + return MIRAnyValue::Ptr(value); + } +} diff --git a/compiler/astoir_mir/src/vals/ptr.rs b/compiler/astoir_mir/src/vals/ptr.rs index 48b3c0a..cca9bb7 100644 --- a/compiler/astoir_mir/src/vals/ptr.rs +++ b/compiler/astoir_mir/src/vals/ptr.rs @@ -3,33 +3,36 @@ use std::fmt::Display; use compiler_typing::raw::RawType; use diagnostics::{DiagnosticResult, builders::make_invalid_var_type_ir}; -use crate::vals::base::{BaseMIRValue}; +use crate::vals::base::BaseMIRValue; #[derive(Clone, Debug)] pub struct MIRPointerValue { - base: BaseMIRValue + base: BaseMIRValue, } impl MIRPointerValue { - pub fn new(base: BaseMIRValue) -> DiagnosticResult { - if base.vtype.is_technically_pointer() || base.vtype.is_array() || base.vtype.as_generic_lowered() == RawType::Pointer { - return Ok(MIRPointerValue { base: base.clone() }) - } - - return Err(make_invalid_var_type_ir().into()) - } + pub fn new(base: BaseMIRValue) -> DiagnosticResult { + if base.vtype.is_technically_pointer() + || base.vtype.is_array() + || base.vtype.as_generic_lowered() == RawType::Pointer + { + return Ok(MIRPointerValue { base: base.clone() }); + } + + return Err(make_invalid_var_type_ir().into()); + } } impl Into for MIRPointerValue { - fn into(self) -> BaseMIRValue { - return self.base; - } + fn into(self) -> BaseMIRValue { + return self.base; + } } impl Display for MIRPointerValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.base.get_ssa_index())?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{}", self.base.get_ssa_index())?; - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/compiler/astoir_mir/src/vals/refer.rs b/compiler/astoir_mir/src/vals/refer.rs index 863eda0..5b43bd9 100644 --- a/compiler/astoir_mir/src/vals/refer.rs +++ b/compiler/astoir_mir/src/vals/refer.rs @@ -1,120 +1,146 @@ use compiler_typing::storage::TypeStorage; use diagnostics::{DiagnosticResult, builders::make_invalid_assign_diff_type_ir, unsure_panic}; -use crate::{blocks::refer::MIRBlockReference, builder::{build_load, build_store}, ctx::MIRContext, vals::{base::BaseMIRValue, ptr::{MIRPointerValue}}}; +use crate::{ + blocks::refer::MIRBlockReference, + builder::{build_load, build_store}, + ctx::MIRContext, + vals::{base::BaseMIRValue, ptr::MIRPointerValue}, +}; /// Represents a reference to a variable. This is not a reference to individual SSA values. -/// +/// /// # Variables /// Variables can be either: -/// - A pointer (using `store` and `load`) +/// - A pointer (using `store` and `load`) /// - SSA handled variable (stores variable ID -> current SSA value for the variable) -/// +/// /// # Finding Guarantee /// This reference guarantees to point to valid variable within a function. Please note that a reference can **only** be used in the function it was created in. /// No Safety has been put in place to limit these errors as these references should never leave their origin function anyways -/// +/// /// # Usage /// This can be used to reference any true variable to modify it's content or read it. This will automatically handle diverse instructions needed such as `load` and `store`. #[derive(Debug)] pub enum MIRVariableReference { - PointerReference(MIRPointerValue), - SSAReference(usize) + PointerReference(MIRPointerValue), + SSAReference(usize), } impl MIRVariableReference { - pub fn read(&self, block: MIRBlockReference, ctx: &mut MIRContext) -> DiagnosticResult { - if self.is_pointer_ref() { - let ptr_ref = self.as_pointer_ref()?; - - let res = build_load(ctx, ptr_ref)?; - - return Ok(res); - } - - let ind = self.as_ssa_ref()?; - - return match &ctx.blocks[block].variables[&ind].hint { - Some(v) => Ok(v.clone()), - None => unsure_panic!("cannot unpack SSA reference for variable in MIRVariableReference::read") - } - } - - pub fn write(&self, block: MIRBlockReference, ctx: &mut MIRContext, val: BaseMIRValue, storage: &TypeStorage) -> DiagnosticResult { - if self.is_pointer_ref() { - let mut ptr_ref = self.as_pointer_ref()?; - let hint = ctx.ssa_hints.get_hint(BaseMIRValue::from(ptr_ref.clone().into()).get_ssa_index()); - - if hint.get_type().is_technically_pointer() { - ptr_ref = build_load(ctx, ptr_ref)?.as_ptr()?; - } - - build_store(ctx, storage, ptr_ref, val)?; - - return Ok(true); - } - - let ind = self.as_ssa_ref()?; - - let block = &mut ctx.blocks[block]; - - if block.variables[&ind].hint.is_some() && !block.variables[&ind].hint.clone().unwrap().vtype.is_truly_eq(&val.vtype) { - return Err(make_invalid_assign_diff_type_ir().into()); - } - - let mut hint = block.variables[&ind].clone(); - hint.hint = Some(val); - - block.variables.insert(ind, hint); - - return Ok(true); - } - - pub fn get_hint(&self) -> usize { - return match self { - Self::PointerReference(e) => { - let clone: BaseMIRValue = e.clone().into(); - - return clone.get_ssa_index(); - }, - Self::SSAReference(e) => *e - } - } - - pub fn is_pointer_ref(&self) -> bool { - return match self { - Self::PointerReference(_) => true, - _ => false - } - } - - pub fn as_pointer_ref(&self) -> DiagnosticResult { - return match self { - Self::PointerReference(e) => Ok(e.clone()), - _ => unsure_panic!("as_pointer_ref requires a pointer var ref!") - } - } - - pub fn as_ssa_ref(&self) -> DiagnosticResult { - return match self { - Self::SSAReference(e) => Ok(*e), - _ => unsure_panic!("as_ssa_ref requires a SSA var ref!") - } - } - - pub fn is_ssa_ref(&self) -> bool { - return !self.is_pointer_ref(); - } + pub fn read( + &self, + block: MIRBlockReference, + ctx: &mut MIRContext, + ) -> DiagnosticResult { + if self.is_pointer_ref() { + let ptr_ref = self.as_pointer_ref()?; + + let res = build_load(ctx, ptr_ref)?; + + return Ok(res); + } + + let ind = self.as_ssa_ref()?; + + return match &ctx.blocks[block].variables[&ind].hint { + Some(v) => Ok(v.clone()), + None => unsure_panic!( + "cannot unpack SSA reference for variable in MIRVariableReference::read" + ), + }; + } + + pub fn write( + &self, + block: MIRBlockReference, + ctx: &mut MIRContext, + val: BaseMIRValue, + storage: &TypeStorage, + ) -> DiagnosticResult { + if self.is_pointer_ref() { + let mut ptr_ref = self.as_pointer_ref()?; + let hint = ctx + .ssa_hints + .get_hint(BaseMIRValue::from(ptr_ref.clone().into()).get_ssa_index()); + + if hint.get_type().is_technically_pointer() { + ptr_ref = build_load(ctx, ptr_ref)?.as_ptr()?; + } + + build_store(ctx, storage, ptr_ref, val)?; + + return Ok(true); + } + + let ind = self.as_ssa_ref()?; + + let block = &mut ctx.blocks[block]; + + if block.variables[&ind].hint.is_some() + && !block.variables[&ind] + .hint + .clone() + .unwrap() + .vtype + .is_truly_eq(&val.vtype) + { + return Err(make_invalid_assign_diff_type_ir().into()); + } + + let mut hint = block.variables[&ind].clone(); + hint.hint = Some(val); + + block.variables.insert(ind, hint); + + return Ok(true); + } + + pub fn get_hint(&self) -> usize { + return match self { + Self::PointerReference(e) => { + let clone: BaseMIRValue = e.clone().into(); + + return clone.get_ssa_index(); + } + Self::SSAReference(e) => *e, + }; + } + + pub fn is_pointer_ref(&self) -> bool { + return match self { + Self::PointerReference(_) => true, + _ => false, + }; + } + + pub fn as_pointer_ref(&self) -> DiagnosticResult { + return match self { + Self::PointerReference(e) => Ok(e.clone()), + _ => unsure_panic!("as_pointer_ref requires a pointer var ref!"), + }; + } + + pub fn as_ssa_ref(&self) -> DiagnosticResult { + return match self { + Self::SSAReference(e) => Ok(*e), + _ => unsure_panic!("as_ssa_ref requires a SSA var ref!"), + }; + } + + pub fn is_ssa_ref(&self) -> bool { + return !self.is_pointer_ref(); + } } impl From for MIRVariableReference { - fn from(value: MIRPointerValue) -> Self { - return MIRVariableReference::PointerReference(value) - } + fn from(value: MIRPointerValue) -> Self { + return MIRVariableReference::PointerReference(value); + } } impl From for MIRVariableReference { - fn from(value: usize) -> Self { - return MIRVariableReference::SSAReference(value) - } -} \ No newline at end of file + fn from(value: usize) -> Self { + return MIRVariableReference::SSAReference(value); + } +} diff --git a/compiler/astoir_mir/src/vals/structs.rs b/compiler/astoir_mir/src/vals/structs.rs index 91ef80c..a6f02e5 100644 --- a/compiler/astoir_mir/src/vals/structs.rs +++ b/compiler/astoir_mir/src/vals/structs.rs @@ -6,30 +6,33 @@ use diagnostics::{DiagnosticResult, builders::make_invalid_var_type_ir}; use crate::vals::base::BaseMIRValue; pub struct MIRStructValue { - pub base: BaseMIRValue, - pub t: RawType, + pub base: BaseMIRValue, + pub t: RawType, } impl MIRStructValue { - pub fn new(base: BaseMIRValue) -> DiagnosticResult { - if let RawType::LoweredStruct(_, _) = base.vtype.clone().as_generic_lowered() { - return Ok(MIRStructValue { base: base.clone(), t: base.vtype.clone().as_generic_lowered() }) - } - - return Err(make_invalid_var_type_ir().into()) - } + pub fn new(base: BaseMIRValue) -> DiagnosticResult { + if let RawType::LoweredStruct(_, _) = base.vtype.clone().as_generic_lowered() { + return Ok(MIRStructValue { + base: base.clone(), + t: base.vtype.clone().as_generic_lowered(), + }); + } + + return Err(make_invalid_var_type_ir().into()); + } } impl Into for MIRStructValue { - fn into(self) -> BaseMIRValue { - return self.base; - } + fn into(self) -> BaseMIRValue { + return self.base; + } } impl Display for MIRStructValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "#{}", self.base.get_ssa_index())?; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "#{}", self.base.get_ssa_index())?; - Ok(()) - } + Ok(()) + } } diff --git a/compiler/astoir_mir_lowering/src/arrays.rs b/compiler/astoir_mir_lowering/src/arrays.rs index 7b6a653..7eb9b14 100644 --- a/compiler/astoir_mir_lowering/src/arrays.rs +++ b/compiler/astoir_mir_lowering/src/arrays.rs @@ -1,39 +1,66 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_index_pointer, build_load, build_store}, vals::base::BaseMIRValue}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{build_index_pointer, build_load, build_store}, + vals::base::BaseMIRValue, +}; use diagnostics::{DiagnosticResult, unsure_panic}; use crate::{MIRLoweringContext, values::lower_hir_value}; -pub fn lower_hir_aray_index_access(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::ArrayIndexAccess { val, index } = node.kind { - let array = lower_hir_value(block, val, ctx)?; +pub fn lower_hir_aray_index_access( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::ArrayIndexAccess { val, index } = node.kind { + let array = lower_hir_value(block, val, ctx)?; - if ctx.mir_ctx.ssa_hints.get_hint(array.get_ssa_index()).is_pointer() { - let index = lower_hir_value(block, index, ctx)?.as_int()?; + if ctx + .mir_ctx + .ssa_hints + .get_hint(array.get_ssa_index()) + .is_pointer() + { + let index = lower_hir_value(block, index, ctx)?.as_int()?; - let res = build_index_pointer(&mut ctx.mir_ctx, array.as_ptr()?, index)?; + let res = build_index_pointer(&mut ctx.mir_ctx, array.as_ptr()?, index)?; - return build_load(&mut ctx.mir_ctx, res); - } else { - unsure_panic!("tried lowering a non SSA array!") - } - } + return build_load(&mut ctx.mir_ctx, res); + } else { + unsure_panic!("tried lowering a non SSA array!") + } + } - panic!("Invalid node type") + panic!("Invalid node type") } -pub fn lower_hir_array_modify(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::ArrayIndexModify { array, index, new_val } = node.kind.clone() { - let array = lower_hir_value(block, array, ctx)?.as_ptr()?; - let index = lower_hir_value(block, index, ctx)?.as_int()?; - let val = lower_hir_value(block, new_val, ctx)?; +pub fn lower_hir_array_modify( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::ArrayIndexModify { + array, + index, + new_val, + } = node.kind.clone() + { + let array = lower_hir_value(block, array, ctx)?.as_ptr()?; + let index = lower_hir_value(block, index, ctx)?.as_int()?; + let val = lower_hir_value(block, new_val, ctx)?; - let index_pointer = build_index_pointer(&mut ctx.mir_ctx, array, index)?; + let index_pointer = build_index_pointer(&mut ctx.mir_ctx, array, index)?; - build_store(&mut ctx.mir_ctx, &ctx.hir_ctx.type_storage, index_pointer, val)?; + build_store( + &mut ctx.mir_ctx, + &ctx.hir_ctx.type_storage, + index_pointer, + val, + )?; - return Ok(true); - } + return Ok(true); + } - panic!("Invalid node type") -} \ No newline at end of file + panic!("Invalid node type") +} diff --git a/compiler/astoir_mir_lowering/src/body.rs b/compiler/astoir_mir_lowering/src/body.rs index 96b93d3..493d33a 100644 --- a/compiler/astoir_mir_lowering/src/body.rs +++ b/compiler/astoir_mir_lowering/src/body.rs @@ -1,61 +1,87 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; use astoir_mir::{blocks::refer::MIRBlockReference, insts::MIRInstruction}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_math_operation_req_assign, move_current_diagnostic_pos}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, builders::make_math_operation_req_assign, + move_current_diagnostic_pos, +}; -use crate::{MIRLoweringContext, arrays::lower_hir_array_modify, control::{forloop::lower_hir_for_loop, ifstatement::lower_hir_if_statement}, funcs::lower_hir_function_call, introductions::handle_var_introduction_queue, math::lower_hir_math_operation, values::lower_hir_value, vars::{lower_hir_variable_assignment, lower_hir_variable_declaration}}; +use crate::{ + MIRLoweringContext, + arrays::lower_hir_array_modify, + control::{forloop::lower_hir_for_loop, ifstatement::lower_hir_if_statement}, + funcs::lower_hir_function_call, + introductions::handle_var_introduction_queue, + math::lower_hir_math_operation, + values::lower_hir_value, + vars::{lower_hir_variable_assignment, lower_hir_variable_declaration}, +}; -pub fn lower_hir_body_member(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - move_current_diagnostic_pos(node.get_pos()); +pub fn lower_hir_body_member( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + move_current_diagnostic_pos(node.get_pos()); - let queue = ctx.block_introduction_var_queue.clone(); - for n in queue { - handle_var_introduction_queue(block, n.clone(), ctx)?; - } - - return match node.kind.clone() { - HIRNodeKind::VarAssigment { .. } => lower_hir_variable_assignment(block, node, ctx), - HIRNodeKind::VarDeclaration { .. } => lower_hir_variable_declaration(block, node, ctx), - HIRNodeKind::MathOperation { left: _, right: _, operation } => { - if !operation.assigns { - return Err(make_math_operation_req_assign(&*node).into()) - } + let queue = ctx.block_introduction_var_queue.clone(); + for n in queue { + handle_var_introduction_queue(block, n.clone(), ctx)?; + } - lower_hir_math_operation(block, node, ctx)?; + return match node.kind.clone() { + HIRNodeKind::VarAssigment { .. } => lower_hir_variable_assignment(block, node, ctx), + HIRNodeKind::VarDeclaration { .. } => lower_hir_variable_declaration(block, node, ctx), + HIRNodeKind::MathOperation { + left: _, + right: _, + operation, + } => { + if !operation.assigns { + return Err(make_math_operation_req_assign(&*node).into()); + } - return Ok(true); - }, + lower_hir_math_operation(block, node, ctx)?; - HIRNodeKind::ArrayIndexModify { .. } => lower_hir_array_modify(block, node, ctx), + return Ok(true); + } - HIRNodeKind::ForBlock { .. } => lower_hir_for_loop(block, node, ctx), - HIRNodeKind::IfStatement { .. } => lower_hir_if_statement(block, node, ctx), - HIRNodeKind::FunctionCall { .. } => { - lower_hir_function_call(block, node, ctx)?; + HIRNodeKind::ArrayIndexModify { .. } => lower_hir_array_modify(block, node, ctx), - return Ok(true) - }, + HIRNodeKind::ForBlock { .. } => lower_hir_for_loop(block, node, ctx), + HIRNodeKind::IfStatement { .. } => lower_hir_if_statement(block, node, ctx), + HIRNodeKind::FunctionCall { .. } => { + lower_hir_function_call(block, node, ctx)?; - HIRNodeKind::ReturnStatement { value } => { - if value.is_some() { - let val = lower_hir_value(block, value.unwrap(), ctx)?; + return Ok(true); + } - ctx.mir_ctx.append_inst(MIRInstruction::Return { val: Some(val) }); - return Ok(true); - } + HIRNodeKind::ReturnStatement { value } => { + if value.is_some() { + let val = lower_hir_value(block, value.unwrap(), ctx)?; - ctx.mir_ctx.append_inst(MIRInstruction::Return { val: None }); + ctx.mir_ctx + .append_inst(MIRInstruction::Return { val: Some(val) }); + return Ok(true); + } - return Ok(true); - } + ctx.mir_ctx + .append_inst(MIRInstruction::Return { val: None }); - _ => panic!("Invalid node") - } + return Ok(true); + } + + _ => panic!("Invalid node"), + }; } -pub fn lower_hir_body(block: MIRBlockReference, nodes: Vec>, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - for node in nodes { - lower_hir_body_member(block, node, ctx)?; - } +pub fn lower_hir_body( + block: MIRBlockReference, + nodes: Vec>, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + for node in nodes { + lower_hir_body_member(block, node, ctx)?; + } - return Ok(true); -} \ No newline at end of file + return Ok(true); +} diff --git a/compiler/astoir_mir_lowering/src/casts.rs b/compiler/astoir_mir_lowering/src/casts.rs index 385b237..8520c88 100644 --- a/compiler/astoir_mir_lowering/src/casts.rs +++ b/compiler/astoir_mir_lowering/src/casts.rs @@ -1,28 +1,52 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::{hints::MIRValueHint, refer::MIRBlockReference}, vals::base::BaseMIRValue}; +use astoir_mir::{ + blocks::{hints::MIRValueHint, refer::MIRBlockReference}, + vals::base::BaseMIRValue, +}; use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; -pub fn lower_cast(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::CastValue { intentional: _, value, old_type, new_type } = node.kind.clone() { - let value = lower_hir_value(block, value, ctx)?; - let old_type = lower_hir_type(ctx, old_type)?; +pub fn lower_cast( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::CastValue { + intentional: _, + value, + old_type, + new_type, + } = node.kind.clone() + { + let value = lower_hir_value(block, value, ctx)?; + let old_type = lower_hir_type(ctx, old_type)?; - let new_type = lower_hir_type(ctx, new_type)?; + let new_type = lower_hir_type(ctx, new_type)?; - if old_type.get_generic(&ctx.hir_ctx.type_storage).is_enum_child() && new_type.get_generic(&ctx.hir_ctx.type_storage).is_enum_parent() { - match ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] { - MIRValueHint::Pointer(_) => ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] = MIRValueHint::Pointer(new_type), - MIRValueHint::Value(_) => ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] = MIRValueHint::Value(new_type), - _ => panic!("constant enum cast") - } + if old_type + .get_generic(&ctx.hir_ctx.type_storage) + .is_enum_child() + && new_type + .get_generic(&ctx.hir_ctx.type_storage) + .is_enum_parent() + { + match ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] { + MIRValueHint::Pointer(_) => { + ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] = + MIRValueHint::Pointer(new_type) + } + MIRValueHint::Value(_) => { + ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] = MIRValueHint::Value(new_type) + } + _ => panic!("constant enum cast"), + } - return Ok(value); - } + return Ok(value); + } - panic!("Bad castt {:#?} -> {:#?}", old_type, new_type); - } + panic!("Bad castt {:#?} -> {:#?}", old_type, new_type); + } - panic!("Invalid node or cast!") -} \ No newline at end of file + panic!("Invalid node or cast!") +} diff --git a/compiler/astoir_mir_lowering/src/control/forloop.rs b/compiler/astoir_mir_lowering/src/control/forloop.rs index b896cb4..22f8d0f 100644 --- a/compiler/astoir_mir_lowering/src/control/forloop.rs +++ b/compiler/astoir_mir_lowering/src/control/forloop.rs @@ -1,48 +1,63 @@ //! Lowering for for loops use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::{MIRBlock, refer::MIRBlockReference}, builder::{build_conditional_branch, build_unconditional_branch}}; +use astoir_mir::{ + blocks::{MIRBlock, refer::MIRBlockReference}, + builder::{build_conditional_branch, build_unconditional_branch}, +}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos}; -use crate::{MIRLoweringContext, body::lower_hir_body, math::lower_hir_math_operation, values::lower_hir_value, vars::lower_hir_variable_declaration}; +use crate::{ + MIRLoweringContext, body::lower_hir_body, math::lower_hir_math_operation, + values::lower_hir_value, vars::lower_hir_variable_declaration, +}; -pub fn lower_hir_for_loop(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::ForBlock { initial_state, condition, incrementation, body } = node.kind.clone() { - let header_ref = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - let cond_ref = MIRBlock::new_merge(header_ref, &mut ctx.mir_ctx, false); - let body_ref = MIRBlock::new_merge(header_ref, &mut ctx.mir_ctx, false); - let exit_ref = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); +pub fn lower_hir_for_loop( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::ForBlock { + initial_state, + condition, + incrementation, + body, + } = node.kind.clone() + { + let header_ref = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); + let cond_ref = MIRBlock::new_merge(header_ref, &mut ctx.mir_ctx, false); + let body_ref = MIRBlock::new_merge(header_ref, &mut ctx.mir_ctx, false); + let exit_ref = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - ctx.mir_ctx.blocks[header_ref].merge_blocks.push(block); - ctx.mir_ctx.blocks[header_ref].merge_blocks.push(body_ref); + ctx.mir_ctx.blocks[header_ref].merge_blocks.push(block); + ctx.mir_ctx.blocks[header_ref].merge_blocks.push(body_ref); - move_current_diagnostic_pos(initial_state.get_pos()); - lower_hir_variable_declaration(block, initial_state, ctx)?; + move_current_diagnostic_pos(initial_state.get_pos()); + lower_hir_variable_declaration(block, initial_state, ctx)?; - ctx.mir_ctx.writer.move_end(body_ref); + ctx.mir_ctx.writer.move_end(body_ref); - lower_hir_body(body_ref, body, ctx)?; + lower_hir_body(body_ref, body, ctx)?; - move_current_diagnostic_pos(incrementation.get_pos()); - lower_hir_math_operation(body_ref, incrementation, ctx)?; + move_current_diagnostic_pos(incrementation.get_pos()); + lower_hir_math_operation(body_ref, incrementation, ctx)?; - build_unconditional_branch(&mut ctx.mir_ctx, header_ref)?; + build_unconditional_branch(&mut ctx.mir_ctx, header_ref)?; - ctx.mir_ctx.writer.move_end(header_ref); + ctx.mir_ctx.writer.move_end(header_ref); - ctx.mir_ctx.resolve_ssa(header_ref)?; - build_unconditional_branch(&mut ctx.mir_ctx, cond_ref)?; + ctx.mir_ctx.resolve_ssa(header_ref)?; + build_unconditional_branch(&mut ctx.mir_ctx, cond_ref)?; - ctx.mir_ctx.writer.move_end(cond_ref); - - move_current_diagnostic_pos(condition.get_pos()); - let cond_val = lower_hir_value(block, condition, ctx)?; + ctx.mir_ctx.writer.move_end(cond_ref); - build_conditional_branch(&mut ctx.mir_ctx, cond_val.as_int()?, body_ref, exit_ref)?; + move_current_diagnostic_pos(condition.get_pos()); + let cond_val = lower_hir_value(block, condition, ctx)?; - ctx.mir_ctx.writer.move_end(exit_ref); + build_conditional_branch(&mut ctx.mir_ctx, cond_val.as_int()?, body_ref, exit_ref)?; - } + ctx.mir_ctx.writer.move_end(exit_ref); + } - panic!("Invalid node") -} \ No newline at end of file + panic!("Invalid node") +} diff --git a/compiler/astoir_mir_lowering/src/control/ifstatement.rs b/compiler/astoir_mir_lowering/src/control/ifstatement.rs index 547944f..179166e 100644 --- a/compiler/astoir_mir_lowering/src/control/ifstatement.rs +++ b/compiler/astoir_mir_lowering/src/control/ifstatement.rs @@ -1,107 +1,128 @@ -use astoir_hir::{nodes::{HIRNode, HIRNodeKind}, structs::HIRIfBranch}; -use astoir_mir::{blocks::{MIRBlock, refer::MIRBlockReference}, builder::{build_conditional_branch, build_unconditional_branch}}; +use astoir_hir::{ + nodes::{HIRNode, HIRNodeKind}, + structs::HIRIfBranch, +}; +use astoir_mir::{ + blocks::{MIRBlock, refer::MIRBlockReference}, + builder::{build_conditional_branch, build_unconditional_branch}, +}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos}; use crate::{MIRLoweringContext, body::lower_hir_body, values::lower_hir_value}; -pub fn lower_hir_if_statement(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::IfStatement { branches } = node.kind.clone() { - let merge_ref = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - let mut branch_blocks = vec![]; +pub fn lower_hir_if_statement( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::IfStatement { branches } = node.kind.clone() { + let merge_ref = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); + let mut branch_blocks = vec![]; - ctx.mir_ctx.blocks[merge_ref].merge_blocks.push(block); + ctx.mir_ctx.blocks[merge_ref].merge_blocks.push(block); - for branch in &branches { - match branch { - &HIRIfBranch::IfBranch { .. } => { - let ifbranch_body = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); + for branch in &branches { + match branch { + &HIRIfBranch::IfBranch { .. } => { + let ifbranch_body = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - branch_blocks.push(ifbranch_body); + branch_blocks.push(ifbranch_body); - ctx.mir_ctx.blocks[merge_ref].merge_blocks.push(ifbranch_body); - }, + ctx.mir_ctx.blocks[merge_ref] + .merge_blocks + .push(ifbranch_body); + } - &HIRIfBranch::ElseIfBranch { .. } => { - let ifelsebranch_cond = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - let ifelsebranch_body = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); + &HIRIfBranch::ElseIfBranch { .. } => { + let ifelsebranch_cond = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); + let ifelsebranch_body = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - branch_blocks.push(ifelsebranch_cond); - branch_blocks.push(ifelsebranch_body); + branch_blocks.push(ifelsebranch_cond); + branch_blocks.push(ifelsebranch_body); - ctx.mir_ctx.blocks[merge_ref].merge_blocks.push(ifelsebranch_body); - }, + ctx.mir_ctx.blocks[merge_ref] + .merge_blocks + .push(ifelsebranch_body); + } - &HIRIfBranch::ElseBranch { .. } => { - let else_body = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); + &HIRIfBranch::ElseBranch { .. } => { + let else_body = MIRBlock::new_merge(block, &mut ctx.mir_ctx, false); - branch_blocks.push(else_body); + branch_blocks.push(else_body); - ctx.mir_ctx.blocks[merge_ref].merge_blocks.push(else_body); - } - } - } + ctx.mir_ctx.blocks[merge_ref].merge_blocks.push(else_body); + } + } + } - branch_blocks.push(merge_ref); // Allows for array usage for branch descending + branch_blocks.push(merge_ref); // Allows for array usage for branch descending + let mut branch_ind = 0; - let mut branch_ind = 0; + for branch in branches { + match branch { + HIRIfBranch::IfBranch { cond, body } => { + ctx.mir_ctx.writer.move_end(block); - for branch in branches { - match branch { - HIRIfBranch::IfBranch { cond, body } => { - ctx.mir_ctx.writer.move_end(block); + move_current_diagnostic_pos(cond.get_pos()); + let val = lower_hir_value(block, cond, ctx)?.as_int()?; - move_current_diagnostic_pos(cond.get_pos()); - let val = lower_hir_value(block, cond, ctx)?.as_int()?; + build_conditional_branch( + &mut ctx.mir_ctx, + val, + branch_blocks[branch_ind], + branch_blocks[branch_ind + 1], + )?; - build_conditional_branch(&mut ctx.mir_ctx, val, branch_blocks[branch_ind], branch_blocks[branch_ind + 1])?; - - ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); + ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); - lower_hir_body(branch_blocks[branch_ind], body, ctx)?; + lower_hir_body(branch_blocks[branch_ind], body, ctx)?; - build_unconditional_branch(&mut ctx.mir_ctx, merge_ref)?; + build_unconditional_branch(&mut ctx.mir_ctx, merge_ref)?; - branch_ind += 1; - }, + branch_ind += 1; + } - HIRIfBranch::ElseIfBranch { cond, body } => { - ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); + HIRIfBranch::ElseIfBranch { cond, body } => { + ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); - move_current_diagnostic_pos(cond.get_pos()); - let val = lower_hir_value(branch_blocks[branch_ind], cond, ctx)?.as_int()?; + move_current_diagnostic_pos(cond.get_pos()); + let val = lower_hir_value(branch_blocks[branch_ind], cond, ctx)?.as_int()?; - build_conditional_branch(&mut ctx.mir_ctx, val, branch_blocks[branch_ind + 1], branch_blocks[branch_ind + 2])?; - - branch_ind += 1; - ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); + build_conditional_branch( + &mut ctx.mir_ctx, + val, + branch_blocks[branch_ind + 1], + branch_blocks[branch_ind + 2], + )?; - lower_hir_body(branch_blocks[branch_ind], body, ctx)?; + branch_ind += 1; + ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); - build_unconditional_branch(&mut ctx.mir_ctx, merge_ref)?; + lower_hir_body(branch_blocks[branch_ind], body, ctx)?; - branch_ind += 1 - }, + build_unconditional_branch(&mut ctx.mir_ctx, merge_ref)?; - HIRIfBranch::ElseBranch { body } => { - ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); + branch_ind += 1 + } - lower_hir_body(branch_blocks[branch_ind], body, ctx)?; + HIRIfBranch::ElseBranch { body } => { + ctx.mir_ctx.writer.move_end(branch_blocks[branch_ind]); - build_unconditional_branch(&mut ctx.mir_ctx, merge_ref)?; + lower_hir_body(branch_blocks[branch_ind], body, ctx)?; - branch_ind += 1; - } + build_unconditional_branch(&mut ctx.mir_ctx, merge_ref)?; - } - } + branch_ind += 1; + } + } + } - ctx.mir_ctx.writer.move_end(merge_ref); - ctx.mir_ctx.resolve_ssa(merge_ref)?; + ctx.mir_ctx.writer.move_end(merge_ref); + ctx.mir_ctx.resolve_ssa(merge_ref)?; - return Ok(true); - } - - panic!("Invalid node"); -} + return Ok(true); + } + panic!("Invalid node"); +} diff --git a/compiler/astoir_mir_lowering/src/control/mod.rs b/compiler/astoir_mir_lowering/src/control/mod.rs index cbb0e5d..f13bb45 100644 --- a/compiler/astoir_mir_lowering/src/control/mod.rs +++ b/compiler/astoir_mir_lowering/src/control/mod.rs @@ -1,4 +1,4 @@ //! Lowering for control blocks such as for blocks, if statements and more! pub mod forloop; -pub mod ifstatement; \ No newline at end of file +pub mod ifstatement; diff --git a/compiler/astoir_mir_lowering/src/funcs.rs b/compiler/astoir_mir_lowering/src/funcs.rs index 0f71c9d..358837f 100644 --- a/compiler/astoir_mir_lowering/src/funcs.rs +++ b/compiler/astoir_mir_lowering/src/funcs.rs @@ -1,96 +1,127 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_argument_grab, build_call}, funcs::MIRFunction, vals::base::BaseMIRValue}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{build_argument_grab, build_call}, + funcs::MIRFunction, + vals::base::BaseMIRValue, +}; use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, body::lower_hir_body, lower_hir_type, values::lower_hir_value}; -pub fn lower_hir_function_decl(node: Box, cctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::FunctionDeclaration { func_name, arguments, return_type, body, ctx: _, requires_this } = node.kind.clone() { - let mut args = vec![]; +pub fn lower_hir_function_decl( + node: Box, + cctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::FunctionDeclaration { + func_name, + arguments, + return_type, + body, + ctx: _, + requires_this, + } = node.kind.clone() + { + let mut args = vec![]; - for argument in arguments { - args.push(lower_hir_type(cctx, argument.1)?); - } + for argument in arguments { + args.push(lower_hir_type(cctx, argument.1)?); + } - let ret_type; + let ret_type; - if return_type.is_some() { - ret_type = Some(lower_hir_type(cctx, return_type.unwrap())?) - } else { - ret_type = None - } + if return_type.is_some() { + ret_type = Some(lower_hir_type(cctx, return_type.unwrap())?) + } else { + ret_type = None + } - let name = cctx.hir_ctx.functions.vals[func_name].2.clone(); + let name = cctx.hir_ctx.functions.vals[func_name].2.clone(); - let mut func = MIRFunction::new(name, args, ret_type, requires_this, &cctx.mir_ctx); - let block = func.append_entry_block(&mut cctx.mir_ctx); + let mut func = MIRFunction::new(name, args, ret_type, requires_this, &cctx.mir_ctx); + let block = func.append_entry_block(&mut cctx.mir_ctx); - cctx.mir_ctx.writer.move_end(block); + cctx.mir_ctx.writer.move_end(block); - let mut ind = 0; - for arg in &func.arguments { - build_argument_grab(&mut cctx.mir_ctx, ind, arg.clone())?; - ind += 1; - } + let mut ind = 0; + for arg in &func.arguments { + build_argument_grab(&mut cctx.mir_ctx, ind, arg.clone())?; + ind += 1; + } - cctx.mir_ctx.append_function(func); + cctx.mir_ctx.append_function(func); - lower_hir_body(block, body, cctx)?; + lower_hir_body(block, body, cctx)?; - return Ok(true) - } + return Ok(true); + } - panic!("Invalid node") + panic!("Invalid node") } +pub fn lower_hir_shadow_decl( + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::ShadowFunctionDeclaration { + func_name, + arguments, + return_type, + } = node.kind.clone() + { + let name = ctx.hir_ctx.functions.vals[func_name].2.clone(); -pub fn lower_hir_shadow_decl(node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::ShadowFunctionDeclaration { func_name, arguments, return_type } = node.kind.clone() { - let name = ctx.hir_ctx.functions.vals[func_name].2.clone(); + let mut args = vec![]; - let mut args = vec![]; + for argument in arguments { + args.push(lower_hir_type(ctx, argument.1)?); + } - for argument in arguments { - args.push(lower_hir_type(ctx, argument.1)?); - } + let ret_type; - let ret_type; + if return_type.is_some() { + ret_type = Some(lower_hir_type(ctx, return_type.unwrap())?) + } else { + ret_type = None + } - if return_type.is_some() { - ret_type = Some(lower_hir_type(ctx, return_type.unwrap())?) - } else { - ret_type = None - } + let func = MIRFunction::new(name, args, ret_type, false, &ctx.mir_ctx); - let func = MIRFunction::new(name, args, ret_type, false, &ctx.mir_ctx); + ctx.mir_ctx.append_function(func); + return Ok(true); + } - ctx.mir_ctx.append_function(func); - return Ok(true); - } - - panic!("Invalid node") + panic!("Invalid node") } -pub fn lower_hir_function_call(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult> { - if let HIRNodeKind::FunctionCall { func_name, arguments } = node.kind.clone() { - let mut args = vec![]; +pub fn lower_hir_function_call( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult> { + if let HIRNodeKind::FunctionCall { + func_name, + arguments, + } = node.kind.clone() + { + let mut args = vec![]; + + for arg in arguments { + let mir_val = lower_hir_value(block, arg, ctx)?; - for arg in arguments { - let mir_val = lower_hir_value(block, arg, ctx)?; - - args.push(mir_val); - } + args.push(mir_val); + } - let res = build_call(&mut ctx.mir_ctx, func_name, func_name, args)?; + let res = build_call(&mut ctx.mir_ctx, func_name, func_name, args)?; - if res.is_some() { - let res = res.unwrap(); + if res.is_some() { + let res = res.unwrap(); - return Ok(Some(res)); - } + return Ok(Some(res)); + } - return Ok(None); - } + return Ok(None); + } - panic!("Invalid node") -} \ No newline at end of file + panic!("Invalid node") +} diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index 9e54e53..1a3831f 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -1,31 +1,70 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::MIRBlockReference}, builder::{build_stack_alloc, build_store}}; +use astoir_mir::{ + blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::MIRBlockReference}, + builder::{build_stack_alloc, build_store}, +}; use compiler_typing::SizedType; -use diagnostics::{MaybeDiagnostic}; +use diagnostics::MaybeDiagnostic; -use crate::{MIRLoweringContext, lower_hir_type, type_tools::cast_to_enum_child, values::lower_hir_value}; +use crate::{ + MIRLoweringContext, lower_hir_type, type_tools::cast_to_enum_child, values::lower_hir_value, +}; -pub fn handle_var_introduction_queue(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> MaybeDiagnostic { - if let HIRNodeKind::UnwrapCondition { original, new_type, new_var, unsafe_unwrap: _ } = node.kind.clone() { - let original = lower_hir_value(block, original, ctx)?; - let new_type = lower_hir_type(ctx, new_type)?; - let func = ctx.mir_ctx.block_to_func[&block]; - let new_var = new_var.unwrap(); - let eligible = ctx.hir_ctx.function_contexts[func].as_ref().unwrap().is_eligible_for_ssa(new_var); +pub fn handle_var_introduction_queue( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> MaybeDiagnostic { + if let HIRNodeKind::UnwrapCondition { + original, + new_type, + new_var, + unsafe_unwrap: _, + } = node.kind.clone() + { + let original = lower_hir_value(block, original, ctx)?; + let new_type = lower_hir_type(ctx, new_type)?; + let func = ctx.mir_ctx.block_to_func[&block]; + let new_var = new_var.unwrap(); + let eligible = ctx.hir_ctx.function_contexts[func] + .as_ref() + .unwrap() + .is_eligible_for_ssa(new_var); - let casted = cast_to_enum_child(block, original, new_type.as_generic(), ctx, &*node)?; + let casted = cast_to_enum_child(block, original, new_type.as_generic(), ctx, &*node)?; - if eligible { - ctx.mir_ctx.blocks[block].variables.insert(new_var, MIRBlockVariableSSAHint { kind: MIRBlockVariableType::SSA, hint: Some(casted) }); - } else { - let ptr = build_stack_alloc(&mut ctx.mir_ctx, new_type.get_size(&new_type, false, &ctx .hir_ctx.type_storage), new_type)?; - - ctx.mir_ctx.blocks[block].variables.insert(new_var, MIRBlockVariableSSAHint { kind: MIRBlockVariableType::Pointer, hint: Some(ptr.clone().into()) }); - build_store(&mut ctx.mir_ctx, &ctx.hir_ctx.type_storage, ptr.clone(), casted)?; - } + if eligible { + ctx.mir_ctx.blocks[block].variables.insert( + new_var, + MIRBlockVariableSSAHint { + kind: MIRBlockVariableType::SSA, + hint: Some(casted), + }, + ); + } else { + let ptr = build_stack_alloc( + &mut ctx.mir_ctx, + new_type.get_size(&new_type, false, &ctx.hir_ctx.type_storage), + new_type, + )?; - return Ok(()) - } + ctx.mir_ctx.blocks[block].variables.insert( + new_var, + MIRBlockVariableSSAHint { + kind: MIRBlockVariableType::Pointer, + hint: Some(ptr.clone().into()), + }, + ); + build_store( + &mut ctx.mir_ctx, + &ctx.hir_ctx.type_storage, + ptr.clone(), + casted, + )?; + } - panic!("Invalid node") -} \ No newline at end of file + return Ok(()); + } + + panic!("Invalid node") +} diff --git a/compiler/astoir_mir_lowering/src/lib.rs b/compiler/astoir_mir_lowering/src/lib.rs index 5e6d181..6feae2c 100644 --- a/compiler/astoir_mir_lowering/src/lib.rs +++ b/compiler/astoir_mir_lowering/src/lib.rs @@ -1,6 +1,9 @@ -use std::{collections::HashMap}; +use std::collections::HashMap; -use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}}; +use astoir_hir::{ + ctx::HIRContext, + nodes::{HIRNode, HIRNodeKind}, +}; use astoir_mir::ctx::MIRContext; use compiler_typing::{SizedType, raw::RawType, structs::LoweredStructTypeContainer, tree::Type}; use compiler_utils::utils::indexed::IndexStorage; @@ -8,120 +11,197 @@ use diagnostics::{DiagnosticResult, unsure_panic}; use crate::funcs::{lower_hir_function_decl, lower_hir_shadow_decl}; -pub mod vars; -pub mod values; -pub mod math; -pub mod funcs; +pub mod arrays; pub mod body; +pub mod casts; pub mod control; -pub mod arrays; -pub mod type_tools; +pub mod funcs; pub mod introductions; -pub mod casts; pub mod lru; +pub mod math; +pub mod type_tools; +pub mod values; +pub mod vars; pub struct MIRLoweringContext { - pub hir_ctx: HIRContext, - pub mir_ctx: MIRContext, - pub block_introduction_var_queue: Vec> + pub hir_ctx: HIRContext, + pub mir_ctx: MIRContext, + pub block_introduction_var_queue: Vec>, } -pub fn lower_hir_top_level(node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - return match node.kind { - HIRNodeKind::FunctionDeclaration { .. } => lower_hir_function_decl(node, ctx), - HIRNodeKind::ShadowFunctionDeclaration { .. } => lower_hir_shadow_decl(node, ctx), - HIRNodeKind::StructDeclaration { .. } => { - // Since Struct declarations are already fulled lowered in HIR, we do need handling here! - - return Ok(true); - }, - - _ => panic!("Invalid tree") - } +pub fn lower_hir_top_level( + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + return match node.kind { + HIRNodeKind::FunctionDeclaration { .. } => lower_hir_function_decl(node, ctx), + HIRNodeKind::ShadowFunctionDeclaration { .. } => lower_hir_shadow_decl(node, ctx), + HIRNodeKind::StructDeclaration { .. } => { + // Since Struct declarations are already fulled lowered in HIR, we do need handling here! + + return Ok(true); + } + + _ => panic!("Invalid tree"), + }; } -pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { - let mut lowering_ctx = MIRLoweringContext { hir_ctx: ctx, mir_ctx: MIRContext::new(), block_introduction_var_queue: vec![] }; +pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { + let mut lowering_ctx = MIRLoweringContext { + hir_ctx: ctx, + mir_ctx: MIRContext::new(), + block_introduction_var_queue: vec![], + }; - let declarations = lowering_ctx.hir_ctx.function_declarations.clone(); + let declarations = lowering_ctx.hir_ctx.function_declarations.clone(); - for decl in declarations { - if let Some(node) = decl { - lower_hir_top_level(node, &mut lowering_ctx)?; - } - } + for decl in declarations { + if let Some(node) = decl { + lower_hir_top_level(node, &mut lowering_ctx)?; + } + } - return Ok(lowering_ctx.mir_ctx); + return Ok(lowering_ctx.mir_ctx); } -pub fn lower_hir_generic(ctx: &MIRLoweringContext, t: &Type, generic: &RawType) -> DiagnosticResult { - match generic { - RawType::Struct(a, b) => { - let mut lowered_container = LoweredStructTypeContainer { fields: IndexStorage::new(), functions: IndexStorage::new(), is_lowered_enum_child: false, is_lowered_enum_parent: false, lowered_enum_child: None, lowered_enum_parent: None, hir_mir_indexes: HashMap::new() }; - - for field in &b.fields.vals { - lowered_container.fields.vals.push(lower_hir_type(ctx, field.clone().resolve(t))?); - } - - return Ok(Type::GenericLowered(RawType::LoweredStruct(*a, lowered_container))); - }, - - RawType::EnumEntry(container) => { - let mut lowered_container = LoweredStructTypeContainer { fields: IndexStorage::new(), functions: IndexStorage::new(), is_lowered_enum_child: true, is_lowered_enum_parent: false, lowered_enum_child: Some(container.clone()), lowered_enum_parent: None, hir_mir_indexes: HashMap::new() }; - - let parent = match &ctx.hir_ctx.type_storage.types.vals[container.parent] { - RawType::Enum(container) => container.clone(), - _ => panic!("Enum parent not enum") - }; - - lowered_container.fields.vals.push(Type::GenericLowered(parent.get_hint_type())); // Enum entry hint - - let mut ind = 0; - for field in &container.fields.vals { - lowered_container.append_hir_index_conv(ind, lowered_container.fields.vals.len()); // Allow for LRU to work correctly - - lowered_container.fields.vals.push(lower_hir_type(ctx, field.clone().resolve(t))?); - - ind += 1; - } - - return Ok(Type::GenericLowered(RawType::LoweredStruct(false, lowered_container))); - }, - - RawType::Enum(container) => { - let mut lowered_container = LoweredStructTypeContainer { fields: IndexStorage::new(), functions: IndexStorage::new(), is_lowered_enum_child: false, is_lowered_enum_parent: true, lowered_enum_parent: Some(container.clone()), lowered_enum_child: None, hir_mir_indexes: HashMap::new() }; - - let mut entry_size = 0; - - let info = t.get_generic_info(); - - for entry in &container.entries { - let lowered = lower_hir_type(ctx, Type::Generic(entry.1.clone(), info.0.clone(), info.1.clone()))?; - - entry_size = entry_size.max(lowered.get_generic(&ctx.hir_ctx.type_storage).get_size(&lowered, false, &ctx.hir_ctx.type_storage)) - } - - lowered_container.fields.vals.push(Type::GenericLowered(container.get_hint_type())); - - lowered_container.fields.vals.push(Type::GenericLowered(RawType::Integer(entry_size, false))); - - return Ok(Type::GenericLowered(RawType::LoweredStruct(false, lowered_container))); - } - - _ => return Ok(Type::GenericLowered(generic.clone())) - }; +pub fn lower_hir_generic( + ctx: &MIRLoweringContext, + t: &Type, + generic: &RawType, +) -> DiagnosticResult { + match generic { + RawType::Struct(a, b) => { + let mut lowered_container = LoweredStructTypeContainer { + fields: IndexStorage::new(), + functions: IndexStorage::new(), + is_lowered_enum_child: false, + is_lowered_enum_parent: false, + lowered_enum_child: None, + lowered_enum_parent: None, + hir_mir_indexes: HashMap::new(), + }; + + for field in &b.fields.vals { + lowered_container + .fields + .vals + .push(lower_hir_type(ctx, field.clone().resolve(t))?); + } + + return Ok(Type::GenericLowered(RawType::LoweredStruct( + *a, + lowered_container, + ))); + } + + RawType::EnumEntry(container) => { + let mut lowered_container = LoweredStructTypeContainer { + fields: IndexStorage::new(), + functions: IndexStorage::new(), + is_lowered_enum_child: true, + is_lowered_enum_parent: false, + lowered_enum_child: Some(container.clone()), + lowered_enum_parent: None, + hir_mir_indexes: HashMap::new(), + }; + + let parent = match &ctx.hir_ctx.type_storage.types.vals[container.parent] { + RawType::Enum(container) => container.clone(), + _ => panic!("Enum parent not enum"), + }; + + lowered_container + .fields + .vals + .push(Type::GenericLowered(parent.get_hint_type())); // Enum entry hint + + let mut ind = 0; + for field in &container.fields.vals { + lowered_container.append_hir_index_conv(ind, lowered_container.fields.vals.len()); // Allow for LRU to work correctly + + lowered_container + .fields + .vals + .push(lower_hir_type(ctx, field.clone().resolve(t))?); + + ind += 1; + } + + return Ok(Type::GenericLowered(RawType::LoweredStruct( + false, + lowered_container, + ))); + } + + RawType::Enum(container) => { + let mut lowered_container = LoweredStructTypeContainer { + fields: IndexStorage::new(), + functions: IndexStorage::new(), + is_lowered_enum_child: false, + is_lowered_enum_parent: true, + lowered_enum_parent: Some(container.clone()), + lowered_enum_child: None, + hir_mir_indexes: HashMap::new(), + }; + + let mut entry_size = 0; + + let info = t.get_generic_info(); + + for entry in &container.entries { + let lowered = lower_hir_type( + ctx, + Type::Generic(entry.1.clone(), info.0.clone(), info.1.clone()), + )?; + + entry_size = + entry_size.max(lowered.get_generic(&ctx.hir_ctx.type_storage).get_size( + &lowered, + false, + &ctx.hir_ctx.type_storage, + )) + } + + lowered_container + .fields + .vals + .push(Type::GenericLowered(container.get_hint_type())); + + lowered_container + .fields + .vals + .push(Type::GenericLowered(RawType::Integer(entry_size, false))); + + return Ok(Type::GenericLowered(RawType::LoweredStruct( + false, + lowered_container, + ))); + } + + _ => return Ok(Type::GenericLowered(generic.clone())), + }; } pub fn lower_hir_type(ctx: &MIRLoweringContext, t: Type) -> DiagnosticResult { - match &t { - Type::Generic(a, _, _) => { - return lower_hir_generic(ctx, &t, a) - }, - - Type::Array(a, b) => return Ok(Type::Array(*a, Box::new(lower_hir_type(ctx, *b.clone())?))), - Type::Pointer(a, b) => return Ok(Type::Pointer(*a, Box::new(lower_hir_type(ctx, *b.clone())?))), - Type::Reference(inner) => return Ok(Type::Reference(Box::new(lower_hir_type(ctx, *inner.clone())?))), - - _ => unsure_panic!("type is already lowered") - } -} \ No newline at end of file + match &t { + Type::Generic(a, _, _) => return lower_hir_generic(ctx, &t, a), + + Type::Array(a, b) => { + return Ok(Type::Array(*a, Box::new(lower_hir_type(ctx, *b.clone())?))); + } + Type::Pointer(a, b) => { + return Ok(Type::Pointer( + *a, + Box::new(lower_hir_type(ctx, *b.clone())?), + )); + } + Type::Reference(inner) => { + return Ok(Type::Reference(Box::new(lower_hir_type( + ctx, + *inner.clone(), + )?))); + } + + _ => unsure_panic!("type is already lowered"), + } +} diff --git a/compiler/astoir_mir_lowering/src/lru.rs b/compiler/astoir_mir_lowering/src/lru.rs index 06fe367..1a97200 100644 --- a/compiler/astoir_mir_lowering/src/lru.rs +++ b/compiler/astoir_mir_lowering/src/lru.rs @@ -1,42 +1,72 @@ -use astoir_hir::{nodes::{HIRNode, HIRNodeKind}, structs::StructLRUStep}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::build_field_pointer, vals::{base::BaseMIRValue, refer::MIRVariableReference}}; +use astoir_hir::{ + nodes::{HIRNode, HIRNodeKind}, + structs::StructLRUStep, +}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::build_field_pointer, + vals::{base::BaseMIRValue, refer::MIRVariableReference}, +}; use compiler_typing::raw::RawType; use diagnostics::{DiagnosticResult, unsure_panic}; use crate::MIRLoweringContext; -pub fn lower_hir_lru_step(block: MIRBlockReference, step: StructLRUStep, ctx: &mut MIRLoweringContext, curr: Option) -> DiagnosticResult { - if let StructLRUStep::VariableStep { variable } = step { - if curr.is_none() { - return Ok(ctx.mir_ctx.blocks[block].get_variable_ref(variable)?.as_pointer_ref()?.into()); - } +pub fn lower_hir_lru_step( + block: MIRBlockReference, + step: StructLRUStep, + ctx: &mut MIRLoweringContext, + curr: Option, +) -> DiagnosticResult { + if let StructLRUStep::VariableStep { variable } = step { + if curr.is_none() { + return Ok(ctx.mir_ctx.blocks[block] + .get_variable_ref(variable)? + .as_pointer_ref()? + .into()); + } - let curr = curr.unwrap(); - let ptr = curr.as_ptr()?; + let curr = curr.unwrap(); + let ptr = curr.as_ptr()?; - let struct_type = match ctx.mir_ctx.ssa_hints.get_hint(curr.get_ssa_index()).get_type().get_generic(&ctx.hir_ctx.type_storage) { - RawType::LoweredStruct(_, container) => container, - _ => unsure_panic!("lower_hir_lru_step curr was not an actual thing") - }; + let struct_type = match ctx + .mir_ctx + .ssa_hints + .get_hint(curr.get_ssa_index()) + .get_type() + .get_generic(&ctx.hir_ctx.type_storage) + { + RawType::LoweredStruct(_, container) => container, + _ => unsure_panic!("lower_hir_lru_step curr was not an actual thing"), + }; - return Ok(build_field_pointer(&mut ctx.mir_ctx, ptr, struct_type.resolve_hir_index(variable))?.into()) - } + return Ok(build_field_pointer( + &mut ctx.mir_ctx, + ptr, + struct_type.resolve_hir_index(variable), + )? + .into()); + } - panic!("Invalid step!") + panic!("Invalid step!") } -pub fn lower_hir_lru(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::StructLRU { steps, last: _ } = node.kind { - let mut curr = lower_hir_lru_step(block, steps[0].clone(), ctx, None)?; +pub fn lower_hir_lru( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::StructLRU { steps, last: _ } = node.kind { + let mut curr = lower_hir_lru_step(block, steps[0].clone(), ctx, None)?; - for i in 1..steps.len() { - curr = lower_hir_lru_step(block, steps[i].clone(), ctx, Some(curr))? - } + for i in 1..steps.len() { + curr = lower_hir_lru_step(block, steps[i].clone(), ctx, Some(curr))? + } - let val = MIRVariableReference::from(curr.as_ptr()?); + let val = MIRVariableReference::from(curr.as_ptr()?); - return Ok(val.read(block, &mut ctx.mir_ctx)?); - } + return Ok(val.read(block, &mut ctx.mir_ctx)?); + } - panic!("Invalid node!") -} \ No newline at end of file + panic!("Invalid node!") +} diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index de846e2..5d7818f 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -1,82 +1,142 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_float_add, build_float_div, build_float_mod, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mod, build_int_mul, build_int_sub, build_shift_left, build_shift_right}, vals::base::BaseMIRValue}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{ + build_float_add, build_float_div, build_float_mod, build_float_mul, build_float_sub, + build_int_add, build_int_div, build_int_mod, build_int_mul, build_int_sub, + build_shift_left, build_shift_right, + }, + vals::base::BaseMIRValue, +}; use compiler_typing::raw::RawType; use compiler_utils::operators::{MathOperator, MathOperatorType}; -use diagnostics::{DiagnosticResult, builders::{make_math_operation_req_assign, make_req_type_kind}, unsure_panic}; +use diagnostics::{ + DiagnosticResult, + builders::{make_math_operation_req_assign, make_req_type_kind}, + unsure_panic, +}; use crate::{MIRLoweringContext, values::lower_hir_value, vars::lower_hir_variable_reference}; - -pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::MathOperation { left, right, operation } = node.clone().kind { - if operation.assigns && !left.is_variable_reference() { - return Err(make_math_operation_req_assign(&*node).into()) - } - let ptr; - - if operation.assigns { - ptr = Some(lower_hir_variable_reference(block, &left, ctx)?); - } else { - ptr = None - } - - let left_val = lower_hir_value(block, left, ctx)?; - let right_val = lower_hir_value(block, right, ctx)?; - - - let val = match left_val.vtype.get_generic(&ctx.hir_ctx.type_storage) { - RawType::Integer(_, _) | RawType::FixedPoint(_, _, _) => lower_hir_math_operation_int(left_val, right_val, operation.clone(), ctx)?, - RawType::Floating(_, _) => lower_hir_math_operation_float(left_val, right_val, operation.clone(), ctx, &*node)?, - - _ => unsure_panic!("Cannot use lower_hir_math_operator on this given value kind!") - }; - - if operation.assigns { - let v = ptr.unwrap(); - - v.write(block, &mut ctx.mir_ctx, val.clone(), &ctx.hir_ctx.type_storage)?; - } - - return Ok(val) - } - - panic!("Invalid node") +pub fn lower_hir_math_operation( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::MathOperation { + left, + right, + operation, + } = node.clone().kind + { + if operation.assigns && !left.is_variable_reference() { + return Err(make_math_operation_req_assign(&*node).into()); + } + + let ptr; + + if operation.assigns { + ptr = Some(lower_hir_variable_reference(block, &left, ctx)?); + } else { + ptr = None + } + + let left_val = lower_hir_value(block, left, ctx)?; + let right_val = lower_hir_value(block, right, ctx)?; + + let val = match left_val.vtype.get_generic(&ctx.hir_ctx.type_storage) { + RawType::Integer(_, _) | RawType::FixedPoint(_, _, _) => { + lower_hir_math_operation_int(left_val, right_val, operation.clone(), ctx)? + } + RawType::Floating(_, _) => { + lower_hir_math_operation_float(left_val, right_val, operation.clone(), ctx, &*node)? + } + + _ => unsure_panic!("Cannot use lower_hir_math_operator on this given value kind!"), + }; + + if operation.assigns { + let v = ptr.unwrap(); + + v.write( + block, + &mut ctx.mir_ctx, + val.clone(), + &ctx.hir_ctx.type_storage, + )?; + } + + return Ok(val); + } + + panic!("Invalid node") } -pub fn lower_hir_math_operation_int(left: BaseMIRValue, right: BaseMIRValue, operator: MathOperator, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - let left = left.as_int()?; - let right = right.as_int()?; - - let signed = left.signed; - - let res = match operator.operator { - MathOperatorType::Add => build_int_add(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Subtract => build_int_sub(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Multiply => build_int_mul(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Divide => build_int_div(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::ShiftLeft => build_shift_left(&mut ctx.mir_ctx, left, right)?, - MathOperatorType::ShiftRight => build_shift_right(&mut ctx.mir_ctx, left, right)?, - MathOperatorType::Modulo => build_int_mod(&mut ctx.mir_ctx, left, right, signed, operator.fast)? - }; - - return Ok(res.into()); +pub fn lower_hir_math_operation_int( + left: BaseMIRValue, + right: BaseMIRValue, + operator: MathOperator, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + let left = left.as_int()?; + let right = right.as_int()?; + + let signed = left.signed; + + let res = match operator.operator { + MathOperatorType::Add => { + build_int_add(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Subtract => { + build_int_sub(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Multiply => { + build_int_mul(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Divide => { + build_int_div(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::ShiftLeft => build_shift_left(&mut ctx.mir_ctx, left, right)?, + MathOperatorType::ShiftRight => build_shift_right(&mut ctx.mir_ctx, left, right)?, + MathOperatorType::Modulo => { + build_int_mod(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + }; + + return Ok(res.into()); } -pub fn lower_hir_math_operation_float(left: BaseMIRValue, right: BaseMIRValue, operator: MathOperator, ctx: &mut MIRLoweringContext, node: &HIRNode) -> DiagnosticResult { - let left = left.as_float()?; - let right = right.as_float()?; - - let signed = left.signed; - - let res = match operator.operator { - MathOperatorType::Add => build_float_add(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Subtract => build_float_sub(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Multiply => build_float_mul(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Divide => build_float_div(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - MathOperatorType::Modulo => build_float_mod(&mut ctx.mir_ctx, left, right, signed, operator.fast)?, - - _ => return Err(make_req_type_kind(node, &"integer".to_string()).into()) - }; - - return Ok(res.into()); -} \ No newline at end of file +pub fn lower_hir_math_operation_float( + left: BaseMIRValue, + right: BaseMIRValue, + operator: MathOperator, + ctx: &mut MIRLoweringContext, + node: &HIRNode, +) -> DiagnosticResult { + let left = left.as_float()?; + let right = right.as_float()?; + + let signed = left.signed; + + let res = match operator.operator { + MathOperatorType::Add => { + build_float_add(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Subtract => { + build_float_sub(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Multiply => { + build_float_mul(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Divide => { + build_float_div(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + MathOperatorType::Modulo => { + build_float_mod(&mut ctx.mir_ctx, left, right, signed, operator.fast)? + } + + _ => return Err(make_req_type_kind(node, &"integer".to_string()).into()), + }; + + return Ok(res.into()); +} diff --git a/compiler/astoir_mir_lowering/src/type_tools.rs b/compiler/astoir_mir_lowering/src/type_tools.rs index e2148b9..789302c 100644 --- a/compiler/astoir_mir_lowering/src/type_tools.rs +++ b/compiler/astoir_mir_lowering/src/type_tools.rs @@ -1,116 +1,192 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_comp_eq, build_field_pointer, build_ir_cast, build_load, build_unsigned_int_const}, vals::{base::BaseMIRValue, int::MIRIntValue}}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{ + build_comp_eq, build_field_pointer, build_ir_cast, build_load, build_unsigned_int_const, + }, + vals::{base::BaseMIRValue, int::MIRIntValue}, +}; use compiler_typing::{SizedType, raw::RawType, tree::Type}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_req_type_kind, make_type_not_partof}}; - -use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value, vars::lower_hir_variable_reference}; - -pub fn is_enum_value_of_kind(_block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { - let enum_type = match ctx.mir_ctx.ssa_hints.get_hint(val.get_ssa_index()).get_type().as_generic_lowered_safe(origin)? { - RawType::Enum(v) => v, - RawType::LoweredStruct(_, container) => { - if !container.is_lowered_enum_parent { - return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()) - } - - container.lowered_enum_parent.unwrap() - } - _ => { - return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()) - } - }; - - let enum_entry = match enum_entry { - RawType::EnumEntry(v) => v, - RawType::LoweredStruct(_, container) => { - if !container.is_lowered_enum_child { - return Err(make_req_type_kind(origin, &"enum child".to_string()).into()) - } - - container.lowered_enum_child.unwrap() - } - _ => return Err(make_req_type_kind(origin, &"enum child".to_string()).into()) - }; - - if enum_entry.parent != enum_type.self_ref { - return Err(make_type_not_partof(origin, &enum_entry.child, &enum_type.self_ref).into()) - } - - let hint_type = enum_type.get_hint_type(); - - let field_ptr = build_field_pointer(&mut ctx.mir_ctx, val.as_ptr()?, 0)?; // 0 = hint type index - let hint_val = build_load(&mut ctx.mir_ctx, field_ptr)?.as_int()?; - - let hint_true = build_unsigned_int_const(&mut ctx.mir_ctx, enum_entry.child as u128, hint_type.get_size(&Type::GenericLowered(hint_type.clone()), false, &ctx.hir_ctx.type_storage))?; - - return build_comp_eq(&mut ctx.mir_ctx, hint_val, hint_true); +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, + builders::{make_req_type_kind, make_type_not_partof}, +}; + +use crate::{ + MIRLoweringContext, lower_hir_type, values::lower_hir_value, vars::lower_hir_variable_reference, +}; + +pub fn is_enum_value_of_kind( + _block: MIRBlockReference, + val: BaseMIRValue, + enum_entry: RawType, + ctx: &mut MIRLoweringContext, + origin: &K, +) -> DiagnosticResult { + let enum_type = match ctx + .mir_ctx + .ssa_hints + .get_hint(val.get_ssa_index()) + .get_type() + .as_generic_lowered_safe(origin)? + { + RawType::Enum(v) => v, + RawType::LoweredStruct(_, container) => { + if !container.is_lowered_enum_parent { + return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()); + } + + container.lowered_enum_parent.unwrap() + } + _ => return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()), + }; + + let enum_entry = match enum_entry { + RawType::EnumEntry(v) => v, + RawType::LoweredStruct(_, container) => { + if !container.is_lowered_enum_child { + return Err(make_req_type_kind(origin, &"enum child".to_string()).into()); + } + + container.lowered_enum_child.unwrap() + } + _ => return Err(make_req_type_kind(origin, &"enum child".to_string()).into()), + }; + + if enum_entry.parent != enum_type.self_ref { + return Err(make_type_not_partof(origin, &enum_entry.child, &enum_type.self_ref).into()); + } + + let hint_type = enum_type.get_hint_type(); + + let field_ptr = build_field_pointer(&mut ctx.mir_ctx, val.as_ptr()?, 0)?; // 0 = hint type index + let hint_val = build_load(&mut ctx.mir_ctx, field_ptr)?.as_int()?; + + let hint_true = build_unsigned_int_const( + &mut ctx.mir_ctx, + enum_entry.child as u128, + hint_type.get_size( + &Type::GenericLowered(hint_type.clone()), + false, + &ctx.hir_ctx.type_storage, + ), + )?; + + return build_comp_eq(&mut ctx.mir_ctx, hint_val, hint_true); } -pub fn cast_to_enum_child(_block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { - let enum_type = match ctx.mir_ctx.ssa_hints.get_hint(val.get_ssa_index()).get_type().as_generic_lowered_safe(origin)? { - RawType::Enum(v) => v, - RawType::LoweredStruct(_, container) => { - if !container.is_lowered_enum_parent { - return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()) - } - - container.lowered_enum_parent.unwrap() - }, - - _ => return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()) - }; - - let enum_entry_container = match &enum_entry { - RawType::EnumEntry(v) => v, - RawType::LoweredStruct(_, container) => { - if !container.is_lowered_enum_child { - return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()) - } - - container.lowered_enum_child.as_ref().unwrap() - }, - _ => return Err(make_req_type_kind(origin, &"enum child".to_string()).into()) - }; - - if enum_entry_container.parent != enum_type.self_ref { - return Err(make_type_not_partof(origin, &enum_entry_container.child, &enum_type.self_ref).into()) - } - - return build_ir_cast(&mut ctx.mir_ctx, val, Type::GenericLowered(enum_entry)) +pub fn cast_to_enum_child( + _block: MIRBlockReference, + val: BaseMIRValue, + enum_entry: RawType, + ctx: &mut MIRLoweringContext, + origin: &K, +) -> DiagnosticResult { + let enum_type = match ctx + .mir_ctx + .ssa_hints + .get_hint(val.get_ssa_index()) + .get_type() + .as_generic_lowered_safe(origin)? + { + RawType::Enum(v) => v, + RawType::LoweredStruct(_, container) => { + if !container.is_lowered_enum_parent { + return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()); + } + + container.lowered_enum_parent.unwrap() + } + + _ => return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()), + }; + + let enum_entry_container = match &enum_entry { + RawType::EnumEntry(v) => v, + RawType::LoweredStruct(_, container) => { + if !container.is_lowered_enum_child { + return Err(make_req_type_kind(origin, &"enum parent".to_string()).into()); + } + + container.lowered_enum_child.as_ref().unwrap() + } + _ => return Err(make_req_type_kind(origin, &"enum child".to_string()).into()), + }; + + if enum_entry_container.parent != enum_type.self_ref { + return Err( + make_type_not_partof(origin, &enum_entry_container.child, &enum_type.self_ref).into(), + ); + } + + return build_ir_cast(&mut ctx.mir_ctx, val, Type::GenericLowered(enum_entry)); } -pub fn lower_hir_unwrap_cond(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::UnwrapCondition { original, new_type, new_var, unsafe_unwrap } = node.kind.clone() { - let original = lower_hir_variable_reference(block, &original, ctx)?.as_pointer_ref()?.into(); - let new_type = lower_hir_type(ctx, new_type)?; - - let cond; - - if unsafe_unwrap { - cond = build_unsigned_int_const(&mut ctx.mir_ctx, 1, 1)?; - } else { - cond = is_enum_value_of_kind(block, original, new_type.get_generic(&ctx.hir_ctx.type_storage), ctx, &*node)? - } - - if new_var.is_none() { - return Ok(cond.into()); - } - - ctx.block_introduction_var_queue.push(node.clone()); - - return Ok(cond.into()); - } - - panic!("Invalid node!") +pub fn lower_hir_unwrap_cond( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::UnwrapCondition { + original, + new_type, + new_var, + unsafe_unwrap, + } = node.kind.clone() + { + let original = lower_hir_variable_reference(block, &original, ctx)? + .as_pointer_ref()? + .into(); + let new_type = lower_hir_type(ctx, new_type)?; + + let cond; + + if unsafe_unwrap { + cond = build_unsigned_int_const(&mut ctx.mir_ctx, 1, 1)?; + } else { + cond = is_enum_value_of_kind( + block, + original, + new_type.get_generic(&ctx.hir_ctx.type_storage), + ctx, + &*node, + )? + } + + if new_var.is_none() { + return Ok(cond.into()); + } + + ctx.block_introduction_var_queue.push(node.clone()); + + return Ok(cond.into()); + } + + panic!("Invalid node!") } -pub fn lower_hir_unwrap_value(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::UnwrapValue { original, new_type, unsafe_unwrap: _ } = node.kind.clone() { - let original = lower_hir_value(block, original, ctx)?; - let new_type = lower_hir_type(ctx, new_type)?; - - return cast_to_enum_child(block, original, new_type.get_generic(&ctx.hir_ctx.type_storage), ctx, &*node) - } - - panic!("Invalid node!") -} \ No newline at end of file +pub fn lower_hir_unwrap_value( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::UnwrapValue { + original, + new_type, + unsafe_unwrap: _, + } = node.kind.clone() + { + let original = lower_hir_value(block, original, ctx)?; + let new_type = lower_hir_type(ctx, new_type)?; + + return cast_to_enum_child( + block, + original, + new_type.get_generic(&ctx.hir_ctx.type_storage), + ctx, + &*node, + ); + } + + panic!("Invalid node!") +} diff --git a/compiler/astoir_mir_lowering/src/values/booleans.rs b/compiler/astoir_mir_lowering/src/values/booleans.rs index 4898435..4e11d4c 100644 --- a/compiler/astoir_mir_lowering/src/values/booleans.rs +++ b/compiler/astoir_mir_lowering/src/values/booleans.rs @@ -1,40 +1,60 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::{refer::MIRBlockReference}, builder::{build_bitwise_not, build_comp_eq, build_comp_ge, build_comp_gt, build_comp_le, build_comp_lt, build_comp_neg}, vals::int::MIRIntValue}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{ + build_bitwise_not, build_comp_eq, build_comp_ge, build_comp_gt, build_comp_le, + build_comp_lt, build_comp_neg, + }, + vals::int::MIRIntValue, +}; use compiler_utils::operators::ComparingOperator; use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, values::lower_hir_value}; -pub fn lower_hir_boolean_operator(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::BooleanOperator { left, right, operator } = node.kind { - let a = lower_hir_value(block, left, ctx)?.as_int()?; - let b = lower_hir_value(block, right, ctx)?.as_int()?; - - let val = match operator { - ComparingOperator::Equal => build_comp_eq(&mut ctx.mir_ctx, a, b)?, - ComparingOperator::NotEqual => build_comp_neg(&mut ctx.mir_ctx, a, b)?, - ComparingOperator::Lower => build_comp_lt(&mut ctx.mir_ctx, a, b)?, - ComparingOperator::LowerEqual => build_comp_le(&mut ctx.mir_ctx, a, b)?, - ComparingOperator::Higher => build_comp_gt(&mut ctx.mir_ctx, a, b)?, - ComparingOperator::HigherEqual => build_comp_ge(&mut ctx.mir_ctx, a, b)? - }; - - return Ok(val); - } - - panic!("Invalid node"); +pub fn lower_hir_boolean_operator( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::BooleanOperator { + left, + right, + operator, + } = node.kind + { + let a = lower_hir_value(block, left, ctx)?.as_int()?; + let b = lower_hir_value(block, right, ctx)?.as_int()?; + + let val = match operator { + ComparingOperator::Equal => build_comp_eq(&mut ctx.mir_ctx, a, b)?, + ComparingOperator::NotEqual => build_comp_neg(&mut ctx.mir_ctx, a, b)?, + ComparingOperator::Lower => build_comp_lt(&mut ctx.mir_ctx, a, b)?, + ComparingOperator::LowerEqual => build_comp_le(&mut ctx.mir_ctx, a, b)?, + ComparingOperator::Higher => build_comp_gt(&mut ctx.mir_ctx, a, b)?, + ComparingOperator::HigherEqual => build_comp_ge(&mut ctx.mir_ctx, a, b)?, + }; + + return Ok(val); + } + + panic!("Invalid node"); } -pub fn lowering_hir_boolean_condition(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::BooleanCondition { value, negation } = node.kind { - let mut val = lower_hir_value(block, value, ctx)?.as_int()?; +pub fn lowering_hir_boolean_condition( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::BooleanCondition { value, negation } = node.kind { + let mut val = lower_hir_value(block, value, ctx)?.as_int()?; - if negation { - val = build_bitwise_not(&mut ctx.mir_ctx, val)?; - } + if negation { + val = build_bitwise_not(&mut ctx.mir_ctx, val)?; + } - return Ok(val); - } + return Ok(val); + } - panic!("Invalid node"); -} \ No newline at end of file + panic!("Invalid node"); +} diff --git a/compiler/astoir_mir_lowering/src/values/consts.rs b/compiler/astoir_mir_lowering/src/values/consts.rs index 8f7817d..b393c70 100644 --- a/compiler/astoir_mir_lowering/src/values/consts.rs +++ b/compiler/astoir_mir_lowering/src/values/consts.rs @@ -1,30 +1,44 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{builder::{build_signed_int_const, build_static_string_const, build_unsigned_int_const}, vals::base::BaseMIRValue}; +use astoir_mir::{ + builder::{build_signed_int_const, build_static_string_const, build_unsigned_int_const}, + vals::base::BaseMIRValue, +}; use compiler_typing::SizedType; use diagnostics::DiagnosticResult; use crate::MIRLoweringContext; -pub fn lower_hir_literal(node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - match node.kind { - HIRNodeKind::IntegerLiteral { value, int_type } => { - if int_type.get_generic(&ctx.hir_ctx.type_storage).is_signed() { - let val = build_signed_int_const(&mut ctx.mir_ctx, value, int_type.get_size(&int_type, true, &ctx.hir_ctx.type_storage))?; - - return Ok(val.into()); - } - - let val = build_unsigned_int_const(&mut ctx.mir_ctx, value as u128, int_type.get_size(&int_type, true, &ctx.hir_ctx.type_storage))?; - - return Ok(val.into()); - }, - - HIRNodeKind::StringLiteral { value } => { - let val = build_static_string_const(&mut ctx.mir_ctx, value)?; - - return Ok(val.into()); - }, - - _ => panic!("Invalid node") - } -} \ No newline at end of file +pub fn lower_hir_literal( + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + match node.kind { + HIRNodeKind::IntegerLiteral { value, int_type } => { + if int_type.get_generic(&ctx.hir_ctx.type_storage).is_signed() { + let val = build_signed_int_const( + &mut ctx.mir_ctx, + value, + int_type.get_size(&int_type, true, &ctx.hir_ctx.type_storage), + )?; + + return Ok(val.into()); + } + + let val = build_unsigned_int_const( + &mut ctx.mir_ctx, + value as u128, + int_type.get_size(&int_type, true, &ctx.hir_ctx.type_storage), + )?; + + return Ok(val.into()); + } + + HIRNodeKind::StringLiteral { value } => { + let val = build_static_string_const(&mut ctx.mir_ctx, value)?; + + return Ok(val.into()); + } + + _ => panic!("Invalid node"), + } +} diff --git a/compiler/astoir_mir_lowering/src/values/mod.rs b/compiler/astoir_mir_lowering/src/values/mod.rs index 93ebcb6..331537e 100644 --- a/compiler/astoir_mir_lowering/src/values/mod.rs +++ b/compiler/astoir_mir_lowering/src/values/mod.rs @@ -1,64 +1,116 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_static_array_const, build_static_array_one_const}, vals::base::BaseMIRValue}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos, unsure_panic}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{build_static_array_const, build_static_array_one_const}, + vals::base::BaseMIRValue, +}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos, unsure_panic, +}; -use crate::{MIRLoweringContext, arrays::lower_hir_aray_index_access, casts::lower_cast, funcs::lower_hir_function_call, lru::lower_hir_lru, math::lower_hir_math_operation, type_tools::{lower_hir_unwrap_cond, lower_hir_unwrap_value}, values::{booleans::{lower_hir_boolean_operator, lowering_hir_boolean_condition}, consts::lower_hir_literal, structs::lower_hir_struct_init}, vars::{lower_hir_variable_reference, lower_hir_variable_reference_value}}; +use crate::{ + MIRLoweringContext, + arrays::lower_hir_aray_index_access, + casts::lower_cast, + funcs::lower_hir_function_call, + lru::lower_hir_lru, + math::lower_hir_math_operation, + type_tools::{lower_hir_unwrap_cond, lower_hir_unwrap_value}, + values::{ + booleans::{lower_hir_boolean_operator, lowering_hir_boolean_condition}, + consts::lower_hir_literal, + structs::lower_hir_struct_init, + }, + vars::{lower_hir_variable_reference, lower_hir_variable_reference_value}, +}; -pub mod consts; pub mod booleans; +pub mod consts; pub mod structs; -pub fn lower_hir_value(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - move_current_diagnostic_pos(node.get_pos()); - - match node.kind { - HIRNodeKind::IntegerLiteral { .. } | HIRNodeKind::StringLiteral { .. } => return lower_hir_literal(node, ctx), - HIRNodeKind::VariableReference { .. } => return lower_hir_variable_reference_value(block, node, ctx), - HIRNodeKind::ReferenceGrab { val } => return Ok(lower_hir_variable_reference(block, &val, ctx)?.as_pointer_ref()?.into()), - HIRNodeKind::PointerGrab { val } => return Ok(lower_hir_variable_reference(block, &val, ctx)?.as_pointer_ref()?.into()), - HIRNodeKind::BooleanCondition { .. } => return Ok(lowering_hir_boolean_condition(block, node, ctx)?.into()), - HIRNodeKind::BooleanOperator { .. } => return Ok(lower_hir_boolean_operator(block, node, ctx)?.into()), - HIRNodeKind::MathOperation { .. } => return Ok(lower_hir_math_operation(block, node, ctx)?), - HIRNodeKind::ArrayIndexAccess { .. } => return Ok(lower_hir_aray_index_access(block, node, ctx)?), - HIRNodeKind::StructInitializerTyped { .. } => return Ok(lower_hir_struct_init(block, node, ctx)?.into()), - HIRNodeKind::UnwrapValue { .. } => lower_hir_unwrap_value(block, node, ctx), - HIRNodeKind::UnwrapCondition { .. } => lower_hir_unwrap_cond(block, node, ctx), - HIRNodeKind::CastValue { .. } => lower_cast(block, node, ctx), - HIRNodeKind::StructLRU { .. } => lower_hir_lru(block, node, ctx), - HIRNodeKind::ArrayVariableInitializerValue { .. } | HIRNodeKind::ArrayVariableInitializerValueSameValue { .. } => lower_array_init(block, node, ctx), - HIRNodeKind::FunctionCall { .. } => { - let res = lower_hir_function_call(block, node, ctx)?; +pub fn lower_hir_value( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + move_current_diagnostic_pos(node.get_pos()); - if res.is_none() { - unsure_panic!("expected val func"); - } + match node.kind { + HIRNodeKind::IntegerLiteral { .. } | HIRNodeKind::StringLiteral { .. } => { + return lower_hir_literal(node, ctx); + } + HIRNodeKind::VariableReference { .. } => { + return lower_hir_variable_reference_value(block, node, ctx); + } + HIRNodeKind::ReferenceGrab { val } => { + return Ok(lower_hir_variable_reference(block, &val, ctx)? + .as_pointer_ref()? + .into()); + } + HIRNodeKind::PointerGrab { val } => { + return Ok(lower_hir_variable_reference(block, &val, ctx)? + .as_pointer_ref()? + .into()); + } + HIRNodeKind::BooleanCondition { .. } => { + return Ok(lowering_hir_boolean_condition(block, node, ctx)?.into()); + } + HIRNodeKind::BooleanOperator { .. } => { + return Ok(lower_hir_boolean_operator(block, node, ctx)?.into()); + } + HIRNodeKind::MathOperation { .. } => { + return Ok(lower_hir_math_operation(block, node, ctx)?); + } + HIRNodeKind::ArrayIndexAccess { .. } => { + return Ok(lower_hir_aray_index_access(block, node, ctx)?); + } + HIRNodeKind::StructInitializerTyped { .. } => { + return Ok(lower_hir_struct_init(block, node, ctx)?.into()); + } + HIRNodeKind::UnwrapValue { .. } => lower_hir_unwrap_value(block, node, ctx), + HIRNodeKind::UnwrapCondition { .. } => lower_hir_unwrap_cond(block, node, ctx), + HIRNodeKind::CastValue { .. } => lower_cast(block, node, ctx), + HIRNodeKind::StructLRU { .. } => lower_hir_lru(block, node, ctx), + HIRNodeKind::ArrayVariableInitializerValue { .. } + | HIRNodeKind::ArrayVariableInitializerValueSameValue { .. } => { + lower_array_init(block, node, ctx) + } + HIRNodeKind::FunctionCall { .. } => { + let res = lower_hir_function_call(block, node, ctx)?; - return Ok(res.unwrap()); - } + if res.is_none() { + unsure_panic!("expected val func"); + } - _ => panic!("Invalid node {:#?}", node) - } -} + return Ok(res.unwrap()); + } -pub fn lower_array_init(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - match node.kind.clone() { - HIRNodeKind::ArrayVariableInitializerValue { vals } => { + _ => panic!("Invalid node {:#?}", node), + } +} - let mut v = vec![]; +pub fn lower_array_init( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + match node.kind.clone() { + HIRNodeKind::ArrayVariableInitializerValue { vals } => { + let mut v = vec![]; - for val in vals { - v.push(lower_hir_value(block, val, ctx)?) - } + for val in vals { + v.push(lower_hir_value(block, val, ctx)?) + } - return Ok(build_static_array_const(&mut ctx.mir_ctx, v)?.into()) - }, + return Ok(build_static_array_const(&mut ctx.mir_ctx, v)?.into()); + } - HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { - let v = lower_hir_value(block, val, ctx)?; + HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { + let v = lower_hir_value(block, val, ctx)?; - return Ok(build_static_array_one_const(&mut ctx.mir_ctx, v, size)?.into()); - }, + return Ok(build_static_array_one_const(&mut ctx.mir_ctx, v, size)?.into()); + } - _ => panic!("Invalid node") - } -} \ No newline at end of file + _ => panic!("Invalid node"), + } +} diff --git a/compiler/astoir_mir_lowering/src/values/structs.rs b/compiler/astoir_mir_lowering/src/values/structs.rs index ea32975..c7e22c2 100644 --- a/compiler/astoir_mir_lowering/src/values/structs.rs +++ b/compiler/astoir_mir_lowering/src/values/structs.rs @@ -1,44 +1,59 @@ use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::refer::MIRBlockReference, builder::{build_static_struct_const, build_unsigned_int_const}, vals::structs::MIRStructValue}; +use astoir_mir::{ + blocks::refer::MIRBlockReference, + builder::{build_static_struct_const, build_unsigned_int_const}, + vals::structs::MIRStructValue, +}; use compiler_typing::{SizedType, raw::RawType, tree::Type}; use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; -pub fn lower_hir_struct_init(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::StructInitializerTyped { t, fields } = node.kind { - let mut values = vec![]; - - match t.get_generic(&ctx.hir_ctx.type_storage) { - RawType::Struct(_, _) => { - for field in fields { - values.push(lower_hir_value(block, field, ctx)?); - } - }, - - RawType::EnumEntry(container) => { - - let parent = match &ctx.hir_ctx.type_storage.types.vals[container.parent] { - RawType::Enum(container) => container.clone(), - _ => panic!("Enum parent not enum") - }; - - let hint = build_unsigned_int_const(&mut ctx.mir_ctx, container.child as u128, parent.get_hint_type().get_size(&Type::GenericLowered(parent.get_hint_type()), false, &ctx.hir_ctx.type_storage))?; - - values.push(hint.into()); - - for field in fields { - values.push(lower_hir_value(block, field, ctx)?); - } - } - - _ => panic!("Invalid type for a StructInitializedTyped") - } - - let lowered_type = lower_hir_type(ctx, t)?.get_generic(&ctx.hir_ctx.type_storage); - - return build_static_struct_const(&mut ctx.mir_ctx, lowered_type, values); - } - - panic!("Invalid node") -} \ No newline at end of file +pub fn lower_hir_struct_init( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::StructInitializerTyped { t, fields } = node.kind { + let mut values = vec![]; + + match t.get_generic(&ctx.hir_ctx.type_storage) { + RawType::Struct(_, _) => { + for field in fields { + values.push(lower_hir_value(block, field, ctx)?); + } + } + + RawType::EnumEntry(container) => { + let parent = match &ctx.hir_ctx.type_storage.types.vals[container.parent] { + RawType::Enum(container) => container.clone(), + _ => panic!("Enum parent not enum"), + }; + + let hint = build_unsigned_int_const( + &mut ctx.mir_ctx, + container.child as u128, + parent.get_hint_type().get_size( + &Type::GenericLowered(parent.get_hint_type()), + false, + &ctx.hir_ctx.type_storage, + ), + )?; + + values.push(hint.into()); + + for field in fields { + values.push(lower_hir_value(block, field, ctx)?); + } + } + + _ => panic!("Invalid type for a StructInitializedTyped"), + } + + let lowered_type = lower_hir_type(ctx, t)?.get_generic(&ctx.hir_ctx.type_storage); + + return build_static_struct_const(&mut ctx.mir_ctx, lowered_type, values); + } + + panic!("Invalid node") +} diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index 391ffb2..36f9578 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -1,73 +1,129 @@ //! Variable related lowering use astoir_hir::nodes::{HIRNode, HIRNodeKind}; -use astoir_mir::{blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::MIRBlockReference}, builder::{build_stack_alloc, build_store}, vals::{base::BaseMIRValue, refer::MIRVariableReference}}; +use astoir_mir::{ + blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::MIRBlockReference}, + builder::{build_stack_alloc, build_store}, + vals::{base::BaseMIRValue, refer::MIRVariableReference}, +}; use compiler_typing::SizedType; use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; -pub fn lower_hir_variable_declaration(block_id: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::VarDeclaration { variable, var_type, default_val } = node.clone().kind { - let func = ctx.mir_ctx.block_to_func[&block_id]; - - let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); - - if local_ctx.is_eligible_for_ssa(variable) { - if default_val.is_some() { - let val = lower_hir_value(block_id, default_val.unwrap(), ctx)?; - - ctx.mir_ctx.blocks[block_id].variables.insert(variable, MIRBlockVariableSSAHint { kind: MIRBlockVariableType::SSA, hint: Some(val) }); - } else { - ctx.mir_ctx.blocks[block_id].variables.insert(variable, MIRBlockVariableSSAHint { kind: MIRBlockVariableType::SSA, hint: None }); - } - } else { - let lowered = lower_hir_type(ctx, var_type)?; - - let ptr = build_stack_alloc(&mut ctx.mir_ctx, lowered.get_size(&lowered, false, &ctx.hir_ctx.type_storage), lowered)?; - - ctx.mir_ctx.blocks[block_id].variables.insert(variable, MIRBlockVariableSSAHint { kind: MIRBlockVariableType::Pointer, hint: Some(ptr.clone().into()) }); - - if default_val.is_some() { - let val = lower_hir_value(block_id, default_val.unwrap(), ctx)?; - - build_store(&mut ctx.mir_ctx, &ctx.hir_ctx.type_storage, ptr.clone(), val)?; - } - } - - return Ok(true) - } - - panic!("Invalid node") +pub fn lower_hir_variable_declaration( + block_id: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::VarDeclaration { + variable, + var_type, + default_val, + } = node.clone().kind + { + let func = ctx.mir_ctx.block_to_func[&block_id]; + + let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); + + if local_ctx.is_eligible_for_ssa(variable) { + if default_val.is_some() { + let val = lower_hir_value(block_id, default_val.unwrap(), ctx)?; + + ctx.mir_ctx.blocks[block_id].variables.insert( + variable, + MIRBlockVariableSSAHint { + kind: MIRBlockVariableType::SSA, + hint: Some(val), + }, + ); + } else { + ctx.mir_ctx.blocks[block_id].variables.insert( + variable, + MIRBlockVariableSSAHint { + kind: MIRBlockVariableType::SSA, + hint: None, + }, + ); + } + } else { + let lowered = lower_hir_type(ctx, var_type)?; + + let ptr = build_stack_alloc( + &mut ctx.mir_ctx, + lowered.get_size(&lowered, false, &ctx.hir_ctx.type_storage), + lowered, + )?; + + ctx.mir_ctx.blocks[block_id].variables.insert( + variable, + MIRBlockVariableSSAHint { + kind: MIRBlockVariableType::Pointer, + hint: Some(ptr.clone().into()), + }, + ); + + if default_val.is_some() { + let val = lower_hir_value(block_id, default_val.unwrap(), ctx)?; + + build_store( + &mut ctx.mir_ctx, + &ctx.hir_ctx.type_storage, + ptr.clone(), + val, + )?; + } + } + + return Ok(true); + } + + panic!("Invalid node") } -pub fn lower_hir_variable_reference(block: MIRBlockReference, node: &Box, ctx: &MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::VariableReference { index, is_static: _ } = &node.kind { // TODO: add support for static variables - return ctx.mir_ctx.blocks[block].get_variable_ref(*index) - } - - panic!("Invalid node") +pub fn lower_hir_variable_reference( + block: MIRBlockReference, + node: &Box, + ctx: &MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::VariableReference { + index, + is_static: _, + } = &node.kind + { + // TODO: add support for static variables + return ctx.mir_ctx.blocks[block].get_variable_ref(*index); + } + + panic!("Invalid node") } - /// Lowers the HIR variable reference as if to obtain it's value. Requires a load -pub fn lower_hir_variable_reference_value(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - let ptr = lower_hir_variable_reference(block, &node, ctx)?; - - let read = ptr.read(block, &mut ctx.mir_ctx)?; +pub fn lower_hir_variable_reference_value( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + let ptr = lower_hir_variable_reference(block, &node, ctx)?; + + let read = ptr.read(block, &mut ctx.mir_ctx)?; - return Ok(read); + return Ok(read); } -pub fn lower_hir_variable_assignment(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::VarAssigment { variable, val } = node.clone().kind { - let variable_ref = ctx.mir_ctx.blocks[block].get_variable_ref(variable)?; - - let val = lower_hir_value(block, val, ctx)?; +pub fn lower_hir_variable_assignment( + block: MIRBlockReference, + node: Box, + ctx: &mut MIRLoweringContext, +) -> DiagnosticResult { + if let HIRNodeKind::VarAssigment { variable, val } = node.clone().kind { + let variable_ref = ctx.mir_ctx.blocks[block].get_variable_ref(variable)?; - variable_ref.write(block, &mut ctx.mir_ctx, val, &ctx.hir_ctx.type_storage)?; - return Ok(true); - } + let val = lower_hir_value(block, val, ctx)?; - panic!("Invalid node") -} \ No newline at end of file + variable_ref.write(block, &mut ctx.mir_ctx, val, &ctx.hir_ctx.type_storage)?; + return Ok(true); + } + + panic!("Invalid node") +} diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs index c430b90..0e3f219 100644 --- a/compiler/compiler_global_scope/src/entry.rs +++ b/compiler/compiler_global_scope/src/entry.rs @@ -8,85 +8,188 @@ use crate::GlobalStorageIdentifier; #[derive(Clone, Debug)] pub enum GlobalStorageEntryType { - Function { descriptor_ind: usize, impl_ind: usize }, - ImplLessFunction(usize), - StructFunction { descriptor_ind: usize, impl_ind: usize, struct_type: GlobalStorageIdentifier }, - - StaticVariable(T), - - TypeAlias(T), - Type(R) + Function { + descriptor_ind: usize, + impl_ind: usize, + }, + ImplLessFunction(usize), + StructFunction { + descriptor_ind: usize, + impl_ind: usize, + struct_type: GlobalStorageIdentifier, + }, + + StaticVariable(T), + + TypeAlias(T), + Type(R), } impl GlobalStorageEntry { - pub fn as_function(&self, origin: &K) -> DiagnosticResult<(usize, usize)> { - match self.entry_type { - GlobalStorageEntryType::Function { descriptor_ind, impl_ind } => Ok((descriptor_ind, impl_ind)), - - _ => Err(make_expected_simple_error(origin, &"function".to_string(), &self.entry_type).into()) - } - } - - pub fn as_implless_function(&self, origin: &K) -> DiagnosticResult { - match self.entry_type { - GlobalStorageEntryType::ImplLessFunction(ind) => Ok(ind), - - _ => Err(make_expected_simple_error(origin, &"implless function".to_string(), &self.entry_type).into()) - } - } - - pub fn as_struct_function(&self, origin: &K) -> DiagnosticResult<(usize, usize, GlobalStorageIdentifier)> { - match self.entry_type { - GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind, struct_type } => Ok((descriptor_ind, impl_ind, struct_type)), - - _ => Err(make_expected_simple_error(origin, &"struct function".to_string(), &self.entry_type).into()) - } - } - - pub fn as_static_variable(&self, origin: &K) -> DiagnosticResult { - match &self.entry_type { - GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), - - _ => Err(make_expected_simple_error(origin, &"static variable".to_string(), &self.entry_type).into()) - } - } - - pub fn as_type_alias(&self, origin: &K) -> DiagnosticResult { - match &self.entry_type { - GlobalStorageEntryType::TypeAlias(t) => Ok(t.clone()), - - _ => Err(make_expected_simple_error(origin, &"type alias".to_string(), &self.entry_type).into()) - } - } - - pub fn as_type(&self, origin: &K) -> DiagnosticResult { - match &self.entry_type { - GlobalStorageEntryType::Type(t) => Ok(t.clone()), - - _ => Err(make_expected_simple_error(origin, &"type".to_string(), &self.entry_type).into()) - } - } + pub fn as_function( + &self, + origin: &K, + ) -> DiagnosticResult<(usize, usize)> { + match self.entry_type { + GlobalStorageEntryType::Function { + descriptor_ind, + impl_ind, + } => Ok((descriptor_ind, impl_ind)), + + _ => Err( + make_expected_simple_error(origin, &"function".to_string(), &self.entry_type) + .into(), + ), + } + } + + pub fn as_function_unsafe(&self) -> (usize, usize) { + match self.entry_type { + GlobalStorageEntryType::Function { + descriptor_ind, + impl_ind, + } => (descriptor_ind, impl_ind), + + _ => panic!(), + } + } + + pub fn as_implless_function( + &self, + origin: &K, + ) -> DiagnosticResult { + match self.entry_type { + GlobalStorageEntryType::ImplLessFunction(ind) => Ok(ind), + + _ => Err(make_expected_simple_error( + origin, + &"implless function".to_string(), + &self.entry_type, + ) + .into()), + } + } + + pub fn as_implless_function_unsafe(&self) -> usize { + match self.entry_type { + GlobalStorageEntryType::ImplLessFunction(ind) => ind, + + _ => panic!(), + } + } + + pub fn as_struct_function( + &self, + origin: &K, + ) -> DiagnosticResult<(usize, usize, GlobalStorageIdentifier)> { + match self.entry_type { + GlobalStorageEntryType::StructFunction { + descriptor_ind, + impl_ind, + struct_type, + } => Ok((descriptor_ind, impl_ind, struct_type)), + + _ => Err(make_expected_simple_error( + origin, + &"struct function".to_string(), + &self.entry_type, + ) + .into()), + } + } + + pub fn as_struct_function_unsafe(&self) -> (usize, usize, GlobalStorageIdentifier) { + match self.entry_type { + GlobalStorageEntryType::StructFunction { + descriptor_ind, + impl_ind, + struct_type, + } => (descriptor_ind, impl_ind, struct_type), + + _ => panic!(), + } + } + + pub fn as_static_variable(&self, origin: &K) -> DiagnosticResult { + match &self.entry_type { + GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), + + _ => Err(make_expected_simple_error( + origin, + &"static variable".to_string(), + &self.entry_type, + ) + .into()), + } + } + + pub fn as_static_variable_unsafe(&self) -> T { + match &self.entry_type { + GlobalStorageEntryType::StaticVariable(t) => t.clone(), + + _ => panic!(), + } + } + + pub fn as_type_alias(&self, origin: &K) -> DiagnosticResult { + match &self.entry_type { + GlobalStorageEntryType::TypeAlias(t) => Ok(t.clone()), + + _ => { + Err( + make_expected_simple_error(origin, &"type alias".to_string(), &self.entry_type) + .into(), + ) + } + } + } + + pub fn as_type_alias_unsafe(&self) -> T { + match &self.entry_type { + GlobalStorageEntryType::TypeAlias(t) => t.clone(), + + _ => panic!(), + } + } + + pub fn as_type(&self, origin: &K) -> DiagnosticResult { + match &self.entry_type { + GlobalStorageEntryType::Type(t) => Ok(t.clone()), + + _ => Err( + make_expected_simple_error(origin, &"type".to_string(), &self.entry_type).into(), + ), + } + } + + pub fn as_type_unsafe(&self) -> R { + match &self.entry_type { + GlobalStorageEntryType::Type(t) => t.clone(), + + _ => panic!(), + } + } } #[derive(Debug)] pub struct GlobalStorageEntry { - pub entry_type: GlobalStorageEntryType, - pub parent_index: usize + pub entry_type: GlobalStorageEntryType, + pub parent_index: usize, } -impl Display for GlobalStorageEntryType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Function { .. } => "function", - Self::ImplLessFunction(_) => "function", - Self::StructFunction { .. } => "function", - Self::StaticVariable(_) => "static variable", - Self::Type(_) => "type", - Self::TypeAlias(_) => "type (alias)" - }; - - write!(f, "{}", s)?; - - Ok(()) - } -} \ No newline at end of file +impl Display for GlobalStorageEntryType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Function { .. } => "function", + Self::ImplLessFunction(_) => "function", + Self::StructFunction { .. } => "function", + Self::StaticVariable(_) => "static variable", + Self::Type(_) => "type", + Self::TypeAlias(_) => "type (alias)", + }; + + write!(f, "{}", s)?; + + Ok(()) + } +} diff --git a/compiler/compiler_global_scope/src/key.rs b/compiler/compiler_global_scope/src/key.rs index 73f7cb3..ed250ba 100644 --- a/compiler/compiler_global_scope/src/key.rs +++ b/compiler/compiler_global_scope/src/key.rs @@ -3,19 +3,19 @@ use std::hash::Hash; /// Represents a key to a global storage entry. Potentially allows for namespaces later on #[derive(Debug)] pub struct EntryKey { - pub name_hash: u64 + pub name_hash: u64, } impl Hash for EntryKey { - fn hash(&self, state: &mut H) { - state.write_u64(self.name_hash); - } + fn hash(&self, state: &mut H) { + state.write_u64(self.name_hash); + } } impl PartialEq for EntryKey { - fn eq(&self, other: &Self) -> bool { - self.name_hash == other.name_hash - } + fn eq(&self, other: &Self) -> bool { + self.name_hash == other.name_hash + } } -impl Eq for EntryKey {} \ No newline at end of file +impl Eq for EntryKey {} diff --git a/compiler/compiler_global_scope/src/lib.rs b/compiler/compiler_global_scope/src/lib.rs index b8ab3b0..8371052 100644 --- a/compiler/compiler_global_scope/src/lib.rs +++ b/compiler/compiler_global_scope/src/lib.rs @@ -1,137 +1,219 @@ use std::collections::HashMap; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, + builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}, +}; -use crate::{entry::{GlobalStorageEntry, GlobalStorageEntryType}, key::EntryKey}; +use crate::{ + entry::{GlobalStorageEntry, GlobalStorageEntryType}, + key::EntryKey, +}; pub mod entry; pub mod key; pub type GlobalStorageIdentifier = usize; - #[derive(Debug)] pub struct GlobalScopeStorage { - pub entry_to_ind: HashMap, - pub entries: Vec>, + pub entry_to_ind: HashMap, + pub entries: Vec>, - pub descriptor_counter: usize, - pub impl_counter: usize + pub descriptor_counter: usize, + pub impl_counter: usize, } - /// The global storage for every element inside of the scope. -/// +/// /// This stores the following: /// - Functions (with or without implementations) /// - Static variables /// - Struct functions /// - Types -/// +/// /// # Safety /// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. impl GlobalScopeStorage { - pub fn new() -> Self { - GlobalScopeStorage { entry_to_ind: HashMap::new(), entries: vec![], descriptor_counter: 0, impl_counter: 0 } - } - - pub fn append(&mut self, name: EntryKey, entry: GlobalStorageEntryType, origin: &K) -> MaybeDiagnostic { - if self.entry_to_ind.contains_key(&name) { - return Err(make_already_in_scope(origin, &name.name_hash).into()) - } - - let parent_index = self.entries.len(); - - let entry = GlobalStorageEntry { entry_type: entry, parent_index }; - - self.entries.push(entry); - self.entry_to_ind.insert(name, parent_index); - - Ok(()) - } - - pub fn get_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult> { - if !self.entry_to_ind.contains_key(&name) { - return Err(make_cannot_find(origin, &name.name_hash).into()); - } - - return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()) - } - - pub fn get_type(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Type(t) => Ok(t.clone()), - _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()) - }; - } - - pub fn get_static_variable(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), - _ => Err(make_expected_simple_error(origin, &"static variable".to_string(), &base).into()) - }; - } - - pub fn get_function_base(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function { descriptor_ind, impl_ind: _ } => Ok(descriptor_ind), - GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), - GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind: _, struct_type: _} => Ok(descriptor_ind), - - _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()) - }; - } - - pub fn get_function_impl(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function { descriptor_ind: _, impl_ind } => Ok(impl_ind), - GlobalStorageEntryType::StructFunction { descriptor_ind: _, impl_ind, struct_type: _ } => Ok(impl_ind), - - _ => Err(make_expected_simple_error(origin, &"function with implementation", &base).into()) - }; - } - - pub fn get_implless_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), - - _ => Err(make_expected_simple_error(origin, &"function without implementation", &base).into()) - } - } - - pub fn get_exact_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(usize, usize)> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function { descriptor_ind, impl_ind} => Ok((descriptor_ind, impl_ind)), - - _ => Err(make_expected_simple_error(origin, &"function", &base).into()) - } - } - - pub fn get_exact_struct_function(&self, name: EntryKey, origin: &K) -> DiagnosticResult<(usize, usize, R)> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind, struct_type } => { - if let GlobalStorageEntryType::Type(t) = self.entries[struct_type].entry_type.clone() { - Ok((descriptor_ind, impl_ind, t)) - } else { - Err(make_expected_simple_error(origin, &"type", &self.entries[0].entry_type).into()) - } - }, - - _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()) - } - } + pub fn new() -> Self { + GlobalScopeStorage { + entry_to_ind: HashMap::new(), + entries: vec![], + descriptor_counter: 0, + impl_counter: 0, + } + } + + pub fn append( + &mut self, + name: EntryKey, + entry: GlobalStorageEntryType, + origin: &K, + ) -> MaybeDiagnostic { + if self.entry_to_ind.contains_key(&name) { + return Err(make_already_in_scope(origin, &name.name_hash).into()); + } + + let parent_index = self.entries.len(); + + let entry = GlobalStorageEntry { + entry_type: entry, + parent_index, + }; + + self.entries.push(entry); + self.entry_to_ind.insert(name, parent_index); + + Ok(()) + } + + pub fn get_base( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult> { + if !self.entry_to_ind.contains_key(&name) { + return Err(make_cannot_find(origin, &name.name_hash).into()); + } + + return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()); + } + + pub fn get_type( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Type(t) => Ok(t.clone()), + _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()), + }; + } + + pub fn get_static_variable( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), + _ => Err( + make_expected_simple_error(origin, &"static variable".to_string(), &base).into(), + ), + }; + } + + pub fn get_function_base( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function { + descriptor_ind, + impl_ind: _, + } => Ok(descriptor_ind), + GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), + GlobalStorageEntryType::StructFunction { + descriptor_ind, + impl_ind: _, + struct_type: _, + } => Ok(descriptor_ind), + + _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()), + }; + } + + pub fn get_function_impl( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function { + descriptor_ind: _, + impl_ind, + } => Ok(impl_ind), + GlobalStorageEntryType::StructFunction { + descriptor_ind: _, + impl_ind, + struct_type: _, + } => Ok(impl_ind), + + _ => Err( + make_expected_simple_error(origin, &"function with implementation", &base).into(), + ), + }; + } + + pub fn get_implless_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), + + _ => Err( + make_expected_simple_error(origin, &"function without implementation", &base) + .into(), + ), + }; + } + + pub fn get_exact_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult<(usize, usize)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function { + descriptor_ind, + impl_ind, + } => Ok((descriptor_ind, impl_ind)), + + _ => Err(make_expected_simple_error(origin, &"function", &base).into()), + }; + } + + pub fn get_exact_struct_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult<(usize, usize, R)> { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::StructFunction { + descriptor_ind, + impl_ind, + struct_type, + } => { + if let GlobalStorageEntryType::Type(t) = + self.entries[struct_type].entry_type.clone() + { + Ok((descriptor_ind, impl_ind, t)) + } else { + Err( + make_expected_simple_error(origin, &"type", &self.entries[0].entry_type) + .into(), + ) + } + } + + _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()), + }; + } } diff --git a/compiler/compiler_main/Cargo.toml b/compiler/compiler_main/Cargo.toml index 5db68fb..6a2ddc3 100644 --- a/compiler/compiler_main/Cargo.toml +++ b/compiler/compiler_main/Cargo.toml @@ -8,10 +8,10 @@ astoir = { path = "../astoir" } ast = { path = "../ast" } ast_parser = { path = "../ast_parser" } lexer = { path = "../lexer" } -llvm_ir_bridge = { path = "../llvm_ir_bridge", optional = true, default-features = false} +llvm_ir_bridge = { path = "../llvm_ir_bridge", optional = true, default-features = false } diagnostics = { path = "../diagnostics" } compiler_utils = { path = "../compiler_utils" } [features] llvm = ["llvm_ir_bridge"] -diagbacktraces = ["diagnostics/compiler_diagbacktraces"] \ No newline at end of file +diagbacktraces = ["diagnostics/compiler_diagbacktraces"] diff --git a/compiler/compiler_main/src/cmds/astoir.rs b/compiler/compiler_main/src/cmds/astoir.rs index 130dca8..3600ee3 100644 --- a/compiler/compiler_main/src/cmds/astoir.rs +++ b/compiler/compiler_main/src/cmds/astoir.rs @@ -11,76 +11,76 @@ use std::process::exit; use llvm_ir_bridge::bridge_llvm; pub fn parse_astoir_command(arguments: Vec) { - if arguments.len() <= 2 { - println!("quickfall astoir paths..."); - return; - } - - let level = match parse_astoir_level(&arguments[2]) { - Ok(v) => v, - Err(_) => return - }; - - for i in 3..arguments.len() { - let lexer = lexer_parse_file(&arguments[i]).unwrap(); - let ast = parse_ast_ctx(&lexer); - - dump_diagnostics(); - - match level { - IRLevel::HIR => { - let ctx = run_astoir_hir(ast.unwrap()); - let res_path = arguments[i].clone() + ".qfhir"; - - dump_diagnostics(); - - fs::write(res_path, format!("{:#?}", ctx.unwrap())).unwrap() - }, - - IRLevel::MIR => { - let ctx = run_astoir_mir(ast.unwrap()); - let res_path = arguments[i].clone() + ".qfmir"; - - dump_diagnostics(); - - let _ = fs::write(res_path, format!("{}", ctx.unwrap())); - }, - - IRLevel::LLVM => { - #[cfg(feature = "llvm_ir_bridge")] { - let ctx = run_astoir_mir(ast.unwrap()); - let res_path = arguments[i].clone() + ".llvm"; - - dump_diagnostics(); - - let ctx = bridge_llvm(&ctx.unwrap()); - - dump_diagnostics(); - - let _ = ctx.module.print_to_file(res_path); - } - - #[cfg(not(feature = "llvm_ir_bridge"))] { - println!("LLVM target is not bundled!"); - - exit(0); - } - } - } - } + if arguments.len() <= 2 { + println!("quickfall astoir paths..."); + return; + } + let level = match parse_astoir_level(&arguments[2]) { + Ok(v) => v, + Err(_) => return, + }; + + for i in 3..arguments.len() { + let lexer = lexer_parse_file(&arguments[i]).unwrap(); + let ast = parse_ast_ctx(&lexer); + + dump_diagnostics(); + + match level { + IRLevel::HIR => { + let ctx = run_astoir_hir(ast.unwrap()); + let res_path = arguments[i].clone() + ".qfhir"; + + dump_diagnostics(); + + fs::write(res_path, format!("{:#?}", ctx.unwrap())).unwrap() + } + + IRLevel::MIR => { + let ctx = run_astoir_mir(ast.unwrap()); + let res_path = arguments[i].clone() + ".qfmir"; + + dump_diagnostics(); + + let _ = fs::write(res_path, format!("{}", ctx.unwrap())); + } + + IRLevel::LLVM => { + #[cfg(feature = "llvm_ir_bridge")] + { + let ctx = run_astoir_mir(ast.unwrap()); + let res_path = arguments[i].clone() + ".llvm"; + + dump_diagnostics(); + + let ctx = bridge_llvm(&ctx.unwrap()); + + dump_diagnostics(); + + let _ = ctx.module.print_to_file(res_path); + } + + #[cfg(not(feature = "llvm_ir_bridge"))] + { + println!("LLVM target is not bundled!"); + + exit(0); + } + } + } + } } fn parse_astoir_level(str: &String) -> DiagnosticResult { - match str as &str { - "hir" | "HIR" | "h" | "H" => return Ok(IRLevel::HIR), - "mir" | "MIR" | "m" | "M" => return Ok(IRLevel::MIR), - "llvm" | "LLVM" => return Ok(IRLevel::LLVM), - - _ => { - println!("Invalid level"); - exit(0); - } - }; - -} \ No newline at end of file + match str as &str { + "hir" | "HIR" | "h" | "H" => return Ok(IRLevel::HIR), + "mir" | "MIR" | "m" | "M" => return Ok(IRLevel::MIR), + "llvm" | "LLVM" => return Ok(IRLevel::LLVM), + + _ => { + println!("Invalid level"); + exit(0); + } + }; +} diff --git a/compiler/compiler_main/src/cmds/mod.rs b/compiler/compiler_main/src/cmds/mod.rs index 35daaaf..64e781c 100644 --- a/compiler/compiler_main/src/cmds/mod.rs +++ b/compiler/compiler_main/src/cmds/mod.rs @@ -1 +1 @@ -pub mod astoir; \ No newline at end of file +pub mod astoir; diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 4987ac7..0ba9386 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -5,21 +5,21 @@ use crate::cmds::astoir::parse_astoir_command; pub mod cmds; fn main() { - let arguments: Vec = env::args().collect(); + let arguments: Vec = env::args().collect(); - if arguments.len() <= 1 { - println!("Usage: quickfall comp|astoir"); - return; - } + if arguments.len() <= 1 { + println!("Usage: quickfall comp|astoir"); + return; + } - match &arguments[1] as &str { - "astoir" => { - parse_astoir_command(arguments); - }, + match &arguments[1] as &str { + "astoir" => { + parse_astoir_command(arguments); + } - _ => { - println!("Invalid subcommand!"); - return; - } - } -} \ No newline at end of file + _ => { + println!("Invalid subcommand!"); + return; + } + } +} diff --git a/compiler/compiler_typing/src/bounds/mod.rs b/compiler/compiler_typing/src/bounds/mod.rs index 2cf89a8..74af8ea 100644 --- a/compiler/compiler_typing/src/bounds/mod.rs +++ b/compiler/compiler_typing/src/bounds/mod.rs @@ -3,5 +3,5 @@ //! - Trait bound: Mostly internal, is used to cleanly handle different types //! - Normal bound: Allows to select which kind of type you want -pub mod traits; pub mod normal; +pub mod traits; diff --git a/compiler/compiler_typing/src/bounds/normal.rs b/compiler/compiler_typing/src/bounds/normal.rs index d2c3d4d..8edd90c 100644 --- a/compiler/compiler_typing/src/bounds/normal.rs +++ b/compiler/compiler_typing/src/bounds/normal.rs @@ -1,41 +1,57 @@ -//! Normal bounds are kind of bounds that allow to require specific functions or fields on the given type. +//! Normal bounds are kind of bounds that allow to require specific functions or fields on the given type. //! Thus allowing you to use these with generics. -use diagnostics::{MaybeDiagnostic, builders::{make_bound_fail_field, make_bound_fail_function}}; +use diagnostics::{ + MaybeDiagnostic, + builders::{make_bound_fail_field, make_bound_fail_function}, +}; -use crate::{TypedResolvedFunction, storage::TypeStorage, tree::Type}; +use crate::{TypedGlobalScope, TypedResolvedFunction, tree::Type}; pub struct NormalBound { - pub functions: Vec<(u64, TypedResolvedFunction)>, - pub fields: Vec<(u64, Type)> + pub functions: Vec<(u64, TypedResolvedFunction)>, + pub fields: Vec<(u64, Type)>, } impl NormalBound { - #[must_use = "Must set the diagnostic position beforehand"] - pub fn matches(&self, t: &Type, storage: &TypeStorage) -> MaybeDiagnostic { - for function in &self.functions { - let func = t.get_function(storage, function.0)?.1; - - let mut ind = 0; - for (_, arg) in func.0 { - if !function.1.0[ind].1.is_truly_eq(&arg.resolve(t)) { - return Err(make_bound_fail_function(&"unnamed".to_string(), &"unnamed".to_string(), &function.0, ind).into()) - } - - ind += 1; - } - } - - for field in &self.fields { - let ff = t.get_field(storage, field.0)?.1; - - let resolved = ff.resolve(t); - - if !field.1.is_truly_eq(&resolved) { - return Err(make_bound_fail_field(&"unnamed".to_string(), &"unnamed".to_string(), &field.0, &resolved, &field.1).into()) - } - } - - return Ok(()) - } -} \ No newline at end of file + #[must_use = "Must set the diagnostic position beforehand"] + pub fn matches(&self, t: &Type, storage: &TypedGlobalScope) -> MaybeDiagnostic { + for function in &self.functions { + let func = t.get_function(storage, function.0)?.1; + + let mut ind = 0; + for (_, arg) in func.0 { + if !function.1.0[ind].1.is_truly_eq(&arg.resolve(t)) { + return Err(make_bound_fail_function( + &"unnamed".to_string(), + &"unnamed".to_string(), + &function.0, + ind, + ) + .into()); + } + + ind += 1; + } + } + + for field in &self.fields { + let ff = t.get_field(storage, field.0)?.1; + + let resolved = ff.resolve(t); + + if !field.1.is_truly_eq(&resolved) { + return Err(make_bound_fail_field( + &"unnamed".to_string(), + &"unnamed".to_string(), + &field.0, + &resolved, + &field.1, + ) + .into()); + } + } + + return Ok(()); + } +} diff --git a/compiler/compiler_typing/src/bounds/traits.rs b/compiler/compiler_typing/src/bounds/traits.rs index b24b48a..898c3c9 100644 --- a/compiler/compiler_typing/src/bounds/traits.rs +++ b/compiler/compiler_typing/src/bounds/traits.rs @@ -1,6 +1,6 @@ //! # Trait bounds //! Trait bounds are used to select types with given features. These traits can be represented with a `!` prefix. They can also be used to exclude certain types with the given features. -//! +//! //! Here's a list of every trait bound with their corresponding feature: //! - `!numeric`: Is a numeric type //! - `!signed`: Is a signed numeric type @@ -11,7 +11,7 @@ //! - `!cpusupported`: Is the type supported by the CPU. //! - `!stringlike`: Is the type a string //! - `!static`: Is the type supposed to be statically stored -//! +//! //! # Examples //! ``` //! struct test { @@ -24,7 +24,7 @@ use std::fmt::Display; use compiler_utils::hash; use diagnostics::{MaybeDiagnostic, builders::make_bound_trait}; -use crate::{tree::Type}; +use crate::tree::Type; pub const TRAIT_NUMERIC: u64 = hash!("numeric"); pub const TRAIT_SIGNED: u64 = hash!("signed"); @@ -38,66 +38,66 @@ pub const TRAIT_STATIC: u64 = hash!("static"); #[derive(Clone)] pub enum Trait { - Numeric, - Signed, - Integer, - Floating, - Fixed, - NonInteger, - CpuSupported, - String, - Static + Numeric, + Signed, + Integer, + Floating, + Fixed, + NonInteger, + CpuSupported, + String, + Static, } impl Display for Trait { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Trait::Numeric => "numeric", - Trait::Signed => "signed", - Trait::Integer => "integer", - Trait::Floating => "floating", - Trait::Fixed => "fixed", - Trait::NonInteger => "noninteger", - Trait::CpuSupported => "cpusupported", - Trait::String => "stringlike", - Trait::Static => "static" - }; + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Trait::Numeric => "numeric", + Trait::Signed => "signed", + Trait::Integer => "integer", + Trait::Floating => "floating", + Trait::Fixed => "fixed", + Trait::NonInteger => "noninteger", + Trait::CpuSupported => "cpusupported", + Trait::String => "stringlike", + Trait::Static => "static", + }; - write!(f, "!{}", s) - } + write!(f, "!{}", s) + } } pub enum TraitBoundMember { - /// Selects a trait to require it - Select(Trait), + /// Selects a trait to require it + Select(Trait), - /// Excludes a trait. Types having this trait will not be accepted - Exclude(Trait) + /// Excludes a trait. Types having this trait will not be accepted + Exclude(Trait), } /// Represents the actual trait bound. Is used to make sure that the type is compatible pub struct TraitBound { - pub members: Vec + pub members: Vec, } impl TraitBound { - pub fn check(&self, t: &Type) -> MaybeDiagnostic { - for member in &self.members { - match member { - TraitBoundMember::Select(tt) => { - if !t.as_generic().has_trait(tt.clone(), t) { - return Err(make_bound_trait(tt, t).into()) - } - }, + pub fn check(&self, t: &Type) -> MaybeDiagnostic { + for member in &self.members { + match member { + TraitBoundMember::Select(tt) => { + if !t.as_generic().has_trait(tt.clone(), t) { + return Err(make_bound_trait(tt, t).into()); + } + } - TraitBoundMember::Exclude(tt) => { - if t.as_generic().has_trait(tt.clone(), t) { - return Err(make_bound_trait(&format!("~{}", tt), t).into()) - } - } - } - } + TraitBoundMember::Exclude(tt) => { + if t.as_generic().has_trait(tt.clone(), t) { + return Err(make_bound_trait(&format!("~{}", tt), t).into()); + } + } + } + } - return Ok(()); - } -} \ No newline at end of file + return Ok(()); + } +} diff --git a/compiler/compiler_typing/src/enums.rs b/compiler/compiler_typing/src/enums.rs index efa4874..3883245 100644 --- a/compiler/compiler_typing/src/enums.rs +++ b/compiler/compiler_typing/src/enums.rs @@ -1,206 +1,246 @@ //! Declarations for enum-kind types. -use std::{collections::HashMap}; - -use compiler_utils::{hash::{HashedString}, utils::indexed::IndexStorage}; -use diagnostics::{DiagnosticResult, builders::{make_cannot_find_type_field, make_cannot_find_type_function, make_cannot_find_type_pos, make_enum_parent_fields}}; - -use crate::{RawTypeReference, SizedType, StructuredType, TypeParamType, TypeParameterContainer, TypedFunction, raw::RawType, references::TypeReference, storage::TypeStorage, tree::Type}; +use std::collections::HashMap; + +use compiler_utils::{hash::HashedString, utils::indexed::IndexStorage}; +use diagnostics::{ + DiagnosticResult, + builders::{ + make_cannot_find_type_field, make_cannot_find_type_function, make_cannot_find_type_pos, + make_enum_parent_fields, + }, +}; + +use crate::{ + RawTypeReference, SizedType, StructuredType, TypeParamType, TypeParameterContainer, + TypedFunction, TypedGlobalScope, raw::RawType, references::TypeReference, tree::Type, +}; /// The container for the parent type of enum. -/// +/// /// # Safety /// This struct guarantees that every contained entry is of type RawType::EnumEntry #[derive(Clone, Debug, PartialEq, Eq)] pub struct RawEnumTypeContainer { - pub self_ref: usize, - pub type_params: TypeParameterContainer, - pub functions: IndexStorage, - pub entries: HashMap + pub self_ref: usize, + pub type_params: TypeParameterContainer, + pub functions: IndexStorage, + pub entries: HashMap, } impl RawEnumTypeContainer { - pub fn new(self_ref: usize, type_params: TypeParameterContainer) -> Self { - RawEnumTypeContainer { self_ref, entries: HashMap::new(), type_params, functions: IndexStorage::new() } - } + pub fn new(self_ref: usize, type_params: TypeParameterContainer) -> Self { + RawEnumTypeContainer { + self_ref, + entries: HashMap::new(), + type_params, + functions: IndexStorage::new(), + } + } + + pub fn append_entry(&mut self, name: HashedString, fields: Vec<(u64, TypeReference)>) { + let mut entry_container = + RawEnumEntryContainer::new(self.self_ref, fields, self.type_params.clone()); + entry_container.child = self.entries.len(); + + self.entries + .insert(name, RawType::EnumEntry(entry_container)); + } + + #[must_use = "Must set the diagnostic position beforehand"] + pub fn get_entry(&self, name: HashedString) -> DiagnosticResult { + if let Some(v) = self.entries.get(&name) { + return Ok(v.clone()); + } + + return Err(make_cannot_find_type_pos(&format!("{}::{}", self.self_ref, name.val)).into()); + } + + pub fn get_hint_type(&self) -> RawType { + RawType::make_hint(self.entries.len()) + } +} - pub fn append_entry(&mut self, name: HashedString, fields: Vec<(u64, TypeReference)>) { - let mut entry_container = RawEnumEntryContainer::new(self.self_ref, fields, self.type_params.clone()); - entry_container.child = self.entries.len(); +impl SizedType for RawEnumTypeContainer { + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { + let mut entry_size = 0; - self.entries.insert(name, RawType::EnumEntry(entry_container)); - } + if compacted_size { + let raw = t.get_generic(); - #[must_use = "Must set the diagnostic position beforehand"] - pub fn get_entry(&self, name: HashedString) -> DiagnosticResult { - if let Some(v) = self.entries.get(&name) { - return Ok(v.clone()); - } + if let RawType::EnumEntry(container) = raw { + entry_size = container.get_size(t, compacted_size, storage); + } + } else { + for entry in &self.entries { + entry_size = entry_size.max(entry.1.get_size(t, compacted_size, storage)); + } + } - return Err(make_cannot_find_type_pos(&format!("{}::{}", self.self_ref, name.val)).into()) - } + let hint = RawType::make_hint(self.entries.len()); - pub fn get_hint_type(&self) -> RawType { - RawType::make_hint(self.entries.len()) - } -} - -impl SizedType for RawEnumTypeContainer { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize { - let mut entry_size = 0; - - if compacted_size { - let raw = t.get_generic(storage); - - if let RawType::EnumEntry(container) = raw { - entry_size = container.get_size(t, compacted_size, storage); - } - } - else { - for entry in &self.entries { - entry_size = entry_size.max(entry.1.get_size(t, compacted_size, storage)); - } - } - - let hint = RawType::make_hint(self.entries.len()); - - return hint.get_size(t, compacted_size, storage) + entry_size; - } + return hint.get_size(t, compacted_size, storage) + entry_size; + } } /// The container for enum entries. #[derive(Clone, Debug, PartialEq, Eq)] pub struct RawEnumEntryContainer { - pub parent: RawTypeReference, - pub type_params: TypeParameterContainer, - pub child: usize, - pub fields: IndexStorage + pub parent: RawTypeReference, + pub type_params: TypeParameterContainer, + pub child: usize, + pub fields: IndexStorage, } impl RawEnumEntryContainer { - pub fn new(parent: RawTypeReference, fields: Vec<(u64, TypeReference)>, type_params: TypeParameterContainer) -> Self { - let mut storage = IndexStorage::new(); - - for field in fields { - let _ = storage.append(field.0, field.1); - } - - RawEnumEntryContainer { parent, fields: storage, child: 0, type_params } - } + pub fn new( + parent: RawTypeReference, + fields: Vec<(u64, TypeReference)>, + type_params: TypeParameterContainer, + ) -> Self { + let mut storage = IndexStorage::new(); + + for field in fields { + let _ = storage.append(field.0, field.1); + } + + RawEnumEntryContainer { + parent, + fields: storage, + child: 0, + type_params, + } + } } impl SizedType for RawEnumEntryContainer { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize { - let mut size = 0; + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { + let mut size = 0; - for tt in &self.fields.vals { - size += tt.clone().resolve(t).get_size(t, compacted_size, storage); - } + for tt in &self.fields.vals { + size += tt.clone().resolve(t).get_size(t, compacted_size, storage); + } - return size; - } + return size; + } } impl StructuredType for RawEnumTypeContainer { - fn get_field(&self, _hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - return Err(make_enum_parent_fields().into()) - } - - fn get_field_hash(&self, _hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - return Err(make_enum_parent_fields().into()) - } - - fn get_fields(&self, _storage: &TypeStorage) -> Vec { - return vec![]; - } - - fn get_functions(&self, _storage: &TypeStorage) -> Vec { - return self.functions.entry_keys.clone(); - } - - fn get_function(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.functions.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()) - }; - - return Ok(self.functions.vals[k].clone()) - } - - fn get_function_hash(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.functions.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()) - }; - - return Ok(k); - } + fn get_field( + &self, + _hash: u64, + _storage: &TypedGlobalScope, + ) -> DiagnosticResult { + return Err(make_enum_parent_fields().into()); + } + + fn get_field_hash(&self, _hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + return Err(make_enum_parent_fields().into()); + } + + fn get_fields(&self, _storage: &TypedGlobalScope) -> Vec { + return vec![]; + } + + fn get_functions(&self, _storage: &TypedGlobalScope) -> Vec { + return self.functions.entry_keys.clone(); + } + + fn get_function( + &self, + hash: u64, + _storage: &TypedGlobalScope, + ) -> DiagnosticResult { + let k = match self.functions.get_index(hash) { + Some(v) => v, + None => { + return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()); + } + }; + + return Ok(self.functions.vals[k].clone()); + } + + fn get_function_hash(&self, hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + let k = match self.functions.get_index(hash) { + Some(v) => v, + None => { + return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()); + } + }; + + return Ok(k); + } } impl TypeParamType for RawEnumTypeContainer { - fn has_type_param(&self, param: &HashedString) -> bool { - self.type_params.contains_key(param) - } + fn has_type_param(&self, param: &HashedString) -> bool { + self.type_params.contains_key(param) + } - fn get_type_param_ind(&self, param: &HashedString) -> usize { - self.type_params[param] - } + fn get_type_param_ind(&self, param: &HashedString) -> usize { + self.type_params[param] + } } impl StructuredType for RawEnumEntryContainer { - fn get_field(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.fields.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()) - }; - - return Ok(self.fields.vals[k].clone()); - } - - fn get_field_hash(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.fields.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()) - }; - - return Ok(k); - } - - fn get_fields(&self, _storage: &TypeStorage) -> Vec { - return self.fields.entry_keys.clone(); - } - - fn get_functions(&self, storage: &TypeStorage) -> Vec { - if let RawType::Enum(container) = &storage.types.vals[self.parent] { - return container.get_functions(storage); - } - - panic!("Parent type of enum entry was not an enum!"); - } - - fn get_function(&self, hash: u64, storage: &TypeStorage) -> DiagnosticResult { - if let RawType::Enum(container) = &storage.types.vals[self.parent] { - return container.get_function(hash, storage); - } - - panic!("Parent type of enum entry was not an enum!"); - } - - fn get_function_hash(&self, hash: u64, storage: &TypeStorage) -> DiagnosticResult { - if let RawType::Enum(container) = &storage.types.vals[self.parent] { - return container.get_function_hash(hash, storage); - } - - panic!("Parent type of enum entry was not an enum!"); - } + fn get_field(&self, hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + let k = match self.fields.get_index(hash) { + Some(v) => v, + None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()), + }; + + return Ok(self.fields.vals[k].clone()); + } + + fn get_field_hash(&self, hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + let k = match self.fields.get_index(hash) { + Some(v) => v, + None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()), + }; + + return Ok(k); + } + + fn get_fields(&self, _storage: &TypedGlobalScope) -> Vec { + return self.fields.entry_keys.clone(); + } + + fn get_functions(&self, storage: &TypedGlobalScope) -> Vec { + if let RawType::Enum(container) = &storage.entries[self.parent].as_type_unsafe() { + return container.get_functions(storage); + } + + panic!("Parent type of enum entry was not an enum!"); + } + + fn get_function( + &self, + hash: u64, + storage: &TypedGlobalScope, + ) -> DiagnosticResult { + if let RawType::Enum(container) = &storage.entries[self.parent].as_type_unsafe() { + return container.get_function(hash, storage); + } + + panic!("Parent type of enum entry was not an enum!"); + } + + fn get_function_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult { + if let RawType::Enum(container) = &storage.entries[self.parent].as_type_unsafe() { + return container.get_function_hash(hash, storage); + } + + panic!("Parent type of enum entry was not an enum!"); + } } impl TypeParamType for RawEnumEntryContainer { - fn has_type_param(&self, param: &HashedString) -> bool { - self.type_params.contains_key(param) - } - - fn get_type_param_ind(&self, param: &HashedString) -> usize { - self.type_params[param] - } -} \ No newline at end of file + fn has_type_param(&self, param: &HashedString) -> bool { + self.type_params.contains_key(param) + } + + fn get_type_param_ind(&self, param: &HashedString) -> usize { + self.type_params[param] + } +} diff --git a/compiler/compiler_typing/src/lib.rs b/compiler/compiler_typing/src/lib.rs index 1e005d4..2494b51 100644 --- a/compiler/compiler_typing/src/lib.rs +++ b/compiler/compiler_typing/src/lib.rs @@ -3,20 +3,19 @@ use std::collections::HashMap; use compiler_global_scope::GlobalScopeStorage; -use compiler_utils::{hash::HashedString}; +use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; -use crate::{raw::RawType, references::TypeReference, storage::TypeStorage, tree::Type}; +use crate::{raw::RawType, references::TypeReference, tree::Type}; -pub mod tree; -pub mod raw; -pub mod structs; +pub mod bounds; pub mod enums; +pub mod raw; pub mod references; -pub mod utils; -pub mod storage; +pub mod structs; pub mod transmutation; -pub mod bounds; +pub mod tree; +pub mod utils; pub type TypedGlobalScope = GlobalScopeStorage; @@ -28,38 +27,42 @@ pub type TypeParameterContainer = HashMap; pub type RawTypeReference = usize; -/// Represents a basic type that has a size. +/// Represents a basic type that has a size. pub trait SizedType { - /// Obtains the size of the type. The `compacted_size` parameter determines if the compacted size should be returned or not - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize; + /// Obtains the size of the type. The `compacted_size` parameter determines if the compacted size should be returned or not + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize; } /// Represents a type that contains type parameters pub trait TypeParamType { - /// Checks if the type contains the given type parameter - fn has_type_param(&self, param: &HashedString) -> bool; - - /// Gets the raw index for the given type parameter - fn get_type_param_ind(&self, param: &HashedString) -> usize; + /// Checks if the type contains the given type parameter + fn has_type_param(&self, param: &HashedString) -> bool; + + /// Gets the raw index for the given type parameter + fn get_type_param_ind(&self, param: &HashedString) -> usize; } /// Represents types that can contain functions and more pub trait StructuredType { - #[must_use = "Must set the diagnostic position beforehand"] - fn get_function(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; + #[must_use = "Must set the diagnostic position beforehand"] + fn get_function( + &self, + hash: u64, + storage: &TypedGlobalScope, + ) -> DiagnosticResult; - #[must_use = "Must set the diagnostic position beforehand"] - fn get_function_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; + #[must_use = "Must set the diagnostic position beforehand"] + fn get_function_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; - #[must_use = "Must set the diagnostic position beforehand"] - fn get_field(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; + #[must_use = "Must set the diagnostic position beforehand"] + fn get_field(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; - #[must_use = "Must set the diagnostic position beforehand"] - fn get_field_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; + #[must_use = "Must set the diagnostic position beforehand"] + fn get_field_hash(&self, hash: u64, storage: &TypedGlobalScope) -> DiagnosticResult; - #[must_use = "Must set the diagnostic position beforehand"] - fn get_fields(&self, storage: &TypedGlobalScope) -> Vec; + #[must_use = "Must set the diagnostic position beforehand"] + fn get_fields(&self, storage: &TypedGlobalScope) -> Vec; - #[must_use = "Must set the diagnostic position beforehand"] - fn get_functions(&self, storage: &TypedGlobalScope) -> Vec; -} \ No newline at end of file + #[must_use = "Must set the diagnostic position beforehand"] + fn get_functions(&self, storage: &TypedGlobalScope) -> Vec; +} diff --git a/compiler/compiler_typing/src/raw.rs b/compiler/compiler_typing/src/raw.rs index feb0862..2d8f0ef 100644 --- a/compiler/compiler_typing/src/raw.rs +++ b/compiler/compiler_typing/src/raw.rs @@ -2,322 +2,339 @@ use std::{fmt::Display, hash::Hash}; -use crate::{SizedType, TypedGlobalScope, bounds::traits::Trait, enums::{RawEnumEntryContainer, RawEnumTypeContainer}, storage::TypeStorage, structs::{LoweredStructTypeContainer, RawStructTypeContainer}, tree::Type, utils::get_pointer_size}; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin}; + +use crate::{ + SizedType, TypedGlobalScope, + bounds::traits::Trait, + enums::{RawEnumEntryContainer, RawEnumTypeContainer}, + structs::{LoweredStructTypeContainer, RawStructTypeContainer}, + tree::Type, + utils::get_pointer_size, +}; /// The raw types. Are also named generics #[derive(Clone, Debug, PartialEq, Eq)] pub enum RawType { - Integer(usize, bool), - Floating(usize, bool), - FixedPoint(usize, usize, bool), + Integer(usize, bool), + Floating(usize, bool), + FixedPoint(usize, usize, bool), + + Boolean, - Boolean, + Pointer, - Pointer, + StaticString, - StaticString, + Struct(bool, RawStructTypeContainer), - Struct(bool, RawStructTypeContainer), - - Enum(RawEnumTypeContainer), - EnumEntry(RawEnumEntryContainer), + Enum(RawEnumTypeContainer), + EnumEntry(RawEnumEntryContainer), - LoweredStruct(bool, LoweredStructTypeContainer), + LoweredStruct(bool, LoweredStructTypeContainer), - SizedInteger(bool), - SizedFloating(bool), - SizedFixedPoint(bool) + SizedInteger(bool), + SizedFloating(bool), + SizedFixedPoint(bool), } impl RawType { - /// Make a hint type. - pub fn make_hint(hint_amount: usize) -> RawType { - let bits = (hint_amount as f64).log2().ceil() as usize; - - return RawType::Integer(bits, false) - } - - pub fn get_type_params_count(&self, storage: &TypedGlobalScope) -> usize { - match self { - RawType::Enum(container) => container.type_params.len(), - RawType::EnumEntry(container), - RawType::Struct(_, container) => container.type_params.len(), - - _ => 0 - } - } - - pub fn is_enum_parent(&self) -> bool { - match self { - Self::Enum(_) => true, - Self::LoweredStruct(_, b) => b.is_lowered_enum_parent, - _ => false - } - } - - pub fn is_enum_child(&self) -> bool { - match self { - Self::EnumEntry(_) => true, - Self::LoweredStruct(_, b) => b.is_lowered_enum_child, - _ => false - } - } - - pub fn is_field_based(&self) -> bool { - match self { - RawType::Struct(_, _) => true, - RawType::EnumEntry(_) => true, - - _ => false - } - } - - pub fn is_signed(&self) -> bool { - match self { - Self::Integer(_, signed) => *signed, - Self::Floating(_, signed) => *signed, - Self::FixedPoint(_, _, signed) => *signed, - - _ => false - } - } - - pub fn is_sized(&self) -> bool { - match self { - Self::SizedInteger(_) => true, - Self::SizedFloating(_) => true, - Self::SizedFixedPoint(_) => true, - - _ => false - } - } - - pub fn is_integer(&self) -> bool { - match self { - Self::SizedInteger(_) => true, - Self::Integer(_, _) => true, - - _ => false - } - } - - pub fn is_floating_point(&self) -> bool { - match self { - Self::SizedFloating(_) => true, - Self::Floating(_, _) => true, - - _ => false - } - } - - pub fn is_fixed_point(&self) -> bool { - match self { - Self::SizedFixedPoint(_) => true, - Self::FixedPoint(_, _, _) => true, - _ => false - } - } - - pub fn is_static(&self) -> bool { - match self { - Self::StaticString => true, - _ => false - } - } - - pub fn has_trait(&self, t: Trait, raw_type: &Type) -> bool { - match t { - Trait::Integer => self.is_integer(), - Trait::Floating => self.is_floating_point(), - Trait::Fixed => self.is_fixed_point(), - Trait::Signed => self.is_signed(), - Trait::String => self == &RawType::StaticString, - Trait::Static => self.is_static(), - Trait::NonInteger => self.is_floating_point() || self.is_fixed_point(), - Trait::Numeric => self.is_integer() || self.is_floating_point() || self.is_fixed_point(), - Trait::CpuSupported => { - match self { - Self::Floating(size, _) => { - let log = size.ilog2(); - - return (log >= 4 && log <= 7) || *size == 80; - }, - - Self::SizedFloating(_) => { - let size = raw_type.get_generic_info().1[0]; - let log = size.ilog2(); - - return (log >= 4 && log <= 7) || size == 80; - } - - _ => return true - } - } - } - } - - pub fn can_transmute(&self, _self_size: Vec, b: &RawType, _b_sizes: Vec) -> bool { - match (self, b) { - (Self::Integer(_, _), Self::Integer(_, _)) => true, - (Self::SizedInteger(_), Self::Integer(_, _)) => true, - (Self::Integer(_, _), Self::SizedInteger(_)) => true, - - (Self::Floating(_, _), Self::Integer(_, _)) => true, - (Self::Integer(_, _), Self::Floating(_, _)) => true, - - (Self::Floating(_, _), Self::SizedInteger(_)) => true, - (Self::SizedInteger(_), Self::Floating(_, _)) => true, - - (Self::StaticString, Self::Pointer) => true, - - (Self::EnumEntry(container), Self::Enum(c2)) => { - return container.parent == c2.self_ref; - } - - _ => false - } - } + /// Make a hint type. + pub fn make_hint(hint_amount: usize) -> RawType { + let bits = (hint_amount as f64).log2().ceil() as usize; + + return RawType::Integer(bits, false); + } + + pub fn get_type_params_count( + &self, + storage: &TypedGlobalScope, + origin: &K, + ) -> DiagnosticResult { + match self { + RawType::Enum(container) => Ok(container.type_params.len()), + RawType::EnumEntry(container) => Ok(storage.entries[container.parent] + .as_type(origin)? + .get_type_params_count(storage, origin)?), + RawType::Struct(_, container) => Ok(container.type_params.len()), + + _ => Ok(0), + } + } + + pub fn is_enum_parent(&self) -> bool { + match self { + Self::Enum(_) => true, + Self::LoweredStruct(_, b) => b.is_lowered_enum_parent, + _ => false, + } + } + + pub fn is_enum_child(&self) -> bool { + match self { + Self::EnumEntry(_) => true, + Self::LoweredStruct(_, b) => b.is_lowered_enum_child, + _ => false, + } + } + + pub fn is_field_based(&self) -> bool { + match self { + RawType::Struct(_, _) => true, + RawType::EnumEntry(_) => true, + + _ => false, + } + } + + pub fn is_signed(&self) -> bool { + match self { + Self::Integer(_, signed) => *signed, + Self::Floating(_, signed) => *signed, + Self::FixedPoint(_, _, signed) => *signed, + + _ => false, + } + } + + pub fn is_sized(&self) -> bool { + match self { + Self::SizedInteger(_) => true, + Self::SizedFloating(_) => true, + Self::SizedFixedPoint(_) => true, + + _ => false, + } + } + + pub fn is_integer(&self) -> bool { + match self { + Self::SizedInteger(_) => true, + Self::Integer(_, _) => true, + + _ => false, + } + } + + pub fn is_floating_point(&self) -> bool { + match self { + Self::SizedFloating(_) => true, + Self::Floating(_, _) => true, + + _ => false, + } + } + + pub fn is_fixed_point(&self) -> bool { + match self { + Self::SizedFixedPoint(_) => true, + Self::FixedPoint(_, _, _) => true, + _ => false, + } + } + + pub fn is_static(&self) -> bool { + match self { + Self::StaticString => true, + _ => false, + } + } + + pub fn has_trait(&self, t: Trait, raw_type: &Type) -> bool { + match t { + Trait::Integer => self.is_integer(), + Trait::Floating => self.is_floating_point(), + Trait::Fixed => self.is_fixed_point(), + Trait::Signed => self.is_signed(), + Trait::String => self == &RawType::StaticString, + Trait::Static => self.is_static(), + Trait::NonInteger => self.is_floating_point() || self.is_fixed_point(), + Trait::Numeric => { + self.is_integer() || self.is_floating_point() || self.is_fixed_point() + } + Trait::CpuSupported => match self { + Self::Floating(size, _) => { + let log = size.ilog2(); + + return (log >= 4 && log <= 7) || *size == 80; + } + + Self::SizedFloating(_) => { + let size = raw_type.get_generic_info().1[0]; + let log = size.ilog2(); + + return (log >= 4 && log <= 7) || size == 80; + } + + _ => return true, + }, + } + } + + pub fn can_transmute(&self, _self_size: Vec, b: &RawType, _b_sizes: Vec) -> bool { + match (self, b) { + (Self::Integer(_, _), Self::Integer(_, _)) => true, + (Self::SizedInteger(_), Self::Integer(_, _)) => true, + (Self::Integer(_, _), Self::SizedInteger(_)) => true, + + (Self::Floating(_, _), Self::Integer(_, _)) => true, + (Self::Integer(_, _), Self::Floating(_, _)) => true, + + (Self::Floating(_, _), Self::SizedInteger(_)) => true, + (Self::SizedInteger(_), Self::Floating(_, _)) => true, + + (Self::StaticString, Self::Pointer) => true, + + (Self::EnumEntry(container), Self::Enum(c2)) => { + return container.parent == c2.self_ref; + } + + _ => false, + } + } } impl SizedType for RawType { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { - match self { - RawType::Integer(size, _) => *size, - RawType::Floating(size, _) => *size, - RawType::FixedPoint(size_a, size_b, _) => *size_a + size_b, - RawType::Boolean => { - if compacted_size { - return 1; - } - - return 8; - }, - - RawType::Pointer => return get_pointer_size(), - - RawType::StaticString => return 0, // TODO: make sure we don't need this - - RawType::Struct(_, container) => return container.get_size(t, compacted_size, storage), - RawType::Enum(container) => return container.get_size(t, compacted_size, storage), - RawType::EnumEntry(container) => return container.get_size(t, compacted_size, storage), - RawType::LoweredStruct(_, container) => return container.get_size(t, compacted_size, storage), - - _ => return 0 - } - } + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { + match self { + RawType::Integer(size, _) => *size, + RawType::Floating(size, _) => *size, + RawType::FixedPoint(size_a, size_b, _) => *size_a + size_b, + RawType::Boolean => { + if compacted_size { + return 1; + } + + return 8; + } + + RawType::Pointer => return get_pointer_size(), + + RawType::StaticString => return 0, // TODO: make sure we don't need this + + RawType::Struct(_, container) => return container.get_size(t, compacted_size, storage), + RawType::Enum(container) => return container.get_size(t, compacted_size, storage), + RawType::EnumEntry(container) => return container.get_size(t, compacted_size, storage), + RawType::LoweredStruct(_, container) => { + return container.get_size(t, compacted_size, storage); + } + + _ => return 0, + } + } } impl Display for RawType { - // TODO: add display names for structs and enums - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Integer(size, signed) => { - if *signed { - format!("s{}", size) - } else { - format!("u{}", size) - } - }, - - Self::Floating(size, signed) => { - if *signed { - format!("f{}", size) - } else { - format!("uf{}", size) - } - }, - - Self::FixedPoint(a, b, signed) => { - if *signed { - format!("x{}", a + b) - } else { - format!("ux{}", a + b) - } - }, - - Self::Boolean => "bool".to_string(), - Self::Pointer => "ptr".to_string(), - Self::StaticString => "staticstr".to_string(), - - Self::Struct(_, _) => "__struct__".to_string(), - Self::Enum(_) => "__enum__".to_string(), - Self::EnumEntry(_) => "__enum__child".to_string(), - Self::LoweredStruct(_, _) => "__low__struct__".to_string(), - - Self::SizedInteger(signed) => { - if *signed { - "s?".to_string() - } else { - "u?".to_string() - } - }, - - Self::SizedFloating(signed) => { - if *signed { - "f?".to_string() - } else { - "uf?".to_string() - } - }, - - Self::SizedFixedPoint(signed) => { - if *signed { - "x?".to_string() - } else { - "ux?".to_string() - } - } - }; - - write!(f, "{}", s) - } + // TODO: add display names for structs and enums + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Integer(size, signed) => { + if *signed { + format!("s{}", size) + } else { + format!("u{}", size) + } + } + + Self::Floating(size, signed) => { + if *signed { + format!("f{}", size) + } else { + format!("uf{}", size) + } + } + + Self::FixedPoint(a, b, signed) => { + if *signed { + format!("x{}", a + b) + } else { + format!("ux{}", a + b) + } + } + + Self::Boolean => "bool".to_string(), + Self::Pointer => "ptr".to_string(), + Self::StaticString => "staticstr".to_string(), + + Self::Struct(_, _) => "__struct__".to_string(), + Self::Enum(_) => "__enum__".to_string(), + Self::EnumEntry(_) => "__enum__child".to_string(), + Self::LoweredStruct(_, _) => "__low__struct__".to_string(), + + Self::SizedInteger(signed) => { + if *signed { + "s?".to_string() + } else { + "u?".to_string() + } + } + + Self::SizedFloating(signed) => { + if *signed { + "f?".to_string() + } else { + "uf?".to_string() + } + } + + Self::SizedFixedPoint(signed) => { + if *signed { + "x?".to_string() + } else { + "ux?".to_string() + } + } + }; + + write!(f, "{}", s) + } } impl Hash for RawType { - fn hash(&self, hasher: &mut H) { - match self { - Self::Integer(a, b) => { - hasher.write_usize(0); - hasher.write_usize(*a); - hasher.write_u8(*b as u8); - }, - - Self::Floating(a, b) => { - hasher.write_usize(1); - hasher.write_usize(*a); - hasher.write_u8(*b as u8); - }, - - Self::FixedPoint(a, b, c) => { - hasher.write_usize(2); - hasher.write_usize(*a); - hasher.write_usize(*b); - hasher.write_u8(*c as u8); - }, - - Self::Boolean => hasher.write_usize(3), - Self::Pointer => hasher.write_usize(4), - Self::StaticString => hasher.write_usize(5), - - Self::LoweredStruct(a, b) => { - hasher.write_usize(6); - hasher.write_u8(*a as u8); - - for field in &b.fields.vals { - field.hash(hasher); - } - - for function in &b.functions.vals { - hasher.write_usize(*function); - } - }, - - RawType::Enum(container) => { - hasher.write_usize(7); - hasher.write_usize(container.self_ref); - } - - _ => panic!("Unhashable type {:#?}", self) - } - } -} \ No newline at end of file + fn hash(&self, hasher: &mut H) { + match self { + Self::Integer(a, b) => { + hasher.write_usize(0); + hasher.write_usize(*a); + hasher.write_u8(*b as u8); + } + + Self::Floating(a, b) => { + hasher.write_usize(1); + hasher.write_usize(*a); + hasher.write_u8(*b as u8); + } + + Self::FixedPoint(a, b, c) => { + hasher.write_usize(2); + hasher.write_usize(*a); + hasher.write_usize(*b); + hasher.write_u8(*c as u8); + } + + Self::Boolean => hasher.write_usize(3), + Self::Pointer => hasher.write_usize(4), + Self::StaticString => hasher.write_usize(5), + + Self::LoweredStruct(a, b) => { + hasher.write_usize(6); + hasher.write_u8(*a as u8); + + for field in &b.fields.vals { + field.hash(hasher); + } + + for function in &b.functions.vals { + hasher.write_usize(*function); + } + } + + RawType::Enum(container) => { + hasher.write_usize(7); + hasher.write_usize(container.self_ref); + } + + _ => panic!("Unhashable type {:#?}", self), + } + } +} diff --git a/compiler/compiler_typing/src/references.rs b/compiler/compiler_typing/src/references.rs index 397cda5..0361eff 100644 --- a/compiler/compiler_typing/src/references.rs +++ b/compiler/compiler_typing/src/references.rs @@ -5,50 +5,47 @@ use crate::tree::Type; /// References a type from two states: resolved and unresolved. Allows for type parameters #[derive(Clone, Debug, PartialEq, Eq)] pub enum TypeReference { - Resolved(Type), - - /// Respresents the index of the type parameter - Unresolved(usize) + Resolved(Type), + + /// Respresents the index of the type parameter + Unresolved(usize), } impl TypeReference { - pub fn make_resolved(t: Type) -> Self { - Self::Resolved(t) - } - - pub fn make_unresolved(index: usize) -> Self { - Self::Unresolved(index) - } - - pub fn is_resolved(&self) -> bool { - if let Self::Resolved(_) = self { - return true; - } - - return false; - } - - /// Attempts to cast the type reference into a concrete Type. Will not try to resolve the type from the argument params - pub fn as_resolved(self) -> Type { - if let TypeReference::Resolved(val) = self { - return val; - } - - unsure_panic!("used as_resolved on a non resolved type") - } - - /// Attempts to resolve the type reference into a concrete `Type`. - pub fn resolve(self, t: &Type) -> Type { - match &self { - TypeReference::Resolved(val) => return val.clone(), - TypeReference::Unresolved(index) => { - let concrete_info = t.get_generic_info(); - - return concrete_info.0[*index].as_ref().clone() - } - } - - - } - -} \ No newline at end of file + pub fn make_resolved(t: Type) -> Self { + Self::Resolved(t) + } + + pub fn make_unresolved(index: usize) -> Self { + Self::Unresolved(index) + } + + pub fn is_resolved(&self) -> bool { + if let Self::Resolved(_) = self { + return true; + } + + return false; + } + + /// Attempts to cast the type reference into a concrete Type. Will not try to resolve the type from the argument params + pub fn as_resolved(self) -> Type { + if let TypeReference::Resolved(val) = self { + return val; + } + + unsure_panic!("used as_resolved on a non resolved type") + } + + /// Attempts to resolve the type reference into a concrete `Type`. + pub fn resolve(self, t: &Type) -> Type { + match &self { + TypeReference::Resolved(val) => return val.clone(), + TypeReference::Unresolved(index) => { + let concrete_info = t.get_generic_info(); + + return concrete_info.0[*index].as_ref().clone(); + } + } + } +} diff --git a/compiler/compiler_typing/src/storage.rs b/compiler/compiler_typing/src/storage.rs deleted file mode 100644 index 3130fa6..0000000 --- a/compiler/compiler_typing/src/storage.rs +++ /dev/null @@ -1,162 +0,0 @@ -use std::collections::HashMap; - -use compiler_utils::{hash, utils::indexed::IndexStorage}; -use compiler_utils::hash::HashedString; - -use crate::{TypeParameterContainer, enums::{RawEnumTypeContainer}, raw::RawType, references::TypeReference}; - -pub const SIGNED_INTEGER_8: u64 = hash!("s8"); -pub const SIGNED_INTEGER_16: u64 = hash!("s16"); -pub const SIGNED_INTEGER_32: u64 = hash!("s32"); -pub const SIGNED_INTEGER_64: u64 = hash!("s64"); -pub const SIGNED_INTEGER_128: u64 = hash!("s128"); -pub const SIGNED_INTEGER: u64 = hash!("s"); - -pub const UNSIGNED_INTEGER_8: u64 = hash!("u8"); -pub const UNSIGNED_INTEGER_16: u64 = hash!("u16"); -pub const UNSIGNED_INTEGER_32: u64 = hash!("u32"); -pub const UNSIGNED_INTEGER_64: u64 = hash!("u64"); -pub const UNSIGNED_INTEGER_128: u64 = hash!("u128"); -pub const UNSIGNED_INTEGER: u64 = hash!("u"); - -pub const SIGNED_FLOATING_POINT_8: u64 = hash!("f8"); -pub const SIGNED_FLOATING_POINT_16: u64 = hash!("f16"); -pub const SIGNED_FLOATING_POINT_32: u64 = hash!("f32"); -pub const SIGNED_FLOATING_POINT_64: u64 = hash!("f64"); -pub const SIGNED_FLOATING_POINT_80: u64 = hash!("f80"); -pub const SIGNED_FLOATING_POINT_128: u64 = hash!("f128"); -pub const SIGNED_FLOATING_POINT: u64 = hash!("f"); - -pub const SIGNED_FIXED_POINT_8: u64 = hash!("x8"); -pub const SIGNED_FIXED_POINT_16: u64 = hash!("x16"); -pub const SIGNED_FIXED_POINT_32: u64 = hash!("x32"); -pub const SIGNED_FIXED_POINT_64: u64 = hash!("x64"); -pub const SIGNED_FIXED_POINT_128: u64 = hash!("x128"); -pub const SIGNED_FIXED_POINT: u64 = hash!("x"); - -pub const UNSIGNED_FLOATING_POINT_8: u64 = hash!("uf8"); -pub const UNSIGNED_FLOATING_POINT_16: u64 = hash!("uf16"); -pub const UNSIGNED_FLOATING_POINT_32: u64 = hash!("uf32"); -pub const UNSIGNED_FLOATING_POINT_64: u64 = hash!("uf64"); -pub const UNSIGNED_FLOATING_POINT_80: u64 = hash!("uf80"); -pub const UNSIGNED_FLOATING_POINT_128: u64 = hash!("uf128"); -pub const UNSIGNED_FLOATING_POINT: u64 = hash!("uf"); - -pub const UNSIGNED_FIXED_POINT_8: u64 = hash!("ux8"); -pub const UNSIGNED_FIXED_POINT_16: u64 = hash!("ux16"); -pub const UNSIGNED_FIXED_POINT_32: u64 = hash!("ux32"); -pub const UNSIGNED_FIXED_POINT_64: u64 = hash!("ux64"); -pub const UNSIGNED_FIXED_POINT_128: u64 = hash!("ux128"); -pub const UNSIGNED_FIXED_POINT: u64 = hash!("ux"); - -pub const STATIC_STR: u64 = hash!("staticstr"); - -pub const POINTER_TYPE: u64 = hash!("ptr"); -pub const BOOLEAN_TYPE: u64 = hash!("bool"); - -/// Experimental -pub const RESULT_TYPE: u64 = hash!("result"); - -#[derive(Debug)] -#[deprecated = "Deprecated to use global scope"] -pub struct TypeStorage { - pub types: IndexStorage, - pub type_to_ind: HashMap -} - -impl TypeStorage { - #[must_use = "must handle errors outside"] - pub fn new() -> Result { - let mut storage = TypeStorage { types: IndexStorage::new(), type_to_ind: HashMap::new() }; - - storage.append_with_hash(SIGNED_INTEGER_8, RawType::Integer(8, true))?; - storage.append_with_hash(SIGNED_INTEGER_16, RawType::Integer(16, true))?; - storage.append_with_hash(SIGNED_INTEGER_32, RawType::Integer(32, true))?; - storage.append_with_hash(SIGNED_INTEGER_64, RawType::Integer(64, true))?; - storage.append_with_hash(SIGNED_INTEGER_128, RawType::Integer(128, true))?; - - storage.append_with_hash(UNSIGNED_INTEGER_8, RawType::Integer(8, false))?; - storage.append_with_hash(UNSIGNED_INTEGER_16, RawType::Integer(16, false))?; - storage.append_with_hash(UNSIGNED_INTEGER_32, RawType::Integer(32, false))?; - storage.append_with_hash(UNSIGNED_INTEGER_64, RawType::Integer(64, false))?; - storage.append_with_hash(UNSIGNED_INTEGER_128, RawType::Integer(128, false))?; - - storage.append_with_hash(SIGNED_FLOATING_POINT_8, RawType::Floating(8, true))?; - storage.append_with_hash(SIGNED_FLOATING_POINT_16, RawType::Floating(16, true))?; - storage.append_with_hash(SIGNED_FLOATING_POINT_32, RawType::Floating(32, true))?; - storage.append_with_hash(SIGNED_FLOATING_POINT_64, RawType::Floating(64, true))?; - storage.append_with_hash(SIGNED_FLOATING_POINT_128, RawType::Floating(128, true))?; - - storage.append_with_hash(UNSIGNED_FLOATING_POINT_8, RawType::Floating(8, false))?; - storage.append_with_hash(UNSIGNED_FLOATING_POINT_16, RawType::Floating(16, false))?; - storage.append_with_hash(UNSIGNED_FLOATING_POINT_32, RawType::Floating(32, false))?; - storage.append_with_hash(UNSIGNED_FLOATING_POINT_64, RawType::Floating(64, false))?; - storage.append_with_hash(UNSIGNED_FLOATING_POINT_128, RawType::Floating(128, false))?; - - storage.append_with_hash(SIGNED_FIXED_POINT_8, RawType::FixedPoint(4, 4, true))?; - storage.append_with_hash(SIGNED_FIXED_POINT_16, RawType::FixedPoint(8, 8, true))?; - storage.append_with_hash(SIGNED_FIXED_POINT_32, RawType::FixedPoint(16, 16, true))?; - storage.append_with_hash(SIGNED_FIXED_POINT_64, RawType::FixedPoint(32, 32, true))?; - storage.append_with_hash(SIGNED_FIXED_POINT_128, RawType::FixedPoint(64, 64, true))?; - - storage.append_with_hash(UNSIGNED_FIXED_POINT_8, RawType::FixedPoint(4, 4, false))?; - storage.append_with_hash(UNSIGNED_FIXED_POINT_16, RawType::FixedPoint(8, 8, false))?; - storage.append_with_hash(UNSIGNED_FIXED_POINT_32, RawType::FixedPoint(16, 16, false))?; - storage.append_with_hash(UNSIGNED_FIXED_POINT_64, RawType::FixedPoint(32, 32, false))?; - storage.append_with_hash(UNSIGNED_FIXED_POINT_128, RawType::FixedPoint(64, 64, false))?; - - storage.append_with_hash(BOOLEAN_TYPE, RawType::Boolean)?; - storage.append_with_hash(POINTER_TYPE, RawType::Pointer)?; - storage.append_with_hash(STATIC_STR, RawType::StaticString)?; - - { - - let mut type_params = TypeParameterContainer::new(); - - type_params.insert(HashedString::new("V".to_string()), 0); - type_params.insert(HashedString::new("E".to_string()), 1); - - let mut result_enum = RawEnumTypeContainer::new(storage.types.vals.len(), type_params); - - result_enum.append_entry(HashedString::new("value".to_string()), vec![(hash!("val"), TypeReference::make_unresolved(0))]); - result_enum.append_entry(HashedString::new("error".to_string()), vec![(hash!("err"), TypeReference::make_unresolved(1))]); - - storage.append(RESULT_TYPE, RawType::Enum(result_enum))?; - } - - return Ok(storage); - } - - #[must_use = "must handle errors outside"] - pub fn append_with_hash(&mut self, hash: u64, base: RawType) -> Result { - if self.types.hash_to_ind.contains_key(&hash) { - return Err(()) - } - - let res = self.types.append(hash, base.clone()); - - self.type_to_ind.insert(base, res); - - return Ok(res); - } - - #[must_use = "must handle errors outside"] - pub fn append(&mut self, hash: u64, base: RawType) -> Result { - if self.types.hash_to_ind.contains_key(&hash) { - return Err(()) - } - - let res = self.types.append(hash, base.clone()); - - return Ok(res); - } - - #[must_use = "must handle errors outside"] - pub fn get_type(&self, hash: u64) -> Result { - if let Some(v) = self.types.get_index(hash) { - return Ok(self.types.get_ind(v).clone()); - } - - return Err(()) - } -} \ No newline at end of file diff --git a/compiler/compiler_typing/src/structs.rs b/compiler/compiler_typing/src/structs.rs index b5bc0c3..f67264c 100644 --- a/compiler/compiler_typing/src/structs.rs +++ b/compiler/compiler_typing/src/structs.rs @@ -1,125 +1,138 @@ use std::collections::HashMap; use compiler_utils::utils::indexed::IndexStorage; -use diagnostics::{DiagnosticResult, builders::{make_cannot_find_type_field, make_cannot_find_type_function}}; - -use crate::{SizedType, StructuredType, TypeParamType, TypeParameterContainer, TypeReference, TypedFunction, enums::{RawEnumEntryContainer, RawEnumTypeContainer}, storage::TypeStorage, tree::Type}; +use diagnostics::{ + DiagnosticResult, + builders::{make_cannot_find_type_field, make_cannot_find_type_function}, +}; + +use crate::{ + SizedType, StructuredType, TypeParamType, TypeParameterContainer, TypeReference, TypedFunction, + TypedGlobalScope, + enums::{RawEnumEntryContainer, RawEnumTypeContainer}, + tree::Type, +}; /// Container for structure types #[derive(Clone, Debug, PartialEq, Eq)] pub struct RawStructTypeContainer { - pub fields: IndexStorage, - pub type_params: TypeParameterContainer, - pub functions: IndexStorage + pub fields: IndexStorage, + pub type_params: TypeParameterContainer, + pub functions: IndexStorage, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct LoweredStructTypeContainer { - pub fields: IndexStorage, - pub is_lowered_enum_child: bool, - pub is_lowered_enum_parent: bool, - pub lowered_enum_parent: Option, - pub lowered_enum_child: Option, - pub hir_mir_indexes: HashMap, - pub functions: IndexStorage + pub fields: IndexStorage, + pub is_lowered_enum_child: bool, + pub is_lowered_enum_parent: bool, + pub lowered_enum_parent: Option, + pub lowered_enum_child: Option, + pub hir_mir_indexes: HashMap, + pub functions: IndexStorage, } impl LoweredStructTypeContainer { - - /// Resolves the given `HIR` field index into the corresponding `MIR` field index if said one has changed. - pub fn resolve_hir_index(&self, ind: usize) -> usize { - if self.hir_mir_indexes.contains_key(&ind) { - return self.hir_mir_indexes[&ind]; - } - - return ind; - } - - pub fn append_hir_index_conv(&mut self, hir: usize, mir: usize) { - self.hir_mir_indexes.insert(hir, mir); - } - + /// Resolves the given `HIR` field index into the corresponding `MIR` field index if said one has changed. + pub fn resolve_hir_index(&self, ind: usize) -> usize { + if self.hir_mir_indexes.contains_key(&ind) { + return self.hir_mir_indexes[&ind]; + } + + return ind; + } + + pub fn append_hir_index_conv(&mut self, hir: usize, mir: usize) { + self.hir_mir_indexes.insert(hir, mir); + } } impl SizedType for LoweredStructTypeContainer { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize { - let mut size = 0; + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { + let mut size = 0; - for field in &self.fields.vals { - size += field.get_size(t, compacted_size, storage) - } + for field in &self.fields.vals { + size += field.get_size(t, compacted_size, storage) + } - return size; - } + return size; + } } impl SizedType for RawStructTypeContainer { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize { - let mut size = 0; + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { + let mut size = 0; - for field in &self.fields.vals { - let base = field.clone().resolve(&t); + for field in &self.fields.vals { + let base = field.clone().resolve(&t); - size += base.get_size(t, compacted_size, storage); - } + size += base.get_size(t, compacted_size, storage); + } - return size - } + return size; + } } impl StructuredType for RawStructTypeContainer { - fn get_function(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.functions.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()) - //None => return Err(BaseError::err(IR_FIND_ELEMENT!().to_string())) - }; - - return Ok(self.functions.vals[k].clone()) - } - - fn get_fields(&self, _storage: &TypeStorage) -> Vec { - return self.fields.entry_keys.clone(); - } - - fn get_functions(&self, _storage: &TypeStorage) -> Vec { - return self.functions.entry_keys.clone(); - } - - fn get_function_hash(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.functions.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()) - }; - - return Ok(k); - } - - fn get_field(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.fields.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()) - }; - - return Ok(self.fields.vals[k].clone()); - } - - fn get_field_hash(&self, hash: u64, _storage: &TypeStorage) -> DiagnosticResult { - let k = match self.fields.get_index(hash) { - Some(v) => v, - None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()) - }; - - return Ok(k); - } + fn get_function( + &self, + hash: u64, + _storage: &TypedGlobalScope, + ) -> DiagnosticResult { + let k = match self.functions.get_index(hash) { + Some(v) => v, + None => { + return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()); + } + }; + + return Ok(self.functions.vals[k].clone()); + } + + fn get_fields(&self, _storage: &TypedGlobalScope) -> Vec { + return self.fields.entry_keys.clone(); + } + + fn get_functions(&self, _storage: &TypedGlobalScope) -> Vec { + return self.functions.entry_keys.clone(); + } + + fn get_function_hash(&self, hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + let k = match self.functions.get_index(hash) { + Some(v) => v, + None => { + return Err(make_cannot_find_type_function(&hash, &"unnamed".to_string()).into()); + } + }; + + return Ok(k); + } + + fn get_field(&self, hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + let k = match self.fields.get_index(hash) { + Some(v) => v, + None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()), + }; + + return Ok(self.fields.vals[k].clone()); + } + + fn get_field_hash(&self, hash: u64, _storage: &TypedGlobalScope) -> DiagnosticResult { + let k = match self.fields.get_index(hash) { + Some(v) => v, + None => return Err(make_cannot_find_type_field(&hash, &"unamed".to_string()).into()), + }; + + return Ok(k); + } } impl TypeParamType for RawStructTypeContainer { - fn has_type_param(&self, param: &compiler_utils::hash::HashedString) -> bool { - self.type_params.contains_key(param) - } - - fn get_type_param_ind(&self, param: &compiler_utils::hash::HashedString) -> usize { - self.type_params[param] - } -} \ No newline at end of file + fn has_type_param(&self, param: &compiler_utils::hash::HashedString) -> bool { + self.type_params.contains_key(param) + } + + fn get_type_param_ind(&self, param: &compiler_utils::hash::HashedString) -> usize { + self.type_params[param] + } +} diff --git a/compiler/compiler_typing/src/transmutation/array.rs b/compiler/compiler_typing/src/transmutation/array.rs index 87e63b1..f715cc0 100644 --- a/compiler/compiler_typing/src/transmutation/array.rs +++ b/compiler/compiler_typing/src/transmutation/array.rs @@ -1,17 +1,21 @@ //! Handles transmutation for arrays. -//! +//! //! # Behavior //! Instead of doing a rough transmutation of the array type, Quickfall will try to transmute the types inside of the array if they can //! be transmutated without a `Cast` node. If that transmutation can happen, Quickfall will directly try to. -use crate::{storage::TypeStorage, tree::Type}; +use crate::{TypedGlobalScope, tree::Type}; -/// Utility function to determinate if an array type can be transmutated by the inner type. +/// Utility function to determinate if an array type can be transmutated by the inner type. /// This determines if we use the array strategy or a cast node. -pub fn can_transmute_inner(array_type: &Type, new_type: &Type, storage: &TypeStorage) -> bool { - if !array_type.can_use_index_access() || !new_type.can_use_index_access() { - panic!("Either ones of the types sent when using can_transmute_inner were not actual array types!") - } +pub fn can_transmute_inner(array_type: &Type, new_type: &Type, storage: &TypedGlobalScope) -> bool { + if !array_type.can_use_index_access() || !new_type.can_use_index_access() { + panic!( + "Either ones of the types sent when using can_transmute_inner were not actual array types!" + ) + } - return array_type.get_inner_type().can_transmute(&new_type.get_inner_type(), storage) -} \ No newline at end of file + return array_type + .get_inner_type() + .can_transmute(&new_type.get_inner_type(), storage); +} diff --git a/compiler/compiler_typing/src/transmutation/mod.rs b/compiler/compiler_typing/src/transmutation/mod.rs index 7bcfefa..cf550d2 100644 --- a/compiler/compiler_typing/src/transmutation/mod.rs +++ b/compiler/compiler_typing/src/transmutation/mod.rs @@ -1,64 +1,66 @@ //! Handling for type transmutations here. -use crate::{storage::TypeStorage, tree::Type}; +use crate::{TypedGlobalScope, tree::Type}; pub mod array; impl Type { - /// Checks if the type tree can be transmuted into another one. Transmutation is the process used by the typing system to see if - /// a variable can automatically be casted into another type. - /// - /// # Note - /// This function uses recursion to go down the type tree and check `can_transmute` on every node. - pub fn can_transmute(&self, other: &Type, storage: &TypeStorage) -> bool { - match (self, other) { - (Self::Pointer(is_array, _), Self::Pointer(is_array_2, _)) => { - return *is_array == *is_array_2; - }, + /// Checks if the type tree can be transmuted into another one. Transmutation is the process used by the typing system to see if + /// a variable can automatically be casted into another type. + /// + /// # Note + /// This function uses recursion to go down the type tree and check `can_transmute` on every node. + pub fn can_transmute(&self, other: &Type, storage: &TypedGlobalScope) -> bool { + match (self, other) { + (Self::Pointer(is_array, _), Self::Pointer(is_array_2, _)) => { + return *is_array == *is_array_2; + } - (Self::Reference(inner), Self::Pointer(array, inner2)) => { - return !*array && inner.can_transmute(inner2, storage); - } + (Self::Reference(inner), Self::Pointer(array, inner2)) => { + return !*array && inner.can_transmute(inner2, storage); + } - (Self::Array(size, base), Self::Array(size2, base2)) => { - if size != size2 { - return false; - } + (Self::Array(size, base), Self::Array(size2, base2)) => { + if size != size2 { + return false; + } - return base.clone().can_transmute(&base2, storage); - }, + return base.clone().can_transmute(&base2, storage); + } - // TODO: add generic transmutation checking when type storage implemented. - (Self::Generic(raw_type, type_params, sizes), Self::Generic(raw_type2, type_params2, sizes2)) => { - if type_params != type_params2 { - return false; - } + // TODO: add generic transmutation checking when type storage implemented. + ( + Self::Generic(raw_type, type_params, sizes), + Self::Generic(raw_type2, type_params2, sizes2), + ) => { + if type_params != type_params2 { + return false; + } - return raw_type.can_transmute(sizes.clone(), raw_type2, sizes2.clone()) - }, + return raw_type.can_transmute(sizes.clone(), raw_type2, sizes2.clone()); + } - (Self::GenericLowered(base), Self::Generic(rawtype, type_params, sizes)) => { - if !type_params.is_empty() { - return false; - } + (Self::GenericLowered(base), Self::Generic(rawtype, type_params, sizes)) => { + if !type_params.is_empty() { + return false; + } - return base.can_transmute(vec![], rawtype, sizes.clone()) - }, + return base.can_transmute(vec![], rawtype, sizes.clone()); + } - (Self::Generic(rawtype, type_params, sizes), Self::GenericLowered(base)) => { - if !type_params.is_empty() { - return false; - } + (Self::Generic(rawtype, type_params, sizes), Self::GenericLowered(base)) => { + if !type_params.is_empty() { + return false; + } - return base.can_transmute(vec![], rawtype, sizes.clone()) - } + return base.can_transmute(vec![], rawtype, sizes.clone()); + } - (Self::GenericLowered(base), Self::GenericLowered(base2)) => { - return base.can_transmute(vec![], base2, vec![]); - } + (Self::GenericLowered(base), Self::GenericLowered(base2)) => { + return base.can_transmute(vec![], base2, vec![]); + } - - _ => false - } - } -} \ No newline at end of file + _ => false, + } + } +} diff --git a/compiler/compiler_typing/src/tree.rs b/compiler/compiler_typing/src/tree.rs index 67e306d..1ac498d 100644 --- a/compiler/compiler_typing/src/tree.rs +++ b/compiler/compiler_typing/src/tree.rs @@ -2,278 +2,319 @@ use std::fmt::Display; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_req_type_kind, unsure_panic}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, builders::make_req_type_kind, unsure_panic, +}; -use crate::{SizedType, StructuredType, TypedFunction, raw::RawType, references::TypeReference, storage::{TypeStorage}, utils::get_pointer_size}; +use crate::{ + SizedType, StructuredType, TypedFunction, TypedGlobalScope, raw::RawType, + references::TypeReference, utils::get_pointer_size, +}; #[derive(Clone, PartialEq, Debug, Eq, Hash)] /// The node-based typing system of Quickfall. Allows for very specific types. pub enum Type { - /// A generic type node. Represents a classic type. - /// 0: The raw type - /// 1: The type parameters - /// 2: The size specifiers - Generic(RawType, Vec>, Vec), // Potential lowering to base-sized - - /// A generic type node but lowered. Represents a concrete type. - GenericLowered(RawType), - - /// A pointer type node. Represents a pointer version - /// 0: Is the pointer a poiner of arrays - /// 1: Inner type - Pointer(bool, Box), - - /// A reference to a variable. - /// 0: Inner type - Reference(Box), - - /// An array type node. Represents an array version - /// 0: The size of the array - /// 1: Inner type - Array(usize, Box) + /// A generic type node. Represents a classic type. + /// 0: The raw type + /// 1: The type parameters + /// 2: The size specifiers + Generic(RawType, Vec>, Vec), // Potential lowering to base-sized + + /// A generic type node but lowered. Represents a concrete type. + GenericLowered(RawType), + + /// A pointer type node. Represents a pointer version + /// 0: Is the pointer a poiner of arrays + /// 1: Inner type + Pointer(bool, Box), + + /// A reference to a variable. + /// 0: Inner type + Reference(Box), + + /// An array type node. Represents an array version + /// 0: The size of the array + /// 1: Inner type + Array(usize, Box), } impl Type { - pub fn is_pointer(&self) -> bool { - match self { - Self::Pointer(_, _) => true, - _ => false - } - } - - pub fn is_technically_pointer(&self) -> bool { - match self { - Self::Pointer(_, _) => true, - Self::Reference(_) => true, - _ => false - } - } - - pub fn is_ptr(&self) -> bool { - match self { - Self::Pointer(_, _) => true, - Self::Reference(_) => true, - Self::GenericLowered(inner) => inner == &RawType::Pointer, - _ => false - } - } - - pub fn get_maybe_containing_type(&self) -> Type { - match self { - Self::Pointer(_, inner) => *inner.clone(), - Self::Reference(inner) => *inner.clone(), - _ => self.clone() - } - } - - pub fn is_array(&self) -> bool { - match self { - Self::Array(_, _) => true, - _ => false - } - } - - pub fn is_truly_eq(&self, other: &Type) -> bool { - match (self, other) { - (Self::Pointer(is_array, _), Self::Pointer(is_array_2, _)) => { - return *is_array == *is_array_2; - }, - - (Self::Reference(_), Self::GenericLowered(lowered)) => { - return lowered == &RawType::Pointer - }, - - (Self::Reference(inner), Self::Reference(inner2)) => { - return inner.is_truly_eq(inner2); - }, - - (Self::Array(size, base), Self::Array(size2, base2)) => { - if size != size2 { - return false; - } - - return base.is_truly_eq(base2); - }, - - (Self::Generic(raw_type, type_params, sizes), Self::Generic(raw_type2, type_params2, sizes2)) => { - return raw_type == raw_type2 && type_params == type_params2 && sizes == sizes2; - }, - - (Self::GenericLowered(base), Self::GenericLowered(base2)) => { - if *base == RawType::Pointer && *base2 == RawType::StaticString { - return true; - } - - return base == base2; - } - - _ => false - } - } - - pub fn as_generic_lowered_safe(&self, origin: &K) -> DiagnosticResult { - match self { - Type::GenericLowered(a) => return Ok(a.clone()), - _ => return Err(make_req_type_kind(origin, &"generic".to_string()).into()) - } - } - - pub fn as_generic_safe(&self, origin: &K) -> DiagnosticResult { - match self { - Type::Generic(a, _, _) => return Ok(a.clone()), - _ => return Err(make_req_type_kind(origin, &"generic".to_string()).into()) - } - } - - - pub fn as_generic_lowered(&self) -> RawType { - match self { - Type::GenericLowered(a) => return a.clone(), - _ => panic!("Not a lowered generic {:#?}", self) - } - } - - pub fn as_generic(&self) -> RawType { - match self { - Self::GenericLowered(a) => return a.clone(), - Self::Generic(a, _, _) => { - return a.clone(); - }, - - _ => panic!("Cannot obtain generic {:#?}", self) - } - } - - pub fn get_inner_type(&self) -> Box { - match self { - Type::Array(_, inner) => inner.clone(), - Type::Pointer(_, inner) => inner.clone(), - Type::Reference(inner) => inner.clone(), - - _ => { - panic!("Error! Compiler tried using get_inner_type on bottom type! Returning bottom type incase!"); - } - } - } - - pub fn can_use_index_access(&self) -> bool { - match self { - Type::Array(_, _) => true, - _ => false - } - } - - pub fn get_generic_info(&self) -> (Vec>, Vec) { - if let Type::Generic(_, types, sizes) = self { - return (types.clone(), sizes.clone()) - } - - return self.get_inner_type().get_generic_info(); - } - - pub fn get_generic(&self, storage: &TypeStorage) -> RawType { - if let Type::Generic(raw, _, _) = self { - return raw.clone(); - }; - - if let Type::GenericLowered(raw) = self { - return raw.clone(); - } - - return self.get_inner_type().get_generic(storage); - } - - /// Cheaply lowers the generic just to avoid a display crash - pub fn faulty_lowering_generic(&self, storage: &TypeStorage) -> Type { - match self { - Type::Array(a, b) => Type::Array(*a, Box::new(b.faulty_lowering_generic(storage))), - Type::Pointer(a, b) => Type::Pointer(*a, Box::new(b.faulty_lowering_generic(storage))), - Type::Reference(t) => Type::Reference(Box::new(t.faulty_lowering_generic(storage))), - Type::Generic(t, _, _) => Type::GenericLowered(t.clone()), - Type::GenericLowered(_) => self.clone() - } - } - - pub fn get_function(&self, storage: &TypeStorage, hash: u64) -> DiagnosticResult<(usize, TypedFunction)> { - return match self.get_generic(storage) { - RawType::Struct(_, container) => Ok((container.get_function_hash(hash, storage)?, container.get_function(hash, storage)?)), - RawType::Enum(container) => Ok((container.get_function_hash(hash, storage)?, container.get_function(hash, storage)?)), - RawType::EnumEntry(container) => Ok((container.get_function_hash(hash, storage)?, container.get_function(hash, storage)?)), - _ => unsure_panic!("Type cannot contain functions") - }; - } - - pub fn get_field(&self, storage: &TypeStorage, hash: u64) -> DiagnosticResult<(usize, TypeReference)> { - return match self.get_generic(storage) { - RawType::Struct(_, container) => Ok((container.get_field_hash(hash, storage)?, container.get_field(hash, storage)?)), - RawType::Enum(container) => Ok((container.get_field_hash(hash, storage)?, container.get_field(hash, storage)?)), - RawType::EnumEntry(container) => Ok((container.get_field_hash(hash, storage)?, container.get_field(hash, storage)?)), - _ => unsure_panic!("Type cannot contain fields") - } - } - - pub fn get_fields(&self, storage: &TypeStorage) -> Vec { - return match self.get_generic(storage) { - RawType::Struct(_, container) => container.get_fields(storage), - RawType::EnumEntry(container) => container.get_fields(storage), - _ => unsure_panic!("Type cannot contain fields") - } - } - - pub fn get_functions(&self, storage: &TypeStorage) -> Vec { - return match self.get_generic(storage) { - RawType::Struct(_, container) => container.get_functions(storage), - RawType::EnumEntry(container) => container.get_functions(storage), - RawType::Enum(container) => container.get_functions(storage), - _ => unsure_panic!("Type cannot contain functions") - } - } + pub fn is_pointer(&self) -> bool { + match self { + Self::Pointer(_, _) => true, + _ => false, + } + } + + pub fn is_technically_pointer(&self) -> bool { + match self { + Self::Pointer(_, _) => true, + Self::Reference(_) => true, + _ => false, + } + } + + pub fn is_ptr(&self) -> bool { + match self { + Self::Pointer(_, _) => true, + Self::Reference(_) => true, + Self::GenericLowered(inner) => inner == &RawType::Pointer, + _ => false, + } + } + + pub fn get_maybe_containing_type(&self) -> Type { + match self { + Self::Pointer(_, inner) => *inner.clone(), + Self::Reference(inner) => *inner.clone(), + _ => self.clone(), + } + } + + pub fn is_array(&self) -> bool { + match self { + Self::Array(_, _) => true, + _ => false, + } + } + + pub fn is_truly_eq(&self, other: &Type) -> bool { + match (self, other) { + (Self::Pointer(is_array, _), Self::Pointer(is_array_2, _)) => { + return *is_array == *is_array_2; + } + + (Self::Reference(_), Self::GenericLowered(lowered)) => { + return lowered == &RawType::Pointer; + } + + (Self::Reference(inner), Self::Reference(inner2)) => { + return inner.is_truly_eq(inner2); + } + + (Self::Array(size, base), Self::Array(size2, base2)) => { + if size != size2 { + return false; + } + + return base.is_truly_eq(base2); + } + + ( + Self::Generic(raw_type, type_params, sizes), + Self::Generic(raw_type2, type_params2, sizes2), + ) => { + return raw_type == raw_type2 && type_params == type_params2 && sizes == sizes2; + } + + (Self::GenericLowered(base), Self::GenericLowered(base2)) => { + if *base == RawType::Pointer && *base2 == RawType::StaticString { + return true; + } + + return base == base2; + } + + _ => false, + } + } + + pub fn as_generic_lowered_safe( + &self, + origin: &K, + ) -> DiagnosticResult { + match self { + Type::GenericLowered(a) => return Ok(a.clone()), + _ => return Err(make_req_type_kind(origin, &"generic".to_string()).into()), + } + } + + pub fn as_generic_safe( + &self, + origin: &K, + ) -> DiagnosticResult { + match self { + Type::Generic(a, _, _) => return Ok(a.clone()), + _ => return Err(make_req_type_kind(origin, &"generic".to_string()).into()), + } + } + + pub fn as_generic_lowered(&self) -> RawType { + match self { + Type::GenericLowered(a) => return a.clone(), + _ => panic!("Not a lowered generic {:#?}", self), + } + } + + pub fn as_generic(&self) -> RawType { + match self { + Self::GenericLowered(a) => return a.clone(), + Self::Generic(a, _, _) => { + return a.clone(); + } + + _ => panic!("Cannot obtain generic {:#?}", self), + } + } + + pub fn get_inner_type(&self) -> Box { + match self { + Type::Array(_, inner) => inner.clone(), + Type::Pointer(_, inner) => inner.clone(), + Type::Reference(inner) => inner.clone(), + + _ => { + panic!( + "Error! Compiler tried using get_inner_type on bottom type! Returning bottom type incase!" + ); + } + } + } + + pub fn can_use_index_access(&self) -> bool { + match self { + Type::Array(_, _) => true, + _ => false, + } + } + + pub fn get_generic_info(&self) -> (Vec>, Vec) { + if let Type::Generic(_, types, sizes) = self { + return (types.clone(), sizes.clone()); + } + + return self.get_inner_type().get_generic_info(); + } + + pub fn get_generic(&self) -> RawType { + if let Type::Generic(raw, _, _) = self { + return raw.clone(); + }; + + if let Type::GenericLowered(raw) = self { + return raw.clone(); + } + + return self.get_inner_type().get_generic(); + } + + /// Cheaply lowers the generic just to avoid a display crash + pub fn faulty_lowering_generic(&self, storage: &TypedGlobalScope) -> Type { + match self { + Type::Array(a, b) => Type::Array(*a, Box::new(b.faulty_lowering_generic(storage))), + Type::Pointer(a, b) => Type::Pointer(*a, Box::new(b.faulty_lowering_generic(storage))), + Type::Reference(t) => Type::Reference(Box::new(t.faulty_lowering_generic(storage))), + Type::Generic(t, _, _) => Type::GenericLowered(t.clone()), + Type::GenericLowered(_) => self.clone(), + } + } + + pub fn get_function( + &self, + storage: &TypedGlobalScope, + hash: u64, + ) -> DiagnosticResult<(usize, TypedFunction)> { + return match self.get_generic() { + RawType::Struct(_, container) => Ok(( + container.get_function_hash(hash, storage)?, + container.get_function(hash, storage)?, + )), + RawType::Enum(container) => Ok(( + container.get_function_hash(hash, storage)?, + container.get_function(hash, storage)?, + )), + RawType::EnumEntry(container) => Ok(( + container.get_function_hash(hash, storage)?, + container.get_function(hash, storage)?, + )), + _ => unsure_panic!("Type cannot contain functions"), + }; + } + + pub fn get_field( + &self, + storage: &TypedGlobalScope, + hash: u64, + ) -> DiagnosticResult<(usize, TypeReference)> { + return match self.get_generic() { + RawType::Struct(_, container) => Ok(( + container.get_field_hash(hash, storage)?, + container.get_field(hash, storage)?, + )), + RawType::Enum(container) => Ok(( + container.get_field_hash(hash, storage)?, + container.get_field(hash, storage)?, + )), + RawType::EnumEntry(container) => Ok(( + container.get_field_hash(hash, storage)?, + container.get_field(hash, storage)?, + )), + _ => unsure_panic!("Type cannot contain fields"), + }; + } + + pub fn get_fields(&self, storage: &TypedGlobalScope) -> Vec { + return match self.get_generic() { + RawType::Struct(_, container) => container.get_fields(storage), + RawType::EnumEntry(container) => container.get_fields(storage), + _ => unsure_panic!("Type cannot contain fields"), + }; + } + + pub fn get_functions(&self, storage: &TypedGlobalScope) -> Vec { + return match self.get_generic() { + RawType::Struct(_, container) => container.get_functions(storage), + RawType::EnumEntry(container) => container.get_functions(storage), + RawType::Enum(container) => container.get_functions(storage), + _ => unsure_panic!("Type cannot contain functions"), + }; + } } impl Display for Type { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Array(size, inner) => { - format!("{}[{}]", inner, size) - }, - - Self::Generic(low, _, _) => { - format!("{}", low) - } - - Self::GenericLowered(low ) => { - format!("{}", low) - }, - - Self::Pointer(arr, inner) => { - let a; - - if *arr { - a = "[]" - } else { - a = "" - } - - format!("{}*{}", inner, a) - }, - - Self::Reference(inner) => { - format!("{}&", inner) - } - }; - - write!(f, "{}", s) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Array(size, inner) => { + format!("{}[{}]", inner, size) + } + + Self::Generic(low, _, _) => { + format!("{}", low) + } + + Self::GenericLowered(low) => { + format!("{}", low) + } + + Self::Pointer(arr, inner) => { + let a; + + if *arr { + a = "[]" + } else { + a = "" + } + + format!("{}*{}", inner, a) + } + + Self::Reference(inner) => { + format!("{}&", inner) + } + }; + + write!(f, "{}", s) + } } impl SizedType for Type { - fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypeStorage) -> usize { - return match self { - Self::Array(size, inner) => inner.clone().get_size(t, compacted_size, storage) * *size, - Self::Pointer(_, _) => get_pointer_size(), - Self::Reference(_) => get_pointer_size(), - Self::Generic(e, _, _) => e.get_size(t, compacted_size, storage), - Self::GenericLowered(e) => e.get_size(t, compacted_size, storage) - } - } -} \ No newline at end of file + fn get_size(&self, t: &Type, compacted_size: bool, storage: &TypedGlobalScope) -> usize { + return match self { + Self::Array(size, inner) => inner.clone().get_size(t, compacted_size, storage) * *size, + Self::Pointer(_, _) => get_pointer_size(), + Self::Reference(_) => get_pointer_size(), + Self::Generic(e, _, _) => e.get_size(t, compacted_size, storage), + Self::GenericLowered(e) => e.get_size(t, compacted_size, storage), + }; + } +} diff --git a/compiler/compiler_typing/src/utils.rs b/compiler/compiler_typing/src/utils.rs index 21b59f8..b66a595 100644 --- a/compiler/compiler_typing/src/utils.rs +++ b/compiler/compiler_typing/src/utils.rs @@ -2,11 +2,11 @@ /// Determines the size of a pointer / memory addressess based on the current platform. pub fn get_pointer_size() -> usize { - if cfg!(target_pointer_width = "32") { - return 32; - } else if cfg!(target_pointer_width = "64") { - return 64; - } else { - return 0; - } -} \ No newline at end of file + if cfg!(target_pointer_width = "32") { + return 32; + } else if cfg!(target_pointer_width = "64") { + return 64; + } else { + return 0; + } +} diff --git a/compiler/compiler_utils/src/hash.rs b/compiler/compiler_utils/src/hash.rs index 71c782f..1b05c58 100644 --- a/compiler/compiler_utils/src/hash.rs +++ b/compiler/compiler_utils/src/hash.rs @@ -1,65 +1,68 @@ //! //! Hash related utilities -//! +//! -use std::{hash::{Hash}}; +use std::hash::Hash; pub type TypeHash = u64; #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct HashedString { - pub val: String, - pub hash: u64 + pub val: String, + pub hash: u64, } impl HashedString { - pub fn new(val: String) -> Self { - HashedString { val: val.clone(), hash: fnv_1ahash_str(val) } - } + pub fn new(val: String) -> Self { + HashedString { + val: val.clone(), + hash: fnv_1ahash_str(val), + } + } } #[derive(Eq, Clone, PartialEq, Debug)] pub struct SelfHash { - pub hash: u64 + pub hash: u64, } impl Hash for SelfHash { - fn hash(&self, state: &mut H) { - state.write_u64(self.hash); - } + fn hash(&self, state: &mut H) { + state.write_u64(self.hash); + } } pub const fn fnv_1ahash(to_hash: &str) -> u64 { - let mut hash: u64 = 14695981039346656037; - let bytes = to_hash.as_bytes(); - let mut i = 0; + let mut hash: u64 = 14695981039346656037; + let bytes = to_hash.as_bytes(); + let mut i = 0; - while i < bytes.len() { - hash ^= bytes[i] as u64; - hash = hash.wrapping_mul(1099511628211); - i += 1; - } + while i < bytes.len() { + hash ^= bytes[i] as u64; + hash = hash.wrapping_mul(1099511628211); + i += 1; + } - return hash; -} + return hash; +} pub fn fnv_1ahash_str(to_hash: String) -> u64 { - let mut hash: u64 = 14695981039346656037; - let bytes = to_hash.as_bytes(); - let mut i = 0; + let mut hash: u64 = 14695981039346656037; + let bytes = to_hash.as_bytes(); + let mut i = 0; - while i < bytes.len() { - hash ^= bytes[i] as u64; - hash = hash.wrapping_mul(1099511628211); - i += 1; - } + while i < bytes.len() { + hash ^= bytes[i] as u64; + hash = hash.wrapping_mul(1099511628211); + i += 1; + } - return hash; -} + return hash; +} #[macro_export] macro_rules! hash { - ($expr:expr) => { - compiler_utils::hash::fnv_1ahash($expr) - }; -} \ No newline at end of file + ($expr:expr) => { + compiler_utils::hash::fnv_1ahash($expr) + }; +} diff --git a/compiler/compiler_utils/src/lib.rs b/compiler/compiler_utils/src/lib.rs index 976aa53..5b4ee33 100644 --- a/compiler/compiler_utils/src/lib.rs +++ b/compiler/compiler_utils/src/lib.rs @@ -1,41 +1,45 @@ use core::fmt; use std::{fs, io::Error}; -pub mod utils; pub mod hash; pub mod operators; +pub mod utils; #[derive(Debug, Clone, PartialEq)] pub struct Position { - pub line: usize, - pub col: usize, - pub file_path: String + pub line: usize, + pub col: usize, + pub file_path: String, } impl Position { - pub fn get_line_content(&self) -> Result { - let contents = fs::read_to_string(&self.file_path)?; + pub fn get_line_content(&self) -> Result { + let contents = fs::read_to_string(&self.file_path)?; - let spl: Vec<&str> = contents.split('\n').collect(); + let spl: Vec<&str> = contents.split('\n').collect(); - return Ok(String::from(spl[self.line - 1])); - } + return Ok(String::from(spl[self.line - 1])); + } } impl Position { - pub fn new(path: String, line: usize, col: usize) -> Self { - return Position { line, col, file_path: path }; - } - - pub fn increment_by(&self, count: usize) -> Self { - return Position::new(self.file_path.clone(), self.line, self.col + count); - } + pub fn new(path: String, line: usize, col: usize) -> Self { + return Position { + line, + col, + file_path: path, + }; + } + + pub fn increment_by(&self, count: usize) -> Self { + return Position::new(self.file_path.clone(), self.line, self.col + count); + } } impl fmt::Display for Position { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let _ = write!(f, "{}:{}:{}", self.file_path, self.line, self.col); + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let _ = write!(f, "{}:{}:{}", self.file_path, self.line, self.col); - Ok(()) - } -} \ No newline at end of file + Ok(()) + } +} diff --git a/compiler/compiler_utils/src/operators.rs b/compiler/compiler_utils/src/operators.rs index 4a3a4a3..92e6013 100644 --- a/compiler/compiler_utils/src/operators.rs +++ b/compiler/compiler_utils/src/operators.rs @@ -3,30 +3,30 @@ /// The different math operator types #[derive(Debug, PartialEq, Clone)] pub enum MathOperatorType { - Add, - Subtract, - Multiply, - Divide, - ShiftLeft, - ShiftRight, - Modulo + Add, + Subtract, + Multiply, + Divide, + ShiftLeft, + ShiftRight, + Modulo, } /// Represents an actual math operator #[derive(Debug, PartialEq, Clone)] pub struct MathOperator { - pub operator: MathOperatorType, - pub assigns: bool, - pub fast: bool + pub operator: MathOperatorType, + pub assigns: bool, + pub fast: bool, } /// The different comparing operators #[derive(Debug, PartialEq, Clone)] pub enum ComparingOperator { - Equal, // A == B - NotEqual, // A != B - Higher, // A > B - HigherEqual, // A >= B - Lower, // A < B - LowerEqual // A <= B + Equal, // A == B + NotEqual, // A != B + Higher, // A > B + HigherEqual, // A >= B + Lower, // A < B + LowerEqual, // A <= B } diff --git a/compiler/compiler_utils/src/utils/indexed.rs b/compiler/compiler_utils/src/utils/indexed.rs index fcd77ba..e12dfb3 100644 --- a/compiler/compiler_utils/src/utils/indexed.rs +++ b/compiler/compiler_utils/src/utils/indexed.rs @@ -4,35 +4,36 @@ use std::collections::HashMap; #[derive(Clone, Debug, PartialEq, Eq)] pub struct IndexStorage { - pub hash_to_ind: HashMap, - pub entry_keys: Vec, - pub vals: Vec + pub hash_to_ind: HashMap, + pub entry_keys: Vec, + pub vals: Vec, } impl IndexStorage { - pub fn new() -> Self { - return IndexStorage { hash_to_ind: HashMap::new(), vals: vec![], entry_keys: vec![] } - } + pub fn new() -> Self { + return IndexStorage { + hash_to_ind: HashMap::new(), + vals: vec![], + entry_keys: vec![], + }; + } - pub fn append(&mut self, hash: u64, v: K) -> usize { - let ind = self.vals.len(); + pub fn append(&mut self, hash: u64, v: K) -> usize { + let ind = self.vals.len(); - self.entry_keys.push(hash); + self.entry_keys.push(hash); - self.hash_to_ind.insert(hash, ind); - self.vals.push(v); + self.hash_to_ind.insert(hash, ind); + self.vals.push(v); - return ind; - } + return ind; + } - pub fn get_index(&self, hash: u64) -> Option { - return self.hash_to_ind.get(&hash).copied(); - } + pub fn get_index(&self, hash: u64) -> Option { + return self.hash_to_ind.get(&hash).copied(); + } - pub fn get_ind(&self, ind: usize) -> &K { - return &self.vals[ind]; - } - - - -} \ No newline at end of file + pub fn get_ind(&self, ind: usize) -> &K { + return &self.vals[ind]; + } +} diff --git a/compiler/compiler_utils/src/utils/map.rs b/compiler/compiler_utils/src/utils/map.rs index 0b3cf56..37d3a6c 100644 --- a/compiler/compiler_utils/src/utils/map.rs +++ b/compiler/compiler_utils/src/utils/map.rs @@ -9,36 +9,41 @@ const MAP_LOAD_FACTOR: f64 = 0.85; #[derive(Debug)] pub struct HashedMap { - meta: Vec, - buckets: Vec>, - capacity: usize, - load: usize + meta: Vec, + buckets: Vec>, + capacity: usize, + load: usize, } impl HashedMap { - pub fn new(capacity: usize) -> Self { - let mut cap: usize = capacity; + pub fn new(capacity: usize) -> Self { + let mut cap: usize = capacity; - if !cap.is_power_of_two() { - cap = cap.next_power_of_two(); - } + if !cap.is_power_of_two() { + cap = cap.next_power_of_two(); + } - let mut buckets: Vec> = Vec::with_capacity(cap); + let mut buckets: Vec> = Vec::with_capacity(cap); - let meta: Vec = vec![BUCKET_EMPTY; cap]; + let meta: Vec = vec![BUCKET_EMPTY; cap]; - unsafe { + unsafe { buckets.set_len(cap); } - return HashedMap { meta , buckets, capacity: cap, load: 0 } - } + return HashedMap { + meta, + buckets, + capacity: cap, + load: 0, + }; + } - pub fn put(&mut self, key: u64, val: V) { - let index = self.index_from_hash(key); - let fingerprint = self.fingerprint_from_hash(key); + pub fn put(&mut self, key: u64, val: V) { + let index = self.index_from_hash(key); + let fingerprint = self.fingerprint_from_hash(key); - let mut insertion: Option = None; + let mut insertion: Option = None; for i in index..self.capacity { let meta: u8 = self.meta[i]; @@ -50,7 +55,7 @@ impl HashedMap { insertion = Some(i); break; - }, + } _ => { if meta != fingerprint { @@ -65,7 +70,7 @@ impl HashedMap { } } } - } + } if insertion.is_some() { let target: usize = insertion.unwrap(); @@ -86,23 +91,23 @@ impl HashedMap { if self.check_for_map_load() { self.change_capacity((self.capacity + 1).next_power_of_two()); - // We didn't find a bucket yet. We increment the capacity. - + // We didn't find a bucket yet. We increment the capacity. + // Since new capacity > old capacity. We can simply claim the old capacity + 1 bucket as ours - + self.put(key, val); } - } + } - pub fn get(&self, key: u64) -> Option<&V> { - let index = self.index_from_hash(key); + pub fn get(&self, key: u64) -> Option<&V> { + let index = self.index_from_hash(key); let fingerprint = self.fingerprint_from_hash(key); for i in index..self.capacity { if self.meta[i] == fingerprint { unsafe { let bucket: &(u64, V) = self.buckets[i].assume_init_ref(); - + if bucket.0 == key { return Some(&bucket.1); } @@ -111,24 +116,25 @@ impl HashedMap { } return None; - } + } - pub fn entries(&self) -> Vec<&(u64, V)> { - let mut vec = Vec::new(); + pub fn entries(&self) -> Vec<&(u64, V)> { + let mut vec = Vec::new(); - for i in 0..self.capacity { - if self.meta[i] == BUCKET_EMPTY || self.meta[i] == BUCKET_TOMBSTONE { - continue; - } + for i in 0..self.capacity { + if self.meta[i] == BUCKET_EMPTY || self.meta[i] == BUCKET_TOMBSTONE { + continue; + } - unsafe { vec.push(self.buckets[i].assume_init_ref()); } - } - - return vec; - } + unsafe { + vec.push(self.buckets[i].assume_init_ref()); + } + } + return vec; + } - pub fn erase(&mut self, key: u64) { + pub fn erase(&mut self, key: u64) { let index = self.index_from_hash(key); let fingerprint = self.fingerprint_from_hash(key); @@ -147,7 +153,7 @@ impl HashedMap { } } - fn check_for_map_load(&self) -> bool { + fn check_for_map_load(&self) -> bool { let curr_load = (self.load / self.capacity) as f64; return curr_load >= MAP_LOAD_FACTOR; @@ -159,7 +165,7 @@ impl HashedMap { } let mut temp: HashedMap = HashedMap::new(new_capacity); - + for i in 0..self.capacity { if self.meta[i] != BUCKET_EMPTY && self.meta[i] != BUCKET_TOMBSTONE { unsafe { @@ -171,7 +177,7 @@ impl HashedMap { temp.put(key, val); } } - + // Append bucket to temp } @@ -179,8 +185,6 @@ impl HashedMap { self.meta = temp.meta; self.capacity = temp.capacity; } - - } impl HashedMap { @@ -191,4 +195,4 @@ impl HashedMap { fn fingerprint_from_hash(&self, hash: u64) -> u8 { (hash >> 57) as u8 // Get the 7 least significant bits } -} \ No newline at end of file +} diff --git a/compiler/compiler_utils/src/utils/mod.rs b/compiler/compiler_utils/src/utils/mod.rs index 500258f..dc9fcdb 100644 --- a/compiler/compiler_utils/src/utils/mod.rs +++ b/compiler/compiler_utils/src/utils/mod.rs @@ -1,3 +1,3 @@ +pub mod indexed; pub mod map; pub mod num; -pub mod indexed; \ No newline at end of file diff --git a/compiler/compiler_utils/src/utils/num.rs b/compiler/compiler_utils/src/utils/num.rs index 1eb3923..ece0cbe 100644 --- a/compiler/compiler_utils/src/utils/num.rs +++ b/compiler/compiler_utils/src/utils/num.rs @@ -1,27 +1,27 @@ pub fn get_signed_highbound(bits: usize) -> i128 { - return 2_i128.pow(bits as u32 - 1) - 1; + return 2_i128.pow(bits as u32 - 1) - 1; } pub fn get_signed_lowbound(bits: usize) -> i128 { - return 0 - 2_i128.pow(bits as u32 - 1) - 1; + return 0 - 2_i128.pow(bits as u32 - 1) - 1; } pub fn get_unsigned_highbound(bits: usize) -> i128 { - return 2_i128.pow(bits as u32) - 1; + return 2_i128.pow(bits as u32) - 1; } pub fn can_num_fit_inbits_signed(bits: usize, num: i128) -> bool { - return num >= get_signed_lowbound(bits) && num <= get_signed_highbound(bits); + return num >= get_signed_lowbound(bits) && num <= get_signed_highbound(bits); } pub fn can_num_fit_inbits_unsigned(bits: usize, num: i128) -> bool { - return num >= 0 && num <= get_unsigned_highbound(bits); + return num >= 0 && num <= get_unsigned_highbound(bits); } pub fn can_fit_in_integer(num: i128, bits: usize, signed: bool) -> bool { - if signed { - return can_num_fit_inbits_signed(bits, num); - } + if signed { + return can_num_fit_inbits_signed(bits, num); + } - return can_num_fit_inbits_unsigned(bits, num); -} \ No newline at end of file + return can_num_fit_inbits_unsigned(bits, num); +} diff --git a/compiler/diagnostics/src/builders.rs b/compiler/diagnostics/src/builders.rs index 956fa2d..e3b3006 100644 --- a/compiler/diagnostics/src/builders.rs +++ b/compiler/diagnostics/src/builders.rs @@ -1,195 +1,626 @@ -use std::{fmt::Display}; - -use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, CANNOT_FIND, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, NOT_FOUND_USE, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; - -pub fn make_expected_simple_error(origin: &K, expected: &E, got: &G) -> Diagnostic { - origin.make_simple_diagnostic(EXPECTED_TOKEN.0, Level::Error, format!("expected {} but got {}", expected, got), None, vec![], vec![], vec![]) -} - -pub fn make_unexpected_simple_error(origin: &K, got: &E) -> Diagnostic { - origin.make_simple_diagnostic(UNEXPECTED_TOKEN.0, Level::Error, format!("unexpected {}", got), None, vec![], vec![], vec![]) +use std::fmt::Display; + +use crate::{ + DiagnosticSpanOrigin, + diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, + errors::{ + ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, CANNOT_FIND, DIFF_SIZE_SPECIFIERS, + DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, + EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, + FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, + INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, NOT_FOUND_USE, + TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT, + }, + get_current_diagnostic_pos, + warnings::UNUSED_VAR, +}; + +pub fn make_expected_simple_error( + origin: &K, + expected: &E, + got: &G, +) -> Diagnostic { + origin.make_simple_diagnostic( + EXPECTED_TOKEN.0, + Level::Error, + format!("expected {} but got {}", expected, got), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_unexpected_simple_error( + origin: &K, + got: &E, +) -> Diagnostic { + origin.make_simple_diagnostic( + UNEXPECTED_TOKEN.0, + Level::Error, + format!("unexpected {}", got), + None, + vec![], + vec![], + vec![], + ) } pub fn make_unexpected_simple_error_outside(got: &K, pos: SpanPosition) -> Diagnostic { - let span = Span::make_primary(pos, None); - - Diagnostic::new_base(Level::Error, EXPECTED_TOKEN.0, format!("unexpected {}", got), span, vec![], vec![], vec![]) -} - -pub fn make_expected_single_simple_error(origin: &K, got: &E) -> Diagnostic { - origin.make_simple_diagnostic(EXPECTED_FREE.0, Level::Error, format!("expected {}", got), None, vec![], vec![], vec![]) -} - -pub fn make_unused_variable(origin: &K, var: &E) -> Diagnostic { - origin.make_simple_diagnostic(UNUSED_VAR.0, Level::Warning, format!("unused variable {}", var), None, vec![], vec![], vec![]) -} - -pub fn make_already_in_scope(origin: &K, val: &E) -> Diagnostic { - origin.make_simple_diagnostic(ALREADY_IN_SCOPE.0, Level::Error, format!("{} was already found in this scope", val), None, vec![], vec![], vec![]) -} - -pub fn make_cannot_find_var(origin: &K, var: &V) -> Diagnostic { - origin.make_simple_diagnostic(FIND_VAR.0, Level::Error, format!("cannot find variable {} in the current context", var), None, vec![], vec![], vec![]) + let span = Span::make_primary(pos, None); + + Diagnostic::new_base( + Level::Error, + EXPECTED_TOKEN.0, + format!("unexpected {}", got), + span, + vec![], + vec![], + vec![], + ) +} + +pub fn make_expected_single_simple_error( + origin: &K, + got: &E, +) -> Diagnostic { + origin.make_simple_diagnostic( + EXPECTED_FREE.0, + Level::Error, + format!("expected {}", got), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_unused_variable( + origin: &K, + var: &E, +) -> Diagnostic { + origin.make_simple_diagnostic( + UNUSED_VAR.0, + Level::Warning, + format!("unused variable {}", var), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_already_in_scope( + origin: &K, + val: &E, +) -> Diagnostic { + origin.make_simple_diagnostic( + ALREADY_IN_SCOPE.0, + Level::Error, + format!("{} was already found in this scope", val), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_cannot_find_var( + origin: &K, + var: &V, +) -> Diagnostic { + origin.make_simple_diagnostic( + FIND_VAR.0, + Level::Error, + format!("cannot find variable {} in the current context", var), + None, + vec![], + vec![], + vec![], + ) } pub fn make_cannot_find_type(origin: &K, t: &E) -> Diagnostic { - origin.make_simple_diagnostic(FIND_TYPE.0, Level::Error, format!("cannot find type {} in the current scope", t), None, vec![], vec![], vec![]) -} - -pub fn make_cannot_find_func(origin: &K, func: &E) -> Diagnostic { - origin.make_simple_diagnostic(FIND_TYPE.0, Level::Error, format!("cannot find function {} in the current scope", func), None, vec![], vec![], vec![]) + origin.make_simple_diagnostic( + FIND_TYPE.0, + Level::Error, + format!("cannot find type {} in the current scope", t), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_cannot_find_func( + origin: &K, + func: &E, +) -> Diagnostic { + origin.make_simple_diagnostic( + FIND_TYPE.0, + Level::Error, + format!("cannot find function {} in the current scope", func), + None, + vec![], + vec![], + vec![], + ) } pub fn make_cannot_find_type_pos(t: &E) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), None); + let primary_span = Span::make_primary(get_current_diagnostic_pos(), None); - return Diagnostic::new_base(Level::Error, FIND_TYPE.0, format!("cannot find type {} in the current scope", t), primary_span, vec![], vec![], vec![]) -} + return Diagnostic::new_base( + Level::Error, + FIND_TYPE.0, + format!("cannot find type {} in the current scope", t), + primary_span, + vec![], + vec![], + vec![], + ); +} #[must_use = "Must set the diagnostic position beforehand"] pub fn make_cannot_find_type_function(func: &F, t: &T) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), Some(format!("function {} required here", func))); - - return Diagnostic::new_base(Level::Error, FIND_TYPE_FUNCTION.0, format!("cannot find function {} in type {}", func, t), primary_span, vec![], vec![], vec![]) + let primary_span = Span::make_primary( + get_current_diagnostic_pos(), + Some(format!("function {} required here", func)), + ); + + return Diagnostic::new_base( + Level::Error, + FIND_TYPE_FUNCTION.0, + format!("cannot find function {} in type {}", func, t), + primary_span, + vec![], + vec![], + vec![], + ); } #[must_use = "Must set the diagnostic position beforehand"] pub fn make_cannot_find_type_field(field: &F, t: &T) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), Some(format!("field {} required here", field))); - - return Diagnostic::new_base(Level::Error, FIND_TYPE_FIELD.0, format!("cannot find field {} in type {}", field, t), primary_span, vec![], vec![], vec![]) -} - -pub fn make_diff_size_specifiers(origin: &K, a: &A, b: &B) -> Diagnostic { - origin.make_simple_diagnostic(DIFF_SIZE_SPECIFIERS.0, Level::Error, format!("expected {} size specifiers on this type, got {}", b, a), None, vec![], vec![], vec![]) -} - -pub fn make_diff_type_specifiers(origin: &K, a: &A, b: &B) -> Diagnostic { - origin.make_simple_diagnostic(DIFF_TYPE_SPECIFIERS.0, Level::Error, format!("expected {} type specifiers on this type, got {}", b, a), None, vec![], vec![], vec![]) -} - -pub fn make_diff_type(origin: &K, var_name: &V, req_type: &T, got: &A, var_origin: &K) -> Diagnostic { - let decl_span = var_origin.make_span(SpanKind::Secondary, Some(format!("variable {} was declared here", var_name))); - origin.make_simple_diagnostic(EXPECTED_TYPE.0, Level::Error, format!("expected {} but got {}", req_type, got), Some(format!("variable {} tried having a {} value here", var_name, req_type)), vec![decl_span], vec![], vec![]) -} - -pub fn make_diff_type_val(origin: &K, req_type: &T, got: &A) -> Diagnostic { - origin.make_simple_diagnostic(EXPECTED_TYPE.0, Level::Error, format!("expected {} but got {}", req_type, got), None, vec![], vec![], vec![]) + let primary_span = Span::make_primary( + get_current_diagnostic_pos(), + Some(format!("field {} required here", field)), + ); + + return Diagnostic::new_base( + Level::Error, + FIND_TYPE_FIELD.0, + format!("cannot find field {} in type {}", field, t), + primary_span, + vec![], + vec![], + vec![], + ); +} + +pub fn make_diff_size_specifiers( + origin: &K, + a: &A, + b: &B, +) -> Diagnostic { + origin.make_simple_diagnostic( + DIFF_SIZE_SPECIFIERS.0, + Level::Error, + format!("expected {} size specifiers on this type, got {}", b, a), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_diff_type_specifiers( + origin: &K, + a: &A, + b: &B, +) -> Diagnostic { + origin.make_simple_diagnostic( + DIFF_TYPE_SPECIFIERS.0, + Level::Error, + format!("expected {} type specifiers on this type, got {}", b, a), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_diff_type( + origin: &K, + var_name: &V, + req_type: &T, + got: &A, + var_origin: &K, +) -> Diagnostic { + let decl_span = var_origin.make_span( + SpanKind::Secondary, + Some(format!("variable {} was declared here", var_name)), + ); + origin.make_simple_diagnostic( + EXPECTED_TYPE.0, + Level::Error, + format!("expected {} but got {}", req_type, got), + Some(format!( + "variable {} tried having a {} value here", + var_name, req_type + )), + vec![decl_span], + vec![], + vec![], + ) +} + +pub fn make_diff_type_val( + origin: &K, + req_type: &T, + got: &A, +) -> Diagnostic { + origin.make_simple_diagnostic( + EXPECTED_TYPE.0, + Level::Error, + format!("expected {} but got {}", req_type, got), + None, + vec![], + vec![], + vec![], + ) } - #[must_use = "Must set the diagnostic position beforehand"] -pub fn make_bound_fail_function(bound: &B, target_t: &T, func: &F, arg_count: usize) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), Some(format!("bound {} required for type {} here", bound, target_t))); - - let notes = vec![format!("function {} declared in bound doesn't match signature!", func)]; - let help = vec![format!("argument type for argument #{} is invalid!", arg_count)]; - - return Diagnostic::new_base(Level::Error, BOUND_MISSING.0, format!("bound {} cannot be applied onto {}", bound, target_t), primary_span, vec![], notes, help) +pub fn make_bound_fail_function( + bound: &B, + target_t: &T, + func: &F, + arg_count: usize, +) -> Diagnostic { + let primary_span = Span::make_primary( + get_current_diagnostic_pos(), + Some(format!( + "bound {} required for type {} here", + bound, target_t + )), + ); + + let notes = vec![format!( + "function {} declared in bound doesn't match signature!", + func + )]; + let help = vec![format!( + "argument type for argument #{} is invalid!", + arg_count + )]; + + return Diagnostic::new_base( + Level::Error, + BOUND_MISSING.0, + format!("bound {} cannot be applied onto {}", bound, target_t), + primary_span, + vec![], + notes, + help, + ); } #[must_use = "Must set the diagnostic position beforehand"] -pub fn make_bound_fail_field(bound: &B, target_t: &T, field: &F, expected: &E, got: &G) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), Some(format!("bound {} required for type {} here", bound, target_t))); - - let notes = vec![format!("field {} declared in bound requires type {} but got {}", field, expected, got)]; - let help = vec![format!("replace the field type with {}", expected)]; - - return Diagnostic::new_base(Level::Error, BOUND_MISSING.0, format!("bound {} cannot be applied onto {}", bound, target_t), primary_span, vec![], notes, help) +pub fn make_bound_fail_field( + bound: &B, + target_t: &T, + field: &F, + expected: &E, + got: &G, +) -> Diagnostic { + let primary_span = Span::make_primary( + get_current_diagnostic_pos(), + Some(format!( + "bound {} required for type {} here", + bound, target_t + )), + ); + + let notes = vec![format!( + "field {} declared in bound requires type {} but got {}", + field, expected, got + )]; + let help = vec![format!("replace the field type with {}", expected)]; + + return Diagnostic::new_base( + Level::Error, + BOUND_MISSING.0, + format!("bound {} cannot be applied onto {}", bound, target_t), + primary_span, + vec![], + notes, + help, + ); } #[must_use = "Must set the diagnostic position beforehand"] pub fn make_bound_trait(bound_trait: &B, t: &T) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), Some(format!("trait {} required for type {} here", bound_trait, t))); - - let notes = vec![format!("type {} doesn't support the bound trait {}", t, bound_trait)]; - let help = vec![format!("replace type {} with a type that supports {}", t, bound_trait)]; - - return Diagnostic::new_base(Level::Error, TRAIT_MISSING.0, format!("bound trait {} cannot be applied onto {}", bound_trait, t), primary_span, vec![], notes, help) + let primary_span = Span::make_primary( + get_current_diagnostic_pos(), + Some(format!( + "trait {} required for type {} here", + bound_trait, t + )), + ); + + let notes = vec![format!( + "type {} doesn't support the bound trait {}", + t, bound_trait + )]; + let help = vec![format!( + "replace type {} with a type that supports {}", + t, bound_trait + )]; + + return Diagnostic::new_base( + Level::Error, + TRAIT_MISSING.0, + format!("bound trait {} cannot be applied onto {}", bound_trait, t), + primary_span, + vec![], + notes, + help, + ); } #[must_use = "Must set the diagnostic position beforehand"] pub fn make_enum_parent_fields() -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), None); + let primary_span = Span::make_primary(get_current_diagnostic_pos(), None); - let notes = vec!["enum fields are only allowed in enum children".to_string()]; - let help = vec!["move the fields into an enum child".to_string()]; + let notes = vec!["enum fields are only allowed in enum children".to_string()]; + let help = vec!["move the fields into an enum child".to_string()]; - return Diagnostic::new_base(Level::Error, ENUM_PARENT_FIELDS.0, ENUM_PARENT_FIELDS.1.to_string(), primary_span, vec![], notes, help) + return Diagnostic::new_base( + Level::Error, + ENUM_PARENT_FIELDS.0, + ENUM_PARENT_FIELDS.1.to_string(), + primary_span, + vec![], + notes, + help, + ); } #[must_use = "Must set the diagnostic position beforehand"] pub fn make_unsure_panic(msg: &M) -> Diagnostic { - let primary_span = Span::make_primary(get_current_diagnostic_pos(), Some("panic happened here".to_string())); - - return Diagnostic::new_base(Level::Error, 99, format!("unsure panic: {}", msg), primary_span, vec![], vec!["Report this at https://github.com/Quickfall/quickfall".to_string()], vec!["create a bug report".to_string()]) + let primary_span = Span::make_primary( + get_current_diagnostic_pos(), + Some("panic happened here".to_string()), + ); + + return Diagnostic::new_base( + Level::Error, + 99, + format!("unsure panic: {}", msg), + primary_span, + vec![], + vec!["Report this at https://github.com/Quickfall/quickfall".to_string()], + vec!["create a bug report".to_string()], + ); } pub fn make_index_usage(origin: &K, ty: &T) -> Diagnostic { - return origin.make_simple_diagnostic(INDEX_USAGE.0, Level::Error, INDEX_USAGE.1.to_string(), Some(format!("index access used on type {} here", ty)), vec![], vec![], vec![]) -} - -pub fn make_struct_init_missing_field(origin: &K, ty: &T, field: &F) -> Diagnostic { - let notes = vec!["a struct initializer must contain all fields on the struct type".to_string()]; - let help = vec![format!("add the {} field in the initializer", field)]; - - return origin.make_simple_diagnostic(FIELD_STRUCT_INIT.0, Level::Error, format!("field {} of type {} is missing in the initializer", field, ty), None, vec![], notes, help) -} - -pub fn make_struct_missing_field(origin: &K, ty: &T, field: &F) -> Diagnostic { - return origin.make_simple_diagnostic(FIELD_MISSING.0, Level::Error, format!("field {} was not found in type {}", field, ty), None, vec![], vec![], vec![]) -} - -pub fn make_struct_missing_func(origin: &K, ty: &T, func: &F) -> Diagnostic { - return origin.make_simple_diagnostic(FUNC_MISSING.0, Level::Error, format!("func {} was not found in type {}", func, ty), None, vec![], vec![], vec![]) -} - -pub fn make_doesnt_exist_in_era(origin: &K, val: &V) -> Diagnostic { - return origin.make_simple_diagnostic(ERA_NOT_EXIST.0, Level::Error, format!("{} doesn't exist in this era", val), None, vec![], vec![], vec![]) + return origin.make_simple_diagnostic( + INDEX_USAGE.0, + Level::Error, + INDEX_USAGE.1.to_string(), + Some(format!("index access used on type {} here", ty)), + vec![], + vec![], + vec![], + ); +} + +pub fn make_struct_init_missing_field( + origin: &K, + ty: &T, + field: &F, +) -> Diagnostic { + let notes = vec!["a struct initializer must contain all fields on the struct type".to_string()]; + let help = vec![format!("add the {} field in the initializer", field)]; + + return origin.make_simple_diagnostic( + FIELD_STRUCT_INIT.0, + Level::Error, + format!( + "field {} of type {} is missing in the initializer", + field, ty + ), + None, + vec![], + notes, + help, + ); +} + +pub fn make_struct_missing_field( + origin: &K, + ty: &T, + field: &F, +) -> Diagnostic { + return origin.make_simple_diagnostic( + FIELD_MISSING.0, + Level::Error, + format!("field {} was not found in type {}", field, ty), + None, + vec![], + vec![], + vec![], + ); +} + +pub fn make_struct_missing_func( + origin: &K, + ty: &T, + func: &F, +) -> Diagnostic { + return origin.make_simple_diagnostic( + FUNC_MISSING.0, + Level::Error, + format!("func {} was not found in type {}", func, ty), + None, + vec![], + vec![], + vec![], + ); +} + +pub fn make_doesnt_exist_in_era( + origin: &K, + val: &V, +) -> Diagnostic { + return origin.make_simple_diagnostic( + ERA_NOT_EXIST.0, + Level::Error, + format!("{} doesn't exist in this era", val), + None, + vec![], + vec![], + vec![], + ); } pub fn make_invalid_pointing(origin: &K) -> Diagnostic { - origin.make_simple_diagnostic(INVALID_POINTING.0, Level::Error, INVALID_POINTING.1.to_string(), None, vec![], vec![], vec![]) -} - -pub fn make_variable_uninit(origin: &K, var: &V) -> Diagnostic { - origin.make_simple_diagnostic(VARIABLE_UNINIT.0, Level::Error, format!("variable {} must be initialized every usage", var), Some("variable not initialized here".to_string()), vec![], vec![], vec![]) + origin.make_simple_diagnostic( + INVALID_POINTING.0, + Level::Error, + INVALID_POINTING.1.to_string(), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_variable_uninit( + origin: &K, + var: &V, +) -> Diagnostic { + origin.make_simple_diagnostic( + VARIABLE_UNINIT.0, + Level::Error, + format!("variable {} must be initialized every usage", var), + Some("variable not initialized here".to_string()), + vec![], + vec![], + vec![], + ) } pub fn make_invalid_var_type_ir() -> Diagnostic { - let span = Span::make_primary(get_current_diagnostic_pos(), None); + let span = Span::make_primary(get_current_diagnostic_pos(), None); - Diagnostic::new_base(Level::Error, IR_CAST.0, IR_CAST.1.to_string(), span, vec![], vec![], vec![]) + Diagnostic::new_base( + Level::Error, + IR_CAST.0, + IR_CAST.1.to_string(), + span, + vec![], + vec![], + vec![], + ) } pub fn make_invalid_assign_diff_type_ir() -> Diagnostic { - let span = Span::make_primary(get_current_diagnostic_pos(), None); + let span = Span::make_primary(get_current_diagnostic_pos(), None); - Diagnostic::new_base(Level::Error, ASSIGN_DIFF_TYPE_IR.0, ASSIGN_DIFF_TYPE_IR.1.to_string(), span, vec![], vec![], vec![]) + Diagnostic::new_base( + Level::Error, + ASSIGN_DIFF_TYPE_IR.0, + ASSIGN_DIFF_TYPE_IR.1.to_string(), + span, + vec![], + vec![], + vec![], + ) } pub fn make_invalid_instruction_held_val() -> Diagnostic { - let span = Span::make_primary(get_current_diagnostic_pos(), None); + let span = Span::make_primary(get_current_diagnostic_pos(), None); - Diagnostic::new_base(Level::Error, IR_INSTRUCTION_HELD_VAL.0, IR_INSTRUCTION_HELD_VAL.1.to_string(), span, vec![], vec![], vec![]) + Diagnostic::new_base( + Level::Error, + IR_INSTRUCTION_HELD_VAL.0, + IR_INSTRUCTION_HELD_VAL.1.to_string(), + span, + vec![], + vec![], + vec![], + ) } pub fn make_math_operation_req_assign(origin: &K) -> Diagnostic { - origin.make_simple_diagnostic(MATH_OPERATION_ASSIGNS.0, Level::Error, MATH_OPERATION_ASSIGNS.1.to_string(), None, vec![], vec![], vec![]) + origin.make_simple_diagnostic( + MATH_OPERATION_ASSIGNS.0, + Level::Error, + MATH_OPERATION_ASSIGNS.1.to_string(), + None, + vec![], + vec![], + vec![], + ) } pub fn make_req_type_kind(origin: &K, t: &T) -> Diagnostic { - origin.make_simple_diagnostic(INVALID_TYPE_REQ.0, Level::Error, format!("this operation requires a {} type", t), None, vec![], vec![], vec![]) -} - -pub fn make_type_not_partof(origin: &K, a: &A, b: &B) -> Diagnostic { - origin.make_simple_diagnostic(TYPE_NOT_PART.0, Level::Error, format!("type {} is not part of type {}", a, b), None, vec![], vec![], vec![]) + origin.make_simple_diagnostic( + INVALID_TYPE_REQ.0, + Level::Error, + format!("this operation requires a {} type", t), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_type_not_partof( + origin: &K, + a: &A, + b: &B, +) -> Diagnostic { + origin.make_simple_diagnostic( + TYPE_NOT_PART.0, + Level::Error, + format!("type {} is not part of type {}", a, b), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_use_not_found( + origin: &K, + element: &E, + path: &P, +) -> Diagnostic { + origin.make_simple_diagnostic( + NOT_FOUND_USE.0, + Level::Error, + format!("element {} was not found in {}", element, path), + None, + vec![], + vec![], + vec![], + ) +} + +pub fn make_cannot_find( + origin: &K, + element: &P, +) -> Diagnostic { + origin.make_simple_diagnostic( + CANNOT_FIND.0, + Level::Error, + format!("cannot find {} in the current scope", element), + None, + vec![], + vec![], + vec![], + ) } - -pub fn make_use_not_found(origin: &K, element: &E, path: &P) -> Diagnostic { - origin.make_simple_diagnostic(NOT_FOUND_USE.0, Level::Error, format!("element {} was not found in {}", element, path), None, vec![], vec![], vec![]) -} - -pub fn make_cannot_find(origin: &K, element: &P) -> Diagnostic { - origin.make_simple_diagnostic(CANNOT_FIND.0, Level::Error, format!("cannot find {} in the current scope", element), None, vec![], vec![], vec![]) -} \ No newline at end of file diff --git a/compiler/diagnostics/src/diagnostic.rs b/compiler/diagnostics/src/diagnostic.rs index ce8c98e..5629bb3 100644 --- a/compiler/diagnostics/src/diagnostic.rs +++ b/compiler/diagnostics/src/diagnostic.rs @@ -12,259 +12,365 @@ use crate::DIAGNOSTIC_CONTAINER; #[derive(Clone)] pub enum Level { - Error, - Warning, - Note + Error, + Warning, + Note, } #[derive(Clone)] pub enum SpanKind { - Primary, - Secondary + Primary, + Secondary, } impl SpanKind { - pub fn get_marker_char(&self) -> char { - match self { - Self::Primary => '^', - Self::Secondary => '-' - } - } + pub fn get_marker_char(&self) -> char { + match self { + Self::Primary => '^', + Self::Secondary => '-', + } + } } impl Level { - pub fn apply_color(&self, str: ColoredString) -> ColoredString { - match self { - Self::Error => str.bright_red().bold(), - Self::Warning => str.yellow().bold(), - Self::Note => str.blue().bold() - } - } - - pub fn get_code_char(&self) -> char { - match self { - Self::Error => 'E', - Self::Warning => 'W', - Self::Note => 'I' - } - } + pub fn apply_color(&self, str: ColoredString) -> ColoredString { + match self { + Self::Error => str.bright_red().bold(), + Self::Warning => str.yellow().bold(), + Self::Note => str.blue().bold(), + } + } + + pub fn get_code_char(&self) -> char { + match self { + Self::Error => 'E', + Self::Warning => 'W', + Self::Note => 'I', + } + } } impl Display for Level { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Error => write!(f, "error"), - Self::Warning => write!(f, "warning"), - Self::Note => writeln!(f, "info") - } - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::Error => write!(f, "error"), + Self::Warning => write!(f, "warning"), + Self::Note => writeln!(f, "info"), + } + } } pub struct Diagnostic { - pub level: Level, - pub code: usize, - pub message: String, + pub level: Level, + pub code: usize, + pub message: String, - pub primary_span: Span, - pub spans: Vec, + pub primary_span: Span, + pub spans: Vec, - pub note: Vec, - pub help: Vec, + pub note: Vec, + pub help: Vec, - #[cfg(feature = "compiler_diagbacktraces")] - pub backtrace: Backtrace + #[cfg(feature = "compiler_diagbacktraces")] + pub backtrace: Backtrace, } impl Clone for Diagnostic { - fn clone(&self) -> Self { - #[cfg(feature = "compiler_diagbacktraces")] - unsafe { std::env::set_var("RUST_BACKTRACE", "1"); } - - #[cfg(feature = "compiler_diagbacktraces")] - return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone(), backtrace: Backtrace::capture() }; - - - #[cfg(not(feature = "compiler_diagbacktraces"))] - return Diagnostic { level: self.level.clone(), code: self.code, message: self.message.clone(), primary_span: self.primary_span.clone(), spans: self.spans.clone(), note: self.note.clone(), help: self.help.clone() }; - } + fn clone(&self) -> Self { + #[cfg(feature = "compiler_diagbacktraces")] + unsafe { + std::env::set_var("RUST_BACKTRACE", "1"); + } + + #[cfg(feature = "compiler_diagbacktraces")] + return Diagnostic { + level: self.level.clone(), + code: self.code, + message: self.message.clone(), + primary_span: self.primary_span.clone(), + spans: self.spans.clone(), + note: self.note.clone(), + help: self.help.clone(), + backtrace: Backtrace::capture(), + }; + + #[cfg(not(feature = "compiler_diagbacktraces"))] + return Diagnostic { + level: self.level.clone(), + code: self.code, + message: self.message.clone(), + primary_span: self.primary_span.clone(), + spans: self.spans.clone(), + note: self.note.clone(), + help: self.help.clone(), + }; + } } impl Diagnostic { - pub fn new(level: Level, decl: (usize, &str), primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { - #[cfg(feature = "compiler_diagbacktraces")] - unsafe { std::env::set_var("RUST_BACKTRACE", "1"); } - - #[cfg(feature = "compiler_diagbacktraces")] - let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help, backtrace: Backtrace::capture() }; - - - #[cfg(not(feature = "compiler_diagbacktraces"))] - let d = Diagnostic { level, code: decl.0, message: decl.1.to_string(), primary_span, spans, note, help }; - - d.push_to_storage(); - - return d - } - - pub fn new_base(level: Level, code: usize, message: String, primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { - #[cfg(feature = "compiler_diagbacktraces")] - unsafe { std::env::set_var("RUST_BACKTRACE", "1"); } - - #[cfg(feature = "compiler_diagbacktraces")] - let d = Diagnostic { level, code, message, primary_span, spans, note, help, backtrace: Backtrace::capture() }; - - - #[cfg(not(feature = "compiler_diagbacktraces"))] - let d = Diagnostic { level, code, message, primary_span, spans, note, help }; - - d.push_to_storage(); - - return d - } - - fn push_to_storage(&self) { - DIAGNOSTIC_CONTAINER.with_borrow_mut(|f| { - f.append(self.clone()); - }) - } + pub fn new( + level: Level, + decl: (usize, &str), + primary_span: Span, + spans: Vec, + note: Vec, + help: Vec, + ) -> Self { + #[cfg(feature = "compiler_diagbacktraces")] + unsafe { + std::env::set_var("RUST_BACKTRACE", "1"); + } + + #[cfg(feature = "compiler_diagbacktraces")] + let d = Diagnostic { + level, + code: decl.0, + message: decl.1.to_string(), + primary_span, + spans, + note, + help, + backtrace: Backtrace::capture(), + }; + + #[cfg(not(feature = "compiler_diagbacktraces"))] + let d = Diagnostic { + level, + code: decl.0, + message: decl.1.to_string(), + primary_span, + spans, + note, + help, + }; + + d.push_to_storage(); + + return d; + } + + pub fn new_base( + level: Level, + code: usize, + message: String, + primary_span: Span, + spans: Vec, + note: Vec, + help: Vec, + ) -> Self { + #[cfg(feature = "compiler_diagbacktraces")] + unsafe { + std::env::set_var("RUST_BACKTRACE", "1"); + } + + #[cfg(feature = "compiler_diagbacktraces")] + let d = Diagnostic { + level, + code, + message, + primary_span, + spans, + note, + help, + backtrace: Backtrace::capture(), + }; + + #[cfg(not(feature = "compiler_diagbacktraces"))] + let d = Diagnostic { + level, + code, + message, + primary_span, + spans, + note, + help, + }; + + d.push_to_storage(); + + return d; + } + + fn push_to_storage(&self) { + DIAGNOSTIC_CONTAINER.with_borrow_mut(|f| { + f.append(self.clone()); + }) + } } impl Into<()> for Diagnostic { - fn into(self) -> () { - - } + fn into(self) -> () {} } #[derive(Clone)] pub struct SpanPosition { - pub line: usize, - pub col: usize, - pub file_path: String, - pub end_col: usize + pub line: usize, + pub col: usize, + pub file_path: String, + pub end_col: usize, } impl SpanPosition { - pub fn from_pos(pos: Position, end_col: usize) -> Self { - SpanPosition { line: pos.line, col: pos.col, file_path: pos.file_path, end_col } - } - - pub fn from_pos2(start: Position, end: Position) -> Self { - SpanPosition { line: start.line, col: start.col, file_path: start.file_path, end_col: end.col } - } - - pub fn get_line_content(&self) -> Result { - let contents = fs::read_to_string(&self.file_path)?; - - let spl: Vec<&str> = contents.split('\n').collect(); - - return Ok(String::from(spl[self.line - 1])); - } + pub fn from_pos(pos: Position, end_col: usize) -> Self { + SpanPosition { + line: pos.line, + col: pos.col, + file_path: pos.file_path, + end_col, + } + } + + pub fn from_pos2(start: Position, end: Position) -> Self { + SpanPosition { + line: start.line, + col: start.col, + file_path: start.file_path, + end_col: end.col, + } + } + + pub fn get_line_content(&self) -> Result { + let contents = fs::read_to_string(&self.file_path)?; + + let spl: Vec<&str> = contents.split('\n').collect(); + + return Ok(String::from(spl[self.line - 1])); + } } impl Display for SpanPosition { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let _ = write!(f, "{}:{}:{}", self.file_path, self.line, self.col); + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let _ = write!(f, "{}:{}:{}", self.file_path, self.line, self.col); - Ok(()) - } + Ok(()) + } } #[derive(Clone)] pub struct Span { - pub start: SpanPosition, + pub start: SpanPosition, - pub label: Option, - pub kind: SpanKind + pub label: Option, + pub kind: SpanKind, } impl Span { - pub fn make_primary(pos: SpanPosition, label: Option) -> Self { - Span { start: pos, label, kind: SpanKind::Primary } - } - - pub fn make_secondary(pos: SpanPosition, label: Option) -> Self { - Span { start: pos, label, kind: SpanKind::Secondary } - } + pub fn make_primary(pos: SpanPosition, label: Option) -> Self { + Span { + start: pos, + label, + kind: SpanKind::Primary, + } + } + + pub fn make_secondary(pos: SpanPosition, label: Option) -> Self { + Span { + start: pos, + label, + kind: SpanKind::Secondary, + } + } } fn print_underline(start: usize, end: usize, c: char) -> String { - let mut str = "".to_string(); - for _ in 0..start { - str += " "; - } + let mut str = "".to_string(); + for _ in 0..start { + str += " "; + } - for _ in start..end { - str += &c.to_string(); - } + for _ in start..end { + str += &c.to_string(); + } - str + str } fn print_space(start: usize) -> String { - let mut str = "".to_string(); + let mut str = "".to_string(); - for _ in 0..start { - str += " "; - } + for _ in 0..start { + str += " "; + } - str + str } impl Display for Span { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let line = match self.start.get_line_content() { - Ok(v) => v, - Err(_) => "".to_string() - }; - - let line = line.replace("\t", ""); - - writeln!(f, " {} {}", "|".bright_blue() , line)?; - - let underline = print_underline(self.start.col, self.start.end_col, self.kind.get_marker_char()); - - writeln!(f, " {} {}", "|".bright_blue(), underline.bright_yellow())?; - - if let Some(v) = self.label.clone() { - let space = print_space(self.start.col + 4); - writeln!(f, " {}{}{}", "|".bright_blue(), space, v)?; - } - - Ok(()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let line = match self.start.get_line_content() { + Ok(v) => v, + Err(_) => "".to_string(), + }; + + let line = line.replace("\t", ""); + + writeln!(f, " {} {}", "|".bright_blue(), line)?; + + let underline = print_underline( + self.start.col, + self.start.end_col, + self.kind.get_marker_char(), + ); + + writeln!( + f, + " {} {}", + "|".bright_blue(), + underline.bright_yellow() + )?; + + if let Some(v) = self.label.clone() { + let space = print_space(self.start.col + 4); + writeln!(f, " {}{}{}", "|".bright_blue(), space, v)?; + } + + Ok(()) + } } impl Display for Diagnostic { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let header = ColoredString::from(format!("{}[{}{}]", self.level, self.level.get_code_char(), self.code)); - let header = self.level.apply_color(header); - - writeln!(f, "{}: {}", header, self.message)?; - writeln!(f, " {} {}", "-->".bright_blue(), self.primary_span.start)?; - writeln!(f, " {}", "|".bright_blue())?; - - write!(f, "{}", self.primary_span)?; - - for span in &self.spans { - writeln!(f, "{}", span)?; - } - - writeln!(f, " {}", "|".bright_blue())?; - - let mut ind = 0; - for note in &self.note { - writeln!(f, " {} {}: {}", "=".bright_blue(), "note".bold(), note)?; - writeln!(f, " {} {}: {}", "=".bright_blue(), "help".bold(), self.help[ind])?; - write!(f, " {}", "|".bright_blue())?; - - ind += 1; - } - - #[cfg(feature = "compiler_diagbacktraces")] { - writeln!(f, "Internally captured in:")?; - writeln!(f, "{}", self.backtrace)?; - } - - Ok(()) - } -} \ No newline at end of file + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let header = ColoredString::from(format!( + "{}[{}{}]", + self.level, + self.level.get_code_char(), + self.code + )); + let header = self.level.apply_color(header); + + writeln!(f, "{}: {}", header, self.message)?; + writeln!(f, " {} {}", "-->".bright_blue(), self.primary_span.start)?; + writeln!(f, " {}", "|".bright_blue())?; + + write!(f, "{}", self.primary_span)?; + + for span in &self.spans { + writeln!(f, "{}", span)?; + } + + writeln!(f, " {}", "|".bright_blue())?; + + let mut ind = 0; + for note in &self.note { + writeln!(f, " {} {}: {}", "=".bright_blue(), "note".bold(), note)?; + writeln!( + f, + " {} {}: {}", + "=".bright_blue(), + "help".bold(), + self.help[ind] + )?; + write!(f, " {}", "|".bright_blue())?; + + ind += 1; + } + + #[cfg(feature = "compiler_diagbacktraces")] + { + writeln!(f, "Internally captured in:")?; + writeln!(f, "{}", self.backtrace)?; + } + + Ok(()) + } +} diff --git a/compiler/diagnostics/src/errors.rs b/compiler/diagnostics/src/errors.rs index c15c071..8f6e25d 100644 --- a/compiler/diagnostics/src/errors.rs +++ b/compiler/diagnostics/src/errors.rs @@ -1,45 +1,105 @@ macro_rules! declare_error { - ($expr: ident, $ind: literal, $err: literal) => { - pub const $expr: (usize, &str) = ($ind, $err); - } + ($expr: ident, $ind: literal, $err: literal) => { + pub const $expr: (usize, &str) = ($ind, $err); + }; } declare_error!(EXPECTED_TOKEN, 0, "expected a {} but got a {}"); declare_error!(UNEXPECTED_TOKEN, 1, "unexpected {}"); -declare_error!(MISMATCHED_LITERAL, 2, "expected literal of type {} but got {} instead"); -declare_error!(MATH_OPERATION_ASSIGNS, 3, "math operations here require assignments"); +declare_error!( + MISMATCHED_LITERAL, + 2, + "expected literal of type {} but got {} instead" +); +declare_error!( + MATH_OPERATION_ASSIGNS, + 3, + "math operations here require assignments" +); declare_error!(FIND_TYPE, 4, "cannot find type {} in the current scope"); -declare_error!(EXPECTED_TYPE, 5, "expected a value of type {} but got a value of type {} instead"); +declare_error!( + EXPECTED_TYPE, + 5, + "expected a value of type {} but got a value of type {} instead" +); declare_error!(ALREADY_IN_SCOPE, 6, "{} was already found in this scope"); declare_error!(ERA_NOT_EXIST, 7, "{} doesn't exist in this era"); -declare_error!(ENUM_PARENT_FIELDS, 8, "fields are not supported in enum parents"); -declare_error!(ENUM_CHILD_FUNCTIONS, 9, "functions are not supported in enum children"); -declare_error!(LAYOUT_FUNCTIONS, 10, "functions are not supported in layouts"); +declare_error!( + ENUM_PARENT_FIELDS, + 8, + "fields are not supported in enum parents" +); +declare_error!( + ENUM_CHILD_FUNCTIONS, + 9, + "functions are not supported in enum children" +); +declare_error!( + LAYOUT_FUNCTIONS, + 10, + "functions are not supported in layouts" +); declare_error!(INVALID_POINTING, 11, "cannot point to a non-variable"); -declare_error!(TRAIT_MISSING, 12, "bound trait {} cannot be applied onto {}"); +declare_error!( + TRAIT_MISSING, + 12, + "bound trait {} cannot be applied onto {}" +); declare_error!(BOUND_MISSING, 13, "bound {} cannot be applied onto {}"); -declare_error!(VARIABLE_UNINIT, 14, "variable {} must be initialized every usage"); +declare_error!( + VARIABLE_UNINIT, + 14, + "variable {} must be initialized every usage" +); declare_error!(TYPE_RESOLVE, 15, "type cannot be fully resolved here"); -declare_error!(DIFF_SIZE_SPECIFIERS, 16, "expected {} size specifiers on this type, got {}"); -declare_error!(DIFF_TYPE_SPECIFIERS, 18, "expected {} type specifiers on this type, got {}"); +declare_error!( + DIFF_SIZE_SPECIFIERS, + 16, + "expected {} size specifiers on this type, got {}" +); +declare_error!( + DIFF_TYPE_SPECIFIERS, + 18, + "expected {} type specifiers on this type, got {}" +); declare_error!(IR_CAST, 19, "cannot cast IR value to given type!"); declare_error!(EXPECTED_FREE, 20, "expected a {}"); declare_error!(FIND_TYPE_FUNCTION, 21, "cannot find function {} in type {}"); declare_error!(FIND_TYPE_FIELD, 22, "cannot find field {} in type {}"); declare_error!(INDEX_USAGE, 23, "cannot use index access on this type"); -declare_error!(FIELD_STRUCT_INIT, 24, "field {} of type {} is missing in the initializer"); +declare_error!( + FIELD_STRUCT_INIT, + 24, + "field {} of type {} is missing in the initializer" +); declare_error!(FIELD_MISSING, 25, "field {} was not found in type {}"); declare_error!(FUNC_MISSING, 25, "function {} was not found in type {}"); -declare_error!(FIND_VAR, 25, "cannot find variable {} in the current context"); +declare_error!( + FIND_VAR, + 25, + "cannot find variable {} in the current context" +); // IR internals declare_error!(LOWER_TYPE_IR, 26, "cannot cast MIR variable to given type"); -declare_error!(ASSIGN_DIFF_TYPE_IR, 27, "cannot write on this value since the two types differ"); -declare_error!(IR_DIFF_SSA_INDEXES, 28, "cannot hint SSA val for pointers! indexes are different"); -declare_error!(IR_INSTRUCTION_HELD_VAL, 29, "cannot extract held value from instruction since it doesnt exist"); +declare_error!( + ASSIGN_DIFF_TYPE_IR, + 27, + "cannot write on this value since the two types differ" +); +declare_error!( + IR_DIFF_SSA_INDEXES, + 28, + "cannot hint SSA val for pointers! indexes are different" +); +declare_error!( + IR_INSTRUCTION_HELD_VAL, + 29, + "cannot extract held value from instruction since it doesnt exist" +); // Misc declare_error!(INVALID_TYPE_REQ, 30, "this operation requires a {} type"); declare_error!(TYPE_NOT_PART, 31, "type {} is not part of type {}"); declare_error!(NOT_FOUND_USE, 32, "element {} was not found in {}"); -declare_error!(CANNOT_FIND, 33, "cannot find {} in the current scope"); \ No newline at end of file +declare_error!(CANNOT_FIND, 33, "cannot find {} in the current scope"); diff --git a/compiler/diagnostics/src/infos.rs b/compiler/diagnostics/src/infos.rs index b89070a..313ecf2 100644 --- a/compiler/diagnostics/src/infos.rs +++ b/compiler/diagnostics/src/infos.rs @@ -1,11 +1,19 @@ macro_rules! declare_info { - ($expr: ident, $ind: literal, $err: literal) => { - pub const $expr: (usize, &str) = ($ind, $err); - } + ($expr: ident, $ind: literal, $err: literal) => { + pub const $expr: (usize, &str) = ($ind, $err); + }; } // Optimizations infos declare_info!(REDUCED_CALL, 0, "call will be optimized here"); -declare_info!(SSA_VARIABLE, 1, "variable will be treated as a register value"); -declare_info!(LINEARIZATION, 2, "function will be linearized as it is pure recursion"); \ No newline at end of file +declare_info!( + SSA_VARIABLE, + 1, + "variable will be treated as a register value" +); +declare_info!( + LINEARIZATION, + 2, + "function will be linearized as it is pure recursion" +); diff --git a/compiler/diagnostics/src/lib.rs b/compiler/diagnostics/src/lib.rs index 88b5521..994c6ba 100644 --- a/compiler/diagnostics/src/lib.rs +++ b/compiler/diagnostics/src/lib.rs @@ -1,73 +1,83 @@ -use std::{cell::RefCell}; +use std::cell::RefCell; use crate::diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}; +pub mod builders; pub mod diagnostic; pub mod errors; -pub mod warnings; pub mod infos; -pub mod builders; +pub mod warnings; pub type DiagnosticResult = Result; pub type MaybeDiagnostic = DiagnosticResult<()>; thread_local! { - static DIAGNOSTIC_CONTAINER: RefCell = RefCell::new(DiagnosticContainer::new()); + static DIAGNOSTIC_CONTAINER: RefCell = RefCell::new(DiagnosticContainer::new()); } thread_local! { - /// Used whenever the position cannot be passed directly (eg: interacting with the typing system or MIR.) - static CURR_DIAGNOSTIC_POS: RefCell> = RefCell::new(None) + /// Used whenever the position cannot be passed directly (eg: interacting with the typing system or MIR.) + static CURR_DIAGNOSTIC_POS: RefCell> = RefCell::new(None) } /// Used whenever a panic might be unsafe to trigger. Every panic triggered by this will be also logged in the error system #[macro_export] macro_rules! unsure_panic { - ($msg: expr) => { { - _ = diagnostics::builders::make_unsure_panic(&$msg.to_string()); - diagnostics::dump_diagnostics(); - panic!($msg); - } - }; + ($msg: expr) => {{ + _ = diagnostics::builders::make_unsure_panic(&$msg.to_string()); + diagnostics::dump_diagnostics(); + panic!($msg); + }}; } /// Origin that can generate diagnostics easily pub trait DiagnosticSpanOrigin { - fn make_span(&self, kind: SpanKind, msg: Option) -> Span; - fn make_simple_diagnostic(&self, code: usize, level: Level, message: String, primary_span_msg: Option, spans: Vec, notes: Vec, help: Vec) -> Diagnostic; - fn get_pos(&self) -> SpanPosition; + fn make_span(&self, kind: SpanKind, msg: Option) -> Span; + fn make_simple_diagnostic( + &self, + code: usize, + level: Level, + message: String, + primary_span_msg: Option, + spans: Vec, + notes: Vec, + help: Vec, + ) -> Diagnostic; + fn get_pos(&self) -> SpanPosition; } pub struct DiagnosticContainer { - pub diagnostics: Vec + pub diagnostics: Vec, } impl DiagnosticContainer { - pub fn new() -> Self { - DiagnosticContainer { diagnostics: vec![] } - } + pub fn new() -> Self { + DiagnosticContainer { + diagnostics: vec![], + } + } - pub fn append(&mut self, diagnostic: Diagnostic) { - self.diagnostics.push(diagnostic); - } + pub fn append(&mut self, diagnostic: Diagnostic) { + self.diagnostics.push(diagnostic); + } } pub fn dump_diagnostics() { - DIAGNOSTIC_CONTAINER.with_borrow(|f| { - for diagnostic in &f.diagnostics { - println!("{}", diagnostic); - } - }) + DIAGNOSTIC_CONTAINER.with_borrow(|f| { + for diagnostic in &f.diagnostics { + println!("{}", diagnostic); + } + }) } pub fn move_current_diagnostic_pos(pos: SpanPosition) { - CURR_DIAGNOSTIC_POS.with_borrow_mut(|f| { - *f = Some(pos); - }) + CURR_DIAGNOSTIC_POS.with_borrow_mut(|f| { + *f = Some(pos); + }) } pub fn get_current_diagnostic_pos() -> SpanPosition { - CURR_DIAGNOSTIC_POS.with_borrow(|f| { - return f.clone().unwrap(); - }) -} \ No newline at end of file + CURR_DIAGNOSTIC_POS.with_borrow(|f| { + return f.clone().unwrap(); + }) +} diff --git a/compiler/diagnostics/src/warnings.rs b/compiler/diagnostics/src/warnings.rs index e561b56..b32ebc8 100644 --- a/compiler/diagnostics/src/warnings.rs +++ b/compiler/diagnostics/src/warnings.rs @@ -1,7 +1,7 @@ macro_rules! declare_warning { - ($expr: ident, $ind: literal, $err: literal) => { - pub const $expr: (usize, &str) = ($ind, $err); - } + ($expr: ident, $ind: literal, $err: literal) => { + pub const $expr: (usize, &str) = ($ind, $err); + }; } // Unused @@ -14,11 +14,23 @@ declare_warning!(UNUSED_USE, 4, "unused `use` statement: {}"); // Support (CPU) declare_warning!(CPU_SUPPORTED_TYPE, 5, "this type is unsupported by the CPU"); -declare_warning!(CPU_SUPPORTED_OP, 6, "this operation is unsupported by the CPU"); +declare_warning!( + CPU_SUPPORTED_OP, + 6, + "this operation is unsupported by the CPU" +); // Support (Quickfall) -declare_warning!(EXPERIMENTAL_FEAT, 7, "this feature was marked as experimental"); -declare_warning!(EXPERIMENTAL_FUNC, 8, "this function was marked as experimental"); +declare_warning!( + EXPERIMENTAL_FEAT, + 7, + "this feature was marked as experimental" +); +declare_warning!( + EXPERIMENTAL_FUNC, + 8, + "this function was marked as experimental" +); declare_warning!(EXPERIMENTAL_TYPE, 9, "this type was marked as experimental"); declare_warning!(DEPRECATED, 10, "this was marked as deprecated"); declare_warning!(DEPRECATED_MSG, 11, "this was marked as deprecated: {}"); @@ -26,4 +38,8 @@ declare_warning!(DEPRECATED_MSG, 11, "this was marked as deprecated: {}"); // Safety declare_warning!(UNSAFE_UNWRAP, 7, "unsafe unwrapping, value might not be {}"); declare_warning!(UNSAFE_FUNC, 7, "this function was marked as unsafe"); -declare_warning!(SHADOWFUNC_INFINITEARGS, 8, "this function doesn't have strict arguments, use with caution"); \ No newline at end of file +declare_warning!( + SHADOWFUNC_INFINITEARGS, + 8, + "this function doesn't have strict arguments, use with caution" +); diff --git a/compiler/lexer/Cargo.toml b/compiler/lexer/Cargo.toml index 5481e8e..7df0051 100644 --- a/compiler/lexer/Cargo.toml +++ b/compiler/lexer/Cargo.toml @@ -5,4 +5,4 @@ edition = "2024" [dependencies] compiler_utils = { path = "../compiler_utils" } -diagnostics = { path = "../diagnostics" } \ No newline at end of file +diagnostics = { path = "../diagnostics" } diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index e724251..d0520bc 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -1,15 +1,15 @@ //! //! Module containing the core lexer algorithm -//! +//! use std::fs; use compiler_utils::{Position, hash}; use diagnostics::DiagnosticResult; -use diagnostics::builders::{make_unexpected_simple_error_outside}; +use diagnostics::builders::make_unexpected_simple_error_outside; use diagnostics::diagnostic::SpanPosition; -use crate::{token::{LexerToken, LexerTokenType}}; +use crate::token::{LexerToken, LexerTokenType}; const SHADOWFUNC_KEYWORD_HASH: u64 = hash!("shadowfunc"); const FUNC_KEYWORD_HASH: u64 = hash!("func"); @@ -33,9 +33,9 @@ const ENUM_KEYWORD_HASH: u64 = hash!("enum"); const USE_KEYWORD_HASH: u64 = hash!("use"); /// Parses a file into a set of lexer tokens. -/// +/// /// # Examples -/// +/// /// ``` /// let result: LexerParseResult> = lexer_parse_file("test_file.qf").expect("Lexer didn't work"); /// ``` @@ -48,141 +48,218 @@ pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> let mut tokens: Vec = Vec::new(); let mut i: usize = 0; - let mut line: usize = 1; - let mut last_line_break: usize = 0; - + let mut line: usize = 1; + let mut last_line_break: usize = 0; + while i < contents.len() { let c: char = contents.chars().nth(i).unwrap(); - - if c == '\n' { - i += 1; - last_line_break = i; - line += 1; - continue; - } + + if c == '\n' { + i += 1; + last_line_break = i; + line += 1; + continue; + } if c.is_numeric() { - let col = i - last_line_break; - tokens.push(parse_number_token(&contents, &mut i, Position::new(file_path.to_string(), line, col))?); + let col = i - last_line_break; + tokens.push(parse_number_token( + &contents, + &mut i, + Position::new(file_path.to_string(), line, col), + )?); continue; } if c == '"' { - let col = i - last_line_break; + let col = i - last_line_break; - tokens.push(parse_string_token(&contents, &mut i, Position::new(file_path.to_string(), line, col))); + tokens.push(parse_string_token( + &contents, + &mut i, + Position::new(file_path.to_string(), line, col), + )); continue; } if c.is_alphabetic() { - let col = i - last_line_break; + let col = i - last_line_break; - tokens.push(parse_keyword(&contents, &mut i, Position::new(file_path.to_string(), line, col))); + tokens.push(parse_keyword( + &contents, + &mut i, + Position::new(file_path.to_string(), line, col), + )); continue; } - if c == '/' { - let cc = contents.chars().nth(i + 1).unwrap(); - if cc == '/' { - let col = i - last_line_break; - - tokens.push(parse_comment(&contents, &mut i, Position::new(file_path.to_string(), line, col))?); - continue; - } else if cc == '.' { - let col = i - last_line_break; - - tokens.push(parse_global_comment(&contents, &mut i, Position::new(file_path.to_string(), line, col))?); - continue; - } - } + if c == '/' { + let cc = contents.chars().nth(i + 1).unwrap(); + if cc == '/' { + let col = i - last_line_break; + + tokens.push(parse_comment( + &contents, + &mut i, + Position::new(file_path.to_string(), line, col), + )?); + continue; + } else if cc == '.' { + let col = i - last_line_break; + + tokens.push(parse_global_comment( + &contents, + &mut i, + Position::new(file_path.to_string(), line, col), + )?); + continue; + } + } i += 1; + let col = i - last_line_break; - let col = i - last_line_break; - - let pos = Position::new(file_path.to_string(), line, col); + let pos = Position::new(file_path.to_string(), line, col); match c { - '{' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::BracketOpen)), - '}' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::BracketClose)), - '(' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ParenOpen)), - ')' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ParenClose)), - '[' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ArrayOpen)), - ']' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ArrayClose)), - '=' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::EqualSign)), + '{' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::BracketOpen, + )), + '}' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::BracketClose, + )), + '(' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::ParenOpen, + )), + ')' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::ParenClose, + )), + '[' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::ArrayOpen, + )), + ']' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::ArrayClose, + )), + '=' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::EqualSign, + )), ',' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Comma)), '.' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Dot)), - '!' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ExclamationMark)), - '&' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Ampersand)), - '<' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::AngelBracketOpen)), - '>' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::AngelBracketClose)), - '*' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Asterisk)), - ':' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Collon)), - '+' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Plus)), - '-' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Minus)), - '/' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Divide)), - '~' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Tidle)), - '%' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::PercentSign)), - _ => continue + '!' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::ExclamationMark, + )), + '&' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::Ampersand, + )), + '<' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::AngelBracketOpen, + )), + '>' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::AngelBracketClose, + )), + '*' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Asterisk)), + ':' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Collon)), + '+' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Plus)), + '-' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Minus)), + '/' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Divide)), + '~' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::Tidle)), + '%' => tokens.push(LexerToken::make_single_sized( + pos, + LexerTokenType::PercentSign, + )), + _ => continue, } - } - tokens.push(LexerToken::make_single_sized(Position::new(file_path.to_string(), line, i - last_line_break + 1), LexerTokenType::EndOfFile)); + tokens.push(LexerToken::make_single_sized( + Position::new(file_path.to_string(), line, i - last_line_break + 1), + LexerTokenType::EndOfFile, + )); Ok(tokens) } -fn parse_comment(contents: &String, ind: &mut usize, start_pos: Position) -> DiagnosticResult { - *ind += 2; +fn parse_comment( + contents: &String, + ind: &mut usize, + start_pos: Position, +) -> DiagnosticResult { + *ind += 2; - let start = *ind; - let mut end = start; + let start = *ind; + let mut end = start; - for (i, c) in contents[start..].char_indices() { - if c == '\n' || c == '\0' { - end = start + i + c.len_utf8(); - break; - } + for (i, c) in contents[start..].char_indices() { + if c == '\n' || c == '\0' { + end = start + i + c.len_utf8(); + break; + } - end = start + i + c.len_utf16(); - } + end = start + i + c.len_utf16(); + } - let slice = &contents[*ind + 1..end - 1]; + let slice = &contents[*ind + 1..end - 1]; - *ind = end; + *ind = end; - return Ok(LexerToken::new(start_pos, end - start, LexerTokenType::Comment(slice.to_string()))) + return Ok(LexerToken::new( + start_pos, + end - start, + LexerTokenType::Comment(slice.to_string()), + )); } -fn parse_global_comment(contents: &String, ind: &mut usize, start_pos: Position) -> DiagnosticResult { - *ind += 2; +fn parse_global_comment( + contents: &String, + ind: &mut usize, + start_pos: Position, +) -> DiagnosticResult { + *ind += 2; - let start = *ind; - let mut end = start; + let start = *ind; + let mut end = start; - for (i, c) in contents[start..].char_indices() { - if c == '\n' || c == '\0' { - end = start + i + c.len_utf8(); - break; - } + for (i, c) in contents[start..].char_indices() { + if c == '\n' || c == '\0' { + end = start + i + c.len_utf8(); + break; + } - end = start + i + c.len_utf16(); - } + end = start + i + c.len_utf16(); + } - let slice = &contents[*ind + 1..end - 1]; + let slice = &contents[*ind + 1..end - 1]; - *ind = end; + *ind = end; - return Ok(LexerToken::new(start_pos, end - start, LexerTokenType::GlobalComment(slice.to_string()))) + return Ok(LexerToken::new( + start_pos, + end - start, + LexerTokenType::GlobalComment(slice.to_string()), + )); } -fn parse_number_token(str: &String, ind: &mut usize, start_pos: Position) -> DiagnosticResult { +fn parse_number_token( + str: &String, + ind: &mut usize, + start_pos: Position, +) -> DiagnosticResult { let start = *ind + 1; let mut end: usize = start; - - for(i, c) in str[start..].char_indices() { + + for (i, c) in str[start..].char_indices() { if !c.is_ascii_digit() { break; } @@ -193,35 +270,45 @@ fn parse_number_token(str: &String, ind: &mut usize, start_pos: Position) -> Dia let slice = &str[*ind..end]; let num: i128 = match slice.parse() { Ok(v) => v, - Err(_) => return Err(make_unexpected_simple_error_outside(&slice, SpanPosition::from_pos(start_pos.clone(), start_pos.col + (end - start))).into()) + Err(_) => { + return Err(make_unexpected_simple_error_outside( + &slice, + SpanPosition::from_pos(start_pos.clone(), start_pos.col + (end - start)), + ) + .into()); + } }; *ind = end; - let mut hash = hash!("s64"); // s64 + let mut hash = hash!("s64"); // s64 + + let endpos = start_pos.increment_by(end - start); - let endpos = start_pos.increment_by(end - start); + if str.chars().nth(*ind).unwrap() == '_' { + *ind += 1; - if str.chars().nth(*ind).unwrap() == '_' { - *ind += 1; - - let tok = parse_keyword(str, ind, endpos.clone()); - let k = match tok.expects_keyword() { - Ok(v) => v, - Err(e) => return Err(e) - }; + let tok = parse_keyword(str, ind, endpos.clone()); + let k = match tok.expects_keyword() { + Ok(v) => v, + Err(e) => return Err(e), + }; - hash = k.1; - } + hash = k.1; + } - return Ok(LexerToken::new(start_pos, end - start, LexerTokenType::IntLit(num, hash))); + return Ok(LexerToken::new( + start_pos, + end - start, + LexerTokenType::IntLit(num, hash), + )); } fn parse_string_token(str: &String, ind: &mut usize, start_pos: Position) -> LexerToken { let start = *ind + 1; let mut end: usize = start; - for(i, c) in str[start..].char_indices() { + for (i, c) in str[start..].char_indices() { if c == '"' { end = start + i + c.len_utf8(); break; @@ -233,15 +320,19 @@ fn parse_string_token(str: &String, ind: &mut usize, start_pos: Position) -> Lex let slice = &str[*ind + 1..end - 1]; *ind = end; - - return LexerToken::new(start_pos, end - start, LexerTokenType::StringLit(slice.to_string())); + + return LexerToken::new( + start_pos, + end - start, + LexerTokenType::StringLit(slice.to_string()), + ); } fn parse_keyword(str: &String, ind: &mut usize, start_pos: Position) -> LexerToken { let start = *ind; let mut end: usize = start; - - for(i, c) in str[start..].char_indices() { + + for (i, c) in str[start..].char_indices() { if !c.is_alphabetic() && !c.is_numeric() && c != '_' && c != '-' { break; } @@ -250,34 +341,34 @@ fn parse_keyword(str: &String, ind: &mut usize, start_pos: Position) -> LexerTok } let slice = &str[start..end]; - - let hash = hash!(slice); + + let hash = hash!(slice); *ind = end; let token_type = match hash { FUNC_KEYWORD_HASH => LexerTokenType::Function, - SHADOWFUNC_KEYWORD_HASH => LexerTokenType::ShadowFunction, + SHADOWFUNC_KEYWORD_HASH => LexerTokenType::ShadowFunction, RET_KEYWORD_HASH => LexerTokenType::Return, - STRUCT_KEYWORD_HASH => LexerTokenType::Struct, - LAYOUT_KEYWORD_HASH => LexerTokenType::Layout, - LAY_KEYWORD_HASH => LexerTokenType::Lay, - TRUE_KEYWORD_HASH => LexerTokenType::True, - FALSE_KEYWORD_HASH => LexerTokenType::False, - VAR_KEYWORD_HASH => LexerTokenType::Var, - IF_KEYWORD_HASH => LexerTokenType::If, - ELSE_KEYWORD_HASH => LexerTokenType::Else, - WHILE_KEYWORD_HASH => LexerTokenType::While, - FOR_KEYWORD_HASH => LexerTokenType::For, - STATIC_KEYWORD_HASH => LexerTokenType::Static, - THIS_KEYWORD_HASH => LexerTokenType::This, - NEW_KEYWORD_HASH => LexerTokenType::New, - UNWRAP_KEYWORD_HASH => LexerTokenType::Unwrap, - UNWRAP_UNSAFE_KEYWORD_HASH => LexerTokenType::UnwrapUnsafe, - ENUM_KEYWORD_HASH => LexerTokenType::Enum, - USE_KEYWORD_HASH => LexerTokenType::Use, - _ => LexerTokenType::Keyword(slice.to_string(), hash) + STRUCT_KEYWORD_HASH => LexerTokenType::Struct, + LAYOUT_KEYWORD_HASH => LexerTokenType::Layout, + LAY_KEYWORD_HASH => LexerTokenType::Lay, + TRUE_KEYWORD_HASH => LexerTokenType::True, + FALSE_KEYWORD_HASH => LexerTokenType::False, + VAR_KEYWORD_HASH => LexerTokenType::Var, + IF_KEYWORD_HASH => LexerTokenType::If, + ELSE_KEYWORD_HASH => LexerTokenType::Else, + WHILE_KEYWORD_HASH => LexerTokenType::While, + FOR_KEYWORD_HASH => LexerTokenType::For, + STATIC_KEYWORD_HASH => LexerTokenType::Static, + THIS_KEYWORD_HASH => LexerTokenType::This, + NEW_KEYWORD_HASH => LexerTokenType::New, + UNWRAP_KEYWORD_HASH => LexerTokenType::Unwrap, + UNWRAP_UNSAFE_KEYWORD_HASH => LexerTokenType::UnwrapUnsafe, + ENUM_KEYWORD_HASH => LexerTokenType::Enum, + USE_KEYWORD_HASH => LexerTokenType::Use, + _ => LexerTokenType::Keyword(slice.to_string(), hash), }; - return LexerToken::new(start_pos, end - start, token_type); -} \ No newline at end of file + return LexerToken::new(start_pos, end - start, token_type); +} diff --git a/compiler/lexer/src/lib.rs b/compiler/lexer/src/lib.rs index baff5a2..bbc3c31 100644 --- a/compiler/lexer/src/lib.rs +++ b/compiler/lexer/src/lib.rs @@ -1,7 +1,7 @@ -//! -//! The core of the lexer crate. +//! +//! The core of the lexer crate. //! The lexer is the first step of parsing within Quickfall. -//! +//! +pub mod lexer; pub mod token; -pub mod lexer; \ No newline at end of file diff --git a/compiler/lexer/src/token.rs b/compiler/lexer/src/token.rs index 6574fd3..c61ee5e 100644 --- a/compiler/lexer/src/token.rs +++ b/compiler/lexer/src/token.rs @@ -1,66 +1,70 @@ -//! +//! //! Module containing lexer token-based utilities and classes -//! +//! use std::fmt::Display; -use compiler_utils::{Position}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_expected_simple_error, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}}; +use compiler_utils::Position; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, + builders::make_expected_simple_error, + diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, +}; /// The token type for the lexer #[derive(PartialEq, Debug)] pub enum LexerTokenType { /// Represent the func keyword Function, - ShadowFunction, + ShadowFunction, - Comment(String), - GlobalComment(String), + Comment(String), + GlobalComment(String), - Unwrap, - UnwrapUnsafe, + Unwrap, + UnwrapUnsafe, - Use, + Use, - Var, - Struct, - Layout, - Lay, + Var, + Struct, + Layout, + Lay, - Enum, + Enum, - This, + This, - Static, + Static, - New, + New, /// Represent the ret keyword Return, - True, - False, + True, + False, - For, - If, - Else, - While, + For, + If, + Else, + While, EqualSign, - ExclamationMark, + ExclamationMark, - Asterisk, + Asterisk, Comma, Dot, - Ampersand, - Collon, + Ampersand, + Collon, - Plus, - Minus, - Divide, - Tidle, - PercentSign, + Plus, + Minus, + Divide, + Tidle, + PercentSign, BracketOpen, BracketClose, @@ -78,148 +82,192 @@ pub enum LexerTokenType { AngelBracketClose, Keyword(String, u64), - EndOfFile + EndOfFile, } #[derive(Debug)] pub struct LexerToken { - pub tok_type: LexerTokenType, - pub pos: Position, - pub pos_size: usize + pub tok_type: LexerTokenType, + pub pos: Position, + pub pos_size: usize, } impl LexerToken { - pub fn make_single_sized(pos: Position, t: LexerTokenType) -> Self { - - return LexerToken { tok_type: t, pos, pos_size: 1 }; - } - - pub fn new(start: Position, size: usize, t: LexerTokenType) -> Self { - return LexerToken { tok_type:t , pos: start, pos_size: size } - } - - pub fn is(&self, t: LexerTokenType) -> bool { - return self.tok_type == t; - } - - pub fn expects(&self, t: LexerTokenType) -> DiagnosticResult<()> { - if self.tok_type != t { - return Err(make_expected_simple_error(self, &t, &self.tok_type).into()) - } - - return Ok(()); - } - - pub fn expects_int_lit(&self) -> DiagnosticResult<(i128, u64)> { - match &self.tok_type { - LexerTokenType::IntLit(v, h) => return Ok((*v, *h)), - _ => return Err(make_expected_simple_error(self, &"integer literal".to_string(), &self.tok_type).into()) - }; - } - - pub fn expects_string_lit(&self) -> DiagnosticResult { - match &self.tok_type { - LexerTokenType::StringLit(v) => return Ok(v.to_string()), - _ => return Err(make_expected_simple_error(self, &"string literal".to_string(), &self.tok_type).into()) - - }; - } - - pub fn expects_keyword(&self) -> DiagnosticResult<(String, u64)> { - match &self.tok_type { - LexerTokenType::Keyword(s, h) => return Ok((s.to_string(), *h)), - _ => return Err(make_expected_simple_error(self, &"keyword".to_string(), &self.tok_type).into()) - }; - } - - pub fn is_keyword(&self) -> bool { - match &self.tok_type { - LexerTokenType::Keyword(_, _) => true, - _ => false - } - } - - pub fn get_size(&self) -> usize { - return self.pos_size; - } - - pub fn get_pos(&self) -> SpanPosition { - return SpanPosition::from_pos(self.pos.clone(), self.pos_size); - } - - pub fn get_end_pos(&self) -> Position { - return self.pos.increment_by(self.pos_size); - } + pub fn make_single_sized(pos: Position, t: LexerTokenType) -> Self { + return LexerToken { + tok_type: t, + pos, + pos_size: 1, + }; + } + + pub fn new(start: Position, size: usize, t: LexerTokenType) -> Self { + return LexerToken { + tok_type: t, + pos: start, + pos_size: size, + }; + } + + pub fn is(&self, t: LexerTokenType) -> bool { + return self.tok_type == t; + } + + pub fn expects(&self, t: LexerTokenType) -> DiagnosticResult<()> { + if self.tok_type != t { + return Err(make_expected_simple_error(self, &t, &self.tok_type).into()); + } + + return Ok(()); + } + + pub fn expects_int_lit(&self) -> DiagnosticResult<(i128, u64)> { + match &self.tok_type { + LexerTokenType::IntLit(v, h) => return Ok((*v, *h)), + _ => { + return Err(make_expected_simple_error( + self, + &"integer literal".to_string(), + &self.tok_type, + ) + .into()); + } + }; + } + + pub fn expects_string_lit(&self) -> DiagnosticResult { + match &self.tok_type { + LexerTokenType::StringLit(v) => return Ok(v.to_string()), + _ => { + return Err(make_expected_simple_error( + self, + &"string literal".to_string(), + &self.tok_type, + ) + .into()); + } + }; + } + + pub fn expects_keyword(&self) -> DiagnosticResult<(String, u64)> { + match &self.tok_type { + LexerTokenType::Keyword(s, h) => return Ok((s.to_string(), *h)), + _ => { + return Err(make_expected_simple_error( + self, + &"keyword".to_string(), + &self.tok_type, + ) + .into()); + } + }; + } + + pub fn is_keyword(&self) -> bool { + match &self.tok_type { + LexerTokenType::Keyword(_, _) => true, + _ => false, + } + } + + pub fn get_size(&self) -> usize { + return self.pos_size; + } + + pub fn get_pos(&self) -> SpanPosition { + return SpanPosition::from_pos(self.pos.clone(), self.pos_size); + } + + pub fn get_end_pos(&self) -> Position { + return self.pos.increment_by(self.pos_size); + } } impl Display for LexerTokenType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Enum => "enum", - Self::Ampersand => "&", - Self::AngelBracketClose => ">", - Self::AngelBracketOpen => "<", - Self::ArrayClose => "]", - Self::ArrayOpen => "[", - Self::Asterisk => "*", - Self::Collon => ":", - Self::BracketClose => "}", - Self::BracketOpen => "{", - Self::Comma => ",", - Self::Comment(_) => "comment", - Self::Dot => ".", - Self::Else => "else", - Self::EndOfFile => "end of file", - Self::EqualSign => "=", - Self::ExclamationMark => "!", - Self::False => "false", - Self::For => "for", - Self::Function => "func", - Self::GlobalComment(_) => "global comment", - Self::If => "if", - Self::IntLit(_, _) => "integer literal", - Self::Keyword(_, _) => "keyword", - Self::Lay => "lay", - Self::Layout => "layout", - Self::New => "new", - Self::ParenClose => ")", - Self::ParenOpen => "(", - Self::Return => "ret", - Self::ShadowFunction => "shadowfunc", - Self::Static => "static", - Self::StringLit(_) => "string literal", - Self::Var => "var", - Self::Struct => "struct", - Self::This => "this", - Self::True => "true", - Self::While => "while", - Self::Unwrap => "unwrap", - Self::Use => "use", - Self::UnwrapUnsafe => "unsafe_unwrap", - Self::Plus => "+", - Self::Minus => "-", - Self::Divide => "/", - Self::Tidle => "~", - Self::PercentSign => "%" - }; - - write!(f, "{}", s)?; - Ok(()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Enum => "enum", + Self::Ampersand => "&", + Self::AngelBracketClose => ">", + Self::AngelBracketOpen => "<", + Self::ArrayClose => "]", + Self::ArrayOpen => "[", + Self::Asterisk => "*", + Self::Collon => ":", + Self::BracketClose => "}", + Self::BracketOpen => "{", + Self::Comma => ",", + Self::Comment(_) => "comment", + Self::Dot => ".", + Self::Else => "else", + Self::EndOfFile => "end of file", + Self::EqualSign => "=", + Self::ExclamationMark => "!", + Self::False => "false", + Self::For => "for", + Self::Function => "func", + Self::GlobalComment(_) => "global comment", + Self::If => "if", + Self::IntLit(_, _) => "integer literal", + Self::Keyword(_, _) => "keyword", + Self::Lay => "lay", + Self::Layout => "layout", + Self::New => "new", + Self::ParenClose => ")", + Self::ParenOpen => "(", + Self::Return => "ret", + Self::ShadowFunction => "shadowfunc", + Self::Static => "static", + Self::StringLit(_) => "string literal", + Self::Var => "var", + Self::Struct => "struct", + Self::This => "this", + Self::True => "true", + Self::While => "while", + Self::Unwrap => "unwrap", + Self::Use => "use", + Self::UnwrapUnsafe => "unsafe_unwrap", + Self::Plus => "+", + Self::Minus => "-", + Self::Divide => "/", + Self::Tidle => "~", + Self::PercentSign => "%", + }; + + write!(f, "{}", s)?; + Ok(()) + } } impl DiagnosticSpanOrigin for LexerToken { - fn make_span(&self, kind: SpanKind, msg: Option) -> Span { - Span { kind, label: msg, start: SpanPosition::from_pos(self.pos.clone(), self.get_size()) } - } - - fn get_pos(&self) -> SpanPosition { - SpanPosition::from_pos(self.pos.clone(), self.get_size()) - } - - fn make_simple_diagnostic(&self, code: usize, level: diagnostics::diagnostic::Level, message: String, primary_span_msg: Option, spans: Vec, notes: Vec, help: Vec) -> diagnostics::diagnostic::Diagnostic { - let primary = Span { kind: SpanKind::Primary, label: primary_span_msg, start: SpanPosition::from_pos(self.pos.clone(), self.get_size()) }; - - Diagnostic::new_base(level, code, message, primary, spans, notes, help) - } -} \ No newline at end of file + fn make_span(&self, kind: SpanKind, msg: Option) -> Span { + Span { + kind, + label: msg, + start: SpanPosition::from_pos(self.pos.clone(), self.get_size()), + } + } + + fn get_pos(&self) -> SpanPosition { + SpanPosition::from_pos(self.pos.clone(), self.get_size()) + } + + fn make_simple_diagnostic( + &self, + code: usize, + level: diagnostics::diagnostic::Level, + message: String, + primary_span_msg: Option, + spans: Vec, + notes: Vec, + help: Vec, + ) -> diagnostics::diagnostic::Diagnostic { + let primary = Span { + kind: SpanKind::Primary, + label: primary_span_msg, + start: SpanPosition::from_pos(self.pos.clone(), self.get_size()), + }; + + Diagnostic::new_base(level, code, message, primary, spans, notes, help) + } +} diff --git a/compiler/llvm_ir_bridge/Cargo.toml b/compiler/llvm_ir_bridge/Cargo.toml index b49da64..01936aa 100644 --- a/compiler/llvm_ir_bridge/Cargo.toml +++ b/compiler/llvm_ir_bridge/Cargo.toml @@ -4,7 +4,9 @@ version = "0.1.0" edition = "2024" [dependencies] -inkwell = { git = "https://github.com/TheDan64/inkwell", features = ["llvm22-1"]} +inkwell = { git = "https://github.com/TheDan64/inkwell", features = [ + "llvm22-1", +] } astoir_mir = { path = "../astoir_mir" } compiler_typing = { path = "../compiler_typing" } -rand = "0.8" \ No newline at end of file +rand = "0.8" diff --git a/compiler/llvm_ir_bridge/src/blocks.rs b/compiler/llvm_ir_bridge/src/blocks.rs index 1d07bf5..82cc642 100644 --- a/compiler/llvm_ir_bridge/src/blocks.rs +++ b/compiler/llvm_ir_bridge/src/blocks.rs @@ -3,31 +3,38 @@ use astoir_mir::{blocks::MIRBlock, ctx::MIRContext}; use crate::{ctx::LLVMBridgeContext, insts::bridge_llvm_instruction}; pub fn bridge_llvm_blocks(mir: &MIRContext, bridge: &mut LLVMBridgeContext) { - for block in &mir.blocks { - for merge in &block.merge_blocks { - let b = &mir.blocks[*merge]; + for block in &mir.blocks { + for merge in &block.merge_blocks { + let b = &mir.blocks[*merge]; - bridge_llvm_block(mir, mir.block_to_func[&block.self_ref], b, bridge); - } + bridge_llvm_block(mir, mir.block_to_func[&block.self_ref], b, bridge); + } - bridge_llvm_block(mir, mir.block_to_func[&block.self_ref], block, bridge); - } + bridge_llvm_block(mir, mir.block_to_func[&block.self_ref], block, bridge); + } } -pub fn bridge_llvm_block(mir: &MIRContext, func: usize, block: &MIRBlock, bridge: &mut LLVMBridgeContext) { - if bridge.completed_blocks.contains(&block.self_ref) { - return; - } - - bridge.builder.position_at_end(bridge.blocks[&block.self_ref].clone().inner); - - for inst in block.instructions.clone() { - let res = bridge_llvm_instruction(inst.clone(), func, bridge, mir); - - if res.is_some() { - bridge.values.insert(inst.as_valuedindex(), res.unwrap()); - } - } - - bridge.completed_blocks.insert(block.self_ref); -} \ No newline at end of file +pub fn bridge_llvm_block( + mir: &MIRContext, + func: usize, + block: &MIRBlock, + bridge: &mut LLVMBridgeContext, +) { + if bridge.completed_blocks.contains(&block.self_ref) { + return; + } + + bridge + .builder + .position_at_end(bridge.blocks[&block.self_ref].clone().inner); + + for inst in block.instructions.clone() { + let res = bridge_llvm_instruction(inst.clone(), func, bridge, mir); + + if res.is_some() { + bridge.values.insert(inst.as_valuedindex(), res.unwrap()); + } + } + + bridge.completed_blocks.insert(block.self_ref); +} diff --git a/compiler/llvm_ir_bridge/src/ctx.rs b/compiler/llvm_ir_bridge/src/ctx.rs index 9c4e74b..203b772 100644 --- a/compiler/llvm_ir_bridge/src/ctx.rs +++ b/compiler/llvm_ir_bridge/src/ctx.rs @@ -1,41 +1,43 @@ use std::collections::{HashMap, HashSet}; use std::{mem::transmute, rc::Rc}; +use inkwell::builder::Builder; use inkwell::module::Module; use inkwell::{context::Context, types::VoidType}; -use inkwell::builder::Builder; -use crate::{types::LLVMTypeStorage, utils::{LLVMBasicValue, LLVMBlock, LLVMFunction}}; +use crate::{ + types::LLVMTypeStorage, + utils::{LLVMBasicValue, LLVMBlock, LLVMFunction}, +}; pub struct LLVMBridgeContext { - pub blocks: HashMap, - pub values: HashMap, - pub completed_blocks: HashSet, - pub functions: Vec, + pub blocks: HashMap, + pub values: HashMap, + pub completed_blocks: HashSet, + pub functions: Vec, - pub types: LLVMTypeStorage, + pub types: LLVMTypeStorage, - pub module: Module<'static>, + pub module: Module<'static>, - pub void_type: VoidType<'static>, - - pub ctx: Rc, - pub builder: Builder<'static> + pub void_type: VoidType<'static>, + pub ctx: Rc, + pub builder: Builder<'static>, } impl LLVMBridgeContext { - pub fn new(ctx: Rc) -> Self { - LLVMBridgeContext { - blocks: HashMap::new(), - completed_blocks: HashSet::new(), - types: LLVMTypeStorage::new(&ctx), - functions: vec![], - void_type: unsafe { transmute::>(ctx.void_type())}, - values: HashMap::new(), - ctx: ctx.clone(), - builder: unsafe { transmute::>(ctx.create_builder())}, - module: unsafe { transmute::>(ctx.create_module("")) } - } - } -} \ No newline at end of file + pub fn new(ctx: Rc) -> Self { + LLVMBridgeContext { + blocks: HashMap::new(), + completed_blocks: HashSet::new(), + types: LLVMTypeStorage::new(&ctx), + functions: vec![], + void_type: unsafe { transmute::>(ctx.void_type()) }, + values: HashMap::new(), + ctx: ctx.clone(), + builder: unsafe { transmute::>(ctx.create_builder()) }, + module: unsafe { transmute::>(ctx.create_module("")) }, + } + } +} diff --git a/compiler/llvm_ir_bridge/src/funcs.rs b/compiler/llvm_ir_bridge/src/funcs.rs index 0746dcf..b48aab5 100644 --- a/compiler/llvm_ir_bridge/src/funcs.rs +++ b/compiler/llvm_ir_bridge/src/funcs.rs @@ -3,31 +3,37 @@ use std::mem::transmute; use astoir_mir::ctx::MIRContext; use inkwell::{basic_block::BasicBlock, types::BasicType}; -use crate::{ctx::LLVMBridgeContext, utils::{LLVMBlock, LLVMFunction}}; +use crate::{ + ctx::LLVMBridgeContext, + utils::{LLVMBlock, LLVMFunction}, +}; pub fn bridge_llvm_functions(mir: &MIRContext, bridge: &mut LLVMBridgeContext) { - for func in &mir.functions { - let mut args = vec![]; - - if !func.blocks.is_empty() { - for arg in &func.arguments { - args.push(bridge.types.convert(arg.clone()).inner.into()); - } - } - - let t = match &func.return_type { - Some(ret) => bridge.types.convert(ret.clone()).fn_type(&args, false), - None => bridge.void_type.fn_type(&args, false) - }; - - let ff = bridge.module.add_function(&func.name.val, t, None); - - for block in &func.blocks { - let b = bridge.ctx.append_basic_block(ff, ""); - - bridge.blocks.insert(*block, LLVMBlock::new(unsafe { transmute::>(b) })); - } - - bridge.functions.push(LLVMFunction::new(ff)); - } -} \ No newline at end of file + for func in &mir.functions { + let mut args = vec![]; + + if !func.blocks.is_empty() { + for arg in &func.arguments { + args.push(bridge.types.convert(arg.clone()).inner.into()); + } + } + + let t = match &func.return_type { + Some(ret) => bridge.types.convert(ret.clone()).fn_type(&args, false), + None => bridge.void_type.fn_type(&args, false), + }; + + let ff = bridge.module.add_function(&func.name.val, t, None); + + for block in &func.blocks { + let b = bridge.ctx.append_basic_block(ff, ""); + + bridge.blocks.insert( + *block, + LLVMBlock::new(unsafe { transmute::>(b) }), + ); + } + + bridge.functions.push(LLVMFunction::new(ff)); + } +} diff --git a/compiler/llvm_ir_bridge/src/insts.rs b/compiler/llvm_ir_bridge/src/insts.rs index 4776f66..ad7edc2 100644 --- a/compiler/llvm_ir_bridge/src/insts.rs +++ b/compiler/llvm_ir_bridge/src/insts.rs @@ -1,703 +1,966 @@ -use astoir_mir::{blocks::MIRBlockHeldInstruction, ctx::MIRContext, insts::{MIRInstruction}, vals::{base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}}; -use compiler_typing::{raw::RawType}; -use inkwell::{IntPredicate, module::Linkage, types::{BasicType, BasicTypeEnum, StringRadix}, values::{BasicValue, BasicValueEnum, FastMathFlags, FloatValue, IntValue}}; +use astoir_mir::{ + blocks::MIRBlockHeldInstruction, + ctx::MIRContext, + insts::MIRInstruction, + vals::{base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue}, +}; +use compiler_typing::raw::RawType; +use inkwell::{ + IntPredicate, + module::Linkage, + types::{BasicType, BasicTypeEnum, StringRadix}, + values::{BasicValue, BasicValueEnum, FastMathFlags, FloatValue, IntValue}, +}; use crate::{ctx::LLVMBridgeContext, llvm_to_base, llvm_to_base_returnless, utils::LLVMBasicValue}; -pub fn bridge_llvm_instruction(instruction: MIRBlockHeldInstruction, func: usize, bridge: &mut LLVMBridgeContext, mir: &MIRContext) -> Option { +pub fn bridge_llvm_instruction( + instruction: MIRBlockHeldInstruction, + func: usize, + bridge: &mut LLVMBridgeContext, + mir: &MIRContext, +) -> Option { + let res: Option> = + match MIRInstruction::from(instruction.clone().into()) { + MIRInstruction::StackAlloc { alloc_size: _, t } => { + let res = llvm_to_base!( + bridge + .builder + .build_alloca(bridge.types.convert(t).inner, "") + ); + + Some(res.into()) + } + + MIRInstruction::Load { value } => { + let base = BaseMIRValue::from(value.into()); + + let res = llvm_to_base!( + bridge.builder.build_load( + bridge + .types + .convert(mir.ssa_hints.get_hint(base.get_ssa_index()).get_type()) + .inner, + bridge.values[&base.get_ssa_index()].into_pointer_value(), + &format!("{}", instruction.as_valuedindex()) + ) + ); + + Some(res.into()) + } + + MIRInstruction::Store { variable, value } => { + let base = BaseMIRValue::from(variable.into()); + let ptr = bridge.values[&base.get_ssa_index()].into_pointer_value(); + + let val = bridge.values[&value.get_ssa_index()].inner; + + llvm_to_base_returnless!(bridge.builder.build_store(ptr, val)); + + None + } + + MIRInstruction::IntegerAdd { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRIntValue::into(left); + let right: BaseMIRValue = MIRIntValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res = llvm_to_base!(bridge.builder.build_int_add( + l.into_int_value(), + r.into_int_value(), + "" + )); + + if fast { + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); + } + + Some(res.into()) + } + + MIRInstruction::IntegerSub { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRIntValue::into(left); + let right: BaseMIRValue = MIRIntValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_sub( + l.into_int_value(), + r.into_int_value(), + "" + )); + + if fast { + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); + } + + Some(res.into()) + } + + MIRInstruction::IntegerMul { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRIntValue::into(left); + let right: BaseMIRValue = MIRIntValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_mul( + l.into_int_value(), + r.into_int_value(), + "" + )); + + if fast { + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); + } + + Some(res.into()) + } + + MIRInstruction::IntegerDiv { + signed, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRIntValue::into(left); + let right: BaseMIRValue = MIRIntValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static>; + + if signed { + res = llvm_to_base!(bridge.builder.build_int_signed_div( + l.into_int_value(), + r.into_int_value(), + "" + )) + } else { + res = llvm_to_base!(bridge.builder.build_int_unsigned_div( + l.into_int_value(), + r.into_int_value(), + "" + )) + } + + if fast { + let res2 = res.as_instruction_value().unwrap(); + + llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); + llvm_to_base_returnless!(res2.set_exact_flag(true)); + } + Some(res.into()) + } + + MIRInstruction::IntegerMod { + signed, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRIntValue::into(left); + let right: BaseMIRValue = MIRIntValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static>; + + if signed { + res = llvm_to_base!(bridge.builder.build_int_signed_rem( + l.into_int_value(), + r.into_int_value(), + "" + )) + } else { + res = llvm_to_base!(bridge.builder.build_int_unsigned_rem( + l.into_int_value(), + r.into_int_value(), + "" + )) + } + + if fast { + llvm_to_base_returnless!( + res.as_instruction_value() + .unwrap() + .set_fast_math_flags(FastMathFlags::all()) + ) + } + + Some(res.into()) + } + + MIRInstruction::FloatAdd { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRFloatValue::into(left); + let right: BaseMIRValue = MIRFloatValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_add( + l.into_float_value(), + r.into_float_value(), + "" + )); + + if fast { + llvm_to_base_returnless!( + res.as_instruction_value() + .unwrap() + .set_fast_math_flags(FastMathFlags::all()) + ) + } + + Some(res.into()) + } + + MIRInstruction::FloatSub { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRFloatValue::into(left); + let right: BaseMIRValue = MIRFloatValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_sub( + l.into_float_value(), + r.into_float_value(), + "" + )); + + if fast { + llvm_to_base_returnless!( + res.as_instruction_value() + .unwrap() + .set_fast_math_flags(FastMathFlags::all()) + ) + } + + Some(res.into()) + } + + MIRInstruction::FloatMul { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRFloatValue::into(left); + let right: BaseMIRValue = MIRFloatValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_mul( + l.into_float_value(), + r.into_float_value(), + "" + )); + + if fast { + llvm_to_base_returnless!( + res.as_instruction_value() + .unwrap() + .set_fast_math_flags(FastMathFlags::all()) + ) + } + + Some(res.into()) + } + + MIRInstruction::FloatDiv { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRFloatValue::into(left); + let right: BaseMIRValue = MIRFloatValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_div( + l.into_float_value(), + r.into_float_value(), + "" + )); + + if fast { + llvm_to_base_returnless!( + res.as_instruction_value() + .unwrap() + .set_fast_math_flags(FastMathFlags::all()) + ) + } + + Some(res.into()) + } + + MIRInstruction::FloatMod { + signed: _, + fast, + left, + right, + } => { + let left: BaseMIRValue = MIRFloatValue::into(left); + let right: BaseMIRValue = MIRFloatValue::into(right); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_rem( + l.into_float_value(), + r.into_float_value(), + "" + )); + + if fast { + llvm_to_base_returnless!( + res.as_instruction_value() + .unwrap() + .set_fast_math_flags(FastMathFlags::all()) + ) + } + + Some(res.into()) + } + + MIRInstruction::BitwiseAnd { a, b } => { + let left: BaseMIRValue = MIRIntValue::into(a); + let right: BaseMIRValue = MIRIntValue::into(b); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_and( + l.into_int_value(), + r.into_int_value(), + "" + )); + + Some(res.into()) + } + + MIRInstruction::BitwiseOr { a, b } => { + let left: BaseMIRValue = MIRIntValue::into(a); + let right: BaseMIRValue = MIRIntValue::into(b); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_or( + l.into_int_value(), + r.into_int_value(), + "" + )); + + Some(res.into()) + } + + MIRInstruction::BitwiseXor { a, b } => { + let left: BaseMIRValue = MIRIntValue::into(a); + let right: BaseMIRValue = MIRIntValue::into(b); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_xor( + l.into_int_value(), + r.into_int_value(), + "" + )); + + Some(res.into()) + } + + MIRInstruction::BitwiseNot { val } => { + let val: BaseMIRValue = MIRIntValue::into(val); + + let v = bridge.values[&val.get_ssa_index()].clone(); + + let res: IntValue<'static> = + llvm_to_base!(bridge.builder.build_not(v.into_int_value(), "e")); + + Some(res.into()) + } + + MIRInstruction::ShiftLeft { a, shift } => { + let val: BaseMIRValue = MIRIntValue::into(a); + let shift: BaseMIRValue = MIRIntValue::into(shift); + + let v = bridge.values[&val.get_ssa_index()].clone(); + let shift = bridge.values[&shift.get_ssa_index()].clone(); + + let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_left_shift( + v.into_int_value(), + shift.into_int_value(), + "" + )); + + Some(res.into()) + } + + // TODO: add toggle between artithmetic & logical + MIRInstruction::ShiftRight { a, shift } => { + let signed = a.signed; + + let val: BaseMIRValue = MIRIntValue::into(a); + let shift: BaseMIRValue = MIRIntValue::into(shift); + + let v = bridge.values[&val.get_ssa_index()].clone(); + let shift = bridge.values[&shift.get_ssa_index()].clone(); + + let res = llvm_to_base!(bridge.builder.build_right_shift( + v.into_int_value(), + shift.into_int_value(), + signed, + "" + )); + + Some(res.into()) + } - let res: Option> = match MIRInstruction::from(instruction.clone().into()) { - MIRInstruction::StackAlloc { alloc_size: _, t } => { - let res = llvm_to_base!(bridge.builder.build_alloca(bridge.types.convert(t).inner, "")); - - Some(res.into()) - }, + MIRInstruction::CompEq { a, b } => { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::EQ, bridge).into()) + } + MIRInstruction::CompNeg { a, b } => { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::EQ, bridge).into()) + } + MIRInstruction::CompLt { a, b } => { + if a.signed { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::SLT, bridge).into()) + } else { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::ULT, bridge).into()) + } + } - MIRInstruction::Load { value } => { - let base = BaseMIRValue::from(value.into()); + MIRInstruction::CompLe { a, b } => { + if a.signed { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::SLE, bridge).into()) + } else { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::ULE, bridge).into()) + } + } - let res = llvm_to_base!(bridge.builder.build_load(bridge.types.convert(mir.ssa_hints.get_hint(base.get_ssa_index()).get_type()).inner, bridge.values[&base.get_ssa_index()].into_pointer_value(), &format!("{}", instruction.as_valuedindex()))); - - Some(res.into()) - }, + MIRInstruction::CompGt { a, b } => { + if a.signed { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::SGT, bridge).into()) + } else { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::UGT, bridge).into()) + } + } - MIRInstruction::Store { variable, value } => { - let base = BaseMIRValue::from(variable.into()); - let ptr = bridge.values[&base.get_ssa_index()].into_pointer_value(); + MIRInstruction::CompGe { a, b } => { + if a.signed { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::SLE, bridge).into()) + } else { + Some(bridge_llvm_int_cmp(a, b, IntPredicate::ULE, bridge).into()) + } + } - let val = bridge.values[&value.get_ssa_index()].inner; - - llvm_to_base_returnless!(bridge.builder.build_store(ptr, val)); - - None - } - - MIRInstruction::IntegerAdd { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRIntValue::into(left); - let right: BaseMIRValue = MIRIntValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); - - let res = llvm_to_base!(bridge.builder.build_int_add(l.into_int_value(), r.into_int_value(), "")); - - if fast { - let res2 = res.as_instruction_value().unwrap(); - - llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); - llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); - } - - Some(res.into()) - }, - - MIRInstruction::IntegerSub { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRIntValue::into(left); - let right: BaseMIRValue = MIRIntValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); - - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_sub(l.into_int_value(), r.into_int_value(), "")); - - if fast { - let res2 = res.as_instruction_value().unwrap(); - - llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); - llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); - } - - Some(res.into()) - }, + MIRInstruction::IntegerSignedConstant { raw, bitsize } => { + let t = RawType::Integer(bitsize, true); - MIRInstruction::IntegerMul { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRIntValue::into(left); - let right: BaseMIRValue = MIRIntValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + let int_type = bridge.types.convert_raw(t).into_int_type(); + let res = int_type + .const_int_from_string(&raw.to_string(), StringRadix::Decimal) + .unwrap(); - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_int_mul(l.into_int_value(), r.into_int_value(), "")); - - if fast { - let res2 = res.as_instruction_value().unwrap(); + Some(res.into()) + } - llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); - llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); - } + MIRInstruction::IntegerUnsignedConstant { raw, bitsize } => { + let t = RawType::Integer(bitsize, false); - Some(res.into()) - }, - - MIRInstruction::IntegerDiv { signed, fast, left, right } => { - let left: BaseMIRValue = MIRIntValue::into(left); - let right: BaseMIRValue = MIRIntValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); - - let res: IntValue<'static>; + let int_type = bridge.types.convert_raw(t).into_int_type(); + let res = int_type + .const_int_from_string(&raw.to_string(), StringRadix::Decimal) + .unwrap(); - if signed { - res = llvm_to_base!(bridge.builder.build_int_signed_div(l.into_int_value(), r.into_int_value(), "")) - } else { - res = llvm_to_base!(bridge.builder.build_int_unsigned_div(l.into_int_value(), r.into_int_value(), "")) - } - - if fast { - let res2 = res.as_instruction_value().unwrap(); - - llvm_to_base_returnless!(res2.set_no_signed_wrap_flag(true)); - llvm_to_base_returnless!(res2.set_no_unsigned_wrap_flag(true)); - llvm_to_base_returnless!(res2.set_exact_flag(true)); - } - Some(res.into()) - }, - - MIRInstruction::IntegerMod { signed, fast, left, right } => { - let left: BaseMIRValue = MIRIntValue::into(left); - let right: BaseMIRValue = MIRIntValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + Some(res.into()) + } - let res: IntValue<'static>; + MIRInstruction::FloatSignedConstant { raw, size } => { + let t = RawType::Floating(size, true); - if signed { - res = llvm_to_base!(bridge.builder.build_int_signed_rem(l.into_int_value(), r.into_int_value(), "")) - } else { - res = llvm_to_base!(bridge.builder.build_int_unsigned_rem(l.into_int_value(), r.into_int_value(), "")) - } - - if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } - - Some(res.into()) - } + let float_type = bridge.types.convert_raw(t).into_float_type(); - MIRInstruction::FloatAdd { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRFloatValue::into(left); - let right: BaseMIRValue = MIRFloatValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); - - let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_add(l.into_float_value(), r.into_float_value(), "")); - - if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } - - Some(res.into()) - }, - - MIRInstruction::FloatSub { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRFloatValue::into(left); - let right: BaseMIRValue = MIRFloatValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + let res = unsafe { float_type.const_float_from_string(&raw.to_string()) }; - let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_sub(l.into_float_value(), r.into_float_value(), "")); + Some(res.into()) + } - if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } + MIRInstruction::FloatUnsignedConstant { raw, size } => { + let t = RawType::Floating(size, false); - Some(res.into()) - }, + let float_type = bridge.types.convert_raw(t).into_float_type(); - MIRInstruction::FloatMul { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRFloatValue::into(left); - let right: BaseMIRValue = MIRFloatValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + let res = unsafe { float_type.const_float_from_string(&raw.to_string()) }; - let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_mul(l.into_float_value(), r.into_float_value(), "")); + Some(res.into()) + } - if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } + MIRInstruction::FixedSignedConstant { .. } + | MIRInstruction::FixedUnsignedConstant { .. } => { + panic!("fixed points numbers are not currently supported") + } - Some(res.into()) - }, + MIRInstruction::StaticStringConstant { raw } => { + let bytes = raw.as_bytes(); + let byte_type = bridge + .types + .convert_raw(RawType::Integer(8, false)) + .into_int_type(); - MIRInstruction::FloatDiv { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRFloatValue::into(left); - let right: BaseMIRValue = MIRFloatValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + let arr_type = byte_type.array_type((bytes.len() + 1) as u32); - let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_div(l.into_float_value(), r.into_float_value(), "")); + let global = bridge.module.add_global(arr_type, None, ""); - if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } + global.set_linkage(Linkage::Private); + global.set_constant(true); + global.set_unnamed_addr(true); - Some(res.into()) - }, + let mut vals: Vec = bytes + .iter() + .map(|b| byte_type.const_int(*b as u64, false)) + .collect(); - MIRInstruction::FloatMod { signed: _, fast, left, right } => { - let left: BaseMIRValue = MIRFloatValue::into(left); - let right: BaseMIRValue = MIRFloatValue::into(right); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + vals.push(byte_type.const_zero()); - let res: FloatValue<'static> = llvm_to_base!(bridge.builder.build_float_rem(l.into_float_value(), r.into_float_value(), "")); + global.set_initializer(&byte_type.const_array(&vals)); - if fast { - llvm_to_base_returnless!(res.as_instruction_value().unwrap().set_fast_math_flags(FastMathFlags::all())) - } + Some(global.as_pointer_value().into()) + } - Some(res.into()) - } + MIRInstruction::StructInitializerConstant { + struct_type, + values, + } => { + let t = bridge.types.convert_raw(struct_type).into_struct_type(); - MIRInstruction::BitwiseAnd { a, b } => { - let left: BaseMIRValue = MIRIntValue::into(a); - let right: BaseMIRValue = MIRIntValue::into(b); + let mut vals = vec![]; - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + for value in values { + vals.push(bridge.values[&value.get_ssa_index()].clone().inner); + } - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_and(l.into_int_value(), r.into_int_value(), "")); - - Some(res.into()) - }, + let val = t.const_named_struct(&vals).into(); - MIRInstruction::BitwiseOr { a, b } => { - let left: BaseMIRValue = MIRIntValue::into(a); - let right: BaseMIRValue = MIRIntValue::into(b); + Some(val) + } - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + MIRInstruction::ArrayInitializerConstant { values } => { + let k = bridge.types.convert(values[0].vtype.clone()); - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_or(l.into_int_value(), r.into_int_value(), "")); - - Some(res.into()) - } + let ke = match k.as_basic_type_enum() { + BasicTypeEnum::IntType(v) => { + let mut vals = vec![]; - MIRInstruction::BitwiseXor { a, b } => { - let left: BaseMIRValue = MIRIntValue::into(a); - let right: BaseMIRValue = MIRIntValue::into(b); + for value in values { + vals.push(bridge.values[&value.get_ssa_index()].into_int_value()) + } - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); + v.const_array(&vals) + } - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_xor(l.into_int_value(), r.into_int_value(), "")); - - Some(res.into()) - }, + BasicTypeEnum::FloatType(v) => { + let mut vals = vec![]; - MIRInstruction::BitwiseNot { val } => { - let val: BaseMIRValue = MIRIntValue::into(val); + for value in values { + vals.push(bridge.values[&value.get_ssa_index()].into_float_value()) + } - let v = bridge.values[&val.get_ssa_index()].clone(); + v.const_array(&vals) + } - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_not(v.into_int_value(), "e")); + BasicTypeEnum::ArrayType(v) => { + let mut vals = vec![]; - Some(res.into()) - }, + for value in values { + vals.push(bridge.values[&value.get_ssa_index()].into_array_value()) + } - MIRInstruction::ShiftLeft { a, shift } => { - let val: BaseMIRValue = MIRIntValue::into(a); - let shift: BaseMIRValue = MIRIntValue::into(shift); + v.const_array(&vals) + } - let v = bridge.values[&val.get_ssa_index()].clone(); - let shift = bridge.values[&shift.get_ssa_index()].clone(); + BasicTypeEnum::PointerType(v) => { + let mut vals = vec![]; - let res: IntValue<'static> = llvm_to_base!(bridge.builder.build_left_shift(v.into_int_value(), shift.into_int_value(), "")); + for value in values { + vals.push(bridge.values[&value.get_ssa_index()].into_pointer_value()) + } - Some(res.into()) - }, + v.const_array(&vals) + } - // TODO: add toggle between artithmetic & logical - MIRInstruction::ShiftRight { a, shift } => { - let signed = a.signed; + BasicTypeEnum::StructType(v) => { + let mut vals = vec![]; - let val: BaseMIRValue = MIRIntValue::into(a); - let shift: BaseMIRValue = MIRIntValue::into(shift); + for value in values { + vals.push(bridge.values[&value.get_ssa_index()].into_struct_value()) + } - let v = bridge.values[&val.get_ssa_index()].clone(); - let shift = bridge.values[&shift.get_ssa_index()].clone(); + v.const_array(&vals) + } - let res = llvm_to_base!(bridge.builder.build_right_shift(v.into_int_value(), shift.into_int_value(), signed, "")); + _ => panic!("got invalid LLVM type"), + }; - Some(res.into()) - }, + Some(ke.into()) + } - MIRInstruction::CompEq { a, b } => Some(bridge_llvm_int_cmp(a, b, IntPredicate::EQ, bridge).into()), - MIRInstruction::CompNeg { a, b } => Some(bridge_llvm_int_cmp(a, b, IntPredicate::EQ, bridge).into()), - MIRInstruction::CompLt { a, b } => { - if a.signed { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::SLT, bridge).into()) - } else { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::ULT, bridge).into()) - } - }, + MIRInstruction::ArrayInitializerConstantSame { size, val } => { + let k = bridge.types.convert(val.vtype.clone()); - MIRInstruction::CompLe { a, b } => { - if a.signed { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::SLE, bridge).into()) - } else { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::ULE, bridge).into()) - } - }, + let ke = match k.as_basic_type_enum() { + BasicTypeEnum::IntType(v) => { + let mut vals = vec![]; - MIRInstruction::CompGt { a, b } => { - if a.signed { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::SGT, bridge).into()) - } else { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::UGT, bridge).into()) - } - }, + for _ in 0..size { + vals.push(bridge.values[&val.get_ssa_index()].into_int_value()) + } - MIRInstruction::CompGe { a, b } => { - if a.signed { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::SLE, bridge).into()) - } else { - Some(bridge_llvm_int_cmp(a, b, IntPredicate::ULE, bridge).into()) - } - }, + v.const_array(&vals) + } - MIRInstruction::IntegerSignedConstant { raw, bitsize } => { - let t = RawType::Integer(bitsize, true); + BasicTypeEnum::FloatType(v) => { + let mut vals = vec![]; - let int_type = bridge.types.convert_raw(t).into_int_type(); - let res = int_type.const_int_from_string(&raw.to_string(), StringRadix::Decimal).unwrap(); + for _ in 0..size { + vals.push(bridge.values[&val.get_ssa_index()].into_float_value()) + } - Some(res.into()) - }, + v.const_array(&vals) + } - MIRInstruction::IntegerUnsignedConstant { raw, bitsize } => { - let t = RawType::Integer(bitsize, false); + BasicTypeEnum::StructType(v) => { + let mut vals = vec![]; - let int_type = bridge.types.convert_raw(t).into_int_type(); - let res = int_type.const_int_from_string(&raw.to_string(), StringRadix::Decimal).unwrap(); + for _ in 0..size { + vals.push(bridge.values[&val.get_ssa_index()].into_struct_value()) + } - Some(res.into()) - }, + v.const_array(&vals) + } - MIRInstruction::FloatSignedConstant { raw, size } => { - let t = RawType::Floating(size, true); + BasicTypeEnum::ArrayType(v) => { + let mut vals = vec![]; - let float_type = bridge.types.convert_raw(t).into_float_type(); + for _ in 0..size { + vals.push(bridge.values[&val.get_ssa_index()].into_array_value()) + } - let res = unsafe { float_type.const_float_from_string(&raw.to_string()) }; + v.const_array(&vals) + } - Some(res.into()) - }, + BasicTypeEnum::PointerType(v) => { + let mut vals = vec![]; - MIRInstruction::FloatUnsignedConstant { raw, size } => { - let t = RawType::Floating(size, false); + for _ in 0..size { + vals.push(bridge.values[&val.get_ssa_index()].into_pointer_value()) + } - let float_type = bridge.types.convert_raw(t).into_float_type(); + v.const_array(&vals) + } - let res = unsafe { float_type.const_float_from_string(&raw.to_string()) }; + _ => panic!("got invalid LLVM type"), + }; - Some(res.into()) - }, + Some(ke.into()) + } - MIRInstruction::FixedSignedConstant { .. } | MIRInstruction::FixedUnsignedConstant { .. } => { - panic!("fixed points numbers are not currently supported") - }, + MIRInstruction::Return { val } => { + if val.is_some() { + let v = bridge.values[&val.unwrap().get_ssa_index()].clone(); - MIRInstruction::StaticStringConstant { raw } => { - let bytes = raw.as_bytes(); - let byte_type = bridge.types.convert_raw(RawType::Integer(8, false)).into_int_type(); + llvm_to_base_returnless!(bridge.builder.build_return(Some(&v.inner))); + } else { + llvm_to_base_returnless!(bridge.builder.build_return(None)); + } - let arr_type = byte_type.array_type((bytes.len() + 1) as u32); + None + } - let global = bridge.module.add_global(arr_type, None, ""); + MIRInstruction::UnconditionalBranch { branch } => { + let block = bridge.blocks[&branch].clone(); - global.set_linkage(Linkage::Private); - global.set_constant(true); - global.set_unnamed_addr(true); + llvm_to_base_returnless!(bridge.builder.build_unconditional_branch(block.inner)); - let mut vals: Vec = bytes.iter().map(|b| byte_type.const_int(*b as u64, false)).collect(); + None + } - vals.push(byte_type.const_zero()); + MIRInstruction::ConditionalBranch { + cond, + if_branch, + else_branch, + } => { + let cond: BaseMIRValue = MIRIntValue::into(cond); - global.set_initializer(&byte_type.const_array(&vals)); - - Some(global.as_pointer_value().into()) - }, + let cond = bridge.values[&cond.get_ssa_index()] + .clone() + .into_int_value(); - MIRInstruction::StructInitializerConstant { struct_type, values } => { - let t = bridge.types.convert_raw(struct_type).into_struct_type(); + let if_branch = bridge.blocks[&if_branch].clone(); + let else_branch = bridge.blocks[&else_branch].clone(); - let mut vals = vec![]; - - for value in values { - vals.push(bridge.values[&value.get_ssa_index()].clone().inner); - } + llvm_to_base_returnless!(bridge.builder.build_conditional_branch( + cond, + if_branch.inner, + else_branch.inner + )); - let val = t.const_named_struct(&vals).into(); + None + } - Some(val) - }, + MIRInstruction::Phi { choices } => { + let mut llvm_choices = vec![]; - MIRInstruction::ArrayInitializerConstant { values } => { - let k = bridge.types.convert(values[0].vtype.clone()); + let t = bridge.types.convert(choices[0].1.vtype.clone()); - let ke = match k.as_basic_type_enum() { + for choice in choices { + let block = bridge.blocks[&choice.0].clone().inner; + let value = bridge.values[&choice.1.get_ssa_index()] + .inner + .as_basic_value_enum(); - BasicTypeEnum::IntType(v) => { - let mut vals = vec![]; + llvm_choices.push((value, block)); + } - for value in values { - vals.push(bridge.values[&value.get_ssa_index()].into_int_value()) - } + let phi = llvm_to_base!(bridge.builder.build_phi(t.inner, "")); - v.const_array(&vals) - }, - - BasicTypeEnum::FloatType(v) => { - let mut vals = vec![]; + for choice in llvm_choices { + phi.add_incoming(&[(&choice.0 as &dyn BasicValue, choice.1)]); + } - for value in values { - vals.push(bridge.values[&value.get_ssa_index()].into_float_value()) - } + Some(phi.as_basic_value()) + } - v.const_array(&vals) - }, - - BasicTypeEnum::ArrayType(v) => { - let mut vals = vec![]; + MIRInstruction::Select { + cond, + if_val, + else_val, + } => { + let cond: BaseMIRValue = MIRIntValue::into(cond); + + let cond = bridge.values[&cond.get_ssa_index()] + .clone() + .into_int_value(); + + let if_val = bridge.values[&if_val.get_ssa_index()].inner; + let else_val = bridge.values[&else_val.get_ssa_index()].inner; + + let res = llvm_to_base!(bridge.builder.build_select(cond, if_val, else_val, "")); + + Some(res) + } + + MIRInstruction::FieldPointer { val, field } => { + let val: BaseMIRValue = MIRPointerValue::into(val); + let struct_type = bridge + .types + .convert(mir.ssa_hints.get_hint(val.get_ssa_index()).get_type()) + .inner; + + let ptr_val = bridge.values[&val.get_ssa_index()].inner; - for value in values { - vals.push(bridge.values[&value.get_ssa_index()].into_array_value()) - } + let res = llvm_to_base!(bridge.builder.build_struct_gep( + struct_type, + ptr_val.into_pointer_value(), + field as u32, + "" + )); + + Some(res.into()) + } - v.const_array(&vals) - }, - - BasicTypeEnum::PointerType(v) => { - let mut vals = vec![]; - - for value in values { - vals.push(bridge.values[&value.get_ssa_index()].into_pointer_value()) - } - - v.const_array(&vals) - }, - - - BasicTypeEnum::StructType(v) => { - let mut vals = vec![]; - - for value in values { - vals.push(bridge.values[&value.get_ssa_index()].into_struct_value()) - } - - v.const_array(&vals) - }, - - _ => panic!("got invalid LLVM type") - }; - - Some(ke.into()) - }, - - MIRInstruction::ArrayInitializerConstantSame { size, val } => { - let k = bridge.types.convert(val.vtype.clone()); - - let ke = match k.as_basic_type_enum() { - - BasicTypeEnum::IntType(v) => { - let mut vals = vec![]; - - for _ in 0..size { - vals.push(bridge.values[&val.get_ssa_index()].into_int_value()) - } - - v.const_array(&vals) - }, - - BasicTypeEnum::FloatType(v) => { - let mut vals = vec![]; - - for _ in 0..size { - vals.push(bridge.values[&val.get_ssa_index()].into_float_value()) - } - - v.const_array(&vals) - }, - - BasicTypeEnum::StructType(v) => { - let mut vals = vec![]; - - for _ in 0..size { - vals.push(bridge.values[&val.get_ssa_index()].into_struct_value()) - } - - v.const_array(&vals) - }, - - BasicTypeEnum::ArrayType(v) => { - let mut vals = vec![]; - - for _ in 0..size { - vals.push(bridge.values[&val.get_ssa_index()].into_array_value()) - } - - v.const_array(&vals) - }, - - BasicTypeEnum::PointerType(v) => { - let mut vals = vec![]; - - for _ in 0..size { - vals.push(bridge.values[&val.get_ssa_index()].into_pointer_value()) - } - - v.const_array(&vals) - }, - - _ => panic!("got invalid LLVM type") - }; - - Some(ke.into()) - }, - - MIRInstruction::Return { val } => { - if val.is_some() { - let v = bridge.values[&val.unwrap().get_ssa_index()].clone(); - - llvm_to_base_returnless!(bridge.builder.build_return(Some(&v.inner))); - } else { - llvm_to_base_returnless!(bridge.builder.build_return(None)); - } - - None - }, - - MIRInstruction::UnconditionalBranch { branch } => { - let block = bridge.blocks[&branch].clone(); - - llvm_to_base_returnless!(bridge.builder.build_unconditional_branch(block.inner)); - - None - }, - - MIRInstruction::ConditionalBranch { cond, if_branch, else_branch } => { - let cond: BaseMIRValue = MIRIntValue::into(cond); - - let cond = bridge.values[&cond.get_ssa_index()].clone().into_int_value(); - - let if_branch = bridge.blocks[&if_branch].clone(); - let else_branch = bridge.blocks[&else_branch].clone(); - - llvm_to_base_returnless!(bridge.builder.build_conditional_branch(cond, if_branch.inner, else_branch.inner)); - - None - }, - - MIRInstruction::Phi { choices } => { - let mut llvm_choices = vec![]; - - let t = bridge.types.convert(choices[0].1.vtype.clone()); - - for choice in choices { - let block = bridge.blocks[&choice.0].clone().inner; - let value = bridge.values[&choice.1.get_ssa_index()].inner.as_basic_value_enum(); - - llvm_choices.push((value, block)); - } - - let phi = llvm_to_base!(bridge.builder.build_phi(t.inner, "")); - - for choice in llvm_choices { - phi.add_incoming(&[(&choice.0 as &dyn BasicValue, choice.1)]); - } - - Some(phi.as_basic_value()) - }, - - MIRInstruction::Select { cond, if_val, else_val } => { - let cond: BaseMIRValue = MIRIntValue::into(cond); - - let cond = bridge.values[&cond.get_ssa_index()].clone().into_int_value(); - - let if_val = bridge.values[&if_val.get_ssa_index()].inner; - let else_val = bridge.values[&else_val.get_ssa_index()].inner; - - let res = llvm_to_base!(bridge.builder.build_select(cond, if_val, else_val, "")); - - Some(res) - }, - - MIRInstruction::FieldPointer { val, field } => { - let val: BaseMIRValue = MIRPointerValue::into(val); - let struct_type = bridge.types.convert(mir.ssa_hints.get_hint(val.get_ssa_index()).get_type()).inner; - - let ptr_val = bridge.values[&val.get_ssa_index()].inner; - - let res = llvm_to_base!(bridge.builder.build_struct_gep(struct_type, ptr_val.into_pointer_value(), field as u32, "")); - - Some(res.into()) - }, - - MIRInstruction::IndexPointer { val, index } => { - let val: BaseMIRValue = MIRPointerValue::into(val); - let struct_type = bridge.types.convert(mir.ssa_hints.get_hint(val.get_ssa_index()).get_type()).inner; - - let index_type = bridge.types.convert_raw(RawType::Integer(32, false)).inner.into_int_type(); - - let ptr_val = bridge.values[&val.get_ssa_index()].inner; - - let index: BaseMIRValue = MIRIntValue::into(index); - let index = bridge.values[&index.get_ssa_index()].inner; - - let res = llvm_to_base!(unsafe { bridge.builder.build_in_bounds_gep(struct_type, ptr_val.into_pointer_value(), &[index_type.const_int(0, false), index.into_int_value()], "") }); - - Some(res.into()) - }, - - MIRInstruction::PointerAdd { pointer, right } => { - let pointer: BaseMIRValue = MIRPointerValue::into(pointer); - let right: BaseMIRValue = MIRIntValue::into(right); - let t = bridge.types.convert_raw(RawType::Integer(8, false)).inner; - - let pointer = bridge.values[&pointer.get_ssa_index()].inner; - let right = bridge.values[&right.get_ssa_index()].inner; - - let res = llvm_to_base!(unsafe { bridge.builder.build_in_bounds_gep(t, pointer.into_pointer_value(), &[right.into_int_value()], "") }); - - Some(res.into()) - }, - - MIRInstruction::PointerSub { pointer, right } => { - let pointer: BaseMIRValue = MIRPointerValue::into(pointer); - let right: BaseMIRValue = MIRIntValue::into(right); - let t = bridge.types.convert_raw(RawType::Integer(8, false)).inner; - - let pointer = bridge.values[&pointer.get_ssa_index()].inner; - let right = bridge.values[&right.get_ssa_index()].inner; - - let res = llvm_to_base!(unsafe { bridge.builder.build_in_bounds_gep(t, pointer.into_pointer_value(), &[right.into_int_value()], "") }); - - Some(res.into()) - }, - - MIRInstruction::Call { function, arguments } => { - let func = bridge.functions[function].clone().inner; - - let mut args = vec![]; - - for arg in arguments { - args.push(bridge.values[&arg.get_ssa_index()].inner.into()); - } - - let res = llvm_to_base!(bridge.builder.build_call(func, &args, "")); - - res.try_as_basic_value().basic() - }, - - MIRInstruction::FuncArgumentGrab { ind, argtype: _ } => { - let func = bridge.functions[func].clone().inner; - - func.get_nth_param(ind as u32) - }, - - MIRInstruction::MemoryCopy { src, dest, sz } => { - let src: BaseMIRValue = src.into(); - let dest: BaseMIRValue = dest.into(); - - let llvm_src = bridge.values[&src.get_ssa_index()].clone(); - let llvm_dest = bridge.values[&dest.get_ssa_index()].clone(); - - let sz_type = bridge.types.convert_raw(RawType::Integer(32, false)).into_int_type(); - let sz = sz_type.const_int(sz as u64, false); - - llvm_to_base_returnless!(bridge.builder.build_memcpy(llvm_dest.inner.into_pointer_value(), 1, llvm_src.into_pointer_value(), 1, sz)); - - None - }, - - MIRInstruction::IRCast { val, to: _ } => { - Some(bridge.values[&val.get_ssa_index()].inner.clone()) - } - - _ => None - }; - - if res.is_some() { - return Some(LLVMBasicValue::new(res.unwrap())) - } - - return None + MIRInstruction::IndexPointer { val, index } => { + let val: BaseMIRValue = MIRPointerValue::into(val); + let struct_type = bridge + .types + .convert(mir.ssa_hints.get_hint(val.get_ssa_index()).get_type()) + .inner; + + let index_type = bridge + .types + .convert_raw(RawType::Integer(32, false)) + .inner + .into_int_type(); + + let ptr_val = bridge.values[&val.get_ssa_index()].inner; + + let index: BaseMIRValue = MIRIntValue::into(index); + let index = bridge.values[&index.get_ssa_index()].inner; + + let res = llvm_to_base!(unsafe { + bridge.builder.build_in_bounds_gep( + struct_type, + ptr_val.into_pointer_value(), + &[index_type.const_int(0, false), index.into_int_value()], + "", + ) + }); + + Some(res.into()) + } + + MIRInstruction::PointerAdd { pointer, right } => { + let pointer: BaseMIRValue = MIRPointerValue::into(pointer); + let right: BaseMIRValue = MIRIntValue::into(right); + let t = bridge.types.convert_raw(RawType::Integer(8, false)).inner; + + let pointer = bridge.values[&pointer.get_ssa_index()].inner; + let right = bridge.values[&right.get_ssa_index()].inner; + + let res = llvm_to_base!(unsafe { + bridge.builder.build_in_bounds_gep( + t, + pointer.into_pointer_value(), + &[right.into_int_value()], + "", + ) + }); + + Some(res.into()) + } + + MIRInstruction::PointerSub { pointer, right } => { + let pointer: BaseMIRValue = MIRPointerValue::into(pointer); + let right: BaseMIRValue = MIRIntValue::into(right); + let t = bridge.types.convert_raw(RawType::Integer(8, false)).inner; + + let pointer = bridge.values[&pointer.get_ssa_index()].inner; + let right = bridge.values[&right.get_ssa_index()].inner; + + let res = llvm_to_base!(unsafe { + bridge.builder.build_in_bounds_gep( + t, + pointer.into_pointer_value(), + &[right.into_int_value()], + "", + ) + }); + + Some(res.into()) + } + + MIRInstruction::Call { + function, + arguments, + } => { + let func = bridge.functions[function].clone().inner; + + let mut args = vec![]; + + for arg in arguments { + args.push(bridge.values[&arg.get_ssa_index()].inner.into()); + } + + let res = llvm_to_base!(bridge.builder.build_call(func, &args, "")); + + res.try_as_basic_value().basic() + } + + MIRInstruction::FuncArgumentGrab { ind, argtype: _ } => { + let func = bridge.functions[func].clone().inner; + + func.get_nth_param(ind as u32) + } + + MIRInstruction::MemoryCopy { src, dest, sz } => { + let src: BaseMIRValue = src.into(); + let dest: BaseMIRValue = dest.into(); + + let llvm_src = bridge.values[&src.get_ssa_index()].clone(); + let llvm_dest = bridge.values[&dest.get_ssa_index()].clone(); + + let sz_type = bridge + .types + .convert_raw(RawType::Integer(32, false)) + .into_int_type(); + let sz = sz_type.const_int(sz as u64, false); + + llvm_to_base_returnless!(bridge.builder.build_memcpy( + llvm_dest.inner.into_pointer_value(), + 1, + llvm_src.into_pointer_value(), + 1, + sz + )); + + None + } + + MIRInstruction::IRCast { val, to: _ } => { + Some(bridge.values[&val.get_ssa_index()].inner.clone()) + } + + _ => None, + }; + + if res.is_some() { + return Some(LLVMBasicValue::new(res.unwrap())); + } + + return None; } -pub fn bridge_llvm_int_cmp(a: MIRIntValue, b: MIRIntValue, predicate: IntPredicate, bridge: &mut LLVMBridgeContext) -> IntValue<'static> { - let left: BaseMIRValue = MIRIntValue::into(a); - let right: BaseMIRValue = MIRIntValue::into(b); - - let l = bridge.values[&left.get_ssa_index()].clone(); - let r = bridge.values[&right.get_ssa_index()].clone(); - - return llvm_to_base!(bridge.builder.build_int_compare(predicate, l.into_int_value(), r.into_int_value(), "e")); -} \ No newline at end of file +pub fn bridge_llvm_int_cmp( + a: MIRIntValue, + b: MIRIntValue, + predicate: IntPredicate, + bridge: &mut LLVMBridgeContext, +) -> IntValue<'static> { + let left: BaseMIRValue = MIRIntValue::into(a); + let right: BaseMIRValue = MIRIntValue::into(b); + + let l = bridge.values[&left.get_ssa_index()].clone(); + let r = bridge.values[&right.get_ssa_index()].clone(); + + return llvm_to_base!(bridge.builder.build_int_compare( + predicate, + l.into_int_value(), + r.into_int_value(), + "e" + )); +} diff --git a/compiler/llvm_ir_bridge/src/lib.rs b/compiler/llvm_ir_bridge/src/lib.rs index 6d59925..d09f490 100644 --- a/compiler/llvm_ir_bridge/src/lib.rs +++ b/compiler/llvm_ir_bridge/src/lib.rs @@ -7,40 +7,40 @@ use inkwell::context::Context; use crate::{blocks::bridge_llvm_blocks, ctx::LLVMBridgeContext, funcs::bridge_llvm_functions}; -pub mod ctx; -pub mod utils; pub mod blocks; -pub mod types; +pub mod ctx; pub mod funcs; pub mod insts; +pub mod types; +pub mod utils; pub fn bridge_llvm(mir: &MIRContext) -> LLVMBridgeContext { - let ctx = Rc::new(Context::create()); + let ctx = Rc::new(Context::create()); - let mut ctx = LLVMBridgeContext::new(ctx); + let mut ctx = LLVMBridgeContext::new(ctx); - bridge_llvm_functions(mir, &mut ctx); - bridge_llvm_blocks(mir, &mut ctx); + bridge_llvm_functions(mir, &mut ctx); + bridge_llvm_blocks(mir, &mut ctx); - return ctx; + return ctx; } #[macro_export] -macro_rules! llvm_to_base { - ($exp:expr) => { - match $exp { - Ok(v) => v, - Err(_) => panic!("inkwell function failed") - } - }; +macro_rules! llvm_to_base { + ($exp:expr) => { + match $exp { + Ok(v) => v, + Err(_) => panic!("inkwell function failed"), + } + }; } #[macro_export] -macro_rules! llvm_to_base_returnless { - ($exp:expr) => { - match $exp { - Ok(_) => {}, - Err(_) => panic!("inkwell function failed") - } - }; -} \ No newline at end of file +macro_rules! llvm_to_base_returnless { + ($exp:expr) => { + match $exp { + Ok(_) => {} + Err(_) => panic!("inkwell function failed"), + } + }; +} diff --git a/compiler/llvm_ir_bridge/src/types.rs b/compiler/llvm_ir_bridge/src/types.rs index 19aac35..8e36270 100644 --- a/compiler/llvm_ir_bridge/src/types.rs +++ b/compiler/llvm_ir_bridge/src/types.rs @@ -1,88 +1,97 @@ use std::{collections::HashMap, mem::transmute, num::NonZero, rc::Rc}; use compiler_typing::{raw::RawType, tree::Type}; -use inkwell::{AddressSpace, context::Context, types::{BasicType, BasicTypeEnum}}; +use inkwell::{ + AddressSpace, + context::Context, + types::{BasicType, BasicTypeEnum}, +}; -use crate::{utils::LLVMTypeEnum}; +use crate::utils::LLVMTypeEnum; pub struct LLVMTypeStorage { - pub map: HashMap, + pub map: HashMap, - pub ctxref: Rc + pub ctxref: Rc, } impl LLVMTypeStorage { - pub fn new(ctx: &Rc) -> Self { - LLVMTypeStorage { map: HashMap::new(), ctxref: ctx.clone() } - } - - pub fn convert(&mut self, base: Type) -> LLVMTypeEnum { - match base { - Type::GenericLowered(raw) => return self.convert_raw(raw), - Type::Generic(_, _, _) => panic!("cannot convert unlowered generics"), - - Type::Reference(_) => return self.convert_raw(RawType::Pointer), - Type::Pointer(_, _) => return self.convert_raw(RawType::Pointer), - - Type::Array(size, inner) => { - let inner_type = self.convert(*inner); - - LLVMTypeEnum::new(inner_type.array_type(size as u32).into()) - } - } - } - - pub fn convert_raw(&mut self, base: RawType) -> LLVMTypeEnum { - if self.map.contains_key(&base) { - return LLVMTypeEnum::clone(&self.map[&base]) - } - - let conv: BasicTypeEnum = match &base { - RawType::Integer(a, _) => { - self.ctxref.custom_width_int_type(NonZero::new(*a as u32).unwrap()).unwrap().into() - }, - - RawType::Floating(a, _) => { - match a { - 16 => self.ctxref.f16_type().into(), - 32 => self.ctxref.f32_type().into(), - 64 => self.ctxref.f64_type().into(), - 80 => self.ctxref.x86_f80_type().into(), - 128 => self.ctxref.f128_type().into(), - - _ => panic!("cannot convert float to LLVM type") - } - }, - - RawType::LoweredStruct(layout, b) => { - let mut fields = vec![]; - - for field in &b.fields.vals { - fields.push(self.convert(field.clone()).inner); - } - - self.ctxref.struct_type(&fields, !*layout).into() - } - - RawType::FixedPoint(a, b, _) => { - let sum = a + b; - - self.ctxref.custom_width_int_type(NonZero::new(sum as u32).unwrap()).unwrap().into() - }, - - RawType::Boolean => self.ctxref.bool_type().into(), - - RawType::Pointer => { - self.ctxref.ptr_type(AddressSpace::from(0u16)).into() - }, - - _ => panic!("cannot convert to LLVM type!") - }; - - let l = LLVMTypeEnum::new(unsafe { transmute::>(conv) }); - - self.map.insert(base, l.clone()); - - return l - } -} \ No newline at end of file + pub fn new(ctx: &Rc) -> Self { + LLVMTypeStorage { + map: HashMap::new(), + ctxref: ctx.clone(), + } + } + + pub fn convert(&mut self, base: Type) -> LLVMTypeEnum { + match base { + Type::GenericLowered(raw) => return self.convert_raw(raw), + Type::Generic(_, _, _) => panic!("cannot convert unlowered generics"), + + Type::Reference(_) => return self.convert_raw(RawType::Pointer), + Type::Pointer(_, _) => return self.convert_raw(RawType::Pointer), + + Type::Array(size, inner) => { + let inner_type = self.convert(*inner); + + LLVMTypeEnum::new(inner_type.array_type(size as u32).into()) + } + } + } + + pub fn convert_raw(&mut self, base: RawType) -> LLVMTypeEnum { + if self.map.contains_key(&base) { + return LLVMTypeEnum::clone(&self.map[&base]); + } + + let conv: BasicTypeEnum = match &base { + RawType::Integer(a, _) => self + .ctxref + .custom_width_int_type(NonZero::new(*a as u32).unwrap()) + .unwrap() + .into(), + + RawType::Floating(a, _) => match a { + 16 => self.ctxref.f16_type().into(), + 32 => self.ctxref.f32_type().into(), + 64 => self.ctxref.f64_type().into(), + 80 => self.ctxref.x86_f80_type().into(), + 128 => self.ctxref.f128_type().into(), + + _ => panic!("cannot convert float to LLVM type"), + }, + + RawType::LoweredStruct(layout, b) => { + let mut fields = vec![]; + + for field in &b.fields.vals { + fields.push(self.convert(field.clone()).inner); + } + + self.ctxref.struct_type(&fields, !*layout).into() + } + + RawType::FixedPoint(a, b, _) => { + let sum = a + b; + + self.ctxref + .custom_width_int_type(NonZero::new(sum as u32).unwrap()) + .unwrap() + .into() + } + + RawType::Boolean => self.ctxref.bool_type().into(), + + RawType::Pointer => self.ctxref.ptr_type(AddressSpace::from(0u16)).into(), + + _ => panic!("cannot convert to LLVM type!"), + }; + + let l = + LLVMTypeEnum::new(unsafe { transmute::>(conv) }); + + self.map.insert(base, l.clone()); + + return l; + } +} diff --git a/compiler/llvm_ir_bridge/src/utils.rs b/compiler/llvm_ir_bridge/src/utils.rs index de1e288..1933bea 100644 --- a/compiler/llvm_ir_bridge/src/utils.rs +++ b/compiler/llvm_ir_bridge/src/utils.rs @@ -1,6 +1,11 @@ use std::{mem::transmute, ops::Deref, rc::Rc}; -use inkwell::{basic_block::BasicBlock, context::Context, types::{BasicMetadataTypeEnum, BasicTypeEnum, IntType, PointerType}, values::{BasicValueEnum, FunctionValue}}; +use inkwell::{ + basic_block::BasicBlock, + context::Context, + types::{BasicMetadataTypeEnum, BasicTypeEnum, IntType, PointerType}, + values::{BasicValueEnum, FunctionValue}, +}; use rand::{Rng, distributions::Alphanumeric}; pub type LLVMBlock = LLVMSiblingObject>; @@ -14,61 +19,78 @@ pub type LLVMMetadataEnum = LLVMSiblingObject>; #[derive(Clone)] pub struct LLVMObject { - pub inner: T, - pub ctx: Rc + pub inner: T, + pub ctx: Rc, } /// The LLVMObject without a safety reference. -/// +/// /// # Safety /// Using this is only safe when the object it is contained in contains a Context ref #[derive(Clone)] pub struct LLVMSiblingObject { - pub inner: T + pub inner: T, } impl LLVMSiblingObject { - pub fn new(inner: K) -> Self { - return LLVMSiblingObject { inner: unsafe { transmute(inner)}} - } - - pub fn new_ref(inner: &K) -> Self { - return LLVMSiblingObject { inner: unsafe { transmute(K::clone(inner)) }} - } + pub fn new(inner: K) -> Self { + return LLVMSiblingObject { + inner: unsafe { transmute(inner) }, + }; + } + + pub fn new_ref(inner: &K) -> Self { + return LLVMSiblingObject { + inner: unsafe { transmute(K::clone(inner)) }, + }; + } } impl LLVMObject { - pub fn new(ctx: &Rc, inner: K) -> Self { - return LLVMObject { inner: unsafe { transmute(inner)} , ctx: ctx.clone() } - } - - pub fn new_ref(ctx: &Rc, inner: &K) -> Self { - return LLVMObject { inner: unsafe { transmute(K::clone(inner)) }, ctx: ctx.clone() } - } - - pub fn new_ownership(ctx: Rc, inner: K) -> Self { - return LLVMObject { inner: unsafe {transmute(inner) }, ctx: ctx } - } + pub fn new(ctx: &Rc, inner: K) -> Self { + return LLVMObject { + inner: unsafe { transmute(inner) }, + ctx: ctx.clone(), + }; + } + + pub fn new_ref(ctx: &Rc, inner: &K) -> Self { + return LLVMObject { + inner: unsafe { transmute(K::clone(inner)) }, + ctx: ctx.clone(), + }; + } + + pub fn new_ownership(ctx: Rc, inner: K) -> Self { + return LLVMObject { + inner: unsafe { transmute(inner) }, + ctx: ctx, + }; + } } impl Deref for LLVMObject { - type Target = T; + type Target = T; - fn deref(&self) -> &Self::Target { - return &self.inner; - } + fn deref(&self) -> &Self::Target { + return &self.inner; + } } impl Deref for LLVMSiblingObject { - type Target = T; + type Target = T; - fn deref(&self) -> &Self::Target { - return &self.inner; - } + fn deref(&self) -> &Self::Target { + return &self.inner; + } } pub fn get_block_name() -> String { - let s = rand::thread_rng().sample_iter(&Alphanumeric).take(24).map(char::from).collect(); + let s = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(24) + .map(char::from) + .collect(); - return s; -} \ No newline at end of file + return s; +} diff --git a/compiler/prelude/src/lib.rs b/compiler/prelude/src/lib.rs index 3abf84b..baa1b1b 100644 --- a/compiler/prelude/src/lib.rs +++ b/compiler/prelude/src/lib.rs @@ -8,5 +8,5 @@ use crate::types::apply_prelude_types; pub mod types; pub fn apply_prelude(hir: &mut HIRContext, origin: &K) -> MaybeDiagnostic { - apply_prelude_types(hir, origin) -} \ No newline at end of file + apply_prelude_types(hir, origin) +} diff --git a/compiler/prelude/src/types.rs b/compiler/prelude/src/types.rs index 33ded04..7af6403 100644 --- a/compiler/prelude/src/types.rs +++ b/compiler/prelude/src/types.rs @@ -1,7 +1,12 @@ -use astoir_hir::{ctx::HIRContext, storage::{EntryKey, GlobalStorageEntryType}}; -use compiler_typing::{TypeParameterContainer, enums::RawEnumTypeContainer, raw::RawType, references::TypeReference}; +use astoir_hir::{ + ctx::HIRContext, + storage::{EntryKey, GlobalStorageEntryType}, +}; +use compiler_typing::{ + TypeParameterContainer, enums::RawEnumTypeContainer, raw::RawType, references::TypeReference, +}; use compiler_utils::hash; -use compiler_utils::hash::{HashedString}; +use compiler_utils::hash::HashedString; use diagnostics::{DiagnosticSpanOrigin, MaybeDiagnostic}; pub const SIGNED_INTEGER_8: u64 = hash!("s8"); @@ -56,72 +61,230 @@ pub const BOOLEAN_TYPE: u64 = hash!("bool"); /// Experimental pub const RESULT_TYPE: u64 = hash!("result"); -pub fn register_prelude_type(hir: &mut HIRContext, hash: u64, t: RawType, origin: &K) -> MaybeDiagnostic { - hir.global_scope.append(EntryKey { name_hash: hash }, GlobalStorageEntryType::Type(t), origin) +pub fn register_prelude_type( + hir: &mut HIRContext, + hash: u64, + t: RawType, + origin: &K, +) -> MaybeDiagnostic { + hir.global_scope.append( + EntryKey { name_hash: hash }, + GlobalStorageEntryType::Type(t), + origin, + ) } -pub fn apply_prelude_types(hir: &mut HIRContext, origin: &K) -> MaybeDiagnostic { - register_prelude_type(hir, SIGNED_INTEGER, RawType::SizedInteger(true), origin)?; - register_prelude_type(hir, SIGNED_INTEGER_8, RawType::Integer(8, true), origin)?; - register_prelude_type(hir, SIGNED_INTEGER_16, RawType::Integer(16, true), origin)?; - register_prelude_type(hir, SIGNED_INTEGER_32, RawType::Integer(32, true), origin)?; - register_prelude_type(hir, SIGNED_INTEGER_64, RawType::Integer(64, true), origin)?; - register_prelude_type(hir, SIGNED_INTEGER_128, RawType::Integer(128, true), origin)?; - - register_prelude_type(hir, UNSIGNED_INTEGER, RawType::SizedInteger(false), origin)?; - register_prelude_type(hir, UNSIGNED_INTEGER_8, RawType::Integer(8, false), origin)?; - register_prelude_type(hir, UNSIGNED_INTEGER_16, RawType::Integer(16, false), origin)?; - register_prelude_type(hir, UNSIGNED_INTEGER_32, RawType::Integer(32, false), origin)?; - register_prelude_type(hir, UNSIGNED_INTEGER_64, RawType::Integer(64, false), origin)?; - register_prelude_type(hir, UNSIGNED_INTEGER_128, RawType::Integer(128, false), origin)?; - - register_prelude_type(hir, SIGNED_FLOATING_POINT, RawType::SizedFloating(true), origin)?; - register_prelude_type(hir, SIGNED_FLOATING_POINT_8, RawType::Floating(8, true), origin)?; - register_prelude_type(hir, SIGNED_FLOATING_POINT_16, RawType::Floating(16, true), origin)?; - register_prelude_type(hir, SIGNED_FLOATING_POINT_32, RawType::Floating(32, true), origin)?; - register_prelude_type(hir, SIGNED_FLOATING_POINT_64, RawType::Floating(64, true), origin)?; - register_prelude_type(hir, SIGNED_FLOATING_POINT_128, RawType::Floating(128, true), origin)?; - - register_prelude_type(hir, UNSIGNED_FLOATING_POINT, RawType::SizedFloating(false), origin)?; - register_prelude_type(hir, UNSIGNED_FLOATING_POINT_8, RawType::Floating(8, false), origin)?; - register_prelude_type(hir, UNSIGNED_FLOATING_POINT_16, RawType::Floating(16, false), origin)?; - register_prelude_type(hir, UNSIGNED_FLOATING_POINT_32, RawType::Floating(32, false), origin)?; - register_prelude_type(hir, UNSIGNED_FLOATING_POINT_64, RawType::Floating(64, false), origin)?; - register_prelude_type(hir, UNSIGNED_FLOATING_POINT_128, RawType::Floating(128, false), origin)?; - - - register_prelude_type(hir, SIGNED_FIXED_POINT, RawType::SizedFixedPoint(true), origin)?; - register_prelude_type(hir, SIGNED_FIXED_POINT_8, RawType::FixedPoint(4, 4, true), origin)?; - register_prelude_type(hir, SIGNED_FIXED_POINT_16, RawType::FixedPoint(8, 8, true), origin)?; - register_prelude_type(hir, SIGNED_FIXED_POINT_32, RawType::FixedPoint(16, 16, true), origin)?; - register_prelude_type(hir, SIGNED_FIXED_POINT_64, RawType::FixedPoint(64, 64, true), origin)?; - register_prelude_type(hir, SIGNED_FIXED_POINT_128, RawType::FixedPoint(128, 128, true), origin)?; - - register_prelude_type(hir, UNSIGNED_FIXED_POINT, RawType::SizedFixedPoint(true), origin)?; - register_prelude_type(hir, UNSIGNED_FIXED_POINT_8, RawType::FixedPoint(4, 4, true), origin)?; - register_prelude_type(hir, UNSIGNED_FIXED_POINT_16, RawType::FixedPoint(8, 8, true), origin)?; - register_prelude_type(hir, UNSIGNED_FIXED_POINT_32, RawType::FixedPoint(16, 16, true), origin)?; - register_prelude_type(hir, UNSIGNED_FIXED_POINT_64, RawType::FixedPoint(64, 64, true), origin)?; - register_prelude_type(hir, UNSIGNED_FIXED_POINT_128, RawType::FixedPoint(128, 128, true), origin)?; - - register_prelude_type(hir, BOOLEAN_TYPE, RawType::Boolean, origin)?; - register_prelude_type(hir, STATIC_STR, RawType::StaticString, origin)?; - register_prelude_type(hir, POINTER_TYPE, RawType::Pointer, origin)?; - - // result - { - let mut type_params = TypeParameterContainer::new(); - - type_params.insert(HashedString::new("V".to_string()), 0); - type_params.insert(HashedString::new("E".to_string()), 1); - - let mut result_enum = RawEnumTypeContainer::new(hir.global_scope.entries.len(), type_params); - - result_enum.append_entry(HashedString::new("value".to_string()), vec![(hash!("val"), TypeReference::make_unresolved(0))]); - result_enum.append_entry(HashedString::new("error".to_string()), vec![(hash!("err"), TypeReference::make_unresolved(1))]); - - register_prelude_type(hir, RESULT_TYPE, RawType::Enum(result_enum), origin)?; - } - - Ok(()) -} \ No newline at end of file +pub fn apply_prelude_types( + hir: &mut HIRContext, + origin: &K, +) -> MaybeDiagnostic { + register_prelude_type(hir, SIGNED_INTEGER, RawType::SizedInteger(true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_8, RawType::Integer(8, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_16, RawType::Integer(16, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_32, RawType::Integer(32, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_64, RawType::Integer(64, true), origin)?; + register_prelude_type(hir, SIGNED_INTEGER_128, RawType::Integer(128, true), origin)?; + + register_prelude_type(hir, UNSIGNED_INTEGER, RawType::SizedInteger(false), origin)?; + register_prelude_type(hir, UNSIGNED_INTEGER_8, RawType::Integer(8, false), origin)?; + register_prelude_type( + hir, + UNSIGNED_INTEGER_16, + RawType::Integer(16, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_INTEGER_32, + RawType::Integer(32, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_INTEGER_64, + RawType::Integer(64, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_INTEGER_128, + RawType::Integer(128, false), + origin, + )?; + + register_prelude_type( + hir, + SIGNED_FLOATING_POINT, + RawType::SizedFloating(true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FLOATING_POINT_8, + RawType::Floating(8, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FLOATING_POINT_16, + RawType::Floating(16, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FLOATING_POINT_32, + RawType::Floating(32, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FLOATING_POINT_64, + RawType::Floating(64, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FLOATING_POINT_128, + RawType::Floating(128, true), + origin, + )?; + + register_prelude_type( + hir, + UNSIGNED_FLOATING_POINT, + RawType::SizedFloating(false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FLOATING_POINT_8, + RawType::Floating(8, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FLOATING_POINT_16, + RawType::Floating(16, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FLOATING_POINT_32, + RawType::Floating(32, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FLOATING_POINT_64, + RawType::Floating(64, false), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FLOATING_POINT_128, + RawType::Floating(128, false), + origin, + )?; + + register_prelude_type( + hir, + SIGNED_FIXED_POINT, + RawType::SizedFixedPoint(true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FIXED_POINT_8, + RawType::FixedPoint(4, 4, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FIXED_POINT_16, + RawType::FixedPoint(8, 8, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FIXED_POINT_32, + RawType::FixedPoint(16, 16, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FIXED_POINT_64, + RawType::FixedPoint(64, 64, true), + origin, + )?; + register_prelude_type( + hir, + SIGNED_FIXED_POINT_128, + RawType::FixedPoint(128, 128, true), + origin, + )?; + + register_prelude_type( + hir, + UNSIGNED_FIXED_POINT, + RawType::SizedFixedPoint(true), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FIXED_POINT_8, + RawType::FixedPoint(4, 4, true), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FIXED_POINT_16, + RawType::FixedPoint(8, 8, true), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FIXED_POINT_32, + RawType::FixedPoint(16, 16, true), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FIXED_POINT_64, + RawType::FixedPoint(64, 64, true), + origin, + )?; + register_prelude_type( + hir, + UNSIGNED_FIXED_POINT_128, + RawType::FixedPoint(128, 128, true), + origin, + )?; + + register_prelude_type(hir, BOOLEAN_TYPE, RawType::Boolean, origin)?; + register_prelude_type(hir, STATIC_STR, RawType::StaticString, origin)?; + register_prelude_type(hir, POINTER_TYPE, RawType::Pointer, origin)?; + + // result + { + let mut type_params = TypeParameterContainer::new(); + + type_params.insert(HashedString::new("V".to_string()), 0); + type_params.insert(HashedString::new("E".to_string()), 1); + + let mut result_enum = + RawEnumTypeContainer::new(hir.global_scope.entries.len(), type_params); + + result_enum.append_entry( + HashedString::new("value".to_string()), + vec![(hash!("val"), TypeReference::make_unresolved(0))], + ); + result_enum.append_entry( + HashedString::new("error".to_string()), + vec![(hash!("err"), TypeReference::make_unresolved(1))], + ); + + register_prelude_type(hir, RESULT_TYPE, RawType::Enum(result_enum), origin)?; + } + + Ok(()) +} From c55ffad9e61d7f32073d54f49de47411ae147a51 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 22:57:31 +0200 Subject: [PATCH 43/60] fix: fixed HIR --- compiler/astoir_hir/src/ctx.rs | 10 +- compiler/astoir_hir/src/lib.rs | 1 - compiler/astoir_hir/src/nodes.rs | 22 +-- compiler/astoir_hir/src/resolve.rs | 4 +- compiler/astoir_hir/src/storage.rs | 241 -------------------------- compiler/astoir_mir/src/builder.rs | 10 +- compiler/astoir_mir/src/vals/refer.rs | 4 +- 7 files changed, 24 insertions(+), 268 deletions(-) delete mode 100644 compiler/astoir_hir/src/storage.rs diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index a8a9635..967d2f5 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; -use compiler_typing::{storage::TypeStorage, tree::Type}; +use compiler_typing::{TypedGlobalScope, tree::Type}; use compiler_utils::{hash::SelfHash, utils::indexed::IndexStorage}; use diagnostics::{ DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_func, make_cannot_find_var, make_doesnt_exist_in_era}, }; -use crate::{nodes::HIRNode, storage::GlobalScopeStorage, structs::HIRStructContainer}; +use crate::{nodes::HIRNode, structs::HIRStructContainer}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); @@ -278,8 +278,7 @@ pub struct HIRContext { pub function_contexts: Vec>, pub static_variables: IndexStorage, pub struct_func_impls: HashMap, - pub type_storage: TypeStorage, - pub global_scope: GlobalScopeStorage, + pub global_scope: TypedGlobalScope, } #[derive(PartialEq)] @@ -293,11 +292,10 @@ impl HIRContext { return HIRContext { functions: IndexStorage::new(), static_variables: IndexStorage::new(), - type_storage: TypeStorage::new().unwrap(), function_contexts: vec![], function_declarations: vec![], struct_func_impls: HashMap::new(), - global_scope: GlobalScopeStorage::new(), + global_scope: TypedGlobalScope::new(), }; } diff --git a/compiler/astoir_hir/src/lib.rs b/compiler/astoir_hir/src/lib.rs index 47ac86a..d3fef0f 100644 --- a/compiler/astoir_hir/src/lib.rs +++ b/compiler/astoir_hir/src/lib.rs @@ -4,5 +4,4 @@ pub mod ctx; pub mod nodes; pub mod resolve; -pub mod storage; pub mod structs; diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index 5e17f87..5a8136c 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -316,7 +316,7 @@ impl HIRNode { return Ok(self.clone()); } - if self_type.can_transmute(&t, &context.type_storage) { + if self_type.can_transmute(&t, &context.global_scope) { match &self.kind { HIRNodeKind::IntegerLiteral { value, int_type: _ } => { return Ok(self.with(HIRNodeKind::IntegerLiteral { @@ -326,7 +326,7 @@ impl HIRNode { } HIRNodeKind::ArrayVariableInitializerValue { vals } => { - if can_transmute_inner(&self_type, &t, &context.type_storage) { + if can_transmute_inner(&self_type, &t, &context.global_scope) { let mut new_vals = vec![]; let inner = t.get_inner_type(); @@ -346,7 +346,7 @@ impl HIRNode { } HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { - if can_transmute_inner(&self_type, &t, &context.type_storage) { + if can_transmute_inner(&self_type, &t, &context.global_scope) { let new_val = Box::new(val.use_as( context, curr_ctx, @@ -355,12 +355,12 @@ impl HIRNode { var_origin, )?); - return Ok( - self.with(HIRNodeKind::ArrayVariableInitializerValueSameValue { + return Ok(self.with( + HIRNodeKind::ArrayVariableInitializerValueSameValue { size: *size, val: new_val, - }), - ); + }, + )); } } @@ -379,11 +379,11 @@ impl HIRNode { return Err(make_diff_type( origin, &"unnamed".to_string(), - &t.faulty_lowering_generic(&context.type_storage), + &t.faulty_lowering_generic(&context.global_scope), &self .get_node_type(context, curr_ctx) .unwrap() - .faulty_lowering_generic(&context.type_storage), + .faulty_lowering_generic(&context.global_scope), v, ) .into()); @@ -391,11 +391,11 @@ impl HIRNode { return Err(make_diff_type_val( origin, - &t.faulty_lowering_generic(&context.type_storage), + &t.faulty_lowering_generic(&context.global_scope), &self .get_node_type(context, curr_ctx) .unwrap() - .faulty_lowering_generic(&context.type_storage), + .faulty_lowering_generic(&context.global_scope), ) .into()); } diff --git a/compiler/astoir_hir/src/resolve.rs b/compiler/astoir_hir/src/resolve.rs index a3cf492..db2c50e 100644 --- a/compiler/astoir_hir/src/resolve.rs +++ b/compiler/astoir_hir/src/resolve.rs @@ -29,7 +29,7 @@ pub fn resolve_to_type( return Err(make_req_type_kind(origin, &"field-having".to_string()).into()); } - for field in destination.get_fields(&context.type_storage) { + for field in destination.get_fields(&context.global_scope) { let identity = SelfHash { hash: field }; if !fields.contains_key(&identity) { @@ -39,7 +39,7 @@ pub fn resolve_to_type( let val = fields[&identity].clone(); let field_data = destination - .get_field(&context.type_storage, field)? + .get_field(&context.global_scope, field)? .1 .resolve(&destination); diff --git a/compiler/astoir_hir/src/storage.rs b/compiler/astoir_hir/src/storage.rs deleted file mode 100644 index e133ee4..0000000 --- a/compiler/astoir_hir/src/storage.rs +++ /dev/null @@ -1,241 +0,0 @@ -//! The global HIR storage, basically stores types, functions, and more - -use std::{collections::HashMap, fmt::Display, hash::Hash}; - -use compiler_typing::{raw::RawType, tree::Type}; -use diagnostics::{ - DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, - builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}, -}; - -use crate::{ctx::HIRFunction, nodes::HIRNode}; - -pub type GlobalStorageIdentifier = usize; - -#[derive(Clone, Debug)] -pub enum GlobalStorageEntryType { - Function(HIRFunction, Box), - ImplLessFunction(HIRFunction), - StaticVariable(Type), - - StructFunction(HIRFunction, Box, GlobalStorageIdentifier), - - Type(RawType), -} - -/// Represents a key to a global storage entry. Potentially allows for namespaces later on -#[derive(Debug)] -pub struct EntryKey { - pub name_hash: u64, -} - -impl Hash for EntryKey { - fn hash(&self, state: &mut H) { - state.write_u64(self.name_hash); - } -} - -impl PartialEq for EntryKey { - fn eq(&self, other: &Self) -> bool { - self.name_hash == other.name_hash - } -} - -impl Eq for EntryKey {} - -#[derive(Debug)] -pub struct GlobalStorageEntry { - pub entry_type: GlobalStorageEntryType, - pub parent_index: usize, -} - -#[derive(Debug)] -pub struct GlobalScopeStorage { - pub entry_to_ind: HashMap, - pub entries: Vec, -} - -/// The global storage for every element inside of the scope. -/// -/// This stores the following: -/// - Functions (with or without implementations) -/// - Static variables -/// - Struct functions -/// - Types -/// -/// # Safety -/// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. -impl GlobalScopeStorage { - pub fn new() -> Self { - GlobalScopeStorage { - entry_to_ind: HashMap::new(), - entries: vec![], - } - } - - pub fn append( - &mut self, - name: EntryKey, - entry: GlobalStorageEntryType, - origin: &K, - ) -> MaybeDiagnostic { - if self.entry_to_ind.contains_key(&name) { - return Err(make_already_in_scope(origin, &name.name_hash).into()); - } - - let parent_index = self.entries.len(); - - let entry = GlobalStorageEntry { - entry_type: entry, - parent_index, - }; - - self.entries.push(entry); - self.entry_to_ind.insert(name, parent_index); - - Ok(()) - } - - pub fn get_base( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult { - if !self.entry_to_ind.contains_key(&name) { - return Err(make_cannot_find(origin, &name.name_hash).into()); - } - - return Ok(self.entries[self.entry_to_ind[&name]].entry_type.clone()); - } - - pub fn get_type( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Type(t) => Ok(t.clone()), - _ => Err(make_expected_simple_error(origin, &"type".to_string(), &base).into()), - }; - } - - pub fn get_static_variable( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::StaticVariable(t) => Ok(t.clone()), - _ => Err( - make_expected_simple_error(origin, &"static variable".to_string(), &base).into(), - ), - }; - } - - pub fn get_function_base( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function(hir, _) => Ok(hir.clone()), - GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), - GlobalStorageEntryType::StructFunction(hir, _, _) => Ok(hir.clone()), - - _ => Err(make_expected_simple_error(origin, &"function".to_string(), &base).into()), - }; - } - - pub fn get_function_impl( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function(_, i) => Ok(i.clone()), - GlobalStorageEntryType::StructFunction(_, i, _) => Ok(i.clone()), - - _ => Err( - make_expected_simple_error(origin, &"function with implementation", &base).into(), - ), - }; - } - - pub fn get_implless_function( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::ImplLessFunction(hir) => Ok(hir.clone()), - - _ => Err( - make_expected_simple_error(origin, &"function without implementation", &base) - .into(), - ), - }; - } - - pub fn get_exact_function( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult<(HIRFunction, Box)> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::Function(hir, i) => Ok((hir.clone(), i.clone())), - - _ => Err(make_expected_simple_error(origin, &"function", &base).into()), - }; - } - - pub fn get_exact_struct_function( - &self, - name: EntryKey, - origin: &K, - ) -> DiagnosticResult<(HIRFunction, Box, RawType)> { - let base = self.get_base(name, origin)?; - - return match base { - GlobalStorageEntryType::StructFunction(hir, i, o) => { - if let GlobalStorageEntryType::Type(t) = self.entries[o].entry_type.clone() { - Ok((hir, i, t)) - } else { - Err( - make_expected_simple_error(origin, &"type", &self.entries[0].entry_type) - .into(), - ) - } - } - - _ => Err(make_expected_simple_error(origin, &"struct function", &base).into()), - }; - } -} - -impl Display for GlobalStorageEntryType { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let s = match self { - Self::Function(_, _) => "function", - Self::ImplLessFunction(_) => "function", - Self::StructFunction(_, _, _) => "function", - Self::StaticVariable(_) => "static variable", - Self::Type(_) => "type", - }; - - write!(f, "{}", s)?; - - Ok(()) - } -} diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 2da1ef7..5f505ce 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -1,6 +1,6 @@ //! Utility functions to build instructions and more -use compiler_typing::{SizedType, raw::RawType, storage::TypeStorage, tree::Type}; +use compiler_typing::{SizedType, TypedGlobalScope, raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult, MaybeDiagnostic, unsure_panic}; use crate::{ @@ -42,7 +42,7 @@ pub fn build_load(ctx: &mut MIRContext, ptr: MIRPointerValue) -> DiagnosticResul pub fn build_store( ctx: &mut MIRContext, - storage: &TypeStorage, + storage: &TypedGlobalScope, ptr: MIRPointerValue, val: BaseMIRValue, ) -> DiagnosticResult<()> { @@ -53,9 +53,9 @@ pub fn build_store( if !hint.get_maybe_containing_type().is_truly_eq(&val.vtype) && !hint.is_ptr() { if hint .get_maybe_containing_type() - .get_generic(storage) + .get_generic() .is_enum_parent() - && val.vtype.get_generic(storage).is_enum_child() + && val.vtype.get_generic().is_enum_child() { return build_store_fallback(ctx, ptr, val.clone(), storage); } @@ -905,7 +905,7 @@ pub fn build_store_fallback( ctx: &mut MIRContext, dest: MIRPointerValue, src: BaseMIRValue, - storage: &TypeStorage, + storage: &TypedGlobalScope, ) -> MaybeDiagnostic { let sz = src.vtype.get_size(&src.vtype, false, storage); diff --git a/compiler/astoir_mir/src/vals/refer.rs b/compiler/astoir_mir/src/vals/refer.rs index 5b43bd9..3c3d6aa 100644 --- a/compiler/astoir_mir/src/vals/refer.rs +++ b/compiler/astoir_mir/src/vals/refer.rs @@ -1,4 +1,4 @@ -use compiler_typing::storage::TypeStorage; +use compiler_typing::TypedGlobalScope; use diagnostics::{DiagnosticResult, builders::make_invalid_assign_diff_type_ir, unsure_panic}; use crate::{ @@ -56,7 +56,7 @@ impl MIRVariableReference { block: MIRBlockReference, ctx: &mut MIRContext, val: BaseMIRValue, - storage: &TypeStorage, + storage: &TypedGlobalScope, ) -> DiagnosticResult { if self.is_pointer_ref() { let mut ptr_ref = self.as_pointer_ref()?; From fbbfd62d570d51ea6ee590c9a785ada6815ce656 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Mon, 20 Apr 2026 23:00:12 +0200 Subject: [PATCH 44/60] fix: fixed MIR --- compiler/astoir_mir_lowering/src/arrays.rs | 2 +- compiler/astoir_mir_lowering/src/casts.rs | 8 +------- .../astoir_mir_lowering/src/introductions.rs | 4 ++-- compiler/astoir_mir_lowering/src/lib.rs | 14 +++++++------- compiler/astoir_mir_lowering/src/lru.rs | 2 +- compiler/astoir_mir_lowering/src/math.rs | 4 ++-- compiler/astoir_mir_lowering/src/type_tools.rs | 18 +++--------------- .../astoir_mir_lowering/src/values/consts.rs | 6 +++--- .../astoir_mir_lowering/src/values/structs.rs | 15 ++++++++------- compiler/astoir_mir_lowering/src/vars.rs | 6 +++--- 10 files changed, 31 insertions(+), 48 deletions(-) diff --git a/compiler/astoir_mir_lowering/src/arrays.rs b/compiler/astoir_mir_lowering/src/arrays.rs index 7eb9b14..67e0216 100644 --- a/compiler/astoir_mir_lowering/src/arrays.rs +++ b/compiler/astoir_mir_lowering/src/arrays.rs @@ -54,7 +54,7 @@ pub fn lower_hir_array_modify( build_store( &mut ctx.mir_ctx, - &ctx.hir_ctx.type_storage, + &ctx.hir_ctx.global_scope, index_pointer, val, )?; diff --git a/compiler/astoir_mir_lowering/src/casts.rs b/compiler/astoir_mir_lowering/src/casts.rs index 8520c88..033e196 100644 --- a/compiler/astoir_mir_lowering/src/casts.rs +++ b/compiler/astoir_mir_lowering/src/casts.rs @@ -24,13 +24,7 @@ pub fn lower_cast( let new_type = lower_hir_type(ctx, new_type)?; - if old_type - .get_generic(&ctx.hir_ctx.type_storage) - .is_enum_child() - && new_type - .get_generic(&ctx.hir_ctx.type_storage) - .is_enum_parent() - { + if old_type.get_generic().is_enum_child() && new_type.get_generic().is_enum_parent() { match ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] { MIRValueHint::Pointer(_) => { ctx.mir_ctx.ssa_hints.vec[value.get_ssa_index()] = diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index 1a3831f..c15e122 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -44,7 +44,7 @@ pub fn handle_var_introduction_queue( } else { let ptr = build_stack_alloc( &mut ctx.mir_ctx, - new_type.get_size(&new_type, false, &ctx.hir_ctx.type_storage), + new_type.get_size(&new_type, false, &ctx.hir_ctx.global_scope), new_type, )?; @@ -57,7 +57,7 @@ pub fn handle_var_introduction_queue( ); build_store( &mut ctx.mir_ctx, - &ctx.hir_ctx.type_storage, + &ctx.hir_ctx.global_scope, ptr.clone(), casted, )?; diff --git a/compiler/astoir_mir_lowering/src/lib.rs b/compiler/astoir_mir_lowering/src/lib.rs index 6feae2c..38010b5 100644 --- a/compiler/astoir_mir_lowering/src/lib.rs +++ b/compiler/astoir_mir_lowering/src/lib.rs @@ -105,7 +105,8 @@ pub fn lower_hir_generic( hir_mir_indexes: HashMap::new(), }; - let parent = match &ctx.hir_ctx.type_storage.types.vals[container.parent] { + let parent = match &ctx.hir_ctx.global_scope.entries[container.parent].as_type_unsafe() + { RawType::Enum(container) => container.clone(), _ => panic!("Enum parent not enum"), }; @@ -154,12 +155,11 @@ pub fn lower_hir_generic( Type::Generic(entry.1.clone(), info.0.clone(), info.1.clone()), )?; - entry_size = - entry_size.max(lowered.get_generic(&ctx.hir_ctx.type_storage).get_size( - &lowered, - false, - &ctx.hir_ctx.type_storage, - )) + entry_size = entry_size.max(lowered.get_generic().get_size( + &lowered, + false, + &ctx.hir_ctx.global_scope, + )) } lowered_container diff --git a/compiler/astoir_mir_lowering/src/lru.rs b/compiler/astoir_mir_lowering/src/lru.rs index 1a97200..c1a05d0 100644 --- a/compiler/astoir_mir_lowering/src/lru.rs +++ b/compiler/astoir_mir_lowering/src/lru.rs @@ -34,7 +34,7 @@ pub fn lower_hir_lru_step( .ssa_hints .get_hint(curr.get_ssa_index()) .get_type() - .get_generic(&ctx.hir_ctx.type_storage) + .get_generic() { RawType::LoweredStruct(_, container) => container, _ => unsure_panic!("lower_hir_lru_step curr was not an actual thing"), diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index 5d7818f..b7556bc 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -44,7 +44,7 @@ pub fn lower_hir_math_operation( let left_val = lower_hir_value(block, left, ctx)?; let right_val = lower_hir_value(block, right, ctx)?; - let val = match left_val.vtype.get_generic(&ctx.hir_ctx.type_storage) { + let val = match left_val.vtype.get_generic() { RawType::Integer(_, _) | RawType::FixedPoint(_, _, _) => { lower_hir_math_operation_int(left_val, right_val, operation.clone(), ctx)? } @@ -62,7 +62,7 @@ pub fn lower_hir_math_operation( block, &mut ctx.mir_ctx, val.clone(), - &ctx.hir_ctx.type_storage, + &ctx.hir_ctx.global_scope, )?; } diff --git a/compiler/astoir_mir_lowering/src/type_tools.rs b/compiler/astoir_mir_lowering/src/type_tools.rs index 789302c..ee20c68 100644 --- a/compiler/astoir_mir_lowering/src/type_tools.rs +++ b/compiler/astoir_mir_lowering/src/type_tools.rs @@ -68,7 +68,7 @@ pub fn is_enum_value_of_kind( hint_type.get_size( &Type::GenericLowered(hint_type.clone()), false, - &ctx.hir_ctx.type_storage, + &ctx.hir_ctx.global_scope, ), )?; @@ -144,13 +144,7 @@ pub fn lower_hir_unwrap_cond( if unsafe_unwrap { cond = build_unsigned_int_const(&mut ctx.mir_ctx, 1, 1)?; } else { - cond = is_enum_value_of_kind( - block, - original, - new_type.get_generic(&ctx.hir_ctx.type_storage), - ctx, - &*node, - )? + cond = is_enum_value_of_kind(block, original, new_type.get_generic(), ctx, &*node)? } if new_var.is_none() { @@ -179,13 +173,7 @@ pub fn lower_hir_unwrap_value( let original = lower_hir_value(block, original, ctx)?; let new_type = lower_hir_type(ctx, new_type)?; - return cast_to_enum_child( - block, - original, - new_type.get_generic(&ctx.hir_ctx.type_storage), - ctx, - &*node, - ); + return cast_to_enum_child(block, original, new_type.get_generic(), ctx, &*node); } panic!("Invalid node!") diff --git a/compiler/astoir_mir_lowering/src/values/consts.rs b/compiler/astoir_mir_lowering/src/values/consts.rs index b393c70..51ac743 100644 --- a/compiler/astoir_mir_lowering/src/values/consts.rs +++ b/compiler/astoir_mir_lowering/src/values/consts.rs @@ -14,11 +14,11 @@ pub fn lower_hir_literal( ) -> DiagnosticResult { match node.kind { HIRNodeKind::IntegerLiteral { value, int_type } => { - if int_type.get_generic(&ctx.hir_ctx.type_storage).is_signed() { + if int_type.get_generic().is_signed() { let val = build_signed_int_const( &mut ctx.mir_ctx, value, - int_type.get_size(&int_type, true, &ctx.hir_ctx.type_storage), + int_type.get_size(&int_type, true, &ctx.hir_ctx.global_scope), )?; return Ok(val.into()); @@ -27,7 +27,7 @@ pub fn lower_hir_literal( let val = build_unsigned_int_const( &mut ctx.mir_ctx, value as u128, - int_type.get_size(&int_type, true, &ctx.hir_ctx.type_storage), + int_type.get_size(&int_type, true, &ctx.hir_ctx.global_scope), )?; return Ok(val.into()); diff --git a/compiler/astoir_mir_lowering/src/values/structs.rs b/compiler/astoir_mir_lowering/src/values/structs.rs index c7e22c2..00b1720 100644 --- a/compiler/astoir_mir_lowering/src/values/structs.rs +++ b/compiler/astoir_mir_lowering/src/values/structs.rs @@ -17,7 +17,7 @@ pub fn lower_hir_struct_init( if let HIRNodeKind::StructInitializerTyped { t, fields } = node.kind { let mut values = vec![]; - match t.get_generic(&ctx.hir_ctx.type_storage) { + match t.get_generic() { RawType::Struct(_, _) => { for field in fields { values.push(lower_hir_value(block, field, ctx)?); @@ -25,10 +25,11 @@ pub fn lower_hir_struct_init( } RawType::EnumEntry(container) => { - let parent = match &ctx.hir_ctx.type_storage.types.vals[container.parent] { - RawType::Enum(container) => container.clone(), - _ => panic!("Enum parent not enum"), - }; + let parent = + match &ctx.hir_ctx.global_scope.entries[container.parent].as_type_unsafe() { + RawType::Enum(container) => container.clone(), + _ => panic!("Enum parent not enum"), + }; let hint = build_unsigned_int_const( &mut ctx.mir_ctx, @@ -36,7 +37,7 @@ pub fn lower_hir_struct_init( parent.get_hint_type().get_size( &Type::GenericLowered(parent.get_hint_type()), false, - &ctx.hir_ctx.type_storage, + &ctx.hir_ctx.global_scope, ), )?; @@ -50,7 +51,7 @@ pub fn lower_hir_struct_init( _ => panic!("Invalid type for a StructInitializedTyped"), } - let lowered_type = lower_hir_type(ctx, t)?.get_generic(&ctx.hir_ctx.type_storage); + let lowered_type = lower_hir_type(ctx, t)?.get_generic(); return build_static_struct_const(&mut ctx.mir_ctx, lowered_type, values); } diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index 36f9578..993d623 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -51,7 +51,7 @@ pub fn lower_hir_variable_declaration( let ptr = build_stack_alloc( &mut ctx.mir_ctx, - lowered.get_size(&lowered, false, &ctx.hir_ctx.type_storage), + lowered.get_size(&lowered, false, &ctx.hir_ctx.global_scope), lowered, )?; @@ -68,7 +68,7 @@ pub fn lower_hir_variable_declaration( build_store( &mut ctx.mir_ctx, - &ctx.hir_ctx.type_storage, + &ctx.hir_ctx.global_scope, ptr.clone(), val, )?; @@ -121,7 +121,7 @@ pub fn lower_hir_variable_assignment( let val = lower_hir_value(block, val, ctx)?; - variable_ref.write(block, &mut ctx.mir_ctx, val, &ctx.hir_ctx.type_storage)?; + variable_ref.write(block, &mut ctx.mir_ctx, val, &ctx.hir_ctx.global_scope)?; return Ok(true); } From cdda6e647d9d7a020c0ef56b8c147ce329629175 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 10:55:03 +0200 Subject: [PATCH 45/60] fix: fixed up global scope to work --- Cargo.lock | 2 ++ compiler/astoir_hir_lowering/Cargo.toml | 3 +- compiler/astoir_hir_lowering/src/enums.rs | 14 ++++++--- compiler/astoir_hir_lowering/src/literals.rs | 6 +++- compiler/astoir_hir_lowering/src/structs.rs | 17 ++++++++--- compiler/astoir_hir_lowering/src/types.rs | 29 ++++++++++++------ compiler/astoir_hir_lowering/src/uses.rs | 32 +++++++++++++++----- compiler/astoir_hir_lowering/src/values.rs | 4 +-- compiler/compiler_global_scope/src/entry.rs | 14 ++++----- compiler/compiler_global_scope/src/lib.rs | 17 +++++++---- compiler/compiler_typing/src/raw.rs | 15 +++++++++ compiler/prelude/Cargo.toml | 1 + compiler/prelude/src/types.rs | 10 +++--- 13 files changed, 115 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 263cedb..0f3c57a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,6 +58,7 @@ dependencies = [ "ast", "ast_parser", "astoir_hir", + "compiler_global_scope", "compiler_typing", "compiler_utils", "diagnostics", @@ -254,6 +255,7 @@ name = "prelude" version = "0.1.0" dependencies = [ "astoir_hir", + "compiler_global_scope", "compiler_typing", "compiler_utils", "diagnostics", diff --git a/compiler/astoir_hir_lowering/Cargo.toml b/compiler/astoir_hir_lowering/Cargo.toml index 5a6b8da..b58e045 100644 --- a/compiler/astoir_hir_lowering/Cargo.toml +++ b/compiler/astoir_hir_lowering/Cargo.toml @@ -11,4 +11,5 @@ diagnostics = { path = "../diagnostics" } compiler_utils = { path = "../compiler_utils" } lexer = { path = "../lexer" } ast_parser = { path = "../ast_parser" } -prelude = { path = "../prelude" } \ No newline at end of file +prelude = { path = "../prelude" } +compiler_global_scope = { path = "../compiler_global_scope" } diff --git a/compiler/astoir_hir_lowering/src/enums.rs b/compiler/astoir_hir_lowering/src/enums.rs index e51fa51..afb713b 100644 --- a/compiler/astoir_hir_lowering/src/enums.rs +++ b/compiler/astoir_hir_lowering/src/enums.rs @@ -3,6 +3,7 @@ use astoir_hir::{ ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}, }; +use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{enums::RawEnumTypeContainer, raw::RawType}; use diagnostics::{DiagnosticResult, MaybeDiagnostic, builders::make_already_in_scope}; @@ -46,16 +47,19 @@ pub fn lower_ast_enum( } = node.kind.clone() { let mut container = - RawEnumTypeContainer::new(context.type_storage.types.vals.len(), type_params); + RawEnumTypeContainer::new(context.global_scope.entries.len(), type_params); for entry in entries { lower_ast_enum_entry(context, entry, &mut container)?; } - let ind = match context - .type_storage - .append_with_hash(name.hash, RawType::Enum(container.clone())) - { + let ind = match context.global_scope.append( + EntryKey { + name_hash: name.hash, + }, + GlobalStorageEntryType::Type(RawType::Enum(container.clone())), + &*node, + ) { Ok(v) => v, Err(_) => return Err(make_already_in_scope(&*node, &name.val).into()), }; diff --git a/compiler/astoir_hir_lowering/src/literals.rs b/compiler/astoir_hir_lowering/src/literals.rs index ff75503..00a3726 100644 --- a/compiler/astoir_hir_lowering/src/literals.rs +++ b/compiler/astoir_hir_lowering/src/literals.rs @@ -3,6 +3,7 @@ use astoir_hir::{ ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}, }; +use compiler_global_scope::key::EntryKey; use compiler_typing::tree::Type; use diagnostics::{DiagnosticResult, builders::make_cannot_find_type}; @@ -12,7 +13,10 @@ pub fn lower_ast_literal( ) -> DiagnosticResult> { match node.kind { ASTTreeNodeKind::IntegerLit { val, hash } => { - let lit_type = match context.type_storage.get_type(hash) { + let lit_type = match context + .global_scope + .get_type(EntryKey { name_hash: hash }, &*node) + { Ok(v) => v, Err(_) => return Err(make_cannot_find_type(&*node, &hash).into()), }; diff --git a/compiler/astoir_hir_lowering/src/structs.rs b/compiler/astoir_hir_lowering/src/structs.rs index d800fea..c43d639 100644 --- a/compiler/astoir_hir_lowering/src/structs.rs +++ b/compiler/astoir_hir_lowering/src/structs.rs @@ -6,6 +6,7 @@ use astoir_hir::{ nodes::{HIRNode, HIRNodeKind}, structs::HIRStructContainer, }; +use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{raw::RawType, structs::RawStructTypeContainer}; use compiler_utils::utils::indexed::IndexStorage; use diagnostics::{DiagnosticResult, builders::make_already_in_scope}; @@ -103,7 +104,13 @@ pub fn lower_ast_struct_declaration( let base = RawType::Struct(layout, container.clone()); - let ind = match context.type_storage.append(name.hash, base) { + let ind = match context.global_scope.append( + EntryKey { + name_hash: name.hash, + }, + GlobalStorageEntryType::Type(base), + &*node, + ) { Ok(v) => v, Err(_) => return Err(make_already_in_scope(&*node, &name.val).into()), }; @@ -113,14 +120,14 @@ pub fn lower_ast_struct_declaration( &ASTTreeNodeKind::StructFieldMember { .. } => { lower_ast_struct_member(context, member, &mut container)?; - context.type_storage.types.vals[ind] = - RawType::Struct(layout, container.clone()); + context.global_scope.entries[ind].entry_type = + GlobalStorageEntryType::Type(RawType::Struct(layout, container.clone())); } &ASTTreeNodeKind::FunctionDeclaration { .. } => { let body = lower_ast_struct_function_decl(context, member, &mut container)?; - context.type_storage.types.vals[ind] = - RawType::Struct(layout, container.clone()); + context.global_scope.entries[ind].entry_type = + GlobalStorageEntryType::Type(RawType::Struct(layout, container.clone())); func_impls.push(body); } diff --git a/compiler/astoir_hir_lowering/src/types.rs b/compiler/astoir_hir_lowering/src/types.rs index 8186492..a7da026 100644 --- a/compiler/astoir_hir_lowering/src/types.rs +++ b/compiler/astoir_hir_lowering/src/types.rs @@ -1,5 +1,6 @@ use ast::types::ASTType; use astoir_hir::ctx::HIRContext; +use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, tree::Type}; use compiler_utils::hash::HashedString; use diagnostics::{ @@ -19,7 +20,10 @@ pub fn lower_ast_type( ASTType::Generic(type_id, type_params, size_params, specifier) => { let hash = HashedString::new(type_id).hash; - let mut t = match context.type_storage.get_type(hash) { + let mut t = match context + .global_scope + .get_type(EntryKey { name_hash: hash }, origin) + { Ok(v) => v, Err(_) => return Err(make_cannot_find_type(origin, &hash).into()), }; @@ -33,11 +37,11 @@ pub fn lower_ast_type( t = container.get_entry(HashedString::new(specifier.unwrap()))? } - if t.get_type_params_count(&context.type_storage) != type_params.len() { + if t.get_type_params_count(&context.global_scope, origin)? != type_params.len() { return Err(make_diff_type_specifiers( origin, &type_params.len(), - &t.get_type_params_count(&context.type_storage), + &t.get_type_params_count(&context.global_scope, origin)?, ) .into()); } @@ -51,18 +55,26 @@ pub fn lower_ast_type( let res = Type::Generic(t.clone(), t_params, size_params); if t.is_sized() { - let lower = lower_sized_base_type(context, &res, origin)?; + let lower = lower_sized_base_type(&res, origin)?; - if context.type_storage.type_to_ind.contains_key(&lower) { + if context + .global_scope + .value_to_ind + .contains_key(&GlobalStorageEntryType::Type(lower.clone())) + { return Ok(Type::Generic(t, vec![], vec![])); } else { - let ind = match context.type_storage.append_with_hash(hash, lower) { + let ind = match context.global_scope.append( + EntryKey { name_hash: hash }, + GlobalStorageEntryType::Type(lower), + origin, + ) { Ok(v) => v, Err(_) => panic!("Generic lowering type cannot be found on type_to_hash"), }; return Ok(Type::Generic( - context.type_storage.types.vals[ind].clone(), + context.global_scope.entries[ind].as_type_unsafe(), vec![], vec![], )); @@ -106,13 +118,12 @@ pub fn lower_ast_type_struct( } pub fn lower_sized_base_type( - context: &HIRContext, t: &Type, origin: &K, ) -> DiagnosticResult { let data = t.get_generic_info(); - match t.get_generic(&context.type_storage) { + match t.get_generic() { RawType::SizedInteger(e) => { if data.1.len() != 1 { return Err(make_diff_size_specifiers(origin, &1, &data.1.len()).into()); diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 4a6d47e..f0b1dc0 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -10,6 +10,7 @@ use astoir_hir::{ ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}, }; +use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{raw::RawType, tree::Type}; use compiler_utils::hash::HashedString; use diagnostics::{ @@ -135,7 +136,12 @@ pub fn gather_type_use( pass: bool, ctx: &ParserCtx, ) -> DiagnosticResult { - match context.type_storage.get_type(val.hash) { + match context.global_scope.get_type( + EntryKey { + name_hash: val.hash, + }, + origin, + ) { Ok(v) => return Ok(v), Err(_) => { if pass { @@ -173,11 +179,11 @@ pub fn lower_ast_type_use_statement( t = container.get_entry(HashedString::new(specifier.unwrap()))? } - if t.get_type_params_count(&context.type_storage) != type_params.len() { + if t.get_type_params_count(&context.global_scope, origin)? != type_params.len() { return Err(make_diff_type_specifiers( origin, &type_params.len(), - &t.get_type_params_count(&context.type_storage), + &t.get_type_params_count(&context.global_scope, origin)?, ) .into()); } @@ -191,18 +197,28 @@ pub fn lower_ast_type_use_statement( let res = Type::Generic(t.clone(), t_params, size_params); if t.is_sized() { - let lower = lower_sized_base_type(context, &res, origin)?; + let lower = lower_sized_base_type(&res, origin)?; - if context.type_storage.type_to_ind.contains_key(&lower) { + if context + .global_scope + .value_to_ind + .contains_key(&GlobalStorageEntryType::Type(lower.clone())) + { return Ok(Type::Generic(t, vec![], vec![])); } else { - let ind = match context.type_storage.append_with_hash(hash, lower) { + let ind = match context.global_scope.append( + EntryKey { name_hash: hash }, + GlobalStorageEntryType::Type(lower), + origin, + ) { Ok(v) => v, - Err(_) => panic!("Generic lowering type cannot be found on type_to_hash"), + Err(_) => { + panic!("Generic lowering type cannot be found on type_to_hash") + } }; return Ok(Type::Generic( - context.type_storage.types.vals[ind].clone(), + context.global_scope.entries[ind].as_type_unsafe(), vec![], vec![], )); diff --git a/compiler/astoir_hir_lowering/src/values.rs b/compiler/astoir_hir_lowering/src/values.rs index e52b9ae..e5418b9 100644 --- a/compiler/astoir_hir_lowering/src/values.rs +++ b/compiler/astoir_hir_lowering/src/values.rs @@ -37,7 +37,7 @@ pub(crate) fn lower_ast_lru_base( let ind: usize; if let Some(curr_type_val) = curr_type { - let res = match curr_type_val.get_function(&context.type_storage, func.hash) { + let res = match curr_type_val.get_function(&context.global_scope, func.hash) { Ok(v) => v, Err(_) => { return Err( @@ -108,7 +108,7 @@ pub(crate) fn lower_ast_lru_base( let ind: usize; if let Some(curr_type_val) = curr_type { - let res = match curr_type_val.get_field(&context.type_storage, str.hash) { + let res = match curr_type_val.get_field(&context.global_scope, str.hash) { Ok(v) => v, Err(_) => { return Err( diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs index 0e3f219..ef3468b 100644 --- a/compiler/compiler_global_scope/src/entry.rs +++ b/compiler/compiler_global_scope/src/entry.rs @@ -1,13 +1,13 @@ //! Definitions for entries -use std::fmt::Display; +use std::{fmt::Display, hash::Hash}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_expected_simple_error}; use crate::GlobalStorageIdentifier; -#[derive(Clone, Debug)] -pub enum GlobalStorageEntryType { +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub enum GlobalStorageEntryType { Function { descriptor_ind: usize, impl_ind: usize, @@ -25,7 +25,7 @@ pub enum GlobalStorageEntryType { Type(R), } -impl GlobalStorageEntry { +impl GlobalStorageEntry { pub fn as_function( &self, origin: &K, @@ -171,13 +171,13 @@ impl GlobalStorageEntry { } } -#[derive(Debug)] -pub struct GlobalStorageEntry { +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub struct GlobalStorageEntry { pub entry_type: GlobalStorageEntryType, pub parent_index: usize, } -impl Display for GlobalStorageEntryType { +impl Display for GlobalStorageEntryType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { Self::Function { .. } => "function", diff --git a/compiler/compiler_global_scope/src/lib.rs b/compiler/compiler_global_scope/src/lib.rs index 8371052..4a4b222 100644 --- a/compiler/compiler_global_scope/src/lib.rs +++ b/compiler/compiler_global_scope/src/lib.rs @@ -1,7 +1,7 @@ -use std::collections::HashMap; +use std::{collections::HashMap, hash::Hash}; use diagnostics::{ - DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, + DiagnosticResult, DiagnosticSpanOrigin, builders::{make_already_in_scope, make_cannot_find, make_expected_simple_error}, }; @@ -16,10 +16,12 @@ pub mod key; pub type GlobalStorageIdentifier = usize; #[derive(Debug)] -pub struct GlobalScopeStorage { +pub struct GlobalScopeStorage { pub entry_to_ind: HashMap, pub entries: Vec>, + pub value_to_ind: HashMap, usize>, + pub descriptor_counter: usize, pub impl_counter: usize, } @@ -34,10 +36,11 @@ pub struct GlobalScopeStorage { /// /// # Safety /// The `GlobalScopeStorage` enforces correctness for global scope types and strictly allows only one entry per name. globally. -impl GlobalScopeStorage { +impl GlobalScopeStorage { pub fn new() -> Self { GlobalScopeStorage { entry_to_ind: HashMap::new(), + value_to_ind: HashMap::new(), entries: vec![], descriptor_counter: 0, impl_counter: 0, @@ -49,13 +52,15 @@ impl GlobalScopeStorage { name: EntryKey, entry: GlobalStorageEntryType, origin: &K, - ) -> MaybeDiagnostic { + ) -> DiagnosticResult { if self.entry_to_ind.contains_key(&name) { return Err(make_already_in_scope(origin, &name.name_hash).into()); } let parent_index = self.entries.len(); + self.value_to_ind.insert(entry.clone(), parent_index); + let entry = GlobalStorageEntry { entry_type: entry, parent_index, @@ -64,7 +69,7 @@ impl GlobalScopeStorage { self.entries.push(entry); self.entry_to_ind.insert(name, parent_index); - Ok(()) + Ok(parent_index) } pub fn get_base( diff --git a/compiler/compiler_typing/src/raw.rs b/compiler/compiler_typing/src/raw.rs index 2d8f0ef..a657d78 100644 --- a/compiler/compiler_typing/src/raw.rs +++ b/compiler/compiler_typing/src/raw.rs @@ -334,6 +334,21 @@ impl Hash for RawType { hasher.write_usize(container.self_ref); } + RawType::SizedInteger(signed) => { + hasher.write_usize(8); + hasher.write_u8(*signed as u8); + } + + RawType::SizedFloating(signed) => { + hasher.write_usize(9); + hasher.write_u8(*signed as u8); + } + + RawType::SizedFixedPoint(signed) => { + hasher.write_usize(8); + hasher.write_u8(*signed as u8); + } + _ => panic!("Unhashable type {:#?}", self), } } diff --git a/compiler/prelude/Cargo.toml b/compiler/prelude/Cargo.toml index 3eee720..2ccc10f 100644 --- a/compiler/prelude/Cargo.toml +++ b/compiler/prelude/Cargo.toml @@ -6,5 +6,6 @@ edition = "2024" [dependencies] compiler_typing = { path = "../compiler_typing" } compiler_utils = { path = "../compiler_utils" } +compiler_global_scope = { path = "../compiler_global_scope" } diagnostics = { path = "../diagnostics" } astoir_hir = { path = "../astoir_hir" } diff --git a/compiler/prelude/src/types.rs b/compiler/prelude/src/types.rs index 7af6403..ce83da9 100644 --- a/compiler/prelude/src/types.rs +++ b/compiler/prelude/src/types.rs @@ -1,7 +1,5 @@ -use astoir_hir::{ - ctx::HIRContext, - storage::{EntryKey, GlobalStorageEntryType}, -}; +use astoir_hir::ctx::HIRContext; +use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{ TypeParameterContainer, enums::RawEnumTypeContainer, raw::RawType, references::TypeReference, }; @@ -71,7 +69,9 @@ pub fn register_prelude_type( EntryKey { name_hash: hash }, GlobalStorageEntryType::Type(t), origin, - ) + )?; + + Ok(()) } pub fn apply_prelude_types( From c61815ffb37a1cd70f048553726c7ea5afa88793 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:06:50 +0200 Subject: [PATCH 46/60] feat: added global scope HIR version --- compiler/astoir_hir/src/lib.rs | 1 + compiler/astoir_hir/src/scope.rs | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 compiler/astoir_hir/src/scope.rs diff --git a/compiler/astoir_hir/src/lib.rs b/compiler/astoir_hir/src/lib.rs index d3fef0f..2642626 100644 --- a/compiler/astoir_hir/src/lib.rs +++ b/compiler/astoir_hir/src/lib.rs @@ -4,4 +4,5 @@ pub mod ctx; pub mod nodes; pub mod resolve; +pub mod scope; pub mod structs; diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs new file mode 100644 index 0000000..c176ccb --- /dev/null +++ b/compiler/astoir_hir/src/scope.rs @@ -0,0 +1,13 @@ +//! HIR version of the global scope in order to store descriptors and implementations + +use compiler_typing::TypedGlobalScope; + +use crate::{ctx::HIRFunction, nodes::HIRNode}; + +/// The HIR version of `GlobalScopeStorage`. Contains the descriptors and implementations. +/// Every function to append, gather will automatically handle descriptors and implementations if needed +pub struct HIRGlobalScopeStorage { + pub scope: TypedGlobalScope, + pub descriptors: Vec, + pub implementations: Vec>, +} From fd4d5e86ee6ad9ef208350c06f6102e8176ada1c Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:17:15 +0200 Subject: [PATCH 47/60] feat: added HIR scope append functions --- Cargo.lock | 1 + compiler/astoir_hir/Cargo.toml | 1 + compiler/astoir_hir/src/scope.rs | 103 +++++++++++++++++++++++++++- compiler/compiler_typing/src/lib.rs | 3 +- 4 files changed, 106 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f3c57a..cedf392 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,7 @@ dependencies = [ name = "astoir_hir" version = "0.1.0" dependencies = [ + "compiler_global_scope", "compiler_typing", "compiler_utils", "diagnostics", diff --git a/compiler/astoir_hir/Cargo.toml b/compiler/astoir_hir/Cargo.toml index 5850806..8f3e523 100644 --- a/compiler/astoir_hir/Cargo.toml +++ b/compiler/astoir_hir/Cargo.toml @@ -7,4 +7,5 @@ edition = "2024" compiler_utils = { path = "../compiler_utils" } diagnostics = { path = "../diagnostics" } compiler_typing = { path = "../compiler_typing" } +compiler_global_scope = { path = "../compiler_global_scope" } lexer = { path = "../lexer" } diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index c176ccb..c7c904d 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -1,6 +1,8 @@ //! HIR version of the global scope in order to store descriptors and implementations -use compiler_typing::TypedGlobalScope; +use compiler_global_scope::key::EntryKey; +use compiler_typing::{TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, tree::Type}; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin}; use crate::{ctx::HIRFunction, nodes::HIRNode}; @@ -11,3 +13,102 @@ pub struct HIRGlobalScopeStorage { pub descriptors: Vec, pub implementations: Vec>, } + +impl HIRGlobalScopeStorage { + pub fn new() -> Self { + HIRGlobalScopeStorage { + scope: TypedGlobalScope::new(), + descriptors: vec![], + implementations: vec![], + } + } + + /// This doesn't automatically handle descriptors and implementations + pub fn append( + &mut self, + name: EntryKey, + entry: TypedGlobalScopeEntry, + origin: &K, + ) -> DiagnosticResult { + self.scope.append(name, entry, origin) + } + + pub fn append_func( + &mut self, + name: EntryKey, + descriptor: HIRFunction, + implementation: Box, + origin: &K, + ) -> DiagnosticResult { + self.descriptors.push(descriptor); + self.implementations.push(implementation); + + self.scope.append( + name, + TypedGlobalScopeEntry::Function { + descriptor_ind: self.scope.descriptor_counter, + impl_ind: self.scope.impl_counter, + }, + origin, + ) + } + + pub fn append_implless_function( + &mut self, + name: EntryKey, + descriptor: HIRFunction, + origin: &K, + ) -> DiagnosticResult { + self.descriptors.push(descriptor); + + self.scope.append( + name, + TypedGlobalScopeEntry::ImplLessFunction(self.scope.descriptor_counter), + origin, + ) + } + + pub fn append_struct_function( + &mut self, + name: EntryKey, + descriptor: HIRFunction, + implementation: Box, + struct_type: RawType, + origin: &K, + ) -> DiagnosticResult { + self.descriptors.push(descriptor); + self.implementations.push(implementation); + + let ind = self.scope.value_to_ind[&TypedGlobalScopeEntry::Type(struct_type)]; + + self.scope.append( + name, + TypedGlobalScopeEntry::StructFunction { + descriptor_ind: self.scope.descriptor_counter, + impl_ind: self.scope.impl_counter, + struct_type: ind, + }, + origin, + ) + } + + pub fn append_type( + &mut self, + name: EntryKey, + t: RawType, + origin: &K, + ) -> DiagnosticResult { + self.scope + .append(name, TypedGlobalScopeEntry::Type(t), origin) + } + + pub fn append_type_binding( + &mut self, + name: EntryKey, + t: Type, + origin: &K, + ) -> DiagnosticResult { + self.scope + .append(name, TypedGlobalScopeEntry::TypeAlias(t), origin) + } +} diff --git a/compiler/compiler_typing/src/lib.rs b/compiler/compiler_typing/src/lib.rs index 2494b51..53aac65 100644 --- a/compiler/compiler_typing/src/lib.rs +++ b/compiler/compiler_typing/src/lib.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use compiler_global_scope::GlobalScopeStorage; +use compiler_global_scope::{GlobalScopeStorage, entry::GlobalStorageEntryType}; use compiler_utils::hash::HashedString; use diagnostics::DiagnosticResult; @@ -18,6 +18,7 @@ pub mod tree; pub mod utils; pub type TypedGlobalScope = GlobalScopeStorage; +pub type TypedGlobalScopeEntry = GlobalStorageEntryType; /// A function contained within a type. pub type TypedFunction = (Vec<(u64, TypeReference)>, Option); From 51e919907c93e4e828de63daa2bbe1ced97f2bc9 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:25:34 +0200 Subject: [PATCH 48/60] feat: added getters --- compiler/astoir_hir/src/scope.rs | 87 +++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 1 deletion(-) diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index c7c904d..0f65136 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -1,7 +1,11 @@ //! HIR version of the global scope in order to store descriptors and implementations +use std::collections::btree_map::Entry; + use compiler_global_scope::key::EntryKey; -use compiler_typing::{TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, tree::Type}; +use compiler_typing::{ + TypedGlobalScope, TypedGlobalScopeEntry, bounds::traits, raw::RawType, tree::Type, +}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin}; use crate::{ctx::HIRFunction, nodes::HIRNode}; @@ -111,4 +115,85 @@ impl HIRGlobalScopeStorage { self.scope .append(name, TypedGlobalScopeEntry::TypeAlias(t), origin) } + + pub fn get_base( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + self.scope.get_base(name, origin) + } + + pub fn get_type( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + self.scope.get_type(name, origin) + } + + pub fn get_static_variable( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + self.scope.get_static_variable(name, origin) + } + + pub fn get_function_base( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let ind = self.scope.get_function_base(name, origin)?; + + return Ok(self.descriptors[ind].clone()); + } + + pub fn get_function_impl( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult> { + let ind = self.scope.get_function_impl(name, origin)?; + + return Ok(self.implementations[ind].clone()); + } + + pub fn get_implless_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let ind = self.scope.get_implless_function(name, origin)?; + + return Ok(self.descriptors[ind].clone()); + } + + pub fn get_exact_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult<(HIRFunction, Box)> { + let inds = self.scope.get_exact_function(name, origin)?; + + return Ok(( + self.descriptors[inds.0].clone(), + self.implementations[inds.1].clone(), + )); + } + + pub fn get_exact_struct_function( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult<(HIRFunction, Box, RawType)> { + let res = self.scope.get_exact_struct_function(name, origin)?; + + return Ok(( + self.descriptors[res.0].clone(), + self.implementations[res.1].clone(), + res.2, + )); + } } From a3420cf18e08de928a2c85b86e33497cf1b5b86a Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:28:52 +0200 Subject: [PATCH 49/60] fix: fixed some errors --- compiler/astoir_hir/src/ctx.rs | 8 ++++---- compiler/astoir_hir/src/nodes.rs | 14 +++++++------- compiler/astoir_hir/src/resolve.rs | 4 ++-- compiler/astoir_hir/src/scope.rs | 7 ++----- compiler/astoir_mir_lowering/src/arrays.rs | 2 +- compiler/astoir_mir_lowering/src/introductions.rs | 4 ++-- compiler/astoir_mir_lowering/src/lib.rs | 12 ++++++------ compiler/astoir_mir_lowering/src/math.rs | 2 +- compiler/astoir_mir_lowering/src/type_tools.rs | 2 +- compiler/astoir_mir_lowering/src/values/consts.rs | 4 ++-- compiler/astoir_mir_lowering/src/values/structs.rs | 13 +++++++------ compiler/astoir_mir_lowering/src/vars.rs | 11 ++++++++--- compiler/prelude/src/types.rs | 2 +- 13 files changed, 44 insertions(+), 41 deletions(-) diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index 967d2f5..7414bef 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -2,14 +2,14 @@ use std::collections::{HashMap, HashSet}; -use compiler_typing::{TypedGlobalScope, tree::Type}; +use compiler_typing::tree::Type; use compiler_utils::{hash::SelfHash, utils::indexed::IndexStorage}; use diagnostics::{ DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_func, make_cannot_find_var, make_doesnt_exist_in_era}, }; -use crate::{nodes::HIRNode, structs::HIRStructContainer}; +use crate::{nodes::HIRNode, scope::HIRGlobalScopeStorage, structs::HIRStructContainer}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); @@ -278,7 +278,7 @@ pub struct HIRContext { pub function_contexts: Vec>, pub static_variables: IndexStorage, pub struct_func_impls: HashMap, - pub global_scope: TypedGlobalScope, + pub global_scope: HIRGlobalScopeStorage, } #[derive(PartialEq)] @@ -295,7 +295,7 @@ impl HIRContext { function_contexts: vec![], function_declarations: vec![], struct_func_impls: HashMap::new(), - global_scope: TypedGlobalScope::new(), + global_scope: HIRGlobalScopeStorage::new(), }; } diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index 5a8136c..caf3c60 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -316,7 +316,7 @@ impl HIRNode { return Ok(self.clone()); } - if self_type.can_transmute(&t, &context.global_scope) { + if self_type.can_transmute(&t, &context.global_scope.scope) { match &self.kind { HIRNodeKind::IntegerLiteral { value, int_type: _ } => { return Ok(self.with(HIRNodeKind::IntegerLiteral { @@ -326,7 +326,7 @@ impl HIRNode { } HIRNodeKind::ArrayVariableInitializerValue { vals } => { - if can_transmute_inner(&self_type, &t, &context.global_scope) { + if can_transmute_inner(&self_type, &t, &context.global_scope.scope) { let mut new_vals = vec![]; let inner = t.get_inner_type(); @@ -346,7 +346,7 @@ impl HIRNode { } HIRNodeKind::ArrayVariableInitializerValueSameValue { size, val } => { - if can_transmute_inner(&self_type, &t, &context.global_scope) { + if can_transmute_inner(&self_type, &t, &context.global_scope.scope) { let new_val = Box::new(val.use_as( context, curr_ctx, @@ -379,11 +379,11 @@ impl HIRNode { return Err(make_diff_type( origin, &"unnamed".to_string(), - &t.faulty_lowering_generic(&context.global_scope), + &t.faulty_lowering_generic(&context.global_scope.scope), &self .get_node_type(context, curr_ctx) .unwrap() - .faulty_lowering_generic(&context.global_scope), + .faulty_lowering_generic(&context.global_scope.scope), v, ) .into()); @@ -391,11 +391,11 @@ impl HIRNode { return Err(make_diff_type_val( origin, - &t.faulty_lowering_generic(&context.global_scope), + &t.faulty_lowering_generic(&context.global_scope.scope), &self .get_node_type(context, curr_ctx) .unwrap() - .faulty_lowering_generic(&context.global_scope), + .faulty_lowering_generic(&context.global_scope.scope), ) .into()); } diff --git a/compiler/astoir_hir/src/resolve.rs b/compiler/astoir_hir/src/resolve.rs index db2c50e..9945dfc 100644 --- a/compiler/astoir_hir/src/resolve.rs +++ b/compiler/astoir_hir/src/resolve.rs @@ -29,7 +29,7 @@ pub fn resolve_to_type( return Err(make_req_type_kind(origin, &"field-having".to_string()).into()); } - for field in destination.get_fields(&context.global_scope) { + for field in destination.get_fields(&context.global_scope.scope) { let identity = SelfHash { hash: field }; if !fields.contains_key(&identity) { @@ -39,7 +39,7 @@ pub fn resolve_to_type( let val = fields[&identity].clone(); let field_data = destination - .get_field(&context.global_scope, field)? + .get_field(&context.global_scope.scope, field)? .1 .resolve(&destination); diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index 0f65136..1c925ce 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -1,17 +1,14 @@ //! HIR version of the global scope in order to store descriptors and implementations -use std::collections::btree_map::Entry; - use compiler_global_scope::key::EntryKey; -use compiler_typing::{ - TypedGlobalScope, TypedGlobalScopeEntry, bounds::traits, raw::RawType, tree::Type, -}; +use compiler_typing::{TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin}; use crate::{ctx::HIRFunction, nodes::HIRNode}; /// The HIR version of `GlobalScopeStorage`. Contains the descriptors and implementations. /// Every function to append, gather will automatically handle descriptors and implementations if needed +#[derive(Debug)] pub struct HIRGlobalScopeStorage { pub scope: TypedGlobalScope, pub descriptors: Vec, diff --git a/compiler/astoir_mir_lowering/src/arrays.rs b/compiler/astoir_mir_lowering/src/arrays.rs index 67e0216..84dc736 100644 --- a/compiler/astoir_mir_lowering/src/arrays.rs +++ b/compiler/astoir_mir_lowering/src/arrays.rs @@ -54,7 +54,7 @@ pub fn lower_hir_array_modify( build_store( &mut ctx.mir_ctx, - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, index_pointer, val, )?; diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index c15e122..6b7583e 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -44,7 +44,7 @@ pub fn handle_var_introduction_queue( } else { let ptr = build_stack_alloc( &mut ctx.mir_ctx, - new_type.get_size(&new_type, false, &ctx.hir_ctx.global_scope), + new_type.get_size(&new_type, false, &ctx.hir_ctx.global_scope.scope), new_type, )?; @@ -57,7 +57,7 @@ pub fn handle_var_introduction_queue( ); build_store( &mut ctx.mir_ctx, - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, ptr.clone(), casted, )?; diff --git a/compiler/astoir_mir_lowering/src/lib.rs b/compiler/astoir_mir_lowering/src/lib.rs index 38010b5..7f82170 100644 --- a/compiler/astoir_mir_lowering/src/lib.rs +++ b/compiler/astoir_mir_lowering/src/lib.rs @@ -105,11 +105,11 @@ pub fn lower_hir_generic( hir_mir_indexes: HashMap::new(), }; - let parent = match &ctx.hir_ctx.global_scope.entries[container.parent].as_type_unsafe() - { - RawType::Enum(container) => container.clone(), - _ => panic!("Enum parent not enum"), - }; + let parent = + match &ctx.hir_ctx.global_scope.scope.entries[container.parent].as_type_unsafe() { + RawType::Enum(container) => container.clone(), + _ => panic!("Enum parent not enum"), + }; lowered_container .fields @@ -158,7 +158,7 @@ pub fn lower_hir_generic( entry_size = entry_size.max(lowered.get_generic().get_size( &lowered, false, - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, )) } diff --git a/compiler/astoir_mir_lowering/src/math.rs b/compiler/astoir_mir_lowering/src/math.rs index b7556bc..af6c034 100644 --- a/compiler/astoir_mir_lowering/src/math.rs +++ b/compiler/astoir_mir_lowering/src/math.rs @@ -62,7 +62,7 @@ pub fn lower_hir_math_operation( block, &mut ctx.mir_ctx, val.clone(), - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, )?; } diff --git a/compiler/astoir_mir_lowering/src/type_tools.rs b/compiler/astoir_mir_lowering/src/type_tools.rs index ee20c68..9bef158 100644 --- a/compiler/astoir_mir_lowering/src/type_tools.rs +++ b/compiler/astoir_mir_lowering/src/type_tools.rs @@ -68,7 +68,7 @@ pub fn is_enum_value_of_kind( hint_type.get_size( &Type::GenericLowered(hint_type.clone()), false, - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, ), )?; diff --git a/compiler/astoir_mir_lowering/src/values/consts.rs b/compiler/astoir_mir_lowering/src/values/consts.rs index 51ac743..52021ec 100644 --- a/compiler/astoir_mir_lowering/src/values/consts.rs +++ b/compiler/astoir_mir_lowering/src/values/consts.rs @@ -18,7 +18,7 @@ pub fn lower_hir_literal( let val = build_signed_int_const( &mut ctx.mir_ctx, value, - int_type.get_size(&int_type, true, &ctx.hir_ctx.global_scope), + int_type.get_size(&int_type, true, &ctx.hir_ctx.global_scope.scope), )?; return Ok(val.into()); @@ -27,7 +27,7 @@ pub fn lower_hir_literal( let val = build_unsigned_int_const( &mut ctx.mir_ctx, value as u128, - int_type.get_size(&int_type, true, &ctx.hir_ctx.global_scope), + int_type.get_size(&int_type, true, &ctx.hir_ctx.global_scope.scope), )?; return Ok(val.into()); diff --git a/compiler/astoir_mir_lowering/src/values/structs.rs b/compiler/astoir_mir_lowering/src/values/structs.rs index 00b1720..f83005c 100644 --- a/compiler/astoir_mir_lowering/src/values/structs.rs +++ b/compiler/astoir_mir_lowering/src/values/structs.rs @@ -25,11 +25,12 @@ pub fn lower_hir_struct_init( } RawType::EnumEntry(container) => { - let parent = - match &ctx.hir_ctx.global_scope.entries[container.parent].as_type_unsafe() { - RawType::Enum(container) => container.clone(), - _ => panic!("Enum parent not enum"), - }; + let parent = match &ctx.hir_ctx.global_scope.scope.entries[container.parent] + .as_type_unsafe() + { + RawType::Enum(container) => container.clone(), + _ => panic!("Enum parent not enum"), + }; let hint = build_unsigned_int_const( &mut ctx.mir_ctx, @@ -37,7 +38,7 @@ pub fn lower_hir_struct_init( parent.get_hint_type().get_size( &Type::GenericLowered(parent.get_hint_type()), false, - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, ), )?; diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index 993d623..5ca0bb0 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -51,7 +51,7 @@ pub fn lower_hir_variable_declaration( let ptr = build_stack_alloc( &mut ctx.mir_ctx, - lowered.get_size(&lowered, false, &ctx.hir_ctx.global_scope), + lowered.get_size(&lowered, false, &ctx.hir_ctx.global_scope.scope), lowered, )?; @@ -68,7 +68,7 @@ pub fn lower_hir_variable_declaration( build_store( &mut ctx.mir_ctx, - &ctx.hir_ctx.global_scope, + &ctx.hir_ctx.global_scope.scope, ptr.clone(), val, )?; @@ -121,7 +121,12 @@ pub fn lower_hir_variable_assignment( let val = lower_hir_value(block, val, ctx)?; - variable_ref.write(block, &mut ctx.mir_ctx, val, &ctx.hir_ctx.global_scope)?; + variable_ref.write( + block, + &mut ctx.mir_ctx, + val, + &ctx.hir_ctx.global_scope.scope, + )?; return Ok(true); } diff --git a/compiler/prelude/src/types.rs b/compiler/prelude/src/types.rs index ce83da9..6763faf 100644 --- a/compiler/prelude/src/types.rs +++ b/compiler/prelude/src/types.rs @@ -272,7 +272,7 @@ pub fn apply_prelude_types( type_params.insert(HashedString::new("E".to_string()), 1); let mut result_enum = - RawEnumTypeContainer::new(hir.global_scope.entries.len(), type_params); + RawEnumTypeContainer::new(hir.global_scope.scope.entries.len(), type_params); result_enum.append_entry( HashedString::new("value".to_string()), From 1022eb958c68d3d1b5b1f8d833dbbef671662fad Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:30:46 +0200 Subject: [PATCH 50/60] fix: fixed some errors --- compiler/astoir_hir_lowering/src/enums.rs | 2 +- compiler/astoir_hir_lowering/src/structs.rs | 4 ++-- compiler/astoir_hir_lowering/src/types.rs | 7 ++++--- compiler/astoir_hir_lowering/src/uses.rs | 7 ++++--- compiler/astoir_hir_lowering/src/values.rs | 4 ++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/compiler/astoir_hir_lowering/src/enums.rs b/compiler/astoir_hir_lowering/src/enums.rs index afb713b..dcaa24d 100644 --- a/compiler/astoir_hir_lowering/src/enums.rs +++ b/compiler/astoir_hir_lowering/src/enums.rs @@ -47,7 +47,7 @@ pub fn lower_ast_enum( } = node.kind.clone() { let mut container = - RawEnumTypeContainer::new(context.global_scope.entries.len(), type_params); + RawEnumTypeContainer::new(context.global_scope.scope.entries.len(), type_params); for entry in entries { lower_ast_enum_entry(context, entry, &mut container)?; diff --git a/compiler/astoir_hir_lowering/src/structs.rs b/compiler/astoir_hir_lowering/src/structs.rs index c43d639..a794444 100644 --- a/compiler/astoir_hir_lowering/src/structs.rs +++ b/compiler/astoir_hir_lowering/src/structs.rs @@ -120,13 +120,13 @@ pub fn lower_ast_struct_declaration( &ASTTreeNodeKind::StructFieldMember { .. } => { lower_ast_struct_member(context, member, &mut container)?; - context.global_scope.entries[ind].entry_type = + context.global_scope.scope.entries[ind].entry_type = GlobalStorageEntryType::Type(RawType::Struct(layout, container.clone())); } &ASTTreeNodeKind::FunctionDeclaration { .. } => { let body = lower_ast_struct_function_decl(context, member, &mut container)?; - context.global_scope.entries[ind].entry_type = + context.global_scope.scope.entries[ind].entry_type = GlobalStorageEntryType::Type(RawType::Struct(layout, container.clone())); func_impls.push(body); diff --git a/compiler/astoir_hir_lowering/src/types.rs b/compiler/astoir_hir_lowering/src/types.rs index a7da026..95d9b44 100644 --- a/compiler/astoir_hir_lowering/src/types.rs +++ b/compiler/astoir_hir_lowering/src/types.rs @@ -37,11 +37,11 @@ pub fn lower_ast_type( t = container.get_entry(HashedString::new(specifier.unwrap()))? } - if t.get_type_params_count(&context.global_scope, origin)? != type_params.len() { + if t.get_type_params_count(&context.global_scope.scope, origin)? != type_params.len() { return Err(make_diff_type_specifiers( origin, &type_params.len(), - &t.get_type_params_count(&context.global_scope, origin)?, + &t.get_type_params_count(&context.global_scope.scope, origin)?, ) .into()); } @@ -59,6 +59,7 @@ pub fn lower_ast_type( if context .global_scope + .scope .value_to_ind .contains_key(&GlobalStorageEntryType::Type(lower.clone())) { @@ -74,7 +75,7 @@ pub fn lower_ast_type( }; return Ok(Type::Generic( - context.global_scope.entries[ind].as_type_unsafe(), + context.global_scope.scope.entries[ind].as_type_unsafe(), vec![], vec![], )); diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index f0b1dc0..2a6c8b9 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -179,11 +179,11 @@ pub fn lower_ast_type_use_statement( t = container.get_entry(HashedString::new(specifier.unwrap()))? } - if t.get_type_params_count(&context.global_scope, origin)? != type_params.len() { + if t.get_type_params_count(&context.global_scope.scope, origin)? != type_params.len() { return Err(make_diff_type_specifiers( origin, &type_params.len(), - &t.get_type_params_count(&context.global_scope, origin)?, + &t.get_type_params_count(&context.global_scope.scope, origin)?, ) .into()); } @@ -201,6 +201,7 @@ pub fn lower_ast_type_use_statement( if context .global_scope + .scope .value_to_ind .contains_key(&GlobalStorageEntryType::Type(lower.clone())) { @@ -218,7 +219,7 @@ pub fn lower_ast_type_use_statement( }; return Ok(Type::Generic( - context.global_scope.entries[ind].as_type_unsafe(), + context.global_scope.scope.entries[ind].as_type_unsafe(), vec![], vec![], )); diff --git a/compiler/astoir_hir_lowering/src/values.rs b/compiler/astoir_hir_lowering/src/values.rs index e5418b9..7a897f3 100644 --- a/compiler/astoir_hir_lowering/src/values.rs +++ b/compiler/astoir_hir_lowering/src/values.rs @@ -37,7 +37,7 @@ pub(crate) fn lower_ast_lru_base( let ind: usize; if let Some(curr_type_val) = curr_type { - let res = match curr_type_val.get_function(&context.global_scope, func.hash) { + let res = match curr_type_val.get_function(&context.global_scope.scope, func.hash) { Ok(v) => v, Err(_) => { return Err( @@ -108,7 +108,7 @@ pub(crate) fn lower_ast_lru_base( let ind: usize; if let Some(curr_type_val) = curr_type { - let res = match curr_type_val.get_field(&context.global_scope, str.hash) { + let res = match curr_type_val.get_field(&context.global_scope.scope, str.hash) { Ok(v) => v, Err(_) => { return Err( From 52e705333978dc4b68effd308dbcec3044fc41e5 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:33:29 +0200 Subject: [PATCH 51/60] feat: added branched contexts inside of HIR global scope --- compiler/astoir_hir/src/ctx.rs | 1 + compiler/astoir_hir/src/scope.rs | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index 7414bef..31f39a2 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -12,6 +12,7 @@ use diagnostics::{ use crate::{nodes::HIRNode, scope::HIRGlobalScopeStorage, structs::HIRStructContainer}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); +pub type HIRFunctionImpl = (HIRBranchedContext, Box); /// The function HIR context. Contains a mapping from element name hash to element index and other variable information. /// Uses a branch based system to contain variables. diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index 1c925ce..eacf2ca 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -4,7 +4,10 @@ use compiler_global_scope::key::EntryKey; use compiler_typing::{TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin}; -use crate::{ctx::HIRFunction, nodes::HIRNode}; +use crate::{ + ctx::{HIRBranchedContext, HIRFunction, HIRFunctionImpl}, + nodes::HIRNode, +}; /// The HIR version of `GlobalScopeStorage`. Contains the descriptors and implementations. /// Every function to append, gather will automatically handle descriptors and implementations if needed @@ -12,7 +15,7 @@ use crate::{ctx::HIRFunction, nodes::HIRNode}; pub struct HIRGlobalScopeStorage { pub scope: TypedGlobalScope, pub descriptors: Vec, - pub implementations: Vec>, + pub implementations: Vec, } impl HIRGlobalScopeStorage { @@ -39,10 +42,11 @@ impl HIRGlobalScopeStorage { name: EntryKey, descriptor: HIRFunction, implementation: Box, + brctx: HIRBranchedContext, origin: &K, ) -> DiagnosticResult { self.descriptors.push(descriptor); - self.implementations.push(implementation); + self.implementations.push((brctx, implementation)); self.scope.append( name, @@ -74,11 +78,12 @@ impl HIRGlobalScopeStorage { name: EntryKey, descriptor: HIRFunction, implementation: Box, + brctx: HIRBranchedContext, struct_type: RawType, origin: &K, ) -> DiagnosticResult { self.descriptors.push(descriptor); - self.implementations.push(implementation); + self.implementations.push((brctx, implementation)); let ind = self.scope.value_to_ind[&TypedGlobalScopeEntry::Type(struct_type)]; @@ -151,7 +156,7 @@ impl HIRGlobalScopeStorage { &self, name: EntryKey, origin: &K, - ) -> DiagnosticResult> { + ) -> DiagnosticResult { let ind = self.scope.get_function_impl(name, origin)?; return Ok(self.implementations[ind].clone()); @@ -171,7 +176,7 @@ impl HIRGlobalScopeStorage { &self, name: EntryKey, origin: &K, - ) -> DiagnosticResult<(HIRFunction, Box)> { + ) -> DiagnosticResult<(HIRFunction, HIRFunctionImpl)> { let inds = self.scope.get_exact_function(name, origin)?; return Ok(( @@ -184,7 +189,7 @@ impl HIRGlobalScopeStorage { &self, name: EntryKey, origin: &K, - ) -> DiagnosticResult<(HIRFunction, Box, RawType)> { + ) -> DiagnosticResult<(HIRFunction, HIRFunctionImpl, RawType)> { let res = self.scope.get_exact_struct_function(name, origin)?; return Ok(( From d1eb351c154bf38e3ee7ec3c9f0bbf16b94dd898 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:37:30 +0200 Subject: [PATCH 52/60] feat: cleaned HIR Context out of global scope contained elements --- compiler/astoir_hir/src/ctx.rs | 45 ++++++----------------- compiler/compiler_global_scope/src/key.rs | 2 +- 2 files changed, 12 insertions(+), 35 deletions(-) diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index 31f39a2..797a70a 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -2,14 +2,15 @@ use std::collections::{HashMap, HashSet}; +use compiler_global_scope::key::EntryKey; use compiler_typing::tree::Type; -use compiler_utils::{hash::SelfHash, utils::indexed::IndexStorage}; +use compiler_utils::hash::SelfHash; use diagnostics::{ DiagnosticResult, DiagnosticSpanOrigin, - builders::{make_cannot_find_func, make_cannot_find_var, make_doesnt_exist_in_era}, + builders::{make_cannot_find_var, make_doesnt_exist_in_era}, }; -use crate::{nodes::HIRNode, scope::HIRGlobalScopeStorage, structs::HIRStructContainer}; +use crate::{nodes::HIRNode, scope::HIRGlobalScopeStorage}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); pub type HIRFunctionImpl = (HIRBranchedContext, Box); @@ -274,11 +275,6 @@ pub struct HIRBranchedVariable { #[derive(Debug)] pub struct HIRContext { - pub functions: IndexStorage, - pub function_declarations: Vec>>, - pub function_contexts: Vec>, - pub static_variables: IndexStorage, - pub struct_func_impls: HashMap, pub global_scope: HIRGlobalScopeStorage, } @@ -291,25 +287,9 @@ pub enum VariableKind { impl HIRContext { pub fn new() -> Self { return HIRContext { - functions: IndexStorage::new(), - static_variables: IndexStorage::new(), - function_contexts: vec![], - function_declarations: vec![], - struct_func_impls: HashMap::new(), global_scope: HIRGlobalScopeStorage::new(), }; } - - pub fn translate_function( - &self, - func_hash: u64, - origin: &K, - ) -> DiagnosticResult { - return match self.functions.get_index(func_hash) { - Some(v) => Ok(v), - None => return Err(make_cannot_find_func(origin, &func_hash).into()), - }; - } } pub fn get_variable( @@ -328,15 +308,12 @@ pub fn get_variable( )); } - match context.static_variables.get_index(hash) { - Some(v) => { - return Ok(( - VariableKind::STATIC, - context.static_variables.vals[v].clone(), - v, - )); - } + let name = EntryKey { name_hash: hash }; + + let ind = context.global_scope.scope.value_to_ind + [&context.global_scope.get_base(name.clone(), origin)?]; + + let t = context.global_scope.get_static_variable(name, origin)?; - None => return Err(make_cannot_find_var(origin, &hash).into()), - }; + Ok((VariableKind::STATIC, t, ind)) } diff --git a/compiler/compiler_global_scope/src/key.rs b/compiler/compiler_global_scope/src/key.rs index ed250ba..2f8827f 100644 --- a/compiler/compiler_global_scope/src/key.rs +++ b/compiler/compiler_global_scope/src/key.rs @@ -1,7 +1,7 @@ use std::hash::Hash; /// Represents a key to a global storage entry. Potentially allows for namespaces later on -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct EntryKey { pub name_hash: u64, } From 7276b82f694651bb36842065df8dd73df83fc301 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:45:18 +0200 Subject: [PATCH 53/60] feat: cleaned nodes to use global scope --- compiler/astoir_hir/src/nodes.rs | 33 +++++++++++++++++++++++----- compiler/diagnostics/src/builders.rs | 17 ++++++++++++++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index caf3c60..d9bc8ce 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use compiler_typing::{ - enums::RawEnumTypeContainer, raw::RawType, references::TypeReference, + TypedGlobalScopeEntry, enums::RawEnumTypeContainer, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type, }; use compiler_utils::{ @@ -13,7 +13,7 @@ use compiler_utils::{ }; use diagnostics::{ DiagnosticSpanOrigin, - builders::{make_diff_type, make_diff_type_val}, + builders::{make_diff_type, make_diff_type_val, make_expected_simple_error_originless}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic, }; @@ -416,7 +416,9 @@ impl HIRNode { match &self.kind { HIRNodeKind::VariableReference { index, is_static } => { if *is_static { - return Some(context.static_variables.vals[*index].clone()); + return Some( + context.global_scope.scope.entries[*index].as_static_variable_unsafe(), + ); } return Some(curr_ctx.variables[*index].variable_type.clone()); @@ -490,9 +492,30 @@ impl HIRNode { func_name, arguments: _, } => { - let f = context.functions.vals[*func_name].0.clone(); + //let f = context.functions.vals[*func_name].0.clone(); + let ind = match &context.global_scope.scope.entries[*func_name].entry_type { + TypedGlobalScopeEntry::Function { + descriptor_ind, + impl_ind: _, + } => descriptor_ind, + TypedGlobalScopeEntry::ImplLessFunction(ind) => ind, + TypedGlobalScopeEntry::StructFunction { + descriptor_ind, + impl_ind: _, + struct_type: _, + } => descriptor_ind, + + _ => { + make_expected_simple_error_originless( + &"function".to_string(), + &context.global_scope.scope.entries[*func_name].entry_type, + ); + + return None; + } + }; - return f; + return context.global_scope.descriptors[*ind].clone().0; } _ => return None, diff --git a/compiler/diagnostics/src/builders.rs b/compiler/diagnostics/src/builders.rs index e3b3006..f5980cf 100644 --- a/compiler/diagnostics/src/builders.rs +++ b/compiler/diagnostics/src/builders.rs @@ -31,6 +31,23 @@ pub fn make_expected_simple_error( + expected: &E, + got: &G, +) -> Diagnostic { + let main_span = Span::make_primary(get_current_diagnostic_pos(), None); + + Diagnostic::new_base( + Level::Error, + EXPECTED_TOKEN.0, + format!("expected {} but got {}", expected, got), + main_span, + vec![], + vec![], + vec![], + ) +} + pub fn make_unexpected_simple_error( origin: &K, got: &E, From 005a2fc0f1ca29381073baa4298ba4477b1e0e31 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 11:58:09 +0200 Subject: [PATCH 54/60] feat: lowered HIR functions to global scope --- compiler/astoir_hir/src/scope.rs | 14 ++++- compiler/astoir_hir_lowering/src/func.rs | 77 ++++++++++++++++-------- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index eacf2ca..fb1c318 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -2,7 +2,7 @@ use compiler_global_scope::key::EntryKey; use compiler_typing::{TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, tree::Type}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin}; +use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_cannot_find}; use crate::{ ctx::{HIRBranchedContext, HIRFunction, HIRFunctionImpl}, @@ -126,6 +126,18 @@ impl HIRGlobalScopeStorage { self.scope.get_base(name, origin) } + pub fn get_ind( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + if self.scope.entry_to_ind.contains_key(&name) { + return Ok(self.scope.entry_to_ind[&name]); + } + + return Err(make_cannot_find(origin, &name.name_hash).into()); + } + pub fn get_type( &self, name: EntryKey, diff --git a/compiler/astoir_hir_lowering/src/func.rs b/compiler/astoir_hir_lowering/src/func.rs index 76aa5f4..0bf3293 100644 --- a/compiler/astoir_hir_lowering/src/func.rs +++ b/compiler/astoir_hir_lowering/src/func.rs @@ -3,10 +3,9 @@ use astoir_hir::{ ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, }; -use diagnostics::{ - DiagnosticResult, - builders::{make_already_in_scope, make_cannot_find_func}, -}; +use compiler_global_scope::key::EntryKey; +use compiler_typing::TypedGlobalScopeEntry; +use diagnostics::{DiagnosticResult, builders::make_already_in_scope}; use crate::{lower_ast_body, types::lower_ast_type, values::lower_ast_value}; @@ -16,12 +15,16 @@ pub fn lower_ast_function_call( node: Box, ) -> DiagnosticResult> { if let ASTTreeNodeKind::FunctionCall { func, args } = node.kind.clone() { - let f_ind = match context.functions.get_index(func.hash) { - Some(v) => v, - None => return Err(make_cannot_find_func(&*node, &func.hash).into()), + let name = EntryKey { + name_hash: func.hash, }; - let func = &context.functions.vals[f_ind].clone(); + let func = context + .global_scope + .get_function_base(name.clone(), &*node)?; + + let func_ind = context.global_scope.get_ind(name, &*node)?; + let mut hir_args = vec![]; let mut ind = 0; @@ -37,7 +40,7 @@ pub fn lower_ast_function_call( return Ok(Box::new(HIRNode::new( HIRNodeKind::FunctionCall { - func_name: f_ind, + func_name: func_ind, arguments: hir_args, }, &node.start, @@ -91,15 +94,21 @@ pub fn lower_ast_function_declaration( } } - let ind = context.functions.append( - func_name.hash, + let key = EntryKey { + name_hash: func_name.hash, + }; + + let entry = + TypedGlobalScopeEntry::ImplLessFunction(context.global_scope.scope.descriptor_counter); + + let ind = context.global_scope.append_implless_function( + key.clone(), (ret_type.clone(), arguments.clone(), func_name.val.clone()), - ); + &*node, + )?; let body = lower_ast_body(context, &mut curr_ctx, body, false)?; - context.function_contexts.push(Some(curr_ctx.clone())); - curr_ctx.end_branch(branch); for var in 0..curr_ctx.variables.len() { @@ -108,18 +117,37 @@ pub fn lower_ast_function_declaration( } } - return Ok(Box::new(HIRNode::new( + let implementation = Box::new(HIRNode::new( HIRNodeKind::FunctionDeclaration { func_name: ind, - arguments, - return_type: ret_type, + arguments: arguments.clone(), + return_type: ret_type.clone(), body, - ctx: curr_ctx, + ctx: curr_ctx.clone(), requires_this, }, &node.start, &node.end, - ))); + )); + + // Remove old impless version + context.global_scope.scope.entries.pop(); + context.global_scope.scope.entry_to_ind.remove(&key); + context.global_scope.scope.value_to_ind.remove(&entry); + context.global_scope.descriptors.pop(); + context.global_scope.scope.descriptor_counter -= 1; + + // Append the new verison as a impl-containing function + + context.global_scope.append_func( + key, + (ret_type.clone(), arguments.clone(), func_name.val.clone()), + implementation.clone(), + curr_ctx.clone(), + &*node, + ); + + return Ok(implementation); } panic!("Invalid node passed!"); @@ -155,12 +183,13 @@ pub fn lower_ast_shadow_function_declaration( arguments.push((arg.name.hash, t)); } - let ind = context.functions.append( - func_name.hash, + let ind = context.global_scope.append_implless_function( + EntryKey { + name_hash: func_name.hash, + }, (ret_type.clone(), arguments.clone(), func_name.val.clone()), - ); - - context.function_contexts.push(None); + &*node, + )?; return Ok(Box::new(HIRNode::new( HIRNodeKind::ShadowFunctionDeclaration { From 586eab1971eab88c746ad3917a6359aa0aa06393 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 12:14:49 +0200 Subject: [PATCH 55/60] fix: fixed HIR lowering layer from errors --- compiler/astoir_hir_lowering/src/func.rs | 2 +- compiler/astoir_hir_lowering/src/lib.rs | 8 +-- compiler/astoir_hir_lowering/src/structs.rs | 72 +++++++++++++++------ compiler/astoir_hir_lowering/src/uses.rs | 28 ++------ compiler/astoir_hir_lowering/src/values.rs | 14 ++-- compiler/compiler_typing/src/raw.rs | 5 ++ compiler/compiler_typing/src/structs.rs | 2 + 7 files changed, 74 insertions(+), 57 deletions(-) diff --git a/compiler/astoir_hir_lowering/src/func.rs b/compiler/astoir_hir_lowering/src/func.rs index 0bf3293..4f0fe7a 100644 --- a/compiler/astoir_hir_lowering/src/func.rs +++ b/compiler/astoir_hir_lowering/src/func.rs @@ -145,7 +145,7 @@ pub fn lower_ast_function_declaration( implementation.clone(), curr_ctx.clone(), &*node, - ); + )?; return Ok(implementation); } diff --git a/compiler/astoir_hir_lowering/src/lib.rs b/compiler/astoir_hir_lowering/src/lib.rs index c434689..863a7b4 100644 --- a/compiler/astoir_hir_lowering/src/lib.rs +++ b/compiler/astoir_hir_lowering/src/lib.rs @@ -123,17 +123,13 @@ pub fn lower_ast_toplevel( ) -> DiagnosticResult { match node.kind { ASTTreeNodeKind::FunctionDeclaration { .. } => { - let func_decl = lower_ast_function_declaration(context, node)?; - - context.function_declarations.push(Some(func_decl)); + lower_ast_function_declaration(context, node)?; return Ok(true); } ASTTreeNodeKind::ShadowFunctionDeclaration { .. } => { - let func_decl = lower_ast_shadow_function_declaration(context, node)?; - - context.function_declarations.push(Some(func_decl)); + lower_ast_shadow_function_declaration(context, node)?; return Ok(true); } diff --git a/compiler/astoir_hir_lowering/src/structs.rs b/compiler/astoir_hir_lowering/src/structs.rs index a794444..3dcd4cf 100644 --- a/compiler/astoir_hir_lowering/src/structs.rs +++ b/compiler/astoir_hir_lowering/src/structs.rs @@ -1,14 +1,16 @@ -use std::collections::HashMap; +use std::{ + collections::HashMap, + hash::{DefaultHasher, Hash, Hasher}, +}; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use astoir_hir::{ ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, - structs::HIRStructContainer, }; use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{raw::RawType, structs::RawStructTypeContainer}; -use compiler_utils::utils::indexed::IndexStorage; +use compiler_utils::{hash::HashedString, utils::indexed::IndexStorage}; use diagnostics::{DiagnosticResult, builders::make_already_in_scope}; use crate::{lower_ast_body, types::lower_ast_type_struct, values::lower_ast_value}; @@ -32,7 +34,8 @@ fn lower_ast_struct_function_decl( context: &mut HIRContext, node: Box, container: &mut RawStructTypeContainer, -) -> DiagnosticResult> { + ty: RawType, +) -> DiagnosticResult<(Box, usize)> { if let ASTTreeNodeKind::FunctionDeclaration { func_name, args, @@ -66,18 +69,47 @@ fn lower_ast_struct_function_decl( .functions .append(func_name.hash, (arguments.clone(), ret_type.clone())); - return Ok(Box::new(HIRNode::new( + let implementation = Box::new(HIRNode::new( HIRNodeKind::StructFunctionDeclaration { func_name: ind, - arguments, - return_type: ret_type, + arguments: arguments.clone(), + return_type: ret_type.clone(), body, - ctx: curr_ctx, + ctx: curr_ctx.clone(), requires_this, }, &node.start, &node.end, - ))); + )); + + let mut hasher = DefaultHasher::new(); + ty.hash(&mut hasher); + + let fnname = format!("{}$${}", hasher.finish(), func_name.hash); + + let ret_type2; + let mut arguments2 = vec![]; + + if let Some(v) = ret_type { + ret_type2 = Some(v.as_resolved()) // TODO: This unsupports generics, maybe fix later + } else { + ret_type2 = None; + } + + for arg in &arguments { + arguments2.push((arg.0, arg.1.clone().as_resolved())); + } + + context.global_scope.append_struct_function( + EntryKey { + name_hash: HashedString::new(fnname.clone()).hash, + }, + (ret_type2, arguments2, fnname), + implementation, + curr_ctx, + ty, + &*node, + )?; } panic!("Invalid node type") @@ -98,10 +130,10 @@ pub fn lower_ast_struct_declaration( fields: IndexStorage::new(), functions: IndexStorage::new(), type_params, + function_ids: vec![], + self_ref: context.global_scope.scope.entries.len(), }; - let mut func_impls = vec![]; - let base = RawType::Struct(layout, container.clone()); let ind = match context.global_scope.append( @@ -124,25 +156,23 @@ pub fn lower_ast_struct_declaration( GlobalStorageEntryType::Type(RawType::Struct(layout, container.clone())); } &ASTTreeNodeKind::FunctionDeclaration { .. } => { - let body = lower_ast_struct_function_decl(context, member, &mut container)?; + let body = lower_ast_struct_function_decl( + context, + member, + &mut container, + context.global_scope.scope.entries[ind].as_type_unsafe(), + )?; + + container.function_ids.push(body.1); context.global_scope.scope.entries[ind].entry_type = GlobalStorageEntryType::Type(RawType::Struct(layout, container.clone())); - - func_impls.push(body); } _ => panic!("Invalid node type"), }; } - context.struct_func_impls.insert( - ind, - HIRStructContainer { - function_impls: func_impls, - }, - ); - return Ok(Box::new(HIRNode::new( HIRNodeKind::StructDeclaration { type_name: ind, diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs index 2a6c8b9..d0ec07f 100644 --- a/compiler/astoir_hir_lowering/src/uses.rs +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -6,10 +6,7 @@ use ast::{ types::ASTType, }; use ast_parser::parse_ast_ctx; -use astoir_hir::{ - ctx::HIRContext, - nodes::{HIRNode, HIRNodeKind}, -}; +use astoir_hir::ctx::HIRContext; use compiler_global_scope::{entry::GlobalStorageEntryType, key::EntryKey}; use compiler_typing::{raw::RawType, tree::Type}; use compiler_utils::hash::HashedString; @@ -60,24 +57,13 @@ pub fn handle_ast_use_statement_function_decl( arguments.push((arg.name.hash, t)); } - let func_name = context.functions.append( - func_name.hash, - (ret_type.clone(), arguments.clone(), func_name.val.clone()), - ); - context.function_contexts.push(None); - - // Fabricate shadow func statement to satisfy functions_declarations - - let node = HIRNode::new( - HIRNodeKind::ShadowFunctionDeclaration { - func_name, - arguments, - return_type: ret_type, + let _ = context.global_scope.append_implless_function( + EntryKey { + name_hash: func_name.hash, }, - &node.start, - &node.end, - ); - context.function_declarations.push(Some(Box::new(node))); + (ret_type.clone(), arguments.clone(), func_name.val.clone()), + &*node, + )?; return Ok(()); } diff --git a/compiler/astoir_hir_lowering/src/values.rs b/compiler/astoir_hir_lowering/src/values.rs index 7a897f3..c96a61e 100644 --- a/compiler/astoir_hir_lowering/src/values.rs +++ b/compiler/astoir_hir_lowering/src/values.rs @@ -4,13 +4,11 @@ use astoir_hir::{ nodes::{HIRNode, HIRNodeKind}, structs::StructLRUStep, }; +use compiler_global_scope::key::EntryKey; use compiler_typing::tree::Type; use diagnostics::{ DiagnosticResult, - builders::{ - make_cannot_find_func, make_invalid_pointing, make_struct_missing_field, - make_struct_missing_func, - }, + builders::{make_invalid_pointing, make_struct_missing_field, make_struct_missing_func}, }; use crate::{ @@ -66,12 +64,12 @@ pub(crate) fn lower_ast_lru_base( ind = res.0; } else { - ind = match context.functions.get_index(func.hash) { - Some(v) => v, - None => return Err(make_cannot_find_func(&*node, &func.val).into()), + let entry = EntryKey { + name_hash: func.hash, }; - func_type = context.functions.vals[ind].clone(); + ind = context.global_scope.get_ind(entry.clone(), &*node)?; + func_type = context.global_scope.get_function_base(entry, &*node)?; } let mut hir_args = vec![]; diff --git a/compiler/compiler_typing/src/raw.rs b/compiler/compiler_typing/src/raw.rs index a657d78..6d48971 100644 --- a/compiler/compiler_typing/src/raw.rs +++ b/compiler/compiler_typing/src/raw.rs @@ -349,6 +349,11 @@ impl Hash for RawType { hasher.write_u8(*signed as u8); } + RawType::Struct(_, container) => { + hasher.write_usize(9); + hasher.write_usize(container.self_ref); + } + _ => panic!("Unhashable type {:#?}", self), } } diff --git a/compiler/compiler_typing/src/structs.rs b/compiler/compiler_typing/src/structs.rs index f67264c..3ee219c 100644 --- a/compiler/compiler_typing/src/structs.rs +++ b/compiler/compiler_typing/src/structs.rs @@ -19,6 +19,8 @@ pub struct RawStructTypeContainer { pub fields: IndexStorage, pub type_params: TypeParameterContainer, pub functions: IndexStorage, + pub function_ids: Vec, + pub self_ref: usize, } #[derive(Debug, Clone, PartialEq, Eq)] From 1a77fbc3e13d3f571938ee9a64378c925e5e2e31 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:16:44 +0200 Subject: [PATCH 56/60] fix: fixed MIR lowering layer --- Cargo.lock | 1 + compiler/astoir_mir_lowering/Cargo.toml | 7 +-- compiler/astoir_mir_lowering/src/funcs.rs | 53 +++++++++++++++++-- .../astoir_mir_lowering/src/introductions.rs | 32 ++++++++--- compiler/astoir_mir_lowering/src/lib.rs | 53 ++++++++++++++++--- compiler/astoir_mir_lowering/src/vars.rs | 28 ++++++++-- 6 files changed, 152 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cedf392..7a22001 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,7 @@ version = "0.1.0" dependencies = [ "astoir_hir", "astoir_mir", + "compiler_global_scope", "compiler_typing", "compiler_utils", "diagnostics", diff --git a/compiler/astoir_mir_lowering/Cargo.toml b/compiler/astoir_mir_lowering/Cargo.toml index 82661b5..d504db1 100644 --- a/compiler/astoir_mir_lowering/Cargo.toml +++ b/compiler/astoir_mir_lowering/Cargo.toml @@ -4,8 +4,9 @@ version = "0.1.0" edition = "2024" [dependencies] -astoir_mir = {path = "../astoir_mir"} -astoir_hir = {path = "../astoir_hir"} +astoir_mir = { path = "../astoir_mir" } +astoir_hir = { path = "../astoir_hir" } diagnostics = { path = "../diagnostics" } compiler_typing = { path = "../compiler_typing" } -compiler_utils = { path = "../compiler_utils" } \ No newline at end of file +compiler_utils = { path = "../compiler_utils" } +compiler_global_scope = { path = "../compiler_global_scope" } diff --git a/compiler/astoir_mir_lowering/src/funcs.rs b/compiler/astoir_mir_lowering/src/funcs.rs index 358837f..09bb634 100644 --- a/compiler/astoir_mir_lowering/src/funcs.rs +++ b/compiler/astoir_mir_lowering/src/funcs.rs @@ -5,7 +5,8 @@ use astoir_mir::{ funcs::MIRFunction, vals::base::BaseMIRValue, }; -use diagnostics::DiagnosticResult; +use compiler_typing::TypedGlobalScopeEntry; +use diagnostics::{DiagnosticResult, builders::make_expected_simple_error_originless}; use crate::{MIRLoweringContext, body::lower_hir_body, lower_hir_type, values::lower_hir_value}; @@ -36,7 +37,30 @@ pub fn lower_hir_function_decl( ret_type = None } - let name = cctx.hir_ctx.functions.vals[func_name].2.clone(); + let fns_ind = match &cctx.hir_ctx.global_scope.scope.entries[func_name].entry_type { + TypedGlobalScopeEntry::Function { + descriptor_ind, + impl_ind: _, + } => descriptor_ind, + TypedGlobalScopeEntry::ImplLessFunction(ind) => ind, + TypedGlobalScopeEntry::StructFunction { + descriptor_ind, + impl_ind: _, + struct_type: _, + } => descriptor_ind, + + _ => { + return Err(make_expected_simple_error_originless( + &"function".to_string(), + &cctx.hir_ctx.global_scope.scope.entries[func_name].entry_type, + ) + .into()); + } + }; + + let fns = cctx.hir_ctx.global_scope.descriptors[*fns_ind].clone(); + + let name = fns.2.clone(); let mut func = MIRFunction::new(name, args, ret_type, requires_this, &cctx.mir_ctx); let block = func.append_entry_block(&mut cctx.mir_ctx); @@ -69,7 +93,30 @@ pub fn lower_hir_shadow_decl( return_type, } = node.kind.clone() { - let name = ctx.hir_ctx.functions.vals[func_name].2.clone(); + let fns_ind = match &ctx.hir_ctx.global_scope.scope.entries[func_name].entry_type { + TypedGlobalScopeEntry::Function { + descriptor_ind, + impl_ind: _, + } => descriptor_ind, + TypedGlobalScopeEntry::ImplLessFunction(ind) => ind, + TypedGlobalScopeEntry::StructFunction { + descriptor_ind, + impl_ind: _, + struct_type: _, + } => descriptor_ind, + + _ => { + return Err(make_expected_simple_error_originless( + &"function".to_string(), + &ctx.hir_ctx.global_scope.scope.entries[func_name].entry_type, + ) + .into()); + } + }; + + let fns = ctx.hir_ctx.global_scope.descriptors[*fns_ind].clone(); + + let name = fns.2.clone(); let mut args = vec![]; diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index 6b7583e..fddd9a3 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -3,8 +3,8 @@ use astoir_mir::{ blocks::{MIRBlockVariableSSAHint, MIRBlockVariableType, refer::MIRBlockReference}, builder::{build_stack_alloc, build_store}, }; -use compiler_typing::SizedType; -use diagnostics::MaybeDiagnostic; +use compiler_typing::{SizedType, TypedGlobalScopeEntry}; +use diagnostics::{MaybeDiagnostic, builders::make_expected_simple_error_originless}; use crate::{ MIRLoweringContext, lower_hir_type, type_tools::cast_to_enum_child, values::lower_hir_value, @@ -26,10 +26,30 @@ pub fn handle_var_introduction_queue( let new_type = lower_hir_type(ctx, new_type)?; let func = ctx.mir_ctx.block_to_func[&block]; let new_var = new_var.unwrap(); - let eligible = ctx.hir_ctx.function_contexts[func] - .as_ref() - .unwrap() - .is_eligible_for_ssa(new_var); + + let fns_ind = match &ctx.hir_ctx.global_scope.scope.entries[func].entry_type { + TypedGlobalScopeEntry::Function { + descriptor_ind: _, + impl_ind, + } => impl_ind, + TypedGlobalScopeEntry::StructFunction { + descriptor_ind: _, + impl_ind, + struct_type: _, + } => impl_ind, + + _ => { + return Err(make_expected_simple_error_originless( + &"function".to_string(), + &ctx.hir_ctx.global_scope.scope.entries[func].entry_type, + ) + .into()); + } + }; + + let fns = &ctx.hir_ctx.global_scope.implementations[*fns_ind].0; + + let eligible = fns.is_eligible_for_ssa(new_var); let casted = cast_to_enum_child(block, original, new_type.as_generic(), ctx, &*node)?; diff --git a/compiler/astoir_mir_lowering/src/lib.rs b/compiler/astoir_mir_lowering/src/lib.rs index 7f82170..41b546a 100644 --- a/compiler/astoir_mir_lowering/src/lib.rs +++ b/compiler/astoir_mir_lowering/src/lib.rs @@ -4,8 +4,10 @@ use astoir_hir::{ ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}, }; -use astoir_mir::ctx::MIRContext; -use compiler_typing::{SizedType, raw::RawType, structs::LoweredStructTypeContainer, tree::Type}; +use astoir_mir::{ctx::MIRContext, funcs::MIRFunction}; +use compiler_typing::{ + SizedType, TypedGlobalScopeEntry, raw::RawType, structs::LoweredStructTypeContainer, tree::Type, +}; use compiler_utils::utils::indexed::IndexStorage; use diagnostics::{DiagnosticResult, unsure_panic}; @@ -53,12 +55,49 @@ pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { block_introduction_var_queue: vec![], }; - let declarations = lowering_ctx.hir_ctx.function_declarations.clone(); + for entry in lowering_ctx.hir_ctx.global_scope.scope.entries.clone() { + match entry.entry_type { + TypedGlobalScopeEntry::Function { + descriptor_ind: _, + impl_ind, + } => { + let node = lowering_ctx.hir_ctx.global_scope.implementations[impl_ind] + .1 + .clone(); + + lower_hir_top_level(node, &mut lowering_ctx)?; + } - for decl in declarations { - if let Some(node) = decl { - lower_hir_top_level(node, &mut lowering_ctx)?; - } + TypedGlobalScopeEntry::ImplLessFunction(descriptor_ind) => { + let descriptor = + lowering_ctx.hir_ctx.global_scope.descriptors[descriptor_ind].clone(); + + let name = descriptor.2.clone(); + + let mut args = vec![]; + + for argument in descriptor.1 { + args.push(lower_hir_type(&mut lowering_ctx, argument.1)?); + } + + let ret_type; + + if descriptor.0.is_some() { + ret_type = Some(lower_hir_type( + &mut lowering_ctx, + descriptor.0.clone().unwrap(), + )?) + } else { + ret_type = None + } + + let func = MIRFunction::new(name, args, ret_type, false, &mut lowering_ctx.mir_ctx); + + lowering_ctx.mir_ctx.append_function(func); + } + + _ => todo!("Add support for remaining nodes"), + }; } return Ok(lowering_ctx.mir_ctx); diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index 5ca0bb0..b158139 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -6,8 +6,8 @@ use astoir_mir::{ builder::{build_stack_alloc, build_store}, vals::{base::BaseMIRValue, refer::MIRVariableReference}, }; -use compiler_typing::SizedType; -use diagnostics::DiagnosticResult; +use compiler_typing::{SizedType, TypedGlobalScopeEntry}; +use diagnostics::{DiagnosticResult, builders::make_expected_simple_error_originless}; use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; @@ -24,7 +24,29 @@ pub fn lower_hir_variable_declaration( { let func = ctx.mir_ctx.block_to_func[&block_id]; - let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); + //let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); + + let fns_ind = match &ctx.hir_ctx.global_scope.scope.entries[func].entry_type { + TypedGlobalScopeEntry::Function { + descriptor_ind, + impl_ind, + } => impl_ind, + TypedGlobalScopeEntry::StructFunction { + descriptor_ind, + impl_ind, + struct_type, + } => impl_ind, + + _ => { + return Err(make_expected_simple_error_originless( + &"function".to_string(), + &ctx.hir_ctx.global_scope.scope.entries[func].entry_type, + ) + .into()); + } + }; + + let local_ctx = ctx.hir_ctx.global_scope.implementations[*fns_ind].0.clone(); if local_ctx.is_eligible_for_ssa(variable) { if default_val.is_some() { From d4a54a0d4dd825b24975bf282db24ae6653cfd6c Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:29:28 +0200 Subject: [PATCH 57/60] feat: added getters for function ctx --- compiler/astoir_hir/src/ctx.rs | 2 +- compiler/astoir_hir/src/scope.rs | 28 +++++++++--- compiler/astoir_mir_lowering/src/lib.rs | 8 +++- compiler/astoir_mir_lowering/src/vars.rs | 2 +- compiler/compiler_global_scope/src/entry.rs | 1 + compiler/compiler_global_scope/src/lib.rs | 48 +++++++++++++++++++++ 6 files changed, 80 insertions(+), 9 deletions(-) diff --git a/compiler/astoir_hir/src/ctx.rs b/compiler/astoir_hir/src/ctx.rs index 797a70a..f978dac 100644 --- a/compiler/astoir_hir/src/ctx.rs +++ b/compiler/astoir_hir/src/ctx.rs @@ -13,7 +13,7 @@ use diagnostics::{ use crate::{nodes::HIRNode, scope::HIRGlobalScopeStorage}; pub type HIRFunction = (Option, Vec<(u64, Type)>, String); -pub type HIRFunctionImpl = (HIRBranchedContext, Box); +pub type HIRFunctionImpl = Box; /// The function HIR context. Contains a mapping from element name hash to element index and other variable information. /// Uses a branch based system to contain variables. diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index fb1c318..f3ea51b 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -16,6 +16,7 @@ pub struct HIRGlobalScopeStorage { pub scope: TypedGlobalScope, pub descriptors: Vec, pub implementations: Vec, + pub contexts: Vec, } impl HIRGlobalScopeStorage { @@ -24,6 +25,7 @@ impl HIRGlobalScopeStorage { scope: TypedGlobalScope::new(), descriptors: vec![], implementations: vec![], + contexts: vec![], } } @@ -46,7 +48,8 @@ impl HIRGlobalScopeStorage { origin: &K, ) -> DiagnosticResult { self.descriptors.push(descriptor); - self.implementations.push((brctx, implementation)); + self.implementations.push(implementation); + self.contexts.push(brctx); self.scope.append( name, @@ -83,7 +86,8 @@ impl HIRGlobalScopeStorage { origin: &K, ) -> DiagnosticResult { self.descriptors.push(descriptor); - self.implementations.push((brctx, implementation)); + self.implementations.push(implementation); + self.contexts.push(brctx); let ind = self.scope.value_to_ind[&TypedGlobalScopeEntry::Type(struct_type)]; @@ -164,14 +168,27 @@ impl HIRGlobalScopeStorage { return Ok(self.descriptors[ind].clone()); } + pub fn get_function_ctx( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let ind = self.scope.get_function_ctx(name, origin)?; + + return Ok(self.contexts[ind].clone()); + } + pub fn get_function_impl( &self, name: EntryKey, origin: &K, - ) -> DiagnosticResult { + ) -> DiagnosticResult<(HIRFunctionImpl, HIRBranchedContext)> { let ind = self.scope.get_function_impl(name, origin)?; - return Ok(self.implementations[ind].clone()); + return Ok(( + self.implementations[ind].clone(), + self.contexts[ind].clone(), + )); } pub fn get_implless_function( @@ -201,12 +218,13 @@ impl HIRGlobalScopeStorage { &self, name: EntryKey, origin: &K, - ) -> DiagnosticResult<(HIRFunction, HIRFunctionImpl, RawType)> { + ) -> DiagnosticResult<(HIRFunction, HIRFunctionImpl, HIRBranchedContext, RawType)> { let res = self.scope.get_exact_struct_function(name, origin)?; return Ok(( self.descriptors[res.0].clone(), self.implementations[res.1].clone(), + self.contexts[res.1].clone(), res.2, )); } diff --git a/compiler/astoir_mir_lowering/src/lib.rs b/compiler/astoir_mir_lowering/src/lib.rs index 41b546a..db7a9eb 100644 --- a/compiler/astoir_mir_lowering/src/lib.rs +++ b/compiler/astoir_mir_lowering/src/lib.rs @@ -6,7 +6,8 @@ use astoir_hir::{ }; use astoir_mir::{ctx::MIRContext, funcs::MIRFunction}; use compiler_typing::{ - SizedType, TypedGlobalScopeEntry, raw::RawType, structs::LoweredStructTypeContainer, tree::Type, + SizedType, TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, + structs::LoweredStructTypeContainer, tree::Type, }; use compiler_utils::utils::indexed::IndexStorage; use diagnostics::{DiagnosticResult, unsure_panic}; @@ -68,6 +69,9 @@ pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { lower_hir_top_level(node, &mut lowering_ctx)?; } + TypedGlobalScopeEntry::TypeAlias(_) => continue, + TypedGlobalScopeEntry::Type(_) => continue, + TypedGlobalScopeEntry::ImplLessFunction(descriptor_ind) => { let descriptor = lowering_ctx.hir_ctx.global_scope.descriptors[descriptor_ind].clone(); @@ -96,7 +100,7 @@ pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { lowering_ctx.mir_ctx.append_function(func); } - _ => todo!("Add support for remaining nodes"), + _ => todo!("Add support for remaining nodes {:#?}", entry), }; } diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index b158139..f56f07f 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -46,7 +46,7 @@ pub fn lower_hir_variable_declaration( } }; - let local_ctx = ctx.hir_ctx.global_scope.implementations[*fns_ind].0.clone(); + let local_ctx = ctx.hir_ctx.global_scope.contexts[*fns_ind].0.clone(); if local_ctx.is_eligible_for_ssa(variable) { if default_val.is_some() { diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs index ef3468b..fa29aa1 100644 --- a/compiler/compiler_global_scope/src/entry.rs +++ b/compiler/compiler_global_scope/src/entry.rs @@ -13,6 +13,7 @@ pub enum GlobalStorageEntryType { impl_ind: usize, }, ImplLessFunction(usize), + HalfImplFunction { descriptor_ind: usize, branch_ctx: usize } StructFunction { descriptor_ind: usize, impl_ind: usize, diff --git a/compiler/compiler_global_scope/src/lib.rs b/compiler/compiler_global_scope/src/lib.rs index 4a4b222..d304096 100644 --- a/compiler/compiler_global_scope/src/lib.rs +++ b/compiler/compiler_global_scope/src/lib.rs @@ -57,6 +57,20 @@ impl GlobalScopeStorage { return Err(make_already_in_scope(origin, &name.name_hash).into()); } + if let GlobalStorageEntryType::Function { .. } = entry { + self.descriptor_counter += 1; + self.impl_counter += 1; + } + + if let GlobalStorageEntryType::ImplLessFunction(_) = entry { + self.descriptor_counter += 1; + } + + if let GlobalStorageEntryType::StructFunction { .. } = entry { + self.descriptor_counter += 1; + self.impl_counter += 1; + } + let parent_index = self.entries.len(); self.value_to_ind.insert(entry.clone(), parent_index); @@ -125,6 +139,10 @@ impl GlobalScopeStorage { impl_ind: _, } => Ok(descriptor_ind), GlobalStorageEntryType::ImplLessFunction(descriptor_ind) => Ok(descriptor_ind), + GlobalStorageEntryType::HalfImplFunction { + descriptor_ind, + branch_ctx: _, + } => Ok(descriptor_ind), GlobalStorageEntryType::StructFunction { descriptor_ind, impl_ind: _, @@ -135,6 +153,36 @@ impl GlobalScopeStorage { }; } + pub fn get_function_ctx( + &self, + name: EntryKey, + origin: &K, + ) -> DiagnosticResult { + let base = self.get_base(name, origin)?; + + return match base { + GlobalStorageEntryType::Function { + descriptor_ind: _, + impl_ind, + } => Ok(impl_ind), + + GlobalStorageEntryType::StructFunction { + descriptor_ind: _, + impl_ind, + struct_type: _, + } => Ok(impl_ind), + + GlobalStorageEntryType::HalfImplFunction { + descriptor_ind: _, + branch_ctx, + } => Ok(branch_ctx), + + _ => Err( + make_expected_simple_error(origin, &"function with implementation", &base).into(), + ), + }; + } + pub fn get_function_impl( &self, name: EntryKey, From 7b5fa0b5542f6bbd429e5e4ec4035f553f27a8bc Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:32:22 +0200 Subject: [PATCH 58/60] feat: added append half function method --- compiler/astoir_hir/src/scope.rs | 19 +++++++++++++++++++ compiler/compiler_global_scope/src/lib.rs | 9 +++++++++ 2 files changed, 28 insertions(+) diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index f3ea51b..1086113 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -61,6 +61,25 @@ impl HIRGlobalScopeStorage { ) } + pub fn append_half_function( + &mut self, + name: EntryKey, + descriptor: HIRFunction, + brctx: HIRBranchedContext, + ) -> DiagnosticResult { + self.descriptors.push(descriptor); + self.contexts.push(brctx); + + self.scope.append( + name, + TypedGlobalScopeEntry::HalfImplFunction { + descriptor_ind: self.scope.descriptor_counter, + branch_ctx: self.scope.ctx_counter, + }, + origin, + ) + } + pub fn append_implless_function( &mut self, name: EntryKey, diff --git a/compiler/compiler_global_scope/src/lib.rs b/compiler/compiler_global_scope/src/lib.rs index d304096..9ad06e7 100644 --- a/compiler/compiler_global_scope/src/lib.rs +++ b/compiler/compiler_global_scope/src/lib.rs @@ -24,6 +24,7 @@ pub struct GlobalScopeStorage { pub descriptor_counter: usize, pub impl_counter: usize, + pub ctx_counter: usize, } /// The global storage for every element inside of the scope. @@ -44,6 +45,7 @@ impl GlobalScopeStorage { entries: vec![], descriptor_counter: 0, impl_counter: 0, + ctx_counter: 0, } } @@ -59,6 +61,7 @@ impl GlobalScopeStorage { if let GlobalStorageEntryType::Function { .. } = entry { self.descriptor_counter += 1; + self.ctx_counter += 1; self.impl_counter += 1; } @@ -68,9 +71,15 @@ impl GlobalScopeStorage { if let GlobalStorageEntryType::StructFunction { .. } = entry { self.descriptor_counter += 1; + self.ctx_counter += 1; self.impl_counter += 1; } + if let GlobalStorageEntryType::HalfImplFunction { .. } = entry { + self.descriptor_counter += 1; + self.ctx_counter += 1; + } + let parent_index = self.entries.len(); self.value_to_ind.insert(entry.clone(), parent_index); From 0cb18fbbbc8371876ed7693143984d103e91be73 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:45:05 +0200 Subject: [PATCH 59/60] fix: added fixes for global scope --- compiler/astoir_hir/src/scope.rs | 1 + compiler/astoir_hir_lowering/src/func.rs | 2 ++ compiler/astoir_mir/src/builder.rs | 2 +- compiler/astoir_mir/src/ctx.rs | 15 +++++++-------- compiler/astoir_mir/src/funcs.rs | 4 ++-- compiler/astoir_mir/src/insts/mod.rs | 4 ++-- compiler/astoir_mir_lowering/src/funcs.rs | 4 ++-- compiler/astoir_mir_lowering/src/introductions.rs | 2 +- compiler/astoir_mir_lowering/src/lib.rs | 9 +++------ compiler/astoir_mir_lowering/src/vars.rs | 9 ++++++++- compiler/compiler_global_scope/src/entry.rs | 6 +++++- compiler/llvm_ir_bridge/src/funcs.rs | 1 + 12 files changed, 35 insertions(+), 24 deletions(-) diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index 1086113..c6065fd 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -66,6 +66,7 @@ impl HIRGlobalScopeStorage { name: EntryKey, descriptor: HIRFunction, brctx: HIRBranchedContext, + origin: &K, ) -> DiagnosticResult { self.descriptors.push(descriptor); self.contexts.push(brctx); diff --git a/compiler/astoir_hir_lowering/src/func.rs b/compiler/astoir_hir_lowering/src/func.rs index 4f0fe7a..f21b45f 100644 --- a/compiler/astoir_hir_lowering/src/func.rs +++ b/compiler/astoir_hir_lowering/src/func.rs @@ -135,7 +135,9 @@ pub fn lower_ast_function_declaration( context.global_scope.scope.entry_to_ind.remove(&key); context.global_scope.scope.value_to_ind.remove(&entry); context.global_scope.descriptors.pop(); + //context.global_scope.contexts.pop(); context.global_scope.scope.descriptor_counter -= 1; + //context.global_scope.scope.ctx_counter -= 1; // Append the new verison as a impl-containing function diff --git a/compiler/astoir_mir/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 5f505ce..6cea1cc 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -838,7 +838,7 @@ pub fn build_call( ind: usize, args: Vec, ) -> DiagnosticResult> { - let func = &ctx.functions[func]; + let func = &ctx.functions[&func]; for (arg, t) in args.iter().zip(func.arguments.iter()) { if !arg.vtype.is_truly_eq(t) { diff --git a/compiler/astoir_mir/src/ctx.rs b/compiler/astoir_mir/src/ctx.rs index c20422b..c08baef 100644 --- a/compiler/astoir_mir/src/ctx.rs +++ b/compiler/astoir_mir/src/ctx.rs @@ -16,7 +16,7 @@ use crate::{ }; pub struct MIRContext { - pub functions: Vec, + pub functions: HashMap, pub blocks: Vec, pub block_to_func: HashMap, @@ -29,7 +29,7 @@ pub struct MIRContext { impl MIRContext { pub fn new() -> Self { MIRContext { - functions: vec![], + functions: HashMap::new(), ssa_hints: HintStorage::new(), blocks: vec![], writer: InstructionWriterPosition { @@ -45,7 +45,7 @@ impl MIRContext { self.blocks.push(MIRBlock::new(ind)); - self.functions[func].blocks.push(ind); + self.functions.get_mut(&func).unwrap().blocks.push(ind); self.block_to_func.insert(ind, func); @@ -67,11 +67,10 @@ impl MIRContext { } pub fn append_function(&mut self, func: MIRFunction) -> usize { - let ind = self.functions.len(); + let id = func.id; + self.functions.insert(id, func); - self.functions.push(func); - - return ind; + return id; } pub fn append_inst(&mut self, inst: MIRInstruction) -> InstructionValue { @@ -156,7 +155,7 @@ impl MIRContext { impl Display for MIRContext { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for func in &self.functions { - writeln!(f, "{}", func)?; + writeln!(f, "{}", func.1)?; } for block in &self.blocks { diff --git a/compiler/astoir_mir/src/funcs.rs b/compiler/astoir_mir/src/funcs.rs index bd3c7ee..8a81506 100644 --- a/compiler/astoir_mir/src/funcs.rs +++ b/compiler/astoir_mir/src/funcs.rs @@ -31,7 +31,7 @@ impl MIRFunction { arguments: Vec, return_type: Option, is_from_struct: bool, - ctx: &MIRContext, + id: usize, ) -> Self { return MIRFunction { blocks: vec![], @@ -39,7 +39,7 @@ impl MIRFunction { arguments, return_type, is_from_struct, - id: ctx.functions.len(), + id, }; } diff --git a/compiler/astoir_mir/src/insts/mod.rs b/compiler/astoir_mir/src/insts/mod.rs index 078209d..eddd863 100644 --- a/compiler/astoir_mir/src/insts/mod.rs +++ b/compiler/astoir_mir/src/insts/mod.rs @@ -294,7 +294,7 @@ impl MIRInstruction { function, arguments: _, } => { - let func = &ctx.functions[*function]; + let func = &ctx.functions[function]; return func.return_type.is_some(); } @@ -476,7 +476,7 @@ impl MIRInstruction { function, arguments: _, } => { - let func = &ctx.functions[*function]; + let func = &ctx.functions[function]; return func.return_type.clone().unwrap(); } diff --git a/compiler/astoir_mir_lowering/src/funcs.rs b/compiler/astoir_mir_lowering/src/funcs.rs index 09bb634..56fe7c6 100644 --- a/compiler/astoir_mir_lowering/src/funcs.rs +++ b/compiler/astoir_mir_lowering/src/funcs.rs @@ -62,7 +62,7 @@ pub fn lower_hir_function_decl( let name = fns.2.clone(); - let mut func = MIRFunction::new(name, args, ret_type, requires_this, &cctx.mir_ctx); + let mut func = MIRFunction::new(name, args, ret_type, requires_this, func_name); let block = func.append_entry_block(&mut cctx.mir_ctx); cctx.mir_ctx.writer.move_end(block); @@ -132,7 +132,7 @@ pub fn lower_hir_shadow_decl( ret_type = None } - let func = MIRFunction::new(name, args, ret_type, false, &ctx.mir_ctx); + let func = MIRFunction::new(name, args, ret_type, false, func_name); ctx.mir_ctx.append_function(func); return Ok(true); diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index fddd9a3..a1c726e 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -47,7 +47,7 @@ pub fn handle_var_introduction_queue( } }; - let fns = &ctx.hir_ctx.global_scope.implementations[*fns_ind].0; + let fns = &ctx.hir_ctx.global_scope.contexts[*fns_ind]; let eligible = fns.is_eligible_for_ssa(new_var); diff --git a/compiler/astoir_mir_lowering/src/lib.rs b/compiler/astoir_mir_lowering/src/lib.rs index db7a9eb..6434ec1 100644 --- a/compiler/astoir_mir_lowering/src/lib.rs +++ b/compiler/astoir_mir_lowering/src/lib.rs @@ -6,8 +6,7 @@ use astoir_hir::{ }; use astoir_mir::{ctx::MIRContext, funcs::MIRFunction}; use compiler_typing::{ - SizedType, TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, - structs::LoweredStructTypeContainer, tree::Type, + SizedType, TypedGlobalScopeEntry, raw::RawType, structs::LoweredStructTypeContainer, tree::Type, }; use compiler_utils::utils::indexed::IndexStorage; use diagnostics::{DiagnosticResult, unsure_panic}; @@ -62,9 +61,7 @@ pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { descriptor_ind: _, impl_ind, } => { - let node = lowering_ctx.hir_ctx.global_scope.implementations[impl_ind] - .1 - .clone(); + let node = lowering_ctx.hir_ctx.global_scope.implementations[impl_ind].clone(); lower_hir_top_level(node, &mut lowering_ctx)?; } @@ -95,7 +92,7 @@ pub fn lower_hir(ctx: HIRContext) -> DiagnosticResult { ret_type = None } - let func = MIRFunction::new(name, args, ret_type, false, &mut lowering_ctx.mir_ctx); + let func = MIRFunction::new(name, args, ret_type, false, entry.parent_index); lowering_ctx.mir_ctx.append_function(func); } diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index f56f07f..2f7f8f9 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -38,6 +38,13 @@ pub fn lower_hir_variable_declaration( } => impl_ind, _ => { + println!("Curr entry: {}", func); + println!("Entry dump: "); + + for entry in ctx.hir_ctx.global_scope.scope.entries.clone() { + println!("- {:#?}", entry); + } + return Err(make_expected_simple_error_originless( &"function".to_string(), &ctx.hir_ctx.global_scope.scope.entries[func].entry_type, @@ -46,7 +53,7 @@ pub fn lower_hir_variable_declaration( } }; - let local_ctx = ctx.hir_ctx.global_scope.contexts[*fns_ind].0.clone(); + let local_ctx = ctx.hir_ctx.global_scope.contexts[*fns_ind].clone(); if local_ctx.is_eligible_for_ssa(variable) { if default_val.is_some() { diff --git a/compiler/compiler_global_scope/src/entry.rs b/compiler/compiler_global_scope/src/entry.rs index fa29aa1..4d4e9b8 100644 --- a/compiler/compiler_global_scope/src/entry.rs +++ b/compiler/compiler_global_scope/src/entry.rs @@ -13,7 +13,10 @@ pub enum GlobalStorageEntryType { impl_ind: usize, }, ImplLessFunction(usize), - HalfImplFunction { descriptor_ind: usize, branch_ctx: usize } + HalfImplFunction { + descriptor_ind: usize, + branch_ctx: usize, + }, StructFunction { descriptor_ind: usize, impl_ind: usize, @@ -181,6 +184,7 @@ pub struct GlobalStorageEntry { impl Display for GlobalStorageEntryType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { + Self::HalfImplFunction { .. } => "function", Self::Function { .. } => "function", Self::ImplLessFunction(_) => "function", Self::StructFunction { .. } => "function", diff --git a/compiler/llvm_ir_bridge/src/funcs.rs b/compiler/llvm_ir_bridge/src/funcs.rs index b48aab5..60d1a01 100644 --- a/compiler/llvm_ir_bridge/src/funcs.rs +++ b/compiler/llvm_ir_bridge/src/funcs.rs @@ -11,6 +11,7 @@ use crate::{ pub fn bridge_llvm_functions(mir: &MIRContext, bridge: &mut LLVMBridgeContext) { for func in &mir.functions { let mut args = vec![]; + let func = func.1; if !func.blocks.is_empty() { for arg in &func.arguments { From 0e9246517a98f0d4264d16bace53740f6d9ea99b Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:50:00 +0200 Subject: [PATCH 60/60] feat: prevented global scope -> local scope duplicate entries by checking for global scope entries for variable names and arguments to prevent some naming issues --- compiler/astoir_hir/src/scope.rs | 17 ++++++++++++++++- compiler/astoir_hir_lowering/src/func.rs | 4 ++++ compiler/astoir_hir_lowering/src/var.rs | 8 ++++++++ compiler/astoir_mir_lowering/src/vars.rs | 6 +++--- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/compiler/astoir_hir/src/scope.rs b/compiler/astoir_hir/src/scope.rs index c6065fd..424c71c 100644 --- a/compiler/astoir_hir/src/scope.rs +++ b/compiler/astoir_hir/src/scope.rs @@ -2,7 +2,10 @@ use compiler_global_scope::key::EntryKey; use compiler_typing::{TypedGlobalScope, TypedGlobalScopeEntry, raw::RawType, tree::Type}; -use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_cannot_find}; +use diagnostics::{ + DiagnosticResult, DiagnosticSpanOrigin, MaybeDiagnostic, + builders::{make_already_in_scope, make_cannot_find}, +}; use crate::{ ctx::{HIRBranchedContext, HIRFunction, HIRFunctionImpl}, @@ -29,6 +32,18 @@ impl HIRGlobalScopeStorage { } } + pub fn enforce_not_here( + &mut self, + name: EntryKey, + origin: &K, + ) -> MaybeDiagnostic { + if self.scope.entry_to_ind.contains_key(&name) { + return Err(make_already_in_scope(origin, &name.name_hash).into()); + } + + Ok(()) + } + /// This doesn't automatically handle descriptors and implementations pub fn append( &mut self, diff --git a/compiler/astoir_hir_lowering/src/func.rs b/compiler/astoir_hir_lowering/src/func.rs index f21b45f..c0ea405 100644 --- a/compiler/astoir_hir_lowering/src/func.rs +++ b/compiler/astoir_hir_lowering/src/func.rs @@ -88,6 +88,10 @@ pub fn lower_ast_function_declaration( let branch = curr_ctx.start_branch(); for arg in &arguments { + context + .global_scope + .enforce_not_here(EntryKey { name_hash: arg.0 }, &*node)?; + match curr_ctx.introduce_variable(arg.0, arg.1.clone(), true) { Ok(_) => {} Err(_) => return Err(make_already_in_scope(&*node, &arg.0).into()), diff --git a/compiler/astoir_hir_lowering/src/var.rs b/compiler/astoir_hir_lowering/src/var.rs index 2e4b970..c22dbf1 100644 --- a/compiler/astoir_hir_lowering/src/var.rs +++ b/compiler/astoir_hir_lowering/src/var.rs @@ -3,6 +3,7 @@ use astoir_hir::{ ctx::{HIRBranchedContext, HIRContext, VariableKind, get_variable}, nodes::{HIRNode, HIRNodeKind}, }; +use compiler_global_scope::key::EntryKey; use diagnostics::{DiagnosticResult, builders::make_variable_uninit}; use crate::{arrays::lower_ast_array_index_access, types::lower_ast_type, values::lower_ast_value}; @@ -18,6 +19,13 @@ pub fn lower_ast_variable_declaration( value, } = node.kind.clone() { + context.global_scope.enforce_not_here( + EntryKey { + name_hash: var_name.hash, + }, + &*node, + )?; + let lowered = lower_ast_type(context, var_type, &*node)?; let name_ind = diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index 2f7f8f9..a613c93 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -28,13 +28,13 @@ pub fn lower_hir_variable_declaration( let fns_ind = match &ctx.hir_ctx.global_scope.scope.entries[func].entry_type { TypedGlobalScopeEntry::Function { - descriptor_ind, + descriptor_ind: _, impl_ind, } => impl_ind, TypedGlobalScopeEntry::StructFunction { - descriptor_ind, + descriptor_ind: _, impl_ind, - struct_type, + struct_type: _, } => impl_ind, _ => {