mirror of
https://github.com/imjasonh/nescript
synced 2026-07-10 09:42:37 +00:00
Language: struct literals
struct Vec2 { x: u8, y: u8 }
var pos: Vec2 = Vec2 { x: 100, y: 50 }
on frame {
pos = Vec2 { x: pos.x + 1, y: pos.y }
}
- AST: new \`Expr::StructLiteral(name, fields, span)\` variant
- Parser: in expression position, \`Ident {\` enters struct-literal
mode when the new \`restrict_struct_literals\` flag is off.
\`if\`/\`while\`/\`for\` conditions set the flag so the \`{\` keeps
going to the following block. Condition contexts can still use
struct literals by parenthesizing them.
- Analyzer: validates that the struct type exists, each named field
belongs to it, and each field value has a compatible type.
- IR lowering: desugars \`var = StructLiteral { ... }\` (both in
assignments and variable initializers) into per-field StoreVar
operations against the analyzer-synthesized \`var.field\`
variables. No IR type for struct values is needed.
- AST codegen: no-op (legacy path).
- examples/structs_enums_for.ne now uses a struct literal for the
initial \`player\` state instead of per-field assignments.
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
parent
f17f1e7267
commit
c8ae433a7c
9 changed files with 221 additions and 13 deletions
|
|
@ -364,6 +364,34 @@ impl Analyzer {
|
|||
self.walk_expr_reads(e);
|
||||
}
|
||||
}
|
||||
Expr::StructLiteral(name, fields, span) => {
|
||||
// Validate that the struct type exists and that each
|
||||
// named field is actually declared. Missing or extra
|
||||
// fields are an error; duplicate fields are silently
|
||||
// ignored (last-writer-wins).
|
||||
if let Some(layout) = self.struct_layouts.get(name).cloned() {
|
||||
for (fname, fexpr) in fields {
|
||||
if let Some((_, field_type, _)) =
|
||||
layout.fields.iter().find(|(n, _, _)| n == fname)
|
||||
{
|
||||
self.walk_expr_reads(fexpr);
|
||||
self.check_expr_type(fexpr, field_type);
|
||||
} else {
|
||||
self.diagnostics.push(Diagnostic::error(
|
||||
ErrorCode::E0201,
|
||||
format!("struct '{name}' has no field '{fname}'"),
|
||||
*span,
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.diagnostics.push(Diagnostic::error(
|
||||
ErrorCode::E0201,
|
||||
format!("unknown struct type '{name}'"),
|
||||
*span,
|
||||
));
|
||||
}
|
||||
}
|
||||
Expr::IntLiteral(_, _) | Expr::BoolLiteral(_, _) | Expr::ButtonRead(_, _, _) => {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1149,6 +1177,7 @@ impl Analyzer {
|
|||
}
|
||||
Expr::ArrayLiteral(_, _) => Some(NesType::U8), // element type inferred from context
|
||||
Expr::Cast(_, target, _) => Some(target.clone()),
|
||||
Expr::StructLiteral(name, _, _) => Some(NesType::Struct(name.clone())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1366,6 +1395,11 @@ fn collect_calls_expr(expr: &Expr, calls: &mut Vec<String>) {
|
|||
collect_calls_expr(e, calls);
|
||||
}
|
||||
}
|
||||
Expr::StructLiteral(_, fields, _) => {
|
||||
for (_, e) in fields {
|
||||
collect_calls_expr(e, calls);
|
||||
}
|
||||
}
|
||||
Expr::Cast(inner, _, _) => {
|
||||
collect_calls_expr(inner, calls);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue