diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8564c7b..cab2824 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,4 +1,4 @@ -name: Rust +name: Compile (No bridges) on: pull_request: @@ -15,4 +15,4 @@ jobs: steps: - uses: actions/checkout@v4 - name: Build - run: cargo build --verbose + run: cargo build -p compiler_main diff --git a/Cargo.lock b/Cargo.lock index 4f8edcd..5009a10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,10 +56,12 @@ name = "astoir_hir_lowering" version = "0.1.0" dependencies = [ "ast", + "ast_parser", "astoir_hir", "compiler_typing", "compiler_utils", "diagnostics", + "lexer", ] [[package]] diff --git a/compiler/ast/src/ctx.rs b/compiler/ast/src/ctx.rs index 02a4d99..0b5ed02 100644 --- a/compiler/ast/src/ctx.rs +++ b/compiler/ast/src/ctx.rs @@ -5,12 +5,13 @@ use crate::tree::ASTTreeNode; #[derive(Debug)] pub struct ParserCtx { pub map: HashMap>, + pub uses: Vec>, pub iter_order: Vec } impl ParserCtx { pub fn new() -> Self { - return ParserCtx { map: HashMap::new(), iter_order: Vec::new() } + return ParserCtx { map: HashMap::new(), iter_order: Vec::new(), uses: vec![] } } pub fn insert(&mut self, name: String, node: Box) -> bool { diff --git a/compiler/ast/src/tree.rs b/compiler/ast/src/tree.rs index 0ceb502..387d1ab 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", diff --git a/compiler/ast_parser/src/lib.rs b/compiler/ast_parser/src/lib.rs index 7bddedf..6be0672 100644 --- a/compiler/ast_parser/src/lib.rs +++ b/compiler/ast_parser/src/lib.rs @@ -2,7 +2,7 @@ //! The parser for the Quickfall AST //! -use ast::ctx::ParserCtx; +use ast::{ctx::ParserCtx, tree::ASTTreeNodeKind}; use diagnostics::{DiagnosticResult, builders::make_unexpected_simple_error}; use lexer::token::{LexerToken, LexerTokenType}; @@ -19,6 +19,7 @@ pub mod variables; pub mod types; pub mod arrays; pub mod unwraps; +pub mod use_statements; pub fn parse_ast_ctx(tokens: &Vec) -> DiagnosticResult { let mut ind = 0; @@ -28,6 +29,11 @@ pub fn parse_ast_ctx(tokens: &Vec) -> DiagnosticResult { while tokens[ind].tok_type != LexerTokenType::EndOfFile { let node = parse_ast_node(tokens, &mut ind)?; + if let ASTTreeNodeKind::UseStatement { .. } = node.kind { + ctx.uses.push(node); + continue; + } + if !node.kind.is_tree_permissible() { return Err(make_unexpected_simple_error(&*node, &node).into()) } diff --git a/compiler/ast_parser/src/parser.rs b/compiler/ast_parser/src/parser.rs index 58e0028..08586a0 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,12 +38,16 @@ 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()) } } /// 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/structs/enums.rs b/compiler/ast_parser/src/structs/enums.rs index c6780bc..8aa4ab7 100644 --- a/compiler/ast_parser/src/structs/enums.rs +++ b/compiler/ast_parser/src/structs/enums.rs @@ -1,9 +1,9 @@ use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType}; use compiler_utils::hash::HashedString; -use diagnostics::{DiagnosticResult, diagnostic::Diagnostic}; +use diagnostics::{DiagnosticResult}; use lexer::token::{LexerToken, LexerTokenType}; -use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::{parse_type_generic, parse_type_parameters_declaration}}; +use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::{parse_type_parameters_declaration}}; pub fn parse_enum_entry(tokens: &Vec, ind: &mut usize) -> DiagnosticResult> { let start = tokens[*ind].pos.clone(); diff --git a/compiler/ast_parser/src/use_statements.rs b/compiler/ast_parser/src/use_statements.rs new file mode 100644 index 0000000..e8b3e3b --- /dev/null +++ b/compiler/ast_parser/src/use_statements.rs @@ -0,0 +1,44 @@ +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)?; + *ind += 1; + + 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; + } + + *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 diff --git a/compiler/astoir_hir/src/nodes.rs b/compiler/astoir_hir/src/nodes.rs index a32a7c6..3e366e1 100644 --- a/compiler/astoir_hir/src/nodes.rs +++ b/compiler/astoir_hir/src/nodes.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use compiler_typing::{enums::{RawEnumEntryContainer, RawEnumTypeContainer}, raw::RawType, references::TypeReference, storage::{BOOLEAN_TYPE, STATIC_STR}, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type}; +use compiler_typing::{enums::{RawEnumTypeContainer}, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type}; use compiler_utils::{Position, hash::SelfHash}; use diagnostics::{DiagnosticSpanOrigin, builders::{make_diff_type, make_diff_type_val}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic}; use lexer::toks::{comp::ComparingOperator, math::MathOperator}; diff --git a/compiler/astoir_hir_lowering/Cargo.toml b/compiler/astoir_hir_lowering/Cargo.toml index c3a60e4..2d35609 100644 --- a/compiler/astoir_hir_lowering/Cargo.toml +++ b/compiler/astoir_hir_lowering/Cargo.toml @@ -8,4 +8,6 @@ astoir_hir = { path = "../astoir_hir" } compiler_typing = { path = "../compiler_typing" } ast = { path = "../ast" } diagnostics = { path = "../diagnostics" } -compiler_utils = { path = "../compiler_utils" } \ No newline at end of file +compiler_utils = { path = "../compiler_utils" } +lexer = { path = "../lexer" } +ast_parser = { path = "../ast_parser" } \ No newline at end of file diff --git a/compiler/astoir_hir_lowering/src/bools.rs b/compiler/astoir_hir_lowering/src/bools.rs index b88d345..16c97e3 100644 --- a/compiler/astoir_hir_lowering/src/bools.rs +++ b/compiler/astoir_hir_lowering/src/bools.rs @@ -1,6 +1,6 @@ use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; -use compiler_typing::{raw::RawType, storage::BOOLEAN_TYPE, tree::Type}; +use compiler_typing::{raw::RawType, tree::Type}; use diagnostics::{DiagnosticResult}; use crate::values::lower_ast_value; diff --git a/compiler/astoir_hir_lowering/src/enums.rs b/compiler/astoir_hir_lowering/src/enums.rs index d3c1d21..5ee4a79 100644 --- a/compiler/astoir_hir_lowering/src/enums.rs +++ b/compiler/astoir_hir_lowering/src/enums.rs @@ -29,7 +29,7 @@ pub fn lower_ast_enum_entry(context: &mut HIRContext, node: Box, co } pub fn lower_ast_enum(context: &mut HIRContext, node: Box) -> DiagnosticResult> { - if let ASTTreeNodeKind::EnumDeclaration { name, entries, functions, type_params } = node.kind.clone() { + if let ASTTreeNodeKind::EnumDeclaration { name, entries, functions: _, type_params } = node.kind.clone() { let mut container = RawEnumTypeContainer::new(context.type_storage.types.vals.len(), type_params); for entry in entries { diff --git a/compiler/astoir_hir_lowering/src/lib.rs b/compiler/astoir_hir_lowering/src/lib.rs index b0df1df..e0deed9 100644 --- a/compiler/astoir_hir_lowering/src/lib.rs +++ b/compiler/astoir_hir_lowering/src/lib.rs @@ -2,7 +2,7 @@ use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}}; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos}; -use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, enums::lower_ast_enum, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}}; +use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, enums::lower_ast_enum, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, uses::handle_ast_use_statement, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}}; pub mod literals; pub mod var; @@ -16,6 +16,7 @@ pub mod structs; pub mod arrays; pub mod unwraps; pub mod enums; +pub mod uses; pub fn lower_ast_body_node(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box) -> DiagnosticResult> { move_current_diagnostic_pos(node.get_pos()); @@ -106,6 +107,10 @@ pub fn lower_ast_toplevel(context: &mut HIRContext, node: Box) -> D pub fn lower_ast(ctx: ParserCtx) -> DiagnosticResult { let mut hir_ctx = HIRContext::new(); + for u in ctx.uses { + handle_ast_use_statement(&mut hir_ctx, u)?; + } + for s in ctx.iter_order { let k = ctx.map[&s].clone(); diff --git a/compiler/astoir_hir_lowering/src/structs.rs b/compiler/astoir_hir_lowering/src/structs.rs index 242b078..4380d57 100644 --- a/compiler/astoir_hir_lowering/src/structs.rs +++ b/compiler/astoir_hir_lowering/src/structs.rs @@ -2,11 +2,11 @@ use std::collections::HashMap; use ast::tree::{ASTTreeNode, ASTTreeNodeKind}; use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, structs::HIRStructContainer}; -use compiler_typing::{raw::RawType, structs::RawStructTypeContainer, tree::Type}; -use compiler_utils::{hash::{HashedString, SelfHash}, utils::indexed::IndexStorage}; -use diagnostics::{DiagnosticResult, builders::{make_already_in_scope, make_cannot_find_type, make_struct_init_missing_field, make_struct_missing_field}}; +use compiler_typing::{raw::RawType, structs::RawStructTypeContainer}; +use compiler_utils::utils::indexed::IndexStorage; +use diagnostics::{DiagnosticResult, builders::make_already_in_scope}; -use crate::{lower_ast_body, types::{lower_ast_type, lower_ast_type_struct}, values::lower_ast_value}; +use crate::{lower_ast_body, types::lower_ast_type_struct, values::lower_ast_value}; fn lower_ast_struct_member(context: &mut HIRContext, node: Box, container: &mut RawStructTypeContainer) -> DiagnosticResult { if let ASTTreeNodeKind::StructFieldMember { name, member_type } = node.kind.clone() { diff --git a/compiler/astoir_hir_lowering/src/types.rs b/compiler/astoir_hir_lowering/src/types.rs index ad9c149..4a807f7 100644 --- a/compiler/astoir_hir_lowering/src/types.rs +++ b/compiler/astoir_hir_lowering/src/types.rs @@ -1,6 +1,6 @@ use ast::types::ASTType; use astoir_hir::ctx::HIRContext; -use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, tree::Type}; +use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, tree::Type}; use compiler_utils::hash::HashedString; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_type, make_diff_size_specifiers, make_diff_type_specifiers, make_req_type_kind}}; diff --git a/compiler/astoir_hir_lowering/src/uses.rs b/compiler/astoir_hir_lowering/src/uses.rs new file mode 100644 index 0000000..5dd1652 --- /dev/null +++ b/compiler/astoir_hir_lowering/src/uses.rs @@ -0,0 +1,154 @@ +use std::path::{MAIN_SEPARATOR_STR}; + +use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType}; +use ast_parser::parse_ast_ctx; +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 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") +} + +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 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/src/builder.rs b/compiler/astoir_mir/src/builder.rs index 297fddf..188073f 100644 --- a/compiler/astoir_mir/src/builder.rs +++ b/compiler/astoir_mir/src/builder.rs @@ -1,7 +1,7 @@ //! Utility functions to build instructions and more use compiler_typing::{SizedType, raw::RawType, storage::TypeStorage, tree::Type}; -use diagnostics::{DiagnosticResult, MaybeDiagnostic, diagnostic::Diagnostic, unsure_panic}; +use diagnostics::{DiagnosticResult, MaybeDiagnostic, unsure_panic}; use crate::{blocks::{hints::MIRValueHint, refer::MIRBlockReference}, ctx::MIRContext, insts::MIRInstruction, vals::{arrays::MIRArrayValue, base::BaseMIRValue, float::MIRFloatValue, int::MIRIntValue, ptr::MIRPointerValue, structs::MIRStructValue}}; diff --git a/compiler/astoir_mir_lowering/src/casts.rs b/compiler/astoir_mir_lowering/src/casts.rs index a2a2136..385b237 100644 --- a/compiler/astoir_mir_lowering/src/casts.rs +++ b/compiler/astoir_mir_lowering/src/casts.rs @@ -5,7 +5,7 @@ use diagnostics::DiagnosticResult; use crate::{MIRLoweringContext, lower_hir_type, values::lower_hir_value}; pub fn lower_cast(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::CastValue { intentional, value, old_type, new_type } = node.kind.clone() { + if let HIRNodeKind::CastValue { intentional: _, value, old_type, new_type } = node.kind.clone() { let value = lower_hir_value(block, value, ctx)?; let old_type = lower_hir_type(ctx, old_type)?; diff --git a/compiler/astoir_mir_lowering/src/introductions.rs b/compiler/astoir_mir_lowering/src/introductions.rs index 756a0ee..9e54e53 100644 --- a/compiler/astoir_mir_lowering/src/introductions.rs +++ b/compiler/astoir_mir_lowering/src/introductions.rs @@ -13,7 +13,7 @@ pub fn handle_var_introduction_queue(block: MIRBlockReference, node: Box(block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { +pub fn is_enum_value_of_kind(_block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { let enum_type = match ctx.mir_ctx.ssa_hints.get_hint(val.get_ssa_index()).get_type().as_generic_lowered_safe(origin)? { RawType::Enum(v) => v, RawType::LoweredStruct(_, container) => { @@ -48,7 +46,7 @@ pub fn is_enum_value_of_kind(block: MIRBlockReference, return build_comp_eq(&mut ctx.mir_ctx, hint_val, hint_true); } -pub fn cast_to_enum_child(block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { +pub fn cast_to_enum_child(_block: MIRBlockReference, val: BaseMIRValue, enum_entry: RawType, ctx: &mut MIRLoweringContext, origin: &K) -> DiagnosticResult { let enum_type = match ctx.mir_ctx.ssa_hints.get_hint(val.get_ssa_index()).get_type().as_generic_lowered_safe(origin)? { RawType::Enum(v) => v, RawType::LoweredStruct(_, container) => { @@ -107,7 +105,7 @@ pub fn lower_hir_unwrap_cond(block: MIRBlockReference, node: Box, ctx: } pub fn lower_hir_unwrap_value(block: MIRBlockReference, node: Box, ctx: &mut MIRLoweringContext) -> DiagnosticResult { - if let HIRNodeKind::UnwrapValue { original, new_type, unsafe_unwrap } = node.kind.clone() { + if let HIRNodeKind::UnwrapValue { original, new_type, unsafe_unwrap: _ } = node.kind.clone() { let original = lower_hir_value(block, original, ctx)?; let new_type = lower_hir_type(ctx, new_type)?; diff --git a/compiler/astoir_mir_lowering/src/vars.rs b/compiler/astoir_mir_lowering/src/vars.rs index fc6ab3f..391ffb2 100644 --- a/compiler/astoir_mir_lowering/src/vars.rs +++ b/compiler/astoir_mir_lowering/src/vars.rs @@ -10,6 +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]; + let local_ctx = ctx.hir_ctx.function_contexts[func].as_ref().unwrap(); if local_ctx.is_eligible_for_ssa(variable) { diff --git a/compiler/compiler_main/Cargo.toml b/compiler/compiler_main/Cargo.toml index 09a0f99..c2a0b92 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, default-features = false} diagnostics = { path = "../diagnostics" } -compiler_utils = { path = "../compiler_utils"} \ No newline at end of file +compiler_utils = { path = "../compiler_utils" } + +[features] +llvm = ["llvm_ir_bridge"] \ No newline at end of file diff --git a/compiler/compiler_main/src/cmds/astoir.rs b/compiler/compiler_main/src/cmds/astoir.rs index 697e989..130dca8 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) { @@ -39,20 +43,28 @@ 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 => { - 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(); + + let _ = ctx.module.print_to_file(res_path); + } + + #[cfg(not(feature = "llvm_ir_bridge"))] { + println!("LLVM target is not bundled!"); + + exit(0); + } } } } @@ -67,7 +79,7 @@ fn parse_astoir_level(str: &String) -> DiagnosticResult { _ => { println!("Invalid level"); - std::process::exit(0); + exit(0); } }; diff --git a/compiler/compiler_typing/src/bounds/traits.rs b/compiler/compiler_typing/src/bounds/traits.rs index 31806c8..b24b48a 100644 --- a/compiler/compiler_typing/src/bounds/traits.rs +++ b/compiler/compiler_typing/src/bounds/traits.rs @@ -24,7 +24,7 @@ use std::fmt::Display; use compiler_utils::hash; use diagnostics::{MaybeDiagnostic, builders::make_bound_trait}; -use crate::{storage::TypeStorage, tree::Type}; +use crate::{tree::Type}; pub const TRAIT_NUMERIC: u64 = hash!("numeric"); pub const TRAIT_SIGNED: u64 = hash!("signed"); @@ -81,17 +81,17 @@ pub struct TraitBound { } impl TraitBound { - pub fn check(&self, t: &Type, storage: &TypeStorage) -> MaybeDiagnostic { + pub fn check(&self, t: &Type) -> MaybeDiagnostic { for member in &self.members { match member { TraitBoundMember::Select(tt) => { - if !t.as_generic(storage).has_trait(tt.clone(), t) { + if !t.as_generic().has_trait(tt.clone(), t) { return Err(make_bound_trait(tt, t).into()) } }, TraitBoundMember::Exclude(tt) => { - if t.as_generic(storage).has_trait(tt.clone(), t) { + if t.as_generic().has_trait(tt.clone(), t) { return Err(make_bound_trait(&format!("~{}", tt), t).into()) } } diff --git a/compiler/compiler_typing/src/enums.rs b/compiler/compiler_typing/src/enums.rs index a60590b..efa4874 100644 --- a/compiler/compiler_typing/src/enums.rs +++ b/compiler/compiler_typing/src/enums.rs @@ -1,6 +1,6 @@ //! Declarations for enum-kind types. -use std::{collections::HashMap, f32::consts::E}; +use std::{collections::HashMap}; use compiler_utils::{hash::{HashedString}, utils::indexed::IndexStorage}; use diagnostics::{DiagnosticResult, builders::{make_cannot_find_type_field, make_cannot_find_type_function, make_cannot_find_type_pos, make_enum_parent_fields}}; diff --git a/compiler/compiler_typing/src/tree.rs b/compiler/compiler_typing/src/tree.rs index 3f32eba..67e306d 100644 --- a/compiler/compiler_typing/src/tree.rs +++ b/compiler/compiler_typing/src/tree.rs @@ -4,7 +4,7 @@ use std::fmt::Display; use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::make_req_type_kind, unsure_panic}; -use crate::{RawTypeReference, SizedType, StructuredType, TypedFunction, raw::RawType, references::TypeReference, storage::{TypeStorage}, utils::get_pointer_size}; +use crate::{SizedType, StructuredType, TypedFunction, raw::RawType, references::TypeReference, storage::{TypeStorage}, utils::get_pointer_size}; #[derive(Clone, PartialEq, Debug, Eq, Hash)] /// The node-based typing system of Quickfall. Allows for very specific types. @@ -133,7 +133,7 @@ impl Type { } } - pub fn as_generic(&self, storage: &TypeStorage) -> RawType { + pub fn as_generic(&self) -> RawType { match self { Self::GenericLowered(a) => return a.clone(), Self::Generic(a, _, _) => { diff --git a/compiler/diagnostics/src/builders.rs b/compiler/diagnostics/src/builders.rs index 7333a0c..36edf54 100644 --- a/compiler/diagnostics/src/builders.rs +++ b/compiler/diagnostics/src/builders.rs @@ -1,6 +1,6 @@ use std::{fmt::Display}; -use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; +use crate::{DiagnosticSpanOrigin, diagnostic::{Diagnostic, Level, Span, SpanKind, SpanPosition}, errors::{ALREADY_IN_SCOPE, ASSIGN_DIFF_TYPE_IR, BOUND_MISSING, DIFF_SIZE_SPECIFIERS, DIFF_TYPE_SPECIFIERS, ENUM_PARENT_FIELDS, ERA_NOT_EXIST, EXPECTED_FREE, EXPECTED_TOKEN, EXPECTED_TYPE, FIELD_MISSING, FIELD_STRUCT_INIT, FIND_TYPE, FIND_TYPE_FIELD, FIND_TYPE_FUNCTION, FIND_VAR, FUNC_MISSING, INDEX_USAGE, INVALID_POINTING, INVALID_TYPE_REQ, IR_CAST, IR_INSTRUCTION_HELD_VAL, MATH_OPERATION_ASSIGNS, NOT_FOUND_USE, TRAIT_MISSING, TYPE_NOT_PART, UNEXPECTED_TOKEN, VARIABLE_UNINIT}, get_current_diagnostic_pos, warnings::UNUSED_VAR}; pub fn make_expected_simple_error(origin: &K, expected: &E, got: &G) -> Diagnostic { origin.make_simple_diagnostic(EXPECTED_TOKEN.0, Level::Error, format!("expected {} but got {}", expected, got), None, vec![], vec![], vec![]) @@ -184,4 +184,8 @@ pub fn make_req_type_kind(origin: &K, t: &T pub fn make_type_not_partof(origin: &K, a: &A, b: &B) -> Diagnostic { origin.make_simple_diagnostic(TYPE_NOT_PART.0, Level::Error, format!("type {} is not part of type {}", a, b), None, vec![], vec![], vec![]) +} + +pub fn make_use_not_found(origin: &K, element: &E, path: &P) -> Diagnostic { + origin.make_simple_diagnostic(NOT_FOUND_USE.0, Level::Error, format!("element {} was not found in {}", element, path), None, vec![], vec![], vec![]) } \ No newline at end of file diff --git a/compiler/diagnostics/src/diagnostic.rs b/compiler/diagnostics/src/diagnostic.rs index a354fe4..301255b 100644 --- a/compiler/diagnostics/src/diagnostic.rs +++ b/compiler/diagnostics/src/diagnostic.rs @@ -86,11 +86,13 @@ impl Diagnostic { } } - pub fn maybe_display_backtrace(&self, fmt: &mut std::fmt::Formatter<'_>) { + pub fn maybe_display_backtrace(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if cfg!(debug_assertions) { - writeln!(fmt, "Internally captured in:"); - writeln!(fmt, "{}", self.backtrace.as_ref().unwrap()); + writeln!(fmt, "Internally captured in:")?; + writeln!(fmt, "{}", self.backtrace.as_ref().unwrap())?; } + + Ok(()) } pub fn new(level: Level, decl: (usize, &str), primary_span: Span, spans: Vec, note: Vec, help: Vec) -> Self { @@ -247,7 +249,7 @@ impl Display for Diagnostic { ind += 1; } - self.maybe_display_backtrace(f); + self.maybe_display_backtrace(f)?; Ok(()) } diff --git a/compiler/diagnostics/src/errors.rs b/compiler/diagnostics/src/errors.rs index ac2c27d..d337b1d 100644 --- a/compiler/diagnostics/src/errors.rs +++ b/compiler/diagnostics/src/errors.rs @@ -40,4 +40,5 @@ declare_error!(IR_INSTRUCTION_HELD_VAL, 29, "cannot extract held value from inst // Misc declare_error!(INVALID_TYPE_REQ, 30, "this operation requires a {} type"); -declare_error!(TYPE_NOT_PART, 31, "type {} is not part of type {}"); \ No newline at end of file +declare_error!(TYPE_NOT_PART, 31, "type {} is not part of type {}"); +declare_error!(NOT_FOUND_USE, 32, "element {} was not found in {}"); \ No newline at end of file diff --git a/compiler/diagnostics/src/lib.rs b/compiler/diagnostics/src/lib.rs index ff8f8c7..88b5521 100644 --- a/compiler/diagnostics/src/lib.rs +++ b/compiler/diagnostics/src/lib.rs @@ -24,7 +24,7 @@ thread_local! { #[macro_export] macro_rules! unsure_panic { ($msg: expr) => { { - diagnostics::builders::make_unsure_panic(&$msg.to_string()); + _ = diagnostics::builders::make_unsure_panic(&$msg.to_string()); diagnostics::dump_diagnostics(); panic!($msg); } diff --git a/compiler/lexer/src/lexer.rs b/compiler/lexer/src/lexer.rs index c13537d..8c6d965 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. /// @@ -207,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) { @@ -375,6 +376,7 @@ fn parse_keyword(str: &String, ind: &mut usize, start_pos: Position) -> LexerTok UNWRAP_KEYWORD_HASH => LexerTokenType::Unwrap, UNWRAP_UNSAFE_KEYWORD_HASH => LexerTokenType::UnwrapUnsafe, ENUM_KEYWORD_HASH => LexerTokenType::Enum, + USE_KEYWORD_HASH => LexerTokenType::Use, _ => LexerTokenType::Keyword(slice.to_string(), hash) }; diff --git a/compiler/lexer/src/token.rs b/compiler/lexer/src/token.rs index c3a1a35..f700669 100644 --- a/compiler/lexer/src/token.rs +++ b/compiler/lexer/src/token.rs @@ -22,6 +22,8 @@ pub enum LexerTokenType { Unwrap, UnwrapUnsafe, + Use, + Var, Struct, Layout, @@ -226,6 +228,7 @@ impl Display for LexerTokenType { Self::True => "true", Self::While => "while", Self::Unwrap => "unwrap", + Self::Use => "use", Self::UnwrapUnsafe => "unsafe_unwrap" }; diff --git a/compiler/llvm_ir_bridge/src/lib.rs b/compiler/llvm_ir_bridge/src/lib.rs index ff69e9e..6d59925 100644 --- a/compiler/llvm_ir_bridge/src/lib.rs +++ b/compiler/llvm_ir_bridge/src/lib.rs @@ -30,7 +30,7 @@ macro_rules! llvm_to_base { ($exp:expr) => { match $exp { Ok(v) => v, - Err(e) => panic!("inkwell function failed") + Err(_) => panic!("inkwell function failed") } }; } @@ -40,7 +40,7 @@ macro_rules! llvm_to_base_returnless { ($exp:expr) => { match $exp { Ok(_) => {}, - Err(e) => panic!("inkwell function failed") + Err(_) => panic!("inkwell function failed") } }; } \ No newline at end of file