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/78] 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 c5661057..a0270a61 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 ba489f08..fed3dc0f 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/78] 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 0ceb5025..1fbce9c8 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/78] 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 02a4d992..0b5ed023 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 1fbce9c8..387d1abe 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 7bddedfe..6be06722 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 00000000..30594586 --- /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/78] 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 4f8edcd5..5009a10c 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 c3a60e46..2d35609e 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 b0df1dfc..e0deed9f 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 00000000..dc10a3bb --- /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/78] 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 58e00282..1fbf7c84 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 30594586..32662818 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 dc10a3bb..95d8205b 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 7333a0c9..36edf542 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 ac2c27dd..d337b1da 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 c13537dc..7730959e 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 c3a1a353..f700669e 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/78] 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 1fbf7c84..08586a0e 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 32662818..e14f3266 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 95d8205b..6b7a7fe1 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 fc6ab3f2..dd1816e6 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 7730959e..8c6d965b 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/78] 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 6b7a7fe1..38d5f554 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/78] 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 38d5f554..6c3d7a0a 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 dd1816e6..391ffb2f 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/78] 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 8564c7bd..74b28283 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 b88d3455..16c97e3b 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 242b0789..4380d577 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 ad9c149a..4a807f75 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 6c3d7a0a..5dd16527 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/78] 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 09a0f997..cf79b940 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 697e9892..4cbe4e1b 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/78] 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 c6780bc8..8aa4ab7e 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 e14f3266..e8b3e3b1 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 a32a7c69..3e366e12 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 d3c1d21c..5ee4a790 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 297fddf4..188073fd 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 a2a21362..385b2376 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 756a0eee..9e54e53b 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 cf79b940..c2a0b92c 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 4cbe4e1b..130dca81 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 31806c84..b24b48a4 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 a60590be..efa48742 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 3f32eba0..67e306d9 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 a354fe44..301255bf 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 ff8f8c7f..88b5521d 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 ff69e9e9..6d599256 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/78] 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 74b28283..cab28246 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/78] 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 a1661bbf..09f99b25 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 301255bf..dec8efdd 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/78] 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 c2a0b92c..5db68fb9 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 dec8efdd..ce8c98e3 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/78] =?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 e81ff1a9..688dee09 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 00000000..e88de570 --- /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 8c6d965b..cea61934 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 8459f9e8..baff5a2b 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 f700669e..6a0f2fca 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 d8df3d0c..00000000 --- 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 06210190..00000000 --- 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 1854b677..00000000 --- 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/78] 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 e88de570..c4e73c99 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 387d1abe..8d771ad9 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/78] 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 5009a10c..a5fa4b46 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 c4e73c99..ff92cf54 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 8d771ad9..307a8c0c 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 00000000..b129c83a --- /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 6be06722..b96b63f0 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 fe33f4b0..c00a5faa 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 cdea242b..7f893480 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 42beefdb..bef950be 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 3e366e12..9544a52d 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 0fd841bb..82661b5f 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 4f68fc52..3c78662e 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 54e81a9d..48984352 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 2cf44620..976aa53b 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 00000000..31c71562 --- /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/78] 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 ff92cf54..542cef2c 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 307a8c0c..09f0c7ae 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 c00a5faa..bb7469d9 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 bef950be..f1765595 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 9544a52d..9de521cc 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 0280b4d9..8a8a4b58 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 d43af45f..96b93d32 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 3c78662e..b9425040 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 31c71562..dc80dee6 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/78] 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 cea61934..38f5fedb 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 6a0f2fca..11162c00 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/78] 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 542cef2c..89565faa 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/78] 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 89565faa..c1df7e6a 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 b9425040..24609a4e 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 dc80dee6..d6d8adf7 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/78] 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 188073fd..2b8322b5 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 24609a4e..181e9cd0 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/78] 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 c1df7e6a..3a33dfc8 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 d6d8adf7..4a3a4a31 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 38f5fedb..e7242517 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 11162c00..6574fd35 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/78] 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 2b8322b5..22ed2017 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 dbb271a3..d3ec5c2b 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 181e9cd0..3c625ef2 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/78] 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 b9fb59ed..3cb6af0e 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/78] 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 22ed2017..7dad1422 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 d3ec5c2b..066b776b 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 3c625ef2..de846e21 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/78] 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 3a33dfc8..6faf3123 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 bb7469d9..ad6664d3 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 3cb6af0e..cb41af95 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/78] 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 cb41af95..4776f669 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/78] 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 f2733963..57e12282 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/78] 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 aff66fe4..eccf9035 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 00000000..1c2f1e7f --- /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 36edf542..956fa2d9 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 d337b1da..c15c0714 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/78] 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 1c2f1e7f..4218528b 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/78] 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 4218528b..4bb0bb49 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/78] 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 a5fa4b46..90cfa8f0 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 293ace96..3b65f4b8 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 00000000..33526a15 --- /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 00000000..423f4755 --- /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 00000000..e69de29b 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/78] 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 90cfa8f0..e0e4fb76 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 2d35609e..5a6b8da5 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 e0deed9f..784d1d3e 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 33526a15..36738a45 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 e69de29b..29561c24 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/78] 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 e0e4fb76..a9f019e7 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 57e12282..e73b8e0f 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 4bb0bb49..e4f88213 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 36738a45..3eee720b 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 29561c24..3abf84b4 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 00000000..33ded047 --- /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/78] 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 784d1d3e..744a6243 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/78] 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 a9f019e7..5cdc38fa 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 3b65f4b8..03da646a 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 00000000..6405f36f --- /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 00000000..e7a11a96 --- /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/78] 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 5cdc38fa..a029fb16 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 6405f36f..1d959713 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 00000000..198c7bcd --- /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 00000000..73f7cb31 --- /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 00000000..6b6b4460 --- /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 e7a11a96..00000000 --- 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/78] 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 a029fb16..263cedb7 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 6c59dd5f..b5a91090 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 e5be3c54..a003dab7 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/78] 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 198c7bcd..7318e020 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 6b6b4460..b8ab3b0e 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/78] 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 7318e020..c430b904 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 a003dab7..1e005d4b 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 35eb5459..feb0862b 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 66d60280..3130fa66 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/78] 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 0b5ed023..20a8b3cc 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 688dee09..3725aeeb 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 6faf3123..6da2475d 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 09f0c7ae..dc0e6789 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 1abbe121..2543be62 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 520f699e..a6d8b3c0 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 b129c83a..2ac5ca92 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 370f21a4..3ff2c66e 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 0b7121fa..e22b0acb 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 9b05368a..012ff5b2 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 210c8ce7..1145c396 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 47f722a8..2a01800c 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 2a9b701e..67413bcc 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 1b1174fa..efb55aaf 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 1747d1fe..c7edaa45 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 b96b63f0..f0379bfb 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 1e67c72e..c81225b0 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 ad6664d3..92d4e235 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 08586a0e..84f207dc 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 8aa4ab7e..60447fd0 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 4e54026c..9b68fd30 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 0fda9eed..18d80cdb 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 244b987c..c44a61fd 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 7f893480..8dcd24c0 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 70893b43..06eb19fa 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 e8b3e3b1..20327639 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 f1765595..1e453cf2 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 bc40d37b..827ee269 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 3575f298..0e5b696a 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 1956625b..2990d019 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 17ecdcc3..ef4b6768 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 e73b8e0f..a8a96359 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 eccf9035..47ac86a0 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 9de521cc..5e17f871 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 607c5093..a3cf4920 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 e4f88213..e133ee4d 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 f0fb144b..5c3725a1 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 d4308d5a..f8691b76 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 16c97e3b..2a2c4e62 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 7507d799..373ac77a 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 5ee4a790..e51fa510 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 56b31f4b..76aa5f4f 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 744a6243..c4346899 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 368348ed..ff755038 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 8a8a4b58..bba22703 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 4380d577..d800fea8 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 4a807f75..81864926 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 ddbcbed7..50bf516d 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 5dd16527..4a6d47ea 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 41bfdd0f..e52b9ae2 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 3c389e12..2e4b970c 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 f5a8f39d..744e8d57 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 c5dcf0b0..0e1109f1 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 72858e48..795a242b 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 7dad1422..2da1ef75 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 e0f78834..c20422b7 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 ee266e35..bd3c7ee7 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 c3d38224..64d7cd1b 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 066b776b..078209d5 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 7749ffe9..c971b532 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 ebbe1c84..ee4987c9 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 8ac66b2a..ac331232 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 15570026..9e64b697 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 d40e0a81..bea371e6 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 a355c7a5..7822ba07 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 01b2c338..8ecb2369 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 63ab81b6..6b760868 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 48b3c0a2..cca9bb7b 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 863eda0f..5b43bd96 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 91ef80c3..a6f02e57 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 7b6a6530..7eb9b145 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 96b93d32..493d33ac 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 385b2376..8520c884 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 b896cb43..22f8d0f8 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 547944fb..179166eb 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 cbb0e5d9..f13bb452 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 0f71c9df..358837fa 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 9e54e53b..1a3831f3 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 5e6d1811..6feae2c8 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 06fe367d..1a972005 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 de846e21..5d7818f9 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 e2148b92..789302ca 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 48984352..4e11d4ca 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 8f7817d9..b393c70a 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 93ebcb64..331537e5 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 ea329756..c7e22c2a 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 391ffb2f..36f95789 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 c430b904..0e3f2192 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 73f7cb31..ed250ba5 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 b8ab3b0e..83710528 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 5db68fb9..6a2ddc34 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 130dca81..3600ee30 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 35daaaf9..64e781c6 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 4987ac7d..0ba93868 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 2cf89a86..74af8eab 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 d2c3d4db..8edd90cb 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 b24b48a4..898c3c9c 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 efa48742..38832458 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 1e005d4b..2494b516 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 feb0862b..2d8f0ef6 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 397cda51..0361eff2 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 3130fa66..00000000 --- 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 b5bc0c30..f67264ce 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 87e63b19..f715cc06 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 7bcfefa1..cf550d22 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 67e306d9..1ac498dc 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 21b59f86..b66a595b 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 71c782f8..1b05c585 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 976aa53b..5b4ee331 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 4a3a4a31..92e60133 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 fcd77bac..e12dfb31 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 0b3cf56f..37d3a6c2 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 500258f0..dc9fcdbd 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 1eb3923e..ece0cbec 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 956fa2d9..e3b30062 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 ce8c98e3..5629bb39 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 c15c0714..8f6e25d2 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 b89070ab..313ecf20 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 88b5521d..994c6bab 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 e561b56d..b32ebc8a 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 5481e8eb..7df00512 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 e7242517..d0520bca 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 baff5a2b..bbc3c310 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 6574fd35..c61ee5e7 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 b49da647..01936aa1 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 1d07bf5b..82cc642a 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 9c4e74b8..203b7726 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 0746dcfa..b48aab51 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 4776f669..ad7edc20 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 6d599256..d09f4906 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 19aac353..8e362703 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 de1e288b..1933beaa 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 3abf84b4..baa1b1bb 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 33ded047..7af6403e 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/78] 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 a8a96359..967d2f5c 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 47ac86a0..d3fef0f9 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 5e17f871..5a8136cf 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 a3cf4920..db2c50ee 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 e133ee4d..00000000 --- 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 2da1ef75..5f505ce5 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 5b43bd96..3c3d6aa1 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/78] 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 7eb9b145..67e02161 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 8520c884..033e1968 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 1a3831f3..c15e1225 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 6feae2c8..38010b5e 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 1a972005..c1a05d0f 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 5d7818f9..b7556bc9 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 789302ca..ee20c68b 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 b393c70a..51ac743b 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 c7e22c2a..00b17200 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 36f95789..993d623d 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/78] 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 263cedb7..0f3c57a2 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 5a6b8da5..b58e0457 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 e51fa510..afb713b1 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 ff755038..00a3726f 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 d800fea8..c43d6393 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 81864926..a7da0265 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 4a6d47ea..f0b1dc04 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 e52b9ae2..e5418b9b 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 0e3f2192..ef3468bb 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 83710528..4a4b222e 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 2d8f0ef6..a657d789 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 3eee720b..2ccc10f5 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 7af6403e..ce83da9f 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/78] 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 d3fef0f9..2642626e 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 00000000..c176ccb4 --- /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/78] 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 0f3c57a2..cedf392e 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 5850806d..8f3e5232 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 c176ccb4..c7c904d9 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 2494b516..53aac654 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/78] 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 c7c904d9..0f651363 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/78] 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 967d2f5c..7414befc 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 5a8136cf..caf3c605 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 db2c50ee..9945dfc1 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 0f651363..1c925ce5 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 67e02161..84dc7360 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 c15e1225..6b7583ea 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 38010b5e..7f821700 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 b7556bc9..af6c0343 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 ee20c68b..9bef1586 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 51ac743b..52021ec8 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 00b17200..f83005c4 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 993d623d..5ca0bb0e 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 ce83da9f..6763faf8 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/78] 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 afb713b1..dcaa24df 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 c43d6393..a7944442 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 a7da0265..95d9b44f 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 f0b1dc04..2a6c8b90 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 e5418b9b..7a897f3e 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/78] 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 7414befc..31f39a22 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 1c925ce5..eacf2ca2 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/78] 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 31f39a22..797a70a6 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 ed250ba5..2f8827f5 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/78] 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 caf3c605..d9bc8ce1 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 e3b30062..f5980cfd 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/78] 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 eacf2ca2..fb1c3182 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 76aa5f4f..0bf32935 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/78] 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 0bf32935..4f0fe7ac 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 c4346899..863a7b46 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 a7944442..3dcd4cfc 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 2a6c8b90..d0ec07fc 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 7a897f3e..c96a61ea 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 a657d789..6d48971d 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 f67264ce..3ee219c4 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/78] 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 cedf392e..7a22001e 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 82661b5f..d504db1e 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 358837fa..09bb6342 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 6b7583ea..fddd9a38 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 7f821700..41b546a5 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 5ca0bb0e..b1581399 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/78] 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 797a70a6..f978dac3 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 fb1c3182..f3ea51bc 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 41b546a5..db7a9eb3 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 b1581399..f56f07f2 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 ef3468bb..fa29aa1a 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 4a4b222e..d304096b 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/78] 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 f3ea51bc..10861139 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 d304096b..9ad06e73 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/78] 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 10861139..c6065fd4 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 4f0fe7ac..f21b45f9 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 5f505ce5..6cea1cca 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 c20422b7..c08baeff 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 bd3c7ee7..8a815062 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 078209d5..eddd8639 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 09bb6342..56fe7c66 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 fddd9a38..a1c726e5 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 db7a9eb3..6434ec17 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 f56f07f2..2f7f8f93 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 fa29aa1a..4d4e9b84 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 b48aab51..60d1a013 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/78] 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 c6065fd4..424c71c7 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 f21b45f9..c0ea4054 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 2e4b970c..c22dbf19 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 2f7f8f93..a613c93c 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, _ => { From 00000639991ab325036dfc2ce8e11b798fcb85fe Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:08:59 +0200 Subject: [PATCH 61/78] feat: started new cli --- Cargo.lock | 127 ++++++++++++++++++++++ compiler/compiler_main/Cargo.toml | 1 + compiler/compiler_main/src/cli.rs | 28 +++++ compiler/compiler_main/src/cmds/astoir.rs | 86 --------------- compiler/compiler_main/src/cmds/mod.rs | 1 - compiler/compiler_main/src/main.rs | 24 +--- 6 files changed, 160 insertions(+), 107 deletions(-) create mode 100644 compiler/compiler_main/src/cli.rs delete mode 100644 compiler/compiler_main/src/cmds/astoir.rs delete mode 100644 compiler/compiler_main/src/cmds/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 7a22001e..12e7acde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,56 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -110,6 +160,52 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "colored" version = "3.1.1" @@ -133,6 +229,7 @@ dependencies = [ "ast", "ast_parser", "astoir", + "clap", "compiler_utils", "diagnostics", "lexer", @@ -177,6 +274,12 @@ dependencies = [ "wasi", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "inkwell" version = "0.8.0" @@ -199,6 +302,12 @@ dependencies = [ "syn", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "lazy_static" version = "1.5.0" @@ -243,6 +352,12 @@ dependencies = [ "rand", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -329,6 +444,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "2.0.117" @@ -366,6 +487,12 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" diff --git a/compiler/compiler_main/Cargo.toml b/compiler/compiler_main/Cargo.toml index 6a2ddc34..4122199a 100644 --- a/compiler/compiler_main/Cargo.toml +++ b/compiler/compiler_main/Cargo.toml @@ -11,6 +11,7 @@ lexer = { path = "../lexer" } llvm_ir_bridge = { path = "../llvm_ir_bridge", optional = true, default-features = false } diagnostics = { path = "../diagnostics" } compiler_utils = { path = "../compiler_utils" } +clap = { version = "4.0", features = ["derive"] } [features] llvm = ["llvm_ir_bridge"] diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs new file mode 100644 index 00000000..a6b68681 --- /dev/null +++ b/compiler/compiler_main/src/cli.rs @@ -0,0 +1,28 @@ +use clap::{Parser, Subcommand, ValueEnum}; + +#[derive(Parser)] +pub struct Cli { + #[command(subcommand)] + pub command: CLICommand, +} + +#[derive(Clone, Copy, PartialEq, Eq, ValueEnum, Debug)] +pub enum Platform { + AstoIR, + LLVM, +} + +#[derive(Subcommand)] +pub enum CLICommand { + #[command(visible_alias = "b")] + Build { + #[arg(short = 'o')] + out: String, + + #[arg(long, value_enum, default_value = "llvm")] + platform: Platform, + + #[arg(required = true)] + input: Vec, + }, +} diff --git a/compiler/compiler_main/src/cmds/astoir.rs b/compiler/compiler_main/src/cmds/astoir.rs deleted file mode 100644 index 3600ee30..00000000 --- a/compiler/compiler_main/src/cmds/astoir.rs +++ /dev/null @@ -1,86 +0,0 @@ -use std::fs; - -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) { - 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); - } - }; -} diff --git a/compiler/compiler_main/src/cmds/mod.rs b/compiler/compiler_main/src/cmds/mod.rs deleted file mode 100644 index 64e781c6..00000000 --- a/compiler/compiler_main/src/cmds/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod astoir; diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 0ba93868..30237354 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -1,25 +1,9 @@ -use std::env; +use clap::Parser; -use crate::cmds::astoir::parse_astoir_command; +use crate::cli::{CLICommand, Cli}; -pub mod cmds; +pub mod cli; fn main() { - let arguments: Vec = env::args().collect(); - - if arguments.len() <= 1 { - println!("Usage: quickfall comp|astoir"); - return; - } - - match &arguments[1] as &str { - "astoir" => { - parse_astoir_command(arguments); - } - - _ => { - println!("Invalid subcommand!"); - return; - } - } + let cli = Cli::parse(); } From 2ebccbcc0508837618417cf8fbf58cd56c5e881f Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:18:46 +0200 Subject: [PATCH 62/78] feat: added more arguments and a check command --- compiler/compiler_main/src/cli.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs index a6b68681..bbb89a7c 100644 --- a/compiler/compiler_main/src/cli.rs +++ b/compiler/compiler_main/src/cli.rs @@ -12,9 +12,15 @@ pub enum Platform { LLVM, } +#[derive(Clone, Copy, PartialEq, Eq, ValueEnum, Debug)] +pub enum IRLayer { + HIR, + MIR, +} + #[derive(Subcommand)] pub enum CLICommand { - #[command(visible_alias = "b")] + #[command(visible_alias = "b", about = "Builds the given file(s)")] Build { #[arg(short = 'o')] out: String, @@ -22,7 +28,22 @@ pub enum CLICommand { #[arg(long, value_enum, default_value = "llvm")] platform: Platform, + #[arg(short = 'l', default_value = "ld")] + linker: String, + + #[arg(required = true)] + input: Vec, + }, + + #[command(visible_alias = "ver", about = "Displays the version")] + Version, + + #[command(about = "Checks if a file is valid")] + Check { #[arg(required = true)] input: Vec, + + #[arg(long, value_enum, default_value = "mir")] + layer: IRLayer, }, } From 9b09b424b2479d823adc1a8dc3865015cfa8cd10 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:23:24 +0200 Subject: [PATCH 63/78] feat: added format argument --- compiler/compiler_main/src/cli.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs index bbb89a7c..1311b8cf 100644 --- a/compiler/compiler_main/src/cli.rs +++ b/compiler/compiler_main/src/cli.rs @@ -18,6 +18,17 @@ pub enum IRLayer { MIR, } +#[derive(Clone, Copy, PartialEq, Eq, ValueEnum, Debug)] +pub enum OutputFormat { + #[value(alias = "exec")] + Executable, + + #[value(alias = "o")] + Object, + + IR, +} + #[derive(Subcommand)] pub enum CLICommand { #[command(visible_alias = "b", about = "Builds the given file(s)")] @@ -28,6 +39,9 @@ pub enum CLICommand { #[arg(long, value_enum, default_value = "llvm")] platform: Platform, + #[arg(short = 't', value_enum, long, default_value = "o")] + format: OutputFormat, + #[arg(short = 'l', default_value = "ld")] linker: String, From c2bab051cb67accb33f56acdaabb52a79f8b1dcb Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:26:57 +0200 Subject: [PATCH 64/78] feat: added version display --- compiler/compiler_main/build.rs | 12 ++++++++++++ compiler/compiler_main/src/main.rs | 14 +++++++++++++- compiler/compiler_main/src/version.rs | 2 ++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 compiler/compiler_main/build.rs create mode 100644 compiler/compiler_main/src/version.rs diff --git a/compiler/compiler_main/build.rs b/compiler/compiler_main/build.rs new file mode 100644 index 00000000..cb884c6b --- /dev/null +++ b/compiler/compiler_main/build.rs @@ -0,0 +1,12 @@ +use std::process::Command; + +fn main() { + let out = Command::new("git") + .args(["rev-parse", "HEAD"]) + .output() + .unwrap(); + + let git_hash = String::from_utf8(out.stdout).unwrap(); + + println!("cargo:rustc-env=GIT_HASH={}", git_hash.trim()); +} diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 30237354..50a13f84 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -1,9 +1,21 @@ use clap::Parser; -use crate::cli::{CLICommand, Cli}; +use crate::{ + cli::{CLICommand, Cli}, + version::{GIT_HASH, VERSION}, +}; pub mod cli; +pub mod version; fn main() { let cli = Cli::parse(); + + match cli.command { + CLICommand::Version => { + println!("Quickfall v{} (commit {})", VERSION, GIT_HASH); + } + + _ => todo!(), + } } diff --git a/compiler/compiler_main/src/version.rs b/compiler/compiler_main/src/version.rs new file mode 100644 index 00000000..ca1b45fd --- /dev/null +++ b/compiler/compiler_main/src/version.rs @@ -0,0 +1,2 @@ +pub const GIT_HASH: &str = env!("GIT_HASH"); +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); From 932041ff831c835a2d2b539e9dd1784efcdf09fd Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 14:45:53 +0200 Subject: [PATCH 65/78] feat: added check subcommand --- compiler/compiler_main/src/cmds/check.rs | 25 ++++++++++++++++++++++++ compiler/compiler_main/src/cmds/mod.rs | 11 +++++++++++ compiler/compiler_main/src/main.rs | 19 ++++++++++++++++++ compiler/diagnostics/src/lib.rs | 4 ++++ 4 files changed, 59 insertions(+) create mode 100644 compiler/compiler_main/src/cmds/check.rs create mode 100644 compiler/compiler_main/src/cmds/mod.rs diff --git a/compiler/compiler_main/src/cmds/check.rs b/compiler/compiler_main/src/cmds/check.rs new file mode 100644 index 00000000..b34aef36 --- /dev/null +++ b/compiler/compiler_main/src/cmds/check.rs @@ -0,0 +1,25 @@ +use ast_parser::parse_ast_ctx; +use astoir::{run_astoir_hir, run_astoir_mir}; +use lexer::lexer::lexer_parse_file; + +use crate::{cli::IRLayer, quietlyquit_if_errors}; + +pub fn run_check(path: String, layer: IRLayer) { + let lexer = lexer_parse_file(&path); + quietlyquit_if_errors!(); + + let ast = parse_ast_ctx(&lexer.unwrap()); + quietlyquit_if_errors!(); + + match layer { + IRLayer::HIR => { + let hir = run_astoir_hir(ast.unwrap()); + quietlyquit_if_errors!(); + } + + IRLayer::MIR => { + let mir = run_astoir_mir(ast.unwrap()); + quietlyquit_if_errors!(); + } + } +} diff --git a/compiler/compiler_main/src/cmds/mod.rs b/compiler/compiler_main/src/cmds/mod.rs new file mode 100644 index 00000000..65a2a0cb --- /dev/null +++ b/compiler/compiler_main/src/cmds/mod.rs @@ -0,0 +1,11 @@ +pub mod check; + +#[macro_export] +macro_rules! quietlyquit_if_errors { + () => { + if (diagnostics::has_diagnostics()) { + diagnostics::dump_diagnostics(); + std::process::exit(445); + } + }; +} diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 50a13f84..471623e6 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -1,11 +1,15 @@ +use std::time::Instant; + use clap::Parser; use crate::{ cli::{CLICommand, Cli}, + cmds::check::run_check, version::{GIT_HASH, VERSION}, }; pub mod cli; +pub mod cmds; pub mod version; fn main() { @@ -16,6 +20,21 @@ fn main() { println!("Quickfall v{} (commit {})", VERSION, GIT_HASH); } + CLICommand::Check { input, layer } => { + let start = Instant::now(); + let count = input.len(); + + for file in input { + run_check(file, layer); + } + + println!( + "No problems could be found in the {} provided files! Checked in {:?}", + count, + start.elapsed() + ) + } + _ => todo!(), } } diff --git a/compiler/diagnostics/src/lib.rs b/compiler/diagnostics/src/lib.rs index 994c6bab..90114d0d 100644 --- a/compiler/diagnostics/src/lib.rs +++ b/compiler/diagnostics/src/lib.rs @@ -70,6 +70,10 @@ pub fn dump_diagnostics() { }) } +pub fn has_diagnostics() -> bool { + DIAGNOSTIC_CONTAINER.with_borrow(|f| return !f.diagnostics.is_empty()) +} + pub fn move_current_diagnostic_pos(pos: SpanPosition) { CURR_DIAGNOSTIC_POS.with_borrow_mut(|f| { *f = Some(pos); From 8e25cee0637e55271acdd5d7756570d5558c45de Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:11:00 +0200 Subject: [PATCH 66/78] feat: added AstoIR build target --- compiler/compiler_main/src/cli.rs | 6 ++- compiler/compiler_main/src/cmds/build.rs | 20 ++++++++++ compiler/compiler_main/src/cmds/mod.rs | 9 +++++ compiler/compiler_main/src/main.rs | 50 ++++++++++++++++++++++-- 4 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 compiler/compiler_main/src/cmds/build.rs diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs index 1311b8cf..d1054531 100644 --- a/compiler/compiler_main/src/cli.rs +++ b/compiler/compiler_main/src/cli.rs @@ -1,3 +1,5 @@ +use std::path::{Path, PathBuf}; + use clap::{Parser, Subcommand, ValueEnum}; #[derive(Parser)] @@ -34,7 +36,7 @@ pub enum CLICommand { #[command(visible_alias = "b", about = "Builds the given file(s)")] Build { #[arg(short = 'o')] - out: String, + out: PathBuf, #[arg(long, value_enum, default_value = "llvm")] platform: Platform, @@ -46,7 +48,7 @@ pub enum CLICommand { linker: String, #[arg(required = true)] - input: Vec, + input: Vec, }, #[command(visible_alias = "ver", about = "Displays the version")] diff --git a/compiler/compiler_main/src/cmds/build.rs b/compiler/compiler_main/src/cmds/build.rs new file mode 100644 index 00000000..c6a238c3 --- /dev/null +++ b/compiler/compiler_main/src/cmds/build.rs @@ -0,0 +1,20 @@ +use std::{fs, path::PathBuf}; + +use ast_parser::parse_ast_ctx; +use astoir::run_astoir_mir; +use lexer::lexer::lexer_parse_file; + +use crate::quietlyquit_if_errors; + +pub fn build_mir(path: String, out: PathBuf) { + let lexer = lexer_parse_file(&path); + quietlyquit_if_errors!(); + + let ast = parse_ast_ctx(&lexer.unwrap()); + quietlyquit_if_errors!(); + + let mir = run_astoir_mir(ast.unwrap()); + quietlyquit_if_errors!(); + + fs::write(out, format!("{}", mir.unwrap())).unwrap(); +} diff --git a/compiler/compiler_main/src/cmds/mod.rs b/compiler/compiler_main/src/cmds/mod.rs index 65a2a0cb..63299823 100644 --- a/compiler/compiler_main/src/cmds/mod.rs +++ b/compiler/compiler_main/src/cmds/mod.rs @@ -1,3 +1,4 @@ +pub mod build; pub mod check; #[macro_export] @@ -9,3 +10,11 @@ macro_rules! quietlyquit_if_errors { } }; } + +#[macro_export] +macro_rules! soft_panic { + ($lit:literal) => { + println!($lit); + std::process::exit(445) + }; +} diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 471623e6..969d31a2 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -1,10 +1,15 @@ -use std::time::Instant; +use std::{ + fs, + path::{Path, PathBuf}, + process::Output, + time::Instant, +}; use clap::Parser; use crate::{ - cli::{CLICommand, Cli}, - cmds::check::run_check, + cli::{CLICommand, Cli, OutputFormat, Platform}, + cmds::{build::build_mir, check::run_check}, version::{GIT_HASH, VERSION}, }; @@ -35,6 +40,45 @@ fn main() { ) } + CLICommand::Build { + out, + platform, + format, + linker, + input, + } => { + let needs_dir = input.len() > 1 && format != OutputFormat::Executable; + + if input.len() > 1 && out.extension().is_some() && format != OutputFormat::Executable { + soft_panic!( + "Output must be a directory if theres more than one input and that the target isn't an executable" + ); + } + + if needs_dir && !out.exists() { + fs::create_dir_all(out.clone()).unwrap(); + } + + if platform == Platform::AstoIR && format != OutputFormat::IR { + soft_panic!("Only IR target is supported by AstoIR platform!"); + } + + match platform { + Platform::AstoIR => { + for i in input { + let mut outfile = PathBuf::from(i.file_name().unwrap()); + outfile.add_extension("air"); + + let output_path = out.join(outfile); + + build_mir(i.to_str().unwrap().to_string(), output_path); + } + } + + _ => todo!(), + } + } + _ => todo!(), } } From 813d555194559a83131eda2bc80f97b06898ca95 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 15:13:18 +0200 Subject: [PATCH 67/78] feat: renamed platform -> bridge --- compiler/compiler_main/src/cli.rs | 6 +++--- compiler/compiler_main/src/main.rs | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs index d1054531..f1d358d7 100644 --- a/compiler/compiler_main/src/cli.rs +++ b/compiler/compiler_main/src/cli.rs @@ -9,7 +9,7 @@ pub struct Cli { } #[derive(Clone, Copy, PartialEq, Eq, ValueEnum, Debug)] -pub enum Platform { +pub enum Bridge { AstoIR, LLVM, } @@ -38,8 +38,8 @@ pub enum CLICommand { #[arg(short = 'o')] out: PathBuf, - #[arg(long, value_enum, default_value = "llvm")] - platform: Platform, + #[arg(long, value_enum, default_value = "llvm", short = 'b')] + bridge: Bridge, #[arg(short = 't', value_enum, long, default_value = "o")] format: OutputFormat, diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 969d31a2..82f35313 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -1,14 +1,13 @@ use std::{ fs, path::{Path, PathBuf}, - process::Output, time::Instant, }; use clap::Parser; use crate::{ - cli::{CLICommand, Cli, OutputFormat, Platform}, + cli::{Bridge, CLICommand, Cli, OutputFormat}, cmds::{build::build_mir, check::run_check}, version::{GIT_HASH, VERSION}, }; @@ -42,7 +41,7 @@ fn main() { CLICommand::Build { out, - platform, + bridge, format, linker, input, @@ -59,12 +58,12 @@ fn main() { fs::create_dir_all(out.clone()).unwrap(); } - if platform == Platform::AstoIR && format != OutputFormat::IR { + if bridge == Bridge::AstoIR && format != OutputFormat::IR { soft_panic!("Only IR target is supported by AstoIR platform!"); } - match platform { - Platform::AstoIR => { + match bridge { + Bridge::AstoIR => { for i in input { let mut outfile = PathBuf::from(i.file_name().unwrap()); outfile.add_extension("air"); From 2c015a221c8d9a1c19366ca415ae12ca2d62860d Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:20:16 +0200 Subject: [PATCH 68/78] feat: added language server check --- compiler/compiler_main/src/cli.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs index f1d358d7..a6378d1f 100644 --- a/compiler/compiler_main/src/cli.rs +++ b/compiler/compiler_main/src/cli.rs @@ -62,4 +62,10 @@ pub enum CLICommand { #[arg(long, value_enum, default_value = "mir")] layer: IRLayer, }, + + #[command(about = "Runs language server analysis", visible_alias = "lscheck")] + LanguageServerCheck { + #[arg(required = true)] + input: PathBuf, + }, } From 20f8ec0b04468319989e10e94452adaea4458fed Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:01:03 +0200 Subject: [PATCH 69/78] chore: started working on LSP --- Cargo.lock | 767 ++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 18 +- lsp/Cargo.toml | 8 + 3 files changed, 791 insertions(+), 2 deletions(-) create mode 100644 lsp/Cargo.toml diff --git a/Cargo.lock b/Cargo.lock index 12e7acde..26889b79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -138,12 +138,46 @@ dependencies = [ "diagnostics", ] +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "auto_impl" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + [[package]] name = "cc" version = "1.2.57" @@ -249,6 +283,19 @@ dependencies = [ name = "compiler_utils" version = "0.1.0" +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "diagnostics" version = "0.1.0" @@ -257,12 +304,118 @@ dependencies = [ "compiler_utils", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -274,18 +427,133 @@ dependencies = [ "wasi", ] +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + [[package]] name = "inkwell" version = "0.8.0" source = "git+https://github.com/TheDan64/inkwell#07fa9f2435a9ee0521b88008324f229ff51a5b3e" dependencies = [ - "bitflags", + "bitflags 2.11.0", "inkwell_internals", "libc", "llvm-sys", @@ -308,6 +576,12 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + [[package]] name = "lazy_static" version = "1.5.0" @@ -328,6 +602,12 @@ version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + [[package]] name = "llvm-sys" version = "221.0.0" @@ -352,12 +632,129 @@ dependencies = [ "rand", ] +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "lsp" +version = "0.1.0" +dependencies = [ + "tokio", + "tower-lsp", +] + +[[package]] +name = "lsp-types" +version = "0.94.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +dependencies = [ + "bitflags 1.3.2", + "serde", + "serde_json", + "serde_repr", + "url", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -426,24 +823,131 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "regex-lite" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strsim" version = "0.11.1" @@ -461,6 +965,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "2.0.18" @@ -481,12 +996,173 @@ dependencies = [ "syn", ] +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tokio" +version = "1.52.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-lsp" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4ba052b54a6627628d9b3c34c176e7eda8359b7da9acd497b9f20998d118508" +dependencies = [ + "async-trait", + "auto_impl", + "bytes", + "dashmap", + "futures", + "httparse", + "lsp-types", + "memchr", + "serde", + "serde_json", + "tokio", + "tokio-util", + "tower", + "tower-lsp-macros", + "tracing", +] + +[[package]] +name = "tower-lsp-macros" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84fd902d4e0b9a4b27f2f440108dc034e1758628a9b702f8ec61ad66355422fa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", + "serde_derive", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -514,6 +1190,35 @@ dependencies = [ "windows-link", ] +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.8.42" @@ -533,3 +1238,63 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index 03da646a..e2fd34c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,18 @@ [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", "compiler/compiler_global_scope"] +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", + "lsp", +] diff --git a/lsp/Cargo.toml b/lsp/Cargo.toml new file mode 100644 index 00000000..b7c93155 --- /dev/null +++ b/lsp/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "lsp" +version = "0.1.0" +edition = "2024" + +[dependencies] +tower-lsp = "0.20" +tokio = { version = "1", features = ["full"] } From 0104e32aafbaf29c7740378a84c65ab613929574 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:05:50 +0200 Subject: [PATCH 70/78] feat: added basic LSP --- lsp/src/lsp.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++++ lsp/src/main.rs | 3 +++ 2 files changed, 49 insertions(+) create mode 100644 lsp/src/lsp.rs create mode 100644 lsp/src/main.rs diff --git a/lsp/src/lsp.rs b/lsp/src/lsp.rs new file mode 100644 index 00000000..cf5465e5 --- /dev/null +++ b/lsp/src/lsp.rs @@ -0,0 +1,46 @@ +use std::{ + collections::{HashMap, HashSet}, + sync::{Arc, Mutex}, +}; + +use tower_lsp::{ + Client, LanguageServer, + lsp_types::{ + CompletionOptions, HoverProviderCapability, InitializeParams, InitializeResult, + InitializedParams, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, + TextDocumentSyncKind, + }, +}; + +#[derive(Debug)] +pub struct LSPBackend { + lsp_client: Client, + documents: Arc>>, +} + +#[tower_lsp::async_trait] +impl LanguageServer for LSPBackend { + async fn initialize( + &self, + _: InitializeParams, + ) -> tower_lsp::jsonrpc::Result { + Ok(InitializeResult { + capabilities: ServerCapabilities { + hover_provider: Some(HoverProviderCapability::Simple(true)), + completion_provider: Some(CompletionOptions::default()), + text_document_sync: Some(TextDocumentSyncCapability::Kind( + TextDocumentSyncKind::FULL, + )), + ..Default::default() + }, + server_info: Some(ServerInfo { + name: "quickfall-lsp".to_string(), + version: Some("0.1".to_string()), + }), + }) + } + + async fn shutdown(&self) -> tower_lsp::jsonrpc::Result<()> { + Ok(()) + } +} diff --git a/lsp/src/main.rs b/lsp/src/main.rs new file mode 100644 index 00000000..4ad3da8e --- /dev/null +++ b/lsp/src/main.rs @@ -0,0 +1,3 @@ +pub mod lsp; + +fn main() {} From b6b5a729044ac70d1d7be967d916808bafc72872 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:18:01 +0200 Subject: [PATCH 71/78] =?UTF-8?q?feat:=20added=20diagnostic=20conversion?= =?UTF-8?q?=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 1 + lsp/Cargo.toml | 1 + lsp/src/diags.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ lsp/src/main.rs | 1 + 4 files changed, 50 insertions(+) create mode 100644 lsp/src/diags.rs diff --git a/Cargo.lock b/Cargo.lock index 26889b79..5b617781 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,6 +645,7 @@ dependencies = [ name = "lsp" version = "0.1.0" dependencies = [ + "diagnostics", "tokio", "tower-lsp", ] diff --git a/lsp/Cargo.toml b/lsp/Cargo.toml index b7c93155..42fb104a 100644 --- a/lsp/Cargo.toml +++ b/lsp/Cargo.toml @@ -6,3 +6,4 @@ edition = "2024" [dependencies] tower-lsp = "0.20" tokio = { version = "1", features = ["full"] } +diagnostics = { path = "../compiler/diagnostics" } diff --git a/lsp/src/diags.rs b/lsp/src/diags.rs new file mode 100644 index 00000000..9b4eee41 --- /dev/null +++ b/lsp/src/diags.rs @@ -0,0 +1,47 @@ +use diagnostics::diagnostic::Level; +use tower_lsp::lsp_types::{ + Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, Location, Position, Range, Url, +}; + +pub fn to_tower_diag(diagnostic: diagnostics::diagnostic::Diagnostic) -> Diagnostic { + let severity = match diagnostic.level { + Level::Error => DiagnosticSeverity::ERROR, + Level::Warning => DiagnosticSeverity::WARNING, + Level::Note => DiagnosticSeverity::INFORMATION, + }; + + let mut related_info = vec![]; + + for span in diagnostic.spans { + related_info.push(DiagnosticRelatedInformation { + location: Location { + uri: Url::parse(&span.start.file_path).unwrap(), + range: Range { + start: Position::new(span.start.line as u32, span.start.col as u32), + end: Position::new(span.start.line as u32, span.start.end_col as u32), + }, + }, + message: span.label.unwrap().into(), + }); + } + + let main_range = Range { + start: Position::new( + diagnostic.primary_span.start.line as u32, + diagnostic.primary_span.start.col as u32, + ), + end: Position::new( + diagnostic.primary_span.start.line as u32, + diagnostic.primary_span.start.end_col as u32, + ), + }; + + Diagnostic { + range: main_range, + message: diagnostic.primary_span.label.unwrap(), + severity: Some(severity), + related_information: Some(related_info), + + ..Default::default() + } +} diff --git a/lsp/src/main.rs b/lsp/src/main.rs index 4ad3da8e..4c24f277 100644 --- a/lsp/src/main.rs +++ b/lsp/src/main.rs @@ -1,3 +1,4 @@ +pub mod diags; pub mod lsp; fn main() {} From 28ea2e9ae324536f23553b13d7c6d89841ed7111 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 22:38:43 +0200 Subject: [PATCH 72/78] feat: added basic checking --- Cargo.lock | 4 ++++ compiler/diagnostics/src/lib.rs | 4 ++++ compiler/lexer/src/lexer.rs | 2 +- lsp/Cargo.toml | 4 ++++ lsp/src/bridge.rs | 20 ++++++++++++++++++++ lsp/src/diags.rs | 20 ++++++++++++++++++-- lsp/src/lsp.rs | 33 ++++++++++++++++++++++++++++----- lsp/src/main.rs | 22 +++++++++++++++++++++- 8 files changed, 100 insertions(+), 9 deletions(-) create mode 100644 lsp/src/bridge.rs diff --git a/Cargo.lock b/Cargo.lock index 5b617781..5a1aa7f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -645,7 +645,11 @@ dependencies = [ name = "lsp" version = "0.1.0" dependencies = [ + "ast", + "ast_parser", + "astoir", "diagnostics", + "lexer", "tokio", "tower-lsp", ] diff --git a/compiler/diagnostics/src/lib.rs b/compiler/diagnostics/src/lib.rs index 90114d0d..3b3cb94b 100644 --- a/compiler/diagnostics/src/lib.rs +++ b/compiler/diagnostics/src/lib.rs @@ -74,6 +74,10 @@ pub fn has_diagnostics() -> bool { DIAGNOSTIC_CONTAINER.with_borrow(|f| return !f.diagnostics.is_empty()) } +pub fn get_diagnostics() -> Vec { + DIAGNOSTIC_CONTAINER.with_borrow(|f| return f.diagnostics.clone()) +} + pub fn move_current_diagnostic_pos(pos: SpanPosition) { CURR_DIAGNOSTIC_POS.with_borrow_mut(|f| { *f = Some(pos); diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index d0520bca..68d87254 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -42,7 +42,7 @@ const USE_KEYWORD_HASH: u64 = hash!("use"); pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> { let contents: String = match fs::read_to_string(file_path) { Ok(v) => v, - Err(_) => panic!("Couldn't read the file"), + Err(_) => panic!("Couldn't read the file {}", file_path), }; let mut tokens: Vec = Vec::new(); diff --git a/lsp/Cargo.toml b/lsp/Cargo.toml index 42fb104a..91c0b493 100644 --- a/lsp/Cargo.toml +++ b/lsp/Cargo.toml @@ -7,3 +7,7 @@ edition = "2024" tower-lsp = "0.20" tokio = { version = "1", features = ["full"] } diagnostics = { path = "../compiler/diagnostics" } +astoir = { path = "../compiler/astoir" } +ast = { path = "../compiler/ast" } +ast_parser = { path = "../compiler/ast_parser" } +lexer = { path = "../compiler/lexer" } diff --git a/lsp/src/bridge.rs b/lsp/src/bridge.rs new file mode 100644 index 00000000..fd13e4b8 --- /dev/null +++ b/lsp/src/bridge.rs @@ -0,0 +1,20 @@ +use ast_parser::parse_ast_ctx; +use astoir::run_astoir_mir; +use diagnostics::{diagnostic::Diagnostic, get_diagnostics, has_diagnostics}; +use lexer::lexer::lexer_parse_file; + +pub fn check_for_file(url: String) -> Vec { + let lexer = lexer_parse_file(&url); + if has_diagnostics() { + return get_diagnostics(); + } + + let ast = parse_ast_ctx(&lexer.unwrap()); + if has_diagnostics() { + return get_diagnostics(); + } + + run_astoir_mir(ast.unwrap()); + + return get_diagnostics(); +} diff --git a/lsp/src/diags.rs b/lsp/src/diags.rs index 9b4eee41..8c0eea83 100644 --- a/lsp/src/diags.rs +++ b/lsp/src/diags.rs @@ -3,6 +3,8 @@ use tower_lsp::lsp_types::{ Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, Location, Position, Range, Url, }; +use crate::main; + pub fn to_tower_diag(diagnostic: diagnostics::diagnostic::Diagnostic) -> Diagnostic { let severity = match diagnostic.level { Level::Error => DiagnosticSeverity::ERROR, @@ -15,7 +17,7 @@ pub fn to_tower_diag(diagnostic: diagnostics::diagnostic::Diagnostic) -> Diagnos for span in diagnostic.spans { related_info.push(DiagnosticRelatedInformation { location: Location { - uri: Url::parse(&span.start.file_path).unwrap(), + uri: Url::parse(&format!("file:///{}", span.start.file_path)).unwrap(), range: Range { start: Position::new(span.start.line as u32, span.start.col as u32), end: Position::new(span.start.line as u32, span.start.end_col as u32), @@ -36,9 +38,23 @@ pub fn to_tower_diag(diagnostic: diagnostics::diagnostic::Diagnostic) -> Diagnos ), }; + if diagnostic.primary_span.label.is_some() { + related_info.push(DiagnosticRelatedInformation { + location: Location { + uri: Url::parse(&format!( + "file:///{}", + diagnostic.primary_span.start.file_path + )) + .unwrap(), + range: main_range.clone(), + }, + message: diagnostic.primary_span.label.unwrap(), + }) + } + Diagnostic { range: main_range, - message: diagnostic.primary_span.label.unwrap(), + message: diagnostic.message, severity: Some(severity), related_information: Some(related_info), diff --git a/lsp/src/lsp.rs b/lsp/src/lsp.rs index cf5465e5..7bb5fa8b 100644 --- a/lsp/src/lsp.rs +++ b/lsp/src/lsp.rs @@ -6,16 +6,18 @@ use std::{ use tower_lsp::{ Client, LanguageServer, lsp_types::{ - CompletionOptions, HoverProviderCapability, InitializeParams, InitializeResult, - InitializedParams, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, - TextDocumentSyncKind, + CompletionOptions, DidOpenTextDocumentParams, HoverProviderCapability, InitializeParams, + InitializeResult, InitializedParams, MessageType, ServerCapabilities, ServerInfo, + TextDocumentSyncCapability, TextDocumentSyncKind, }, }; +use crate::{bridge::check_for_file, diags::to_tower_diag}; + #[derive(Debug)] pub struct LSPBackend { - lsp_client: Client, - documents: Arc>>, + pub lsp_client: Client, + pub documents: Arc>>, } #[tower_lsp::async_trait] @@ -40,6 +42,27 @@ impl LanguageServer for LSPBackend { }) } + async fn did_open(&self, param: DidOpenTextDocumentParams) { + let uri = param.text_document.uri.to_string(); + let text = param.text_document.text; + + self.documents.lock().unwrap().insert(uri.clone()); + + let mut diags = vec![]; + + self.lsp_client + .log_message(MessageType::ERROR, format!("Path: {}", uri)) + .await; + + for diag in check_for_file(uri.clone().replace("file://", "")) { + diags.push(to_tower_diag(diag)) + } + + self.lsp_client + .publish_diagnostics(uri.parse().unwrap(), diags, None) + .await; + } + async fn shutdown(&self) -> tower_lsp::jsonrpc::Result<()> { Ok(()) } diff --git a/lsp/src/main.rs b/lsp/src/main.rs index 4c24f277..97fb340e 100644 --- a/lsp/src/main.rs +++ b/lsp/src/main.rs @@ -1,4 +1,24 @@ +use std::{ + collections::HashSet, + sync::{Arc, Mutex}, +}; + +use tower_lsp::{LspService, Server}; + +use crate::lsp::LSPBackend; + +pub mod bridge; pub mod diags; pub mod lsp; -fn main() {} +#[tokio::main] +async fn main() { + let stdin = tokio::io::stdin(); + let stdout = tokio::io::stdout(); + let (service, socket) = LspService::build(|client| LSPBackend { + lsp_client: client, + documents: Arc::new(Mutex::new(HashSet::new())), + }) + .finish(); + Server::new(stdin, stdout, socket).serve(service).await; +} From feb51e69c5ad22aa1511723fdec8a7664c49c7e3 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:03:52 +0200 Subject: [PATCH 73/78] feat: added debug log for later --- compiler/astoir_hir_lowering/src/types.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/astoir_hir_lowering/src/types.rs b/compiler/astoir_hir_lowering/src/types.rs index 95d9b44f..f04c4b09 100644 --- a/compiler/astoir_hir_lowering/src/types.rs +++ b/compiler/astoir_hir_lowering/src/types.rs @@ -65,6 +65,10 @@ pub fn lower_ast_type( { return Ok(Type::Generic(t, vec![], vec![])); } else { + + println!("{}: {:#?}", hash, lower); + println!("{:#?}", context.global_scope.get_type(EntryKey { name_hash: hash }, origin)); + let ind = match context.global_scope.append( EntryKey { name_hash: hash }, GlobalStorageEntryType::Type(lower), From 4d555513532c1a9327794ff18f526e6ca20da523 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:04:50 +0200 Subject: [PATCH 74/78] chore: fixed warns --- compiler/compiler_main/src/cli.rs | 2 +- compiler/compiler_main/src/cmds/check.rs | 4 ++-- compiler/compiler_main/src/main.rs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/compiler_main/src/cli.rs b/compiler/compiler_main/src/cli.rs index a6378d1f..9687fdd4 100644 --- a/compiler/compiler_main/src/cli.rs +++ b/compiler/compiler_main/src/cli.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use clap::{Parser, Subcommand, ValueEnum}; diff --git a/compiler/compiler_main/src/cmds/check.rs b/compiler/compiler_main/src/cmds/check.rs index b34aef36..cc402530 100644 --- a/compiler/compiler_main/src/cmds/check.rs +++ b/compiler/compiler_main/src/cmds/check.rs @@ -13,12 +13,12 @@ pub fn run_check(path: String, layer: IRLayer) { match layer { IRLayer::HIR => { - let hir = run_astoir_hir(ast.unwrap()); + let _hir = run_astoir_hir(ast.unwrap()); quietlyquit_if_errors!(); } IRLayer::MIR => { - let mir = run_astoir_mir(ast.unwrap()); + let _mir = run_astoir_mir(ast.unwrap()); quietlyquit_if_errors!(); } } diff --git a/compiler/compiler_main/src/main.rs b/compiler/compiler_main/src/main.rs index 82f35313..c0e5855b 100644 --- a/compiler/compiler_main/src/main.rs +++ b/compiler/compiler_main/src/main.rs @@ -1,6 +1,6 @@ use std::{ fs, - path::{Path, PathBuf}, + path::PathBuf, time::Instant, }; @@ -43,7 +43,7 @@ fn main() { out, bridge, format, - linker, + linker: _, input, } => { let needs_dir = input.len() > 1 && format != OutputFormat::Executable; From a5ab5ab83b905a590a17acd06afc54d49ea5d268 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:10:52 +0200 Subject: [PATCH 75/78] chore: added README --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index fed3dc0f..668ce99b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ # Quickfall +![GitHub Release](https://img.shields.io/github/v/release/Quickfall/quickfall?include_prereleases) +![GitHub repo size](https://img.shields.io/github/repo-size/Quickfall/quickfall) +![GitHub Issues or Pull Requests](https://img.shields.io/github/issues/Quickfall/Quickfall) + + Quickfall is a programming language focusing on allowing everyone to build fast, reliable and safe software. ## Why Quickfall From 07ffc58d5d3c0ea5f241f552760b4dc8615f87d1 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:14:13 +0200 Subject: [PATCH 76/78] chore: added more detail for the CONTRIBUTING --- CONTRIBUTING.MD | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD index a0270a61..2ada2422 100644 --- a/CONTRIBUTING.MD +++ b/CONTRIBUTING.MD @@ -17,4 +17,11 @@ You will need the following installed in order to compile & use Quickfall: - 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 +You can then build the project by using the `cargo` Rust tool. + +You can build different targets for the Quickfall project: +- `-p compiler_main`: The compiler +- `-p lsp`: The language server provider + +Additionally, for the compiler target. You can add different features to customize the build. Here's a list of features and what they change +- `diagbacktraces`: Add backtraces for inside of the compiler codebase for every Diagnostic. Automatically enables backtraces on diagnostics \ No newline at end of file From 7cefa3313cf337d9a1d65d2b9d43eb06a317ef48 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Tue, 21 Apr 2026 23:06:15 +0200 Subject: [PATCH 77/78] feat: made LSP work --- compiler/diagnostics/src/lib.rs | 4 ++++ compiler/lexer/src/lexer.rs | 10 +++++++--- lsp/src/bridge.rs | 12 +++++++----- lsp/src/diags.rs | 2 -- lsp/src/lsp.rs | 33 +++++++++++++++++++++++++-------- 5 files changed, 43 insertions(+), 18 deletions(-) diff --git a/compiler/diagnostics/src/lib.rs b/compiler/diagnostics/src/lib.rs index 3b3cb94b..c0428c06 100644 --- a/compiler/diagnostics/src/lib.rs +++ b/compiler/diagnostics/src/lib.rs @@ -70,6 +70,10 @@ pub fn dump_diagnostics() { }) } +pub fn clear_diagnostics() { + DIAGNOSTIC_CONTAINER.with_borrow_mut(|f| f.diagnostics.clear()) +} + pub fn has_diagnostics() -> bool { DIAGNOSTIC_CONTAINER.with_borrow(|f| return !f.diagnostics.is_empty()) } diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index 68d87254..202ba992 100644 --- a/compiler/lexer/src/lexer.rs +++ b/compiler/lexer/src/lexer.rs @@ -39,12 +39,16 @@ const USE_KEYWORD_HASH: u64 = hash!("use"); /// ``` /// let result: LexerParseResult> = lexer_parse_file("test_file.qf").expect("Lexer didn't work"); /// ``` -pub fn lexer_parse_file(file_path: &String) -> DiagnosticResult> { - let contents: String = match fs::read_to_string(file_path) { +pub fn lexer_parse_file(path: &String) -> DiagnosticResult> { + let contents: String = match fs::read_to_string(path) { Ok(v) => v, - Err(_) => panic!("Couldn't read the file {}", file_path), + Err(_) => panic!("Couldn't read the file {}", path), }; + lexer_parse(contents, path) +} + +pub fn lexer_parse(contents: String, file_path: &String) -> DiagnosticResult> { let mut tokens: Vec = Vec::new(); let mut i: usize = 0; diff --git a/lsp/src/bridge.rs b/lsp/src/bridge.rs index fd13e4b8..51ce0889 100644 --- a/lsp/src/bridge.rs +++ b/lsp/src/bridge.rs @@ -1,10 +1,12 @@ use ast_parser::parse_ast_ctx; use astoir::run_astoir_mir; -use diagnostics::{diagnostic::Diagnostic, get_diagnostics, has_diagnostics}; -use lexer::lexer::lexer_parse_file; +use diagnostics::{clear_diagnostics, diagnostic::Diagnostic, get_diagnostics, has_diagnostics}; +use lexer::lexer::lexer_parse; -pub fn check_for_file(url: String) -> Vec { - let lexer = lexer_parse_file(&url); +pub fn check_for_file(url: String, text: String) -> Vec { + clear_diagnostics(); + + let lexer = lexer_parse(text, &url); if has_diagnostics() { return get_diagnostics(); } @@ -14,7 +16,7 @@ pub fn check_for_file(url: String) -> Vec { return get_diagnostics(); } - run_astoir_mir(ast.unwrap()); + let _ = run_astoir_mir(ast.unwrap()); return get_diagnostics(); } diff --git a/lsp/src/diags.rs b/lsp/src/diags.rs index 8c0eea83..c80053e8 100644 --- a/lsp/src/diags.rs +++ b/lsp/src/diags.rs @@ -3,8 +3,6 @@ use tower_lsp::lsp_types::{ Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, Location, Position, Range, Url, }; -use crate::main; - pub fn to_tower_diag(diagnostic: diagnostics::diagnostic::Diagnostic) -> Diagnostic { let severity = match diagnostic.level { Level::Error => DiagnosticSeverity::ERROR, diff --git a/lsp/src/lsp.rs b/lsp/src/lsp.rs index 7bb5fa8b..e9fc247f 100644 --- a/lsp/src/lsp.rs +++ b/lsp/src/lsp.rs @@ -1,14 +1,14 @@ use std::{ - collections::{HashMap, HashSet}, + collections::HashSet, sync::{Arc, Mutex}, }; use tower_lsp::{ Client, LanguageServer, lsp_types::{ - CompletionOptions, DidOpenTextDocumentParams, HoverProviderCapability, InitializeParams, - InitializeResult, InitializedParams, MessageType, ServerCapabilities, ServerInfo, - TextDocumentSyncCapability, TextDocumentSyncKind, + DidChangeTextDocumentParams, DidOpenTextDocumentParams, InitializeParams, InitializeResult, + MessageType, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, + TextDocumentSyncKind, }, }; @@ -28,8 +28,8 @@ impl LanguageServer for LSPBackend { ) -> tower_lsp::jsonrpc::Result { Ok(InitializeResult { capabilities: ServerCapabilities { - hover_provider: Some(HoverProviderCapability::Simple(true)), - completion_provider: Some(CompletionOptions::default()), + hover_provider: None, + completion_provider: None, text_document_sync: Some(TextDocumentSyncCapability::Kind( TextDocumentSyncKind::FULL, )), @@ -50,14 +50,31 @@ impl LanguageServer for LSPBackend { let mut diags = vec![]; + for diag in check_for_file(uri.clone().replace("file://", ""), text.clone()) { + diags.push(to_tower_diag(diag)) + } + + self.lsp_client.log_message(MessageType::ERROR, text).await; + self.lsp_client - .log_message(MessageType::ERROR, format!("Path: {}", uri)) + .publish_diagnostics(uri.parse().unwrap(), diags, None) .await; + } - for diag in check_for_file(uri.clone().replace("file://", "")) { + async fn did_change(&self, params: DidChangeTextDocumentParams) { + let uri = params.text_document.uri.to_string(); + let text = params.content_changes[0].text.clone(); + + self.documents.lock().unwrap().insert(uri.clone()); + + let mut diags = vec![]; + + for diag in check_for_file(uri.clone().replace("file://", ""), text.clone()) { diags.push(to_tower_diag(diag)) } + self.lsp_client.log_message(MessageType::ERROR, text).await; + self.lsp_client .publish_diagnostics(uri.parse().unwrap(), diags, None) .await; From 9dadf3a93460ec7a80d8a9b27e7510ae670c88e6 Mon Sep 17 00:00:00 2001 From: Zffu <103074097+Zffu@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:27:09 +0200 Subject: [PATCH 78/78] chore: removed vulnerable rand crate usage --- Cargo.lock | 71 ---------------------------- compiler/llvm_ir_bridge/Cargo.toml | 1 - compiler/llvm_ir_bridge/src/utils.rs | 11 ----- 3 files changed, 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a1aa7f4..dec2b97b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -416,17 +416,6 @@ dependencies = [ "slab", ] -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "hashbrown" version = "0.14.5" @@ -629,7 +618,6 @@ dependencies = [ "astoir_mir", "compiler_typing", "inkwell", - "rand", ] [[package]] @@ -760,15 +748,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "prelude" version = "0.1.0" @@ -798,36 +777,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -1224,26 +1173,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zerocopy" -version = "0.8.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zerofrom" version = "0.1.7" diff --git a/compiler/llvm_ir_bridge/Cargo.toml b/compiler/llvm_ir_bridge/Cargo.toml index 01936aa1..1c97086e 100644 --- a/compiler/llvm_ir_bridge/Cargo.toml +++ b/compiler/llvm_ir_bridge/Cargo.toml @@ -9,4 +9,3 @@ inkwell = { git = "https://github.com/TheDan64/inkwell", features = [ ] } astoir_mir = { path = "../astoir_mir" } compiler_typing = { path = "../compiler_typing" } -rand = "0.8" diff --git a/compiler/llvm_ir_bridge/src/utils.rs b/compiler/llvm_ir_bridge/src/utils.rs index 1933beaa..c770cc7e 100644 --- a/compiler/llvm_ir_bridge/src/utils.rs +++ b/compiler/llvm_ir_bridge/src/utils.rs @@ -6,7 +6,6 @@ use inkwell::{ types::{BasicMetadataTypeEnum, BasicTypeEnum, IntType, PointerType}, values::{BasicValueEnum, FunctionValue}, }; -use rand::{Rng, distributions::Alphanumeric}; pub type LLVMBlock = LLVMSiblingObject>; pub type LLVMBasicValue = LLVMSiblingObject>; @@ -84,13 +83,3 @@ impl Deref for LLVMSiblingObject { return &self.inner; } } - -pub fn get_block_name() -> String { - let s = rand::thread_rng() - .sample_iter(&Alphanumeric) - .take(24) - .map(char::from) - .collect(); - - return s; -}