Skip to content

Commit 6d26c05

Browse files
authored
Merge pull request #82 from Quickfall/feat/enum-decls
Feat/enum decls
2 parents e2eecf7 + dcbaee9 commit 6d26c05

17 files changed

Lines changed: 218 additions & 20 deletions

File tree

compiler/ast/src/tree.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub enum ASTTreeNodeKind {
5151
ArrayIndexAccess { val: Box<ASTTreeNode>, index: Box<ASTTreeNode> },
5252
ArrayIndexModifiy { array: Box<ASTTreeNode>, index: Box<ASTTreeNode>, val: Box<ASTTreeNode> },
5353

54+
EnumDeclaration { name: HashedString, entries: Vec<Box<ASTTreeNode>>, functions: Vec<Box<ASTTreeNode>>, type_params: TypeParameterContainer },
55+
EnumEntryDeclaration { name: HashedString, fields: Vec<Box<ASTTreeNode>> },
56+
5457
StructLayoutDeclaration { name: HashedString, layout: bool, members: Vec<Box<ASTTreeNode>>, type_params: TypeParameterContainer },
5558
StructFieldMember { name: HashedString, member_type: ASTType },
5659

@@ -88,7 +91,7 @@ impl ASTTreeNodeKind {
8891
}
8992

9093
pub fn is_tree_permissible(&self) -> bool {
91-
return matches!(self, ASTTreeNodeKind::FunctionDeclaration { .. } | ASTTreeNodeKind::StaticVariableDeclaration { .. } | ASTTreeNodeKind::ShadowFunctionDeclaration { .. }| ASTTreeNodeKind::StructLayoutDeclaration { .. })
94+
return matches!(self, ASTTreeNodeKind::FunctionDeclaration { .. } | ASTTreeNodeKind::EnumDeclaration { .. } | ASTTreeNodeKind::StaticVariableDeclaration { .. } | ASTTreeNodeKind::ShadowFunctionDeclaration { .. }| ASTTreeNodeKind::StructLayoutDeclaration { .. })
9295
}
9396

9497
pub fn get_tree_name(&self) -> Option<HashedString> {
@@ -113,6 +116,10 @@ impl ASTTreeNodeKind {
113116
return Some(HashedString::new(var_name.val.to_string()));
114117
},
115118

119+
ASTTreeNodeKind::EnumDeclaration { name, entries: _, functions: _, type_params: _ } => {
120+
return Some(name.clone())
121+
}
122+
116123
_ => return None
117124
}
118125
}
@@ -188,7 +195,9 @@ impl Display for ASTTreeNodeKind {
188195
Self::StructLRFunction { .. } => "struct LRU function usage",
189196
Self::StructLRVariable { .. } => "struct LRU variable usage",
190197
Self::StructLayoutDeclaration { .. } => "struct / layout declaration",
191-
Self::StructFieldMember { .. } => "struct field"
198+
Self::StructFieldMember { .. } => "struct field",
199+
Self::EnumDeclaration { .. } => "enum declaration",
200+
Self::EnumEntryDeclaration { .. } => "enum entry declaration",
192201
};
193202

194203
write!(f, "{}", s)?;

compiler/ast_parser/src/parser.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use compiler_utils::hash::HashedString;
33
use diagnostics::{DiagnosticResult, builders::{make_unexpected_simple_error, make_unused_variable}};
44
use lexer::token::{LexerToken, LexerTokenType};
55

6-
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::parse_type_declaration, value::parse_ast_value_post_l, variables::{decl::parse_variable_declaration, static_decl::parse_static_variable_declaration}};
6+
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}};
77

88
/// Parses an AST node outside of any other node.
99
///
@@ -34,6 +34,10 @@ pub fn parse_ast_node(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticRe
3434
return parse_type_declaration(tokens, ind, true);
3535
},
3636

