mirror of
https://github.com/imjasonh/nescript
synced 2026-07-17 06:02:01 +00:00
Language: struct types
Adds composite \`struct\` types with field access:
struct Vec2 { x: u8, y: u8 }
var pos: Vec2
pos.x = 100
pos.y = pos.x + 5
- Lexer: \`struct\` keyword
- AST: \`StructDecl\` with \`StructField\` list; \`NesType::Struct(name)\`
for struct-typed variable declarations; \`Expr::FieldAccess\` and
\`LValue::Field\` for reads/writes
- Parser: top-level \`struct Name { field: type, ... }\` (optional
trailing comma) and \`ident.field\` syntax in both expression and
lvalue position
- Analyzer: \`register_struct\` computes contiguous field offsets
(no padding) and stores them in \`struct_layouts\`. Struct variables
synthesize a \`VarAllocation\` per field under the name
\`"struct_var.field"\`, and \`Expr::FieldAccess\` / \`LValue::Field\`
resolve against those. Unknown struct types and unknown fields
emit E0201.
- IR lowering + AST codegen: treat struct field access as ordinary
variable access against the synthetic per-field symbols. No new IR
ops are needed.
v1 structs only support primitive fields (u8/i8/bool). Nested structs,
u16 fields, and array fields are not yet allowed.
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
parent
9c102cb68e
commit
225d40cea5
12 changed files with 464 additions and 3 deletions
|
|
@ -298,6 +298,68 @@ fn analyze_return_wrong_type() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn analyze_struct_variable_allocates_fields() {
|
||||
let result = analyze_ok(
|
||||
r#"
|
||||
game "Test" { mapper: NROM }
|
||||
struct Vec2 { x: u8, y: u8 }
|
||||
var pos: Vec2
|
||||
on frame {
|
||||
pos.x = 10
|
||||
pos.y = pos.x
|
||||
}
|
||||
start Main
|
||||
"#,
|
||||
);
|
||||
// The analyzer should synthesize pos.x and pos.y as separate
|
||||
// variables with consecutive addresses.
|
||||
let px = result
|
||||
.var_allocations
|
||||
.iter()
|
||||
.find(|a| a.name == "pos.x")
|
||||
.expect("pos.x should be allocated");
|
||||
let py = result
|
||||
.var_allocations
|
||||
.iter()
|
||||
.find(|a| a.name == "pos.y")
|
||||
.expect("pos.y should be allocated");
|
||||
assert_eq!(py.address, px.address + 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn analyze_struct_unknown_field_errors() {
|
||||
let errors = analyze_errors(
|
||||
r#"
|
||||
game "Test" { mapper: NROM }
|
||||
struct Vec2 { x: u8, y: u8 }
|
||||
var pos: Vec2
|
||||
on frame { pos.z = 5 }
|
||||
start Main
|
||||
"#,
|
||||
);
|
||||
assert!(
|
||||
errors.contains(&ErrorCode::E0201),
|
||||
"unknown field should emit E0201: {errors:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn analyze_unknown_struct_type_errors() {
|
||||
let errors = analyze_errors(
|
||||
r#"
|
||||
game "Test" { mapper: NROM }
|
||||
var pos: NoSuchStruct
|
||||
on frame { wait_frame }
|
||||
start Main
|
||||
"#,
|
||||
);
|
||||
assert!(
|
||||
errors.contains(&ErrorCode::E0201),
|
||||
"unknown struct type should emit E0201: {errors:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn analyze_enum_variants_as_constants() {
|
||||
let result = analyze_ok(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue