Skip to content

Commit 27ae91c

Browse files
authored
Merge pull request #77 from Quickfall/feat/uniform-struct-decls
[feat] Uniform struct declarations
2 parents 2764dbf + b277564 commit 27ae91c

32 files changed

Lines changed: 431 additions & 125 deletions

File tree

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@ target/
22
*.ll
33

44
out
5-
out.*
5+
out.*
6+
7+
*.qf
8+
*.qfmir
9+
10+
!examples/**.qf

compiler/ast/src/tree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub enum ASTTreeNodeKind {
4444
PointerGrab(Box<ASTTreeNode>),
4545
ReferenceGrab(Box<ASTTreeNode>),
4646

47-
StructVariableInitializerValue { struct_type: ASTType, map: HashMap<SelfHash, Box<ASTTreeNode>> },
47+
StructInitializer { map: HashMap<SelfHash, Box<ASTTreeNode>> },
4848
ArrayVariableInitializerValueSameValue { size: usize, v: Box<ASTTreeNode> },
4949
ArrayVariableInitializerValue { vals: Vec<Box<ASTTreeNode>> },
5050

@@ -169,7 +169,7 @@ impl Display for ASTTreeNodeKind {
169169
Self::VariableReference(_) => "variable reference",
170170
Self::PointerGrab(_) => "pointer grabbing",
171171
Self::ReferenceGrab(_) => "reference",
172-
Self::StructVariableInitializerValue { .. } => "struct value initializer",
172+
Self::StructInitializer { .. } => "struct value initializer",
173173
Self::ArrayVariableInitializerValue { .. } | Self::ArrayVariableInitializerValueSameValue { .. } => "array value initializer",
174174
Self::ArrayIndexAccess { .. } | Self::ArrayIndexModifiy { .. } => "index access",
175175
Self::VarDeclaration { .. } => "variable declaration",

compiler/ast_parser/src/structs/val.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,9 @@ use compiler_utils::hash::{HashedString, SelfHash};
55
use diagnostics::DiagnosticResult;
66
use lexer::token::{LexerToken, LexerTokenType};
77

8-
use crate::{types::parse_type, value::parse_ast_value};
8+
use crate::{value::parse_ast_value};
99

1010
pub fn parse_struct_initialize(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticResult<Box<ASTTreeNode>> {
11-
*ind += 1;
12-
13-
let t = parse_type(tokens, ind)?;
14-
15-
tokens[*ind].expects(LexerTokenType::BracketOpen)?;
16-
1711
let start = tokens[*ind].pos.clone();
1812

1913
*ind += 1;
@@ -24,8 +18,13 @@ pub fn parse_struct_initialize(tokens: &Vec<LexerToken>, ind: &mut usize) -> Dia
2418
let field_name = tokens[*ind].expects_keyword()?;
2519
*ind += 1;
2620

21+
tokens[*ind].expects(LexerTokenType::Collon)?;
22+
*ind += 1;
23+
24+
2725
let value = parse_ast_value(tokens, ind)?;
2826

27+
2928
map.insert(SelfHash { hash: HashedString::new(field_name.0).hash }, value);
3029

3130
//*ind += 1;
@@ -40,5 +39,5 @@ pub fn parse_struct_initialize(tokens: &Vec<LexerToken>, ind: &mut usize) -> Dia
4039

4140
*ind += 1;
4241

43-
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructVariableInitializerValue { struct_type: t, map }, start, tokens[*ind].get_end_pos())))
42+
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::StructInitializer { map }, start, tokens[*ind].get_end_pos())))
4443
}

compiler/ast_parser/src/types.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,6 @@ pub fn parse_type_generic(tokens: &Vec<LexerToken>, ind: &mut usize) -> Diagnost
7979
specifier = None;
8080
}
8181

82-
println!("{:#?}", specifier.clone());
83-
8482
let sizes = parse_type_size_specifiers(tokens, ind)?;
8583
let types = parse_type_type_parameters(tokens, ind)?;
8684

compiler/ast_parser/src/value.rs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ pub fn parse_ast_value(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticR
177177
return Err(make_expected_simple_error(&tokens[*ind], &"function call or variable access".to_string(),&ast).into());
178178
},
179179

180-
LexerTokenType::BracketOpen | LexerTokenType::ArrayOpen => {
180+
LexerTokenType::ArrayOpen => {
181181
return parse_ast_array_init(tokens, ind);
182182
}
183183

@@ -194,7 +194,7 @@ pub fn parse_ast_value(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticR
194194
return parse_ast_value_post_l(tokens, ind, str, false);
195195
},
196196

197-
LexerTokenType::New => {
197+
LexerTokenType::BracketOpen => {
198198
return parse_struct_initialize(tokens, ind);
199199
}
200200

@@ -221,46 +221,36 @@ pub fn parse_ast_value(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticR
221221

222222
pub fn parse_ast_array_init(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticResult<Box<ASTTreeNode>> {
223223
let start = tokens[*ind].pos.clone();
224+
*ind += 1;
224225

225-
if tokens[*ind].tok_type == LexerTokenType::BracketOpen {
226-
*ind += 1;
227-
228-
let int_lit = tokens[*ind].expects_int_lit()?;
229-
230-
*ind += 1;
231-
232-
tokens[*ind].expects(LexerTokenType::Dot)?;
233-
234-
*ind += 1;
235-
226+
if tokens[*ind + 1].tok_type == LexerTokenType::Comma {
236227
let val = parse_ast_value(tokens, ind)?;
237228

238-
tokens[*ind].expects(LexerTokenType::BracketClose)?;
239-
229+
tokens[*ind].expects(LexerTokenType::Comma)?;
240230
*ind += 1;
241231

242-
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { size: int_lit.0 as usize, v: val }, start, tokens[*ind].get_end_pos())));
243-
}
232+
let count = tokens[*ind].expects_int_lit()?;
244233

245-
tokens[*ind].expects(LexerTokenType::ArrayOpen)?;
246-
*ind += 1;
234+
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ArrayVariableInitializerValueSameValue { size: count.0 as usize, v: val }, start, tokens[*ind].get_end_pos())))
235+
}
247236

248237
let mut vals = vec![];
249238

250239
loop {
251-
vals.push(parse_ast_value(tokens, ind)?);
240+
let val = parse_ast_value(tokens, ind)?;
252241

253242
if tokens[*ind].tok_type == LexerTokenType::ArrayClose {
254243
break;
255244
}
256245

257246
tokens[*ind].expects(LexerTokenType::Comma)?;
258247
*ind += 1;
259-
}
260248

261-
*ind += 1;
249+
vals.push(val);
250+
}
262251

263252
return Ok(Box::new(ASTTreeNode::new(ASTTreeNodeKind::ArrayVariableInitializerValue { vals }, start, tokens[*ind].get_end_pos())))
253+
264254
}
265255

266256
pub fn parse_ast_pointer(tokens: &Vec<LexerToken>, ind: &mut usize) -> DiagnosticResult<Box<ASTTreeNode>> {

compiler/astoir_hir/src/ctx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ impl HIRBranchedContext {
207207
pub fn is_eligible_for_ssa(&self, ind: usize) -> bool {
208208
let var = &self.variables[ind];
209209

210-
return !var.requires_address && var.mutation_count <= 1 && !var.variable_type.can_use_index_access()
210+
return !var.requires_address && var.mutation_count <= 1 && !var.variable_type.can_use_index_access() && false
211211
}
212212

213213
}

compiler/astoir_hir/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@
33
44
pub mod ctx;
55
pub mod nodes;
6-
pub mod structs;
6+
pub mod structs;
7+
pub mod resolve;

compiler/astoir_hir/src/nodes.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
//! The nodes inside of the AstoIR HIR.
22
3+
use std::collections::HashMap;
4+
35
use compiler_typing::{raw::RawType, references::TypeReference, storage::{BOOLEAN_TYPE, STATIC_STR}, structs::RawStructTypeContainer, transmutation::array::can_transmute_inner, tree::Type};
4-
use compiler_utils::Position;
6+
use compiler_utils::{Position, hash::SelfHash};
57
use diagnostics::{DiagnosticSpanOrigin, builders::{make_diff_type, make_diff_type_val}, diagnostic::{Diagnostic, Span, SpanKind, SpanPosition}, unsure_panic};
68
use lexer::toks::{comp::ComparingOperator, math::MathOperator};
79

8-
use crate::{ctx::{HIRBranchedContext, HIRContext}, structs::{HIRIfBranch, StructLRUStep}};
10+
use crate::{ctx::{HIRBranchedContext, HIRContext}, resolve::resolve_to_type, structs::{HIRIfBranch, StructLRUStep}};
911

1012
#[derive(Debug, Clone)]
1113
pub struct HIRNode {
@@ -62,6 +64,8 @@ pub enum HIRNodeKind {
6264

6365
StructLRU { steps: Vec<StructLRUStep>, last: Type },
6466

67+
EnumParentCast { val: Box<HIRNode>, parent: Type },
68+
6569
StructDeclaration { type_name: usize, container: RawStructTypeContainer, layout: bool },
6670
StructFunctionDeclaration { func_name: usize, arguments: Vec<(u64, TypeReference)>, return_type: Option<TypeReference>, body: Vec<Box<HIRNode>>, ctx: HIRBranchedContext, requires_this: bool },
6771

@@ -71,7 +75,9 @@ pub enum HIRNodeKind {
7175
ArrayIndexAccess { val: Box<HIRNode>, index: Box<HIRNode> },
7276
ArrayIndexModify { array: Box<HIRNode>, index: Box<HIRNode>, new_val : Box<HIRNode> },
7377

74-
StructVariableInitializerValue { t: Type, fields: Vec<Box<HIRNode>> },
78+
/// Before transmutation
79+
StructInitializer { fields: HashMap<SelfHash, Box<HIRNode>> },
80+
StructInitializerTyped { t: Type, fields: Vec<Box<HIRNode>> },
7581

7682
FunctionDeclaration { func_name: usize, arguments: Vec<(u64, Type)>, return_type: Option<Type>, body: Vec<Box<HIRNode>>, ctx: HIRBranchedContext, requires_this: bool },
7783

@@ -132,6 +138,10 @@ impl HIRNode {
132138
}
133139

134140
pub fn use_as<K: DiagnosticSpanOrigin>(&self, context: &HIRContext, curr_ctx: &HIRBranchedContext, t: Type, origin: &K, var_origin: Option<&K>) -> Result<HIRNode, ()> {
141+
if self.is_intederminately_typed() {
142+
return Ok(resolve_to_type(Box::new(self.clone()), t.clone(), context, curr_ctx, origin)?.use_as(context, curr_ctx, t, origin, var_origin)?);
143+
}
144+
135145
let self_type = match self.get_node_type(context, curr_ctx) {
136146
Some(v) => v,
137147
_ => panic!("Tried using a typeless node in use_as: {:#?}", self)
@@ -146,7 +156,7 @@ impl HIRNode {
146156
HIRNodeKind::IntegerLiteral { value, int_type: _ } => {
147157
return Ok(self.with(HIRNodeKind::IntegerLiteral { value: *value, int_type: t }));
148158
},
149-
159+
150160
HIRNodeKind::ArrayVariableInitializerValue { vals } => {
151161
if can_transmute_inner(&self_type, &t, &context.type_storage) {
152162
let mut new_vals = vec![];
@@ -181,6 +191,14 @@ impl HIRNode {
181191
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())
182192
}
183193

194+
pub fn is_intederminately_typed(&self) -> bool {
195+
match self.kind {
196+
HIRNodeKind::StructInitializer { .. } => true,
197+
198+
_ => false
199+
}
200+
}
201+
184202
pub fn get_node_type(&self, context: &HIRContext, curr_ctx: &HIRBranchedContext) -> Option<Type> {
185203
match &self.kind {
186204
HIRNodeKind::VariableReference { index, is_static } => {
@@ -218,12 +236,7 @@ impl HIRNode {
218236
},
219237

220238
HIRNodeKind::StringLiteral { value: _ } => {
221-
let ind = match context.type_storage.types.get_index(STATIC_STR) {
222-
Some(v) => v,
223-
None => return None
224-
};
225-
226-
return Some(Type::Generic(RawType::Boolean, vec![], vec![]))
239+
return Some(Type::Generic(RawType::StaticString, vec![], vec![]))
227240
},
228241

229242
HIRNodeKind::ArrayVariableInitializerValue { vals } => return Some(Type::Array(vals.len(), Box::new(vals[0].get_node_type(context, curr_ctx).unwrap()))),
@@ -241,9 +254,7 @@ impl HIRNode {
241254
return Some(Type::Generic(RawType::Boolean, vec![], vec![]))
242255
},
243256

244-
HIRNodeKind::StructVariableInitializerValue { t, fields: _ } => {
245-
return Some(t.clone())
246-
}
257+
HIRNodeKind::StructInitializerTyped { t, fields: _ } => Some(t.clone()),
247258

248259
HIRNodeKind::FunctionCall { func_name, arguments: _ } => {
249260
let f = context.functions.vals[*func_name].0.clone();

compiler/astoir_hir/src/resolve.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//! Used to resolve incomplete HIR nodes like initializers
2+
3+
use compiler_typing::tree::Type;
4+
use compiler_utils::hash::SelfHash;
5+
use diagnostics::{DiagnosticResult, DiagnosticSpanOrigin, builders::{make_req_type_kind, make_struct_init_missing_field}};
6+
7+
use crate::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}};
8+
9+
/// Resolves incomplete HIR nodes into complete nodes
10+
pub fn resolve_to_type<K: DiagnosticSpanOrigin>(node: Box<HIRNode>, destination: Type, context: &HIRContext, curr_ctx: &HIRBranchedContext, origin: &K) -> DiagnosticResult<Box<HIRNode>> {
11+
match node.kind {
12+
HIRNodeKind::StructInitializer { fields } => {
13+
let generic = destination.as_generic_safe(origin)?;
14+
let mut new_fields = vec![];
15+
16+
if !generic.is_field_based() {
17+
return Err(make_req_type_kind(origin, &"field-having".to_string()).into())
18+
}
19+
20+
for field in destination.get_fields(&context.type_storage) {
21+
let identity = SelfHash { hash: field };
22+
23+
if !fields.contains_key(&identity) {
24+
return Err(make_struct_init_missing_field(origin, &destination, &field).into())
25+
}
26+
27+
let val = fields[&identity].clone();
28+
29+
let field_data = destination.get_field(&context.type_storage, field)?.1.resolve(&destination);
30+
31+
let val = Box::new(val.use_as(context, curr_ctx, field_data, origin, None)?);
32+
33+
new_fields.push(val);
34+
}
35+
36+
return Ok(Box::new(HIRNode::new(HIRNodeKind::StructInitializerTyped { t: destination, fields: new_fields }, &node.start, &node.end)))
37+
},
38+
39+
_ => panic!("Invalid node")
40+
}
41+
}

compiler/astoir_hir_lowering/src/structs.rs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::collections::HashMap;
2+
13
use ast::tree::{ASTTreeNode, ASTTreeNodeKind};
24
use astoir_hir::{ctx::{HIRBranchedContext, HIRContext}, nodes::{HIRNode, HIRNodeKind}, structs::HIRStructContainer};
35
use compiler_typing::{raw::RawType, structs::RawStructTypeContainer, tree::Type};
@@ -89,40 +91,14 @@ pub fn lower_ast_struct_declaration(context: &mut HIRContext, node: Box<ASTTreeN
8991
}
9092

9193
pub fn lower_ast_struct_initializer(context: &mut HIRContext, curr_ctx: &mut HIRBranchedContext, node: Box<ASTTreeNode>) -> DiagnosticResult<Box<HIRNode>> {
92-
if let ASTTreeNodeKind::StructVariableInitializerValue { struct_type, map } = node.kind.clone() {
93-
let raw = match context.type_storage.get_type(HashedString::new(struct_type.get_generic_name()).hash) {
94-
Ok(v) => Type::GenericLowered(v),
95-
Err(_) => return Err(make_cannot_find_type(&*node, &struct_type.get_generic_name()).into())
96-
};
97-
98-
let hir_type = lower_ast_type(context, struct_type, &*node)?;
99-
100-
let fields = raw.get_fields(&context.type_storage);
101-
102-
let mut vals = vec![];
103-
104-
for field in fields {
105-
let id = SelfHash { hash: field };
106-
107-
if !map.contains_key(&id) {
108-
return Err(make_struct_init_missing_field(&*node, &hir_type, &field).into())
109-
}
110-
111-
let field = match raw.get_field(&context.type_storage, field) {
112-
Ok(v) => v,
113-
Err(_) => return Err(make_struct_missing_field(&*node, &hir_type, &id.hash).into())
114-
};
115-
116-
let tt = field.1.resolve(&hir_type);
117-
118-
let val = lower_ast_value(context, curr_ctx, map[&id].clone())?;
119-
120-
let val = Box::new(val.use_as(context, curr_ctx, tt.clone(), &*node, None)?);
94+
if let ASTTreeNodeKind::StructInitializer { map } = node.kind.clone() {
95+
let mut new_map = HashMap::new();
12196

122-
vals.push(val)
97+
for (k, v) in map {
98+
new_map.insert(k, lower_ast_value(context, curr_ctx, v)?);
12399
}
124100

125-
return Ok(Box::new(HIRNode::new(HIRNodeKind::StructVariableInitializerValue { t: hir_type, fields: vals }, &node.start, &node.end)))
101+
return Ok(Box::new(HIRNode::new(HIRNodeKind::StructInitializer { fields: new_map }, &node.start, &node.end)))
126102
}
127103

128104
panic!("Invalid node type")

0 commit comments

Comments
 (0)