37+
LexerTokenType::Enum => {
38+
return parse_enum_declaration(tokens, ind);
39+
},
40+
3741
_ => return Err(make_unexpected_simple_error(&tokens[*ind], &tokens[*ind].tok_type).into())
3842
}
3943
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use ast::{tree::{ASTTreeNode, ASTTreeNodeKind}, types::ASTType};
2+
use compiler_utils::hash::HashedString;
3+
use diagnostics::{DiagnosticResult, diagnostic::Diagnostic};
4+
use lexer::token::{LexerToken, LexerTokenType};
5+
6+
use crate::{functions::parse_function_declaraction, structs::members::parse_types_field_member, types::{parse_type_generic, parse_type_parameters_declaration}};
7+
8+
pub fn parse_enum_entry(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticResult<Box<ASTTreeNode>> {
9+
let start = tokens[*ind].pos.clone();
10+
11+
let name = tokens[*ind].expects_keyword()?;
12+
*ind += 1;
13+
14+
let mut fields = vec![];
15+
16+
tokens[*ind].expects(LexerTokenType::ParenOpen)?;
17+
*ind += 1;
18+
19+
loop {
20+
fields.push(parse_types_field_member(tokens, ind)?);
21+
22+
if tokens[*ind].tok_type == LexerTokenType::ParenClose {
23+
break;
24+
}
25+
26+
tokens[*ind].expects(LexerTokenType::Comma)?;
27+
}
28+
29+
*ind += 1;
30+
31+
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::EnumEntryDeclaration { name: HashedString::new(name.0), fields }, start, tokens[*ind].get_end_pos())))
32+
}
33+
34+
pub fn parse_enum_declaration(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticResult<Box<ASTTreeNode>> {
35+
let start = tokens[*ind].pos.clone();
36+
37+
*ind += 1;
38+
39+
let name = tokens[*ind].expects_keyword()?;
40+
*ind += 1;
41+
42+
let t = parse_type_parameters_declaration(tokens, ind)?;
43+
44+
tokens[*ind].expects(LexerTokenType::BracketOpen)?;
45+
*ind += 1;
46+
47+
let mut entries = vec![];
48+
let mut functions = vec![];
49+
50+
let temp_type = ASTType::Generic(name.0.clone(), vec![], vec![], None);
51+
52+
loop {
53+
if tokens[*ind].is_keyword() {
54+
entries.push(parse_enum_entry(tokens, ind)?);
55+
} else {
56+
tokens[*ind].expects(LexerTokenType::Function)?;
57+
58+
functions.push(parse_function_declaraction(tokens, ind, Some(temp_type.clone()))?)
59+
}
60+
61+
if tokens[*ind].tok_type == LexerTokenType::BracketClose {
62+
break;
63+
}
64+
}
65+
*ind += 1;
66+
67+
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::EnumDeclaration { name: HashedString::new(name.0), entries, functions, type_params: t }, start, tokens[*ind].get_end_pos())))
68+
}

