feat: support source pointers and references

This commit is contained in:
2026-10-26 10:37:08 +01:00
parent 9966a1f523
commit 676f3666b4
17 changed files with 981 additions and 78 deletions
+44 -4
View File
@@ -1,9 +1,9 @@
#! grammar:
#! * type ..... -> identifier {'.' member} | '[' (expr | '_') ']' ['mut'] type | 'struct' '{' fields '}' | 'enum' ['(' type ')'] '{' members '}' | 'union' ['(' (type | 'enum') ')'] '{' fields '}' | ('distinct' | 'alias') type
#! * type ..... -> identifier {'.' member} | ('@' | '*') ['mut'] type | '[' (expr | '_') ']' ['mut'] type | 'struct' '{' fields '}' | 'enum' ['(' type ')'] '{' members '}' | 'union' ['(' (type | 'enum') ')'] '{' fields '}' | ('distinct' | 'alias') type
#! * binding ... -> :: | :=
#! * literal .. -> int | float | string | 'true' | 'false'
#! * op ....... -> '+' | '-' | '*' | '/' | '==' | '!=' | '<' | '<=' | '>' | '>=' | 'and' | 'or'
#! * expr ..... -> identifier | literal | type | '.' member | '[' [expr {',' expr} [',']] ']' | [type] '{' [initializer {',' initializer} [',']] '}' | '(' expr ')' | ('-' | '!') expr | expr op expr | expr '(' [expr {',' expr} [',']] ')' | expr '[' expr ']' | expr '.' (member | int) | expr ('..' | '..=') expr | 'match' expr '{' match_arms '}'
#! * expr ..... -> identifier | literal | type | '.' member | '[' [expr {',' expr} [',']] ']' | [type] '{' [initializer {',' initializer} [',']] '}' | '(' expr ')' | ('-' | '!' | '&') expr | expr '^' | expr op expr | expr '(' [expr {',' expr} [',']] ')' | expr '[' expr ']' | expr '.' (member | int) | expr ('..' | '..=') expr | 'match' expr '{' match_arms '}'
#! * decl ..... -> identifier [type] binding expr | ['test'] [identifier '::'] 'import' string
#! * block .... -> '{' {stmt} '}'
#! * arm ...... -> block | stmt (single statements become canonical blocks)
@@ -11,7 +11,7 @@
#! enum members and tagged-union variants accept keyword names; member names do not enter lexical scopes.
#! * stmt ..... -> decl | expr | expr '=' expr | 'return' [expr] | 'break' | 'continue' | 'if' expr arm ['else' arm] | 'while' expr arm | 'for' expr '|' ['@'] identifier [',' identifier] '|' arm
#! braceless guards/iterables require parentheses unless they are calls; else binds to the nearest if.
#! precedence (tightest first): calls/indices/selections, unary -/!, multiplication/division, addition/subtraction, relational comparisons, equality, and, or, ranges. compound range endpoints require their own parentheses.
#! precedence (tightest first): calls/indices/selections/dereference, unary -/!/& higher than multiplication/division, addition/subtraction, relational comparisons, equality, and, or, ranges. compound range endpoints require their own parentheses.
#! binary operators associate left; unary operators associate right.
import "@std/debug"
@@ -44,6 +44,7 @@ ExprKind :: enum {
call
range
array_type
pointer_type
array_literal
record_type
record_literal
@@ -82,7 +83,12 @@ Mutability :: enum {
constant, variable
}
UnaryOperator :: enum { negate, logical_not }
UnaryOperator :: enum {
negate
logical_not
address_of
dereference
}
BinaryOperator :: enum {
add, subtract
@@ -105,6 +111,7 @@ NodeKind :: enum {
expr_call
expr_range
expr_array_type
expr_pointer_type
expr_array_literal
expr_record_type
expr_record_literal
@@ -231,6 +238,12 @@ ArrayTypeView :: struct {
mutable bool
}
PointerTypeView :: struct {
element NodeId
mutable bool
many bool
}
RecordLiteralView :: struct {
span Span
type ?NodeId
@@ -482,6 +495,22 @@ add_array_type proc(
}, span)
}
add_pointer_type proc(
builder @mut Builder,
span Span,
element NodeId,
mutable, many bool,
) NodeId ! mem.AllocError {
mutable_flag :: if (mutable) u32(1) else u32(0)
many_flag :: if (many) u32(1) else u32(0)
return try add_node(builder, Node{
kind = .expr_pointer_type,
main = NodeData{ extra = mutable_flag },
data0 = NodeData{ extra = many_flag },
data1 = NodeData{ node_id = element },
}, span)
}
add_array_literal proc(builder @mut Builder, span Span, elements []NodeId) NodeId ! mem.AllocError {
start :: builder.storage.extra.items.len
for (elements) |element| _ = try add_extra(builder, u32(element))
@@ -1073,6 +1102,7 @@ expression_kind proc(kind NodeKind) ExprKind {
.expr_call: .call
.expr_range: .range
.expr_array_type: .array_type
.expr_pointer_type: .pointer_type
.expr_array_literal: .array_literal
.expr_record_type: .record_type
.expr_record_literal: .record_literal
@@ -1154,6 +1184,16 @@ array_type proc(tree @Tree, id NodeId) ArrayTypeView {
}
}
pointer_type proc(tree @Tree, id NodeId) PointerTypeView {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .expr_pointer_type)
return PointerTypeView{
element = node.data1.node_id,
mutable = node.main.extra != 0,
many = node.data0.extra != 0,
}
}
array_element_count proc(tree @Tree, id NodeId) usize {
node :: get_node(&tree.storage, id)
debug.assert(node.kind == .expr_array_literal)