authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-13 18:15:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-13 18:15:51-07:00
logb28b7f63d15ab0fdd9064c6c58e6339705edbc27
tree8139f31b749a6838bb92d16053e371f826224d32
parentcb46d0b5b0d1d83856adab34b461049f5cfac019

all types are now expressions

See #22

26 files changed, 1570 insertions(+), 1818 deletions(-)

doc/langref.md+23-33
...@@ -34,13 +34,13 @@ Root : many(TopLevelDecl) token(EOF)...@@ -34,13 +34,13 @@ Root : many(TopLevelDecl) token(EOF)
3434
35TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | ContainerDecl | VariableDeclaration35TopLevelDecl : FnDef | ExternBlock | RootExportDecl | Use | ContainerDecl | VariableDeclaration
3636
37VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))37VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) UnwrapMaybeExpression option(token(Eq) Expression))
3838
39ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)39ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
4040
41StructMember: StructField | FnDecl41StructMember: StructField | FnDecl
4242
43StructField : token(Symbol) option(token(Colon) Type token(Comma))43StructField : token(Symbol) option(token(Colon) Expression) token(Comma))
4444
45Use : many(Directive) token(Use) token(String) token(Semicolon)45Use : many(Directive) token(Use) token(String) token(Semicolon)
4646
...@@ -48,7 +48,7 @@ RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token...@@ -48,7 +48,7 @@ RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token
4848
49ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnDecl) token(RBrace)49ExternBlock : many(Directive) token(Extern) token(LBrace) many(FnDecl) token(RBrace)
5050
51FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type)51FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(Expression)
5252
53Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)53Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)
5454
...@@ -56,23 +56,11 @@ FnVisibleMod : token(Pub) | token(Export)...@@ -56,23 +56,11 @@ FnVisibleMod : token(Pub) | token(Export)
5656
57FnDecl : FnProto token(Semicolon)57FnDecl : FnProto token(Semicolon)
5858
59FnDef : FnProto Block59FnDef : FnProto token(FatArrow) Block
6060
61ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen)61ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen)
6262
63ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis)63ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis)
64
65Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompilerFnExpr
66
67CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen)
68
69CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Type token(RParen)
70
71PointerType : token(Ampersand) option(token(Const)) option(token(NoAlias)) Type
72
73MaybeType : token(Question) Type
74
75ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(NoAlias)) Type
7664
77Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)65Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
7866
...@@ -80,11 +68,9 @@ Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression to...@@ -80,11 +68,9 @@ Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression to
8068
81Label: token(Symbol) token(Colon)69Label: token(Symbol) token(Colon)
8270
83VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
84
85Expression : BlockExpression | NonBlockExpression71Expression : BlockExpression | NonBlockExpression
8672
87NonBlockExpression : ReturnExpression | AssignmentExpression | AsmExpression73NonBlockExpression : ReturnExpression | AssignmentExpression
8874
89AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen)75AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen)
9076
...@@ -92,13 +78,13 @@ AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput)...@@ -92,13 +78,13 @@ AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput)
9278
93AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers)79AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers)
9480
95AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) Type) token(RParen)81AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) Expression) token(RParen)
9682
97AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)83AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)
9884
99AsmClobbers: token(Colon) list(token(String), token(Comma))85AsmClobbers: token(Colon) list(token(String), token(Comma))
10086
101UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression87UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestionMark) BoolOrExpression | BoolOrExpression
10288
103AssignmentExpression : UnwrapMaybeExpression AssignmentOperator UnwrapMaybeExpression | UnwrapMaybeExpression89AssignmentExpression : UnwrapMaybeExpression AssignmentOperator UnwrapMaybeExpression | UnwrapMaybeExpression
10490
...@@ -116,7 +102,7 @@ IfExpression : IfVarExpression | IfBoolExpression...@@ -116,7 +102,7 @@ IfExpression : IfVarExpression | IfBoolExpression
116102
117IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)103IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)
118104
119IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)105IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Expression) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)
120106
121Else : token(Else) Expression107Else : token(Else) Expression
122108
...@@ -144,11 +130,11 @@ MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastEx...@@ -144,11 +130,11 @@ MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastEx
144130
145MultiplyOperator : token(Star) | token(Slash) | token(Percent)131MultiplyOperator : token(Star) | token(Slash) | token(Percent)
146132
147CastExpression : CastExpression token(as) Type | PrefixOpExpression133CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
148134
149PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression135PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
150136
151SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)137SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
152138
153FieldAccessExpression : token(Dot) token(Symbol)139FieldAccessExpression : token(Dot) token(Symbol)
154140
...@@ -158,26 +144,30 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)...@@ -158,26 +144,30 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
158144
159SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))145SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
160146
161PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))147ContainerInitExpression : token(LBrace) ContainerInitBody token(RBrace)
148
149ContainerInitBody : list(StructLiteralField, token(Comma)) | list(Expression, token(Comma))
150
151StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
162152
163PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression)153PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const))) | token(QuestionMark)
164154
165StructValueExpression : token(Type) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)155PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | token(Symbol) | (token(AtSign) token(Symbol) FnCallExpression) | ArrayType | AsmExpression
166156
167StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression157ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) Expression
168158
169Goto: token(Goto) token(Symbol)159GotoExpression: token(Goto) token(Symbol)
170160
171GroupedExpression : token(LParen) Expression token(RParen)161GroupedExpression : token(LParen) Expression token(RParen)
172162
173KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False) | token(Null)163KeywordLiteral : token(True) | token(False) | token(Null) | token(Break) | token(Continue)
174```164```
175165
176## Operator Precedence166## Operator Precedence
177167
178```168```
179x() x[] x.y169x() x[] x{} x.y
180!x -x ~x *x &x &const x170!x -x ~x *x &x
181as171as
182* / %172* / %
183+ -173+ -
doc/vim/syntax/zig.vim+2-2
...@@ -15,8 +15,8 @@ syn keyword zigConditional if else switch...@@ -15,8 +15,8 @@ syn keyword zigConditional if else switch
15syn keyword zigRepeat while for15syn keyword zigRepeat while for
1616
17syn keyword zigConstant null17syn keyword zigConstant null
18syn keyword zigKeyword fn unreachable use void18syn keyword zigKeyword fn use
19syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string19syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string void unreachable
2020
21syn keyword zigBoolean true false21syn keyword zigBoolean true false
2222
example/arrays/arrays.zig deleted-36
...@@ -1,36 +0,0 @@
1export executable "arrays";
2
3use "std.zig";
4
5pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
6 var array : [5]u32;
7
8 var i : u32 = 0;
9 while (i < 5) {
10 array[i] = i + 1;
11 i = array[i];
12 }
13
14 i = 0;
15 var accumulator : u32 = 0;
16 while (i < 5) {
17 accumulator += array[i];
18
19 i += 1;
20 }
21
22 if (accumulator != 15) {
23 print_str("BAD\n");
24 }
25
26 if (get_array_len(array) != 5) {
27 print_str("BAD\n");
28 }
29
30 print_str("OK\n");
31 return 0;
32}
33
34fn get_array_len(a: []u32) -> usize {
35 a.len
36}
example/cat/main.zig created+7
...@@ -0,0 +1,7 @@
1export executable "cat";
2
3pub main(argv: [][]u8) -> i32 {
4
5
6 return 0;
7}
example/expressions/expressions.zig deleted-52
...@@ -1,52 +0,0 @@
1export executable "expressions";
2
3use "std.zig";
4
5fn other_exit() -> unreachable {
6 if (true) { exit(0); }
7 // the unreachable statement is the programmer assuring the compiler that this code is impossible to execute.
8 unreachable;
9}
10
11export fn main(argc: isize, argv: &&u8, env: &&u8) -> unreachable {
12 const a : i32 = 1;
13 const b = 2 as i32;
14 // const c : i32; // not yet support for const variables
15 // const d; // parse error
16 if (a + b == 3) {
17 const no_conflict : i32 = 5;
18 if (no_conflict == 5) { print_str("OK 1\n" as string); }
19 }
20
21 const c = {
22 const no_conflict : i32 = 10;
23 no_conflict
24 };
25 if (c == 10) { print_str("OK 2\n" as string); }
26
27 void_fun(1, void, 2);
28
29 test_mutable_vars();
30
31 other_exit();
32}
33
34fn void_fun(a : i32, b : void, c : i32) -> void {
35 const x = a + 1; // i32
36 const y = c + 1; // i32
37 const z = b; // void
38 const w : void = z; // void
39 if (x + y == 4) { return w; }
40}
41
42fn test_mutable_vars() {
43 var i : i32 = 0;
44loop_start:
45 if i == 3 {
46 goto done;
47 }
48 print_str("loop\n" as string);
49 i = i + 1;
50 goto loop_start;
51done:
52}
example/guess_number/main.zig+3-3
...@@ -3,12 +3,12 @@ export executable "guess_number";...@@ -3,12 +3,12 @@ export executable "guess_number";
3use "std.zig";3use "std.zig";
4use "rand.zig";4use "rand.zig";
55
6pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {6pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
7 print_str("Welcome to the Guess Number Game in Zig.\n");7 print_str("Welcome to the Guess Number Game in Zig.\n");
88
9 var seed : u32;9 var seed : u32;
10 const err = os_get_random_bytes(&seed as &u8, #sizeof(u32));10 const err = os_get_random_bytes(&seed as (&u8), @sizeof(u32));
11 if (err != #sizeof(u32)) {11 if (err != @sizeof(u32)) {
12 // TODO full error message12 // TODO full error message
13 fprint_str(stderr_fileno, "unable to get random bytes\n");13 fprint_str(stderr_fileno, "unable to get random bytes\n");
14 return 1;14 return 1;
example/hello_world/hello.zig+1-1
...@@ -2,7 +2,7 @@ export executable "hello";...@@ -2,7 +2,7 @@ export executable "hello";
22
3use "std.zig";3use "std.zig";
44
5pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {5pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
6 print_str("Hello, world!\n");6 print_str("Hello, world!\n");
7 return 0;7 return 0;
8}8}
example/hello_world/hello_libc.zig+2-3
...@@ -2,11 +2,10 @@ export executable "hello";...@@ -2,11 +2,10 @@ export executable "hello";
22
3#link("c")3#link("c")
4extern {4extern {
5 fn printf(__format: &const u8, ...) -> i32;5 fn printf(__format: &const u8, ...) i32;
6 fn exit(__status: i32) -> unreachable;
7}6}
87
9export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {8export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {
10 printf(c"Hello, world!\n");9 printf(c"Hello, world!\n");
11 return 0;10 return 0;
12}11}
example/list/list.zig+45-7
...@@ -1,16 +1,16 @@...@@ -1,16 +1,16 @@
1pub struct List#(T: type) {1pub struct List#(T: type) {
2 items: ?&T,2 items: ?&T,
3 length: usize,3 length: isize,
4 capacity: usize,4 capacity: isize,
55
6 pub fn (l: &List) deinit() {6 pub fn deinit(l: &List) {
7 free(l.items);7 free(l.items);
8 l.items = None;8 l.items = null;
9 }9 }
1010
11 pub fn append(l: &List, item: T) -> error {11 pub fn append(l: &List, item: T) -> error {
12 const err = l.ensure_capacity(l.length + 1);12 const err = l.ensure_capacity(l.length + 1);
13 if err != Error.None {13 if err != error.None {
14 return err;14 return err;
15 }15 }
16 const raw_items = l.items ?? unreachable;16 const raw_items = l.items ?? unreachable;
...@@ -47,11 +47,11 @@ pub struct List#(T: type) {...@@ -47,11 +47,11 @@ pub struct List#(T: type) {
47 better_capacity *= 2;47 better_capacity *= 2;
48 }48 }
49 if better_capacity != l.capacity {49 if better_capacity != l.capacity {
50 const new_items = realloc(l.items, better_capacity) ?? { return Error.NoMem };50 const new_items = realloc(l.items, better_capacity) ?? { return error.NoMem };
51 l.items = new_items;51 l.items = new_items;
52 l.capacity = better_capacity;52 l.capacity = better_capacity;
53 }53 }
54 Error.None54 error.None
55 }55 }
56}56}
5757
...@@ -64,3 +64,41 @@ pub fn realloc#(T: type)(ptr: ?&T, new_count: usize) -> ?&T {...@@ -64,3 +64,41 @@ pub fn realloc#(T: type)(ptr: ?&T, new_count: usize) -> ?&T {
64pub fn free#(T: type)(ptr: ?&T) {64pub fn free#(T: type)(ptr: ?&T) {
6565
66}66}
67
68
69////////////////// alternate
70
71// previously proposed, but with : instead of ->
72// `:` means "parser should expect a type now"
73fn max#(T :type)(a :T, b :T) :T {
74 if (a > b) a else b
75}
76
77// andy's new idea
78// parameters can talk about @typeof() for previous parameters.
79// using :T here is equivalent to @child_type(@typeof(T))
80fn max(T :type, a :T, b :T) :T {
81 if (a > b) a else b
82}
83
84fn f() {
85 const x :i32 = 1234;
86 const y :i32 = 5678;
87 const z = max(@typeof(x), x, y);
88}
89
90// So, type-generic functions don't need any fancy syntax. type-generic
91// containers still do, though:
92
93pub struct List(T :type) {
94 items :?&T,
95 length :isize,
96 capacity :isize,
97}
98
99// Types are always marked with ':' so we don't need '#' to indicate type generic parameters.
100
101fn f() {
102 var list :List(:u8);
103}
104
example/maybe_type/main.zig+2-2
...@@ -2,7 +2,7 @@ export executable "maybe_type";...@@ -2,7 +2,7 @@ export executable "maybe_type";
22
3use "std.zig";3use "std.zig";
44
5pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {5pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
6 const x : ?bool = true;6 const x : ?bool = true;
77
8 if (const y ?= x) {8 if (const y ?= x) {
...@@ -25,7 +25,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -25,7 +25,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
2525
26 const final_x : ?i32 = 13;26 const final_x : ?i32 = 13;
2727
28 const num = final_x ?? unreachable;28 const num = final_x ?? unreachable{};
2929
30 if (num != 13) {30 if (num != 13) {
31 print_str("BAD\n");31 print_str("BAD\n");
example/multiple_files/foo.zig+2-2
...@@ -2,10 +2,10 @@ use "std.zig";...@@ -2,10 +2,10 @@ use "std.zig";
22
3// purposefully conflicting function with main.zig3// purposefully conflicting function with main.zig
4// but it's private so it should be OK4// but it's private so it should be OK
5fn private_function() {5fn private_function() => {
6 print_str("OK 1\n");6 print_str("OK 1\n");
7}7}
88
9pub fn print_text() {9pub fn print_text() => {
10 private_function();10 private_function();
11}11}
example/multiple_files/main.zig+2-2
...@@ -3,12 +3,12 @@ export executable "test-multiple-files";...@@ -3,12 +3,12 @@ export executable "test-multiple-files";
3use "std.zig";3use "std.zig";
4use "foo.zig";4use "foo.zig";
55
6pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {6pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
7 private_function();7 private_function();
8 print_str("OK 2\n");8 print_str("OK 2\n");
9 return 0;9 return 0;
10}10}
1111
12fn private_function() {12fn private_function() => {
13 print_text();13 print_text();
14}14}
example/structs/structs.zig deleted-87
...@@ -1,87 +0,0 @@
1export executable "structs";
2
3use "std.zig";
4
5pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
6 var foo : Foo;
7
8 foo.a = foo.a + 1;
9
10 foo.b = foo.a == 1;
11
12 test_foo(foo);
13
14 modify_foo(&foo);
15
16 if foo.c != 100 {
17 print_str("BAD\n");
18 }
19
20 test_point_to_self();
21
22 test_byval_assign();
23
24 test_initializer();
25
26 print_str("OK\n");
27 return 0;
28}
29
30struct Foo {
31 a : i32,
32 b : bool,
33 c : f32,
34}
35
36struct Node {
37 val: Val,
38 next: &Node,
39}
40
41struct Val {
42 x: i32,
43}
44
45fn test_foo(foo : Foo) {
46 if !foo.b {
47 print_str("BAD\n");
48 }
49}
50
51fn modify_foo(foo : &Foo) {
52 foo.c = 100;
53}
54
55fn test_point_to_self() {
56 var root : Node;
57 root.val.x = 1;
58
59 var node : Node;
60 node.next = &root;
61 node.val.x = 2;
62
63 root.next = &node;
64
65 if node.next.next.next.val.x != 1 {
66 print_str("BAD\n");
67 }
68}
69
70fn test_byval_assign() {
71 var foo1 : Foo;
72 var foo2 : Foo;
73
74 foo1.a = 1234;
75
76 if foo2.a != 0 { print_str("BAD\n"); }
77
78 foo2 = foo1;
79
80 if foo2.a != 1234 { print_str("BAD - byval assignment failed\n"); }
81
82}
83
84fn test_initializer() {
85 const val = Val { .x = 42 };
86 if val.x != 42 { print_str("BAD\n"); }
87}
src/all_types.hpp+30-64
...@@ -100,7 +100,6 @@ enum NodeType {...@@ -100,7 +100,6 @@ enum NodeType {
100 NodeTypeFnDef,100 NodeTypeFnDef,
101 NodeTypeFnDecl,101 NodeTypeFnDecl,
102 NodeTypeParamDecl,102 NodeTypeParamDecl,
103 NodeTypeType,
104 NodeTypeBlock,103 NodeTypeBlock,
105 NodeTypeExternBlock,104 NodeTypeExternBlock,
106 NodeTypeDirective,105 NodeTypeDirective,
...@@ -111,7 +110,6 @@ enum NodeType {...@@ -111,7 +110,6 @@ enum NodeType {
111 NodeTypeNumberLiteral,110 NodeTypeNumberLiteral,
112 NodeTypeStringLiteral,111 NodeTypeStringLiteral,
113 NodeTypeCharLiteral,112 NodeTypeCharLiteral,
114 NodeTypeUnreachable,
115 NodeTypeSymbol,113 NodeTypeSymbol,
116 NodeTypePrefixOpExpr,114 NodeTypePrefixOpExpr,
117 NodeTypeFnCallExpr,115 NodeTypeFnCallExpr,
...@@ -119,7 +117,6 @@ enum NodeType {...@@ -119,7 +117,6 @@ enum NodeType {
119 NodeTypeSliceExpr,117 NodeTypeSliceExpr,
120 NodeTypeFieldAccessExpr,118 NodeTypeFieldAccessExpr,
121 NodeTypeUse,119 NodeTypeUse,
122 NodeTypeVoid,
123 NodeTypeBoolLiteral,120 NodeTypeBoolLiteral,
124 NodeTypeNullLiteral,121 NodeTypeNullLiteral,
125 NodeTypeIfBoolExpr,122 NodeTypeIfBoolExpr,
...@@ -132,10 +129,9 @@ enum NodeType {...@@ -132,10 +129,9 @@ enum NodeType {
132 NodeTypeAsmExpr,129 NodeTypeAsmExpr,
133 NodeTypeStructDecl,130 NodeTypeStructDecl,
134 NodeTypeStructField,131 NodeTypeStructField,
135 NodeTypeStructValueExpr,132 NodeTypeContainerInitExpr,
136 NodeTypeStructValueField,133 NodeTypeStructValueField,
137 NodeTypeCompilerFnExpr,134 NodeTypeArrayType,
138 NodeTypeCompilerFnType,
139};135};
140136
141struct AstNodeRoot {137struct AstNodeRoot {
...@@ -185,30 +181,10 @@ struct AstNodeFnDecl {...@@ -185,30 +181,10 @@ struct AstNodeFnDecl {
185struct AstNodeParamDecl {181struct AstNodeParamDecl {
186 Buf name;182 Buf name;
187 AstNode *type;183 AstNode *type;
188
189 // populated by semantic analyzer
190 VariableTableEntry *variable;
191};
192
193enum AstNodeTypeType {
194 AstNodeTypeTypePrimitive,
195 AstNodeTypeTypePointer,
196 AstNodeTypeTypeArray,
197 AstNodeTypeTypeMaybe,
198 AstNodeTypeTypeCompilerExpr,
199};
200
201struct AstNodeType {
202 AstNodeTypeType type;
203 Buf primitive_name;
204 AstNode *child_type;
205 AstNode *array_size; // can be null
206 bool is_const;
207 bool is_noalias;184 bool is_noalias;
208 AstNode *compiler_expr;
209185
210 // populated by semantic analyzer186 // populated by semantic analyzer
211 TypeTableEntry *entry;187 VariableTableEntry *variable;
212};188};
213189
214struct AstNodeBlock {190struct AstNodeBlock {
...@@ -295,6 +271,7 @@ struct AstNodeFnCallExpr {...@@ -295,6 +271,7 @@ struct AstNodeFnCallExpr {
295 // populated by semantic analyzer:271 // populated by semantic analyzer:
296 BuiltinFnEntry *builtin_fn;272 BuiltinFnEntry *builtin_fn;
297 Expr resolved_expr;273 Expr resolved_expr;
274 NumLitCodeGen resolved_num_lit;
298};275};
299276
300struct AstNodeArrayAccessExpr {277struct AstNodeArrayAccessExpr {
...@@ -360,6 +337,7 @@ enum PrefixOp {...@@ -360,6 +337,7 @@ enum PrefixOp {
360 PrefixOpAddressOf,337 PrefixOpAddressOf,
361 PrefixOpConstAddressOf,338 PrefixOpConstAddressOf,
362 PrefixOpDereference,339 PrefixOpDereference,
340 PrefixOpMaybe,
363};341};
364342
365struct AstNodePrefixOpExpr {343struct AstNodePrefixOpExpr {
...@@ -537,30 +515,19 @@ struct AstNodeStructValueField {...@@ -537,30 +515,19 @@ struct AstNodeStructValueField {
537 TypeStructField *type_struct_field;515 TypeStructField *type_struct_field;
538};516};
539517
540struct AstNodeStructValueExpr {518enum ContainerInitKind {
541 AstNode *type;519 ContainerInitKindStruct,
542 ZigList<AstNode *> fields;520 ContainerInitKindArray,
543
544 // populated by semantic analyzer
545 StructValExprCodeGen codegen;
546 Expr resolved_expr;
547};
548
549struct AstNodeCompilerFnExpr {
550 Buf name;
551 AstNode *expr;
552
553 // populated by semantic analyzer
554 Expr resolved_expr;
555};521};
556522
557struct AstNodeCompilerFnType {523struct AstNodeContainerInitExpr {
558 Buf name;
559 AstNode *type;524 AstNode *type;
525 ZigList<AstNode *> entries;
526 ContainerInitKind kind;
560527
561 // populated by semantic analyzer528 // populated by semantic analyzer
529 StructValExprCodeGen resolved_struct_val_expr;
562 Expr resolved_expr;530 Expr resolved_expr;
563 NumLitCodeGen resolved_num_lit;
564};531};
565532
566struct AstNodeNullLiteral {533struct AstNodeNullLiteral {
...@@ -569,16 +536,6 @@ struct AstNodeNullLiteral {...@@ -569,16 +536,6 @@ struct AstNodeNullLiteral {
569 Expr resolved_expr;536 Expr resolved_expr;
570};537};
571538
572struct AstNodeVoidExpr {
573 // populated by semantic analyzer
574 Expr resolved_expr;
575};
576
577struct AstNodeUnreachableExpr {
578 // populated by semantic analyzer
579 Expr resolved_expr;
580};
581
582struct AstNodeSymbolExpr {539struct AstNodeSymbolExpr {
583 Buf symbol;540 Buf symbol;
584541
...@@ -603,6 +560,15 @@ struct AstNodeContinueExpr {...@@ -603,6 +560,15 @@ struct AstNodeContinueExpr {
603 Expr resolved_expr;560 Expr resolved_expr;
604};561};
605562
563struct AstNodeArrayType {
564 AstNode *size;
565 AstNode *child_type;
566 bool is_const;
567
568 // populated by semantic analyzer
569 Expr resolved_expr;
570};
571
606struct AstNode {572struct AstNode {
607 enum NodeType type;573 enum NodeType type;
608 int line;574 int line;
...@@ -615,7 +581,6 @@ struct AstNode {...@@ -615,7 +581,6 @@ struct AstNode {
615 AstNodeFnDef fn_def;581 AstNodeFnDef fn_def;
616 AstNodeFnDecl fn_decl;582 AstNodeFnDecl fn_decl;
617 AstNodeFnProto fn_proto;583 AstNodeFnProto fn_proto;
618 AstNodeType type;
619 AstNodeParamDecl param_decl;584 AstNodeParamDecl param_decl;
620 AstNodeBlock block;585 AstNodeBlock block;
621 AstNodeReturnExpr return_expr;586 AstNodeReturnExpr return_expr;
...@@ -641,17 +606,14 @@ struct AstNode {...@@ -641,17 +606,14 @@ struct AstNode {
641 AstNodeStringLiteral string_literal;606 AstNodeStringLiteral string_literal;
642 AstNodeCharLiteral char_literal;607 AstNodeCharLiteral char_literal;
643 AstNodeNumberLiteral number_literal;608 AstNodeNumberLiteral number_literal;
644 AstNodeStructValueExpr struct_val_expr;609 AstNodeContainerInitExpr container_init_expr;
645 AstNodeStructValueField struct_val_field;610 AstNodeStructValueField struct_val_field;
646 AstNodeCompilerFnExpr compiler_fn_expr;
647 AstNodeCompilerFnType compiler_fn_type;
648 AstNodeNullLiteral null_literal;611 AstNodeNullLiteral null_literal;
649 AstNodeVoidExpr void_expr;
650 AstNodeUnreachableExpr unreachable_expr;
651 AstNodeSymbolExpr symbol_expr;612 AstNodeSymbolExpr symbol_expr;
652 AstNodeBoolLiteral bool_literal;613 AstNodeBoolLiteral bool_literal;
653 AstNodeBreakExpr break_expr;614 AstNodeBreakExpr break_expr;
654 AstNodeContinueExpr continue_expr;615 AstNodeContinueExpr continue_expr;
616 AstNodeArrayType array_type;
655 } data;617 } data;
656};618};
657619
...@@ -670,7 +632,6 @@ struct AsmToken {...@@ -670,7 +632,6 @@ struct AsmToken {
670struct TypeTableEntryPointer {632struct TypeTableEntryPointer {
671 TypeTableEntry *child_type;633 TypeTableEntry *child_type;
672 bool is_const;634 bool is_const;
673 bool is_noalias;
674};635};
675636
676struct TypeTableEntryInt {637struct TypeTableEntryInt {
...@@ -770,8 +731,8 @@ struct TypeTableEntry {...@@ -770,8 +731,8 @@ struct TypeTableEntry {
770 } data;731 } data;
771732
772 // use these fields to make sure we don't duplicate type table entries for the same type733 // use these fields to make sure we don't duplicate type table entries for the same type
773 TypeTableEntry *pointer_parent[2][2]; // 0 - const. 1 - noalias734 TypeTableEntry *pointer_parent[2];
774 TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias735 TypeTableEntry *unknown_size_array_parent[2];
775 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;736 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
776 TypeTableEntry *maybe_parent;737 TypeTableEntry *maybe_parent;
777 TypeTableEntry *meta_parent;738 TypeTableEntry *meta_parent;
...@@ -830,6 +791,11 @@ enum BuiltinFnId {...@@ -830,6 +791,11 @@ enum BuiltinFnId {
830 BuiltinFnIdArithmeticWithOverflow,791 BuiltinFnIdArithmeticWithOverflow,
831 BuiltinFnIdMemcpy,792 BuiltinFnIdMemcpy,
832 BuiltinFnIdMemset,793 BuiltinFnIdMemset,
794 BuiltinFnIdSizeof,
795 BuiltinFnIdMaxValue,
796 BuiltinFnIdMinValue,
797 BuiltinFnIdValueCount,
798 BuiltinFnIdTypeof,
833};799};
834800
835struct BuiltinFnEntry {801struct BuiltinFnEntry {
src/analyze.cpp+570-576
...@@ -15,10 +15,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -15,10 +15,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
15 TypeTableEntry *expected_type, AstNode *node);15 TypeTableEntry *expected_type, AstNode *node);
16static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,16static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
17 AstNode *node, AstNodeNumberLiteral *out_number_literal);17 AstNode *node, AstNodeNumberLiteral *out_number_literal);
18static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node);
19static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,18static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
20 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);19 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
21static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);20static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
21static TypeTableEntry *unwrapped_node_type(AstNode *node);
2222
23static AstNode *first_executing_node(AstNode *node) {23static AstNode *first_executing_node(AstNode *node) {
24 switch (node->type) {24 switch (node->type) {
...@@ -40,7 +40,6 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -40,7 +40,6 @@ static AstNode *first_executing_node(AstNode *node) {
40 case NodeTypeFnDef:40 case NodeTypeFnDef:
41 case NodeTypeFnDecl:41 case NodeTypeFnDecl:
42 case NodeTypeParamDecl:42 case NodeTypeParamDecl:
43 case NodeTypeType:
44 case NodeTypeBlock:43 case NodeTypeBlock:
45 case NodeTypeExternBlock:44 case NodeTypeExternBlock:
46 case NodeTypeDirective:45 case NodeTypeDirective:
...@@ -49,11 +48,9 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -49,11 +48,9 @@ static AstNode *first_executing_node(AstNode *node) {
49 case NodeTypeNumberLiteral:48 case NodeTypeNumberLiteral:
50 case NodeTypeStringLiteral:49 case NodeTypeStringLiteral:
51 case NodeTypeCharLiteral:50 case NodeTypeCharLiteral:
52 case NodeTypeUnreachable:
53 case NodeTypeSymbol:51 case NodeTypeSymbol:
54 case NodeTypePrefixOpExpr:52 case NodeTypePrefixOpExpr:
55 case NodeTypeUse:53 case NodeTypeUse:
56 case NodeTypeVoid:
57 case NodeTypeBoolLiteral:54 case NodeTypeBoolLiteral:
58 case NodeTypeNullLiteral:55 case NodeTypeNullLiteral:
59 case NodeTypeIfBoolExpr:56 case NodeTypeIfBoolExpr:
...@@ -65,11 +62,10 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -65,11 +62,10 @@ static AstNode *first_executing_node(AstNode *node) {
65 case NodeTypeAsmExpr:62 case NodeTypeAsmExpr:
66 case NodeTypeStructDecl:63 case NodeTypeStructDecl:
67 case NodeTypeStructField:64 case NodeTypeStructField:
68 case NodeTypeStructValueExpr:
69 case NodeTypeStructValueField:65 case NodeTypeStructValueField:
70 case NodeTypeWhileExpr:66 case NodeTypeWhileExpr:
71 case NodeTypeCompilerFnExpr:67 case NodeTypeContainerInitExpr:
72 case NodeTypeCompilerFnType:68 case NodeTypeArrayType:
73 return node;69 return node;
74 }70 }
75 zig_panic("unreachable");71 zig_panic("unreachable");
...@@ -188,8 +184,9 @@ static TypeTableEntry *get_meta_type(CodeGen *g, TypeTableEntry *child_type) {...@@ -188,8 +184,9 @@ static TypeTableEntry *get_meta_type(CodeGen *g, TypeTableEntry *child_type) {
188 }184 }
189}185}
190186
191TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias) {187TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
192 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)];188 assert(child_type->id != TypeTableEntryIdInvalid);
189 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
193 if (*parent_pointer) {190 if (*parent_pointer) {
194 return *parent_pointer;191 return *parent_pointer;
195 } else {192 } else {
...@@ -197,9 +194,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -197,9 +194,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
197 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);194 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
198195
199 const char *const_str = is_const ? "const " : "";196 const char *const_str = is_const ? "const " : "";
200 const char *noalias_str = is_noalias ? "noalias " : "";
201 buf_resize(&entry->name, 0);197 buf_resize(&entry->name, 0);
202 buf_appendf(&entry->name, "&%s%s%s", const_str, noalias_str, buf_ptr(&child_type->name));198 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));
203199
204 entry->size_in_bits = g->pointer_size_bytes * 8;200 entry->size_in_bits = g->pointer_size_bytes * 8;
205 entry->align_in_bits = g->pointer_size_bytes * 8;201 entry->align_in_bits = g->pointer_size_bytes * 8;
...@@ -208,14 +204,13 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool...@@ -208,14 +204,13 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
208 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));204 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
209 entry->data.pointer.child_type = child_type;205 entry->data.pointer.child_type = child_type;
210 entry->data.pointer.is_const = is_const;206 entry->data.pointer.is_const = is_const;
211 entry->data.pointer.is_noalias = is_noalias;
212207
213 *parent_pointer = entry;208 *parent_pointer = entry;
214 return entry;209 return entry;
215 }210 }
216}211}
217212
218static TypeTableEntry *get_maybe_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *child_type) {213static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
219 if (child_type->maybe_parent) {214 if (child_type->maybe_parent) {
220 TypeTableEntry *entry = child_type->maybe_parent;215 TypeTableEntry *entry = child_type->maybe_parent;
221 return entry;216 return entry;
...@@ -293,9 +288,10 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,...@@ -293,9 +288,10 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
293}288}
294289
295static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import,290static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry *import,
296 TypeTableEntry *child_type, bool is_const, bool is_noalias)291 TypeTableEntry *child_type, bool is_const)
297{292{
298 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)];293 assert(child_type->id != TypeTableEntryIdInvalid);
294 TypeTableEntry **parent_pointer = &child_type->unknown_size_array_parent[(is_const ? 1 : 0)];
299 if (*parent_pointer) {295 if (*parent_pointer) {
300 return *parent_pointer;296 return *parent_pointer;
301 } else {297 } else {
...@@ -305,7 +301,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry...@@ -305,7 +301,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
305 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));301 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
306 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));302 entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name));
307303
308 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const, is_noalias);304 TypeTableEntry *pointer_type = get_pointer_to_type(g, child_type, is_const);
309305
310 unsigned element_count = 2;306 unsigned element_count = 2;
311 LLVMTypeRef element_types[] = {307 LLVMTypeRef element_types[] = {
...@@ -343,6 +339,25 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry...@@ -343,6 +339,25 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
343 }339 }
344}340}
345341
342// like analyze expression, but expects a type. creates an error if resulting type is
343// not a meta type. unwraps it if it is.
344static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
345 AstNode *node)
346{
347 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, node);
348 if (type_entry->id == TypeTableEntryIdInvalid) {
349 return type_entry;
350 } else if (type_entry->id == TypeTableEntryIdMetaType) {
351 return type_entry->data.meta_type.child_type;
352 } else {
353 add_node_error(g, first_executing_node(node),
354 buf_sprintf("expected type, found expression"));
355 get_resolved_expr(node)->type_entry = g->builtin_types.entry_invalid;
356 return g->builtin_types.entry_invalid;
357 }
358}
359
360
346static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,361static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
347 AstNode *node, AstNodeNumberLiteral *out_number_literal)362 AstNode *node, AstNodeNumberLiteral *out_number_literal)
348{363{
...@@ -436,6 +451,40 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,...@@ -436,6 +451,40 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
436 zig_unreachable();451 zig_unreachable();
437}452}
438453
454static TypeTableEntry *eval_const_expr_fn_call(CodeGen *g, BlockContext *context,
455 AstNode *node, AstNodeNumberLiteral *out_number_literal)
456{
457 if (!node->data.fn_call_expr.is_builtin) {
458 return g->builtin_types.entry_invalid;
459 }
460
461 switch (node->data.fn_call_expr.builtin_fn->id) {
462 case BuiltinFnIdInvalid:
463 zig_unreachable();
464 case BuiltinFnIdArithmeticWithOverflow:
465 case BuiltinFnIdMemcpy:
466 case BuiltinFnIdMemset:
467 return g->builtin_types.entry_invalid;
468 case BuiltinFnIdSizeof:
469 {
470 AstNode *type_node = node->data.fn_call_expr.params.at(0);
471 TypeTableEntry *target_type = unwrapped_node_type(type_node);
472 out_number_literal->overflow = false;
473 out_number_literal->data.x_uint = target_type->size_in_bits / 8;
474 out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint);
475 return get_resolved_expr(node)->type_entry;
476 }
477 case BuiltinFnIdMaxValue:
478 case BuiltinFnIdMinValue:
479 zig_panic("TODO eval_const_expr_fn_call max/min value");
480 case BuiltinFnIdValueCount:
481 zig_panic("TODO eval_const_expr_fn_call value_count");
482 case BuiltinFnIdTypeof:
483 return get_resolved_expr(node)->type_entry;
484 }
485 zig_unreachable();
486}
487
439static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,488static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
440 AstNode *node, AstNodeNumberLiteral *out_number_literal)489 AstNode *node, AstNodeNumberLiteral *out_number_literal)
441{490{
...@@ -450,175 +499,25 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,...@@ -450,175 +499,25 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
450 return get_resolved_expr(node)->type_entry;499 return get_resolved_expr(node)->type_entry;
451 case NodeTypeBinOpExpr:500 case NodeTypeBinOpExpr:
452 return eval_const_expr_bin_op(g, context, node, out_number_literal);501 return eval_const_expr_bin_op(g, context, node, out_number_literal);
453 case NodeTypeCompilerFnType:
454 {
455 Buf *name = &node->data.compiler_fn_type.name;
456 TypeTableEntry *expr_type = get_resolved_expr(node)->type_entry;
457 if (buf_eql_str(name, "sizeof")) {
458 TypeTableEntry *target_type = node->data.compiler_fn_type.type->data.type.entry;
459 out_number_literal->overflow = false;
460 out_number_literal->data.x_uint = target_type->size_in_bits / 8;
461 out_number_literal->kind = get_number_literal_kind_unsigned(out_number_literal->data.x_uint);
462
463 return expr_type;
464 } else if (buf_eql_str(name, "max_value")) {
465 zig_panic("TODO eval_const_expr max_value");
466 } else if (buf_eql_str(name, "min_value")) {
467 zig_panic("TODO eval_const_expr min_value");
468 } else if (buf_eql_str(name, "value_count")) {
469 zig_panic("TODO eval_const_expr value_count");
470 } else {
471 return g->builtin_types.entry_invalid;
472 }
473 break;
474 }
475 case NodeTypeSymbol:502 case NodeTypeSymbol:
476 {503 {
477 VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol);504 VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol);
478 assert(var);505 assert(var);
479 AstNode *decl_node = var->decl_node;506 AstNode *decl_node = var->decl_node;
480 AstNode *expr_node = decl_node->data.variable_declaration.expr;507 AstNode *expr_node = decl_node->data.variable_declaration.expr;
481 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;508 if (expr_node) {
482 return eval_const_expr(g, next_context, expr_node, out_number_literal);509 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
483 }510 return eval_const_expr(g, next_context, expr_node, out_number_literal);
484 default:
485 return g->builtin_types.entry_invalid;
486 }
487}
488
489static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import,
490 BlockContext *context, bool noalias_allowed)
491{
492 assert(node->type == NodeTypeType);
493 switch (node->data.type.type) {
494 case AstNodeTypeTypePrimitive:
495 {
496 Buf *name = &node->data.type.primitive_name;
497 auto table_entry = import->block_context->type_table.maybe_get(name);
498 if (!table_entry) {
499 table_entry = g->primitive_type_table.maybe_get(name);
500 }
501 if (table_entry) {
502 node->data.type.entry = table_entry->value;
503 } else {
504 add_node_error(g, node,
505 buf_sprintf("invalid type name: '%s'", buf_ptr(name)));
506 node->data.type.entry = g->builtin_types.entry_invalid;
507 }
508 return node->data.type.entry;
509 }
510 case AstNodeTypeTypePointer:
511 {
512 bool use_noalias = false;
513 if (node->data.type.is_noalias) {
514 if (!noalias_allowed) {
515 add_node_error(g, node,
516 buf_create_from_str("invalid noalias qualifier"));
517 } else {
518 use_noalias = true;
519 }
520 }
521
522 resolve_type(g, node->data.type.child_type, import, context, false);
523 TypeTableEntry *child_type = node->data.type.child_type->data.type.entry;
524 assert(child_type);
525 if (child_type->id == TypeTableEntryIdUnreachable) {
526 add_node_error(g, node,
527 buf_create_from_str("pointer to unreachable not allowed"));
528 node->data.type.entry = g->builtin_types.entry_invalid;
529 return node->data.type.entry;
530 } else if (child_type->id == TypeTableEntryIdInvalid) {
531 node->data.type.entry = child_type;
532 return child_type;
533 } else {
534 node->data.type.entry = get_pointer_to_type(g, child_type, node->data.type.is_const, use_noalias);
535 return node->data.type.entry;
536 }
537 }
538 case AstNodeTypeTypeArray:
539 {
540 AstNode *size_node = node->data.type.array_size;
541
542 bool use_noalias = false;
543 if (node->data.type.is_noalias) {
544 if (!noalias_allowed || size_node) {
545 add_node_error(g, node,
546 buf_create_from_str("invalid noalias qualifier"));
547 } else {
548 use_noalias = true;
549 }
550 }
551
552 TypeTableEntry *child_type = resolve_type(g, node->data.type.child_type, import, context, false);
553 if (child_type->id == TypeTableEntryIdUnreachable) {
554 add_node_error(g, node,
555 buf_create_from_str("array of unreachable not allowed"));
556 node->data.type.entry = g->builtin_types.entry_invalid;
557 return node->data.type.entry;
558 }
559
560 if (size_node) {
561 TypeTableEntry *size_type = analyze_expression(g, import, context,
562 g->builtin_types.entry_usize, size_node);
563 if (size_type->id == TypeTableEntryIdInvalid) {
564 node->data.type.entry = g->builtin_types.entry_invalid;
565 return node->data.type.entry;
566 }
567
568 AstNodeNumberLiteral number_literal;
569 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
570
571 if (resolved_type->id == TypeTableEntryIdInt) {
572 if (resolved_type->data.integral.is_signed) {
573 add_node_error(g, size_node,
574 buf_create_from_str("array size must be unsigned integer"));
575 node->data.type.entry = g->builtin_types.entry_invalid;
576 } else {
577 node->data.type.entry = get_array_type(g, import, child_type, number_literal.data.x_uint);
578 }
579 } else {
580 add_node_error(g, size_node,
581 buf_create_from_str("unable to resolve constant expression"));
582 node->data.type.entry = g->builtin_types.entry_invalid;
583 }
584 return node->data.type.entry;
585 } else {
586 node->data.type.entry = get_unknown_size_array_type(g, import, child_type,
587 node->data.type.is_const, use_noalias);
588 return node->data.type.entry;
589 }
590
591 }
592 case AstNodeTypeTypeMaybe:
593 {
594 resolve_type(g, node->data.type.child_type, import, context, false);
595 TypeTableEntry *child_type = node->data.type.child_type->data.type.entry;
596 assert(child_type);
597 if (child_type->id == TypeTableEntryIdUnreachable) {
598 add_node_error(g, node,
599 buf_create_from_str("maybe unreachable type not allowed"));
600 } else if (child_type->id == TypeTableEntryIdInvalid) {
601 return child_type;
602 }
603 node->data.type.entry = get_maybe_type(g, import, child_type);
604 return node->data.type.entry;
605 }
606 case AstNodeTypeTypeCompilerExpr:
607 {
608 AstNode *compiler_expr_node = node->data.type.compiler_expr;
609 Buf *fn_name = &compiler_expr_node->data.compiler_fn_expr.name;
610 if (buf_eql_str(fn_name, "typeof")) {
611 node->data.type.entry = analyze_expression(g, import, context, nullptr,
612 compiler_expr_node->data.compiler_fn_expr.expr);
613 } else {511 } else {
614 add_node_error(g, node,512 // can't eval it
615 buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name)));513 return g->builtin_types.entry_invalid;
616 node->data.type.entry = g->builtin_types.entry_invalid;
617 }514 }
618 return node->data.type.entry;
619 }515 }
516 case NodeTypeFnCallExpr:
517 return eval_const_expr_fn_call(g, context, node, out_number_literal);
518 default:
519 return g->builtin_types.entry_invalid;
620 }520 }
621 zig_unreachable();
622}521}
623522
624static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,523static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,
...@@ -654,8 +553,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -654,8 +553,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
654 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {553 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
655 AstNode *child = node->data.fn_proto.params.at(i);554 AstNode *child = node->data.fn_proto.params.at(i);
656 assert(child->type == NodeTypeParamDecl);555 assert(child->type == NodeTypeParamDecl);
657 TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type,556 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
658 import, import->block_context, true);557 child->data.param_decl.type);
558
659 if (type_entry->id == TypeTableEntryIdUnreachable) {559 if (type_entry->id == TypeTableEntryIdUnreachable) {
660 add_node_error(g, child->data.param_decl.type,560 add_node_error(g, child->data.param_decl.type,
661 buf_sprintf("parameter of type 'unreachable' not allowed"));561 buf_sprintf("parameter of type 'unreachable' not allowed"));
...@@ -667,7 +567,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -667,7 +567,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
667 }567 }
668 }568 }
669569
670 resolve_type(g, node->data.fn_proto.return_type, import, import->block_context, true);570 analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);
671}571}
672572
673static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {573static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) {
...@@ -729,8 +629,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -729,8 +629,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
729 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);629 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
730 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];630 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
731 type_enum_field->name = &field_node->data.struct_field.name;631 type_enum_field->name = &field_node->data.struct_field.name;
732 type_enum_field->type_entry = resolve_type(g, field_node->data.struct_field.type,632 type_enum_field->type_entry = analyze_type_expr(g, import, import->block_context,
733 import, import->block_context, false);633 field_node->data.struct_field.type);
734 type_enum_field->value = i;634 type_enum_field->value = i;
735635
736 di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i);636 di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i);
...@@ -815,7 +715,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt...@@ -815,7 +715,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
815 biggest_align_in_bits,715 biggest_align_in_bits,
816 tag_type_entry->size_in_bits, 0, union_di_type);716 tag_type_entry->size_in_bits, 0, union_di_type);
817717
818 // create debug type for root struct 718 // create debug type for root struct
819 LLVMZigDIType *di_root_members[] = {719 LLVMZigDIType *di_root_members[] = {
820 tag_member_di_type,720 tag_member_di_type,
821 union_member_di_type,721 union_member_di_type,
...@@ -893,8 +793,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -893,8 +793,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
893 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);793 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
894 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];794 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
895 type_struct_field->name = &field_node->data.struct_field.name;795 type_struct_field->name = &field_node->data.struct_field.name;
896 type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type,796 type_struct_field->type_entry = analyze_type_expr(g, import, import->block_context,
897 import, import->block_context, false);797 field_node->data.struct_field.type);
898 type_struct_field->src_index = i;798 type_struct_field->src_index = i;
899 type_struct_field->gen_index = -1;799 type_struct_field->gen_index = -1;
900800
...@@ -1144,7 +1044,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1144,7 +1044,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1144 case NodeTypeFnDef:1044 case NodeTypeFnDef:
1145 case NodeTypeDirective:1045 case NodeTypeDirective:
1146 case NodeTypeParamDecl:1046 case NodeTypeParamDecl:
1147 case NodeTypeType:
1148 case NodeTypeFnDecl:1047 case NodeTypeFnDecl:
1149 case NodeTypeReturnExpr:1048 case NodeTypeReturnExpr:
1150 case NodeTypeRoot:1049 case NodeTypeRoot:
...@@ -1156,8 +1055,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1156,8 +1055,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1156 case NodeTypeNumberLiteral:1055 case NodeTypeNumberLiteral:
1157 case NodeTypeStringLiteral:1056 case NodeTypeStringLiteral:
1158 case NodeTypeCharLiteral:1057 case NodeTypeCharLiteral:
1159 case NodeTypeUnreachable:
1160 case NodeTypeVoid:
1161 case NodeTypeBoolLiteral:1058 case NodeTypeBoolLiteral:
1162 case NodeTypeNullLiteral:1059 case NodeTypeNullLiteral:
1163 case NodeTypeSymbol:1060 case NodeTypeSymbol:
...@@ -1173,10 +1070,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1173,10 +1070,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1173 case NodeTypeAsmExpr:1070 case NodeTypeAsmExpr:
1174 case NodeTypeFieldAccessExpr:1071 case NodeTypeFieldAccessExpr:
1175 case NodeTypeStructField:1072 case NodeTypeStructField:
1176 case NodeTypeStructValueExpr:
1177 case NodeTypeStructValueField:1073 case NodeTypeStructValueField:
1178 case NodeTypeCompilerFnExpr:1074 case NodeTypeContainerInitExpr:
1179 case NodeTypeCompilerFnType:1075 case NodeTypeArrayType:
1180 zig_unreachable();1076 zig_unreachable();
1181 }1077 }
1182}1078}
...@@ -1186,13 +1082,22 @@ static FnTableEntry *get_context_fn_entry(BlockContext *context) {...@@ -1186,13 +1082,22 @@ static FnTableEntry *get_context_fn_entry(BlockContext *context) {
1186 return context->fn_entry;1082 return context->fn_entry;
1187}1083}
11881084
1085static TypeTableEntry *unwrapped_node_type(AstNode *node) {
1086 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;
1087 if (meta_type_entry->id == TypeTableEntryIdInvalid) {
1088 return meta_type_entry;
1089 } else {
1090 assert(meta_type_entry->id == TypeTableEntryIdMetaType);
1091 return meta_type_entry->data.meta_type.child_type;
1092 }
1093}
1094
1189static TypeTableEntry *get_return_type(BlockContext *context) {1095static TypeTableEntry *get_return_type(BlockContext *context) {
1190 FnTableEntry *fn_entry = get_context_fn_entry(context);1096 FnTableEntry *fn_entry = get_context_fn_entry(context);
1191 AstNode *fn_proto_node = fn_entry->proto_node;1097 AstNode *fn_proto_node = fn_entry->proto_node;
1192 assert(fn_proto_node->type == NodeTypeFnProto);1098 assert(fn_proto_node->type == NodeTypeFnProto);
1193 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;1099 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
1194 assert(return_type_node->type == NodeTypeType);1100 return unwrapped_node_type(return_type_node);
1195 return return_type_node->data.type.entry;
1196}1101}
11971102
1198static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) {1103static bool num_lit_fits_in_other_type(CodeGen *g, TypeTableEntry *literal_type, TypeTableEntry *other_type) {
...@@ -1553,6 +1458,114 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp...@@ -1553,6 +1458,114 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
1553 return enum_type;1458 return enum_type;
1554}1459}
15551460
1461static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name, int *index) {
1462 assert(type_entry->id == TypeTableEntryIdStruct);
1463 for (int i = 0; i < type_entry->data.structure.field_count; i += 1) {
1464 TypeStructField *field = &type_entry->data.structure.fields[i];
1465 if (buf_eql_buf(field->name, name)) {
1466 *index = i;
1467 return field;
1468 }
1469 }
1470 return nullptr;
1471}
1472
1473static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1474 AstNode *node)
1475{
1476 assert(node->type == NodeTypeContainerInitExpr);
1477
1478 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
1479
1480 ContainerInitKind kind = container_init_expr->kind;
1481
1482 TypeTableEntry *container_type = analyze_type_expr(g, import, context, container_init_expr->type);
1483
1484 if (container_type->id == TypeTableEntryIdInvalid) {
1485 return container_type;
1486 } else if (container_type->id == TypeTableEntryIdStruct) {
1487 switch (kind) {
1488 case ContainerInitKindStruct:
1489 {
1490 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
1491 codegen->type_entry = container_type;
1492 codegen->source_node = node;
1493 context->struct_val_expr_alloca_list.append(codegen);
1494
1495
1496 int expr_field_count = container_init_expr->entries.length;
1497 int actual_field_count = container_type->data.structure.field_count;
1498
1499 int *field_use_counts = allocate<int>(actual_field_count);
1500 for (int i = 0; i < expr_field_count; i += 1) {
1501 AstNode *val_field_node = container_init_expr->entries.at(i);
1502 assert(val_field_node->type == NodeTypeStructValueField);
1503
1504 int field_index;
1505 TypeStructField *type_field = find_struct_type_field(container_type,
1506 &val_field_node->data.struct_val_field.name, &field_index);
1507
1508 if (!type_field) {
1509 add_node_error(g, val_field_node,
1510 buf_sprintf("no member named '%s' in '%s'",
1511 buf_ptr(&val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
1512 continue;
1513 }
1514
1515 field_use_counts[field_index] += 1;
1516 if (field_use_counts[field_index] > 1) {
1517 add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
1518 continue;
1519 }
1520
1521 val_field_node->data.struct_val_field.type_struct_field = type_field;
1522
1523 analyze_expression(g, import, context, type_field->type_entry,
1524 val_field_node->data.struct_val_field.expr);
1525 }
1526
1527 for (int i = 0; i < actual_field_count; i += 1) {
1528 if (field_use_counts[i] == 0) {
1529 add_node_error(g, node,
1530 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
1531 }
1532 }
1533 break;
1534 }
1535 case ContainerInitKindArray:
1536 add_node_error(g, node,
1537 buf_sprintf("struct '%s' does not support array initialization syntax",
1538 buf_ptr(&container_type->name)));
1539 break;
1540 }
1541 return container_type;
1542 } else if (container_type->id == TypeTableEntryIdArray) {
1543 zig_panic("TODO array container init");
1544 return container_type;
1545 } else if (container_type->id == TypeTableEntryIdEnum) {
1546 zig_panic("TODO enum container init");
1547 return container_type;
1548 } else if (container_type->id == TypeTableEntryIdVoid) {
1549 if (container_init_expr->entries.length != 0) {
1550 add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
1551 return g->builtin_types.entry_invalid;
1552 } else {
1553 return container_type;
1554 }
1555 } else if (container_type->id == TypeTableEntryIdUnreachable) {
1556 if (container_init_expr->entries.length != 0) {
1557 add_node_error(g, node, buf_sprintf("unreachable expression expects no arguments"));
1558 return g->builtin_types.entry_invalid;
1559 } else {
1560 return container_type;
1561 }
1562 } else {
1563 add_node_error(g, node,
1564 buf_sprintf("type '%s' does not support initialization syntax", buf_ptr(&container_type->name)));
1565 return g->builtin_types.entry_invalid;
1566 }
1567}
1568
1556static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,1569static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1557 AstNode *node)1570 AstNode *node)
1558{1571{
...@@ -1585,7 +1598,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -1585,7 +1598,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
1585 return_type = g->builtin_types.entry_usize;1598 return_type = g->builtin_types.entry_usize;
1586 } else if (buf_eql_str(name, "ptr")) {1599 } else if (buf_eql_str(name, "ptr")) {
1587 // TODO determine whether the pointer should be const1600 // TODO determine whether the pointer should be const
1588 return_type = get_pointer_to_type(g, struct_type->data.array.child_type, false, false);1601 return_type = get_pointer_to_type(g, struct_type->data.array.child_type, false);
1589 } else {1602 } else {
1590 add_node_error(g, node,1603 add_node_error(g, node,
1591 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),1604 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),
...@@ -1623,16 +1636,16 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,...@@ -1623,16 +1636,16 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
1623 return_type = g->builtin_types.entry_invalid;1636 return_type = g->builtin_types.entry_invalid;
1624 } else if (array_type->id == TypeTableEntryIdArray) {1637 } else if (array_type->id == TypeTableEntryIdArray) {
1625 return_type = get_unknown_size_array_type(g, import, array_type->data.array.child_type,1638 return_type = get_unknown_size_array_type(g, import, array_type->data.array.child_type,
1626 node->data.slice_expr.is_const, false);1639 node->data.slice_expr.is_const);
1627 } else if (array_type->id == TypeTableEntryIdPointer) {1640 } else if (array_type->id == TypeTableEntryIdPointer) {
1628 return_type = get_unknown_size_array_type(g, import, array_type->data.pointer.child_type,1641 return_type = get_unknown_size_array_type(g, import, array_type->data.pointer.child_type,
1629 node->data.slice_expr.is_const, false);1642 node->data.slice_expr.is_const);
1630 } else if (array_type->id == TypeTableEntryIdStruct &&1643 } else if (array_type->id == TypeTableEntryIdStruct &&
1631 array_type->data.structure.is_unknown_size_array)1644 array_type->data.structure.is_unknown_size_array)
1632 {1645 {
1633 return_type = get_unknown_size_array_type(g, import,1646 return_type = get_unknown_size_array_type(g, import,
1634 array_type->data.structure.fields[0].type_entry->data.pointer.child_type,1647 array_type->data.structure.fields[0].type_entry->data.pointer.child_type,
1635 node->data.slice_expr.is_const, false);1648 node->data.slice_expr.is_const);
1636 } else {1649 } else {
1637 add_node_error(g, node,1650 add_node_error(g, node,
1638 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));1651 buf_sprintf("slice of non-array type '%s'", buf_ptr(&array_type->name)));
...@@ -1687,19 +1700,24 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,...@@ -1687,19 +1700,24 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
1687 TypeTableEntry *expected_type, AstNode *node)1700 TypeTableEntry *expected_type, AstNode *node)
1688{1701{
1689 Buf *variable_name = &node->data.symbol_expr.symbol;1702 Buf *variable_name = &node->data.symbol_expr.symbol;
1703
1704 auto primitive_table_entry = g->primitive_type_table.maybe_get(variable_name);
1705 if (primitive_table_entry) {
1706 return get_meta_type(g, primitive_table_entry->value);
1707 }
1708
1690 VariableTableEntry *var = find_variable(context, variable_name);1709 VariableTableEntry *var = find_variable(context, variable_name);
1691 if (var) {1710 if (var) {
1692 return var->type;1711 return var->type;
1693 } else {
1694 TypeTableEntry *container_type = find_container(context, variable_name);
1695 if (container_type) {
1696 return get_meta_type(g, container_type);
1697 } else {
1698 add_node_error(g, node,
1699 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
1700 return g->builtin_types.entry_invalid;
1701 }
1702 }1712 }
1713
1714 TypeTableEntry *container_type = find_container(context, variable_name);
1715 if (container_type) {
1716 return get_meta_type(g, container_type);
1717 }
1718
1719 add_node_error(g, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
1720 return g->builtin_types.entry_invalid;
1703}1721}
17041722
1705static TypeTableEntry *analyze_variable_name(CodeGen *g, ImportTableEntry *import, BlockContext *context,1723static TypeTableEntry *analyze_variable_name(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -1768,7 +1786,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -1768,7 +1786,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
1768{1786{
1769 assert(node->type == NodeTypeCastExpr);1787 assert(node->type == NodeTypeCastExpr);
17701788
1771 TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context, false);1789 TypeTableEntry *wanted_type = analyze_type_expr(g, import, context, node->data.cast_expr.type);
1772 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr);1790 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr);
17731791
1774 if (wanted_type->id == TypeTableEntryIdInvalid ||1792 if (wanted_type->id == TypeTableEntryIdInvalid ||
...@@ -1833,23 +1851,22 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc...@@ -1833,23 +1851,22 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
1833 TypeTableEntry *expected_rhs_type = nullptr;1851 TypeTableEntry *expected_rhs_type = nullptr;
1834 if (lhs_node->type == NodeTypeSymbol) {1852 if (lhs_node->type == NodeTypeSymbol) {
1835 Buf *name = &lhs_node->data.symbol_expr.symbol;1853 Buf *name = &lhs_node->data.symbol_expr.symbol;
1836 VariableTableEntry *var = find_variable(block_context, name);1854 if (purpose == LValPurposeAddressOf) {
1837 if (var) {1855 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);
1838 if (purpose == LValPurposeAssign && var->is_const) {1856 } else {
1839 add_node_error(g, lhs_node,1857 VariableTableEntry *var = find_variable(block_context, name);
1840 buf_sprintf("cannot assign to constant"));1858 if (var) {
1841 expected_rhs_type = g->builtin_types.entry_invalid;1859 if (var->is_const) {
1842 } else if (purpose == LValPurposeAddressOf && var->is_const && !is_ptr_const) {1860 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
1861 expected_rhs_type = g->builtin_types.entry_invalid;
1862 } else {
1863 expected_rhs_type = var->type;
1864 }
1865 } else {
1843 add_node_error(g, lhs_node,1866 add_node_error(g, lhs_node,
1844 buf_sprintf("must use &const to get address of constant"));1867 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(name)));
1845 expected_rhs_type = g->builtin_types.entry_invalid;1868 expected_rhs_type = g->builtin_types.entry_invalid;
1846 } else {
1847 expected_rhs_type = var->type;
1848 }1869 }
1849 } else {
1850 add_node_error(g, lhs_node,
1851 buf_sprintf("use of undeclared identifier '%s'", buf_ptr(name)));
1852 expected_rhs_type = g->builtin_types.entry_invalid;
1853 }1870 }
1854 } else if (lhs_node->type == NodeTypeArrayAccessExpr) {1871 } else if (lhs_node->type == NodeTypeArrayAccessExpr) {
1855 expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node);1872 expected_rhs_type = analyze_array_access_expr(g, import, block_context, lhs_node);
...@@ -1873,13 +1890,19 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc...@@ -1873,13 +1890,19 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
1873 }1890 }
1874 } else {1891 } else {
1875 if (purpose == LValPurposeAssign) {1892 if (purpose == LValPurposeAssign) {
1876 add_node_error(g, lhs_node,1893 add_node_error(g, lhs_node, buf_sprintf("invalid assignment target"));
1877 buf_sprintf("invalid assignment target"));1894 expected_rhs_type = g->builtin_types.entry_invalid;
1878 } else if (purpose == LValPurposeAddressOf) {1895 } else if (purpose == LValPurposeAddressOf) {
1879 add_node_error(g, lhs_node,1896 TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, lhs_node);
1880 buf_sprintf("invalid addressof target"));1897 if (type_entry->id == TypeTableEntryIdInvalid) {
1898 expected_rhs_type = g->builtin_types.entry_invalid;
1899 } else if (type_entry->id == TypeTableEntryIdMetaType) {
1900 expected_rhs_type = type_entry;
1901 } else {
1902 add_node_error(g, lhs_node, buf_sprintf("invalid addressof target"));
1903 expected_rhs_type = g->builtin_types.entry_invalid;
1904 }
1881 }1905 }
1882 expected_rhs_type = g->builtin_types.entry_invalid;
1883 }1906 }
1884 assert(expected_rhs_type);1907 assert(expected_rhs_type);
1885 return expected_rhs_type;1908 return expected_rhs_type;
...@@ -1988,7 +2011,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -1988,7 +2011,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
1988{2011{
1989 TypeTableEntry *explicit_type = nullptr;2012 TypeTableEntry *explicit_type = nullptr;
1990 if (variable_declaration->type != nullptr) {2013 if (variable_declaration->type != nullptr) {
1991 explicit_type = resolve_type(g, variable_declaration->type, import, context, false);2014 explicit_type = analyze_type_expr(g, import, context, variable_declaration->type);
1992 if (explicit_type->id == TypeTableEntryIdUnreachable) {2015 if (explicit_type->id == TypeTableEntryIdUnreachable) {
1993 add_node_error(g, variable_declaration->type,2016 add_node_error(g, variable_declaration->type,
1994 buf_sprintf("variable of type 'unreachable' not allowed"));2017 buf_sprintf("variable of type 'unreachable' not allowed"));
...@@ -2109,78 +2132,46 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry...@@ -2109,78 +2132,46 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry
2109 }2132 }
2110}2133}
21112134
2112static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name, int *index) {2135static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2113 assert(type_entry->id == TypeTableEntryIdStruct);
2114 for (int i = 0; i < type_entry->data.structure.field_count; i += 1) {
2115 TypeStructField *field = &type_entry->data.structure.fields[i];
2116 if (buf_eql_buf(field->name, name)) {
2117 *index = i;
2118 return field;
2119 }
2120 }
2121 return nullptr;
2122}
2123
2124static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2125 TypeTableEntry *expected_type, AstNode *node)2136 TypeTableEntry *expected_type, AstNode *node)
2126{2137{
2127 assert(node->type == NodeTypeStructValueExpr);2138 AstNode *size_node = node->data.array_type.size;
2128
2129 AstNodeStructValueExpr *struct_val_expr = &node->data.struct_val_expr;
21302139
2131 TypeTableEntry *type_entry = resolve_type(g, struct_val_expr->type, import, context, false);2140 TypeTableEntry *child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type);
21322141
2133 if (type_entry->id == TypeTableEntryIdInvalid) {2142 if (child_type->id == TypeTableEntryIdUnreachable) {
2143 add_node_error(g, node, buf_create_from_str("array of unreachable not allowed"));
2134 return g->builtin_types.entry_invalid;2144 return g->builtin_types.entry_invalid;
2135 } else if (type_entry->id != TypeTableEntryIdStruct) {2145 } else if (child_type->id == TypeTableEntryIdInvalid) {
2136 add_node_error(g, node,
2137 buf_sprintf("type '%s' is not a struct", buf_ptr(&type_entry->name)));
2138 return g->builtin_types.entry_invalid;2146 return g->builtin_types.entry_invalid;
2139 }2147 }
21402148
2141 node->data.struct_val_expr.codegen.type_entry = type_entry;2149 if (size_node) {
2142 node->data.struct_val_expr.codegen.source_node = node;2150 TypeTableEntry *size_type = analyze_expression(g, import, context,
2143 context->struct_val_expr_alloca_list.append(&node->data.struct_val_expr.codegen);2151 g->builtin_types.entry_usize, size_node);
21442152 if (size_type->id == TypeTableEntryIdInvalid) {
2145 int expr_field_count = struct_val_expr->fields.length;2153 return g->builtin_types.entry_invalid;
2146 int actual_field_count = type_entry->data.structure.field_count;
2147
2148 int *field_use_counts = allocate<int>(actual_field_count);
2149 for (int i = 0; i < expr_field_count; i += 1) {
2150 AstNode *val_field_node = struct_val_expr->fields.at(i);
2151 assert(val_field_node->type == NodeTypeStructValueField);
2152
2153 int field_index;
2154 TypeStructField *type_field = find_struct_type_field(type_entry,
2155 &val_field_node->data.struct_val_field.name, &field_index);
2156
2157 if (!type_field) {
2158 add_node_error(g, val_field_node,
2159 buf_sprintf("no member named '%s' in '%s'",
2160 buf_ptr(&val_field_node->data.struct_val_field.name), buf_ptr(&type_entry->name)));
2161 continue;
2162 }
2163
2164 field_use_counts[field_index] += 1;
2165 if (field_use_counts[field_index] > 1) {
2166 add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
2167 continue;
2168 }2154 }
21692155
2170 val_field_node->data.struct_val_field.type_struct_field = type_field;2156 AstNodeNumberLiteral number_literal;
21712157 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
2172 analyze_expression(g, import, context, type_field->type_entry,
2173 val_field_node->data.struct_val_field.expr);
2174 }
21752158
2176 for (int i = 0; i < actual_field_count; i += 1) {2159 if (resolved_type->id == TypeTableEntryIdInt) {
2177 if (field_use_counts[i] == 0) {2160 if (resolved_type->data.integral.is_signed) {
2178 add_node_error(g, node,2161 add_node_error(g, size_node,
2179 buf_sprintf("missing field: '%s'", buf_ptr(type_entry->data.structure.fields[i].name)));2162 buf_create_from_str("array size must be unsigned integer"));
2163 return g->builtin_types.entry_invalid;
2164 } else {
2165 return get_meta_type(g, get_array_type(g, import, child_type, number_literal.data.x_uint));
2166 }
2167 } else {
2168 add_node_error(g, size_node,
2169 buf_create_from_str("unable to resolve constant expression"));
2170 return g->builtin_types.entry_invalid;
2180 }2171 }
2172 } else {
2173 return get_meta_type(g, get_unknown_size_array_type(g, import, child_type, node->data.array_type.is_const));
2181 }2174 }
2182
2183 return type_entry;
2184}2175}
21852176
2186static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2177static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
...@@ -2293,9 +2284,14 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,...@@ -2293,9 +2284,14 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
2293 node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node);2284 node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node);
2294}2285}
22952286
2296static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTableEntry *type_entry,2287static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2297 const char *err_format)2288 AstNode *node, const char *err_format)
2298{2289{
2290 assert(node->type == NodeTypeFnCallExpr);
2291 assert(node->data.fn_call_expr.params.length == 1);
2292
2293 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2294 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2299 if (type_entry->id == TypeTableEntryIdInt ||2295 if (type_entry->id == TypeTableEntryIdInt ||
2300 type_entry->id == TypeTableEntryIdFloat ||2296 type_entry->id == TypeTableEntryIdFloat ||
2301 type_entry->id == TypeTableEntryIdBool ||2297 type_entry->id == TypeTableEntryIdBool ||
...@@ -2309,54 +2305,6 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTabl...@@ -2309,54 +2305,6 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTabl
2309 }2305 }
2310}2306}
23112307
2312static TypeTableEntry *analyze_compiler_fn_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2313 TypeTableEntry *expected_type, AstNode *node)
2314{
2315 assert(node->type == NodeTypeCompilerFnType);
2316
2317 Buf *name = &node->data.compiler_fn_type.name;
2318 TypeTableEntry *type_entry = resolve_type(g, node->data.compiler_fn_type.type, import, context, false);
2319
2320 if (buf_eql_str(name, "sizeof")) {
2321 if (type_entry->id == TypeTableEntryIdInvalid) {
2322 return type_entry;
2323 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2324 add_node_error(g, node,
2325 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
2326 return g->builtin_types.entry_invalid;
2327 } else {
2328 uint64_t size_in_bytes = type_entry->size_in_bits / 8;
2329
2330 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);
2331 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2332 return resolved_type ? resolved_type : num_lit_type;
2333 }
2334 } else if (buf_eql_str(name, "min_value")) {
2335 return analyze_min_max_value(g, node, type_entry, "no min value available for type '%s'");
2336 } else if (buf_eql_str(name, "max_value")) {
2337 return analyze_min_max_value(g, node, type_entry, "no max value available for type '%s'");
2338 } else if (buf_eql_str(name, "value_count")) {
2339 if (type_entry->id == TypeTableEntryIdInvalid) {
2340 return type_entry;
2341 } else if (type_entry->id == TypeTableEntryIdEnum) {
2342 uint64_t value_count = type_entry->data.enumeration.field_count;
2343
2344 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, value_count);
2345 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2346 return resolved_type ? resolved_type : num_lit_type;
2347
2348 } else {
2349 add_node_error(g, node,
2350 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
2351 return g->builtin_types.entry_invalid;
2352 }
2353 } else {
2354 add_node_error(g, node,
2355 buf_sprintf("invalid compiler function: '%s'", buf_ptr(name)));
2356 return g->builtin_types.entry_invalid;
2357 }
2358}
2359
2360static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2308static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2361 TypeTableEntry *expected_type, AstNode *node)2309 TypeTableEntry *expected_type, AstNode *node)
2362{2310{
...@@ -2445,6 +2393,62 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -2445,6 +2393,62 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
24452393
2446 return builtin_fn->return_type;2394 return builtin_fn->return_type;
2447 }2395 }
2396 case BuiltinFnIdSizeof:
2397 {
2398 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2399 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2400 if (type_entry->id == TypeTableEntryIdInvalid) {
2401 return g->builtin_types.entry_invalid;
2402 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2403 add_node_error(g, first_executing_node(type_node),
2404 buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
2405 return g->builtin_types.entry_invalid;
2406 } else {
2407 uint64_t size_in_bytes = type_entry->size_in_bits / 8;
2408
2409 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, size_in_bytes);
2410 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2411 return resolved_type ? resolved_type : num_lit_type;
2412 }
2413 }
2414 case BuiltinFnIdMaxValue:
2415 return analyze_min_max_value(g, import, context, node, "no max value available for type '%s'");
2416 case BuiltinFnIdMinValue:
2417 return analyze_min_max_value(g, import, context, node, "no min value available for type '%s'");
2418 case BuiltinFnIdValueCount:
2419 {
2420 AstNode *type_node = node->data.fn_call_expr.params.at(0);
2421 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
2422
2423 if (type_entry->id == TypeTableEntryIdInvalid) {
2424 return type_entry;
2425 } else if (type_entry->id == TypeTableEntryIdEnum) {
2426 uint64_t value_count = type_entry->data.enumeration.field_count;
2427
2428 TypeTableEntry *num_lit_type = get_number_literal_type_unsigned(g, value_count);
2429 TypeTableEntry *resolved_type = resolve_rhs_number_literal(g, nullptr, expected_type, node, num_lit_type);
2430 return resolved_type ? resolved_type : num_lit_type;
2431
2432 } else {
2433 add_node_error(g, node,
2434 buf_sprintf("no value count available for type '%s'", buf_ptr(&type_entry->name)));
2435 return g->builtin_types.entry_invalid;
2436 }
2437 }
2438 case BuiltinFnIdTypeof:
2439 {
2440 AstNode *expr_node = node->data.fn_call_expr.params.at(0);
2441 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
2442
2443 if (type_entry->id == TypeTableEntryIdInvalid) {
2444 return g->builtin_types.entry_invalid;
2445 } else if (type_entry->id == TypeTableEntryIdMetaType) {
2446 add_node_error(g, node, buf_sprintf("expected expression, got type"));
2447 } else {
2448 return get_meta_type(g, type_entry);
2449 }
2450 }
2451
2448 }2452 }
2449 zig_unreachable();2453 zig_unreachable();
2450 } else {2454 } else {
...@@ -2560,15 +2564,127 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -2560,15 +2564,127 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
2560 AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);2564 AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);
2561 assert(param_decl_node->type == NodeTypeParamDecl);2565 assert(param_decl_node->type == NodeTypeParamDecl);
2562 AstNode *param_type_node = param_decl_node->data.param_decl.type;2566 AstNode *param_type_node = param_decl_node->data.param_decl.type;
2563 assert(param_type_node->type == NodeTypeType);2567 TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry;
2564 if (param_type_node->data.type.entry) {2568 if (param_type_entry) {
2565 expected_param_type = param_type_node->data.type.entry;2569 expected_param_type = unwrapped_node_type(param_type_node);
2566 }2570 }
2567 }2571 }
2568 analyze_expression(g, import, context, expected_param_type, child);2572 analyze_expression(g, import, context, expected_param_type, child);
2569 }2573 }
25702574
2571 return fn_proto->return_type->data.type.entry;2575 return unwrapped_node_type(fn_proto->return_type);
2576 }
2577}
2578
2579static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2580 TypeTableEntry *expected_type, AstNode *node)
2581{
2582 switch (node->data.prefix_op_expr.prefix_op) {
2583 case PrefixOpInvalid:
2584 zig_unreachable();
2585 case PrefixOpBoolNot:
2586 analyze_expression(g, import, context, g->builtin_types.entry_bool,
2587 node->data.prefix_op_expr.primary_expr);
2588 return g->builtin_types.entry_bool;
2589 case PrefixOpBinNot:
2590 {
2591 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
2592 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2593 operand_node);
2594 if (expr_type->id == TypeTableEntryIdInvalid) {
2595 return expr_type;
2596 } else if (expr_type->id == TypeTableEntryIdInt ||
2597 (expr_type->id == TypeTableEntryIdNumberLiteral &&
2598 !is_num_lit_float(expr_type->data.num_lit.kind)))
2599 {
2600 return expr_type;
2601 } else {
2602 add_node_error(g, operand_node, buf_sprintf("invalid binary not type: '%s'",
2603 buf_ptr(&expr_type->name)));
2604 return g->builtin_types.entry_invalid;
2605 }
2606 }
2607 case PrefixOpNegation:
2608 {
2609 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
2610 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2611 operand_node);
2612 if (expr_type->id == TypeTableEntryIdInvalid) {
2613 return expr_type;
2614 } else if (expr_type->id == TypeTableEntryIdInt &&
2615 expr_type->data.integral.is_signed)
2616 {
2617 return expr_type;
2618 } else if (expr_type->id == TypeTableEntryIdFloat) {
2619 return expr_type;
2620 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {
2621 return expr_type;
2622 } else {
2623 add_node_error(g, operand_node, buf_sprintf("invalid negation type: '%s'",
2624 buf_ptr(&expr_type->name)));
2625 return g->builtin_types.entry_invalid;
2626 }
2627 }
2628 case PrefixOpAddressOf:
2629 case PrefixOpConstAddressOf:
2630 {
2631 bool is_const = (node->data.prefix_op_expr.prefix_op == PrefixOpConstAddressOf);
2632
2633 TypeTableEntry *child_type = analyze_lvalue(g, import, context,
2634 node->data.prefix_op_expr.primary_expr, LValPurposeAddressOf, is_const);
2635
2636 if (child_type->id == TypeTableEntryIdInvalid) {
2637 return g->builtin_types.entry_invalid;
2638 } else if (child_type->id == TypeTableEntryIdMetaType) {
2639 TypeTableEntry *meta_child_type = child_type->data.meta_type.child_type;
2640 if (meta_child_type->id == TypeTableEntryIdUnreachable) {
2641 add_node_error(g, node,
2642 buf_create_from_str("pointer to unreachable not allowed"));
2643 } else {
2644 return get_meta_type(g, get_pointer_to_type(g, meta_child_type, is_const));
2645 }
2646 } else {
2647 return get_pointer_to_type(g, child_type, is_const);
2648 }
2649 }
2650 case PrefixOpDereference:
2651 {
2652 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,
2653 node->data.prefix_op_expr.primary_expr);
2654 if (type_entry->id == TypeTableEntryIdInvalid) {
2655 return type_entry;
2656 } else if (type_entry->id == TypeTableEntryIdPointer) {
2657 return type_entry->data.pointer.child_type;
2658 } else {
2659 add_node_error(g, node->data.prefix_op_expr.primary_expr,
2660 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
2661 buf_ptr(&type_entry->name)));
2662 return g->builtin_types.entry_invalid;
2663 }
2664 }
2665 case PrefixOpMaybe:
2666 {
2667 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,
2668 node->data.prefix_op_expr.primary_expr);
2669
2670 if (type_entry->id == TypeTableEntryIdInvalid) {
2671 return type_entry;
2672 } else if (type_entry->id == TypeTableEntryIdMetaType) {
2673 TypeTableEntry *child_type = type_entry->data.meta_type.child_type;
2674 if (child_type->id == TypeTableEntryIdUnreachable) {
2675 add_node_error(g, node, buf_create_from_str("maybe unreachable type not allowed"));
2676 return g->builtin_types.entry_invalid;
2677 } else {
2678 return get_meta_type(g, get_maybe_type(g, child_type));
2679 }
2680 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
2681 add_node_error(g, node->data.prefix_op_expr.primary_expr,
2682 buf_sprintf("unable to wrap unreachable in maybe type"));
2683 return g->builtin_types.entry_invalid;
2684 } else {
2685 return get_maybe_type(g, type_entry);
2686 }
2687 }
2572 }2688 }
2573}2689}
25742690
...@@ -2593,9 +2709,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2593,9 +2709,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2593 continue;2709 continue;
2594 }2710 }
2595 if (return_type->id == TypeTableEntryIdUnreachable) {2711 if (return_type->id == TypeTableEntryIdUnreachable) {
2596 if (child->type == NodeTypeVoid) {2712 if (is_node_void_expr(child)) {
2597 // {unreachable;void;void} is allowed.2713 // {unreachable;void;void} is allowed.
2598 // ignore void statements once we enter unreachable land.2714 // ignore void statements once we enter unreachable land.
2715 analyze_expression(g, import, context, g->builtin_types.entry_void, child);
2599 continue;2716 continue;
2600 }2717 }
2601 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));2718 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
...@@ -2604,6 +2721,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2604,6 +2721,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2604 bool is_last = (i == node->data.block.statements.length - 1);2721 bool is_last = (i == node->data.block.statements.length - 1);
2605 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;2722 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
2606 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);2723 return_type = analyze_expression(g, import, child_context, passed_expected_type, child);
2724 if (!is_last && return_type->id == TypeTableEntryIdMetaType) {
2725 add_node_error(g, child, buf_sprintf("expected expression, found type"));
2726 }
2607 }2727 }
2608 break;2728 break;
2609 }2729 }
...@@ -2664,7 +2784,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2664,7 +2784,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2664 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);2784 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
2665 if (asm_output->return_type) {2785 if (asm_output->return_type) {
2666 node->data.asm_expr.return_count += 1;2786 node->data.asm_expr.return_count += 1;
2667 return_type = resolve_type(g, asm_output->return_type, import, context, false);2787 return_type = analyze_type_expr(g, import, context, asm_output->return_type);
2668 if (node->data.asm_expr.return_count > 1) {2788 if (node->data.asm_expr.return_count > 1) {
2669 add_node_error(g, node,2789 add_node_error(g, node,
2670 buf_sprintf("inline assembly allows up to one output value"));2790 buf_sprintf("inline assembly allows up to one output value"));
...@@ -2699,6 +2819,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2699,6 +2819,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2699 case NodeTypeFieldAccessExpr:2819 case NodeTypeFieldAccessExpr:
2700 return_type = analyze_field_access_expr(g, import, context, node);2820 return_type = analyze_field_access_expr(g, import, context, node);
2701 break;2821 break;
2822 case NodeTypeContainerInitExpr:
2823 return_type = analyze_container_init_expr(g, import, context, node);
2824 break;
2702 case NodeTypeNumberLiteral:2825 case NodeTypeNumberLiteral:
2703 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);2826 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);
2704 break;2827 break;
...@@ -2713,14 +2836,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2713,14 +2836,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2713 case NodeTypeCharLiteral:2836 case NodeTypeCharLiteral:
2714 return_type = g->builtin_types.entry_u8;2837 return_type = g->builtin_types.entry_u8;
2715 break;2838 break;
2716 case NodeTypeUnreachable:
2717 return_type = g->builtin_types.entry_unreachable;
2718 break;
2719
2720 case NodeTypeVoid:
2721 return_type = g->builtin_types.entry_void;
2722 break;
2723
2724 case NodeTypeBoolLiteral:2839 case NodeTypeBoolLiteral:
2725 return_type = g->builtin_types.entry_bool;2840 return_type = g->builtin_types.entry_bool;
2726 break;2841 break;
...@@ -2730,96 +2845,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2730,96 +2845,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2730 break;2845 break;
27312846
2732 case NodeTypeSymbol:2847 case NodeTypeSymbol:
2733 {2848 return_type = analyze_symbol_expr(g, import, context, expected_type, node);
2734 return_type = analyze_symbol_expr(g, import, context, expected_type, node);2849 break;
2735 break;
2736 }
2737 case NodeTypeCastExpr:2850 case NodeTypeCastExpr:
2738 return_type = analyze_cast_expr(g, import, context, expected_type, node);2851 return_type = analyze_cast_expr(g, import, context, expected_type, node);
2739 break;2852 break;
2740 case NodeTypePrefixOpExpr:2853 case NodeTypePrefixOpExpr:
2741 switch (node->data.prefix_op_expr.prefix_op) {2854 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
2742 case PrefixOpInvalid:
2743 zig_unreachable();
2744 case PrefixOpBoolNot:
2745 analyze_expression(g, import, context, g->builtin_types.entry_bool,
2746 node->data.prefix_op_expr.primary_expr);
2747 return_type = g->builtin_types.entry_bool;
2748 break;
2749 case PrefixOpBinNot:
2750 {
2751 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
2752 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2753 operand_node);
2754 if (expr_type->id == TypeTableEntryIdInvalid) {
2755 return_type = expr_type;
2756 } else if (expr_type->id == TypeTableEntryIdInt ||
2757 (expr_type->id == TypeTableEntryIdNumberLiteral &&
2758 !is_num_lit_float(expr_type->data.num_lit.kind)))
2759 {
2760 return_type = expr_type;
2761 } else {
2762 add_node_error(g, operand_node, buf_sprintf("invalid binary not type: '%s'",
2763 buf_ptr(&expr_type->name)));
2764 return_type = g->builtin_types.entry_invalid;
2765 }
2766 break;
2767 }
2768 case PrefixOpNegation:
2769 {
2770 AstNode *operand_node = node->data.prefix_op_expr.primary_expr;
2771 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
2772 operand_node);
2773 if (expr_type->id == TypeTableEntryIdInvalid) {
2774 return_type = expr_type;
2775 } else if (expr_type->id == TypeTableEntryIdInt &&
2776 expr_type->data.integral.is_signed)
2777 {
2778 return_type = expr_type;
2779 } else if (expr_type->id == TypeTableEntryIdFloat) {
2780 return_type = expr_type;
2781 } else if (expr_type->id == TypeTableEntryIdNumberLiteral) {
2782 return_type = expr_type;
2783 } else {
2784 add_node_error(g, operand_node, buf_sprintf("invalid negation type: '%s'",
2785 buf_ptr(&expr_type->name)));
2786 return_type = g->builtin_types.entry_invalid;
2787 }
2788 break;
2789 }
2790 case PrefixOpAddressOf:
2791 case PrefixOpConstAddressOf:
2792 {
2793 bool is_const = (node->data.prefix_op_expr.prefix_op == PrefixOpConstAddressOf);
2794
2795 TypeTableEntry *child_type = analyze_lvalue(g, import, context,
2796 node->data.prefix_op_expr.primary_expr, LValPurposeAddressOf, is_const);
2797
2798 if (child_type->id == TypeTableEntryIdInvalid) {
2799 return_type = g->builtin_types.entry_invalid;
2800 break;
2801 }
2802
2803 return_type = get_pointer_to_type(g, child_type, is_const, false);
2804 break;
2805 }
2806 case PrefixOpDereference:
2807 {
2808 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr,
2809 node->data.prefix_op_expr.primary_expr);
2810 if (type_entry->id == TypeTableEntryIdInvalid) {
2811 return_type = type_entry;
2812 } else if (type_entry->id == TypeTableEntryIdPointer) {
2813 return_type = type_entry->data.pointer.child_type;
2814 } else {
2815 add_node_error(g, node->data.prefix_op_expr.primary_expr,
2816 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
2817 buf_ptr(&type_entry->name)));
2818 return_type = g->builtin_types.entry_invalid;
2819 }
2820 break;
2821 }
2822 }
2823 break;2855 break;
2824 case NodeTypeIfBoolExpr:2856 case NodeTypeIfBoolExpr:
2825 return_type = analyze_if_bool_expr(g, import, context, expected_type, node);2857 return_type = analyze_if_bool_expr(g, import, context, expected_type, node);
...@@ -2830,17 +2862,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2830,17 +2862,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2830 case NodeTypeWhileExpr:2862 case NodeTypeWhileExpr:
2831 return_type = analyze_while_expr(g, import, context, expected_type, node);2863 return_type = analyze_while_expr(g, import, context, expected_type, node);
2832 break;2864 break;
2833 case NodeTypeStructValueExpr:2865 case NodeTypeArrayType:
2834 return_type = analyze_struct_val_expr(g, import, context, expected_type, node);2866 return_type = analyze_array_type(g, import, context, expected_type, node);
2835 break;
2836 case NodeTypeCompilerFnType:
2837 return_type = analyze_compiler_fn_type(g, import, context, expected_type, node);
2838 break;2867 break;
2839 case NodeTypeDirective:2868 case NodeTypeDirective:
2840 case NodeTypeFnDecl:2869 case NodeTypeFnDecl:
2841 case NodeTypeFnProto:2870 case NodeTypeFnProto:
2842 case NodeTypeParamDecl:2871 case NodeTypeParamDecl:
2843 case NodeTypeType:
2844 case NodeTypeRoot:2872 case NodeTypeRoot:
2845 case NodeTypeRootExportDecl:2873 case NodeTypeRootExportDecl:
2846 case NodeTypeExternBlock:2874 case NodeTypeExternBlock:
...@@ -2850,7 +2878,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -2850,7 +2878,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
2850 case NodeTypeStructDecl:2878 case NodeTypeStructDecl:
2851 case NodeTypeStructField:2879 case NodeTypeStructField:
2852 case NodeTypeStructValueField:2880 case NodeTypeStructValueField:
2853 case NodeTypeCompilerFnExpr:
2854 zig_unreachable();2881 zig_unreachable();
2855 }2882 }
2856 assert(return_type);2883 assert(return_type);
...@@ -2885,8 +2912,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -2885,8 +2912,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
28852912
2886 // define local variables for parameters2913 // define local variables for parameters
2887 AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;2914 AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;
2888 assert(param_decl->type->type == NodeTypeType);2915 TypeTableEntry *type = unwrapped_node_type(param_decl->type);
2889 TypeTableEntry *type = param_decl->type->data.type.entry;
28902916
2891 if (is_exported && type->id == TypeTableEntryIdStruct) {2917 if (is_exported && type->id == TypeTableEntryIdStruct) {
2892 add_node_error(g, param_decl_node,2918 add_node_error(g, param_decl_node,
...@@ -2918,7 +2944,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -2918,7 +2944,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
2918 }2944 }
2919 }2945 }
29202946
2921 TypeTableEntry *expected_type = fn_proto->return_type->data.type.entry;2947 TypeTableEntry *expected_type = unwrapped_node_type(fn_proto->return_type);
2922 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);2948 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
29232949
2924 node->data.fn_def.implicit_return_type = block_return_type;2950 node->data.fn_def.implicit_return_type = block_return_type;
...@@ -2963,7 +2989,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -2963,7 +2989,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
2963 case NodeTypeDirective:2989 case NodeTypeDirective:
2964 case NodeTypeParamDecl:2990 case NodeTypeParamDecl:
2965 case NodeTypeFnProto:2991 case NodeTypeFnProto:
2966 case NodeTypeType:
2967 case NodeTypeFnDecl:2992 case NodeTypeFnDecl:
2968 case NodeTypeReturnExpr:2993 case NodeTypeReturnExpr:
2969 case NodeTypeRoot:2994 case NodeTypeRoot:
...@@ -2975,8 +3000,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -2975,8 +3000,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
2975 case NodeTypeNumberLiteral:3000 case NodeTypeNumberLiteral:
2976 case NodeTypeStringLiteral:3001 case NodeTypeStringLiteral:
2977 case NodeTypeCharLiteral:3002 case NodeTypeCharLiteral:
2978 case NodeTypeUnreachable:
2979 case NodeTypeVoid:
2980 case NodeTypeBoolLiteral:3003 case NodeTypeBoolLiteral:
2981 case NodeTypeNullLiteral:3004 case NodeTypeNullLiteral:
2982 case NodeTypeSymbol:3005 case NodeTypeSymbol:
...@@ -2992,177 +3015,150 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -2992,177 +3015,150 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
2992 case NodeTypeAsmExpr:3015 case NodeTypeAsmExpr:
2993 case NodeTypeFieldAccessExpr:3016 case NodeTypeFieldAccessExpr:
2994 case NodeTypeStructField:3017 case NodeTypeStructField:
2995 case NodeTypeStructValueExpr:
2996 case NodeTypeStructValueField:3018 case NodeTypeStructValueField:
2997 case NodeTypeCompilerFnExpr:3019 case NodeTypeContainerInitExpr:
2998 case NodeTypeCompilerFnType:3020 case NodeTypeArrayType:
2999 zig_unreachable();3021 zig_unreachable();
3000 }3022 }
3001}3023}
30023024
3003static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *expr_node,3025static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node,
3004 TopLevelDecl *decl_node)3026 TopLevelDecl *decl_node)
3005{3027{
3006 switch (expr_node->type) {3028 switch (node->type) {
3007 case NodeTypeNumberLiteral:3029 case NodeTypeNumberLiteral:
3008 case NodeTypeStringLiteral:3030 case NodeTypeStringLiteral:
3009 case NodeTypeCharLiteral:3031 case NodeTypeCharLiteral:
3010 case NodeTypeVoid:
3011 case NodeTypeBoolLiteral:3032 case NodeTypeBoolLiteral:
3012 case NodeTypeNullLiteral:3033 case NodeTypeNullLiteral:
3013 case NodeTypeUnreachable:
3014 case NodeTypeGoto:3034 case NodeTypeGoto:
3015 case NodeTypeBreak:3035 case NodeTypeBreak:
3016 case NodeTypeContinue:3036 case NodeTypeContinue:
3017 // no dependencies on other top level declarations3037 // no dependencies on other top level declarations
3018 break;3038 break;
3019 case NodeTypeSymbol:3039 case NodeTypeSymbol:
3020 decl_node->deps.put(&expr_node->data.symbol_expr.symbol, expr_node);3040 {
3021 break;3041 Buf *name = &node->data.symbol_expr.symbol;
3042 auto table_entry = g->primitive_type_table.maybe_get(name);
3043 if (!table_entry) {
3044 table_entry = import->block_context->type_table.maybe_get(name);
3045 }
3046 if (!table_entry) {
3047 decl_node->deps.put(name, node);
3048 }
3049 break;
3050 }
3022 case NodeTypeBinOpExpr:3051 case NodeTypeBinOpExpr:
3023 collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op1, decl_node);3052 collect_expr_decl_deps(g, import, node->data.bin_op_expr.op1, decl_node);
3024 collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op2, decl_node);3053 collect_expr_decl_deps(g, import, node->data.bin_op_expr.op2, decl_node);
3025 break;3054 break;
3026 case NodeTypeReturnExpr:3055 case NodeTypeReturnExpr:
3027 collect_expr_decl_deps(g, import, expr_node->data.return_expr.expr, decl_node);3056 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
3028 break;3057 break;
3029 case NodeTypeCastExpr:3058 case NodeTypeCastExpr:
3030 collect_expr_decl_deps(g, import, expr_node->data.cast_expr.expr, decl_node);3059 collect_expr_decl_deps(g, import, node->data.cast_expr.expr, decl_node);
3031 collect_type_decl_deps(g, import, expr_node->data.cast_expr.type, decl_node);3060 collect_expr_decl_deps(g, import, node->data.cast_expr.type, decl_node);
3032 break;3061 break;
3033 case NodeTypePrefixOpExpr:3062 case NodeTypePrefixOpExpr:
3034 collect_expr_decl_deps(g, import, expr_node->data.prefix_op_expr.primary_expr, decl_node);3063 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
3035 break;3064 break;
3036 case NodeTypeFnCallExpr:3065 case NodeTypeFnCallExpr:
3037 collect_expr_decl_deps(g, import, expr_node->data.fn_call_expr.fn_ref_expr, decl_node);3066 collect_expr_decl_deps(g, import, node->data.fn_call_expr.fn_ref_expr, decl_node);
3038 for (int i = 0; i < expr_node->data.fn_call_expr.params.length; i += 1) {3067 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
3039 AstNode *arg_node = expr_node->data.fn_call_expr.params.at(i);3068 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
3040 collect_expr_decl_deps(g, import, arg_node, decl_node);3069 collect_expr_decl_deps(g, import, arg_node, decl_node);
3041 }3070 }
3042 break;3071 break;
3043 case NodeTypeArrayAccessExpr:3072 case NodeTypeArrayAccessExpr:
3044 collect_expr_decl_deps(g, import, expr_node->data.array_access_expr.array_ref_expr, decl_node);3073 collect_expr_decl_deps(g, import, node->data.array_access_expr.array_ref_expr, decl_node);
3045 collect_expr_decl_deps(g, import, expr_node->data.array_access_expr.subscript, decl_node);3074 collect_expr_decl_deps(g, import, node->data.array_access_expr.subscript, decl_node);
3046 break;3075 break;
3047 case NodeTypeSliceExpr:3076 case NodeTypeSliceExpr:
3048 collect_expr_decl_deps(g, import, expr_node->data.slice_expr.array_ref_expr, decl_node);3077 collect_expr_decl_deps(g, import, node->data.slice_expr.array_ref_expr, decl_node);
3049 collect_expr_decl_deps(g, import, expr_node->data.slice_expr.start, decl_node);3078 collect_expr_decl_deps(g, import, node->data.slice_expr.start, decl_node);
3050 if (expr_node->data.slice_expr.end) {3079 if (node->data.slice_expr.end) {
3051 collect_expr_decl_deps(g, import, expr_node->data.slice_expr.end, decl_node);3080 collect_expr_decl_deps(g, import, node->data.slice_expr.end, decl_node);
3052 }3081 }
3053 break;3082 break;
3054 case NodeTypeFieldAccessExpr:3083 case NodeTypeFieldAccessExpr:
3055 collect_expr_decl_deps(g, import, expr_node->data.field_access_expr.struct_expr, decl_node);3084 collect_expr_decl_deps(g, import, node->data.field_access_expr.struct_expr, decl_node);
3056 break;3085 break;
3057 case NodeTypeIfBoolExpr:3086 case NodeTypeIfBoolExpr:
3058 collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.condition, decl_node);3087 collect_expr_decl_deps(g, import, node->data.if_bool_expr.condition, decl_node);
3059 collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.then_block, decl_node);3088 collect_expr_decl_deps(g, import, node->data.if_bool_expr.then_block, decl_node);
3060 if (expr_node->data.if_bool_expr.else_node) {3089 if (node->data.if_bool_expr.else_node) {
3061 collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.else_node, decl_node);3090 collect_expr_decl_deps(g, import, node->data.if_bool_expr.else_node, decl_node);
3062 }3091 }
3063 break;3092 break;
3064 case NodeTypeIfVarExpr:3093 case NodeTypeIfVarExpr:
3065 if (expr_node->data.if_var_expr.var_decl.type) {3094 if (node->data.if_var_expr.var_decl.type) {
3066 collect_type_decl_deps(g, import, expr_node->data.if_var_expr.var_decl.type, decl_node);3095 collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.type, decl_node);
3067 }3096 }
3068 if (expr_node->data.if_var_expr.var_decl.expr) {3097 if (node->data.if_var_expr.var_decl.expr) {
3069 collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.var_decl.expr, decl_node);3098 collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.expr, decl_node);
3070 }3099 }
3071 collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.then_block, decl_node);3100 collect_expr_decl_deps(g, import, node->data.if_var_expr.then_block, decl_node);
3072 if (expr_node->data.if_bool_expr.else_node) {3101 if (node->data.if_bool_expr.else_node) {
3073 collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.else_node, decl_node);3102 collect_expr_decl_deps(g, import, node->data.if_var_expr.else_node, decl_node);
3074 }3103 }
3075 break;3104 break;
3076 case NodeTypeWhileExpr:3105 case NodeTypeWhileExpr:
3077 collect_expr_decl_deps(g, import, expr_node->data.while_expr.condition, decl_node);3106 collect_expr_decl_deps(g, import, node->data.while_expr.condition, decl_node);
3078 collect_expr_decl_deps(g, import, expr_node->data.while_expr.body, decl_node);3107 collect_expr_decl_deps(g, import, node->data.while_expr.body, decl_node);
3079 break;3108 break;
3080 case NodeTypeBlock:3109 case NodeTypeBlock:
3081 for (int i = 0; i < expr_node->data.block.statements.length; i += 1) {3110 for (int i = 0; i < node->data.block.statements.length; i += 1) {
3082 AstNode *stmt = expr_node->data.block.statements.at(i);3111 AstNode *stmt = node->data.block.statements.at(i);
3083 collect_expr_decl_deps(g, import, stmt, decl_node);3112 collect_expr_decl_deps(g, import, stmt, decl_node);
3084 }3113 }
3085 break;3114 break;
3086 case NodeTypeAsmExpr:3115 case NodeTypeAsmExpr:
3087 for (int i = 0; i < expr_node->data.asm_expr.output_list.length; i += 1) {3116 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
3088 AsmOutput *asm_output = expr_node->data.asm_expr.output_list.at(i);3117 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
3089 if (asm_output->return_type) {3118 if (asm_output->return_type) {
3090 collect_type_decl_deps(g, import, asm_output->return_type, decl_node);3119 collect_expr_decl_deps(g, import, asm_output->return_type, decl_node);
3091 } else {3120 } else {
3092 decl_node->deps.put(&asm_output->variable_name, expr_node);3121 decl_node->deps.put(&asm_output->variable_name, node);
3093 }3122 }
3094 }3123 }
3095 for (int i = 0; i < expr_node->data.asm_expr.input_list.length; i += 1) {3124 for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
3096 AsmInput *asm_input = expr_node->data.asm_expr.input_list.at(i);3125 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
3097 collect_expr_decl_deps(g, import, asm_input->expr, decl_node);3126 collect_expr_decl_deps(g, import, asm_input->expr, decl_node);
3098 }3127 }
3099 break;3128 break;
3100 case NodeTypeStructValueExpr:3129 case NodeTypeContainerInitExpr:
3101 collect_type_decl_deps(g, import, expr_node->data.struct_val_expr.type, decl_node);3130 collect_expr_decl_deps(g, import, node->data.container_init_expr.type, decl_node);
3102 for (int i = 0; i < expr_node->data.struct_val_expr.fields.length; i += 1) {3131 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
3103 AstNode *field_node = expr_node->data.struct_val_expr.fields.at(i);3132 AstNode *child_node = node->data.container_init_expr.entries.at(i);
3104 assert(field_node->type == NodeTypeStructValueField);3133 collect_expr_decl_deps(g, import, child_node, decl_node);
3105 collect_expr_decl_deps(g, import, field_node->data.struct_val_field.expr, decl_node);
3106 }3134 }
3107 break;3135 break;
3108 case NodeTypeCompilerFnExpr:3136 case NodeTypeStructValueField:
3109 collect_expr_decl_deps(g, import, expr_node->data.compiler_fn_expr.expr, decl_node);3137 collect_expr_decl_deps(g, import, node->data.struct_val_field.expr, decl_node);
3110 break;3138 break;
3111 case NodeTypeCompilerFnType:3139 case NodeTypeArrayType:
3112 collect_type_decl_deps(g, import, expr_node->data.compiler_fn_type.type, decl_node);3140 if (node->data.array_type.size) {
3141 collect_expr_decl_deps(g, import, node->data.array_type.size, decl_node);
3142 }
3143 collect_expr_decl_deps(g, import, node->data.array_type.child_type, decl_node);
3113 break;3144 break;
3114 case NodeTypeRoot:3145 case NodeTypeVariableDeclaration:
3115 case NodeTypeRootExportDecl:
3116 case NodeTypeFnProto:3146 case NodeTypeFnProto:
3147 case NodeTypeExternBlock:
3148 case NodeTypeRootExportDecl:
3117 case NodeTypeFnDef:3149 case NodeTypeFnDef:
3150 case NodeTypeRoot:
3118 case NodeTypeFnDecl:3151 case NodeTypeFnDecl:
3119 case NodeTypeParamDecl:3152 case NodeTypeParamDecl:
3120 case NodeTypeType:
3121 case NodeTypeExternBlock:
3122 case NodeTypeDirective:3153 case NodeTypeDirective:
3123 case NodeTypeVariableDeclaration:
3124 case NodeTypeUse:3154 case NodeTypeUse:
3125 case NodeTypeLabel:3155 case NodeTypeLabel:
3126 case NodeTypeStructDecl:3156 case NodeTypeStructDecl:
3127 case NodeTypeStructField:3157 case NodeTypeStructField:
3128 case NodeTypeStructValueField:
3129 zig_unreachable();3158 zig_unreachable();
3130 }3159 }
3131}3160}
31323161
3133static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node) {
3134 assert(type_node->type == NodeTypeType);
3135 switch (type_node->data.type.type) {
3136 case AstNodeTypeTypePrimitive:
3137 {
3138 Buf *name = &type_node->data.type.primitive_name;
3139 auto table_entry = g->primitive_type_table.maybe_get(name);
3140 if (!table_entry) {
3141 table_entry = import->block_context->type_table.maybe_get(name);
3142 }
3143 if (!table_entry) {
3144 decl_node->deps.put(name, type_node);
3145 }
3146 break;
3147 }
3148 case AstNodeTypeTypePointer:
3149 collect_type_decl_deps(g, import, type_node->data.type.child_type, decl_node);
3150 break;
3151 case AstNodeTypeTypeArray:
3152 collect_type_decl_deps(g, import, type_node->data.type.child_type, decl_node);
3153 if (type_node->data.type.array_size) {
3154 collect_expr_decl_deps(g, import, type_node->data.type.array_size, decl_node);
3155 }
3156 break;
3157 case AstNodeTypeTypeMaybe:
3158 collect_type_decl_deps(g, import, type_node->data.type.child_type, decl_node);
3159 break;
3160 case AstNodeTypeTypeCompilerExpr:
3161 collect_expr_decl_deps(g, import, type_node->data.type.compiler_expr, decl_node);
3162 break;
3163 }
3164}
3165
3166static TypeTableEntryId container_to_type(ContainerKind kind) {3162static TypeTableEntryId container_to_type(ContainerKind kind) {
3167 switch (kind) {3163 switch (kind) {
3168 case ContainerKindStruct:3164 case ContainerKindStruct:
...@@ -3231,7 +3227,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3231,7 +3227,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3231 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {3227 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
3232 AstNode *field_node = node->data.struct_decl.fields.at(i);3228 AstNode *field_node = node->data.struct_decl.fields.at(i);
3233 AstNode *type_node = field_node->data.struct_field.type;3229 AstNode *type_node = field_node->data.struct_field.type;
3234 collect_type_decl_deps(g, import, type_node, decl_node);3230 collect_expr_decl_deps(g, import, type_node, decl_node);
3235 }3231 }
3236 decl_node->name = name;3232 decl_node->name = name;
3237 decl_node->import = import;3233 decl_node->import = import;
...@@ -3271,7 +3267,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3271,7 +3267,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3271 TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl;3267 TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl;
3272 decl_node->deps.init(1);3268 decl_node->deps.init(1);
3273 if (node->data.variable_declaration.type) {3269 if (node->data.variable_declaration.type) {
3274 collect_type_decl_deps(g, import, node->data.variable_declaration.type, decl_node);3270 collect_expr_decl_deps(g, import, node->data.variable_declaration.type, decl_node);
3275 }3271 }
3276 if (node->data.variable_declaration.expr) {3272 if (node->data.variable_declaration.expr) {
3277 collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node);3273 collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node);
...@@ -3294,8 +3290,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3294,8 +3290,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3294 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {3290 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
3295 AstNode *param_node = node->data.fn_proto.params.at(i);3291 AstNode *param_node = node->data.fn_proto.params.at(i);
3296 assert(param_node->type == NodeTypeParamDecl);3292 assert(param_node->type == NodeTypeParamDecl);
3297 collect_type_decl_deps(g, import, param_node->data.param_decl.type, decl_node);3293 collect_expr_decl_deps(g, import, param_node->data.param_decl.type, decl_node);
3298 }3294 }
3295 collect_expr_decl_deps(g, import, node->data.fn_proto.return_type, decl_node);
32993296
3300 Buf *name = &node->data.fn_proto.name;3297 Buf *name = &node->data.fn_proto.name;
3301 decl_node->name = name;3298 decl_node->name = name;
...@@ -3315,7 +3312,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3315,7 +3312,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3315 break;3312 break;
3316 case NodeTypeDirective:3313 case NodeTypeDirective:
3317 case NodeTypeParamDecl:3314 case NodeTypeParamDecl:
3318 case NodeTypeType:
3319 case NodeTypeFnDecl:3315 case NodeTypeFnDecl:
3320 case NodeTypeReturnExpr:3316 case NodeTypeReturnExpr:
3321 case NodeTypeRoot:3317 case NodeTypeRoot:
...@@ -3327,8 +3323,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3327,8 +3323,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3327 case NodeTypeNumberLiteral:3323 case NodeTypeNumberLiteral:
3328 case NodeTypeStringLiteral:3324 case NodeTypeStringLiteral:
3329 case NodeTypeCharLiteral:3325 case NodeTypeCharLiteral:
3330 case NodeTypeUnreachable:
3331 case NodeTypeVoid:
3332 case NodeTypeBoolLiteral:3326 case NodeTypeBoolLiteral:
3333 case NodeTypeNullLiteral:3327 case NodeTypeNullLiteral:
3334 case NodeTypeSymbol:3328 case NodeTypeSymbol:
...@@ -3344,10 +3338,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -3344,10 +3338,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
3344 case NodeTypeAsmExpr:3338 case NodeTypeAsmExpr:
3345 case NodeTypeFieldAccessExpr:3339 case NodeTypeFieldAccessExpr:
3346 case NodeTypeStructField:3340 case NodeTypeStructField:
3347 case NodeTypeStructValueExpr:3341 case NodeTypeContainerInitExpr:
3348 case NodeTypeStructValueField:3342 case NodeTypeStructValueField:
3349 case NodeTypeCompilerFnExpr:3343 case NodeTypeArrayType:
3350 case NodeTypeCompilerFnType:
3351 zig_unreachable();3344 zig_unreachable();
3352 }3345 }
3353}3346}
...@@ -3526,18 +3519,14 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -3526,18 +3519,14 @@ Expr *get_resolved_expr(AstNode *node) {
3526 return &node->data.while_expr.resolved_expr;3519 return &node->data.while_expr.resolved_expr;
3527 case NodeTypeAsmExpr:3520 case NodeTypeAsmExpr:
3528 return &node->data.asm_expr.resolved_expr;3521 return &node->data.asm_expr.resolved_expr;
3529 case NodeTypeStructValueExpr:3522 case NodeTypeContainerInitExpr:
3530 return &node->data.struct_val_expr.resolved_expr;3523 return &node->data.container_init_expr.resolved_expr;
3531 case NodeTypeNumberLiteral:3524 case NodeTypeNumberLiteral:
3532 return &node->data.number_literal.resolved_expr;3525 return &node->data.number_literal.resolved_expr;
3533 case NodeTypeStringLiteral:3526 case NodeTypeStringLiteral:
3534 return &node->data.string_literal.resolved_expr;3527 return &node->data.string_literal.resolved_expr;
3535 case NodeTypeBlock:3528 case NodeTypeBlock:
3536 return &node->data.block.resolved_expr;3529 return &node->data.block.resolved_expr;
3537 case NodeTypeVoid:
3538 return &node->data.void_expr.resolved_expr;
3539 case NodeTypeUnreachable:
3540 return &node->data.unreachable_expr.resolved_expr;
3541 case NodeTypeSymbol:3530 case NodeTypeSymbol:
3542 return &node->data.symbol_expr.resolved_expr;3531 return &node->data.symbol_expr.resolved_expr;
3543 case NodeTypeVariableDeclaration:3532 case NodeTypeVariableDeclaration:
...@@ -3554,19 +3543,16 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -3554,19 +3543,16 @@ Expr *get_resolved_expr(AstNode *node) {
3554 return &node->data.break_expr.resolved_expr;3543 return &node->data.break_expr.resolved_expr;
3555 case NodeTypeContinue:3544 case NodeTypeContinue:
3556 return &node->data.continue_expr.resolved_expr;3545 return &node->data.continue_expr.resolved_expr;
3557 case NodeTypeCompilerFnExpr:
3558 return &node->data.compiler_fn_expr.resolved_expr;
3559 case NodeTypeCompilerFnType:
3560 return &node->data.compiler_fn_type.resolved_expr;
3561 case NodeTypeLabel:3546 case NodeTypeLabel:
3562 return &node->data.label.resolved_expr;3547 return &node->data.label.resolved_expr;
3548 case NodeTypeArrayType:
3549 return &node->data.array_type.resolved_expr;
3563 case NodeTypeRoot:3550 case NodeTypeRoot:
3564 case NodeTypeRootExportDecl:3551 case NodeTypeRootExportDecl:
3565 case NodeTypeFnProto:3552 case NodeTypeFnProto:
3566 case NodeTypeFnDef:3553 case NodeTypeFnDef:
3567 case NodeTypeFnDecl:3554 case NodeTypeFnDecl:
3568 case NodeTypeParamDecl:3555 case NodeTypeParamDecl:
3569 case NodeTypeType:
3570 case NodeTypeExternBlock:3556 case NodeTypeExternBlock:
3571 case NodeTypeDirective:3557 case NodeTypeDirective:
3572 case NodeTypeUse:3558 case NodeTypeUse:
...@@ -3581,13 +3567,12 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {...@@ -3581,13 +3567,12 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
3581 switch (node->type) {3567 switch (node->type) {
3582 case NodeTypeNumberLiteral:3568 case NodeTypeNumberLiteral:
3583 return &node->data.number_literal.codegen;3569 return &node->data.number_literal.codegen;
3584 case NodeTypeCompilerFnType:3570 case NodeTypeFnCallExpr:
3585 return &node->data.compiler_fn_type.resolved_num_lit;3571 return &node->data.fn_call_expr.resolved_num_lit;
3586 case NodeTypeReturnExpr:3572 case NodeTypeReturnExpr:
3587 case NodeTypeBinOpExpr:3573 case NodeTypeBinOpExpr:
3588 case NodeTypeCastExpr:3574 case NodeTypeCastExpr:
3589 case NodeTypePrefixOpExpr:3575 case NodeTypePrefixOpExpr:
3590 case NodeTypeFnCallExpr:
3591 case NodeTypeArrayAccessExpr:3576 case NodeTypeArrayAccessExpr:
3592 case NodeTypeSliceExpr:3577 case NodeTypeSliceExpr:
3593 case NodeTypeFieldAccessExpr:3578 case NodeTypeFieldAccessExpr:
...@@ -3595,24 +3580,21 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {...@@ -3595,24 +3580,21 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
3595 case NodeTypeIfVarExpr:3580 case NodeTypeIfVarExpr:
3596 case NodeTypeWhileExpr:3581 case NodeTypeWhileExpr:
3597 case NodeTypeAsmExpr:3582 case NodeTypeAsmExpr:
3598 case NodeTypeStructValueExpr:3583 case NodeTypeContainerInitExpr:
3599 case NodeTypeRoot:3584 case NodeTypeRoot:
3600 case NodeTypeRootExportDecl:3585 case NodeTypeRootExportDecl:
3601 case NodeTypeFnProto:3586 case NodeTypeFnProto:
3602 case NodeTypeFnDef:3587 case NodeTypeFnDef:
3603 case NodeTypeFnDecl:3588 case NodeTypeFnDecl:
3604 case NodeTypeParamDecl:3589 case NodeTypeParamDecl:
3605 case NodeTypeType:
3606 case NodeTypeBlock:3590 case NodeTypeBlock:
3607 case NodeTypeExternBlock:3591 case NodeTypeExternBlock:
3608 case NodeTypeDirective:3592 case NodeTypeDirective:
3609 case NodeTypeVariableDeclaration:3593 case NodeTypeVariableDeclaration:
3610 case NodeTypeStringLiteral:3594 case NodeTypeStringLiteral:
3611 case NodeTypeCharLiteral:3595 case NodeTypeCharLiteral:
3612 case NodeTypeUnreachable:
3613 case NodeTypeSymbol:3596 case NodeTypeSymbol:
3614 case NodeTypeUse:3597 case NodeTypeUse:
3615 case NodeTypeVoid:
3616 case NodeTypeBoolLiteral:3598 case NodeTypeBoolLiteral:
3617 case NodeTypeNullLiteral:3599 case NodeTypeNullLiteral:
3618 case NodeTypeLabel:3600 case NodeTypeLabel:
...@@ -3622,7 +3604,7 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {...@@ -3622,7 +3604,7 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
3622 case NodeTypeStructDecl:3604 case NodeTypeStructDecl:
3623 case NodeTypeStructField:3605 case NodeTypeStructField:
3624 case NodeTypeStructValueField:3606 case NodeTypeStructValueField:
3625 case NodeTypeCompilerFnExpr:3607 case NodeTypeArrayType:
3626 zig_unreachable();3608 zig_unreachable();
3627 }3609 }
3628}3610}
...@@ -3648,22 +3630,19 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -3648,22 +3630,19 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
3648 case NodeTypeIfVarExpr:3630 case NodeTypeIfVarExpr:
3649 case NodeTypeWhileExpr:3631 case NodeTypeWhileExpr:
3650 case NodeTypeAsmExpr:3632 case NodeTypeAsmExpr:
3651 case NodeTypeStructValueExpr:3633 case NodeTypeContainerInitExpr:
3652 case NodeTypeRoot:3634 case NodeTypeRoot:
3653 case NodeTypeRootExportDecl:3635 case NodeTypeRootExportDecl:
3654 case NodeTypeFnDef:3636 case NodeTypeFnDef:
3655 case NodeTypeFnDecl:3637 case NodeTypeFnDecl:
3656 case NodeTypeParamDecl:3638 case NodeTypeParamDecl:
3657 case NodeTypeType:
3658 case NodeTypeBlock:3639 case NodeTypeBlock:
3659 case NodeTypeExternBlock:3640 case NodeTypeExternBlock:
3660 case NodeTypeDirective:3641 case NodeTypeDirective:
3661 case NodeTypeStringLiteral:3642 case NodeTypeStringLiteral:
3662 case NodeTypeCharLiteral:3643 case NodeTypeCharLiteral:
3663 case NodeTypeUnreachable:
3664 case NodeTypeSymbol:3644 case NodeTypeSymbol:
3665 case NodeTypeUse:3645 case NodeTypeUse:
3666 case NodeTypeVoid:
3667 case NodeTypeBoolLiteral:3646 case NodeTypeBoolLiteral:
3668 case NodeTypeNullLiteral:3647 case NodeTypeNullLiteral:
3669 case NodeTypeLabel:3648 case NodeTypeLabel:
...@@ -3672,8 +3651,23 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -3672,8 +3651,23 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
3672 case NodeTypeContinue:3651 case NodeTypeContinue:
3673 case NodeTypeStructField:3652 case NodeTypeStructField:
3674 case NodeTypeStructValueField:3653 case NodeTypeStructValueField:
3675 case NodeTypeCompilerFnExpr:3654 case NodeTypeArrayType:
3676 case NodeTypeCompilerFnType:
3677 zig_unreachable();3655 zig_unreachable();
3678 }3656 }
3679}3657}
3658
3659bool is_node_void_expr(AstNode *node) {
3660 if (node->type == NodeTypeContainerInitExpr &&
3661 node->data.container_init_expr.kind == ContainerInitKindArray)
3662 {
3663 AstNode *type_node = node->data.container_init_expr.type;
3664 if (type_node->type == NodeTypeSymbol &&
3665 buf_eql_str(&type_node->data.symbol_expr.symbol, "void"))
3666 {
3667 return true;
3668 }
3669 }
3670
3671 return false;
3672}
3673
src/analyze.hpp+2-1
...@@ -13,12 +13,13 @@...@@ -13,12 +13,13 @@
13void semantic_analyze(CodeGen *g);13void semantic_analyze(CodeGen *g);
14void add_node_error(CodeGen *g, AstNode *node, Buf *msg);14void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15TypeTableEntry *new_type_table_entry(TypeTableEntryId id);15TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
16TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias);16TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
17VariableTableEntry *find_variable(BlockContext *context, Buf *name);17VariableTableEntry *find_variable(BlockContext *context, Buf *name);
18TypeTableEntry *find_container(BlockContext *context, Buf *name);18TypeTableEntry *find_container(BlockContext *context, Buf *name);
19BlockContext *new_block_context(AstNode *node, BlockContext *parent);19BlockContext *new_block_context(AstNode *node, BlockContext *parent);
20Expr *get_resolved_expr(AstNode *node);20Expr *get_resolved_expr(AstNode *node);
21NumLitCodeGen *get_resolved_num_lit(AstNode *node);21NumLitCodeGen *get_resolved_num_lit(AstNode *node);
22TopLevelDecl *get_resolved_top_level_decl(AstNode *node);22TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
23bool is_node_void_expr(AstNode *node);
2324
24#endif25#endif
src/codegen.cpp+197-156
...@@ -72,35 +72,35 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -72,35 +72,35 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
72 LLVMValueRef target_ref, LLVMValueRef value,72 LLVMValueRef target_ref, LLVMValueRef value,
73 TypeTableEntry *op1_type, TypeTableEntry *op2_type);73 TypeTableEntry *op1_type, TypeTableEntry *op2_type);
74 74
7575static TypeTableEntry *get_type_for_type_node(AstNode *node) {
76static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) {76 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;
77 assert(type_node->type == NodeTypeType);77 assert(meta_type_entry->id == TypeTableEntryIdMetaType);
78 return type_node->data.type.entry;78 return meta_type_entry->data.meta_type.child_type;
79}79}
8080
81static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {81static TypeTableEntry *fn_proto_type_from_type_node(CodeGen *g, AstNode *type_node) {
82 TypeTableEntry *type_entry = get_type_for_type_node(g, type_node);82 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
8383
84 if (type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdArray) {84 if (type_entry->id == TypeTableEntryIdStruct || type_entry->id == TypeTableEntryIdArray) {
85 return get_pointer_to_type(g, type_entry, true, true);85 return get_pointer_to_type(g, type_entry, true);
86 } else {86 } else {
87 return type_entry;87 return type_entry;
88 }88 }
89}89}
9090
91static LLVMZigDIType *to_llvm_debug_type(CodeGen *g, AstNode *type_node) {91static LLVMZigDIType *to_llvm_debug_type(CodeGen *g, AstNode *type_node) {
92 TypeTableEntry *type_entry = get_type_for_type_node(g, type_node);92 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
93 return type_entry->di_type;93 return type_entry->di_type;
94}94}
9595
9696
97static bool type_is_unreachable(CodeGen *g, AstNode *type_node) {97static bool type_is_unreachable(CodeGen *g, AstNode *type_node) {
98 return get_type_for_type_node(g, type_node)->id == TypeTableEntryIdUnreachable;98 return get_type_for_type_node(type_node)->id == TypeTableEntryIdUnreachable;
99}99}
100100
101static bool is_param_decl_type_void(CodeGen *g, AstNode *param_decl_node) {101static bool is_param_decl_type_void(CodeGen *g, AstNode *param_decl_node) {
102 assert(param_decl_node->type == NodeTypeParamDecl);102 assert(param_decl_node->type == NodeTypeParamDecl);
103 return get_type_for_type_node(g, param_decl_node->data.param_decl.type)->id == TypeTableEntryIdVoid;103 return get_type_for_type_node(param_decl_node->data.param_decl.type)->id == TypeTableEntryIdVoid;
104}104}
105105
106static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {106static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
...@@ -146,6 +146,32 @@ static TypeTableEntry *get_expr_type(AstNode *node) {...@@ -146,6 +146,32 @@ static TypeTableEntry *get_expr_type(AstNode *node) {
146 return expr->type_entry;146 return expr->type_entry;
147}147}
148148
149static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,
150 NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)
151{
152 TypeTableEntry *type_entry = codegen_num_lit->resolved_type;
153 assert(type_entry);
154
155 // override the expression type for number literals
156 get_resolved_expr(source_node)->type_entry = type_entry;
157
158 if (type_entry->id == TypeTableEntryIdInt) {
159 // here the union has int64_t and uint64_t and we purposefully read
160 // the uint64_t value in either case, because we want the twos
161 // complement representation
162
163 return LLVMConstInt(type_entry->type_ref,
164 num_lit_node->data.x_uint,
165 type_entry->data.integral.is_signed);
166 } else if (type_entry->id == TypeTableEntryIdFloat) {
167
168 return LLVMConstReal(type_entry->type_ref,
169 num_lit_node->data.x_float);
170 } else {
171 zig_panic("bad number literal type");
172 }
173}
174
149static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {175static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
150 assert(node->type == NodeTypeFnCallExpr);176 assert(node->type == NodeTypeFnCallExpr);
151 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;177 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
...@@ -154,6 +180,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -154,6 +180,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
154180
155 switch (builtin_fn->id) {181 switch (builtin_fn->id) {
156 case BuiltinFnIdInvalid:182 case BuiltinFnIdInvalid:
183 case BuiltinFnIdTypeof:
157 zig_unreachable();184 zig_unreachable();
158 case BuiltinFnIdArithmeticWithOverflow:185 case BuiltinFnIdArithmeticWithOverflow:
159 {186 {
...@@ -238,6 +265,74 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -238,6 +265,74 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
238 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");265 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
239 return nullptr;266 return nullptr;
240 }267 }
268 case BuiltinFnIdSizeof:
269 {
270 assert(node->data.fn_call_expr.params.length == 1);
271 AstNode *type_node = node->data.fn_call_expr.params.at(0);
272 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
273
274 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
275 AstNodeNumberLiteral num_lit_node;
276 num_lit_node.kind = NumLitU64; // this field isn't even read
277 num_lit_node.overflow = false;
278 num_lit_node.data.x_uint = type_entry->size_in_bits / 8;
279 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
280 }
281 case BuiltinFnIdMinValue:
282 {
283 assert(node->data.fn_call_expr.params.length == 1);
284 AstNode *type_node = node->data.fn_call_expr.params.at(0);
285 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
286
287
288 if (type_entry->id == TypeTableEntryIdInt) {
289 if (type_entry->data.integral.is_signed) {
290 return LLVMConstInt(type_entry->type_ref, 1ULL << (type_entry->size_in_bits - 1), false);
291 } else {
292 return LLVMConstNull(type_entry->type_ref);
293 }
294 } else if (type_entry->id == TypeTableEntryIdFloat) {
295 zig_panic("TODO codegen min_value float");
296 } else {
297 zig_unreachable();
298 }
299 }
300 case BuiltinFnIdMaxValue:
301 {
302 assert(node->data.fn_call_expr.params.length == 1);
303 AstNode *type_node = node->data.fn_call_expr.params.at(0);
304 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
305
306
307 if (type_entry->id == TypeTableEntryIdInt) {
308 if (type_entry->data.integral.is_signed) {
309 return LLVMConstInt(type_entry->type_ref, (1ULL << (type_entry->size_in_bits - 1)) - 1, false);
310 } else {
311 return LLVMConstAllOnes(type_entry->type_ref);
312 }
313 } else if (type_entry->id == TypeTableEntryIdFloat) {
314 zig_panic("TODO codegen max_value float");
315 } else {
316 zig_unreachable();
317 }
318 }
319 case BuiltinFnIdValueCount:
320 {
321 assert(node->data.fn_call_expr.params.length == 1);
322 AstNode *type_node = node->data.fn_call_expr.params.at(0);
323 TypeTableEntry *type_entry = get_type_for_type_node(type_node);
324
325 if (type_entry->id == TypeTableEntryIdEnum) {
326 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
327 AstNodeNumberLiteral num_lit_node;
328 num_lit_node.kind = NumLitU64; // field ignored
329 num_lit_node.overflow = false;
330 num_lit_node.data.x_uint = type_entry->data.enumeration.field_count;
331 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
332 } else {
333 zig_unreachable();
334 }
335 }
241 }336 }
242 zig_unreachable();337 zig_unreachable();
243}338}
...@@ -692,6 +787,10 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {...@@ -692,6 +787,10 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
692 add_debug_source_node(g, node);787 add_debug_source_node(g, node);
693 return LLVMBuildLoad(g->builder, expr, "");788 return LLVMBuildLoad(g->builder, expr, "");
694 }789 }
790 case PrefixOpMaybe:
791 {
792 zig_panic("TODO codegen PrefixOpMaybe");
793 }
695 }794 }
696 zig_unreachable();795 zig_unreachable();
697}796}
...@@ -1484,35 +1583,46 @@ static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) {...@@ -1484,35 +1583,46 @@ static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) {
1484 return tmp_struct_ptr;1583 return tmp_struct_ptr;
1485}1584}
14861585
1487static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {1586static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
1488 assert(node->type == NodeTypeStructValueExpr);1587 assert(node->type == NodeTypeContainerInitExpr);
14891588
1490 TypeTableEntry *type_entry = get_expr_type(node);1589 TypeTableEntry *type_entry = get_expr_type(node);
14911590
1492 assert(type_entry->id == TypeTableEntryIdStruct);1591 if (type_entry->id == TypeTableEntryIdStruct) {
1592 assert(node->data.container_init_expr.kind == ContainerInitKindStruct);
14931593
1494 int field_count = type_entry->data.structure.field_count;1594 int field_count = type_entry->data.structure.field_count;
1495 assert(field_count == node->data.struct_val_expr.fields.length);1595 assert(field_count == node->data.container_init_expr.entries.length);
14961596
1497 StructValExprCodeGen *struct_val_expr_node = &node->data.struct_val_expr.codegen;1597 StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
1498 LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;1598 LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
14991599
1500 for (int i = 0; i < field_count; i += 1) {1600 for (int i = 0; i < field_count; i += 1) {
1501 AstNode *field_node = node->data.struct_val_expr.fields.at(i);1601 AstNode *field_node = node->data.container_init_expr.entries.at(i);
1502 assert(field_node->type == NodeTypeStructValueField);1602 assert(field_node->type == NodeTypeStructValueField);
1503 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;1603 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
1504 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {1604 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
1505 continue;1605 continue;
1606 }
1607 assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
1608
1609 add_debug_source_node(g, field_node);
1610 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
1611 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);
1612 LLVMBuildStore(g->builder, value, field_ptr);
1506 }1613 }
1507 assert(buf_eql_buf(type_struct_field->name, &field_node->data.struct_val_field.name));
15081614
1509 add_debug_source_node(g, field_node);1615 return tmp_struct_ptr;
1510 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");1616 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
1511 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);1617 assert(node->data.container_init_expr.entries.length == 0);
1512 LLVMBuildStore(g->builder, value, field_ptr);1618 add_debug_source_node(g, node);
1619 return LLVMBuildUnreachable(g->builder);
1620 } else if (type_entry->id == TypeTableEntryIdVoid) {
1621 assert(node->data.container_init_expr.entries.length == 0);
1622 return nullptr;
1623 } else {
1624 zig_unreachable();
1513 }1625 }
1514
1515 return tmp_struct_ptr;
1516}1626}
15171627
1518static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {1628static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
...@@ -1659,93 +1769,39 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {...@@ -1659,93 +1769,39 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
1659 get_resolved_expr(node)->block_context, false, &init_val);1769 get_resolved_expr(node)->block_context, false, &init_val);
1660}1770}
16611771
1662static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,1772static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) {
1663 NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)1773 assert(node->type == NodeTypeNumberLiteral);
1664{
1665 TypeTableEntry *type_entry = codegen_num_lit->resolved_type;
1666 assert(type_entry);
1667
1668 // override the expression type for number literals
1669 get_resolved_expr(source_node)->type_entry = type_entry;
1670
1671 if (type_entry->id == TypeTableEntryIdInt) {
1672 // here the union has int64_t and uint64_t and we purposefully read
1673 // the uint64_t value in either case, because we want the twos
1674 // complement representation
16751774
1676 return LLVMConstInt(type_entry->type_ref,1775 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1677 num_lit_node->data.x_uint,1776 assert(codegen_num_lit);
1678 type_entry->data.integral.is_signed);
1679 } else if (type_entry->id == TypeTableEntryIdFloat) {
16801777
1681 return LLVMConstReal(type_entry->type_ref,1778 return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal);
1682 num_lit_node->data.x_float);
1683 } else {
1684 zig_panic("bad number literal type");
1685 }
1686}1779}
16871780
1688static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {1781static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
1689 assert(node->type == NodeTypeCompilerFnType);1782 VariableTableEntry *variable = find_variable(
16901783 get_resolved_expr(node)->block_context,
1691 Buf *name = &node->data.compiler_fn_type.name;1784 &node->data.symbol_expr.symbol);
1692 TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type);1785 assert(variable);
1693 if (buf_eql_str(name, "sizeof")) {1786 if (variable->type->id == TypeTableEntryIdVoid) {
1694 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);1787 return nullptr;
1695 AstNodeNumberLiteral num_lit_node;1788 } else if (variable->is_ptr) {
1696 num_lit_node.kind = type_entry->data.num_lit.kind;1789 assert(variable->value_ref);
1697 num_lit_node.overflow = false;1790 if (variable->type->id == TypeTableEntryIdArray) {
1698 num_lit_node.data.x_uint = type_entry->size_in_bits / 8;1791 return variable->value_ref;
1699 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);1792 } else if (variable->type->id == TypeTableEntryIdStruct ||
1700 } else if (buf_eql_str(name, "min_value")) {1793 variable->type->id == TypeTableEntryIdMaybe)
1701 if (type_entry->id == TypeTableEntryIdInt) {1794 {
1702 if (type_entry->data.integral.is_signed) {1795 return variable->value_ref;
1703 return LLVMConstInt(type_entry->type_ref, 1ULL << (type_entry->size_in_bits - 1), false);
1704 } else {
1705 return LLVMConstNull(type_entry->type_ref);
1706 }
1707 } else if (type_entry->id == TypeTableEntryIdFloat) {
1708 zig_panic("TODO codegen min_value float");
1709 } else {
1710 zig_unreachable();
1711 }
1712 } else if (buf_eql_str(name, "max_value")) {
1713 if (type_entry->id == TypeTableEntryIdInt) {
1714 if (type_entry->data.integral.is_signed) {
1715 return LLVMConstInt(type_entry->type_ref, (1ULL << (type_entry->size_in_bits - 1)) - 1, false);
1716 } else {
1717 return LLVMConstAllOnes(type_entry->type_ref);
1718 }
1719 } else if (type_entry->id == TypeTableEntryIdFloat) {
1720 zig_panic("TODO codegen max_value float");
1721 } else {
1722 zig_unreachable();
1723 }
1724 } else if (buf_eql_str(name, "value_count")) {
1725 if (type_entry->id == TypeTableEntryIdEnum) {
1726 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1727 AstNodeNumberLiteral num_lit_node;
1728 num_lit_node.kind = type_entry->data.num_lit.kind;
1729 num_lit_node.overflow = false;
1730 num_lit_node.data.x_uint = type_entry->data.enumeration.field_count;
1731 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
1732 } else {1796 } else {
1733 zig_unreachable();1797 add_debug_source_node(g, node);
1798 return LLVMBuildLoad(g->builder, variable->value_ref, "");
1734 }1799 }
1735 } else {1800 } else {
1736 zig_unreachable();1801 return variable->value_ref;
1737 }1802 }
1738}1803}
17391804
1740static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) {
1741 assert(node->type == NodeTypeNumberLiteral);
1742
1743 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1744 assert(codegen_num_lit);
1745
1746 return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal);
1747}
1748
1749static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {1805static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1750 switch (node->type) {1806 switch (node->type) {
1751 case NodeTypeBinOpExpr:1807 case NodeTypeBinOpExpr:
...@@ -1766,11 +1822,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1766,11 +1822,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1766 return gen_slice_expr(g, node);1822 return gen_slice_expr(g, node);
1767 case NodeTypeFieldAccessExpr:1823 case NodeTypeFieldAccessExpr:
1768 return gen_field_access_expr(g, node, false);1824 return gen_field_access_expr(g, node, false);
1769 case NodeTypeUnreachable:
1770 add_debug_source_node(g, node);
1771 return LLVMBuildUnreachable(g->builder);
1772 case NodeTypeVoid:
1773 return nullptr;
1774 case NodeTypeBoolLiteral:1825 case NodeTypeBoolLiteral:
1775 if (node->data.bool_literal.value)1826 if (node->data.bool_literal.value)
1776 return LLVMConstAllOnes(LLVMInt1Type());1827 return LLVMConstAllOnes(LLVMInt1Type());
...@@ -1802,29 +1853,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1802,29 +1853,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1802 case NodeTypeCharLiteral:1853 case NodeTypeCharLiteral:
1803 return LLVMConstInt(LLVMInt8Type(), node->data.char_literal.value, false);1854 return LLVMConstInt(LLVMInt8Type(), node->data.char_literal.value, false);
1804 case NodeTypeSymbol:1855 case NodeTypeSymbol:
1805 {1856 return gen_symbol(g, node);
1806 VariableTableEntry *variable = find_variable(
1807 get_resolved_expr(node)->block_context,
1808 &node->data.symbol_expr.symbol);
1809 assert(variable);
1810 if (variable->type->id == TypeTableEntryIdVoid) {
1811 return nullptr;
1812 } else if (variable->is_ptr) {
1813 assert(variable->value_ref);
1814 if (variable->type->id == TypeTableEntryIdArray) {
1815 return variable->value_ref;
1816 } else if (variable->type->id == TypeTableEntryIdStruct ||
1817 variable->type->id == TypeTableEntryIdMaybe)
1818 {
1819 return variable->value_ref;
1820 } else {
1821 add_debug_source_node(g, node);
1822 return LLVMBuildLoad(g->builder, variable->value_ref, "");
1823 }
1824 } else {
1825 return variable->value_ref;
1826 }
1827 }
1828 case NodeTypeBlock:1857 case NodeTypeBlock:
1829 return gen_block(g, node, nullptr);1858 return gen_block(g, node, nullptr);
1830 case NodeTypeGoto:1859 case NodeTypeGoto:
...@@ -1846,24 +1875,21 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1846,24 +1875,21 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1846 LLVMPositionBuilderAtEnd(g->builder, basic_block);1875 LLVMPositionBuilderAtEnd(g->builder, basic_block);
1847 return nullptr;1876 return nullptr;
1848 }1877 }
1849 case NodeTypeStructValueExpr:1878 case NodeTypeContainerInitExpr:
1850 return gen_struct_val_expr(g, node);1879 return gen_container_init_expr(g, node);
1851 case NodeTypeCompilerFnType:
1852 return gen_compiler_fn_type(g, node);
1853 case NodeTypeRoot:1880 case NodeTypeRoot:
1854 case NodeTypeRootExportDecl:1881 case NodeTypeRootExportDecl:
1855 case NodeTypeFnProto:1882 case NodeTypeFnProto:
1856 case NodeTypeFnDef:1883 case NodeTypeFnDef:
1857 case NodeTypeFnDecl:1884 case NodeTypeFnDecl:
1858 case NodeTypeParamDecl:1885 case NodeTypeParamDecl:
1859 case NodeTypeType:
1860 case NodeTypeExternBlock:1886 case NodeTypeExternBlock:
1861 case NodeTypeDirective:1887 case NodeTypeDirective:
1862 case NodeTypeUse:1888 case NodeTypeUse:
1863 case NodeTypeStructDecl:1889 case NodeTypeStructDecl:
1864 case NodeTypeStructField:1890 case NodeTypeStructField:
1865 case NodeTypeStructValueField:1891 case NodeTypeStructValueField:
1866 case NodeTypeCompilerFnExpr:1892 case NodeTypeArrayType:
1867 zig_unreachable();1893 zig_unreachable();
1868 }1894 }
1869 zig_unreachable();1895 zig_unreachable();
...@@ -1872,7 +1898,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {...@@ -1872,7 +1898,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
1872static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {1898static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
1873 LLVMValueRef val = gen_expr_no_cast(g, node);1899 LLVMValueRef val = gen_expr_no_cast(g, node);
18741900
1875 if (node->type == NodeTypeVoid) {1901 if (is_node_void_expr(node)) {
1876 return val;1902 return val;
1877 }1903 }
18781904
...@@ -1966,7 +1992,7 @@ static void do_code_gen(CodeGen *g) {...@@ -1966,7 +1992,7 @@ static void do_code_gen(CodeGen *g) {
1966 assert(proto_node->type == NodeTypeFnProto);1992 assert(proto_node->type == NodeTypeFnProto);
1967 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;1993 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
19681994
1969 LLVMTypeRef ret_type = get_type_for_type_node(g, fn_proto->return_type)->type_ref;1995 LLVMTypeRef ret_type = get_type_for_type_node(fn_proto->return_type)->type_ref;
1970 int param_count = count_non_void_params(g, &fn_proto->params);1996 int param_count = count_non_void_params(g, &fn_proto->params);
1971 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count);1997 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count);
1972 int gen_param_index = 0;1998 int gen_param_index = 0;
...@@ -2009,7 +2035,7 @@ static void do_code_gen(CodeGen *g) {...@@ -2009,7 +2035,7 @@ static void do_code_gen(CodeGen *g) {
2009 TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);2035 TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);
2010 LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index);2036 LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index);
2011 if (param_type->id == TypeTableEntryIdPointer &&2037 if (param_type->id == TypeTableEntryIdPointer &&
2012 param_type->data.pointer.is_noalias)2038 false) // TODO test if parameter is noalias
2013 {2039 {
2014 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);2040 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
2015 } else if (param_type->id == TypeTableEntryIdPointer &&2041 } else if (param_type->id == TypeTableEntryIdPointer &&
...@@ -2267,7 +2293,7 @@ static void define_builtin_types(CodeGen *g) {...@@ -2267,7 +2293,7 @@ static void define_builtin_types(CodeGen *g) {
2267 g->builtin_types.entry_u64 = entry;2293 g->builtin_types.entry_u64 = entry;
2268 g->primitive_type_table.put(&entry->name, entry);2294 g->primitive_type_table.put(&entry->name, entry);
2269 }2295 }
2270 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true, false);2296 g->builtin_types.entry_c_string_literal = get_pointer_to_type(g, g->builtin_types.entry_u8, true);
2271 {2297 {
2272 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);2298 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
2273 entry->type_ref = LLVMInt8Type();2299 entry->type_ref = LLVMInt8Type();
...@@ -2413,7 +2439,7 @@ static void define_builtin_fns_int(CodeGen *g, TypeTableEntry *type_entry) {...@@ -2413,7 +2439,7 @@ static void define_builtin_fns_int(CodeGen *g, TypeTableEntry *type_entry) {
2413 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);2439 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
2414 builtin_fn->param_types[0] = type_entry;2440 builtin_fn->param_types[0] = type_entry;
2415 builtin_fn->param_types[1] = type_entry;2441 builtin_fn->param_types[1] = type_entry;
2416 builtin_fn->param_types[2] = get_pointer_to_type(g, type_entry, false, false);2442 builtin_fn->param_types[2] = get_pointer_to_type(g, type_entry, false);
24172443
24182444
2419 const char *signed_str = type_entry->data.integral.is_signed ?2445 const char *signed_str = type_entry->data.integral.is_signed ?
...@@ -2437,6 +2463,23 @@ static void define_builtin_fns_int(CodeGen *g, TypeTableEntry *type_entry) {...@@ -2437,6 +2463,23 @@ static void define_builtin_fns_int(CodeGen *g, TypeTableEntry *type_entry) {
2437 }2463 }
2438}2464}
24392465
2466static BuiltinFnEntry *create_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name) {
2467 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
2468 buf_init_from_str(&builtin_fn->name, name);
2469 builtin_fn->id = id;
2470 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
2471 return builtin_fn;
2472}
2473
2474static BuiltinFnEntry *create_one_arg_builtin_fn(CodeGen *g, BuiltinFnId id, const char *name) {
2475 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, id, name);
2476 builtin_fn->return_type = nullptr; // manually determined later
2477 builtin_fn->param_count = 1;
2478 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
2479 builtin_fn->param_types[0] = nullptr; // manually checked later
2480 return builtin_fn;
2481}
2482
2440static void define_builtin_fns(CodeGen *g) {2483static void define_builtin_fns(CodeGen *g) {
2441 define_builtin_fns_int(g, g->builtin_types.entry_u8);2484 define_builtin_fns_int(g, g->builtin_types.entry_u8);
2442 define_builtin_fns_int(g, g->builtin_types.entry_u16);2485 define_builtin_fns_int(g, g->builtin_types.entry_u16);
...@@ -2447,9 +2490,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -2447,9 +2490,7 @@ static void define_builtin_fns(CodeGen *g) {
2447 define_builtin_fns_int(g, g->builtin_types.entry_i32);2490 define_builtin_fns_int(g, g->builtin_types.entry_i32);
2448 define_builtin_fns_int(g, g->builtin_types.entry_i64);2491 define_builtin_fns_int(g, g->builtin_types.entry_i64);
2449 {2492 {
2450 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);2493 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
2451 buf_init_from_str(&builtin_fn->name, "memcpy");
2452 builtin_fn->id = BuiltinFnIdMemcpy;
2453 builtin_fn->return_type = g->builtin_types.entry_void;2494 builtin_fn->return_type = g->builtin_types.entry_void;
2454 builtin_fn->param_count = 3;2495 builtin_fn->param_count = 3;
2455 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);2496 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
...@@ -2470,12 +2511,9 @@ static void define_builtin_fns(CodeGen *g) {...@@ -2470,12 +2511,9 @@ static void define_builtin_fns(CodeGen *g) {
2470 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));2511 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
24712512
2472 g->memcpy_fn_val = builtin_fn->fn_val;2513 g->memcpy_fn_val = builtin_fn->fn_val;
2473 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
2474 }2514 }
2475 {2515 {
2476 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);2516 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemset, "memset");
2477 buf_init_from_str(&builtin_fn->name, "memset");
2478 builtin_fn->id = BuiltinFnIdMemset;
2479 builtin_fn->return_type = g->builtin_types.entry_void;2517 builtin_fn->return_type = g->builtin_types.entry_void;
2480 builtin_fn->param_count = 3;2518 builtin_fn->param_count = 3;
2481 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);2519 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
...@@ -2496,8 +2534,12 @@ static void define_builtin_fns(CodeGen *g) {...@@ -2496,8 +2534,12 @@ static void define_builtin_fns(CodeGen *g) {
2496 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));2534 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
24972535
2498 g->memset_fn_val = builtin_fn->fn_val;2536 g->memset_fn_val = builtin_fn->fn_val;
2499 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
2500 }2537 }
2538 create_one_arg_builtin_fn(g, BuiltinFnIdSizeof, "sizeof");
2539 create_one_arg_builtin_fn(g, BuiltinFnIdMaxValue, "max_value");
2540 create_one_arg_builtin_fn(g, BuiltinFnIdMinValue, "min_value");
2541 create_one_arg_builtin_fn(g, BuiltinFnIdValueCount, "value_count");
2542 create_one_arg_builtin_fn(g, BuiltinFnIdTypeof, "typeof");
2501}2543}
25022544
25032545
...@@ -2780,9 +2822,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -2780,9 +2822,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
2780}2822}
27812823
2782static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {2824static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
2783 assert(type_node->type == NodeTypeType);2825 zig_panic("TODO this function needs some love");
27842826 TypeTableEntry *type_entry = get_resolved_expr(type_node)->type_entry;
2785 TypeTableEntry *type_entry = type_node->data.type.entry;
2786 assert(type_entry);2827 assert(type_entry);
27872828
2788 if (type_entry == g->builtin_types.entry_u8) {2829 if (type_entry == g->builtin_types.entry_u8) {
src/parser.cpp+395-528
...@@ -62,6 +62,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {...@@ -62,6 +62,7 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
62 case PrefixOpAddressOf: return "&";62 case PrefixOpAddressOf: return "&";
63 case PrefixOpConstAddressOf: return "&const";63 case PrefixOpConstAddressOf: return "&const";
64 case PrefixOpDereference: return "*";64 case PrefixOpDereference: return "*";
65 case PrefixOpMaybe: return "?";
65 }66 }
66 zig_unreachable();67 zig_unreachable();
67}68}
...@@ -80,8 +81,6 @@ const char *node_type_str(NodeType node_type) {...@@ -80,8 +81,6 @@ const char *node_type_str(NodeType node_type) {
80 return "FnProto";81 return "FnProto";
81 case NodeTypeParamDecl:82 case NodeTypeParamDecl:
82 return "ParamDecl";83 return "ParamDecl";
83 case NodeTypeType:
84 return "Type";
85 case NodeTypeBlock:84 case NodeTypeBlock:
86 return "Block";85 return "Block";
87 case NodeTypeBinOpExpr:86 case NodeTypeBinOpExpr:
...@@ -108,16 +107,12 @@ const char *node_type_str(NodeType node_type) {...@@ -108,16 +107,12 @@ const char *node_type_str(NodeType node_type) {
108 return "StringLiteral";107 return "StringLiteral";
109 case NodeTypeCharLiteral:108 case NodeTypeCharLiteral:
110 return "CharLiteral";109 return "CharLiteral";
111 case NodeTypeUnreachable:
112 return "Unreachable";
113 case NodeTypeSymbol:110 case NodeTypeSymbol:
114 return "Symbol";111 return "Symbol";
115 case NodeTypePrefixOpExpr:112 case NodeTypePrefixOpExpr:
116 return "PrefixOpExpr";113 return "PrefixOpExpr";
117 case NodeTypeUse:114 case NodeTypeUse:
118 return "Use";115 return "Use";
119 case NodeTypeVoid:
120 return "Void";
121 case NodeTypeBoolLiteral:116 case NodeTypeBoolLiteral:
122 return "BoolLiteral";117 return "BoolLiteral";
123 case NodeTypeNullLiteral:118 case NodeTypeNullLiteral:
...@@ -144,14 +139,12 @@ const char *node_type_str(NodeType node_type) {...@@ -144,14 +139,12 @@ const char *node_type_str(NodeType node_type) {
144 return "StructDecl";139 return "StructDecl";
145 case NodeTypeStructField:140 case NodeTypeStructField:
146 return "StructField";141 return "StructField";
147 case NodeTypeStructValueExpr:
148 return "StructValueExpr";
149 case NodeTypeStructValueField:142 case NodeTypeStructValueField:
150 return "StructValueField";143 return "StructValueField";
151 case NodeTypeCompilerFnExpr:144 case NodeTypeContainerInitExpr:
152 return "CompilerFnExpr";145 return "ContainerInitExpr";
153 case NodeTypeCompilerFnType:146 case NodeTypeArrayType:
154 return "CompilerFnType";147 return "ArrayType";
155 }148 }
156 zig_unreachable();149 zig_unreachable();
157}150}
...@@ -214,47 +207,6 @@ void ast_print(AstNode *node, int indent) {...@@ -214,47 +207,6 @@ void ast_print(AstNode *node, int indent) {
214207
215 break;208 break;
216 }209 }
217 case NodeTypeType:
218 switch (node->data.type.type) {
219 case AstNodeTypeTypePrimitive:
220 {
221 Buf *name_buf = &node->data.type.primitive_name;
222 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
223 break;
224 }
225 case AstNodeTypeTypePointer:
226 {
227 const char *const_or_mut_str = node->data.type.is_const ? "const " : "";
228 const char *noalias_or_not_str = node->data.type.is_noalias ? "noalias " : "";
229 fprintf(stderr, "%s%s PointerType\n", const_or_mut_str, noalias_or_not_str);
230
231 ast_print(node->data.type.child_type, indent + 2);
232 break;
233 }
234 case AstNodeTypeTypeArray:
235 {
236 const char *const_or_mut_str = node->data.type.is_const ? "const " : "";
237 const char *noalias_or_not_str = node->data.type.is_noalias ? "noalias " : "";
238 fprintf(stderr, "%s%s ArrayType\n", const_or_mut_str, noalias_or_not_str);
239 if (node->data.type.array_size)
240 ast_print(node->data.type.array_size, indent + 2);
241 ast_print(node->data.type.child_type, indent + 2);
242 break;
243 }
244 case AstNodeTypeTypeMaybe:
245 {
246 fprintf(stderr, "MaybeType\n");
247 ast_print(node->data.type.child_type, indent + 2);
248 break;
249 }
250 case AstNodeTypeTypeCompilerExpr:
251 {
252 fprintf(stderr, "CompilerExprType\n");
253 ast_print(node->data.type.compiler_expr, indent + 2);
254 break;
255 }
256 }
257 break;
258 case NodeTypeReturnExpr:210 case NodeTypeReturnExpr:
259 fprintf(stderr, "%s\n", node_type_str(node->type));211 fprintf(stderr, "%s\n", node_type_str(node->type));
260 if (node->data.return_expr.expr)212 if (node->data.return_expr.expr)
...@@ -348,18 +300,12 @@ void ast_print(AstNode *node, int indent) {...@@ -348,18 +300,12 @@ void ast_print(AstNode *node, int indent) {
348 fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);300 fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
349 break;301 break;
350 }302 }
351 case NodeTypeUnreachable:
352 fprintf(stderr, "Unreachable\n");
353 break;
354 case NodeTypeSymbol:303 case NodeTypeSymbol:
355 fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));304 fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
356 break;305 break;
357 case NodeTypeUse:306 case NodeTypeUse:
358 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));307 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));
359 break;308 break;
360 case NodeTypeVoid:
361 fprintf(stderr, "%s\n", node_type_str(node->type));
362 break;
363 case NodeTypeBoolLiteral:309 case NodeTypeBoolLiteral:
364 fprintf(stderr, "%s '%s'\n", node_type_str(node->type),310 fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
365 node->data.bool_literal.value ? "true" : "false");311 node->data.bool_literal.value ? "true" : "false");
...@@ -431,24 +377,28 @@ void ast_print(AstNode *node, int indent) {...@@ -431,24 +377,28 @@ void ast_print(AstNode *node, int indent) {
431 ast_print(node->data.struct_field.type, indent + 2);377 ast_print(node->data.struct_field.type, indent + 2);
432 }378 }
433 break;379 break;
434 case NodeTypeStructValueExpr:
435 fprintf(stderr, "%s\n", node_type_str(node->type));
436 ast_print(node->data.struct_val_expr.type, indent + 2);
437 for (int i = 0; i < node->data.struct_val_expr.fields.length; i += 1) {
438 AstNode *child = node->data.struct_val_expr.fields.at(i);
439 ast_print(child, indent + 2);
440 }
441 break;
442 case NodeTypeStructValueField:380 case NodeTypeStructValueField:
443 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));381 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));
444 ast_print(node->data.struct_val_field.expr, indent + 2);382 ast_print(node->data.struct_val_field.expr, indent + 2);
445 break;383 break;
446 case NodeTypeCompilerFnExpr:384 case NodeTypeContainerInitExpr:
447 fprintf(stderr, "%s\n", node_type_str(node->type));
448 break;
449 case NodeTypeCompilerFnType:
450 fprintf(stderr, "%s\n", node_type_str(node->type));385 fprintf(stderr, "%s\n", node_type_str(node->type));
386 ast_print(node->data.container_init_expr.type, indent + 2);
387 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
388 AstNode *child = node->data.container_init_expr.entries.at(i);
389 ast_print(child, indent + 2);
390 }
451 break;391 break;
392 case NodeTypeArrayType:
393 {
394 const char *const_str = node->data.array_type.is_const ? "const" : "var";
395 fprintf(stderr, "%s %s\n", node_type_str(node->type), const_str);
396 if (node->data.array_type.size) {
397 ast_print(node->data.array_type.size, indent + 2);
398 }
399 ast_print(node->data.array_type.child_type, indent + 2);
400 break;
401 }
452 }402 }
453}403}
454404
...@@ -539,9 +489,8 @@ static AstNode *ast_create_node_with_node(ParseContext *pc, NodeType type, AstNo...@@ -539,9 +489,8 @@ static AstNode *ast_create_node_with_node(ParseContext *pc, NodeType type, AstNo
539}489}
540490
541static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {491static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {
542 AstNode *node = ast_create_node(pc, NodeTypeType, token);492 AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
543 node->data.type.type = AstNodeTypeTypePrimitive;493 buf_init_from_str(&node->data.symbol_expr.symbol, "void");
544 buf_init_from_str(&node->data.type.primitive_name, "void");
545 return node;494 return node;
546}495}
547496
...@@ -961,7 +910,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma...@@ -961,7 +910,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma
961static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory);910static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory);
962static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory);911static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory);
963static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory);912static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool mandatory);
964static AstNode *ast_parse_type(ParseContext *pc, int *token_index);913static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory);
965914
966static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {915static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
967 if (token->id != token_id) {916 if (token->id != token_id) {
...@@ -1022,172 +971,42 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,...@@ -1022,172 +971,42 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,
1022 zig_unreachable();971 zig_unreachable();
1023}972}
1024973
1025static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNode *node) {
1026 node->data.type.type = AstNodeTypeTypePointer;
1027 Token *first_type_token = &pc->tokens->at(*token_index);
1028 if (first_type_token->id == TokenIdKeywordConst) {
1029 node->data.type.is_const = true;
1030 *token_index += 1;
1031 first_type_token = &pc->tokens->at(*token_index);
1032 if (first_type_token->id == TokenIdKeywordNoAlias) {
1033 node->data.type.is_noalias = true;
1034 *token_index += 1;
1035 }
1036 } else if (first_type_token->id == TokenIdKeywordNoAlias) {
1037 node->data.type.is_noalias = true;
1038 *token_index += 1;
1039 }
1040
1041 node->data.type.child_type = ast_parse_type(pc, token_index);
1042}
1043
1044/*974/*
1045CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen)975ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis)
1046*/976*/
1047static AstNode *ast_parse_compiler_fn_type(ParseContext *pc, int *token_index, bool mandatory) {977static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {
1048 Token *token = &pc->tokens->at(*token_index);978 Token *first_token = &pc->tokens->at(*token_index);
1049979
1050 if (token->id == TokenIdNumberSign) {980 if (first_token->id == TokenIdEllipsis) {
1051 *token_index += 1;981 *token_index += 1;
1052 } else if (mandatory) {
1053 ast_invalid_token_error(pc, token);
1054 } else {
1055 return nullptr;982 return nullptr;
1056 }983 }
1057984
1058 Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);985 AstNode *node = ast_create_node(pc, NodeTypeParamDecl, first_token);
1059 ast_eat_token(pc, token_index, TokenIdLParen);986 Token *name_token;
1060
1061 AstNode *node = ast_create_node(pc, NodeTypeCompilerFnType, token);
1062 ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_type.name);
1063 node->data.compiler_fn_type.type = ast_parse_type(pc, token_index);
1064
1065 ast_eat_token(pc, token_index, TokenIdRParen);
1066 return node;
1067}
1068987
1069/*988 if (first_token->id == TokenIdKeywordNoAlias) {
1070CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen)989 node->data.param_decl.is_noalias = true;
1071*/990 *token_index += 1;
1072static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, bool mandatory) {991 name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1073 Token *token = &pc->tokens->at(*token_index);992 } else if (first_token->id == TokenIdSymbol) {
1074993 name_token = first_token;
1075 if (token->id == TokenIdNumberSign) {
1076 *token_index += 1;994 *token_index += 1;
1077 } else if (mandatory) {
1078 ast_invalid_token_error(pc, token);
1079 } else {995 } else {
1080 return nullptr;996 ast_invalid_token_error(pc, first_token);
1081 }997 }
1082998
1083 Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);999 ast_buf_from_token(pc, name_token, &node->data.param_decl.name);
1084 ast_eat_token(pc, token_index, TokenIdLParen);
1085
1086 AstNode *node = ast_create_node(pc, NodeTypeCompilerFnExpr, token);
1087 ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_expr.name);
1088 node->data.compiler_fn_expr.expr = ast_parse_expression(pc, token_index, true);
1089
1090 ast_eat_token(pc, token_index, TokenIdRParen);
1091 return node;
1092}
1093
1094/*
1095Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompilerFnExpr
1096PointerType : token(Ampersand) option(token(Const)) option(token(NoAlias)) Type
1097ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) option(token(NoAlias)) Type
1098*/
1099static AstNode *ast_parse_type(ParseContext *pc, int *token_index) {
1100 Token *token = &pc->tokens->at(*token_index);
1101 AstNode *node = ast_create_node(pc, NodeTypeType, token);
1102
1103 AstNode *compiler_fn_expr = ast_parse_compiler_fn_call(pc, token_index, false);
1104 if (compiler_fn_expr) {
1105 node->data.type.type = AstNodeTypeTypeCompilerExpr;
1106 node->data.type.compiler_expr = compiler_fn_expr;
1107 return node;
1108 }
11091000
1001 Token *colon = &pc->tokens->at(*token_index);
1110 *token_index += 1;1002 *token_index += 1;
1003 ast_expect_token(pc, colon, TokenIdColon);
11111004
1112 if (token->id == TokenIdKeywordUnreachable) {1005 node->data.param_decl.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
1113 node->data.type.type = AstNodeTypeTypePrimitive;
1114 buf_init_from_str(&node->data.type.primitive_name, "unreachable");
1115 } else if (token->id == TokenIdKeywordVoid) {
1116 node->data.type.type = AstNodeTypeTypePrimitive;
1117 buf_init_from_str(&node->data.type.primitive_name, "void");
1118 } else if (token->id == TokenIdSymbol) {
1119 node->data.type.type = AstNodeTypeTypePrimitive;
1120 ast_buf_from_token(pc, token, &node->data.type.primitive_name);
1121 } else if (token->id == TokenIdAmpersand) {
1122 ast_parse_type_assume_amp(pc, token_index, node);
1123 } else if (token->id == TokenIdMaybe) {
1124 node->data.type.type = AstNodeTypeTypeMaybe;
1125 node->data.type.child_type = ast_parse_type(pc, token_index);
1126 } else if (token->id == TokenIdBoolAnd) {
1127 // Pretend that we got 2 ampersand tokens
1128 node->data.type.type = AstNodeTypeTypePointer;
1129
1130 node->data.type.child_type = ast_create_node_no_line_info(pc, NodeTypeType);
1131 node->data.type.child_type->line = token->start_line;
1132 node->data.type.child_type->column = token->start_column + 1;
1133
1134 ast_parse_type_assume_amp(pc, token_index, node->data.type.child_type);
1135 } else if (token->id == TokenIdLBracket) {
1136 node->data.type.type = AstNodeTypeTypeArray;
1137
1138 node->data.type.array_size = ast_parse_expression(pc, token_index, false);
1139
1140 ast_eat_token(pc, token_index, TokenIdRBracket);
1141
1142 Token *const_tok = &pc->tokens->at(*token_index);
1143 if (const_tok->id == TokenIdKeywordConst) {
1144 *token_index += 1;
1145 node->data.type.is_const = true;
1146
1147 Token *next_tok = &pc->tokens->at(*token_index);
1148 if (next_tok->id == TokenIdKeywordNoAlias) {
1149 *token_index += 1;
1150 node->data.type.is_noalias = true;
1151 }
1152 } else if (const_tok->id == TokenIdKeywordNoAlias) {
1153 *token_index += 1;
1154 node->data.type.is_noalias = true;
1155 }
1156
1157 node->data.type.child_type = ast_parse_type(pc, token_index);
1158 } else {
1159 ast_invalid_token_error(pc, token);
1160 }
11611006
1162 return node;1007 return node;
1163}1008}
11641009
1165/*
1166ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis)
1167*/
1168static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {
1169 Token *param_name = &pc->tokens->at(*token_index);
1170 *token_index += 1;
1171
1172 if (param_name->id == TokenIdSymbol) {
1173 AstNode *node = ast_create_node(pc, NodeTypeParamDecl, param_name);
1174
1175 ast_buf_from_token(pc, param_name, &node->data.param_decl.name);
1176
1177 Token *colon = &pc->tokens->at(*token_index);
1178 *token_index += 1;
1179 ast_expect_token(pc, colon, TokenIdColon);
1180
1181 node->data.param_decl.type = ast_parse_type(pc, token_index);
1182
1183 return node;
1184 } else if (param_name->id == TokenIdEllipsis) {
1185 return nullptr;
1186 } else {
1187 ast_invalid_token_error(pc, param_name);
1188 }
1189}
1190
11911010
1192static void ast_parse_param_decl_list(ParseContext *pc, int *token_index,1011static void ast_parse_param_decl_list(ParseContext *pc, int *token_index,
1193 ZigList<AstNode *> *params, bool *is_var_args)1012 ZigList<AstNode *> *params, bool *is_var_args)
...@@ -1274,52 +1093,222 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool...@@ -1274,52 +1093,222 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool
1274}1093}
12751094
1276/*1095/*
1277StructValueExpression : token(Symbol) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)1096ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) Expression
1278StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression
1279*/1097*/
1280static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {1098static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bool mandatory) {
1281 Token *first_token = &pc->tokens->at(*token_index);1099 Token *l_bracket = &pc->tokens->at(*token_index);
1282 AstNode *node = ast_create_node(pc, NodeTypeStructValueExpr, first_token);1100 if (l_bracket->id != TokenIdLBracket) {
1101 if (mandatory) {
1102 ast_invalid_token_error(pc, l_bracket);
1103 } else {
1104 return nullptr;
1105 }
1106 }
12831107
1284 node->data.struct_val_expr.type = ast_parse_type(pc, token_index);1108 *token_index += 1;
12851109
1286 ast_eat_token(pc, token_index, TokenIdLBrace);1110 AstNode *node = ast_create_node(pc, NodeTypeArrayType, l_bracket);
1111 node->data.array_type.size = ast_parse_expression(pc, token_index, false);
1112
1113 ast_eat_token(pc, token_index, TokenIdRBracket);
1114
1115 Token *const_tok = &pc->tokens->at(*token_index);
1116 if (const_tok->id == TokenIdKeywordConst) {
1117 *token_index += 1;
1118 node->data.array_type.is_const = true;
1119 }
1120
1121 node->data.array_type.child_type = ast_parse_expression(pc, token_index, true);
1122
1123 return node;
1124}
1125
1126/*
1127AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)
1128*/
1129static void ast_parse_asm_input_item(ParseContext *pc, int *token_index, AstNode *node) {
1130 ast_eat_token(pc, token_index, TokenIdLBracket);
1131 Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol);
1132 ast_eat_token(pc, token_index, TokenIdRBracket);
1133
1134 Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral);
1135
1136 ast_eat_token(pc, token_index, TokenIdLParen);
1137 AstNode *expr_node = ast_parse_expression(pc, token_index, true);
1138 ast_eat_token(pc, token_index, TokenIdRParen);
1139
1140 AsmInput *asm_input = allocate<AsmInput>(1);
1141 ast_buf_from_token(pc, alias, &asm_input->asm_symbolic_name);
1142 parse_string_literal(pc, constraint, &asm_input->constraint, nullptr, nullptr);
1143 asm_input->expr = expr_node;
1144 node->data.asm_expr.input_list.append(asm_input);
1145}
1146
1147/*
1148AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) Expression) token(RParen)
1149*/
1150static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNode *node) {
1151 ast_eat_token(pc, token_index, TokenIdLBracket);
1152 Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol);
1153 ast_eat_token(pc, token_index, TokenIdRBracket);
1154
1155 Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral);
1156
1157 AsmOutput *asm_output = allocate<AsmOutput>(1);
1158
1159 ast_eat_token(pc, token_index, TokenIdLParen);
1160
1161 Token *token = &pc->tokens->at(*token_index);
1162 *token_index += 1;
1163 if (token->id == TokenIdSymbol) {
1164 ast_buf_from_token(pc, token, &asm_output->variable_name);
1165 } else if (token->id == TokenIdArrow) {
1166 asm_output->return_type = ast_parse_expression(pc, token_index, true);
1167 } else {
1168 ast_invalid_token_error(pc, token);
1169 }
1170
1171 ast_eat_token(pc, token_index, TokenIdRParen);
1172
1173 ast_buf_from_token(pc, alias, &asm_output->asm_symbolic_name);
1174 parse_string_literal(pc, constraint, &asm_output->constraint, nullptr, nullptr);
1175 node->data.asm_expr.output_list.append(asm_output);
1176}
1177
1178/*
1179AsmClobbers: token(Colon) list(token(String), token(Comma))
1180*/
1181static void ast_parse_asm_clobbers(ParseContext *pc, int *token_index, AstNode *node) {
1182 Token *colon_tok = &pc->tokens->at(*token_index);
1183
1184 if (colon_tok->id != TokenIdColon)
1185 return;
1186
1187 *token_index += 1;
12871188
1288 for (;;) {1189 for (;;) {
1289 Token *token = &pc->tokens->at(*token_index);1190 Token *string_tok = &pc->tokens->at(*token_index);
1191 ast_expect_token(pc, string_tok, TokenIdStringLiteral);
1290 *token_index += 1;1192 *token_index += 1;
12911193
1292 if (token->id == TokenIdRBrace) {1194 Buf *clobber_buf = buf_alloc();
1293 return node;1195 parse_string_literal(pc, string_tok, clobber_buf, nullptr, nullptr);
1294 } else if (token->id == TokenIdDot) {1196 node->data.asm_expr.clobber_list.append(clobber_buf);
1295 Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);1197
1296 ast_eat_token(pc, token_index, TokenIdEq);1198 Token *comma = &pc->tokens->at(*token_index);
1199
1200 if (comma->id == TokenIdComma) {
1201 *token_index += 1;
1202 continue;
1203 } else {
1204 break;
1205 }
1206 }
1207}
12971208
1298 AstNode *field_node = ast_create_node(pc, NodeTypeStructValueField, token);1209/*
1210AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers)
1211*/
1212static void ast_parse_asm_input(ParseContext *pc, int *token_index, AstNode *node) {
1213 Token *colon_tok = &pc->tokens->at(*token_index);
12991214
1300 ast_buf_from_token(pc, field_name_tok, &field_node->data.struct_val_field.name);1215 if (colon_tok->id != TokenIdColon)
1301 field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true);1216 return;
13021217
1303 node->data.struct_val_expr.fields.append(field_node);1218 *token_index += 1;
13041219
1305 Token *comma_tok = &pc->tokens->at(*token_index);1220 for (;;) {
1306 if (comma_tok->id == TokenIdComma) {1221 ast_parse_asm_input_item(pc, token_index, node);
1307 *token_index += 1;1222
1308 } else if (comma_tok->id != TokenIdRBrace) {1223 Token *comma = &pc->tokens->at(*token_index);
1309 ast_invalid_token_error(pc, comma_tok);1224
1310 } else {1225 if (comma->id == TokenIdComma) {
1311 *token_index += 1;1226 *token_index += 1;
1312 return node;1227 continue;
1313 }
1314 } else {1228 } else {
1315 ast_invalid_token_error(pc, token);1229 break;
1316 }1230 }
1317 }1231 }
1232
1233 ast_parse_asm_clobbers(pc, token_index, node);
1318}1234}
13191235
1320/*1236/*
1321PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression)1237AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput)
1322KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False) | token(Null)1238*/
1239static void ast_parse_asm_output(ParseContext *pc, int *token_index, AstNode *node) {
1240 Token *colon_tok = &pc->tokens->at(*token_index);
1241
1242 if (colon_tok->id != TokenIdColon)
1243 return;
1244
1245 *token_index += 1;
1246
1247 for (;;) {
1248 ast_parse_asm_output_item(pc, token_index, node);
1249
1250 Token *comma = &pc->tokens->at(*token_index);
1251
1252 if (comma->id == TokenIdComma) {
1253 *token_index += 1;
1254 continue;
1255 } else {
1256 break;
1257 }
1258 }
1259
1260 ast_parse_asm_input(pc, token_index, node);
1261}
1262
1263/*
1264AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen)
1265*/
1266static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mandatory) {
1267 Token *asm_token = &pc->tokens->at(*token_index);
1268
1269 if (asm_token->id != TokenIdKeywordAsm) {
1270 if (mandatory) {
1271 ast_invalid_token_error(pc, asm_token);
1272 } else {
1273 return nullptr;
1274 }
1275 }
1276
1277 AstNode *node = ast_create_node(pc, NodeTypeAsmExpr, asm_token);
1278
1279 *token_index += 1;
1280 Token *lparen_tok = &pc->tokens->at(*token_index);
1281
1282 if (lparen_tok->id == TokenIdKeywordVolatile) {
1283 node->data.asm_expr.is_volatile = true;
1284
1285 *token_index += 1;
1286 lparen_tok = &pc->tokens->at(*token_index);
1287 }
1288
1289 ast_expect_token(pc, lparen_tok, TokenIdLParen);
1290 *token_index += 1;
1291
1292 Token *template_tok = &pc->tokens->at(*token_index);
1293 ast_expect_token(pc, template_tok, TokenIdStringLiteral);
1294 *token_index += 1;
1295
1296 parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template, nullptr,
1297 &node->data.asm_expr.offset_map);
1298 parse_asm_template(pc, node);
1299
1300 ast_parse_asm_output(pc, token_index, node);
1301
1302 Token *rparen_tok = &pc->tokens->at(*token_index);
1303 ast_expect_token(pc, rparen_tok, TokenIdRParen);
1304 *token_index += 1;
1305
1306 return node;
1307}
1308
1309/*
1310PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | token(Symbol) | (token(AtSign) token(Symbol) FnCallExpression) | ArrayType | AsmExpression
1311KeywordLiteral : token(True) | token(False) | token(Null) | token(Break) | token(Continue)
1323*/1312*/
1324static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {1313static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
1325 Token *token = &pc->tokens->at(*token_index);1314 Token *token = &pc->tokens->at(*token_index);
...@@ -1339,14 +1328,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1339,14 +1328,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1339 node->data.char_literal.value = parse_char_literal(pc, token);1328 node->data.char_literal.value = parse_char_literal(pc, token);
1340 *token_index += 1;1329 *token_index += 1;
1341 return node;1330 return node;
1342 } else if (token->id == TokenIdKeywordUnreachable) {
1343 AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
1344 *token_index += 1;
1345 return node;
1346 } else if (token->id == TokenIdKeywordVoid) {
1347 AstNode *node = ast_create_node(pc, NodeTypeVoid, token);
1348 *token_index += 1;
1349 return node;
1350 } else if (token->id == TokenIdKeywordTrue) {1331 } else if (token->id == TokenIdKeywordTrue) {
1351 AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token);1332 AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token);
1352 node->data.bool_literal.value = true;1333 node->data.bool_literal.value = true;
...@@ -1357,8 +1338,16 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1357,8 +1338,16 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1357 node->data.bool_literal.value = false;1338 node->data.bool_literal.value = false;
1358 *token_index += 1;1339 *token_index += 1;
1359 return node;1340 return node;
1360 } else if (token->id == TokenIdKeywordNull) {1341 } else if (token->id == TokenIdKeywordNull) {
1361 AstNode *node = ast_create_node(pc, NodeTypeNullLiteral, token);1342 AstNode *node = ast_create_node(pc, NodeTypeNullLiteral, token);
1343 *token_index += 1;
1344 return node;
1345 } else if (token->id == TokenIdKeywordBreak) {
1346 AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
1347 *token_index += 1;
1348 return node;
1349 } else if (token->id == TokenIdKeywordContinue) {
1350 AstNode *node = ast_create_node(pc, NodeTypeContinue, token);
1362 *token_index += 1;1351 *token_index += 1;
1363 return node;1352 return node;
1364 } else if (token->id == TokenIdAtSign) {1353 } else if (token->id == TokenIdAtSign) {
...@@ -1374,16 +1363,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1374,16 +1363,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1374 node->data.fn_call_expr.is_builtin = true;1363 node->data.fn_call_expr.is_builtin = true;
1375 return node;1364 return node;
1376 } else if (token->id == TokenIdSymbol) {1365 } else if (token->id == TokenIdSymbol) {
1377 Token *next_token = &pc->tokens->at(*token_index + 1);1366 *token_index += 1;
13781367 AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
1379 if (next_token->id == TokenIdLBrace) {1368 ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol);
1380 return ast_parse_struct_val_expr(pc, token_index);1369 return node;
1381 } else {
1382 *token_index += 1;
1383 AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
1384 ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol);
1385 return node;
1386 }
1387 } else if (token->id == TokenIdKeywordGoto) {1370 } else if (token->id == TokenIdKeywordGoto) {
1388 AstNode *node = ast_create_node(pc, NodeTypeGoto, token);1371 AstNode *node = ast_create_node(pc, NodeTypeGoto, token);
1389 *token_index += 1;1372 *token_index += 1;
...@@ -1394,14 +1377,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1394,14 +1377,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
13941377
1395 ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name);1378 ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name);
1396 return node;1379 return node;
1397 } else if (token->id == TokenIdKeywordBreak) {
1398 AstNode *node = ast_create_node(pc, NodeTypeBreak, token);
1399 *token_index += 1;
1400 return node;
1401 } else if (token->id == TokenIdKeywordContinue) {
1402 AstNode *node = ast_create_node(pc, NodeTypeContinue, token);
1403 *token_index += 1;
1404 return node;
1405 }1380 }
14061381
1407 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);1382 AstNode *grouped_expr_node = ast_parse_grouped_expr(pc, token_index, false);
...@@ -1414,9 +1389,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1414,9 +1389,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1414 return block_expr_node;1389 return block_expr_node;
1415 }1390 }
14161391
1417 AstNode *compiler_fn_type = ast_parse_compiler_fn_type(pc, token_index, false);1392 AstNode *array_type_node = ast_parse_array_type_expr(pc, token_index, false);
1418 if (compiler_fn_type) {1393 if (array_type_node) {
1419 return compiler_fn_type;1394 return array_type_node;
1395 }
1396
1397 AstNode *asm_expr = ast_parse_asm_expr(pc, token_index, false);
1398 if (asm_expr) {
1399 return asm_expr;
1420 }1400 }
14211401
1422 if (!mandatory)1402 if (!mandatory)
...@@ -1426,11 +1406,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool...@@ -1426,11 +1406,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
1426}1406}
14271407
1428/*1408/*
1429SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)1409SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
1430FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)1410FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
1431ArrayAccessExpression : token(LBracket) Expression token(RBracket)1411ArrayAccessExpression : token(LBracket) Expression token(RBracket)
1432SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))1412SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
1433FieldAccessExpression : token(Dot) token(Symbol)1413FieldAccessExpression : token(Dot) token(Symbol)
1414ContainerInitExpression : token(LBrace) ContainerInitBody token(RBrace)
1415ContainerInitBody : list(StructLiteralField, token(Comma)) | list(Expression, token(Comma))
1416StructLiteralField : token(Dot) token(Symbol) token(Eq) Expression
1434*/1417*/
1435static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {1418static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
1436 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);1419 AstNode *primary_expr = ast_parse_primary_expr(pc, token_index, mandatory);
...@@ -1439,16 +1422,16 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1439,16 +1422,16 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
1439 }1422 }
14401423
1441 while (true) {1424 while (true) {
1442 Token *token = &pc->tokens->at(*token_index);1425 Token *first_token = &pc->tokens->at(*token_index);
1443 if (token->id == TokenIdLParen) {1426 if (first_token->id == TokenIdLParen) {
1444 *token_index += 1;1427 *token_index += 1;
14451428
1446 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token);1429 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token);
1447 node->data.fn_call_expr.fn_ref_expr = primary_expr;1430 node->data.fn_call_expr.fn_ref_expr = primary_expr;
1448 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);1431 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
14491432
1450 primary_expr = node;1433 primary_expr = node;
1451 } else if (token->id == TokenIdLBracket) {1434 } else if (first_token->id == TokenIdLBracket) {
1452 *token_index += 1;1435 *token_index += 1;
14531436
1454 AstNode *expr_node = ast_parse_expression(pc, token_index, true);1437 AstNode *expr_node = ast_parse_expression(pc, token_index, true);
...@@ -1458,7 +1441,7 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1458,7 +1441,7 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
1458 if (ellipsis_or_r_bracket->id == TokenIdEllipsis) {1441 if (ellipsis_or_r_bracket->id == TokenIdEllipsis) {
1459 *token_index += 1;1442 *token_index += 1;
14601443
1461 AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, token);1444 AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, first_token);
1462 node->data.slice_expr.array_ref_expr = primary_expr;1445 node->data.slice_expr.array_ref_expr = primary_expr;
1463 node->data.slice_expr.start = expr_node;1446 node->data.slice_expr.start = expr_node;
1464 node->data.slice_expr.end = ast_parse_expression(pc, token_index, false);1447 node->data.slice_expr.end = ast_parse_expression(pc, token_index, false);
...@@ -1475,23 +1458,88 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo...@@ -1475,23 +1458,88 @@ static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, boo
1475 } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {1458 } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {
1476 *token_index += 1;1459 *token_index += 1;
14771460
1478 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token);1461 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, first_token);
1479 node->data.array_access_expr.array_ref_expr = primary_expr;1462 node->data.array_access_expr.array_ref_expr = primary_expr;
1480 node->data.array_access_expr.subscript = expr_node;1463 node->data.array_access_expr.subscript = expr_node;
14811464
1482 primary_expr = node;1465 primary_expr = node;
1483 } else {1466 } else {
1484 ast_invalid_token_error(pc, token);1467 ast_invalid_token_error(pc, first_token);
1485 }1468 }
1486 } else if (token->id == TokenIdDot) {1469 } else if (first_token->id == TokenIdDot) {
1487 *token_index += 1;1470 *token_index += 1;
14881471
1489 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);1472 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
14901473
1491 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, token);1474 AstNode *node = ast_create_node(pc, NodeTypeFieldAccessExpr, first_token);
1492 node->data.field_access_expr.struct_expr = primary_expr;1475 node->data.field_access_expr.struct_expr = primary_expr;
1493 ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name);1476 ast_buf_from_token(pc, name_token, &node->data.field_access_expr.field_name);
14941477
1478 primary_expr = node;
1479 } else if (first_token->id == TokenIdLBrace) {
1480 *token_index += 1;
1481
1482 AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, first_token);
1483 node->data.container_init_expr.type = primary_expr;
1484
1485 Token *token = &pc->tokens->at(*token_index);
1486 if (token->id == TokenIdDot) {
1487 for (;;) {
1488 if (token->id == TokenIdDot) {
1489 ast_eat_token(pc, token_index, TokenIdDot);
1490 Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
1491 ast_eat_token(pc, token_index, TokenIdEq);
1492
1493 AstNode *field_node = ast_create_node(pc, NodeTypeStructValueField, token);
1494
1495 ast_buf_from_token(pc, field_name_tok, &field_node->data.struct_val_field.name);
1496 field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true);
1497
1498 node->data.container_init_expr.entries.append(field_node);
1499
1500 Token *comma_tok = &pc->tokens->at(*token_index);
1501 if (comma_tok->id == TokenIdComma) {
1502 *token_index += 1;
1503 token = &pc->tokens->at(*token_index);
1504 continue;
1505 } else if (comma_tok->id != TokenIdRBrace) {
1506 ast_invalid_token_error(pc, comma_tok);
1507 } else {
1508 *token_index += 1;
1509 break;
1510 }
1511 } else if (token->id == TokenIdRBrace) {
1512 *token_index += 1;
1513 break;
1514 } else {
1515 ast_invalid_token_error(pc, token);
1516 }
1517 }
1518
1519 } else {
1520 for (;;) {
1521 if (token->id == TokenIdRBrace) {
1522 *token_index += 1;
1523 break;
1524 } else {
1525 AstNode *elem_node = ast_parse_expression(pc, token_index, true);
1526 node->data.container_init_expr.entries.append(elem_node);
1527
1528 Token *comma_tok = &pc->tokens->at(*token_index);
1529 if (comma_tok->id == TokenIdComma) {
1530 *token_index += 1;
1531 token = &pc->tokens->at(*token_index);
1532 continue;
1533 } else if (comma_tok->id != TokenIdRBrace) {
1534 ast_invalid_token_error(pc, comma_tok);
1535 } else {
1536 *token_index += 1;
1537 break;
1538 }
1539 }
1540 }
1541 }
1542
1495 primary_expr = node;1543 primary_expr = node;
1496 } else {1544 } else {
1497 return primary_expr;1545 return primary_expr;
...@@ -1506,56 +1554,54 @@ static PrefixOp tok_to_prefix_op(Token *token) {...@@ -1506,56 +1554,54 @@ static PrefixOp tok_to_prefix_op(Token *token) {
1506 case TokenIdTilde: return PrefixOpBinNot;1554 case TokenIdTilde: return PrefixOpBinNot;
1507 case TokenIdAmpersand: return PrefixOpAddressOf;1555 case TokenIdAmpersand: return PrefixOpAddressOf;
1508 case TokenIdStar: return PrefixOpDereference;1556 case TokenIdStar: return PrefixOpDereference;
1557 case TokenIdMaybe: return PrefixOpMaybe;
1558 case TokenIdBoolAnd: return PrefixOpAddressOf;
1509 default: return PrefixOpInvalid;1559 default: return PrefixOpInvalid;
1510 }1560 }
1511}1561}
15121562
1513/*1563/*
1564PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
1514PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))1565PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))
1515*/1566*/
1516static PrefixOp ast_parse_prefix_op(ParseContext *pc, int *token_index, bool mandatory) {1567static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
1517 Token *token = &pc->tokens->at(*token_index);1568 Token *token = &pc->tokens->at(*token_index);
1518 PrefixOp result = tok_to_prefix_op(token);1569 PrefixOp prefix_op = tok_to_prefix_op(token);
1519 if (result == PrefixOpInvalid) {1570 if (prefix_op == PrefixOpInvalid) {
1520 if (mandatory) {1571 return ast_parse_suffix_op_expr(pc, token_index, mandatory);
1521 ast_invalid_token_error(pc, token);
1522 } else {
1523 return PrefixOpInvalid;
1524 }
1525 }1572 }
1526 *token_index += 1;1573 *token_index += 1;
15271574
1528 if (result == PrefixOpAddressOf) {1575 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
1576 AstNode *parent_node = node;
1577 if (token->id == TokenIdBoolAnd) {
1578 // pretend that we got 2 ampersand tokens
1579
1580 parent_node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
1581 parent_node->data.prefix_op_expr.primary_expr = node;
1582 parent_node->data.prefix_op_expr.prefix_op = PrefixOpAddressOf;
1583
1584 node->column += 1;
1585 }
1586
1587 if (prefix_op == PrefixOpAddressOf) {
1529 Token *token = &pc->tokens->at(*token_index);1588 Token *token = &pc->tokens->at(*token_index);
1530 if (token->id == TokenIdKeywordConst) {1589 if (token->id == TokenIdKeywordConst) {
1531 *token_index += 1;1590 *token_index += 1;
1532 result = PrefixOpConstAddressOf;1591 prefix_op = PrefixOpConstAddressOf;
1533 }1592 }
1534 }1593 }
15351594
1536 return result;
1537}
1538
1539/*
1540PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
1541*/
1542static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
1543 Token *token = &pc->tokens->at(*token_index);
1544 PrefixOp prefix_op = ast_parse_prefix_op(pc, token_index, false);
1545 if (prefix_op == PrefixOpInvalid)
1546 return ast_parse_suffix_op_expr(pc, token_index, mandatory);
1547
1548 AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true);1595 AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true);
1549 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
1550 node->data.prefix_op_expr.primary_expr = prefix_op_expr;1596 node->data.prefix_op_expr.primary_expr = prefix_op_expr;
1551 node->data.prefix_op_expr.prefix_op = prefix_op;1597 node->data.prefix_op_expr.prefix_op = prefix_op;
15521598
1553 return node;1599 return parent_node;
1554}1600}
15551601
15561602
1557/*1603/*
1558CastExpression : CastExpression token(as) Type | PrefixOpExpression1604CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
1559*/1605*/
1560static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {1606static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {
1561 AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory);1607 AstNode *operand_1 = ast_parse_prefix_op_expr(pc, token_index, mandatory);
...@@ -1571,7 +1617,7 @@ static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bo...@@ -1571,7 +1617,7 @@ static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bo
1571 AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw);1617 AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw);
1572 node->data.cast_expr.expr = operand_1;1618 node->data.cast_expr.expr = operand_1;
15731619
1574 node->data.cast_expr.type = ast_parse_type(pc, token_index);1620 node->data.cast_expr.type = ast_parse_primary_expr(pc, token_index, true);
15751621
1576 operand_1 = node;1622 operand_1 = node;
1577 }1623 }
...@@ -1899,7 +1945,7 @@ static AstNode *ast_parse_else(ParseContext *pc, int *token_index, bool mandator...@@ -1899,7 +1945,7 @@ static AstNode *ast_parse_else(ParseContext *pc, int *token_index, bool mandator
1899/*1945/*
1900IfExpression : IfVarExpression | IfBoolExpression1946IfExpression : IfVarExpression | IfBoolExpression
1901IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)1947IfBoolExpression : token(If) token(LParen) Expression token(RParen) Expression option(Else)
1902IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(token(Colon) Type) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)1948IfVarExpression : token(If) token(LParen) (token(Const) | token(Var)) token(Symbol) option(Expression) Token(MaybeAssign) Expression token(RParen) Expression Option(Else)
1903*/1949*/
1904static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory) {1950static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory) {
1905 Token *if_tok = &pc->tokens->at(*token_index);1951 Token *if_tok = &pc->tokens->at(*token_index);
...@@ -1924,11 +1970,12 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda...@@ -1924,11 +1970,12 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
1924 ast_buf_from_token(pc, name_token, &node->data.if_var_expr.var_decl.symbol);1970 ast_buf_from_token(pc, name_token, &node->data.if_var_expr.var_decl.symbol);
19251971
1926 Token *eq_or_colon = &pc->tokens->at(*token_index);1972 Token *eq_or_colon = &pc->tokens->at(*token_index);
1927 *token_index += 1;
1928 if (eq_or_colon->id == TokenIdMaybeAssign) {1973 if (eq_or_colon->id == TokenIdMaybeAssign) {
1974 *token_index += 1;
1929 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);1975 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
1930 } else if (eq_or_colon->id == TokenIdColon) {1976 } else if (eq_or_colon->id == TokenIdColon) {
1931 node->data.if_var_expr.var_decl.type = ast_parse_type(pc, token_index);1977 *token_index += 1;
1978 node->data.if_var_expr.var_decl.type = ast_parse_expression(pc, token_index, true);
19321979
1933 ast_eat_token(pc, token_index, TokenIdMaybeAssign);1980 ast_eat_token(pc, token_index, TokenIdMaybeAssign);
1934 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);1981 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
...@@ -1967,7 +2014,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m...@@ -1967,7 +2014,7 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
1967}2014}
19682015
1969/*2016/*
1970VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))2017VariableDeclaration : option(FnVisibleMod) (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) UnwrapMaybeExpression option(token(Eq) Expression))
1971*/2018*/
1972static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {2019static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {
1973 Token *first_token = &pc->tokens->at(*token_index);2020 Token *first_token = &pc->tokens->at(*token_index);
...@@ -2008,8 +2055,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token...@@ -2008,8 +2055,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
2008 node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);2055 node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
2009 return node;2056 return node;
2010 } else if (eq_or_colon->id == TokenIdColon) {2057 } else if (eq_or_colon->id == TokenIdColon) {
2011 node->data.variable_declaration.type = ast_parse_type(pc, token_index);2058 node->data.variable_declaration.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
2012
2013 Token *eq_token = &pc->tokens->at(*token_index);2059 Token *eq_token = &pc->tokens->at(*token_index);
2014 if (eq_token->id == TokenIdEq) {2060 if (eq_token->id == TokenIdEq) {
2015 *token_index += 1;2061 *token_index += 1;
...@@ -2138,6 +2184,7 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool manda...@@ -2138,6 +2184,7 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool manda
2138/*2184/*
2139UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression2185UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression
2140*/2186*/
2187// this is currently the first child expression of assignment
2141static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory) {2188static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory) {
2142 AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);2189 AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);
2143 if (!lhs)2190 if (!lhs)
...@@ -2185,190 +2232,7 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand...@@ -2185,190 +2232,7 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand
2185}2232}
21862233
2187/*2234/*
2188AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)2235NonBlockExpression : ReturnExpression | AssignmentExpression
2189*/
2190static void ast_parse_asm_input_item(ParseContext *pc, int *token_index, AstNode *node) {
2191 ast_eat_token(pc, token_index, TokenIdLBracket);
2192 Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol);
2193 ast_eat_token(pc, token_index, TokenIdRBracket);
2194
2195 Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral);
2196
2197 ast_eat_token(pc, token_index, TokenIdLParen);
2198 AstNode *expr_node = ast_parse_expression(pc, token_index, true);
2199 ast_eat_token(pc, token_index, TokenIdRParen);
2200
2201 AsmInput *asm_input = allocate<AsmInput>(1);
2202 ast_buf_from_token(pc, alias, &asm_input->asm_symbolic_name);
2203 parse_string_literal(pc, constraint, &asm_input->constraint, nullptr, nullptr);
2204 asm_input->expr = expr_node;
2205 node->data.asm_expr.input_list.append(asm_input);
2206}
2207
2208/*
2209AsmOutputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) (token(Symbol) | token(Arrow) Type) token(RParen)
2210*/
2211static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNode *node) {
2212 ast_eat_token(pc, token_index, TokenIdLBracket);
2213 Token *alias = ast_eat_token(pc, token_index, TokenIdSymbol);
2214 ast_eat_token(pc, token_index, TokenIdRBracket);
2215
2216 Token *constraint = ast_eat_token(pc, token_index, TokenIdStringLiteral);
2217
2218 AsmOutput *asm_output = allocate<AsmOutput>(1);
2219
2220 ast_eat_token(pc, token_index, TokenIdLParen);
2221
2222 Token *token = &pc->tokens->at(*token_index);
2223 *token_index += 1;
2224 if (token->id == TokenIdSymbol) {
2225 ast_buf_from_token(pc, token, &asm_output->variable_name);
2226 } else if (token->id == TokenIdArrow) {
2227 asm_output->return_type = ast_parse_type(pc, token_index);
2228 } else {
2229 ast_invalid_token_error(pc, token);
2230 }
2231
2232 ast_eat_token(pc, token_index, TokenIdRParen);
2233
2234 ast_buf_from_token(pc, alias, &asm_output->asm_symbolic_name);
2235 parse_string_literal(pc, constraint, &asm_output->constraint, nullptr, nullptr);
2236 node->data.asm_expr.output_list.append(asm_output);
2237}
2238
2239/*
2240AsmClobbers: token(Colon) list(token(String), token(Comma))
2241*/
2242static void ast_parse_asm_clobbers(ParseContext *pc, int *token_index, AstNode *node) {
2243 Token *colon_tok = &pc->tokens->at(*token_index);
2244
2245 if (colon_tok->id != TokenIdColon)
2246 return;
2247
2248 *token_index += 1;
2249
2250 for (;;) {
2251 Token *string_tok = &pc->tokens->at(*token_index);
2252 ast_expect_token(pc, string_tok, TokenIdStringLiteral);
2253 *token_index += 1;
2254
2255 Buf *clobber_buf = buf_alloc();
2256 parse_string_literal(pc, string_tok, clobber_buf, nullptr, nullptr);
2257 node->data.asm_expr.clobber_list.append(clobber_buf);
2258
2259 Token *comma = &pc->tokens->at(*token_index);
2260
2261 if (comma->id == TokenIdComma) {
2262 *token_index += 1;
2263 continue;
2264 } else {
2265 break;
2266 }
2267 }
2268}
2269
2270/*
2271AsmInput : token(Colon) list(AsmInputItem, token(Comma)) option(AsmClobbers)
2272*/
2273static void ast_parse_asm_input(ParseContext *pc, int *token_index, AstNode *node) {
2274 Token *colon_tok = &pc->tokens->at(*token_index);
2275
2276 if (colon_tok->id != TokenIdColon)
2277 return;
2278
2279 *token_index += 1;
2280
2281 for (;;) {
2282 ast_parse_asm_input_item(pc, token_index, node);
2283
2284 Token *comma = &pc->tokens->at(*token_index);
2285
2286 if (comma->id == TokenIdComma) {
2287 *token_index += 1;
2288 continue;
2289 } else {
2290 break;
2291 }
2292 }
2293
2294 ast_parse_asm_clobbers(pc, token_index, node);
2295}
2296
2297/*
2298AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput)
2299*/
2300static void ast_parse_asm_output(ParseContext *pc, int *token_index, AstNode *node) {
2301 Token *colon_tok = &pc->tokens->at(*token_index);
2302
2303 if (colon_tok->id != TokenIdColon)
2304 return;
2305
2306 *token_index += 1;
2307
2308 for (;;) {
2309 ast_parse_asm_output_item(pc, token_index, node);
2310
2311 Token *comma = &pc->tokens->at(*token_index);
2312
2313 if (comma->id == TokenIdComma) {
2314 *token_index += 1;
2315 continue;
2316 } else {
2317 break;
2318 }
2319 }
2320
2321 ast_parse_asm_input(pc, token_index, node);
2322}
2323
2324/*
2325AsmExpression : token(Asm) option(token(Volatile)) token(LParen) token(String) option(AsmOutput) token(RParen)
2326*/
2327static AstNode *ast_parse_asm_expr(ParseContext *pc, int *token_index, bool mandatory) {
2328 Token *asm_token = &pc->tokens->at(*token_index);
2329
2330 if (asm_token->id != TokenIdKeywordAsm) {
2331 if (mandatory) {
2332 ast_invalid_token_error(pc, asm_token);
2333 } else {
2334 return nullptr;
2335 }
2336 }
2337
2338 AstNode *node = ast_create_node(pc, NodeTypeAsmExpr, asm_token);
2339
2340 *token_index += 1;
2341 Token *lparen_tok = &pc->tokens->at(*token_index);
2342
2343 if (lparen_tok->id == TokenIdKeywordVolatile) {
2344 node->data.asm_expr.is_volatile = true;
2345
2346 *token_index += 1;
2347 lparen_tok = &pc->tokens->at(*token_index);
2348 }
2349
2350 ast_expect_token(pc, lparen_tok, TokenIdLParen);
2351 *token_index += 1;
2352
2353 Token *template_tok = &pc->tokens->at(*token_index);
2354 ast_expect_token(pc, template_tok, TokenIdStringLiteral);
2355 *token_index += 1;
2356
2357 parse_string_literal(pc, template_tok, &node->data.asm_expr.asm_template, nullptr,
2358 &node->data.asm_expr.offset_map);
2359 parse_asm_template(pc, node);
2360
2361 ast_parse_asm_output(pc, token_index, node);
2362
2363 Token *rparen_tok = &pc->tokens->at(*token_index);
2364 ast_expect_token(pc, rparen_tok, TokenIdRParen);
2365 *token_index += 1;
2366
2367 return node;
2368}
2369
2370/*
2371NonBlockExpression : ReturnExpression | AssignmentExpression | AsmExpression
2372*/2236*/
2373static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {2237static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
2374 Token *token = &pc->tokens->at(*token_index);2238 Token *token = &pc->tokens->at(*token_index);
...@@ -2381,10 +2245,6 @@ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, boo...@@ -2381,10 +2245,6 @@ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, boo
2381 if (ass_expr)2245 if (ass_expr)
2382 return ass_expr;2246 return ass_expr;
23832247
2384 AstNode *asm_expr = ast_parse_asm_expr(pc, token_index, false);
2385 if (asm_expr)
2386 return asm_expr;
2387
2388 if (mandatory)2248 if (mandatory)
2389 ast_invalid_token_error(pc, token);2249 ast_invalid_token_error(pc, token);
23902250
...@@ -2440,6 +2300,14 @@ static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandato...@@ -2440,6 +2300,14 @@ static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandato
2440 return node;2300 return node;
2441}2301}
24422302
2303static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
2304 AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, token);
2305 node->data.container_init_expr.type = ast_create_node(pc, NodeTypeSymbol, token);
2306 node->data.container_init_expr.kind = ContainerInitKindArray;
2307 buf_init_from_str(&node->data.container_init_expr.type->data.symbol_expr.symbol, "void");
2308 return node;
2309}
2310
2443/*2311/*
2444Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)2312Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
2445Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression2313Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression
...@@ -2478,7 +2346,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato...@@ -2478,7 +2346,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
2478 if (!statement_node) {2346 if (!statement_node) {
2479 statement_node = ast_parse_non_block_expr(pc, token_index, false);2347 statement_node = ast_parse_non_block_expr(pc, token_index, false);
2480 if (!statement_node) {2348 if (!statement_node) {
2481 statement_node = ast_create_node(pc, NodeTypeVoid, last_token);2349 statement_node = ast_create_void_expr(pc, last_token);
2482 }2350 }
2483 }2351 }
2484 }2352 }
...@@ -2501,7 +2369,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato...@@ -2501,7 +2369,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
2501}2369}
25022370
2503/*2371/*
2504FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(token(Arrow) Type)2372FnProto : many(Directive) option(FnVisibleMod) token(Fn) token(Symbol) ParamDeclList option(Expression)
2505*/2373*/
2506static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) {2374static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) {
2507 Token *first_token = &pc->tokens->at(*token_index);2375 Token *first_token = &pc->tokens->at(*token_index);
...@@ -2552,19 +2420,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand...@@ -2552,19 +2420,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
25522420
2553 ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);2421 ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);
25542422
2555 Token *arrow = &pc->tokens->at(*token_index);2423 Token *next_token = &pc->tokens->at(*token_index);
2556 if (arrow->id == TokenIdArrow) {2424 node->data.fn_proto.return_type = ast_parse_expression(pc, token_index, false);
2557 *token_index += 1;2425 if (!node->data.fn_proto.return_type) {
2558 node->data.fn_proto.return_type = ast_parse_type(pc, token_index);2426 node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token);
2559 } else {
2560 node->data.fn_proto.return_type = ast_create_void_type_node(pc, arrow);
2561 }2427 }
25622428
2563 return node;2429 return node;
2564}2430}
25652431
2566/*2432/*
2567FnDef : FnProto Block2433FnDef : FnProto token(FatArrow) Block
2568*/2434*/
2569static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) {2435static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) {
2570 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory);2436 AstNode *fn_proto = ast_parse_fn_proto(pc, token_index, mandatory);
...@@ -2573,6 +2439,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandat...@@ -2573,6 +2439,7 @@ static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandat
2573 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);2439 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);
25742440
2575 node->data.fn_def.fn_proto = fn_proto;2441 node->data.fn_def.fn_proto = fn_proto;
2442 ast_eat_token(pc, token_index, TokenIdFatArrow);
2576 node->data.fn_def.body = ast_parse_block(pc, token_index, true);2443 node->data.fn_def.body = ast_parse_block(pc, token_index, true);
25772444
2578 return node;2445 return node;
...@@ -2709,7 +2576,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {...@@ -2709,7 +2576,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {
2709/*2576/*
2710ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)2577ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
2711StructMember: StructField | FnDecl2578StructMember: StructField | FnDecl
2712StructField : token(Symbol) token(Colon) Type token(Comma)2579StructField : token(Symbol) option(token(Colon) Expression) token(Comma))
2713*/2580*/
2714static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {2581static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
2715 Token *first_token = &pc->tokens->at(*token_index);2582 Token *first_token = &pc->tokens->at(*token_index);
...@@ -2792,16 +2659,16 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {...@@ -2792,16 +2659,16 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
27922659
2793 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);2660 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);
27942661
2795 Token *colon_tok = &pc->tokens->at(*token_index);2662 Token *expr_or_comma = &pc->tokens->at(*token_index);
2796 if (colon_tok->id == TokenIdColon) {2663 if (expr_or_comma->id == TokenIdComma) {
2664 field_node->data.struct_field.type = ast_create_void_type_node(pc, expr_or_comma);
2797 *token_index += 1;2665 *token_index += 1;
2798 field_node->data.struct_field.type = ast_parse_type(pc, token_index);
2799 } else {2666 } else {
2800 field_node->data.struct_field.type = ast_create_void_type_node(pc, colon_tok);2667 ast_eat_token(pc, token_index, TokenIdColon);
2668 field_node->data.struct_field.type = ast_parse_expression(pc, token_index, true);
2669 ast_eat_token(pc, token_index, TokenIdComma);
2801 }2670 }
28022671
2803 ast_eat_token(pc, token_index, TokenIdComma);
2804
2805 node->data.struct_decl.fields.append(field_node);2672 node->data.struct_decl.fields.append(field_node);
2806 } else {2673 } else {
2807 ast_invalid_token_error(pc, token);2674 ast_invalid_token_error(pc, token);
src/tokenizer.cpp+6-6
...@@ -207,8 +207,6 @@ static void end_token(Tokenize *t) {...@@ -207,8 +207,6 @@ static void end_token(Tokenize *t) {
207 t->cur_tok->id = TokenIdKeywordConst;207 t->cur_tok->id = TokenIdKeywordConst;
208 } else if (mem_eql_str(token_mem, token_len, "extern")) {208 } else if (mem_eql_str(token_mem, token_len, "extern")) {
209 t->cur_tok->id = TokenIdKeywordExtern;209 t->cur_tok->id = TokenIdKeywordExtern;
210 } else if (mem_eql_str(token_mem, token_len, "unreachable")) {
211 t->cur_tok->id = TokenIdKeywordUnreachable;
212 } else if (mem_eql_str(token_mem, token_len, "pub")) {210 } else if (mem_eql_str(token_mem, token_len, "pub")) {
213 t->cur_tok->id = TokenIdKeywordPub;211 t->cur_tok->id = TokenIdKeywordPub;
214 } else if (mem_eql_str(token_mem, token_len, "export")) {212 } else if (mem_eql_str(token_mem, token_len, "export")) {
...@@ -217,8 +215,6 @@ static void end_token(Tokenize *t) {...@@ -217,8 +215,6 @@ static void end_token(Tokenize *t) {
217 t->cur_tok->id = TokenIdKeywordAs;215 t->cur_tok->id = TokenIdKeywordAs;
218 } else if (mem_eql_str(token_mem, token_len, "use")) {216 } else if (mem_eql_str(token_mem, token_len, "use")) {
219 t->cur_tok->id = TokenIdKeywordUse;217 t->cur_tok->id = TokenIdKeywordUse;
220 } else if (mem_eql_str(token_mem, token_len, "void")) {
221 t->cur_tok->id = TokenIdKeywordVoid;
222 } else if (mem_eql_str(token_mem, token_len, "true")) {218 } else if (mem_eql_str(token_mem, token_len, "true")) {
223 t->cur_tok->id = TokenIdKeywordTrue;219 t->cur_tok->id = TokenIdKeywordTrue;
224 } else if (mem_eql_str(token_mem, token_len, "false")) {220 } else if (mem_eql_str(token_mem, token_len, "false")) {
...@@ -553,6 +549,11 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -553,6 +549,11 @@ void tokenize(Buf *buf, Tokenization *out) {
553 end_token(&t);549 end_token(&t);
554 t.state = TokenizeStateStart;550 t.state = TokenizeStateStart;
555 break;551 break;
552 case '>':
553 t.cur_tok->id = TokenIdFatArrow;
554 end_token(&t);
555 t.state = TokenizeStateStart;
556 break;
556 default:557 default:
557 t.pos -= 1;558 t.pos -= 1;
558 end_token(&t);559 end_token(&t);
...@@ -1009,12 +1010,10 @@ static const char * token_name(Token *token) {...@@ -1009,12 +1010,10 @@ static const char * token_name(Token *token) {
1009 case TokenIdKeywordVar: return "Var";1010 case TokenIdKeywordVar: return "Var";
1010 case TokenIdKeywordReturn: return "Return";1011 case TokenIdKeywordReturn: return "Return";
1011 case TokenIdKeywordExtern: return "Extern";1012 case TokenIdKeywordExtern: return "Extern";
1012 case TokenIdKeywordUnreachable: return "Unreachable";
1013 case TokenIdKeywordPub: return "Pub";1013 case TokenIdKeywordPub: return "Pub";
1014 case TokenIdKeywordExport: return "Export";1014 case TokenIdKeywordExport: return "Export";
1015 case TokenIdKeywordAs: return "As";1015 case TokenIdKeywordAs: return "As";
1016 case TokenIdKeywordUse: return "Use";1016 case TokenIdKeywordUse: return "Use";
1017 case TokenIdKeywordVoid: return "Void";
1018 case TokenIdKeywordTrue: return "True";1017 case TokenIdKeywordTrue: return "True";
1019 case TokenIdKeywordFalse: return "False";1018 case TokenIdKeywordFalse: return "False";
1020 case TokenIdKeywordIf: return "If";1019 case TokenIdKeywordIf: return "If";
...@@ -1044,6 +1043,7 @@ static const char * token_name(Token *token) {...@@ -1044,6 +1043,7 @@ static const char * token_name(Token *token) {
1044 case TokenIdPlus: return "Plus";1043 case TokenIdPlus: return "Plus";
1045 case TokenIdColon: return "Colon";1044 case TokenIdColon: return "Colon";
1046 case TokenIdArrow: return "Arrow";1045 case TokenIdArrow: return "Arrow";
1046 case TokenIdFatArrow: return "FatArrow";
1047 case TokenIdDash: return "Dash";1047 case TokenIdDash: return "Dash";
1048 case TokenIdNumberSign: return "NumberSign";1048 case TokenIdNumberSign: return "NumberSign";
1049 case TokenIdBinOr: return "BinOr";1049 case TokenIdBinOr: return "BinOr";
src/tokenizer.hpp+1-2
...@@ -18,12 +18,10 @@ enum TokenId {...@@ -18,12 +18,10 @@ enum TokenId {
18 TokenIdKeywordVar,18 TokenIdKeywordVar,
19 TokenIdKeywordConst,19 TokenIdKeywordConst,
20 TokenIdKeywordExtern,20 TokenIdKeywordExtern,
21 TokenIdKeywordUnreachable,
22 TokenIdKeywordPub,21 TokenIdKeywordPub,
23 TokenIdKeywordExport,22 TokenIdKeywordExport,
24 TokenIdKeywordAs,23 TokenIdKeywordAs,
25 TokenIdKeywordUse,24 TokenIdKeywordUse,
26 TokenIdKeywordVoid,
27 TokenIdKeywordTrue,25 TokenIdKeywordTrue,
28 TokenIdKeywordFalse,26 TokenIdKeywordFalse,
29 TokenIdKeywordIf,27 TokenIdKeywordIf,
...@@ -53,6 +51,7 @@ enum TokenId {...@@ -53,6 +51,7 @@ enum TokenId {
53 TokenIdPlus,51 TokenIdPlus,
54 TokenIdColon,52 TokenIdColon,
55 TokenIdArrow,53 TokenIdArrow,
54 TokenIdFatArrow,
56 TokenIdDash,55 TokenIdDash,
57 TokenIdNumberSign,56 TokenIdNumberSign,
58 TokenIdBoolOr,57 TokenIdBoolOr,
std/bootstrap.zig+30-5
...@@ -3,10 +3,35 @@ use "syscall.zig";...@@ -3,10 +3,35 @@ use "syscall.zig";
3// The compiler treats this file special by implicitly importing the function `main`3// The compiler treats this file special by implicitly importing the function `main`
4// from the root source file.4// from the root source file.
55
6var env: &&u8;
7
6#attribute("naked")8#attribute("naked")
7export fn _start() -> unreachable {9export fn _start() unreachable => {
8 const argc = asm("mov (%%rsp), %[argc]" : [argc] "=r" (-> isize));10 const argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> isize));
9 const argv = asm("lea 0x8(%%rsp), %[argv]" : [argv] "=r" (-> &&u8));11 const argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8));
10 const env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]" : [env] "=r" (-> &&u8));12 env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]": [env] "=r" (-> &&u8));
11 exit(main(argc, argv, env))13
14 exit(main(argc, argv, env));
15
16/*
17 var args = @alloca_array([]u8, argc);
18 var i : @typeof(argc) = 0;
19 // TODO for in loop over the array
20 while (i < argc) {
21 const ptr = argv[i];
22 args[i] = ptr[0...strlen(ptr)];
23 i += 1;
24 }
25 exit(main(args))
26 */
27}
28
29/*
30fn strlen(ptr: &u8) isize => {
31 var count: isize = 0;
32 while (ptr[count]) {
33 count += 1;
34 }
35 return count;
12}36}
37*/
std/builtin.zig+4-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// These functions are provided when not linking against libc because LLVM1// These functions are provided when not linking against libc because LLVM
2// sometimes generates code that calls them.2// sometimes generates code that calls them.
33
4export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {4export fn memset(dest: &u8, c: u8, n: usize) &u8 => {
5 var index : #typeof(n) = 0;5 var index : @typeof(n) = 0;
6 while (index != n) {6 while (index != n) {
7 dest[index] = c;7 dest[index] = c;
8 index += 1;8 index += 1;
...@@ -10,8 +10,8 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {...@@ -10,8 +10,8 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
10 return dest;10 return dest;
11}11}
1212
13export fn memcpy(dest: &noalias u8, src: &const noalias u8, n: usize) -> &u8 {13export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) &u8 => {
14 var index : #typeof(n) = 0;14 var index : @typeof(n) = 0;
15 while (index != n) {15 while (index != n) {
16 dest[index] = src[index];16 dest[index] = src[index];
17 index += 1;17 index += 1;
std/rand.zig+18-18
...@@ -4,13 +4,13 @@ const ARRAY_SIZE : u16 = 624;...@@ -4,13 +4,13 @@ const ARRAY_SIZE : u16 = 624;
4/// Use `rand_init` to initialize this state.4/// Use `rand_init` to initialize this state.
5pub struct Rand {5pub struct Rand {
6 array: [ARRAY_SIZE]u32,6 array: [ARRAY_SIZE]u32,
7 index: #typeof(ARRAY_SIZE),7 index: @typeof(ARRAY_SIZE),
88
9 /// Initialize random state with the given seed.9 /// Initialize random state with the given seed.
10 pub fn init(r: &Rand, seed: u32) {10 pub fn init(r: &Rand, seed: u32) => {
11 r.index = 0;11 r.index = 0;
12 r.array[0] = seed;12 r.array[0] = seed;
13 var i : #typeof(ARRAY_SIZE) = 1;13 var i : @typeof(ARRAY_SIZE) = 1;
14 while (i < ARRAY_SIZE) {14 while (i < ARRAY_SIZE) {
15 const prev_value : u64 = r.array[i - 1];15 const prev_value : u64 = r.array[i - 1];
16 r.array[i] = ((prev_value ^ (prev_value << 30)) * 0x6c078965 + i) as u32;16 r.array[i] = ((prev_value ^ (prev_value << 30)) * 0x6c078965 + i) as u32;
...@@ -20,7 +20,7 @@ pub struct Rand {...@@ -20,7 +20,7 @@ pub struct Rand {
2020
2121
22 /// Get 32 bits of randomness.22 /// Get 32 bits of randomness.
23 pub fn get_u32(r: &Rand) -> u32 {23 pub fn get_u32(r: &Rand) u32 => {
24 if (r.index == 0) {24 if (r.index == 0) {
25 r.generate_numbers();25 r.generate_numbers();
26 }26 }
...@@ -37,13 +37,13 @@ pub struct Rand {...@@ -37,13 +37,13 @@ pub struct Rand {
37 }37 }
3838
39 /// Fill `buf` with randomness.39 /// Fill `buf` with randomness.
40 pub fn get_bytes(r: &Rand, buf: []u8) {40 pub fn get_bytes(r: &Rand, buf: []u8) => {
41 var bytes_left = r.get_bytes_aligned(buf);41 var bytes_left = r.get_bytes_aligned(buf);
42 if (bytes_left > 0) {42 if (bytes_left > 0) {
43 var rand_val_array : [#sizeof(u32)]u8;43 var rand_val_array : [@sizeof(u32)]u8;
44 *(rand_val_array.ptr as &u32) = r.get_u32();44 *(rand_val_array.ptr as (&u32)) = r.get_u32();
45 while (bytes_left > 0) {45 while (bytes_left > 0) {
46 buf[buf.len - bytes_left] = rand_val_array[#sizeof(u32) - bytes_left];46 buf[buf.len - bytes_left] = rand_val_array[@sizeof(u32) - bytes_left];
47 bytes_left -= 1;47 bytes_left -= 1;
48 }48 }
49 }49 }
...@@ -51,23 +51,23 @@ pub struct Rand {...@@ -51,23 +51,23 @@ pub struct Rand {
5151
52 /// Get a random unsigned integer with even distribution between `start`52 /// Get a random unsigned integer with even distribution between `start`
53 /// inclusive and `end` exclusive.53 /// inclusive and `end` exclusive.
54 pub fn range_u64(r: &Rand, start: u64, end: u64) -> u64 {54 pub fn range_u64(r: &Rand, start: u64, end: u64) u64 => {
55 const range = end - start;55 const range = end - start;
56 const leftover = #max_value(u64) % range;56 const leftover = @max_value(u64) % range;
57 const upper_bound = #max_value(u64) - leftover;57 const upper_bound = @max_value(u64) - leftover;
58 var rand_val_array : [#sizeof(u64)]u8;58 var rand_val_array : [@sizeof(u64)]u8;
5959
60 while (true) {60 while (true) {
61 r.get_bytes_aligned(rand_val_array);61 r.get_bytes_aligned(rand_val_array);
62 const rand_val = *(rand_val_array.ptr as &u64);62 const rand_val = *(rand_val_array.ptr as (&u64));
63 if (rand_val < upper_bound) {63 if (rand_val < upper_bound) {
64 return start + (rand_val % range);64 return start + (rand_val % range);
65 }65 }
66 }66 }
67 }67 }
6868
69 fn generate_numbers(r: &Rand) {69 fn generate_numbers(r: &Rand) => {
70 var i : #typeof(ARRAY_SIZE) = 0;70 var i : @typeof(ARRAY_SIZE) = 0;
71 while (i < ARRAY_SIZE) {71 while (i < ARRAY_SIZE) {
72 const y : u32 = (r.array[i] & 0x80000000) + (r.array[(i + 1) % ARRAY_SIZE] & 0x7fffffff);72 const y : u32 = (r.array[i] & 0x80000000) + (r.array[(i + 1) % ARRAY_SIZE] & 0x7fffffff);
73 const untempered : u32 = r.array[(i + 397) % ARRAY_SIZE] ^ (y >> 1);73 const untempered : u32 = r.array[(i + 397) % ARRAY_SIZE] ^ (y >> 1);
...@@ -82,11 +82,11 @@ pub struct Rand {...@@ -82,11 +82,11 @@ pub struct Rand {
82 }82 }
8383
84 // does not populate the remaining (buf.len % 4) bytes84 // does not populate the remaining (buf.len % 4) bytes
85 fn get_bytes_aligned(r: &Rand, buf: []u8) -> usize {85 fn get_bytes_aligned(r: &Rand, buf: []u8) usize => {
86 var bytes_left = buf.len;86 var bytes_left = buf.len;
87 while (bytes_left >= 4) {87 while (bytes_left >= 4) {
88 *(&buf[buf.len - bytes_left] as &u32) = r.get_u32();88 *(&buf[buf.len - bytes_left] as (&u32)) = r.get_u32();
89 bytes_left -= #sizeof(u32);89 bytes_left -= @sizeof(u32);
90 }90 }
91 return bytes_left;91 return bytes_left;
92 }92 }
std/std.zig+12-12
...@@ -5,25 +5,25 @@ pub const stdout_fileno : isize = 1;...@@ -5,25 +5,25 @@ pub const stdout_fileno : isize = 1;
5pub const stderr_fileno : isize = 2;5pub const stderr_fileno : isize = 2;
66
7// TODO error handling7// TODO error handling
8pub fn os_get_random_bytes(buf: &u8, count: usize) -> isize {8pub fn os_get_random_bytes(buf: &u8, count: usize) isize => {
9 getrandom(buf, count, 0)9 getrandom(buf, count, 0)
10}10}
1111
12// TODO error handling12// TODO error handling
13// TODO handle buffering and flushing (mutex protected)13// TODO handle buffering and flushing (mutex protected)
14pub fn print_str(str: []const u8) -> isize {14pub fn print_str(str: []const u8) isize => {
15 fprint_str(stdout_fileno, str)15 fprint_str(stdout_fileno, str)
16}16}
1717
18// TODO error handling18// TODO error handling
19// TODO handle buffering and flushing (mutex protected)19// TODO handle buffering and flushing (mutex protected)
20pub fn fprint_str(fd: isize, str: []const u8) -> isize {20pub fn fprint_str(fd: isize, str: []const u8) isize => {
21 write(fd, str.ptr, str.len)21 write(fd, str.ptr, str.len)
22}22}
2323
24// TODO handle buffering and flushing (mutex protected)24// TODO handle buffering and flushing (mutex protected)
25// TODO error handling25// TODO error handling
26pub fn print_u64(x: u64) -> isize {26pub fn print_u64(x: u64) isize => {
27 var buf: [max_u64_base10_digits]u8;27 var buf: [max_u64_base10_digits]u8;
28 const len = buf_print_u64(buf, x);28 const len = buf_print_u64(buf, x);
29 return write(stdout_fileno, buf.ptr, len);29 return write(stdout_fileno, buf.ptr, len);
...@@ -31,14 +31,14 @@ pub fn print_u64(x: u64) -> isize {...@@ -31,14 +31,14 @@ pub fn print_u64(x: u64) -> isize {
3131
32// TODO handle buffering and flushing (mutex protected)32// TODO handle buffering and flushing (mutex protected)
33// TODO error handling33// TODO error handling
34pub fn print_i64(x: i64) -> isize {34pub fn print_i64(x: i64) isize => {
35 var buf: [max_u64_base10_digits]u8;35 var buf: [max_u64_base10_digits]u8;
36 const len = buf_print_i64(buf, x);36 const len = buf_print_i64(buf, x);
37 return write(stdout_fileno, buf.ptr, len);37 return write(stdout_fileno, buf.ptr, len);
38}38}
3939
40// TODO error handling40// TODO error handling
41pub fn readline(buf: []u8, out_len: &usize) -> bool {41pub fn readline(buf: []u8, out_len: &usize) bool => {
42 const amt_read = read(stdin_fileno, buf.ptr, buf.len);42 const amt_read = read(stdin_fileno, buf.ptr, buf.len);
43 if (amt_read < 0) {43 if (amt_read < 0) {
44 return true;44 return true;
...@@ -48,10 +48,10 @@ pub fn readline(buf: []u8, out_len: &usize) -> bool {...@@ -48,10 +48,10 @@ pub fn readline(buf: []u8, out_len: &usize) -> bool {
48}48}
4949
50// TODO return ?u64 when we support returning struct byval50// TODO return ?u64 when we support returning struct byval
51pub fn parse_u64(buf: []u8, radix: u8, result: &u64) -> bool {51pub fn parse_u64(buf: []u8, radix: u8, result: &u64) bool => {
52 var x : u64 = 0;52 var x : u64 = 0;
5353
54 var i : #typeof(buf.len) = 0;54 var i : @typeof(buf.len) = 0;
55 while (i < buf.len) {55 while (i < buf.len) {
56 const c = buf[i];56 const c = buf[i];
57 const digit = char_to_digit(c);57 const digit = char_to_digit(c);
...@@ -77,7 +77,7 @@ pub fn parse_u64(buf: []u8, radix: u8, result: &u64) -> bool {...@@ -77,7 +77,7 @@ pub fn parse_u64(buf: []u8, radix: u8, result: &u64) -> bool {
77 return false;77 return false;
78}78}
7979
80fn char_to_digit(c: u8) -> u8 {80fn char_to_digit(c: u8) u8 => {
81 if ('0' <= c && c <= '9') {81 if ('0' <= c && c <= '9') {
82 c - '0'82 c - '0'
83 } else if ('A' <= c && c <= 'Z') {83 } else if ('A' <= c && c <= 'Z') {
...@@ -85,13 +85,13 @@ fn char_to_digit(c: u8) -> u8 {...@@ -85,13 +85,13 @@ fn char_to_digit(c: u8) -> u8 {
85 } else if ('a' <= c && c <= 'z') {85 } else if ('a' <= c && c <= 'z') {
86 c - 'a' + 1086 c - 'a' + 10
87 } else {87 } else {
88 #max_value(u8)88 @max_value(u8)
89 }89 }
90}90}
9191
92const max_u64_base10_digits: usize = 20;92const max_u64_base10_digits: usize = 20;
9393
94fn buf_print_i64(out_buf: []u8, x: i64) -> usize {94fn buf_print_i64(out_buf: []u8, x: i64) usize => {
95 if (x < 0) {95 if (x < 0) {
96 out_buf[0] = '-';96 out_buf[0] = '-';
97 return 1 + buf_print_u64(out_buf[1...], ((-(x + 1)) as u64) + 1);97 return 1 + buf_print_u64(out_buf[1...], ((-(x + 1)) as u64) + 1);
...@@ -100,7 +100,7 @@ fn buf_print_i64(out_buf: []u8, x: i64) -> usize {...@@ -100,7 +100,7 @@ fn buf_print_i64(out_buf: []u8, x: i64) -> usize {
100 }100 }
101}101}
102102
103fn buf_print_u64(out_buf: []u8, x: u64) -> usize {103fn buf_print_u64(out_buf: []u8, x: u64) usize => {
104 var buf: [max_u64_base10_digits]u8;104 var buf: [max_u64_base10_digits]u8;
105 var a = x;105 var a = x;
106 var index = buf.len;106 var index = buf.len;
std/syscall.zig+7-7
...@@ -3,34 +3,34 @@ const SYS_write : usize = 1;...@@ -3,34 +3,34 @@ const SYS_write : usize = 1;
3const SYS_exit : usize = 60;3const SYS_exit : usize = 60;
4const SYS_getrandom : usize = 318;4const SYS_getrandom : usize = 318;
55
6fn syscall1(number: usize, arg1: usize) -> usize {6fn syscall1(number: usize, arg1: usize) usize => {
7 asm volatile ("syscall"7 asm volatile ("syscall"
8 : [ret] "={rax}" (-> usize)8 : [ret] "={rax}" (-> usize)
9 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1)9 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1)
10 : "rcx", "r11")10 : "rcx", "r11")
11}11}
1212
13fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {13fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize => {
14 asm volatile ("syscall"14 asm volatile ("syscall"
15 : [ret] "={rax}" (-> usize)15 : [ret] "={rax}" (-> usize)
16 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3)16 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3)
17 : "rcx", "r11")17 : "rcx", "r11")
18}18}
1919
20pub fn read(fd: isize, buf: &u8, count: usize) -> isize {20pub fn read(fd: isize, buf: &u8, count: usize) isize => {
21 syscall3(SYS_read, fd as usize, buf as usize, count) as isize21 syscall3(SYS_read, fd as usize, buf as usize, count) as isize
22}22}
2323
24pub fn write(fd: isize, buf: &const u8, count: usize) -> isize {24pub fn write(fd: isize, buf: &const u8, count: usize) isize => {
25 syscall3(SYS_write, fd as usize, buf as usize, count) as isize25 syscall3(SYS_write, fd as usize, buf as usize, count) as isize
26}26}
2727
28pub fn exit(status: i32) -> unreachable {28pub fn exit(status: i32) unreachable => {
29 syscall1(SYS_exit, status as usize);29 syscall1(SYS_exit, status as usize);
30 unreachable30 unreachable{}
31}31}
3232
33pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize {33pub fn getrandom(buf: &u8, count: usize, flags: u32) isize => {
34 syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize34 syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize
35}35}
3636
test/run_tests.cpp+209-209
...@@ -96,50 +96,50 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source...@@ -96,50 +96,50 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
9696
97static void add_compiling_test_cases(void) {97static void add_compiling_test_cases(void) {
98 add_simple_case("hello world with libc", R"SOURCE(98 add_simple_case("hello world with libc", R"SOURCE(
99 #link("c")99#link("c")
100 extern {100extern {
101 fn puts(s: &const u8) -> i32;101 fn puts(s: &const u8) i32;
102 }102}
103103
104 export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {104export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {
105 puts(c"Hello, world!");105 puts(c"Hello, world!");
106 return 0;106 return 0;
107 }107}
108 )SOURCE", "Hello, world!\n");108 )SOURCE", "Hello, world!\n");
109109
110 add_simple_case("function call", R"SOURCE(110 add_simple_case("function call", R"SOURCE(
111 use "std.zig";111use "std.zig";
112 use "syscall.zig";112use "syscall.zig";
113113
114 fn empty_function_1() {}114fn empty_function_1() => {}
115 fn empty_function_2() { return; }115fn empty_function_2() => { return; }
116116
117 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {117pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
118 empty_function_1();118 empty_function_1();
119 empty_function_2();119 empty_function_2();
120 this_is_a_function();120 this_is_a_function();
121 }121}
122122
123 fn this_is_a_function() -> unreachable {123fn this_is_a_function() unreachable => {
124 print_str("OK\n");124 print_str("OK\n");
125 exit(0);125 exit(0);
126 }126}
127 )SOURCE", "OK\n");127 )SOURCE", "OK\n");
128128
129 add_simple_case("comments", R"SOURCE(129 add_simple_case("comments", R"SOURCE(
130 use "std.zig";130use "std.zig";
131131
132 /**132/**
133 * multi line doc comment133 * multi line doc comment
134 */134 */
135 fn another_function() {}135fn another_function() => {}
136136
137 /// this is a documentation comment137/// this is a documentation comment
138 /// doc comment line 2138/// doc comment line 2
139 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {139pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
140 print_str(/* mid-line comment /* nested */ */ "OK\n");140 print_str(/* mid-line comment /* nested */ */ "OK\n");
141 return 0;141 return 0;
142 }142}
143 )SOURCE", "OK\n");143 )SOURCE", "OK\n");
144144
145 {145 {
...@@ -147,13 +147,13 @@ static void add_compiling_test_cases(void) {...@@ -147,13 +147,13 @@ static void add_compiling_test_cases(void) {
147use "std.zig";147use "std.zig";
148use "foo.zig";148use "foo.zig";
149149
150pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {150pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
151 private_function();151 private_function();
152 print_str("OK 2\n");152 print_str("OK 2\n");
153 return 0;153 return 0;
154}154}
155155
156fn private_function() {156fn private_function() => {
157 print_text();157 print_text();
158}158}
159 )SOURCE", "OK 1\nOK 2\n");159 )SOURCE", "OK 1\nOK 2\n");
...@@ -163,11 +163,11 @@ use "std.zig";...@@ -163,11 +163,11 @@ use "std.zig";
163163
164// purposefully conflicting function with main.zig164// purposefully conflicting function with main.zig
165// but it's private so it should be OK165// but it's private so it should be OK
166fn private_function() {166fn private_function() => {
167 print_str("OK 1\n");167 print_str("OK 1\n");
168}168}
169169
170pub fn print_text() {170pub fn print_text() => {
171 private_function();171 private_function();
172}172}
173 )SOURCE");173 )SOURCE");
...@@ -178,7 +178,7 @@ pub fn print_text() {...@@ -178,7 +178,7 @@ pub fn print_text() {
178use "foo.zig";178use "foo.zig";
179use "bar.zig";179use "bar.zig";
180180
181pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {181pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
182 foo_function();182 foo_function();
183 bar_function();183 bar_function();
184 return 0;184 return 0;
...@@ -187,7 +187,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -187,7 +187,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
187187
188 add_source_file(tc, "foo.zig", R"SOURCE(188 add_source_file(tc, "foo.zig", R"SOURCE(
189use "std.zig";189use "std.zig";
190pub fn foo_function() {190pub fn foo_function() => {
191 print_str("OK\n");191 print_str("OK\n");
192}192}
193 )SOURCE");193 )SOURCE");
...@@ -196,7 +196,7 @@ pub fn foo_function() {...@@ -196,7 +196,7 @@ pub fn foo_function() {
196use "other.zig";196use "other.zig";
197use "std.zig";197use "std.zig";
198198
199pub fn bar_function() {199pub fn bar_function() => {
200 if (foo_function()) {200 if (foo_function()) {
201 print_str("OK\n");201 print_str("OK\n");
202 }202 }
...@@ -204,7 +204,7 @@ pub fn bar_function() {...@@ -204,7 +204,7 @@ pub fn bar_function() {
204 )SOURCE");204 )SOURCE");
205205
206 add_source_file(tc, "other.zig", R"SOURCE(206 add_source_file(tc, "other.zig", R"SOURCE(
207pub fn foo_function() -> bool {207pub fn foo_function() bool => {
208 // this one conflicts with the one from foo208 // this one conflicts with the one from foo
209 return true;209 return true;
210}210}
...@@ -212,65 +212,65 @@ pub fn foo_function() -> bool {...@@ -212,65 +212,65 @@ pub fn foo_function() -> bool {
212 }212 }
213213
214 add_simple_case("if statements", R"SOURCE(214 add_simple_case("if statements", R"SOURCE(
215 use "std.zig";215use "std.zig";
216216
217 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {217pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
218 if (1 != 0) {218 if (1 != 0) {
219 print_str("1 is true\n");219 print_str("1 is true\n");
220 } else {220 } else {
221 print_str("1 is false\n");221 print_str("1 is false\n");
222 }222 }
223 if (0 != 0) {223 if (0 != 0) {
224 print_str("0 is true\n");224 print_str("0 is true\n");
225 } else if (1 - 1 != 0) {225 } else if (1 - 1 != 0) {
226 print_str("1 - 1 is true\n");226 print_str("1 - 1 is true\n");
227 }227 }
228 if (!(0 != 0)) {228 if (!(0 != 0)) {
229 print_str("!0 is true\n");229 print_str("!0 is true\n");
230 }230 }
231 return 0;231 return 0;
232 }232}
233 )SOURCE", "1 is true\n!0 is true\n");233 )SOURCE", "1 is true\n!0 is true\n");
234234
235 add_simple_case("params", R"SOURCE(235 add_simple_case("params", R"SOURCE(
236 use "std.zig";236use "std.zig";
237237
238 fn add(a: i32, b: i32) -> i32 {238fn add(a: i32, b: i32) i32 => {
239 a + b239 a + b
240 }240}
241241
242 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {242pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
243 if (add(22, 11) == 33) {243 if (add(22, 11) == 33) {
244 print_str("pass\n");244 print_str("pass\n");
245 }245 }
246 return 0;246 return 0;
247 }247}
248 )SOURCE", "pass\n");248 )SOURCE", "pass\n");
249249
250 add_simple_case("goto", R"SOURCE(250 add_simple_case("goto", R"SOURCE(
251 use "std.zig";251use "std.zig";
252252
253 fn loop(a : i32) {253fn loop(a : i32) => {
254 if (a == 0) {254 if (a == 0) {
255 goto done;255 goto done;
256 }256 }
257 print_str("loop\n");257 print_str("loop\n");
258 loop(a - 1);258 loop(a - 1);
259259
260 done:260done:
261 return;261 return;
262 }262}
263263
264 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {264pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
265 loop(3);265 loop(3);
266 return 0;266 return 0;
267 }267}
268 )SOURCE", "loop\nloop\nloop\n");268 )SOURCE", "loop\nloop\nloop\n");
269269
270 add_simple_case("local variables", R"SOURCE(270 add_simple_case("local variables", R"SOURCE(
271use "std.zig";271use "std.zig";
272272
273pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {273pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
274 const a : i32 = 1;274 const a : i32 = 1;
275 const b = 2 as i32;275 const b = 2 as i32;
276 if (a + b == 3) {276 if (a + b == 3) {
...@@ -283,7 +283,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -283,7 +283,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
283 add_simple_case("bool literals", R"SOURCE(283 add_simple_case("bool literals", R"SOURCE(
284use "std.zig";284use "std.zig";
285285
286pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {286pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
287 if (true) { print_str("OK 1\n"); }287 if (true) { print_str("OK 1\n"); }
288 if (false) { print_str("BAD 1\n"); }288 if (false) { print_str("BAD 1\n"); }
289 if (!true) { print_str("BAD 2\n"); }289 if (!true) { print_str("BAD 2\n"); }
...@@ -295,7 +295,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -295,7 +295,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
295 add_simple_case("separate block scopes", R"SOURCE(295 add_simple_case("separate block scopes", R"SOURCE(
296use "std.zig";296use "std.zig";
297297
298pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {298pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
299 if (true) {299 if (true) {
300 const no_conflict : i32 = 5;300 const no_conflict : i32 = 5;
301 if (no_conflict == 5) { print_str("OK 1\n"); }301 if (no_conflict == 5) { print_str("OK 1\n"); }
...@@ -313,12 +313,12 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -313,12 +313,12 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
313 add_simple_case("void parameters", R"SOURCE(313 add_simple_case("void parameters", R"SOURCE(
314use "std.zig";314use "std.zig";
315315
316pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {316pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
317 void_fun(1, void, 2);317 void_fun(1, void{}, 2);
318 return 0;318 return 0;
319}319}
320320
321fn void_fun(a : i32, b : void, c : i32) {321fn void_fun(a : i32, b : void, c : i32) => {
322 const v = b;322 const v = b;
323 const vv : void = if (a == 1) {v} else {};323 const vv : void = if (a == 1) {v} else {};
324 if (a + c == 3) { print_str("OK\n"); }324 if (a + c == 3) { print_str("OK\n"); }
...@@ -333,16 +333,16 @@ struct Foo {...@@ -333,16 +333,16 @@ struct Foo {
333 b : i32,333 b : i32,
334 c : void,334 c : void,
335}335}
336pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {336pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
337 const foo = Foo {337 const foo = Foo {
338 .a = void,338 .a = void{},
339 .b = 1,339 .b = 1,
340 .c = void,340 .c = void{},
341 };341 };
342 if (foo.b != 1) {342 if (foo.b != 1) {
343 print_str("BAD\n");343 print_str("BAD\n");
344 }344 }
345 if (#sizeof(Foo) != 4) {345 if (@sizeof(Foo) != 4) {
346 print_str("BAD\n");346 print_str("BAD\n");
347 }347 }
348 print_str("OK\n");348 print_str("OK\n");
...@@ -354,7 +354,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -354,7 +354,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
354 add_simple_case("mutable local variables", R"SOURCE(354 add_simple_case("mutable local variables", R"SOURCE(
355use "std.zig";355use "std.zig";
356356
357pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {357pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
358 var zero : i32 = 0;358 var zero : i32 = 0;
359 if (zero == 0) { print_str("zero\n"); }359 if (zero == 0) { print_str("zero\n"); }
360360
...@@ -374,7 +374,7 @@ done:...@@ -374,7 +374,7 @@ done:
374 add_simple_case("arrays", R"SOURCE(374 add_simple_case("arrays", R"SOURCE(
375use "std.zig";375use "std.zig";
376376
377pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {377pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
378 var array : [5]u32;378 var array : [5]u32;
379379
380 var i : u32 = 0;380 var i : u32 = 0;
...@@ -401,7 +401,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -401,7 +401,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
401401
402 return 0;402 return 0;
403}403}
404fn get_array_len(a: []u32) -> usize {404fn get_array_len(a: []u32) usize => {
405 a.len405 a.len
406}406}
407 )SOURCE", "OK\n");407 )SOURCE", "OK\n");
...@@ -410,7 +410,7 @@ fn get_array_len(a: []u32) -> usize {...@@ -410,7 +410,7 @@ fn get_array_len(a: []u32) -> usize {
410 add_simple_case("hello world without libc", R"SOURCE(410 add_simple_case("hello world without libc", R"SOURCE(
411use "std.zig";411use "std.zig";
412412
413pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {413pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
414 print_str("Hello, world!\n");414 print_str("Hello, world!\n");
415 return 0;415 return 0;
416}416}
...@@ -420,7 +420,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -420,7 +420,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
420 add_simple_case("a + b + c", R"SOURCE(420 add_simple_case("a + b + c", R"SOURCE(
421use "std.zig";421use "std.zig";
422422
423pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {423pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
424 if (false || false || false) { print_str("BAD 1\n"); }424 if (false || false || false) { print_str("BAD 1\n"); }
425 if (true && true && false) { print_str("BAD 2\n"); }425 if (true && true && false) { print_str("BAD 2\n"); }
426 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }426 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }
...@@ -442,7 +442,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -442,7 +442,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
442 add_simple_case("short circuit", R"SOURCE(442 add_simple_case("short circuit", R"SOURCE(
443use "std.zig";443use "std.zig";
444444
445pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {445pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
446 if (true || { print_str("BAD 1\n"); false }) {446 if (true || { print_str("BAD 1\n"); false }) {
447 print_str("OK 1\n");447 print_str("OK 1\n");
448 }448 }
...@@ -465,7 +465,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -465,7 +465,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
465 add_simple_case("modify operators", R"SOURCE(465 add_simple_case("modify operators", R"SOURCE(
466use "std.zig";466use "std.zig";
467467
468pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {468pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
469 var i : i32 = 0;469 var i : i32 = 0;
470 i += 5; if (i != 5) { print_str("BAD +=\n"); }470 i += 5; if (i != 5) { print_str("BAD +=\n"); }
471 i -= 2; if (i != 3) { print_str("BAD -=\n"); }471 i -= 2; if (i != 3) { print_str("BAD -=\n"); }
...@@ -488,10 +488,10 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -488,10 +488,10 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
488 add_simple_case("number literals", R"SOURCE(488 add_simple_case("number literals", R"SOURCE(
489#link("c")489#link("c")
490extern {490extern {
491 fn printf(__format: &const u8, ...) -> i32;491 fn printf(__format: &const u8, ...) i32;
492}492}
493493
494export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {494export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
495 printf(c"\n");495 printf(c"\n");
496496
497 printf(c"0: %llu\n",497 printf(c"0: %llu\n",
...@@ -617,9 +617,9 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -617,9 +617,9 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
617 add_simple_case("structs", R"SOURCE(617 add_simple_case("structs", R"SOURCE(
618use "std.zig";618use "std.zig";
619619
620pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {620pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
621 var foo : Foo;621 var foo : Foo;
622 @memset(&foo, 0, #sizeof(Foo));622 @memset(&foo, 0, @sizeof(Foo));
623 foo.a += 1;623 foo.a += 1;
624 foo.b = foo.a == 1;624 foo.b = foo.a == 1;
625 test_foo(foo);625 test_foo(foo);
...@@ -638,12 +638,12 @@ struct Foo {...@@ -638,12 +638,12 @@ struct Foo {
638 b : bool,638 b : bool,
639 c : f32,639 c : f32,
640}640}
641fn test_foo(foo : Foo) {641fn test_foo(foo : Foo) => {
642 if (!foo.b) {642 if (!foo.b) {
643 print_str("BAD\n");643 print_str("BAD\n");
644 }644 }
645}645}
646fn test_mutation(foo : &Foo) {646fn test_mutation(foo : &Foo) => {
647 foo.c = 100;647 foo.c = 100;
648}648}
649struct Node {649struct Node {
...@@ -654,7 +654,7 @@ struct Node {...@@ -654,7 +654,7 @@ struct Node {
654struct Val {654struct Val {
655 x: i32,655 x: i32,
656}656}
657fn test_point_to_self() {657fn test_point_to_self() => {
658 var root : Node;658 var root : Node;
659 root.val.x = 1;659 root.val.x = 1;
660660
...@@ -668,7 +668,7 @@ fn test_point_to_self() {...@@ -668,7 +668,7 @@ fn test_point_to_self() {
668 print_str("BAD\n");668 print_str("BAD\n");
669 }669 }
670}670}
671fn test_byval_assign() {671fn test_byval_assign() => {
672 var foo1 : Foo;672 var foo1 : Foo;
673 var foo2 : Foo;673 var foo2 : Foo;
674674
...@@ -680,7 +680,7 @@ fn test_byval_assign() {...@@ -680,7 +680,7 @@ fn test_byval_assign() {
680680
681 if (foo2.a != 1234) { print_str("BAD - byval assignment failed\n"); }681 if (foo2.a != 1234) { print_str("BAD - byval assignment failed\n"); }
682}682}
683fn test_initializer() {683fn test_initializer() => {
684 const val = Val { .x = 42 };684 const val = Val { .x = 42 };
685 if (val.x != 42) { print_str("BAD\n"); }685 if (val.x != 42) { print_str("BAD\n"); }
686}686}
...@@ -692,7 +692,7 @@ use "std.zig";...@@ -692,7 +692,7 @@ use "std.zig";
692const g1 : i32 = 1233 + 1;692const g1 : i32 = 1233 + 1;
693var g2 : i32 = 0;693var g2 : i32 = 0;
694694
695pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {695pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
696 if (g2 != 0) { print_str("BAD\n"); }696 if (g2 != 0) { print_str("BAD\n"); }
697 g2 = g1;697 g2 = g1;
698 if (g2 != 1234) { print_str("BAD\n"); }698 if (g2 != 1234) { print_str("BAD\n"); }
...@@ -703,7 +703,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -703,7 +703,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
703703
704 add_simple_case("while loop", R"SOURCE(704 add_simple_case("while loop", R"SOURCE(
705use "std.zig";705use "std.zig";
706pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {706pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
707 var i : i32 = 0;707 var i : i32 = 0;
708 while (i < 4) {708 while (i < 4) {
709 print_str("loop\n");709 print_str("loop\n");
...@@ -711,7 +711,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -711,7 +711,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
711 }711 }
712 return f();712 return f();
713}713}
714fn f() -> i32 {714fn f() i32 => {
715 while (true) {715 while (true) {
716 return 0;716 return 0;
717 }717 }
...@@ -720,7 +720,7 @@ fn f() -> i32 {...@@ -720,7 +720,7 @@ fn f() -> i32 {
720720
721 add_simple_case("continue and break", R"SOURCE(721 add_simple_case("continue and break", R"SOURCE(
722use "std.zig";722use "std.zig";
723pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {723pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
724 var i : i32 = 0;724 var i : i32 = 0;
725 while (true) {725 while (true) {
726 print_str("loop\n");726 print_str("loop\n");
...@@ -736,7 +736,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -736,7 +736,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
736736
737 add_simple_case("maybe type", R"SOURCE(737 add_simple_case("maybe type", R"SOURCE(
738use "std.zig";738use "std.zig";
739pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {739pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
740 const x : ?bool = true;740 const x : ?bool = true;
741741
742 if (const y ?= x) {742 if (const y ?= x) {
...@@ -759,7 +759,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -759,7 +759,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
759759
760 const final_x : ?i32 = 13;760 const final_x : ?i32 = 13;
761761
762 const num = final_x ?? unreachable;762 const num = final_x ?? unreachable{};
763763
764 if (num != 13) {764 if (num != 13) {
765 print_str("BAD\n");765 print_str("BAD\n");
...@@ -771,26 +771,26 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -771,26 +771,26 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
771771
772 add_simple_case("implicit cast after unreachable", R"SOURCE(772 add_simple_case("implicit cast after unreachable", R"SOURCE(
773use "std.zig";773use "std.zig";
774pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {774pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
775 const x = outer();775 const x = outer();
776 if (x == 1234) {776 if (x == 1234) {
777 print_str("OK\n");777 print_str("OK\n");
778 }778 }
779 return 0;779 return 0;
780}780}
781fn inner() -> i32 { 1234 }781fn inner() i32 => { 1234 }
782fn outer() -> isize {782fn outer() isize => {
783 return inner();783 return inner();
784}784}
785 )SOURCE", "OK\n");785 )SOURCE", "OK\n");
786786
787 add_simple_case("#sizeof() and #typeof()", R"SOURCE(787 add_simple_case("@sizeof() and @typeof()", R"SOURCE(
788use "std.zig";788use "std.zig";
789const x: u16 = 13;789const x: u16 = 13;
790const z: #typeof(x) = 19;790const z: @typeof(x) = 19;
791pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {791pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
792 const y: #typeof(x) = 120;792 const y: @typeof(x) = 120;
793 print_u64(#sizeof(#typeof(y)));793 print_u64(@sizeof(@typeof(y)));
794 print_str("\n");794 print_str("\n");
795 return 0;795 return 0;
796}796}
...@@ -800,11 +800,11 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -800,11 +800,11 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
800use "std.zig";800use "std.zig";
801struct Rand {801struct Rand {
802 seed: u32,802 seed: u32,
803 pub fn get_seed(r: Rand) -> u32 {803 pub fn get_seed(r: Rand) u32 => {
804 r.seed804 r.seed
805 }805 }
806}806}
807pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {807pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
808 const r = Rand {.seed = 1234};808 const r = Rand {.seed = 1234};
809 if (r.get_seed() != 1234) {809 if (r.get_seed() != 1234) {
810 print_str("BAD seed\n");810 print_str("BAD seed\n");
...@@ -817,7 +817,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {...@@ -817,7 +817,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
817 add_simple_case("pointer dereferencing", R"SOURCE(817 add_simple_case("pointer dereferencing", R"SOURCE(
818use "std.zig";818use "std.zig";
819819
820pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {820pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
821 var x = 3 as i32;821 var x = 3 as i32;
822 const y = &x;822 const y = &x;
823823
...@@ -839,9 +839,9 @@ use "std.zig";...@@ -839,9 +839,9 @@ use "std.zig";
839839
840const ARRAY_SIZE : u8 = 20;840const ARRAY_SIZE : u8 = 20;
841841
842pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {842pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
843 var array : [ARRAY_SIZE]u8;843 var array : [ARRAY_SIZE]u8;
844 print_u64(#sizeof(#typeof(array)));844 print_u64(@sizeof(@typeof(array)));
845 print_str("\n");845 print_str("\n");
846 return 0;846 return 0;
847}847}
...@@ -849,69 +849,69 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -849,69 +849,69 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
849849
850 add_simple_case("#min_value() and #max_value()", R"SOURCE(850 add_simple_case("#min_value() and #max_value()", R"SOURCE(
851use "std.zig";851use "std.zig";
852pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {852pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
853 print_str("max u8: ");853 print_str("max u8: ");
854 print_u64(#max_value(u8));854 print_u64(@max_value(u8));
855 print_str("\n");855 print_str("\n");
856856
857 print_str("max u16: ");857 print_str("max u16: ");
858 print_u64(#max_value(u16));858 print_u64(@max_value(u16));
859 print_str("\n");859 print_str("\n");
860860
861 print_str("max u32: ");861 print_str("max u32: ");
862 print_u64(#max_value(u32));862 print_u64(@max_value(u32));
863 print_str("\n");863 print_str("\n");
864864
865 print_str("max u64: ");865 print_str("max u64: ");
866 print_u64(#max_value(u64));866 print_u64(@max_value(u64));
867 print_str("\n");867 print_str("\n");
868868
869 print_str("max i8: ");869 print_str("max i8: ");
870 print_i64(#max_value(i8));870 print_i64(@max_value(i8));
871 print_str("\n");871 print_str("\n");
872872
873 print_str("max i16: ");873 print_str("max i16: ");
874 print_i64(#max_value(i16));874 print_i64(@max_value(i16));
875 print_str("\n");875 print_str("\n");
876876
877 print_str("max i32: ");877 print_str("max i32: ");
878 print_i64(#max_value(i32));878 print_i64(@max_value(i32));
879 print_str("\n");879 print_str("\n");
880880
881 print_str("max i64: ");881 print_str("max i64: ");
882 print_i64(#max_value(i64));882 print_i64(@max_value(i64));
883 print_str("\n");883 print_str("\n");
884884
885 print_str("min u8: ");885 print_str("min u8: ");
886 print_u64(#min_value(u8));886 print_u64(@min_value(u8));
887 print_str("\n");887 print_str("\n");
888888
889 print_str("min u16: ");889 print_str("min u16: ");
890 print_u64(#min_value(u16));890 print_u64(@min_value(u16));
891 print_str("\n");891 print_str("\n");
892892
893 print_str("min u32: ");893 print_str("min u32: ");
894 print_u64(#min_value(u32));894 print_u64(@min_value(u32));
895 print_str("\n");895 print_str("\n");
896896
897 print_str("min u64: ");897 print_str("min u64: ");
898 print_u64(#min_value(u64));898 print_u64(@min_value(u64));
899 print_str("\n");899 print_str("\n");
900900
901 print_str("min i8: ");901 print_str("min i8: ");
902 print_i64(#min_value(i8));902 print_i64(@min_value(i8));
903 print_str("\n");903 print_str("\n");
904904
905 print_str("min i16: ");905 print_str("min i16: ");
906 print_i64(#min_value(i16));906 print_i64(@min_value(i16));
907 print_str("\n");907 print_str("\n");
908908
909 print_str("min i32: ");909 print_str("min i32: ");
910 print_i64(#min_value(i32));910 print_i64(@min_value(i32));
911 print_str("\n");911 print_str("\n");
912912
913 print_str("min i64: ");913 print_str("min i64: ");
914 print_i64(#min_value(i64));914 print_i64(@min_value(i64));
915 print_str("\n");915 print_str("\n");
916916
917 return 0;917 return 0;
...@@ -937,7 +937,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -937,7 +937,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
937937
938 add_simple_case("slicing", R"SOURCE(938 add_simple_case("slicing", R"SOURCE(
939use "std.zig";939use "std.zig";
940pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {940pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
941 var array : [20]i32;941 var array : [20]i32;
942942
943 array[5] = 1234;943 array[5] = 1234;
...@@ -965,13 +965,13 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -965,13 +965,13 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
965965
966 add_simple_case("else if expression", R"SOURCE(966 add_simple_case("else if expression", R"SOURCE(
967use "std.zig";967use "std.zig";
968pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {968pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
969 if (f(1) == 1) {969 if (f(1) == 1) {
970 print_str("OK\n");970 print_str("OK\n");
971 }971 }
972 return 0;972 return 0;
973}973}
974fn f(c: u8) -> u8 {974fn f(c: u8) u8 => {
975 if (c == 0) {975 if (c == 0) {
976 0976 0
977 } else if (c == 1) {977 } else if (c == 1) {
...@@ -984,7 +984,7 @@ fn f(c: u8) -> u8 {...@@ -984,7 +984,7 @@ fn f(c: u8) -> u8 {
984984
985 add_simple_case("overflow intrinsics", R"SOURCE(985 add_simple_case("overflow intrinsics", R"SOURCE(
986use "std.zig";986use "std.zig";
987pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {987pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
988 var result: u8;988 var result: u8;
989 if (!@add_with_overflow_u8(250, 100, &result)) {989 if (!@add_with_overflow_u8(250, 100, &result)) {
990 print_str("BAD\n");990 print_str("BAD\n");
...@@ -1002,7 +1002,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -1002,7 +1002,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10021002
1003 add_simple_case("memcpy and memset intrinsics", R"SOURCE(1003 add_simple_case("memcpy and memset intrinsics", R"SOURCE(
1004use "std.zig";1004use "std.zig";
1005pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {1005pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
1006 var foo : [20]u8;1006 var foo : [20]u8;
1007 var bar : [20]u8;1007 var bar : [20]u8;
10081008
...@@ -1020,13 +1020,13 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -1020,13 +1020,13 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10201020
1021 add_simple_case("order-independent declarations", R"SOURCE(1021 add_simple_case("order-independent declarations", R"SOURCE(
1022use "std.zig";1022use "std.zig";
1023const z : #typeof(stdin_fileno) = 0;1023const z : @typeof(stdin_fileno) = 0;
1024const x : #typeof(y) = 1234;1024const x : @typeof(y) = 1234;
1025const y : u16 = 5678;1025const y : u16 = 5678;
1026pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {1026pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
1027 print_ok(x)1027 print_ok(x)
1028}1028}
1029fn print_ok(val: #typeof(x)) -> #typeof(foo) {1029fn print_ok(val: @typeof(x)) @typeof(foo) => {
1030 print_str("OK\n");1030 print_str("OK\n");
1031 return 0;1031 return 0;
1032}1032}
...@@ -1054,7 +1054,7 @@ enum Bar {...@@ -1054,7 +1054,7 @@ enum Bar {
1054 D,1054 D,
1055}1055}
10561056
1057pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {1057pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
1058 const foo1 = Foo.One(13);1058 const foo1 = Foo.One(13);
1059 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });1059 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });
1060 const bar = Bar.B;1060 const bar = Bar.B;
...@@ -1063,18 +1063,18 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -1063,18 +1063,18 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
1063 print_str("BAD\n");1063 print_str("BAD\n");
1064 }1064 }
10651065
1066 if (#value_count(Foo) != 3) {1066 if (@value_count(Foo) != 3) {
1067 print_str("BAD\n");1067 print_str("BAD\n");
1068 }1068 }
10691069
1070 if (#value_count(Bar) != 4) {1070 if (@value_count(Bar) != 4) {
1071 print_str("BAD\n");1071 print_str("BAD\n");
1072 }1072 }
10731073
1074 if (#sizeof(Foo) != 17) {1074 if (@sizeof(Foo) != 17) {
1075 print_str("BAD\n");1075 print_str("BAD\n");
1076 }1076 }
1077 if (#sizeof(Bar) != 1) {1077 if (@sizeof(Bar) != 1) {
1078 print_str("BAD\n");1078 print_str("BAD\n");
1079 }1079 }
10801080
...@@ -1090,8 +1090,8 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {...@@ -1090,8 +1090,8 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10901090
1091static void add_compile_failure_test_cases(void) {1091static void add_compile_failure_test_cases(void) {
1092 add_compile_fail_case("multiple function definitions", R"SOURCE(1092 add_compile_fail_case("multiple function definitions", R"SOURCE(
1093fn a() {}1093fn a() => {}
1094fn a() {}1094fn a() => {}
1095 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");1095 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
10961096
1097 add_compile_fail_case("bad directive", R"SOURCE(1097 add_compile_fail_case("bad directive", R"SOURCE(
...@@ -1100,46 +1100,46 @@ extern {...@@ -1100,46 +1100,46 @@ extern {
1100 fn b();1100 fn b();
1101}1101}
1102#bogus2("")1102#bogus2("")
1103fn a() {}1103fn a() => {}
1104 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",1104 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
1105 ".tmp_source.zig:6:1: error: invalid directive: 'bogus2'");1105 ".tmp_source.zig:6:1: error: invalid directive: 'bogus2'");
11061106
1107 add_compile_fail_case("unreachable with return", R"SOURCE(1107 add_compile_fail_case("unreachable with return", R"SOURCE(
1108fn a() -> unreachable {return;}1108fn a() unreachable => {return;}
1109 )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");1109 )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");
11101110
1111 add_compile_fail_case("control reaches end of non-void function", R"SOURCE(1111 add_compile_fail_case("control reaches end of non-void function", R"SOURCE(
1112fn a() -> i32 {}1112fn a() i32 => {}
1113 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got 'void'");1113 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got 'void'");
11141114
1115 add_compile_fail_case("undefined function call", R"SOURCE(1115 add_compile_fail_case("undefined function call", R"SOURCE(
1116fn a() {1116fn a() => {
1117 b();1117 b();
1118}1118}
1119 )SOURCE", 1, ".tmp_source.zig:3:5: error: undefined function: 'b'");1119 )SOURCE", 1, ".tmp_source.zig:3:5: error: undefined function: 'b'");
11201120
1121 add_compile_fail_case("wrong number of arguments", R"SOURCE(1121 add_compile_fail_case("wrong number of arguments", R"SOURCE(
1122fn a() {1122fn a() => {
1123 b(1);1123 b(1);
1124}1124}
1125fn b(a: i32, b: i32, c: i32) { }1125fn b(a: i32, b: i32, c: i32) => { }
1126 )SOURCE", 1, ".tmp_source.zig:3:6: error: expected 3 arguments, got 1");1126 )SOURCE", 1, ".tmp_source.zig:3:6: error: expected 3 arguments, got 1");
11271127
1128 add_compile_fail_case("invalid type", R"SOURCE(1128 add_compile_fail_case("invalid type", R"SOURCE(
1129fn a() -> bogus {}1129fn a() bogus => {}
1130 )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid type name: 'bogus'");1130 )SOURCE", 1, ".tmp_source.zig:2:8: error: use of undeclared identifier 'bogus'");
11311131
1132 add_compile_fail_case("pointer to unreachable", R"SOURCE(1132 add_compile_fail_case("pointer to unreachable", R"SOURCE(
1133fn a() -> &unreachable {}1133fn a() &unreachable => {}
1134 )SOURCE", 1, ".tmp_source.zig:2:11: error: pointer to unreachable not allowed");1134 )SOURCE", 1, ".tmp_source.zig:2:8: error: pointer to unreachable not allowed");
11351135
1136 add_compile_fail_case("unreachable code", R"SOURCE(1136 add_compile_fail_case("unreachable code", R"SOURCE(
1137fn a() {1137fn a() => {
1138 return;1138 return;
1139 b();1139 b();
1140}1140}
11411141
1142fn b() {}1142fn b() => {}
1143 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");1143 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
11441144
1145 add_compile_fail_case("bad version string", R"SOURCE(1145 add_compile_fail_case("bad version string", R"SOURCE(
...@@ -1152,7 +1152,7 @@ use "bogus-does-not-exist.zig";...@@ -1152,7 +1152,7 @@ use "bogus-does-not-exist.zig";
1152 )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");1152 )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");
11531153
1154 add_compile_fail_case("undeclared identifier", R"SOURCE(1154 add_compile_fail_case("undeclared identifier", R"SOURCE(
1155fn a() {1155fn a() => {
1156 b +1156 b +
1157 c1157 c
1158}1158}
...@@ -1161,99 +1161,99 @@ fn a() {...@@ -1161,99 +1161,99 @@ fn a() {
1161 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");1161 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");
11621162
1163 add_compile_fail_case("goto cause unreachable code", R"SOURCE(1163 add_compile_fail_case("goto cause unreachable code", R"SOURCE(
1164fn a() {1164fn a() => {
1165 goto done;1165 goto done;
1166 b();1166 b();
1167done:1167done:
1168 return;1168 return;
1169}1169}
1170fn b() {}1170fn b() => {}
1171 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");1171 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
11721172
1173 add_compile_fail_case("parameter redeclaration", R"SOURCE(1173 add_compile_fail_case("parameter redeclaration", R"SOURCE(
1174fn f(a : i32, a : i32) {1174fn f(a : i32, a : i32) => {
1175}1175}
1176 )SOURCE", 1, ".tmp_source.zig:2:1: error: redeclaration of parameter 'a'");1176 )SOURCE", 1, ".tmp_source.zig:2:1: error: redeclaration of parameter 'a'");
11771177
1178 add_compile_fail_case("local variable redeclaration", R"SOURCE(1178 add_compile_fail_case("local variable redeclaration", R"SOURCE(
1179fn f() {1179fn f() => {
1180 const a : i32 = 0;1180 const a : i32 = 0;
1181 const a = 0;1181 const a = 0;
1182}1182}
1183 )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'");1183 )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'");
11841184
1185 add_compile_fail_case("local variable redeclares parameter", R"SOURCE(1185 add_compile_fail_case("local variable redeclares parameter", R"SOURCE(
1186fn f(a : i32) {1186fn f(a : i32) => {
1187 const a = 0;1187 const a = 0;
1188}1188}
1189 )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'");1189 )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'");
11901190
1191 add_compile_fail_case("variable has wrong type", R"SOURCE(1191 add_compile_fail_case("variable has wrong type", R"SOURCE(
1192fn f() -> i32 {1192fn f() i32 => {
1193 const a = c"a";1193 const a = c"a";
1194 a1194 a
1195}1195}
1196 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got '&const u8'");1196 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got '&const u8'");
11971197
1198 add_compile_fail_case("if condition is bool, not int", R"SOURCE(1198 add_compile_fail_case("if condition is bool, not int", R"SOURCE(
1199fn f() {1199fn f() => {
1200 if (0) {}1200 if (0) {}
1201}1201}
1202 )SOURCE", 1, ".tmp_source.zig:3:9: error: expected type 'bool', got '(u8 literal)'");1202 )SOURCE", 1, ".tmp_source.zig:3:9: error: expected type 'bool', got '(u8 literal)'");
12031203
1204 add_compile_fail_case("assign unreachable", R"SOURCE(1204 add_compile_fail_case("assign unreachable", R"SOURCE(
1205fn f() {1205fn f() => {
1206 const a = return;1206 const a = return;
1207}1207}
1208 )SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable");1208 )SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable");
12091209
1210 add_compile_fail_case("unreachable variable", R"SOURCE(1210 add_compile_fail_case("unreachable variable", R"SOURCE(
1211fn f() {1211fn f() => {
1212 const a : unreachable = return;1212 const a : unreachable = return;
1213}1213}
1214 )SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");1214 )SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");
12151215
1216 add_compile_fail_case("unreachable parameter", R"SOURCE(1216 add_compile_fail_case("unreachable parameter", R"SOURCE(
1217fn f(a : unreachable) {}1217fn f(a : unreachable) => {}
1218 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");1218 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
12191219
1220 add_compile_fail_case("exporting a void parameter", R"SOURCE(1220 add_compile_fail_case("exporting a void parameter", R"SOURCE(
1221export fn f(a : void) {}1221export fn f(a : void) => {}
1222 )SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions");1222 )SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions");
12231223
1224 add_compile_fail_case("unused label", R"SOURCE(1224 add_compile_fail_case("unused label", R"SOURCE(
1225fn f() {1225fn f() => {
1226a_label:1226a_label:
1227}1227}
1228 )SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used");1228 )SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used");
12291229
1230 add_compile_fail_case("bad assignment target", R"SOURCE(1230 add_compile_fail_case("bad assignment target", R"SOURCE(
1231fn f() {1231fn f() => {
1232 3 = 3;1232 3 = 3;
1233}1233}
1234 )SOURCE", 1, ".tmp_source.zig:3:5: error: invalid assignment target");1234 )SOURCE", 1, ".tmp_source.zig:3:5: error: invalid assignment target");
12351235
1236 add_compile_fail_case("assign to constant variable", R"SOURCE(1236 add_compile_fail_case("assign to constant variable", R"SOURCE(
1237fn f() {1237fn f() => {
1238 const a = 3;1238 const a = 3;
1239 a = 4;1239 a = 4;
1240}1240}
1241 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");1241 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");
12421242
1243 add_compile_fail_case("use of undeclared identifier", R"SOURCE(1243 add_compile_fail_case("use of undeclared identifier", R"SOURCE(
1244fn f() {1244fn f() => {
1245 b = 3;1245 b = 3;
1246}1246}
1247 )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");1247 )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
12481248
1249 add_compile_fail_case("const is a statement, not an expression", R"SOURCE(1249 add_compile_fail_case("const is a statement, not an expression", R"SOURCE(
1250fn f() {1250fn f() => {
1251 (const a = 0);1251 (const a = 0);
1252}1252}
1253 )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'");1253 )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'");
12541254
1255 add_compile_fail_case("array access errors", R"SOURCE(1255 add_compile_fail_case("array access errors", R"SOURCE(
1256fn f() {1256fn f() => {
1257 var bad : bool;1257 var bad : bool;
1258 i[i] = i[i];1258 i[i] = i[i];
1259 bad[bad] = bad[bad];1259 bad[bad] = bad[bad];
...@@ -1268,19 +1268,19 @@ fn f() {...@@ -1268,19 +1268,19 @@ fn f() {
1268 ".tmp_source.zig:5:20: error: expected type 'usize', got 'bool'");1268 ".tmp_source.zig:5:20: error: expected type 'usize', got 'bool'");
12691269
1270 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(1270 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
1271fn f(...) {}1271fn f(...) => {}
1272 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");1272 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
12731273
1274 add_compile_fail_case("write to const global variable", R"SOURCE(1274 add_compile_fail_case("write to const global variable", R"SOURCE(
1275const x : i32 = 99;1275const x : i32 = 99;
1276fn f() {1276fn f() => {
1277 x = 1;1277 x = 1;
1278}1278}
1279 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");1279 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");
12801280
12811281
1282 add_compile_fail_case("missing else clause", R"SOURCE(1282 add_compile_fail_case("missing else clause", R"SOURCE(
1283fn f() {1283fn f() => {
1284 const x : i32 = if (true) { 1 };1284 const x : i32 = if (true) { 1 };
1285 const y = if (true) { 1 as i32 };1285 const y = if (true) { 1 as i32 };
1286}1286}
...@@ -1299,7 +1299,7 @@ struct C { a : A, }...@@ -1299,7 +1299,7 @@ struct C { a : A, }
12991299
1300 add_compile_fail_case("invalid struct field", R"SOURCE(1300 add_compile_fail_case("invalid struct field", R"SOURCE(
1301struct A { x : i32, }1301struct A { x : i32, }
1302fn f() {1302fn f() => {
1303 var a : A;1303 var a : A;
1304 a.foo = 1;1304 a.foo = 1;
1305 const y = a.bar;1305 const y = a.bar;
...@@ -1315,7 +1315,7 @@ struct A { y : i32, }...@@ -1315,7 +1315,7 @@ struct A { y : i32, }
13151315
1316 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(1316 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(
1317struct A { x : i32, }1317struct A { x : i32, }
1318export fn f(a : A) {}1318export fn f(a : A) => {}
1319 )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on exported functions");1319 )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on exported functions");
13201320
1321 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(1321 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(
...@@ -1324,7 +1324,7 @@ struct A {...@@ -1324,7 +1324,7 @@ struct A {
1324 y : i32,1324 y : i32,
1325 z : i32,1325 z : i32,
1326}1326}
1327fn f() {1327fn f() => {
1328 const a = A {1328 const a = A {
1329 .z = 1,1329 .z = 1,
1330 .y = 2,1330 .y = 2,
...@@ -1340,13 +1340,13 @@ struct A {...@@ -1340,13 +1340,13 @@ struct A {
1340 y : i32,1340 y : i32,
1341 z : i32,1341 z : i32,
1342}1342}
1343fn f() {1343fn f() => {
1344 const a = A {1344 const a = A {
1345 .z = 4,1345 .z = 4,
1346 .y = 2,1346 .y = 2,
1347 };1347 };
1348}1348}
1349 )SOURCE", 1, ".tmp_source.zig:8:15: error: missing field: 'x'");1349 )SOURCE", 1, ".tmp_source.zig:8:17: error: missing field: 'x'");
13501350
1351 add_compile_fail_case("invalid field in struct value expression", R"SOURCE(1351 add_compile_fail_case("invalid field in struct value expression", R"SOURCE(
1352struct A {1352struct A {
...@@ -1354,7 +1354,7 @@ struct A {...@@ -1354,7 +1354,7 @@ struct A {
1354 y : i32,1354 y : i32,
1355 z : i32,1355 z : i32,
1356}1356}
1357fn f() {1357fn f() => {
1358 const a = A {1358 const a = A {
1359 .z = 4,1359 .z = 4,
1360 .y = 2,1360 .y = 2,
...@@ -1364,37 +1364,37 @@ fn f() {...@@ -1364,37 +1364,37 @@ fn f() {
1364 )SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'");1364 )SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'");
13651365
1366 add_compile_fail_case("invalid break expression", R"SOURCE(1366 add_compile_fail_case("invalid break expression", R"SOURCE(
1367fn f() {1367fn f() => {
1368 break;1368 break;
1369}1369}
1370 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop");1370 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop");
13711371
1372 add_compile_fail_case("invalid continue expression", R"SOURCE(1372 add_compile_fail_case("invalid continue expression", R"SOURCE(
1373fn f() {1373fn f() => {
1374 continue;1374 continue;
1375}1375}
1376 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop");1376 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop");
13771377
1378 add_compile_fail_case("invalid maybe type", R"SOURCE(1378 add_compile_fail_case("invalid maybe type", R"SOURCE(
1379fn f() {1379fn f() => {
1380 if (const x ?= true) { }1380 if (const x ?= true) { }
1381}1381}
1382 )SOURCE", 1, ".tmp_source.zig:3:20: error: expected maybe type");1382 )SOURCE", 1, ".tmp_source.zig:3:20: error: expected maybe type");
13831383
1384 add_compile_fail_case("cast unreachable", R"SOURCE(1384 add_compile_fail_case("cast unreachable", R"SOURCE(
1385fn f() -> i32 {1385fn f() i32 => {
1386 (return 1) as i321386 (return 1) as i32
1387}1387}
1388 )SOURCE", 1, ".tmp_source.zig:3:16: error: invalid cast from type 'unreachable' to 'i32'");1388 )SOURCE", 1, ".tmp_source.zig:3:16: error: invalid cast from type 'unreachable' to 'i32'");
13891389
1390 add_compile_fail_case("invalid compiler fn", R"SOURCE(1390 add_compile_fail_case("invalid builtin fn", R"SOURCE(
1391fn f() -> #bogus(foo) {1391fn f() @bogus(foo) => {
1392}1392}
1393 )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid compiler function: 'bogus'");1393 )SOURCE", 1, ".tmp_source.zig:2:8: error: invalid builtin function: 'bogus'");
13941394
1395 add_compile_fail_case("top level decl dependency loop", R"SOURCE(1395 add_compile_fail_case("top level decl dependency loop", R"SOURCE(
1396const a : #typeof(b) = 0;1396const a : @typeof(b) = 0;
1397const b : #typeof(a) = 0;1397const b : @typeof(a) = 0;
1398 )SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");1398 )SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");
1399}1399}
14001400