compiler/ast_parser/src/structs/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{functions::parse_function_declaraction, structs::members::parse_type
88

99
pub mod members;
1010
pub mod val;
11+
pub mod enums;
1112

1213
pub fn parse_type_declaration(tokens: &Vec<LexerToken>, ind: &mut usize, layout: bool) -> DiagnosticResult<Box<ASTTreeNode>> {
1314
let start = tokens[*ind].pos.clone();

compiler/ast_parser/src/types.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,15 @@ pub fn parse_type_parameters_declaration(tokens: &Vec<LexerToken>, ind: &mut usi
206206

207207
*ind += 1;
208208

209-
if tokens[*ind].tok_type == LexerTokenType::AngelBracketClose {
209+
if tokens[*ind].is_angel_bracket_close() {
210210
break;
211211
}
212212

213213
tokens[*ind].expects(LexerTokenType::Comma)?;
214214
*ind += 1;
215215
}
216216

217+
*ind += 1;
218+
217219
return Ok(container);
218220
}

compiler/astoir/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,7 @@ pub fn run_astoir_hir(ctx: ParserCtx) -> DiagnosticResult<HIRContext> {
1616
}
1717

1818
pub fn run_astoir_mir(ctx: ParserCtx) -> DiagnosticResult<MIRContext> {
19-
return lower_hir(run_astoir_hir(ctx)?);
19+
let hir = run_astoir_hir(ctx)?;
20+
21+
return lower_hir(hir);
2022
}

compiler/astoir_hir/src/nodes.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::collections::HashMap;
44

5-
use compiler_typing::{raw::RawType, references::TypeReference, storage::{BOOLEAN_TYPE, STATIC_STR}, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type};
5+
use compiler_typing::{enums::{RawEnumEntryContainer, RawEnumTypeContainer}, raw::RawType, references::TypeReference, storage::{BOOLEAN_TYPE, STATIC_STR}, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type};
66
use compiler_utils::{Position, hash::SelfHash};
77
use diagnostics::{DiagnosticSpanOrigin, builders::{make_diff_type, make_diff_type_val}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic};
88
use lexer::toks::{comp::ComparingOperator, math::MathOperator};
@@ -66,6 +66,8 @@ pub enum HIRNodeKind {
6666

6767
EnumParentCast { val: Box<HIRNode>, parent: Type },
6868

69+
EnumDeclaration { type_name: usize, container: RawEnumTypeContainer },
70+
6971
StructDeclaration { type_name: usize, container: RawStructTypeContainer, layout: bool },
7072
StructFunctionDeclaration { func_name: usize, arguments: Vec<(u64, TypeReference)>, return_type: Option<TypeReference>, body: Vec<Box<HIRNode>>, ctx: HIRBranchedContext, requires_this: bool },
7173

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use ast::tree::{ASTTreeNode, ASTTreeNodeKind};
2+
use astoir_hir::{ctx::HIRContext, nodes::{HIRNode, HIRNodeKind}};
3+
use compiler_typing::{enums::{RawEnumTypeContainer}, raw::RawType};
4+
use diagnostics::{DiagnosticResult, MaybeDiagnostic, builders::make_already_in_scope};
5+
6+
use crate::types::{lower_ast_type_struct};
7+
8+
pub fn lower_ast_enum_entry(context: &mut HIRContext, node: Box<ASTTreeNode>, container: &mut RawEnumTypeContainer) -> MaybeDiagnostic {
9+
if let ASTTreeNodeKind::EnumEntryDeclaration { name, fields } = node.kind.clone() {
10+
let mut hir_fields = vec![];
11+
12+
for f in fields {
13+
if let ASTTreeNodeKind::StructFieldMember { name, member_type } = f.kind {
14+
let t = lower_ast_type_struct(context, member_type, container, &*node)?;
15+
16+
hir_fields.push((name.hash, t));
17+
continue;
18+
}
19+
20+
panic!("Invalid field node type!");
21+
}
22+
23+
container.append_entry(name, hir_fields);
24+
return Ok(())
25+
}
26+
27+
28+
panic!("Invalid node")
29+
}
30+
31+
pub fn lower_ast_enum(context: &mut HIRContext, node: Box<ASTTreeNode>) -> DiagnosticResult<Box<HIRNode>> {
32+
if let ASTTreeNodeKind::EnumDeclaration { name, entries, functions, type_params } = node.kind.clone() {
33+
let mut container = RawEnumTypeContainer::new(context.type_storage.types.vals.len(), type_params);
34+
35+
for entry in entries {
36+
lower_ast_enum_entry(context, entry, &mut container)?;
37+
}
38+
39+
let ind = match context.type_storage.append_with_hash(name.hash, RawType::Enum(container.clone())) {
40+
Ok(v) => v,
41+
Err(_) => return Err(make_already_in_scope(&*node, &name.val).into())
42+
};
43+
44+
return Ok(Box::new(HIRNode::new(HIRNodeKind::EnumDeclaration { type_name: ind, container }, &node.start, &node.end)))
45+
}
46+
47+
panic!("Invalid node")
48+
}

compiler/astoir_hir_lowering/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use ast::{ctx::ParserCtx, tree::{ASTTreeNode, ASTTreeNodeKind}};
22
use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}};
33
use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, move_current_diagnostic_pos};
44

