feat: support source pointers and references
This commit is contained in:
+44
-4
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user