5-
use crate::{arrays::lower_ast_array_modify, control::{lower_ast_for_block, lower_ast_if_statement, lower_ast_while_block}, func::{lower_ast_function_call, lower_ast_function_declaration, lower_ast_shadow_function_declaration}, math::lower_ast_math_operation, structs::lower_ast_struct_declaration, values::lower_ast_value, var::{lower_ast_variable_assign, lower_ast_variable_declaration}};
5+
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}};
66

77
pub mod literals;
88
pub mod var;
@@ -15,6 +15,7 @@ pub mod control;
1515
pub mod structs;
1616
pub mod arrays;
1717
pub mod unwraps;
18+
pub mod enums;
1819

1920
pub fn lower_ast_body_node(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box<ASTTreeNode>) -> DiagnosticResult<Box<HIRNode>> {
2021
move_current_diagnostic_pos(node.get_pos());
@@ -92,6 +93,12 @@ pub fn lower_ast_toplevel(context: &mut HIRContext, node: Box<ASTTreeNode>) -> D
9293
return Ok(true)
9394
},
9495

96+
ASTTreeNodeKind::EnumDeclaration { .. } => {
97+
lower_ast_enum(context, node)?;
98+
99+
return Ok(true)
100+
}
101+
95102
_ => panic!("Invalid node type")
96103
}
97104
}

compiler/astoir_hir_lowering/src/types.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use ast::types::ASTType;
22
use astoir_hir::ctx::HIRContext;
3-
use compiler_typing::{raw::RawType, references::TypeReference, structs::RawStructTypeContainer, tree::Type};
3+
use compiler_typing::{TypeParamType, raw::RawType, references::TypeReference, structs::RawStructTypeContainer, tree::Type};
44
use compiler_utils::hash::HashedString;
5-
use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_type, make_diff_size_specifiers, make_req_type_kind}};
5+
use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_cannot_find_type, make_diff_size_specifiers, make_diff_type_specifiers, make_req_type_kind}};
66

77
pub fn lower_ast_type<K: DiagnosticSpanOrigin>(context: &mut HIRContext, t: ASTType, origin: &K) -> DiagnosticResult<Type> {
88
return match t {
@@ -24,7 +24,7 @@ pub fn lower_ast_type<K: DiagnosticSpanOrigin>(context: &mut HIRContext, t: ASTT
2424
}
2525

2626
if t.get_type_params_count(&context.type_storage) != type_params.len() {
27-
return Err(make_diff_size_specifiers(origin, &type_params.len(), &t.get_type_params_count(&context.type_storage)).into())
27+
return Err(make_diff_type_specifiers(origin, &type_params.len(), &t.get_type_params_count(&context.type_storage)).into())
2828
}
2929

3030
let mut t_params = vec![];
@@ -59,12 +59,12 @@ pub fn lower_ast_type<K: DiagnosticSpanOrigin>(context: &mut HIRContext, t: ASTT
5959
};
6060
}
6161

62-
pub fn lower_ast_type_struct<K: DiagnosticSpanOrigin>(context: &mut HIRContext, t: ASTType, struct_container: &RawStructTypeContainer, origin: &K) -> DiagnosticResult<TypeReference> {
62+
pub fn lower_ast_type_struct<K: DiagnosticSpanOrigin, T: TypeParamType>(context: &mut HIRContext, t: ASTType, container: &T, origin: &K) -> DiagnosticResult<TypeReference> {
6363
if let ASTType::Generic(id, _, _, _) = &t {
6464
let key = HashedString::new(id.clone());
6565

66-
if struct_container.type_params.contains_key(&key) {
67-
return Ok(TypeReference::Unresolved(struct_container.type_params[&key]));
66+
if container.has_type_param(&key) {
67+
return Ok(TypeReference::Unresolved(container.get_type_param_ind(&key)));
6868
}
6969
}
7070

0 commit comments

Comments
 (0)