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)
3434
3535TopLevelDecl : 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
3939ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
4040
4141StructMember: StructField | FnDecl
4242
43StructField : token(Symbol) option(token(Colon) Type token(Comma))
43StructField : token(Symbol) option(token(Colon) Expression) token(Comma))
4444
4545Use : many(Directive) token(Use) token(String) token(Semicolon)
4646
......@@ -48,7 +48,7 @@ RootExportDecl : many(Directive) token(Export) token(Symbol) token(String) token
4848
4949ExternBlock : 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
5353Directive : token(NumberSign) token(Symbol) token(LParen) token(String) token(RParen)
5454
......@@ -56,23 +56,11 @@ FnVisibleMod : token(Pub) | token(Export)
5656
5757FnDecl : FnProto token(Semicolon)
5858
59FnDef : FnProto Block
59FnDef : FnProto token(FatArrow) Block
6060
6161ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen)
6262
63ParamDecl : token(Symbol) token(Colon) Type | 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
63ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis)
7664
7765Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
7866
......@@ -80,11 +68,9 @@ Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression to
8068
8169Label: token(Symbol) token(Colon)
8270
83VariableDeclaration : (token(Var) | token(Const)) token(Symbol) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
84
8571Expression : BlockExpression | NonBlockExpression
8672
87NonBlockExpression : ReturnExpression | AssignmentExpression | AsmExpression
73NonBlockExpression : ReturnExpression | AssignmentExpression
8874
8975AsmExpression : 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)
9278
9379AsmInput : 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
9783AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)
9884
9985AsmClobbers: token(Colon) list(token(String), token(Comma))
10086
101UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression
87UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestionMark) BoolOrExpression | BoolOrExpression
10288
10389AssignmentExpression : UnwrapMaybeExpression AssignmentOperator UnwrapMaybeExpression | UnwrapMaybeExpression
10490
......@@ -116,7 +102,7 @@ IfExpression : IfVarExpression | IfBoolExpression
116102
117103IfBoolExpression : 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
121107Else : token(Else) Expression
122108
......@@ -144,11 +130,11 @@ MultiplyExpression : CastExpression MultiplyOperator MultiplyExpression | CastEx
144130
145131MultiplyOperator : token(Star) | token(Slash) | token(Percent)
146132
147CastExpression : CastExpression token(as) Type | PrefixOpExpression
133CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
148134
149135PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
150136
151SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
137SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
152138
153139FieldAccessExpression : token(Dot) token(Symbol)
154140
......@@ -158,26 +144,30 @@ ArrayAccessExpression : token(LBracket) Expression token(RBracket)
158144
159145SliceExpression : 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) Expression
157ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) Expression
168158
169Goto: token(Goto) token(Symbol)
159GotoExpression: token(Goto) token(Symbol)
170160
171161GroupedExpression : 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)
174164```
175165
176166## Operator Precedence
177167
178168```
179x() x[] x.y
180!x -x ~x *x &x &const x
169x() x[] x{} x.y
170!x -x ~x *x &x
181171as
182172* / %
183173+ -
doc/vim/syntax/zig.vim+2-2
......@@ -15,8 +15,8 @@ syn keyword zigConditional if else switch
1515syn keyword zigRepeat while for
1616
1717syn keyword zigConstant null
18syn keyword zigKeyword fn unreachable use void
19syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string
18syn keyword zigKeyword fn use
19syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 f128 string void unreachable
2020
2121syn 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";
33use "std.zig";
44use "rand.zig";
55
6pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
6pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
77 print_str("Welcome to the Guess Number Game in Zig.\n");
88
99 var seed : u32;
10 const err = os_get_random_bytes(&seed as &u8, #sizeof(u32));
11 if (err != #sizeof(u32)) {
10 const err = os_get_random_bytes(&seed as (&u8), @sizeof(u32));
11 if (err != @sizeof(u32)) {
1212 // TODO full error message
1313 fprint_str(stderr_fileno, "unable to get random bytes\n");
1414 return 1;
example/hello_world/hello.zig+1-1
......@@ -2,7 +2,7 @@ export executable "hello";
22
33use "std.zig";
44
5pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
5pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
66 print_str("Hello, world!\n");
77 return 0;
88}
example/hello_world/hello_libc.zig+2-3
......@@ -2,11 +2,10 @@ export executable "hello";
22
33#link("c")
44extern {
5 fn printf(__format: &const u8, ...) -> i32;
6 fn exit(__status: i32) -> unreachable;
5 fn printf(__format: &const u8, ...) i32;
76}
87
9export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
8export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {
109 printf(c"Hello, world!\n");
1110 return 0;
1211}
example/list/list.zig+45-7
......@@ -1,16 +1,16 @@
11pub struct List#(T: type) {
22 items: ?&T,
3 length: usize,
4 capacity: usize,
3 length: isize,
4 capacity: isize,
55
6 pub fn (l: &List) deinit() {
6 pub fn deinit(l: &List) {
77 free(l.items);
8 l.items = None;
8 l.items = null;
99 }
1010
1111 pub fn append(l: &List, item: T) -> error {
1212 const err = l.ensure_capacity(l.length + 1);
13 if err != Error.None {
13 if err != error.None {
1414 return err;
1515 }
1616 const raw_items = l.items ?? unreachable;
......@@ -47,11 +47,11 @@ pub struct List#(T: type) {
4747 better_capacity *= 2;
4848 }
4949 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 };
5151 l.items = new_items;
5252 l.capacity = better_capacity;
5353 }
54 Error.None
54 error.None
5555 }
5656}
5757
......@@ -64,3 +64,41 @@ pub fn realloc#(T: type)(ptr: ?&T, new_count: usize) -> ?&T {
6464pub fn free#(T: type)(ptr: ?&T) {
6565
6666}
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";
22
33use "std.zig";
44
5pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
5pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
66 const x : ?bool = true;
77
88 if (const y ?= x) {
......@@ -25,7 +25,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
2525
2626 const final_x : ?i32 = 13;
2727
28 const num = final_x ?? unreachable;
28 const num = final_x ?? unreachable{};
2929
3030 if (num != 13) {
3131 print_str("BAD\n");
example/multiple_files/foo.zig+2-2
......@@ -2,10 +2,10 @@ use "std.zig";
22
33// purposefully conflicting function with main.zig
44// but it's private so it should be OK
5fn private_function() {
5fn private_function() => {
66 print_str("OK 1\n");
77}
88
9pub fn print_text() {
9pub fn print_text() => {
1010 private_function();
1111}
example/multiple_files/main.zig+2-2
......@@ -3,12 +3,12 @@ export executable "test-multiple-files";
33use "std.zig";
44use "foo.zig";
55
6pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
6pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
77 private_function();
88 print_str("OK 2\n");
99 return 0;
1010}
1111
12fn private_function() {
12fn private_function() => {
1313 print_text();
1414}
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 {
100100 NodeTypeFnDef,
101101 NodeTypeFnDecl,
102102 NodeTypeParamDecl,
103 NodeTypeType,
104103 NodeTypeBlock,
105104 NodeTypeExternBlock,
106105 NodeTypeDirective,
......@@ -111,7 +110,6 @@ enum NodeType {
111110 NodeTypeNumberLiteral,
112111 NodeTypeStringLiteral,
113112 NodeTypeCharLiteral,
114 NodeTypeUnreachable,
115113 NodeTypeSymbol,
116114 NodeTypePrefixOpExpr,
117115 NodeTypeFnCallExpr,
......@@ -119,7 +117,6 @@ enum NodeType {
119117 NodeTypeSliceExpr,
120118 NodeTypeFieldAccessExpr,
121119 NodeTypeUse,
122 NodeTypeVoid,
123120 NodeTypeBoolLiteral,
124121 NodeTypeNullLiteral,
125122 NodeTypeIfBoolExpr,
......@@ -132,10 +129,9 @@ enum NodeType {
132129 NodeTypeAsmExpr,
133130 NodeTypeStructDecl,
134131 NodeTypeStructField,
135 NodeTypeStructValueExpr,
132 NodeTypeContainerInitExpr,
136133 NodeTypeStructValueField,
137 NodeTypeCompilerFnExpr,
138 NodeTypeCompilerFnType,
134 NodeTypeArrayType,
139135};
140136
141137struct AstNodeRoot {
......@@ -185,30 +181,10 @@ struct AstNodeFnDecl {
185181struct AstNodeParamDecl {
186182 Buf name;
187183 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;
207184 bool is_noalias;
208 AstNode *compiler_expr;
209185
210186 // populated by semantic analyzer
211 TypeTableEntry *entry;
187 VariableTableEntry *variable;
212188};
213189
214190struct AstNodeBlock {
......@@ -295,6 +271,7 @@ struct AstNodeFnCallExpr {
295271 // populated by semantic analyzer:
296272 BuiltinFnEntry *builtin_fn;
297273 Expr resolved_expr;
274 NumLitCodeGen resolved_num_lit;
298275};
299276
300277struct AstNodeArrayAccessExpr {
......@@ -360,6 +337,7 @@ enum PrefixOp {
360337 PrefixOpAddressOf,
361338 PrefixOpConstAddressOf,
362339 PrefixOpDereference,
340 PrefixOpMaybe,
363341};
364342
365343struct AstNodePrefixOpExpr {
......@@ -537,30 +515,19 @@ struct AstNodeStructValueField {
537515 TypeStructField *type_struct_field;
538516};
539517
540struct AstNodeStructValueExpr {
541 AstNode *type;
542 ZigList<AstNode *> fields;
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;
518enum ContainerInitKind {
519 ContainerInitKindStruct,
520 ContainerInitKindArray,
555521};
556522
557struct AstNodeCompilerFnType {
558 Buf name;
523struct AstNodeContainerInitExpr {
559524 AstNode *type;
525 ZigList<AstNode *> entries;
526 ContainerInitKind kind;
560527
561528 // populated by semantic analyzer
529 StructValExprCodeGen resolved_struct_val_expr;
562530 Expr resolved_expr;
563 NumLitCodeGen resolved_num_lit;
564531};
565532
566533struct AstNodeNullLiteral {
......@@ -569,16 +536,6 @@ struct AstNodeNullLiteral {
569536 Expr resolved_expr;
570537};
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
582539struct AstNodeSymbolExpr {
583540 Buf symbol;
584541
......@@ -603,6 +560,15 @@ struct AstNodeContinueExpr {
603560 Expr resolved_expr;
604561};
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
606572struct AstNode {
607573 enum NodeType type;
608574 int line;
......@@ -615,7 +581,6 @@ struct AstNode {
615581 AstNodeFnDef fn_def;
616582 AstNodeFnDecl fn_decl;
617583 AstNodeFnProto fn_proto;
618 AstNodeType type;
619584 AstNodeParamDecl param_decl;
620585 AstNodeBlock block;
621586 AstNodeReturnExpr return_expr;
......@@ -641,17 +606,14 @@ struct AstNode {
641606 AstNodeStringLiteral string_literal;
642607 AstNodeCharLiteral char_literal;
643608 AstNodeNumberLiteral number_literal;
644 AstNodeStructValueExpr struct_val_expr;
609 AstNodeContainerInitExpr container_init_expr;
645610 AstNodeStructValueField struct_val_field;
646 AstNodeCompilerFnExpr compiler_fn_expr;
647 AstNodeCompilerFnType compiler_fn_type;
648611 AstNodeNullLiteral null_literal;
649 AstNodeVoidExpr void_expr;
650 AstNodeUnreachableExpr unreachable_expr;
651612 AstNodeSymbolExpr symbol_expr;
652613 AstNodeBoolLiteral bool_literal;
653614 AstNodeBreakExpr break_expr;
654615 AstNodeContinueExpr continue_expr;
616 AstNodeArrayType array_type;
655617 } data;
656618};
657619
......@@ -670,7 +632,6 @@ struct AsmToken {
670632struct TypeTableEntryPointer {
671633 TypeTableEntry *child_type;
672634 bool is_const;
673 bool is_noalias;
674635};
675636
676637struct TypeTableEntryInt {
......@@ -770,8 +731,8 @@ struct TypeTableEntry {
770731 } data;
771732
772733 // 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 - noalias
774 TypeTableEntry *unknown_size_array_parent[2][2]; // 0 - const. 1 - noalias
734 TypeTableEntry *pointer_parent[2];
735 TypeTableEntry *unknown_size_array_parent[2];
775736 HashMap<uint64_t, TypeTableEntry *, uint64_hash, uint64_eq> arrays_by_size;
776737 TypeTableEntry *maybe_parent;
777738 TypeTableEntry *meta_parent;
......@@ -830,6 +791,11 @@ enum BuiltinFnId {
830791 BuiltinFnIdArithmeticWithOverflow,
831792 BuiltinFnIdMemcpy,
832793 BuiltinFnIdMemset,
794 BuiltinFnIdSizeof,
795 BuiltinFnIdMaxValue,
796 BuiltinFnIdMinValue,
797 BuiltinFnIdValueCount,
798 BuiltinFnIdTypeof,
833799};
834800
835801struct BuiltinFnEntry {
src/analyze.cpp+570-576
......@@ -15,10 +15,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
1515 TypeTableEntry *expected_type, AstNode *node);
1616static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
1717 AstNode *node, AstNodeNumberLiteral *out_number_literal);
18static void collect_type_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *type_node, TopLevelDecl *decl_node);
1918static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
2019 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
2120static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
21static TypeTableEntry *unwrapped_node_type(AstNode *node);
2222
2323static AstNode *first_executing_node(AstNode *node) {
2424 switch (node->type) {
......@@ -40,7 +40,6 @@ static AstNode *first_executing_node(AstNode *node) {
4040 case NodeTypeFnDef:
4141 case NodeTypeFnDecl:
4242 case NodeTypeParamDecl:
43 case NodeTypeType:
4443 case NodeTypeBlock:
4544 case NodeTypeExternBlock:
4645 case NodeTypeDirective:
......@@ -49,11 +48,9 @@ static AstNode *first_executing_node(AstNode *node) {
4948 case NodeTypeNumberLiteral:
5049 case NodeTypeStringLiteral:
5150 case NodeTypeCharLiteral:
52 case NodeTypeUnreachable:
5351 case NodeTypeSymbol:
5452 case NodeTypePrefixOpExpr:
5553 case NodeTypeUse:
56 case NodeTypeVoid:
5754 case NodeTypeBoolLiteral:
5855 case NodeTypeNullLiteral:
5956 case NodeTypeIfBoolExpr:
......@@ -65,11 +62,10 @@ static AstNode *first_executing_node(AstNode *node) {
6562 case NodeTypeAsmExpr:
6663 case NodeTypeStructDecl:
6764 case NodeTypeStructField:
68 case NodeTypeStructValueExpr:
6965 case NodeTypeStructValueField:
7066 case NodeTypeWhileExpr:
71 case NodeTypeCompilerFnExpr:
72 case NodeTypeCompilerFnType:
67 case NodeTypeContainerInitExpr:
68 case NodeTypeArrayType:
7369 return node;
7470 }
7571 zig_panic("unreachable");
......@@ -188,8 +184,9 @@ static TypeTableEntry *get_meta_type(CodeGen *g, TypeTableEntry *child_type) {
188184 }
189185}
190186
191TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const, bool is_noalias) {
192 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)][(is_noalias ? 1 : 0)];
187TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
188 assert(child_type->id != TypeTableEntryIdInvalid);
189 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
193190 if (*parent_pointer) {
194191 return *parent_pointer;
195192 } else {
......@@ -197,9 +194,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
197194 entry->type_ref = LLVMPointerType(child_type->type_ref, 0);
198195
199196 const char *const_str = is_const ? "const " : "";
200 const char *noalias_str = is_noalias ? "noalias " : "";
201197 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
204200 entry->size_in_bits = g->pointer_size_bytes * 8;
205201 entry->align_in_bits = g->pointer_size_bytes * 8;
......@@ -208,14 +204,13 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
208204 entry->size_in_bits, entry->align_in_bits, buf_ptr(&entry->name));
209205 entry->data.pointer.child_type = child_type;
210206 entry->data.pointer.is_const = is_const;
211 entry->data.pointer.is_noalias = is_noalias;
212207
213208 *parent_pointer = entry;
214209 return entry;
215210 }
216211}
217212
218static TypeTableEntry *get_maybe_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *child_type) {
213static TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
219214 if (child_type->maybe_parent) {
220215 TypeTableEntry *entry = child_type->maybe_parent;
221216 return entry;
......@@ -293,9 +288,10 @@ static TypeTableEntry *get_array_type(CodeGen *g, ImportTableEntry *import,
293288}
294289
295290static 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)
297292{
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)];
299295 if (*parent_pointer) {
300296 return *parent_pointer;
301297 } else {
......@@ -305,7 +301,7 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
305301 buf_appendf(&entry->name, "[]%s", buf_ptr(&child_type->name));
306302 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
310306 unsigned element_count = 2;
311307 LLVMTypeRef element_types[] = {
......@@ -343,6 +339,25 @@ static TypeTableEntry *get_unknown_size_array_type(CodeGen *g, ImportTableEntry
343339 }
344340}
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
346361static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
347362 AstNode *node, AstNodeNumberLiteral *out_number_literal)
348363{
......@@ -436,6 +451,40 @@ static TypeTableEntry *eval_const_expr_bin_op(CodeGen *g, BlockContext *context,
436451 zig_unreachable();
437452}
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
439488static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
440489 AstNode *node, AstNodeNumberLiteral *out_number_literal)
441490{
......@@ -450,175 +499,25 @@ static TypeTableEntry *eval_const_expr(CodeGen *g, BlockContext *context,
450499 return get_resolved_expr(node)->type_entry;
451500 case NodeTypeBinOpExpr:
452501 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 }
475502 case NodeTypeSymbol:
476503 {
477504 VariableTableEntry *var = find_variable(context, &node->data.symbol_expr.symbol);
478505 assert(var);
479506 AstNode *decl_node = var->decl_node;
480507 AstNode *expr_node = decl_node->data.variable_declaration.expr;
481 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
482 return eval_const_expr(g, next_context, expr_node, out_number_literal);
483 }
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);
508 if (expr_node) {
509 BlockContext *next_context = get_resolved_expr(expr_node)->block_context;
510 return eval_const_expr(g, next_context, expr_node, out_number_literal);
613511 } else {
614 add_node_error(g, node,
615 buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name)));
616 node->data.type.entry = g->builtin_types.entry_invalid;
512 // can't eval it
513 return g->builtin_types.entry_invalid;
617514 }
618 return node->data.type.entry;
619515 }
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;
620520 }
621 zig_unreachable();
622521}
623522
624523static 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
654553 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
655554 AstNode *child = node->data.fn_proto.params.at(i);
656555 assert(child->type == NodeTypeParamDecl);
657 TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type,
658 import, import->block_context, true);
556 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
557 child->data.param_decl.type);
558
659559 if (type_entry->id == TypeTableEntryIdUnreachable) {
660560 add_node_error(g, child->data.param_decl.type,
661561 buf_sprintf("parameter of type 'unreachable' not allowed"));
......@@ -667,7 +567,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
667567 }
668568 }
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);
671571}
672572
673573static 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
729629 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
730630 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
731631 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,
733 import, import->block_context, false);
632 type_enum_field->type_entry = analyze_type_expr(g, import, import->block_context,
633 field_node->data.struct_field.type);
734634 type_enum_field->value = i;
735635
736636 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
815715 biggest_align_in_bits,
816716 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
819719 LLVMZigDIType *di_root_members[] = {
820720 tag_member_di_type,
821721 union_member_di_type,
......@@ -893,8 +793,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
893793 AstNode *field_node = decl_node->data.struct_decl.fields.at(i);
894794 TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
895795 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,
897 import, import->block_context, false);
796 type_struct_field->type_entry = analyze_type_expr(g, import, import->block_context,
797 field_node->data.struct_field.type);
898798 type_struct_field->src_index = i;
899799 type_struct_field->gen_index = -1;
900800
......@@ -1144,7 +1044,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
11441044 case NodeTypeFnDef:
11451045 case NodeTypeDirective:
11461046 case NodeTypeParamDecl:
1147 case NodeTypeType:
11481047 case NodeTypeFnDecl:
11491048 case NodeTypeReturnExpr:
11501049 case NodeTypeRoot:
......@@ -1156,8 +1055,6 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
11561055 case NodeTypeNumberLiteral:
11571056 case NodeTypeStringLiteral:
11581057 case NodeTypeCharLiteral:
1159 case NodeTypeUnreachable:
1160 case NodeTypeVoid:
11611058 case NodeTypeBoolLiteral:
11621059 case NodeTypeNullLiteral:
11631060 case NodeTypeSymbol:
......@@ -1173,10 +1070,9 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
11731070 case NodeTypeAsmExpr:
11741071 case NodeTypeFieldAccessExpr:
11751072 case NodeTypeStructField:
1176 case NodeTypeStructValueExpr:
11771073 case NodeTypeStructValueField:
1178 case NodeTypeCompilerFnExpr:
1179 case NodeTypeCompilerFnType:
1074 case NodeTypeContainerInitExpr:
1075 case NodeTypeArrayType:
11801076 zig_unreachable();
11811077 }
11821078}
......@@ -1186,13 +1082,22 @@ static FnTableEntry *get_context_fn_entry(BlockContext *context) {
11861082 return context->fn_entry;
11871083}
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
11891095static TypeTableEntry *get_return_type(BlockContext *context) {
11901096 FnTableEntry *fn_entry = get_context_fn_entry(context);
11911097 AstNode *fn_proto_node = fn_entry->proto_node;
11921098 assert(fn_proto_node->type == NodeTypeFnProto);
11931099 AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type;
1194 assert(return_type_node->type == NodeTypeType);
1195 return return_type_node->data.type.entry;
1100 return unwrapped_node_type(return_type_node);
11961101}
11971102
11981103static 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
15531458 return enum_type;
15541459}
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
15561569static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
15571570 AstNode *node)
15581571{
......@@ -1585,7 +1598,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
15851598 return_type = g->builtin_types.entry_usize;
15861599 } else if (buf_eql_str(name, "ptr")) {
15871600 // 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);
15891602 } else {
15901603 add_node_error(g, node,
15911604 buf_sprintf("no member named '%s' in '%s'", buf_ptr(name),
......@@ -1623,16 +1636,16 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
16231636 return_type = g->builtin_types.entry_invalid;
16241637 } else if (array_type->id == TypeTableEntryIdArray) {
16251638 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);
16271640 } else if (array_type->id == TypeTableEntryIdPointer) {
16281641 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);
16301643 } else if (array_type->id == TypeTableEntryIdStruct &&
16311644 array_type->data.structure.is_unknown_size_array)
16321645 {
16331646 return_type = get_unknown_size_array_type(g, import,
16341647 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);
16361649 } else {
16371650 add_node_error(g, node,
16381651 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,
16871700 TypeTableEntry *expected_type, AstNode *node)
16881701{
16891702 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
16901709 VariableTableEntry *var = find_variable(context, variable_name);
16911710 if (var) {
16921711 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 }
17021712 }
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;
17031721}
17041722
17051723static TypeTableEntry *analyze_variable_name(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -1768,7 +1786,7 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
17681786{
17691787 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);
17721790 TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr);
17731791
17741792 if (wanted_type->id == TypeTableEntryIdInvalid ||
......@@ -1833,23 +1851,22 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
18331851 TypeTableEntry *expected_rhs_type = nullptr;
18341852 if (lhs_node->type == NodeTypeSymbol) {
18351853 Buf *name = &lhs_node->data.symbol_expr.symbol;
1836 VariableTableEntry *var = find_variable(block_context, name);
1837 if (var) {
1838 if (purpose == LValPurposeAssign && var->is_const) {
1839 add_node_error(g, lhs_node,
1840 buf_sprintf("cannot assign to constant"));
1841 expected_rhs_type = g->builtin_types.entry_invalid;
1842 } else if (purpose == LValPurposeAddressOf && var->is_const && !is_ptr_const) {
1854 if (purpose == LValPurposeAddressOf) {
1855 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);
1856 } else {
1857 VariableTableEntry *var = find_variable(block_context, name);
1858 if (var) {
1859 if (var->is_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 {
18431866 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)));
18451868 expected_rhs_type = g->builtin_types.entry_invalid;
1846 } else {
1847 expected_rhs_type = var->type;
18481869 }
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;
18531870 }
18541871 } else if (lhs_node->type == NodeTypeArrayAccessExpr) {
18551872 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
18731890 }
18741891 } else {
18751892 if (purpose == LValPurposeAssign) {
1876 add_node_error(g, lhs_node,
1877 buf_sprintf("invalid assignment target"));
1893 add_node_error(g, lhs_node, buf_sprintf("invalid assignment target"));
1894 expected_rhs_type = g->builtin_types.entry_invalid;
18781895 } else if (purpose == LValPurposeAddressOf) {
1879 add_node_error(g, lhs_node,
1880 buf_sprintf("invalid addressof target"));
1896 TypeTableEntry *type_entry = analyze_expression(g, import, block_context, nullptr, lhs_node);
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 }
18811905 }
1882 expected_rhs_type = g->builtin_types.entry_invalid;
18831906 }
18841907 assert(expected_rhs_type);
18851908 return expected_rhs_type;
......@@ -1988,7 +2011,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
19882011{
19892012 TypeTableEntry *explicit_type = nullptr;
19902013 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);
19922015 if (explicit_type->id == TypeTableEntryIdUnreachable) {
19932016 add_node_error(g, variable_declaration->type,
19942017 buf_sprintf("variable of type 'unreachable' not allowed"));
......@@ -2109,78 +2132,46 @@ static TypeTableEntry *analyze_number_literal_expr(CodeGen *g, ImportTableEntry
21092132 }
21102133}
21112134
2112static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name, int *index) {
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,
2135static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
21252136 TypeTableEntry *expected_type, AstNode *node)
21262137{
2127 assert(node->type == NodeTypeStructValueExpr);
2128
2129 AstNodeStructValueExpr *struct_val_expr = &node->data.struct_val_expr;
2138 AstNode *size_node = node->data.array_type.size;
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"));
21342144 return g->builtin_types.entry_invalid;
2135 } else if (type_entry->id != TypeTableEntryIdStruct) {
2136 add_node_error(g, node,
2137 buf_sprintf("type '%s' is not a struct", buf_ptr(&type_entry->name)));
2145 } else if (child_type->id == TypeTableEntryIdInvalid) {
21382146 return g->builtin_types.entry_invalid;
21392147 }
21402148
2141 node->data.struct_val_expr.codegen.type_entry = type_entry;
2142 node->data.struct_val_expr.codegen.source_node = node;
2143 context->struct_val_expr_alloca_list.append(&node->data.struct_val_expr.codegen);
2144
2145 int expr_field_count = struct_val_expr->fields.length;
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;
2149 if (size_node) {
2150 TypeTableEntry *size_type = analyze_expression(g, import, context,
2151 g->builtin_types.entry_usize, size_node);
2152 if (size_type->id == TypeTableEntryIdInvalid) {
2153 return g->builtin_types.entry_invalid;
21682154 }
21692155
2170 val_field_node->data.struct_val_field.type_struct_field = type_field;
2171
2172 analyze_expression(g, import, context, type_field->type_entry,
2173 val_field_node->data.struct_val_field.expr);
2174 }
2156 AstNodeNumberLiteral number_literal;
2157 TypeTableEntry *resolved_type = eval_const_expr(g, context, size_node, &number_literal);
21752158
2176 for (int i = 0; i < actual_field_count; i += 1) {
2177 if (field_use_counts[i] == 0) {
2178 add_node_error(g, node,
2179 buf_sprintf("missing field: '%s'", buf_ptr(type_entry->data.structure.fields[i].name)));
2159 if (resolved_type->id == TypeTableEntryIdInt) {
2160 if (resolved_type->data.integral.is_signed) {
2161 add_node_error(g, size_node,
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;
21802171 }
2172 } else {
2173 return get_meta_type(g, get_unknown_size_array_type(g, import, child_type, node->data.array_type.is_const));
21812174 }
2182
2183 return type_entry;
21842175}
21852176
21862177static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -2293,9 +2284,14 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
22932284 node->data.if_var_expr.then_block, node->data.if_var_expr.else_node, node);
22942285}
22952286
2296static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTableEntry *type_entry,
2297 const char *err_format)
2287static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2288 AstNode *node, const char *err_format)
22982289{
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);
22992295 if (type_entry->id == TypeTableEntryIdInt ||
23002296 type_entry->id == TypeTableEntryIdFloat ||
23012297 type_entry->id == TypeTableEntryIdBool ||
......@@ -2309,54 +2305,6 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, AstNode *node, TypeTabl
23092305 }
23102306}
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
23602308static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
23612309 TypeTableEntry *expected_type, AstNode *node)
23622310{
......@@ -2445,6 +2393,62 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
24452393
24462394 return builtin_fn->return_type;
24472395 }
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
24482452 }
24492453 zig_unreachable();
24502454 } else {
......@@ -2560,15 +2564,127 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
25602564 AstNode *param_decl_node = fn_proto->params.at(fn_proto_i);
25612565 assert(param_decl_node->type == NodeTypeParamDecl);
25622566 AstNode *param_type_node = param_decl_node->data.param_decl.type;
2563 assert(param_type_node->type == NodeTypeType);
2564 if (param_type_node->data.type.entry) {
2565 expected_param_type = param_type_node->data.type.entry;
2567 TypeTableEntry *param_type_entry = get_resolved_expr(param_type_node)->type_entry;
2568 if (param_type_entry) {
2569 expected_param_type = unwrapped_node_type(param_type_node);
25662570 }
25672571 }
25682572 analyze_expression(g, import, context, expected_param_type, child);
25692573 }
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 }
25722688 }
25732689}
25742690
......@@ -2593,9 +2709,10 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
25932709 continue;
25942710 }
25952711 if (return_type->id == TypeTableEntryIdUnreachable) {
2596 if (child->type == NodeTypeVoid) {
2712 if (is_node_void_expr(child)) {
25972713 // {unreachable;void;void} is allowed.
25982714 // ignore void statements once we enter unreachable land.
2715 analyze_expression(g, import, context, g->builtin_types.entry_void, child);
25992716 continue;
26002717 }
26012718 add_node_error(g, first_executing_node(child), buf_sprintf("unreachable code"));
......@@ -2604,6 +2721,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
26042721 bool is_last = (i == node->data.block.statements.length - 1);
26052722 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
26062723 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 }
26072727 }
26082728 break;
26092729 }
......@@ -2664,7 +2784,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
26642784 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
26652785 if (asm_output->return_type) {
26662786 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);
26682788 if (node->data.asm_expr.return_count > 1) {
26692789 add_node_error(g, node,
26702790 buf_sprintf("inline assembly allows up to one output value"));
......@@ -2699,6 +2819,9 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
26992819 case NodeTypeFieldAccessExpr:
27002820 return_type = analyze_field_access_expr(g, import, context, node);
27012821 break;
2822 case NodeTypeContainerInitExpr:
2823 return_type = analyze_container_init_expr(g, import, context, node);
2824 break;
27022825 case NodeTypeNumberLiteral:
27032826 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);
27042827 break;
......@@ -2713,14 +2836,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
27132836 case NodeTypeCharLiteral:
27142837 return_type = g->builtin_types.entry_u8;
27152838 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
27242839 case NodeTypeBoolLiteral:
27252840 return_type = g->builtin_types.entry_bool;
27262841 break;
......@@ -2730,96 +2845,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
27302845 break;
27312846
27322847 case NodeTypeSymbol:
2733 {
2734 return_type = analyze_symbol_expr(g, import, context, expected_type, node);
2735 break;
2736 }
2848 return_type = analyze_symbol_expr(g, import, context, expected_type, node);
2849 break;
27372850 case NodeTypeCastExpr:
27382851 return_type = analyze_cast_expr(g, import, context, expected_type, node);
27392852 break;
27402853 case NodeTypePrefixOpExpr:
2741 switch (node->data.prefix_op_expr.prefix_op) {
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 }
2854 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
28232855 break;
28242856 case NodeTypeIfBoolExpr:
28252857 return_type = analyze_if_bool_expr(g, import, context, expected_type, node);
......@@ -2830,17 +2862,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
28302862 case NodeTypeWhileExpr:
28312863 return_type = analyze_while_expr(g, import, context, expected_type, node);
28322864 break;
2833 case NodeTypeStructValueExpr:
2834 return_type = analyze_struct_val_expr(g, import, context, expected_type, node);
2835 break;
2836 case NodeTypeCompilerFnType:
2837 return_type = analyze_compiler_fn_type(g, import, context, expected_type, node);
2865 case NodeTypeArrayType:
2866 return_type = analyze_array_type(g, import, context, expected_type, node);
28382867 break;
28392868 case NodeTypeDirective:
28402869 case NodeTypeFnDecl:
28412870 case NodeTypeFnProto:
28422871 case NodeTypeParamDecl:
2843 case NodeTypeType:
28442872 case NodeTypeRoot:
28452873 case NodeTypeRootExportDecl:
28462874 case NodeTypeExternBlock:
......@@ -2850,7 +2878,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
28502878 case NodeTypeStructDecl:
28512879 case NodeTypeStructField:
28522880 case NodeTypeStructValueField:
2853 case NodeTypeCompilerFnExpr:
28542881 zig_unreachable();
28552882 }
28562883 assert(return_type);
......@@ -2885,8 +2912,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
28852912
28862913 // define local variables for parameters
28872914 AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;
2888 assert(param_decl->type->type == NodeTypeType);
2889 TypeTableEntry *type = param_decl->type->data.type.entry;
2915 TypeTableEntry *type = unwrapped_node_type(param_decl->type);
28902916
28912917 if (is_exported && type->id == TypeTableEntryIdStruct) {
28922918 add_node_error(g, param_decl_node,
......@@ -2918,7 +2944,7 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
29182944 }
29192945 }
29202946
2921 TypeTableEntry *expected_type = fn_proto->return_type->data.type.entry;
2947 TypeTableEntry *expected_type = unwrapped_node_type(fn_proto->return_type);
29222948 TypeTableEntry *block_return_type = analyze_expression(g, import, context, expected_type, node->data.fn_def.body);
29232949
29242950 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
29632989 case NodeTypeDirective:
29642990 case NodeTypeParamDecl:
29652991 case NodeTypeFnProto:
2966 case NodeTypeType:
29672992 case NodeTypeFnDecl:
29682993 case NodeTypeReturnExpr:
29692994 case NodeTypeRoot:
......@@ -2975,8 +3000,6 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
29753000 case NodeTypeNumberLiteral:
29763001 case NodeTypeStringLiteral:
29773002 case NodeTypeCharLiteral:
2978 case NodeTypeUnreachable:
2979 case NodeTypeVoid:
29803003 case NodeTypeBoolLiteral:
29813004 case NodeTypeNullLiteral:
29823005 case NodeTypeSymbol:
......@@ -2992,177 +3015,150 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
29923015 case NodeTypeAsmExpr:
29933016 case NodeTypeFieldAccessExpr:
29943017 case NodeTypeStructField:
2995 case NodeTypeStructValueExpr:
29963018 case NodeTypeStructValueField:
2997 case NodeTypeCompilerFnExpr:
2998 case NodeTypeCompilerFnType:
3019 case NodeTypeContainerInitExpr:
3020 case NodeTypeArrayType:
29993021 zig_unreachable();
30003022 }
30013023}
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,
30043026 TopLevelDecl *decl_node)
30053027{
3006 switch (expr_node->type) {
3028 switch (node->type) {
30073029 case NodeTypeNumberLiteral:
30083030 case NodeTypeStringLiteral:
30093031 case NodeTypeCharLiteral:
3010 case NodeTypeVoid:
30113032 case NodeTypeBoolLiteral:
30123033 case NodeTypeNullLiteral:
3013 case NodeTypeUnreachable:
30143034 case NodeTypeGoto:
30153035 case NodeTypeBreak:
30163036 case NodeTypeContinue:
30173037 // no dependencies on other top level declarations
30183038 break;
30193039 case NodeTypeSymbol:
3020 decl_node->deps.put(&expr_node->data.symbol_expr.symbol, expr_node);
3021 break;
3040 {
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 }
30223051 case NodeTypeBinOpExpr:
3023 collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op1, decl_node);
3024 collect_expr_decl_deps(g, import, expr_node->data.bin_op_expr.op2, decl_node);
3052 collect_expr_decl_deps(g, import, node->data.bin_op_expr.op1, decl_node);
3053 collect_expr_decl_deps(g, import, node->data.bin_op_expr.op2, decl_node);
30253054 break;
30263055 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);
30283057 break;
30293058 case NodeTypeCastExpr:
3030 collect_expr_decl_deps(g, import, expr_node->data.cast_expr.expr, decl_node);
3031 collect_type_decl_deps(g, import, expr_node->data.cast_expr.type, decl_node);
3059 collect_expr_decl_deps(g, import, node->data.cast_expr.expr, decl_node);
3060 collect_expr_decl_deps(g, import, node->data.cast_expr.type, decl_node);
30323061 break;
30333062 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);
30353064 break;
30363065 case NodeTypeFnCallExpr:
3037 collect_expr_decl_deps(g, import, expr_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) {
3039 AstNode *arg_node = expr_node->data.fn_call_expr.params.at(i);
3066 collect_expr_decl_deps(g, import, node->data.fn_call_expr.fn_ref_expr, decl_node);
3067 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
3068 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
30403069 collect_expr_decl_deps(g, import, arg_node, decl_node);
30413070 }
30423071 break;
30433072 case NodeTypeArrayAccessExpr:
3044 collect_expr_decl_deps(g, import, expr_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);
3073 collect_expr_decl_deps(g, import, node->data.array_access_expr.array_ref_expr, decl_node);
3074 collect_expr_decl_deps(g, import, node->data.array_access_expr.subscript, decl_node);
30463075 break;
30473076 case NodeTypeSliceExpr:
3048 collect_expr_decl_deps(g, import, expr_node->data.slice_expr.array_ref_expr, decl_node);
3049 collect_expr_decl_deps(g, import, expr_node->data.slice_expr.start, decl_node);
3050 if (expr_node->data.slice_expr.end) {
3051 collect_expr_decl_deps(g, import, expr_node->data.slice_expr.end, decl_node);
3077 collect_expr_decl_deps(g, import, node->data.slice_expr.array_ref_expr, decl_node);
3078 collect_expr_decl_deps(g, import, node->data.slice_expr.start, decl_node);
3079 if (node->data.slice_expr.end) {
3080 collect_expr_decl_deps(g, import, node->data.slice_expr.end, decl_node);
30523081 }
30533082 break;
30543083 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);
30563085 break;
30573086 case NodeTypeIfBoolExpr:
3058 collect_expr_decl_deps(g, import, expr_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);
3060 if (expr_node->data.if_bool_expr.else_node) {
3061 collect_expr_decl_deps(g, import, expr_node->data.if_bool_expr.else_node, decl_node);
3087 collect_expr_decl_deps(g, import, node->data.if_bool_expr.condition, decl_node);
3088 collect_expr_decl_deps(g, import, node->data.if_bool_expr.then_block, decl_node);
3089 if (node->data.if_bool_expr.else_node) {
3090 collect_expr_decl_deps(g, import, node->data.if_bool_expr.else_node, decl_node);
30623091 }
30633092 break;
30643093 case NodeTypeIfVarExpr:
3065 if (expr_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);
3094 if (node->data.if_var_expr.var_decl.type) {
3095 collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.type, decl_node);
30673096 }
3068 if (expr_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);
3097 if (node->data.if_var_expr.var_decl.expr) {
3098 collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.expr, decl_node);
30703099 }
3071 collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.then_block, decl_node);
3072 if (expr_node->data.if_bool_expr.else_node) {
3073 collect_expr_decl_deps(g, import, expr_node->data.if_var_expr.else_node, decl_node);
3100 collect_expr_decl_deps(g, import, node->data.if_var_expr.then_block, decl_node);
3101 if (node->data.if_bool_expr.else_node) {
3102 collect_expr_decl_deps(g, import, node->data.if_var_expr.else_node, decl_node);
30743103 }
30753104 break;
30763105 case NodeTypeWhileExpr:
3077 collect_expr_decl_deps(g, import, expr_node->data.while_expr.condition, decl_node);
3078 collect_expr_decl_deps(g, import, expr_node->data.while_expr.body, decl_node);
3106 collect_expr_decl_deps(g, import, node->data.while_expr.condition, decl_node);
3107 collect_expr_decl_deps(g, import, node->data.while_expr.body, decl_node);
30793108 break;
30803109 case NodeTypeBlock:
3081 for (int i = 0; i < expr_node->data.block.statements.length; i += 1) {
3082 AstNode *stmt = expr_node->data.block.statements.at(i);
3110 for (int i = 0; i < node->data.block.statements.length; i += 1) {
3111 AstNode *stmt = node->data.block.statements.at(i);
30833112 collect_expr_decl_deps(g, import, stmt, decl_node);
30843113 }
30853114 break;
30863115 case NodeTypeAsmExpr:
3087 for (int i = 0; i < expr_node->data.asm_expr.output_list.length; i += 1) {
3088 AsmOutput *asm_output = expr_node->data.asm_expr.output_list.at(i);
3116 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
3117 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
30893118 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);
30913120 } else {
3092 decl_node->deps.put(&asm_output->variable_name, expr_node);
3121 decl_node->deps.put(&asm_output->variable_name, node);
30933122 }
30943123 }
3095 for (int i = 0; i < expr_node->data.asm_expr.input_list.length; i += 1) {
3096 AsmInput *asm_input = expr_node->data.asm_expr.input_list.at(i);
3124 for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
3125 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
30973126 collect_expr_decl_deps(g, import, asm_input->expr, decl_node);
30983127 }
30993128 break;
3100 case NodeTypeStructValueExpr:
3101 collect_type_decl_deps(g, import, expr_node->data.struct_val_expr.type, decl_node);
3102 for (int i = 0; i < expr_node->data.struct_val_expr.fields.length; i += 1) {
3103 AstNode *field_node = expr_node->data.struct_val_expr.fields.at(i);
3104 assert(field_node->type == NodeTypeStructValueField);
3105 collect_expr_decl_deps(g, import, field_node->data.struct_val_field.expr, decl_node);
3129 case NodeTypeContainerInitExpr:
3130 collect_expr_decl_deps(g, import, node->data.container_init_expr.type, decl_node);
3131 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
3132 AstNode *child_node = node->data.container_init_expr.entries.at(i);
3133 collect_expr_decl_deps(g, import, child_node, decl_node);
31063134 }
31073135 break;
3108 case NodeTypeCompilerFnExpr:
3109 collect_expr_decl_deps(g, import, expr_node->data.compiler_fn_expr.expr, decl_node);
3136 case NodeTypeStructValueField:
3137 collect_expr_decl_deps(g, import, node->data.struct_val_field.expr, decl_node);
31103138 break;
3111 case NodeTypeCompilerFnType:
3112 collect_type_decl_deps(g, import, expr_node->data.compiler_fn_type.type, decl_node);
3139 case NodeTypeArrayType:
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);
31133144 break;
3114 case NodeTypeRoot:
3115 case NodeTypeRootExportDecl:
3145 case NodeTypeVariableDeclaration:
31163146 case NodeTypeFnProto:
3147 case NodeTypeExternBlock:
3148 case NodeTypeRootExportDecl:
31173149 case NodeTypeFnDef:
3150 case NodeTypeRoot:
31183151 case NodeTypeFnDecl:
31193152 case NodeTypeParamDecl:
3120 case NodeTypeType:
3121 case NodeTypeExternBlock:
31223153 case NodeTypeDirective:
3123 case NodeTypeVariableDeclaration:
31243154 case NodeTypeUse:
31253155 case NodeTypeLabel:
31263156 case NodeTypeStructDecl:
31273157 case NodeTypeStructField:
3128 case NodeTypeStructValueField:
31293158 zig_unreachable();
31303159 }
31313160}
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
31663162static TypeTableEntryId container_to_type(ContainerKind kind) {
31673163 switch (kind) {
31683164 case ContainerKindStruct:
......@@ -3231,7 +3227,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
32313227 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
32323228 AstNode *field_node = node->data.struct_decl.fields.at(i);
32333229 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);
32353231 }
32363232 decl_node->name = name;
32373233 decl_node->import = import;
......@@ -3271,7 +3267,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
32713267 TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl;
32723268 decl_node->deps.init(1);
32733269 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);
32753271 }
32763272 if (node->data.variable_declaration.expr) {
32773273 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
32943290 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
32953291 AstNode *param_node = node->data.fn_proto.params.at(i);
32963292 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);
32983294 }
3295 collect_expr_decl_deps(g, import, node->data.fn_proto.return_type, decl_node);
32993296
33003297 Buf *name = &node->data.fn_proto.name;
33013298 decl_node->name = name;
......@@ -3315,7 +3312,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
33153312 break;
33163313 case NodeTypeDirective:
33173314 case NodeTypeParamDecl:
3318 case NodeTypeType:
33193315 case NodeTypeFnDecl:
33203316 case NodeTypeReturnExpr:
33213317 case NodeTypeRoot:
......@@ -3327,8 +3323,6 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
33273323 case NodeTypeNumberLiteral:
33283324 case NodeTypeStringLiteral:
33293325 case NodeTypeCharLiteral:
3330 case NodeTypeUnreachable:
3331 case NodeTypeVoid:
33323326 case NodeTypeBoolLiteral:
33333327 case NodeTypeNullLiteral:
33343328 case NodeTypeSymbol:
......@@ -3344,10 +3338,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
33443338 case NodeTypeAsmExpr:
33453339 case NodeTypeFieldAccessExpr:
33463340 case NodeTypeStructField:
3347 case NodeTypeStructValueExpr:
3341 case NodeTypeContainerInitExpr:
33483342 case NodeTypeStructValueField:
3349 case NodeTypeCompilerFnExpr:
3350 case NodeTypeCompilerFnType:
3343 case NodeTypeArrayType:
33513344 zig_unreachable();
33523345 }
33533346}
......@@ -3526,18 +3519,14 @@ Expr *get_resolved_expr(AstNode *node) {
35263519 return &node->data.while_expr.resolved_expr;
35273520 case NodeTypeAsmExpr:
35283521 return &node->data.asm_expr.resolved_expr;
3529 case NodeTypeStructValueExpr:
3530 return &node->data.struct_val_expr.resolved_expr;
3522 case NodeTypeContainerInitExpr:
3523 return &node->data.container_init_expr.resolved_expr;
35313524 case NodeTypeNumberLiteral:
35323525 return &node->data.number_literal.resolved_expr;
35333526 case NodeTypeStringLiteral:
35343527 return &node->data.string_literal.resolved_expr;
35353528 case NodeTypeBlock:
35363529 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;
35413530 case NodeTypeSymbol:
35423531 return &node->data.symbol_expr.resolved_expr;
35433532 case NodeTypeVariableDeclaration:
......@@ -3554,19 +3543,16 @@ Expr *get_resolved_expr(AstNode *node) {
35543543 return &node->data.break_expr.resolved_expr;
35553544 case NodeTypeContinue:
35563545 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;
35613546 case NodeTypeLabel:
35623547 return &node->data.label.resolved_expr;
3548 case NodeTypeArrayType:
3549 return &node->data.array_type.resolved_expr;
35633550 case NodeTypeRoot:
35643551 case NodeTypeRootExportDecl:
35653552 case NodeTypeFnProto:
35663553 case NodeTypeFnDef:
35673554 case NodeTypeFnDecl:
35683555 case NodeTypeParamDecl:
3569 case NodeTypeType:
35703556 case NodeTypeExternBlock:
35713557 case NodeTypeDirective:
35723558 case NodeTypeUse:
......@@ -3581,13 +3567,12 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
35813567 switch (node->type) {
35823568 case NodeTypeNumberLiteral:
35833569 return &node->data.number_literal.codegen;
3584 case NodeTypeCompilerFnType:
3585 return &node->data.compiler_fn_type.resolved_num_lit;
3570 case NodeTypeFnCallExpr:
3571 return &node->data.fn_call_expr.resolved_num_lit;
35863572 case NodeTypeReturnExpr:
35873573 case NodeTypeBinOpExpr:
35883574 case NodeTypeCastExpr:
35893575 case NodeTypePrefixOpExpr:
3590 case NodeTypeFnCallExpr:
35913576 case NodeTypeArrayAccessExpr:
35923577 case NodeTypeSliceExpr:
35933578 case NodeTypeFieldAccessExpr:
......@@ -3595,24 +3580,21 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
35953580 case NodeTypeIfVarExpr:
35963581 case NodeTypeWhileExpr:
35973582 case NodeTypeAsmExpr:
3598 case NodeTypeStructValueExpr:
3583 case NodeTypeContainerInitExpr:
35993584 case NodeTypeRoot:
36003585 case NodeTypeRootExportDecl:
36013586 case NodeTypeFnProto:
36023587 case NodeTypeFnDef:
36033588 case NodeTypeFnDecl:
36043589 case NodeTypeParamDecl:
3605 case NodeTypeType:
36063590 case NodeTypeBlock:
36073591 case NodeTypeExternBlock:
36083592 case NodeTypeDirective:
36093593 case NodeTypeVariableDeclaration:
36103594 case NodeTypeStringLiteral:
36113595 case NodeTypeCharLiteral:
3612 case NodeTypeUnreachable:
36133596 case NodeTypeSymbol:
36143597 case NodeTypeUse:
3615 case NodeTypeVoid:
36163598 case NodeTypeBoolLiteral:
36173599 case NodeTypeNullLiteral:
36183600 case NodeTypeLabel:
......@@ -3622,7 +3604,7 @@ NumLitCodeGen *get_resolved_num_lit(AstNode *node) {
36223604 case NodeTypeStructDecl:
36233605 case NodeTypeStructField:
36243606 case NodeTypeStructValueField:
3625 case NodeTypeCompilerFnExpr:
3607 case NodeTypeArrayType:
36263608 zig_unreachable();
36273609 }
36283610}
......@@ -3648,22 +3630,19 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
36483630 case NodeTypeIfVarExpr:
36493631 case NodeTypeWhileExpr:
36503632 case NodeTypeAsmExpr:
3651 case NodeTypeStructValueExpr:
3633 case NodeTypeContainerInitExpr:
36523634 case NodeTypeRoot:
36533635 case NodeTypeRootExportDecl:
36543636 case NodeTypeFnDef:
36553637 case NodeTypeFnDecl:
36563638 case NodeTypeParamDecl:
3657 case NodeTypeType:
36583639 case NodeTypeBlock:
36593640 case NodeTypeExternBlock:
36603641 case NodeTypeDirective:
36613642 case NodeTypeStringLiteral:
36623643 case NodeTypeCharLiteral:
3663 case NodeTypeUnreachable:
36643644 case NodeTypeSymbol:
36653645 case NodeTypeUse:
3666 case NodeTypeVoid:
36673646 case NodeTypeBoolLiteral:
36683647 case NodeTypeNullLiteral:
36693648 case NodeTypeLabel:
......@@ -3672,8 +3651,23 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
36723651 case NodeTypeContinue:
36733652 case NodeTypeStructField:
36743653 case NodeTypeStructValueField:
3675 case NodeTypeCompilerFnExpr:
3676 case NodeTypeCompilerFnType:
3654 case NodeTypeArrayType:
36773655 zig_unreachable();
36783656 }
36793657}
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 @@
1313void semantic_analyze(CodeGen *g);
1414void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
1515TypeTableEntry *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);
1717VariableTableEntry *find_variable(BlockContext *context, Buf *name);
1818TypeTableEntry *find_container(BlockContext *context, Buf *name);
1919BlockContext *new_block_context(AstNode *node, BlockContext *parent);
2020Expr *get_resolved_expr(AstNode *node);
2121NumLitCodeGen *get_resolved_num_lit(AstNode *node);
2222TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
23bool is_node_void_expr(AstNode *node);
2324
2425#endif
src/codegen.cpp+197-156
......@@ -72,35 +72,35 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
7272 LLVMValueRef target_ref, LLVMValueRef value,
7373 TypeTableEntry *op1_type, TypeTableEntry *op2_type);
7474
75
76static TypeTableEntry *get_type_for_type_node(CodeGen *g, AstNode *type_node) {
77 assert(type_node->type == NodeTypeType);
78 return type_node->data.type.entry;
75static TypeTableEntry *get_type_for_type_node(AstNode *node) {
76 TypeTableEntry *meta_type_entry = get_resolved_expr(node)->type_entry;
77 assert(meta_type_entry->id == TypeTableEntryIdMetaType);
78 return meta_type_entry->data.meta_type.child_type;
7979}
8080
8181static 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
8484 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);
8686 } else {
8787 return type_entry;
8888 }
8989}
9090
9191static 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);
9393 return type_entry->di_type;
9494}
9595
9696
9797static 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;
9999}
100100
101101static bool is_param_decl_type_void(CodeGen *g, AstNode *param_decl_node) {
102102 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;
104104}
105105
106106static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
......@@ -146,6 +146,32 @@ static TypeTableEntry *get_expr_type(AstNode *node) {
146146 return expr->type_entry;
147147}
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
149175static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
150176 assert(node->type == NodeTypeFnCallExpr);
151177 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) {
154180
155181 switch (builtin_fn->id) {
156182 case BuiltinFnIdInvalid:
183 case BuiltinFnIdTypeof:
157184 zig_unreachable();
158185 case BuiltinFnIdArithmeticWithOverflow:
159186 {
......@@ -238,6 +265,74 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
238265 LLVMBuildCall(g->builder, builtin_fn->fn_val, params, 5, "");
239266 return nullptr;
240267 }
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 }
241336 }
242337 zig_unreachable();
243338}
......@@ -692,6 +787,10 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
692787 add_debug_source_node(g, node);
693788 return LLVMBuildLoad(g->builder, expr, "");
694789 }
790 case PrefixOpMaybe:
791 {
792 zig_panic("TODO codegen PrefixOpMaybe");
793 }
695794 }
696795 zig_unreachable();
697796}
......@@ -1484,35 +1583,46 @@ static LLVMValueRef gen_null_literal(CodeGen *g, AstNode *node) {
14841583 return tmp_struct_ptr;
14851584}
14861585
1487static LLVMValueRef gen_struct_val_expr(CodeGen *g, AstNode *node) {
1488 assert(node->type == NodeTypeStructValueExpr);
1586static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
1587 assert(node->type == NodeTypeContainerInitExpr);
14891588
14901589 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;
1495 assert(field_count == node->data.struct_val_expr.fields.length);
1594 int field_count = type_entry->data.structure.field_count;
1595 assert(field_count == node->data.container_init_expr.entries.length);
14961596
1497 StructValExprCodeGen *struct_val_expr_node = &node->data.struct_val_expr.codegen;
1498 LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
1597 StructValExprCodeGen *struct_val_expr_node = &node->data.container_init_expr.resolved_struct_val_expr;
1598 LLVMValueRef tmp_struct_ptr = struct_val_expr_node->ptr;
14991599
1500 for (int i = 0; i < field_count; i += 1) {
1501 AstNode *field_node = node->data.struct_val_expr.fields.at(i);
1502 assert(field_node->type == NodeTypeStructValueField);
1503 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
1504 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
1505 continue;
1600 for (int i = 0; i < field_count; i += 1) {
1601 AstNode *field_node = node->data.container_init_expr.entries.at(i);
1602 assert(field_node->type == NodeTypeStructValueField);
1603 TypeStructField *type_struct_field = field_node->data.struct_val_field.type_struct_field;
1604 if (type_struct_field->type_entry->id == TypeTableEntryIdVoid) {
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);
15061613 }
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);
1510 LLVMValueRef field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, type_struct_field->gen_index, "");
1511 LLVMValueRef value = gen_expr(g, field_node->data.struct_val_field.expr);
1512 LLVMBuildStore(g->builder, value, field_ptr);
1615 return tmp_struct_ptr;
1616 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
1617 assert(node->data.container_init_expr.entries.length == 0);
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();
15131625 }
1514
1515 return tmp_struct_ptr;
15161626}
15171627
15181628static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
......@@ -1659,93 +1769,39 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
16591769 get_resolved_expr(node)->block_context, false, &init_val);
16601770}
16611771
1662static LLVMValueRef gen_number_literal_raw(CodeGen *g, AstNode *source_node,
1663 NumLitCodeGen *codegen_num_lit, AstNodeNumberLiteral *num_lit_node)
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
1772static LLVMValueRef gen_number_literal(CodeGen *g, AstNode *node) {
1773 assert(node->type == NodeTypeNumberLiteral);
16751774
1676 return LLVMConstInt(type_entry->type_ref,
1677 num_lit_node->data.x_uint,
1678 type_entry->data.integral.is_signed);
1679 } else if (type_entry->id == TypeTableEntryIdFloat) {
1775 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1776 assert(codegen_num_lit);
16801777
1681 return LLVMConstReal(type_entry->type_ref,
1682 num_lit_node->data.x_float);
1683 } else {
1684 zig_panic("bad number literal type");
1685 }
1778 return gen_number_literal_raw(g, node, codegen_num_lit, &node->data.number_literal);
16861779}
16871780
1688static LLVMValueRef gen_compiler_fn_type(CodeGen *g, AstNode *node) {
1689 assert(node->type == NodeTypeCompilerFnType);
1690
1691 Buf *name = &node->data.compiler_fn_type.name;
1692 TypeTableEntry *type_entry = get_type_for_type_node(g, node->data.compiler_fn_type.type);
1693 if (buf_eql_str(name, "sizeof")) {
1694 NumLitCodeGen *codegen_num_lit = get_resolved_num_lit(node);
1695 AstNodeNumberLiteral num_lit_node;
1696 num_lit_node.kind = type_entry->data.num_lit.kind;
1697 num_lit_node.overflow = false;
1698 num_lit_node.data.x_uint = type_entry->size_in_bits / 8;
1699 return gen_number_literal_raw(g, node, codegen_num_lit, &num_lit_node);
1700 } else if (buf_eql_str(name, "min_value")) {
1701 if (type_entry->id == TypeTableEntryIdInt) {
1702 if (type_entry->data.integral.is_signed) {
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);
1781static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
1782 VariableTableEntry *variable = find_variable(
1783 get_resolved_expr(node)->block_context,
1784 &node->data.symbol_expr.symbol);
1785 assert(variable);
1786 if (variable->type->id == TypeTableEntryIdVoid) {
1787 return nullptr;
1788 } else if (variable->is_ptr) {
1789 assert(variable->value_ref);
1790 if (variable->type->id == TypeTableEntryIdArray) {
1791 return variable->value_ref;
1792 } else if (variable->type->id == TypeTableEntryIdStruct ||
1793 variable->type->id == TypeTableEntryIdMaybe)
1794 {
1795 return variable->value_ref;
17321796 } else {
1733 zig_unreachable();
1797 add_debug_source_node(g, node);
1798 return LLVMBuildLoad(g->builder, variable->value_ref, "");
17341799 }
17351800 } else {
1736 zig_unreachable();
1801 return variable->value_ref;
17371802 }
17381803}
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
17491805static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
17501806 switch (node->type) {
17511807 case NodeTypeBinOpExpr:
......@@ -1766,11 +1822,6 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
17661822 return gen_slice_expr(g, node);
17671823 case NodeTypeFieldAccessExpr:
17681824 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;
17741825 case NodeTypeBoolLiteral:
17751826 if (node->data.bool_literal.value)
17761827 return LLVMConstAllOnes(LLVMInt1Type());
......@@ -1802,29 +1853,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
18021853 case NodeTypeCharLiteral:
18031854 return LLVMConstInt(LLVMInt8Type(), node->data.char_literal.value, false);
18041855 case NodeTypeSymbol:
1805 {
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 }
1856 return gen_symbol(g, node);
18281857 case NodeTypeBlock:
18291858 return gen_block(g, node, nullptr);
18301859 case NodeTypeGoto:
......@@ -1846,24 +1875,21 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
18461875 LLVMPositionBuilderAtEnd(g->builder, basic_block);
18471876 return nullptr;
18481877 }
1849 case NodeTypeStructValueExpr:
1850 return gen_struct_val_expr(g, node);
1851 case NodeTypeCompilerFnType:
1852 return gen_compiler_fn_type(g, node);
1878 case NodeTypeContainerInitExpr:
1879 return gen_container_init_expr(g, node);
18531880 case NodeTypeRoot:
18541881 case NodeTypeRootExportDecl:
18551882 case NodeTypeFnProto:
18561883 case NodeTypeFnDef:
18571884 case NodeTypeFnDecl:
18581885 case NodeTypeParamDecl:
1859 case NodeTypeType:
18601886 case NodeTypeExternBlock:
18611887 case NodeTypeDirective:
18621888 case NodeTypeUse:
18631889 case NodeTypeStructDecl:
18641890 case NodeTypeStructField:
18651891 case NodeTypeStructValueField:
1866 case NodeTypeCompilerFnExpr:
1892 case NodeTypeArrayType:
18671893 zig_unreachable();
18681894 }
18691895 zig_unreachable();
......@@ -1872,7 +1898,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) {
18721898static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
18731899 LLVMValueRef val = gen_expr_no_cast(g, node);
18741900
1875 if (node->type == NodeTypeVoid) {
1901 if (is_node_void_expr(node)) {
18761902 return val;
18771903 }
18781904
......@@ -1966,7 +1992,7 @@ static void do_code_gen(CodeGen *g) {
19661992 assert(proto_node->type == NodeTypeFnProto);
19671993 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;
19701996 int param_count = count_non_void_params(g, &fn_proto->params);
19711997 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(param_count);
19721998 int gen_param_index = 0;
......@@ -2009,7 +2035,7 @@ static void do_code_gen(CodeGen *g) {
20092035 TypeTableEntry *param_type = fn_proto_type_from_type_node(g, type_node);
20102036 LLVMValueRef argument_val = LLVMGetParam(fn, gen_param_index);
20112037 if (param_type->id == TypeTableEntryIdPointer &&
2012 param_type->data.pointer.is_noalias)
2038 false) // TODO test if parameter is noalias
20132039 {
20142040 LLVMAddAttribute(argument_val, LLVMNoAliasAttribute);
20152041 } else if (param_type->id == TypeTableEntryIdPointer &&
......@@ -2267,7 +2293,7 @@ static void define_builtin_types(CodeGen *g) {
22672293 g->builtin_types.entry_u64 = entry;
22682294 g->primitive_type_table.put(&entry->name, entry);
22692295 }
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);
22712297 {
22722298 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
22732299 entry->type_ref = LLVMInt8Type();
......@@ -2413,7 +2439,7 @@ static void define_builtin_fns_int(CodeGen *g, TypeTableEntry *type_entry) {
24132439 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
24142440 builtin_fn->param_types[0] = type_entry;
24152441 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
24192445 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) {
24372463 }
24382464}
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
24402483static void define_builtin_fns(CodeGen *g) {
24412484 define_builtin_fns_int(g, g->builtin_types.entry_u8);
24422485 define_builtin_fns_int(g, g->builtin_types.entry_u16);
......@@ -2447,9 +2490,7 @@ static void define_builtin_fns(CodeGen *g) {
24472490 define_builtin_fns_int(g, g->builtin_types.entry_i32);
24482491 define_builtin_fns_int(g, g->builtin_types.entry_i64);
24492492 {
2450 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
2451 buf_init_from_str(&builtin_fn->name, "memcpy");
2452 builtin_fn->id = BuiltinFnIdMemcpy;
2493 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
24532494 builtin_fn->return_type = g->builtin_types.entry_void;
24542495 builtin_fn->param_count = 3;
24552496 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
......@@ -2470,12 +2511,9 @@ static void define_builtin_fns(CodeGen *g) {
24702511 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
24712512
24722513 g->memcpy_fn_val = builtin_fn->fn_val;
2473 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
24742514 }
24752515 {
2476 BuiltinFnEntry *builtin_fn = allocate<BuiltinFnEntry>(1);
2477 buf_init_from_str(&builtin_fn->name, "memset");
2478 builtin_fn->id = BuiltinFnIdMemset;
2516 BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemset, "memset");
24792517 builtin_fn->return_type = g->builtin_types.entry_void;
24802518 builtin_fn->param_count = 3;
24812519 builtin_fn->param_types = allocate<TypeTableEntry *>(builtin_fn->param_count);
......@@ -2496,8 +2534,12 @@ static void define_builtin_fns(CodeGen *g) {
24962534 assert(LLVMGetIntrinsicID(builtin_fn->fn_val));
24972535
24982536 g->memset_fn_val = builtin_fn->fn_val;
2499 g->builtin_fn_table.put(&builtin_fn->name, builtin_fn);
25002537 }
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");
25012543}
25022544
25032545
......@@ -2780,9 +2822,8 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
27802822}
27812823
27822824static void to_c_type(CodeGen *g, AstNode *type_node, Buf *out_buf) {
2783 assert(type_node->type == NodeTypeType);
2784
2785 TypeTableEntry *type_entry = type_node->data.type.entry;
2825 zig_panic("TODO this function needs some love");
2826 TypeTableEntry *type_entry = get_resolved_expr(type_node)->type_entry;
27862827 assert(type_entry);
27872828
27882829 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) {
6262 case PrefixOpAddressOf: return "&";
6363 case PrefixOpConstAddressOf: return "&const";
6464 case PrefixOpDereference: return "*";
65 case PrefixOpMaybe: return "?";
6566 }
6667 zig_unreachable();
6768}
......@@ -80,8 +81,6 @@ const char *node_type_str(NodeType node_type) {
8081 return "FnProto";
8182 case NodeTypeParamDecl:
8283 return "ParamDecl";
83 case NodeTypeType:
84 return "Type";
8584 case NodeTypeBlock:
8685 return "Block";
8786 case NodeTypeBinOpExpr:
......@@ -108,16 +107,12 @@ const char *node_type_str(NodeType node_type) {
108107 return "StringLiteral";
109108 case NodeTypeCharLiteral:
110109 return "CharLiteral";
111 case NodeTypeUnreachable:
112 return "Unreachable";
113110 case NodeTypeSymbol:
114111 return "Symbol";
115112 case NodeTypePrefixOpExpr:
116113 return "PrefixOpExpr";
117114 case NodeTypeUse:
118115 return "Use";
119 case NodeTypeVoid:
120 return "Void";
121116 case NodeTypeBoolLiteral:
122117 return "BoolLiteral";
123118 case NodeTypeNullLiteral:
......@@ -144,14 +139,12 @@ const char *node_type_str(NodeType node_type) {
144139 return "StructDecl";
145140 case NodeTypeStructField:
146141 return "StructField";
147 case NodeTypeStructValueExpr:
148 return "StructValueExpr";
149142 case NodeTypeStructValueField:
150143 return "StructValueField";
151 case NodeTypeCompilerFnExpr:
152 return "CompilerFnExpr";
153 case NodeTypeCompilerFnType:
154 return "CompilerFnType";
144 case NodeTypeContainerInitExpr:
145 return "ContainerInitExpr";
146 case NodeTypeArrayType:
147 return "ArrayType";
155148 }
156149 zig_unreachable();
157150}
......@@ -214,47 +207,6 @@ void ast_print(AstNode *node, int indent) {
214207
215208 break;
216209 }
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;
258210 case NodeTypeReturnExpr:
259211 fprintf(stderr, "%s\n", node_type_str(node->type));
260212 if (node->data.return_expr.expr)
......@@ -348,18 +300,12 @@ void ast_print(AstNode *node, int indent) {
348300 fprintf(stderr, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
349301 break;
350302 }
351 case NodeTypeUnreachable:
352 fprintf(stderr, "Unreachable\n");
353 break;
354303 case NodeTypeSymbol:
355304 fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
356305 break;
357306 case NodeTypeUse:
358307 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path));
359308 break;
360 case NodeTypeVoid:
361 fprintf(stderr, "%s\n", node_type_str(node->type));
362 break;
363309 case NodeTypeBoolLiteral:
364310 fprintf(stderr, "%s '%s'\n", node_type_str(node->type),
365311 node->data.bool_literal.value ? "true" : "false");
......@@ -431,24 +377,28 @@ void ast_print(AstNode *node, int indent) {
431377 ast_print(node->data.struct_field.type, indent + 2);
432378 }
433379 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;
442380 case NodeTypeStructValueField:
443381 fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));
444382 ast_print(node->data.struct_val_field.expr, indent + 2);
445383 break;
446 case NodeTypeCompilerFnExpr:
447 fprintf(stderr, "%s\n", node_type_str(node->type));
448 break;
449 case NodeTypeCompilerFnType:
384 case NodeTypeContainerInitExpr:
450385 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 }
451391 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 }
452402 }
453403}
454404
......@@ -539,9 +489,8 @@ static AstNode *ast_create_node_with_node(ParseContext *pc, NodeType type, AstNo
539489}
540490
541491static AstNode *ast_create_void_type_node(ParseContext *pc, Token *token) {
542 AstNode *node = ast_create_node(pc, NodeTypeType, token);
543 node->data.type.type = AstNodeTypeTypePrimitive;
544 buf_init_from_str(&node->data.type.primitive_name, "void");
492 AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
493 buf_init_from_str(&node->data.symbol_expr.symbol, "void");
545494 return node;
546495}
547496
......@@ -961,7 +910,7 @@ static AstNode *ast_parse_expression(ParseContext *pc, int *token_index, bool ma
961910static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandatory);
962911static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory);
963912static 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
966915static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
967916 if (token->id != token_id) {
......@@ -1022,172 +971,42 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,
1022971 zig_unreachable();
1023972}
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
1044974/*
1045CompilerFnType : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen)
975ParamDecl : option(token(NoAlias)) token(Symbol) token(Colon) UnwrapMaybeExpression | token(Ellipsis)
1046976*/
1047static AstNode *ast_parse_compiler_fn_type(ParseContext *pc, int *token_index, bool mandatory) {
1048 Token *token = &pc->tokens->at(*token_index);
977static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {
978 Token *first_token = &pc->tokens->at(*token_index);
1049979
1050 if (token->id == TokenIdNumberSign) {
980 if (first_token->id == TokenIdEllipsis) {
1051981 *token_index += 1;
1052 } else if (mandatory) {
1053 ast_invalid_token_error(pc, token);
1054 } else {
1055982 return nullptr;
1056983 }
1057984
1058 Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);
1059 ast_eat_token(pc, token_index, TokenIdLParen);
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}
985 AstNode *node = ast_create_node(pc, NodeTypeParamDecl, first_token);
986 Token *name_token;
1068987
1069/*
1070CompilerFnExpr : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen)
1071*/
1072static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, bool mandatory) {
1073 Token *token = &pc->tokens->at(*token_index);
1074
1075 if (token->id == TokenIdNumberSign) {
988 if (first_token->id == TokenIdKeywordNoAlias) {
989 node->data.param_decl.is_noalias = true;
990 *token_index += 1;
991 name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
992 } else if (first_token->id == TokenIdSymbol) {
993 name_token = first_token;
1076994 *token_index += 1;
1077 } else if (mandatory) {
1078 ast_invalid_token_error(pc, token);
1079995 } else {
1080 return nullptr;
996 ast_invalid_token_error(pc, first_token);
1081997 }
1082998
1083 Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol);
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 }
999 ast_buf_from_token(pc, name_token, &node->data.param_decl.name);
11091000
1001 Token *colon = &pc->tokens->at(*token_index);
11101002 *token_index += 1;
1003 ast_expect_token(pc, colon, TokenIdColon);
11111004
1112 if (token->id == TokenIdKeywordUnreachable) {
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 }
1005 node->data.param_decl.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
11611006
11621007 return node;
11631008}
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
11921011static void ast_parse_param_decl_list(ParseContext *pc, int *token_index,
11931012 ZigList<AstNode *> *params, bool *is_var_args)
......@@ -1274,52 +1093,222 @@ static AstNode *ast_parse_grouped_expr(ParseContext *pc, int *token_index, bool
12741093}
12751094
12761095/*
1277StructValueExpression : token(Symbol) token(LBrace) list(StructValueExpressionField, token(Comma)) token(RBrace)
1278StructValueExpressionField : token(Dot) token(Symbol) token(Eq) Expression
1096ArrayType : token(LBracket) option(Expression) token(RBracket) option(token(Const)) Expression
12791097*/
1280static AstNode *ast_parse_struct_val_expr(ParseContext *pc, int *token_index) {
1281 Token *first_token = &pc->tokens->at(*token_index);
1282 AstNode *node = ast_create_node(pc, NodeTypeStructValueExpr, first_token);
1098static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bool mandatory) {
1099 Token *l_bracket = &pc->tokens->at(*token_index);
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
12881189 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);
12901192 *token_index += 1;
12911193
1292 if (token->id == TokenIdRBrace) {
1293 return node;
1294 } else if (token->id == TokenIdDot) {
1295 Token *field_name_tok = ast_eat_token(pc, token_index, TokenIdSymbol);
1296 ast_eat_token(pc, token_index, TokenIdEq);
1194 Buf *clobber_buf = buf_alloc();
1195 parse_string_literal(pc, string_tok, clobber_buf, nullptr, nullptr);
1196 node->data.asm_expr.clobber_list.append(clobber_buf);
1197
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);
1301 field_node->data.struct_val_field.expr = ast_parse_expression(pc, token_index, true);
1215 if (colon_tok->id != TokenIdColon)
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);
1306 if (comma_tok->id == TokenIdComma) {
1307 *token_index += 1;
1308 } else if (comma_tok->id != TokenIdRBrace) {
1309 ast_invalid_token_error(pc, comma_tok);
1310 } else {
1311 *token_index += 1;
1312 return node;
1313 }
1220 for (;;) {
1221 ast_parse_asm_input_item(pc, token_index, node);
1222
1223 Token *comma = &pc->tokens->at(*token_index);
1224
1225 if (comma->id == TokenIdComma) {
1226 *token_index += 1;
1227 continue;
13141228 } else {
1315 ast_invalid_token_error(pc, token);
1229 break;
13161230 }
13171231 }
1232
1233 ast_parse_asm_clobbers(pc, token_index, node);
13181234}
13191235
13201236/*
1321PrimaryExpression : token(Number) | token(String) | token(CharLiteral) | KeywordLiteral | GroupedExpression | Goto | token(Break) | token(Continue) | BlockExpression | token(Symbol) | StructValueExpression | CompilerFnType | (token(AtSign) token(Symbol) FnCallExpression)
1322KeywordLiteral : token(Unreachable) | token(Void) | token(True) | token(False) | token(Null)
1237AsmOutput : token(Colon) list(AsmOutputItem, token(Comma)) option(AsmInput)
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)
13231312*/
13241313static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool mandatory) {
13251314 Token *token = &pc->tokens->at(*token_index);
......@@ -1339,14 +1328,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
13391328 node->data.char_literal.value = parse_char_literal(pc, token);
13401329 *token_index += 1;
13411330 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;
13501331 } else if (token->id == TokenIdKeywordTrue) {
13511332 AstNode *node = ast_create_node(pc, NodeTypeBoolLiteral, token);
13521333 node->data.bool_literal.value = true;
......@@ -1357,8 +1338,16 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
13571338 node->data.bool_literal.value = false;
13581339 *token_index += 1;
13591340 return node;
1360 } else if (token->id == TokenIdKeywordNull) {
1361 AstNode *node = ast_create_node(pc, NodeTypeNullLiteral, token);
1341 } else if (token->id == TokenIdKeywordNull) {
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);
13621351 *token_index += 1;
13631352 return node;
13641353 } else if (token->id == TokenIdAtSign) {
......@@ -1374,16 +1363,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
13741363 node->data.fn_call_expr.is_builtin = true;
13751364 return node;
13761365 } else if (token->id == TokenIdSymbol) {
1377 Token *next_token = &pc->tokens->at(*token_index + 1);
1378
1379 if (next_token->id == TokenIdLBrace) {
1380 return ast_parse_struct_val_expr(pc, token_index);
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 }
1366 *token_index += 1;
1367 AstNode *node = ast_create_node(pc, NodeTypeSymbol, token);
1368 ast_buf_from_token(pc, token, &node->data.symbol_expr.symbol);
1369 return node;
13871370 } else if (token->id == TokenIdKeywordGoto) {
13881371 AstNode *node = ast_create_node(pc, NodeTypeGoto, token);
13891372 *token_index += 1;
......@@ -1394,14 +1377,6 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
13941377
13951378 ast_buf_from_token(pc, dest_symbol, &node->data.goto_expr.name);
13961379 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;
14051380 }
14061381
14071382 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
14141389 return block_expr_node;
14151390 }
14161391
1417 AstNode *compiler_fn_type = ast_parse_compiler_fn_type(pc, token_index, false);
1418 if (compiler_fn_type) {
1419 return compiler_fn_type;
1392 AstNode *array_type_node = ast_parse_array_type_expr(pc, token_index, false);
1393 if (array_type_node) {
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;
14201400 }
14211401
14221402 if (!mandatory)
......@@ -1426,11 +1406,14 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, int *token_index, bool
14261406}
14271407
14281408/*
1429SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression)
1409SuffixOpExpression : PrimaryExpression option(FnCallExpression | ArrayAccessExpression | FieldAccessExpression | SliceExpression | ContainerInitExpression)
14301410FnCallExpression : token(LParen) list(Expression, token(Comma)) token(RParen)
14311411ArrayAccessExpression : token(LBracket) Expression token(RBracket)
14321412SliceExpression : token(LBracket) Expression token(Ellipsis) option(Expression) token(RBracket) option(token(Const))
14331413FieldAccessExpression : 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
14341417*/
14351418static AstNode *ast_parse_suffix_op_expr(ParseContext *pc, int *token_index, bool mandatory) {
14361419 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
14391422 }
14401423
14411424 while (true) {
1442 Token *token = &pc->tokens->at(*token_index);
1443 if (token->id == TokenIdLParen) {
1425 Token *first_token = &pc->tokens->at(*token_index);
1426 if (first_token->id == TokenIdLParen) {
14441427 *token_index += 1;
14451428
1446 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, token);
1429 AstNode *node = ast_create_node(pc, NodeTypeFnCallExpr, first_token);
14471430 node->data.fn_call_expr.fn_ref_expr = primary_expr;
14481431 ast_parse_fn_call_param_list(pc, token_index, &node->data.fn_call_expr.params);
14491432
14501433 primary_expr = node;
1451 } else if (token->id == TokenIdLBracket) {
1434 } else if (first_token->id == TokenIdLBracket) {
14521435 *token_index += 1;
14531436
14541437 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
14581441 if (ellipsis_or_r_bracket->id == TokenIdEllipsis) {
14591442 *token_index += 1;
14601443
1461 AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, token);
1444 AstNode *node = ast_create_node(pc, NodeTypeSliceExpr, first_token);
14621445 node->data.slice_expr.array_ref_expr = primary_expr;
14631446 node->data.slice_expr.start = expr_node;
14641447 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
14751458 } else if (ellipsis_or_r_bracket->id == TokenIdRBracket) {
14761459 *token_index += 1;
14771460
1478 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, token);
1461 AstNode *node = ast_create_node(pc, NodeTypeArrayAccessExpr, first_token);
14791462 node->data.array_access_expr.array_ref_expr = primary_expr;
14801463 node->data.array_access_expr.subscript = expr_node;
14811464
14821465 primary_expr = node;
14831466 } else {
1484 ast_invalid_token_error(pc, token);
1467 ast_invalid_token_error(pc, first_token);
14851468 }
1486 } else if (token->id == TokenIdDot) {
1469 } else if (first_token->id == TokenIdDot) {
14871470 *token_index += 1;
14881471
14891472 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);
14921475 node->data.field_access_expr.struct_expr = primary_expr;
14931476 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
14951543 primary_expr = node;
14961544 } else {
14971545 return primary_expr;
......@@ -1506,56 +1554,54 @@ static PrefixOp tok_to_prefix_op(Token *token) {
15061554 case TokenIdTilde: return PrefixOpBinNot;
15071555 case TokenIdAmpersand: return PrefixOpAddressOf;
15081556 case TokenIdStar: return PrefixOpDereference;
1557 case TokenIdMaybe: return PrefixOpMaybe;
1558 case TokenIdBoolAnd: return PrefixOpAddressOf;
15091559 default: return PrefixOpInvalid;
15101560 }
15111561}
15121562
15131563/*
1564PrefixOpExpression : PrefixOp PrefixOpExpression | SuffixOpExpression
15141565PrefixOp : token(Not) | token(Dash) | token(Tilde) | token(Star) | (token(Ampersand) option(token(Const)))
15151566*/
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) {
15171568 Token *token = &pc->tokens->at(*token_index);
1518 PrefixOp result = tok_to_prefix_op(token);
1519 if (result == PrefixOpInvalid) {
1520 if (mandatory) {
1521 ast_invalid_token_error(pc, token);
1522 } else {
1523 return PrefixOpInvalid;
1524 }
1569 PrefixOp prefix_op = tok_to_prefix_op(token);
1570 if (prefix_op == PrefixOpInvalid) {
1571 return ast_parse_suffix_op_expr(pc, token_index, mandatory);
15251572 }
15261573 *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) {
15291588 Token *token = &pc->tokens->at(*token_index);
15301589 if (token->id == TokenIdKeywordConst) {
15311590 *token_index += 1;
1532 result = PrefixOpConstAddressOf;
1591 prefix_op = PrefixOpConstAddressOf;
15331592 }
15341593 }
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
15481595 AstNode *prefix_op_expr = ast_parse_prefix_op_expr(pc, token_index, true);
1549 AstNode *node = ast_create_node(pc, NodeTypePrefixOpExpr, token);
15501596 node->data.prefix_op_expr.primary_expr = prefix_op_expr;
15511597 node->data.prefix_op_expr.prefix_op = prefix_op;
15521598
1553 return node;
1599 return parent_node;
15541600}
15551601
15561602
15571603/*
1558CastExpression : CastExpression token(as) Type | PrefixOpExpression
1604CastExpression : CastExpression token(as) PrimaryExpression | PrefixOpExpression
15591605*/
15601606static AstNode *ast_parse_cast_expression(ParseContext *pc, int *token_index, bool mandatory) {
15611607 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
15711617 AstNode *node = ast_create_node(pc, NodeTypeCastExpr, as_kw);
15721618 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
15761622 operand_1 = node;
15771623 }
......@@ -1899,7 +1945,7 @@ static AstNode *ast_parse_else(ParseContext *pc, int *token_index, bool mandator
18991945/*
19001946IfExpression : IfVarExpression | IfBoolExpression
19011947IfBoolExpression : 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)
19031949*/
19041950static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool mandatory) {
19051951 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
19241970 ast_buf_from_token(pc, name_token, &node->data.if_var_expr.var_decl.symbol);
19251971
19261972 Token *eq_or_colon = &pc->tokens->at(*token_index);
1927 *token_index += 1;
19281973 if (eq_or_colon->id == TokenIdMaybeAssign) {
1974 *token_index += 1;
19291975 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
19301976 } 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
19331980 ast_eat_token(pc, token_index, TokenIdMaybeAssign);
19341981 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
19672014}
19682015
19692016/*
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))
19712018*/
19722019static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {
19732020 Token *first_token = &pc->tokens->at(*token_index);
......@@ -2008,8 +2055,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
20082055 node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
20092056 return node;
20102057 } else if (eq_or_colon->id == TokenIdColon) {
2011 node->data.variable_declaration.type = ast_parse_type(pc, token_index);
2012
2058 node->data.variable_declaration.type = ast_parse_unwrap_maybe_expr(pc, token_index, true);
20132059 Token *eq_token = &pc->tokens->at(*token_index);
20142060 if (eq_token->id == TokenIdEq) {
20152061 *token_index += 1;
......@@ -2138,6 +2184,7 @@ static BinOpType ast_parse_ass_op(ParseContext *pc, int *token_index, bool manda
21382184/*
21392185UnwrapMaybeExpression : BoolOrExpression token(DoubleQuestion) BoolOrExpression | BoolOrExpression
21402186*/
2187// this is currently the first child expression of assignment
21412188static AstNode *ast_parse_unwrap_maybe_expr(ParseContext *pc, int *token_index, bool mandatory) {
21422189 AstNode *lhs = ast_parse_bool_or_expr(pc, token_index, mandatory);
21432190 if (!lhs)
......@@ -2185,190 +2232,7 @@ static AstNode *ast_parse_ass_expr(ParseContext *pc, int *token_index, bool mand
21852232}
21862233
21872234/*
2188AsmInputItem : token(LBracket) token(Symbol) token(RBracket) token(String) token(LParen) Expression token(RParen)
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
2235NonBlockExpression : ReturnExpression | AssignmentExpression
23722236*/
23732237static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
23742238 Token *token = &pc->tokens->at(*token_index);
......@@ -2381,10 +2245,6 @@ static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, boo
23812245 if (ass_expr)
23822246 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
23882248 if (mandatory)
23892249 ast_invalid_token_error(pc, token);
23902250
......@@ -2440,6 +2300,14 @@ static AstNode *ast_parse_label(ParseContext *pc, int *token_index, bool mandato
24402300 return node;
24412301}
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
24432311/*
24442312Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
24452313Statement : Label | VariableDeclaration token(Semicolon) | NonBlockExpression token(Semicolon) | BlockExpression
......@@ -2478,7 +2346,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
24782346 if (!statement_node) {
24792347 statement_node = ast_parse_non_block_expr(pc, token_index, false);
24802348 if (!statement_node) {
2481 statement_node = ast_create_node(pc, NodeTypeVoid, last_token);
2349 statement_node = ast_create_void_expr(pc, last_token);
24822350 }
24832351 }
24842352 }
......@@ -2501,7 +2369,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
25012369}
25022370
25032371/*
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)
25052373*/
25062374static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory) {
25072375 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
25522420
25532421 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);
2556 if (arrow->id == TokenIdArrow) {
2557 *token_index += 1;
2558 node->data.fn_proto.return_type = ast_parse_type(pc, token_index);
2559 } else {
2560 node->data.fn_proto.return_type = ast_create_void_type_node(pc, arrow);
2423 Token *next_token = &pc->tokens->at(*token_index);
2424 node->data.fn_proto.return_type = ast_parse_expression(pc, token_index, false);
2425 if (!node->data.fn_proto.return_type) {
2426 node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token);
25612427 }
25622428
25632429 return node;
25642430}
25652431
25662432/*
2567FnDef : FnProto Block
2433FnDef : FnProto token(FatArrow) Block
25682434*/
25692435static AstNode *ast_parse_fn_def(ParseContext *pc, int *token_index, bool mandatory) {
25702436 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
25732439 AstNode *node = ast_create_node_with_node(pc, NodeTypeFnDef, fn_proto);
25742440
25752441 node->data.fn_def.fn_proto = fn_proto;
2442 ast_eat_token(pc, token_index, TokenIdFatArrow);
25762443 node->data.fn_def.body = ast_parse_block(pc, token_index, true);
25772444
25782445 return node;
......@@ -2709,7 +2576,7 @@ static AstNode *ast_parse_use(ParseContext *pc, int *token_index) {
27092576/*
27102577ContainerDecl : many(Directive) option(FnVisibleMod) (token(Struct) | token(Enum)) token(Symbol) token(LBrace) many(StructMember) token(RBrace)
27112578StructMember: StructField | FnDecl
2712StructField : token(Symbol) token(Colon) Type token(Comma)
2579StructField : token(Symbol) option(token(Colon) Expression) token(Comma))
27132580*/
27142581static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
27152582 Token *first_token = &pc->tokens->at(*token_index);
......@@ -2792,16 +2659,16 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index) {
27922659
27932660 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);
27942661
2795 Token *colon_tok = &pc->tokens->at(*token_index);
2796 if (colon_tok->id == TokenIdColon) {
2662 Token *expr_or_comma = &pc->tokens->at(*token_index);
2663 if (expr_or_comma->id == TokenIdComma) {
2664 field_node->data.struct_field.type = ast_create_void_type_node(pc, expr_or_comma);
27972665 *token_index += 1;
2798 field_node->data.struct_field.type = ast_parse_type(pc, token_index);
27992666 } 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);
28012670 }
28022671
2803 ast_eat_token(pc, token_index, TokenIdComma);
2804
28052672 node->data.struct_decl.fields.append(field_node);
28062673 } else {
28072674 ast_invalid_token_error(pc, token);
src/tokenizer.cpp+6-6
......@@ -207,8 +207,6 @@ static void end_token(Tokenize *t) {
207207 t->cur_tok->id = TokenIdKeywordConst;
208208 } else if (mem_eql_str(token_mem, token_len, "extern")) {
209209 t->cur_tok->id = TokenIdKeywordExtern;
210 } else if (mem_eql_str(token_mem, token_len, "unreachable")) {
211 t->cur_tok->id = TokenIdKeywordUnreachable;
212210 } else if (mem_eql_str(token_mem, token_len, "pub")) {
213211 t->cur_tok->id = TokenIdKeywordPub;
214212 } else if (mem_eql_str(token_mem, token_len, "export")) {
......@@ -217,8 +215,6 @@ static void end_token(Tokenize *t) {
217215 t->cur_tok->id = TokenIdKeywordAs;
218216 } else if (mem_eql_str(token_mem, token_len, "use")) {
219217 t->cur_tok->id = TokenIdKeywordUse;
220 } else if (mem_eql_str(token_mem, token_len, "void")) {
221 t->cur_tok->id = TokenIdKeywordVoid;
222218 } else if (mem_eql_str(token_mem, token_len, "true")) {
223219 t->cur_tok->id = TokenIdKeywordTrue;
224220 } else if (mem_eql_str(token_mem, token_len, "false")) {
......@@ -553,6 +549,11 @@ void tokenize(Buf *buf, Tokenization *out) {
553549 end_token(&t);
554550 t.state = TokenizeStateStart;
555551 break;
552 case '>':
553 t.cur_tok->id = TokenIdFatArrow;
554 end_token(&t);
555 t.state = TokenizeStateStart;
556 break;
556557 default:
557558 t.pos -= 1;
558559 end_token(&t);
......@@ -1009,12 +1010,10 @@ static const char * token_name(Token *token) {
10091010 case TokenIdKeywordVar: return "Var";
10101011 case TokenIdKeywordReturn: return "Return";
10111012 case TokenIdKeywordExtern: return "Extern";
1012 case TokenIdKeywordUnreachable: return "Unreachable";
10131013 case TokenIdKeywordPub: return "Pub";
10141014 case TokenIdKeywordExport: return "Export";
10151015 case TokenIdKeywordAs: return "As";
10161016 case TokenIdKeywordUse: return "Use";
1017 case TokenIdKeywordVoid: return "Void";
10181017 case TokenIdKeywordTrue: return "True";
10191018 case TokenIdKeywordFalse: return "False";
10201019 case TokenIdKeywordIf: return "If";
......@@ -1044,6 +1043,7 @@ static const char * token_name(Token *token) {
10441043 case TokenIdPlus: return "Plus";
10451044 case TokenIdColon: return "Colon";
10461045 case TokenIdArrow: return "Arrow";
1046 case TokenIdFatArrow: return "FatArrow";
10471047 case TokenIdDash: return "Dash";
10481048 case TokenIdNumberSign: return "NumberSign";
10491049 case TokenIdBinOr: return "BinOr";
src/tokenizer.hpp+1-2
......@@ -18,12 +18,10 @@ enum TokenId {
1818 TokenIdKeywordVar,
1919 TokenIdKeywordConst,
2020 TokenIdKeywordExtern,
21 TokenIdKeywordUnreachable,
2221 TokenIdKeywordPub,
2322 TokenIdKeywordExport,
2423 TokenIdKeywordAs,
2524 TokenIdKeywordUse,
26 TokenIdKeywordVoid,
2725 TokenIdKeywordTrue,
2826 TokenIdKeywordFalse,
2927 TokenIdKeywordIf,
......@@ -53,6 +51,7 @@ enum TokenId {
5351 TokenIdPlus,
5452 TokenIdColon,
5553 TokenIdArrow,
54 TokenIdFatArrow,
5655 TokenIdDash,
5756 TokenIdNumberSign,
5857 TokenIdBoolOr,
std/bootstrap.zig+30-5
......@@ -3,10 +3,35 @@ use "syscall.zig";
33// The compiler treats this file special by implicitly importing the function `main`
44// from the root source file.
55
6var env: &&u8;
7
68#attribute("naked")
7export fn _start() -> unreachable {
8 const argc = asm("mov (%%rsp), %[argc]" : [argc] "=r" (-> isize));
9 const argv = asm("lea 0x8(%%rsp), %[argv]" : [argv] "=r" (-> &&u8));
10 const env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]" : [env] "=r" (-> &&u8));
11 exit(main(argc, argv, env))
9export fn _start() unreachable => {
10 const argc = asm("mov (%%rsp), %[argc]": [argc] "=r" (-> isize));
11 const argv = asm("lea 0x8(%%rsp), %[argv]": [argv] "=r" (-> &&u8));
12 env = asm("lea 0x10(%%rsp,%%rdi,8), %[env]": [env] "=r" (-> &&u8));
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;
1236}
37*/
std/builtin.zig+4-4
......@@ -1,8 +1,8 @@
11// These functions are provided when not linking against libc because LLVM
22// sometimes generates code that calls them.
33
4export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
5 var index : #typeof(n) = 0;
4export fn memset(dest: &u8, c: u8, n: usize) &u8 => {
5 var index : @typeof(n) = 0;
66 while (index != n) {
77 dest[index] = c;
88 index += 1;
......@@ -10,8 +10,8 @@ export fn memset(dest: &u8, c: u8, n: usize) -> &u8 {
1010 return dest;
1111}
1212
13export fn memcpy(dest: &noalias u8, src: &const noalias u8, n: usize) -> &u8 {
14 var index : #typeof(n) = 0;
13export fn memcpy(noalias dest: &u8, noalias src: &const u8, n: usize) &u8 => {
14 var index : @typeof(n) = 0;
1515 while (index != n) {
1616 dest[index] = src[index];
1717 index += 1;
std/rand.zig+18-18
......@@ -4,13 +4,13 @@ const ARRAY_SIZE : u16 = 624;
44/// Use `rand_init` to initialize this state.
55pub struct Rand {
66 array: [ARRAY_SIZE]u32,
7 index: #typeof(ARRAY_SIZE),
7 index: @typeof(ARRAY_SIZE),
88
99 /// Initialize random state with the given seed.
10 pub fn init(r: &Rand, seed: u32) {
10 pub fn init(r: &Rand, seed: u32) => {
1111 r.index = 0;
1212 r.array[0] = seed;
13 var i : #typeof(ARRAY_SIZE) = 1;
13 var i : @typeof(ARRAY_SIZE) = 1;
1414 while (i < ARRAY_SIZE) {
1515 const prev_value : u64 = r.array[i - 1];
1616 r.array[i] = ((prev_value ^ (prev_value << 30)) * 0x6c078965 + i) as u32;
......@@ -20,7 +20,7 @@ pub struct Rand {
2020
2121
2222 /// Get 32 bits of randomness.
23 pub fn get_u32(r: &Rand) -> u32 {
23 pub fn get_u32(r: &Rand) u32 => {
2424 if (r.index == 0) {
2525 r.generate_numbers();
2626 }
......@@ -37,13 +37,13 @@ pub struct Rand {
3737 }
3838
3939 /// Fill `buf` with randomness.
40 pub fn get_bytes(r: &Rand, buf: []u8) {
40 pub fn get_bytes(r: &Rand, buf: []u8) => {
4141 var bytes_left = r.get_bytes_aligned(buf);
4242 if (bytes_left > 0) {
43 var rand_val_array : [#sizeof(u32)]u8;
44 *(rand_val_array.ptr as &u32) = r.get_u32();
43 var rand_val_array : [@sizeof(u32)]u8;
44 *(rand_val_array.ptr as (&u32)) = r.get_u32();
4545 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];
4747 bytes_left -= 1;
4848 }
4949 }
......@@ -51,23 +51,23 @@ pub struct Rand {
5151
5252 /// Get a random unsigned integer with even distribution between `start`
5353 /// 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 => {
5555 const range = end - start;
56 const leftover = #max_value(u64) % range;
57 const upper_bound = #max_value(u64) - leftover;
58 var rand_val_array : [#sizeof(u64)]u8;
56 const leftover = @max_value(u64) % range;
57 const upper_bound = @max_value(u64) - leftover;
58 var rand_val_array : [@sizeof(u64)]u8;
5959
6060 while (true) {
6161 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));
6363 if (rand_val < upper_bound) {
6464 return start + (rand_val % range);
6565 }
6666 }
6767 }
6868
69 fn generate_numbers(r: &Rand) {
70 var i : #typeof(ARRAY_SIZE) = 0;
69 fn generate_numbers(r: &Rand) => {
70 var i : @typeof(ARRAY_SIZE) = 0;
7171 while (i < ARRAY_SIZE) {
7272 const y : u32 = (r.array[i] & 0x80000000) + (r.array[(i + 1) % ARRAY_SIZE] & 0x7fffffff);
7373 const untempered : u32 = r.array[(i + 397) % ARRAY_SIZE] ^ (y >> 1);
......@@ -82,11 +82,11 @@ pub struct Rand {
8282 }
8383
8484 // 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 => {
8686 var bytes_left = buf.len;
8787 while (bytes_left >= 4) {
88 *(&buf[buf.len - bytes_left] as &u32) = r.get_u32();
89 bytes_left -= #sizeof(u32);
88 *(&buf[buf.len - bytes_left] as (&u32)) = r.get_u32();
89 bytes_left -= @sizeof(u32);
9090 }
9191 return bytes_left;
9292 }
std/std.zig+12-12
......@@ -5,25 +5,25 @@ pub const stdout_fileno : isize = 1;
55pub const stderr_fileno : isize = 2;
66
77// 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 => {
99 getrandom(buf, count, 0)
1010}
1111
1212// TODO error handling
1313// TODO handle buffering and flushing (mutex protected)
14pub fn print_str(str: []const u8) -> isize {
14pub fn print_str(str: []const u8) isize => {
1515 fprint_str(stdout_fileno, str)
1616}
1717
1818// TODO error handling
1919// 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 => {
2121 write(fd, str.ptr, str.len)
2222}
2323
2424// TODO handle buffering and flushing (mutex protected)
2525// TODO error handling
26pub fn print_u64(x: u64) -> isize {
26pub fn print_u64(x: u64) isize => {
2727 var buf: [max_u64_base10_digits]u8;
2828 const len = buf_print_u64(buf, x);
2929 return write(stdout_fileno, buf.ptr, len);
......@@ -31,14 +31,14 @@ pub fn print_u64(x: u64) -> isize {
3131
3232// TODO handle buffering and flushing (mutex protected)
3333// TODO error handling
34pub fn print_i64(x: i64) -> isize {
34pub fn print_i64(x: i64) isize => {
3535 var buf: [max_u64_base10_digits]u8;
3636 const len = buf_print_i64(buf, x);
3737 return write(stdout_fileno, buf.ptr, len);
3838}
3939
4040// TODO error handling
41pub fn readline(buf: []u8, out_len: &usize) -> bool {
41pub fn readline(buf: []u8, out_len: &usize) bool => {
4242 const amt_read = read(stdin_fileno, buf.ptr, buf.len);
4343 if (amt_read < 0) {
4444 return true;
......@@ -48,10 +48,10 @@ pub fn readline(buf: []u8, out_len: &usize) -> bool {
4848}
4949
5050// 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 => {
5252 var x : u64 = 0;
5353
54 var i : #typeof(buf.len) = 0;
54 var i : @typeof(buf.len) = 0;
5555 while (i < buf.len) {
5656 const c = buf[i];
5757 const digit = char_to_digit(c);
......@@ -77,7 +77,7 @@ pub fn parse_u64(buf: []u8, radix: u8, result: &u64) -> bool {
7777 return false;
7878}
7979
80fn char_to_digit(c: u8) -> u8 {
80fn char_to_digit(c: u8) u8 => {
8181 if ('0' <= c && c <= '9') {
8282 c - '0'
8383 } else if ('A' <= c && c <= 'Z') {
......@@ -85,13 +85,13 @@ fn char_to_digit(c: u8) -> u8 {
8585 } else if ('a' <= c && c <= 'z') {
8686 c - 'a' + 10
8787 } else {
88 #max_value(u8)
88 @max_value(u8)
8989 }
9090}
9191
9292const 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 => {
9595 if (x < 0) {
9696 out_buf[0] = '-';
9797 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 {
100100 }
101101}
102102
103fn buf_print_u64(out_buf: []u8, x: u64) -> usize {
103fn buf_print_u64(out_buf: []u8, x: u64) usize => {
104104 var buf: [max_u64_base10_digits]u8;
105105 var a = x;
106106 var index = buf.len;
std/syscall.zig+7-7
......@@ -3,34 +3,34 @@ const SYS_write : usize = 1;
33const SYS_exit : usize = 60;
44const SYS_getrandom : usize = 318;
55
6fn syscall1(number: usize, arg1: usize) -> usize {
6fn syscall1(number: usize, arg1: usize) usize => {
77 asm volatile ("syscall"
88 : [ret] "={rax}" (-> usize)
99 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1)
1010 : "rcx", "r11")
1111}
1212
13fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) -> usize {
13fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize => {
1414 asm volatile ("syscall"
1515 : [ret] "={rax}" (-> usize)
1616 : [number] "{rax}" (number), [arg1] "{rdi}" (arg1), [arg2] "{rsi}" (arg2), [arg3] "{rdx}" (arg3)
1717 : "rcx", "r11")
1818}
1919
20pub fn read(fd: isize, buf: &u8, count: usize) -> isize {
20pub fn read(fd: isize, buf: &u8, count: usize) isize => {
2121 syscall3(SYS_read, fd as usize, buf as usize, count) as isize
2222}
2323
24pub fn write(fd: isize, buf: &const u8, count: usize) -> isize {
24pub fn write(fd: isize, buf: &const u8, count: usize) isize => {
2525 syscall3(SYS_write, fd as usize, buf as usize, count) as isize
2626}
2727
28pub fn exit(status: i32) -> unreachable {
28pub fn exit(status: i32) unreachable => {
2929 syscall1(SYS_exit, status as usize);
30 unreachable
30 unreachable{}
3131}
3232
33pub fn getrandom(buf: &u8, count: usize, flags: u32) -> isize {
33pub fn getrandom(buf: &u8, count: usize, flags: u32) isize => {
3434 syscall3(SYS_getrandom, buf as usize, count, flags as usize) as isize
3535}
3636
test/run_tests.cpp+209-209
......@@ -96,50 +96,50 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
9696
9797static void add_compiling_test_cases(void) {
9898 add_simple_case("hello world with libc", R"SOURCE(
99 #link("c")
100 extern {
101 fn puts(s: &const u8) -> i32;
102 }
99#link("c")
100extern {
101 fn puts(s: &const u8) i32;
102}
103103
104 export fn main(argc: i32, argv: &&u8, env: &&u8) -> i32 {
105 puts(c"Hello, world!");
106 return 0;
107 }
104export fn main(argc: i32, argv: &&u8, env: &&u8) i32 => {
105 puts(c"Hello, world!");
106 return 0;
107}
108108 )SOURCE", "Hello, world!\n");
109109
110110 add_simple_case("function call", R"SOURCE(
111 use "std.zig";
112 use "syscall.zig";
111use "std.zig";
112use "syscall.zig";
113113
114 fn empty_function_1() {}
115 fn empty_function_2() { return; }
114fn empty_function_1() => {}
115fn empty_function_2() => { return; }
116116
117 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
118 empty_function_1();
119 empty_function_2();
120 this_is_a_function();
121 }
117pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
118 empty_function_1();
119 empty_function_2();
120 this_is_a_function();
121}
122122
123 fn this_is_a_function() -> unreachable {
124 print_str("OK\n");
125 exit(0);
126 }
123fn this_is_a_function() unreachable => {
124 print_str("OK\n");
125 exit(0);
126}
127127 )SOURCE", "OK\n");
128128
129129 add_simple_case("comments", R"SOURCE(
130 use "std.zig";
131
132 /**
133 * multi line doc comment
134 */
135 fn another_function() {}
136
137 /// this is a documentation comment
138 /// doc comment line 2
139 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
140 print_str(/* mid-line comment /* nested */ */ "OK\n");
141 return 0;
142 }
130use "std.zig";
131
132/**
133 * multi line doc comment
134 */
135fn another_function() => {}
136
137/// this is a documentation comment
138/// doc comment line 2
139pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
140 print_str(/* mid-line comment /* nested */ */ "OK\n");
141 return 0;
142}
143143 )SOURCE", "OK\n");
144144
145145 {
......@@ -147,13 +147,13 @@ static void add_compiling_test_cases(void) {
147147use "std.zig";
148148use "foo.zig";
149149
150pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
150pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
151151 private_function();
152152 print_str("OK 2\n");
153153 return 0;
154154}
155155
156fn private_function() {
156fn private_function() => {
157157 print_text();
158158}
159159 )SOURCE", "OK 1\nOK 2\n");
......@@ -163,11 +163,11 @@ use "std.zig";
163163
164164// purposefully conflicting function with main.zig
165165// but it's private so it should be OK
166fn private_function() {
166fn private_function() => {
167167 print_str("OK 1\n");
168168}
169169
170pub fn print_text() {
170pub fn print_text() => {
171171 private_function();
172172}
173173 )SOURCE");
......@@ -178,7 +178,7 @@ pub fn print_text() {
178178use "foo.zig";
179179use "bar.zig";
180180
181pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
181pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
182182 foo_function();
183183 bar_function();
184184 return 0;
......@@ -187,7 +187,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
187187
188188 add_source_file(tc, "foo.zig", R"SOURCE(
189189use "std.zig";
190pub fn foo_function() {
190pub fn foo_function() => {
191191 print_str("OK\n");
192192}
193193 )SOURCE");
......@@ -196,7 +196,7 @@ pub fn foo_function() {
196196use "other.zig";
197197use "std.zig";
198198
199pub fn bar_function() {
199pub fn bar_function() => {
200200 if (foo_function()) {
201201 print_str("OK\n");
202202 }
......@@ -204,7 +204,7 @@ pub fn bar_function() {
204204 )SOURCE");
205205
206206 add_source_file(tc, "other.zig", R"SOURCE(
207pub fn foo_function() -> bool {
207pub fn foo_function() bool => {
208208 // this one conflicts with the one from foo
209209 return true;
210210}
......@@ -212,65 +212,65 @@ pub fn foo_function() -> bool {
212212 }
213213
214214 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 {
218 if (1 != 0) {
219 print_str("1 is true\n");
220 } else {
221 print_str("1 is false\n");
222 }
223 if (0 != 0) {
224 print_str("0 is true\n");
225 } else if (1 - 1 != 0) {
226 print_str("1 - 1 is true\n");
227 }
228 if (!(0 != 0)) {
229 print_str("!0 is true\n");
230 }
231 return 0;
232 }
217pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
218 if (1 != 0) {
219 print_str("1 is true\n");
220 } else {
221 print_str("1 is false\n");
222 }
223 if (0 != 0) {
224 print_str("0 is true\n");
225 } else if (1 - 1 != 0) {
226 print_str("1 - 1 is true\n");
227 }
228 if (!(0 != 0)) {
229 print_str("!0 is true\n");
230 }
231 return 0;
232}
233233 )SOURCE", "1 is true\n!0 is true\n");
234234
235235 add_simple_case("params", R"SOURCE(
236 use "std.zig";
236use "std.zig";
237237
238 fn add(a: i32, b: i32) -> i32 {
239 a + b
240 }
238fn add(a: i32, b: i32) i32 => {
239 a + b
240}
241241
242 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
243 if (add(22, 11) == 33) {
244 print_str("pass\n");
245 }
246 return 0;
247 }
242pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
243 if (add(22, 11) == 33) {
244 print_str("pass\n");
245 }
246 return 0;
247}
248248 )SOURCE", "pass\n");
249249
250250 add_simple_case("goto", R"SOURCE(
251 use "std.zig";
251use "std.zig";
252252
253 fn loop(a : i32) {
254 if (a == 0) {
255 goto done;
256 }
257 print_str("loop\n");
258 loop(a - 1);
253fn loop(a : i32) => {
254 if (a == 0) {
255 goto done;
256 }
257 print_str("loop\n");
258 loop(a - 1);
259259
260 done:
261 return;
262 }
260done:
261 return;
262}
263263
264 pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
265 loop(3);
266 return 0;
267 }
264pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
265 loop(3);
266 return 0;
267}
268268 )SOURCE", "loop\nloop\nloop\n");
269269
270270 add_simple_case("local variables", R"SOURCE(
271271use "std.zig";
272272
273pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
273pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
274274 const a : i32 = 1;
275275 const b = 2 as i32;
276276 if (a + b == 3) {
......@@ -283,7 +283,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
283283 add_simple_case("bool literals", R"SOURCE(
284284use "std.zig";
285285
286pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
286pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
287287 if (true) { print_str("OK 1\n"); }
288288 if (false) { print_str("BAD 1\n"); }
289289 if (!true) { print_str("BAD 2\n"); }
......@@ -295,7 +295,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
295295 add_simple_case("separate block scopes", R"SOURCE(
296296use "std.zig";
297297
298pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
298pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
299299 if (true) {
300300 const no_conflict : i32 = 5;
301301 if (no_conflict == 5) { print_str("OK 1\n"); }
......@@ -313,12 +313,12 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
313313 add_simple_case("void parameters", R"SOURCE(
314314use "std.zig";
315315
316pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
317 void_fun(1, void, 2);
316pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
317 void_fun(1, void{}, 2);
318318 return 0;
319319}
320320
321fn void_fun(a : i32, b : void, c : i32) {
321fn void_fun(a : i32, b : void, c : i32) => {
322322 const v = b;
323323 const vv : void = if (a == 1) {v} else {};
324324 if (a + c == 3) { print_str("OK\n"); }
......@@ -333,16 +333,16 @@ struct Foo {
333333 b : i32,
334334 c : void,
335335}
336pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
336pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
337337 const foo = Foo {
338 .a = void,
338 .a = void{},
339339 .b = 1,
340 .c = void,
340 .c = void{},
341341 };
342342 if (foo.b != 1) {
343343 print_str("BAD\n");
344344 }
345 if (#sizeof(Foo) != 4) {
345 if (@sizeof(Foo) != 4) {
346346 print_str("BAD\n");
347347 }
348348 print_str("OK\n");
......@@ -354,7 +354,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
354354 add_simple_case("mutable local variables", R"SOURCE(
355355use "std.zig";
356356
357pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
357pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
358358 var zero : i32 = 0;
359359 if (zero == 0) { print_str("zero\n"); }
360360
......@@ -374,7 +374,7 @@ done:
374374 add_simple_case("arrays", R"SOURCE(
375375use "std.zig";
376376
377pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
377pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
378378 var array : [5]u32;
379379
380380 var i : u32 = 0;
......@@ -401,7 +401,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
401401
402402 return 0;
403403}
404fn get_array_len(a: []u32) -> usize {
404fn get_array_len(a: []u32) usize => {
405405 a.len
406406}
407407 )SOURCE", "OK\n");
......@@ -410,7 +410,7 @@ fn get_array_len(a: []u32) -> usize {
410410 add_simple_case("hello world without libc", R"SOURCE(
411411use "std.zig";
412412
413pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
413pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
414414 print_str("Hello, world!\n");
415415 return 0;
416416}
......@@ -420,7 +420,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
420420 add_simple_case("a + b + c", R"SOURCE(
421421use "std.zig";
422422
423pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
423pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
424424 if (false || false || false) { print_str("BAD 1\n"); }
425425 if (true && true && false) { print_str("BAD 2\n"); }
426426 if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); }
......@@ -442,7 +442,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
442442 add_simple_case("short circuit", R"SOURCE(
443443use "std.zig";
444444
445pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
445pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
446446 if (true || { print_str("BAD 1\n"); false }) {
447447 print_str("OK 1\n");
448448 }
......@@ -465,7 +465,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
465465 add_simple_case("modify operators", R"SOURCE(
466466use "std.zig";
467467
468pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
468pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
469469 var i : i32 = 0;
470470 i += 5; if (i != 5) { print_str("BAD +=\n"); }
471471 i -= 2; if (i != 3) { print_str("BAD -=\n"); }
......@@ -488,10 +488,10 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
488488 add_simple_case("number literals", R"SOURCE(
489489#link("c")
490490extern {
491 fn printf(__format: &const u8, ...) -> i32;
491 fn printf(__format: &const u8, ...) i32;
492492}
493493
494export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
494export fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
495495 printf(c"\n");
496496
497497 printf(c"0: %llu\n",
......@@ -617,9 +617,9 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
617617 add_simple_case("structs", R"SOURCE(
618618use "std.zig";
619619
620pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
620pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
621621 var foo : Foo;
622 @memset(&foo, 0, #sizeof(Foo));
622 @memset(&foo, 0, @sizeof(Foo));
623623 foo.a += 1;
624624 foo.b = foo.a == 1;
625625 test_foo(foo);
......@@ -638,12 +638,12 @@ struct Foo {
638638 b : bool,
639639 c : f32,
640640}
641fn test_foo(foo : Foo) {
641fn test_foo(foo : Foo) => {
642642 if (!foo.b) {
643643 print_str("BAD\n");
644644 }
645645}
646fn test_mutation(foo : &Foo) {
646fn test_mutation(foo : &Foo) => {
647647 foo.c = 100;
648648}
649649struct Node {
......@@ -654,7 +654,7 @@ struct Node {
654654struct Val {
655655 x: i32,
656656}
657fn test_point_to_self() {
657fn test_point_to_self() => {
658658 var root : Node;
659659 root.val.x = 1;
660660
......@@ -668,7 +668,7 @@ fn test_point_to_self() {
668668 print_str("BAD\n");
669669 }
670670}
671fn test_byval_assign() {
671fn test_byval_assign() => {
672672 var foo1 : Foo;
673673 var foo2 : Foo;
674674
......@@ -680,7 +680,7 @@ fn test_byval_assign() {
680680
681681 if (foo2.a != 1234) { print_str("BAD - byval assignment failed\n"); }
682682}
683fn test_initializer() {
683fn test_initializer() => {
684684 const val = Val { .x = 42 };
685685 if (val.x != 42) { print_str("BAD\n"); }
686686}
......@@ -692,7 +692,7 @@ use "std.zig";
692692const g1 : i32 = 1233 + 1;
693693var g2 : i32 = 0;
694694
695pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
695pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
696696 if (g2 != 0) { print_str("BAD\n"); }
697697 g2 = g1;
698698 if (g2 != 1234) { print_str("BAD\n"); }
......@@ -703,7 +703,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
703703
704704 add_simple_case("while loop", R"SOURCE(
705705use "std.zig";
706pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
706pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
707707 var i : i32 = 0;
708708 while (i < 4) {
709709 print_str("loop\n");
......@@ -711,7 +711,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
711711 }
712712 return f();
713713}
714fn f() -> i32 {
714fn f() i32 => {
715715 while (true) {
716716 return 0;
717717 }
......@@ -720,7 +720,7 @@ fn f() -> i32 {
720720
721721 add_simple_case("continue and break", R"SOURCE(
722722use "std.zig";
723pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
723pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
724724 var i : i32 = 0;
725725 while (true) {
726726 print_str("loop\n");
......@@ -736,7 +736,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
736736
737737 add_simple_case("maybe type", R"SOURCE(
738738use "std.zig";
739pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
739pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
740740 const x : ?bool = true;
741741
742742 if (const y ?= x) {
......@@ -759,7 +759,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
759759
760760 const final_x : ?i32 = 13;
761761
762 const num = final_x ?? unreachable;
762 const num = final_x ?? unreachable{};
763763
764764 if (num != 13) {
765765 print_str("BAD\n");
......@@ -771,26 +771,26 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
771771
772772 add_simple_case("implicit cast after unreachable", R"SOURCE(
773773use "std.zig";
774pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
774pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
775775 const x = outer();
776776 if (x == 1234) {
777777 print_str("OK\n");
778778 }
779779 return 0;
780780}
781fn inner() -> i32 { 1234 }
782fn outer() -> isize {
781fn inner() i32 => { 1234 }
782fn outer() isize => {
783783 return inner();
784784}
785785 )SOURCE", "OK\n");
786786
787 add_simple_case("#sizeof() and #typeof()", R"SOURCE(
787 add_simple_case("@sizeof() and @typeof()", R"SOURCE(
788788use "std.zig";
789789const x: u16 = 13;
790const z: #typeof(x) = 19;
791pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
792 const y: #typeof(x) = 120;
793 print_u64(#sizeof(#typeof(y)));
790const z: @typeof(x) = 19;
791pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
792 const y: @typeof(x) = 120;
793 print_u64(@sizeof(@typeof(y)));
794794 print_str("\n");
795795 return 0;
796796}
......@@ -800,11 +800,11 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
800800use "std.zig";
801801struct Rand {
802802 seed: u32,
803 pub fn get_seed(r: Rand) -> u32 {
803 pub fn get_seed(r: Rand) u32 => {
804804 r.seed
805805 }
806806}
807pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
807pub fn main(argc : isize, argv : &&u8, env : &&u8) i32 => {
808808 const r = Rand {.seed = 1234};
809809 if (r.get_seed() != 1234) {
810810 print_str("BAD seed\n");
......@@ -817,7 +817,7 @@ pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 {
817817 add_simple_case("pointer dereferencing", R"SOURCE(
818818use "std.zig";
819819
820pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
820pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
821821 var x = 3 as i32;
822822 const y = &x;
823823
......@@ -839,9 +839,9 @@ use "std.zig";
839839
840840const 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 => {
843843 var array : [ARRAY_SIZE]u8;
844 print_u64(#sizeof(#typeof(array)));
844 print_u64(@sizeof(@typeof(array)));
845845 print_str("\n");
846846 return 0;
847847}
......@@ -849,69 +849,69 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
849849
850850 add_simple_case("#min_value() and #max_value()", R"SOURCE(
851851use "std.zig";
852pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
852pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
853853 print_str("max u8: ");
854 print_u64(#max_value(u8));
854 print_u64(@max_value(u8));
855855 print_str("\n");
856856
857857 print_str("max u16: ");
858 print_u64(#max_value(u16));
858 print_u64(@max_value(u16));
859859 print_str("\n");
860860
861861 print_str("max u32: ");
862 print_u64(#max_value(u32));
862 print_u64(@max_value(u32));
863863 print_str("\n");
864864
865865 print_str("max u64: ");
866 print_u64(#max_value(u64));
866 print_u64(@max_value(u64));
867867 print_str("\n");
868868
869869 print_str("max i8: ");
870 print_i64(#max_value(i8));
870 print_i64(@max_value(i8));
871871 print_str("\n");
872872
873873 print_str("max i16: ");
874 print_i64(#max_value(i16));
874 print_i64(@max_value(i16));
875875 print_str("\n");
876876
877877 print_str("max i32: ");
878 print_i64(#max_value(i32));
878 print_i64(@max_value(i32));
879879 print_str("\n");
880880
881881 print_str("max i64: ");
882 print_i64(#max_value(i64));
882 print_i64(@max_value(i64));
883883 print_str("\n");
884884
885885 print_str("min u8: ");
886 print_u64(#min_value(u8));
886 print_u64(@min_value(u8));
887887 print_str("\n");
888888
889889 print_str("min u16: ");
890 print_u64(#min_value(u16));
890 print_u64(@min_value(u16));
891891 print_str("\n");
892892
893893 print_str("min u32: ");
894 print_u64(#min_value(u32));
894 print_u64(@min_value(u32));
895895 print_str("\n");
896896
897897 print_str("min u64: ");
898 print_u64(#min_value(u64));
898 print_u64(@min_value(u64));
899899 print_str("\n");
900900
901901 print_str("min i8: ");
902 print_i64(#min_value(i8));
902 print_i64(@min_value(i8));
903903 print_str("\n");
904904
905905 print_str("min i16: ");
906 print_i64(#min_value(i16));
906 print_i64(@min_value(i16));
907907 print_str("\n");
908908
909909 print_str("min i32: ");
910 print_i64(#min_value(i32));
910 print_i64(@min_value(i32));
911911 print_str("\n");
912912
913913 print_str("min i64: ");
914 print_i64(#min_value(i64));
914 print_i64(@min_value(i64));
915915 print_str("\n");
916916
917917 return 0;
......@@ -937,7 +937,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
937937
938938 add_simple_case("slicing", R"SOURCE(
939939use "std.zig";
940pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
940pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
941941 var array : [20]i32;
942942
943943 array[5] = 1234;
......@@ -965,13 +965,13 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
965965
966966 add_simple_case("else if expression", R"SOURCE(
967967use "std.zig";
968pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
968pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
969969 if (f(1) == 1) {
970970 print_str("OK\n");
971971 }
972972 return 0;
973973}
974fn f(c: u8) -> u8 {
974fn f(c: u8) u8 => {
975975 if (c == 0) {
976976 0
977977 } else if (c == 1) {
......@@ -984,7 +984,7 @@ fn f(c: u8) -> u8 {
984984
985985 add_simple_case("overflow intrinsics", R"SOURCE(
986986use "std.zig";
987pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
987pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
988988 var result: u8;
989989 if (!@add_with_overflow_u8(250, 100, &result)) {
990990 print_str("BAD\n");
......@@ -1002,7 +1002,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10021002
10031003 add_simple_case("memcpy and memset intrinsics", R"SOURCE(
10041004use "std.zig";
1005pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
1005pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
10061006 var foo : [20]u8;
10071007 var bar : [20]u8;
10081008
......@@ -1020,13 +1020,13 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10201020
10211021 add_simple_case("order-independent declarations", R"SOURCE(
10221022use "std.zig";
1023const z : #typeof(stdin_fileno) = 0;
1024const x : #typeof(y) = 1234;
1023const z : @typeof(stdin_fileno) = 0;
1024const x : @typeof(y) = 1234;
10251025const y : u16 = 5678;
1026pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
1026pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
10271027 print_ok(x)
10281028}
1029fn print_ok(val: #typeof(x)) -> #typeof(foo) {
1029fn print_ok(val: @typeof(x)) @typeof(foo) => {
10301030 print_str("OK\n");
10311031 return 0;
10321032}
......@@ -1054,7 +1054,7 @@ enum Bar {
10541054 D,
10551055}
10561056
1057pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
1057pub fn main(argc: isize, argv: &&u8, env: &&u8) i32 => {
10581058 const foo1 = Foo.One(13);
10591059 const foo2 = Foo.Two(Point { .x = 1234, .y = 5678, });
10601060 const bar = Bar.B;
......@@ -1063,18 +1063,18 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10631063 print_str("BAD\n");
10641064 }
10651065
1066 if (#value_count(Foo) != 3) {
1066 if (@value_count(Foo) != 3) {
10671067 print_str("BAD\n");
10681068 }
10691069
1070 if (#value_count(Bar) != 4) {
1070 if (@value_count(Bar) != 4) {
10711071 print_str("BAD\n");
10721072 }
10731073
1074 if (#sizeof(Foo) != 17) {
1074 if (@sizeof(Foo) != 17) {
10751075 print_str("BAD\n");
10761076 }
1077 if (#sizeof(Bar) != 1) {
1077 if (@sizeof(Bar) != 1) {
10781078 print_str("BAD\n");
10791079 }
10801080
......@@ -1090,8 +1090,8 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
10901090
10911091static void add_compile_failure_test_cases(void) {
10921092 add_compile_fail_case("multiple function definitions", R"SOURCE(
1093fn a() {}
1094fn a() {}
1093fn a() => {}
1094fn a() => {}
10951095 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
10961096
10971097 add_compile_fail_case("bad directive", R"SOURCE(
......@@ -1100,46 +1100,46 @@ extern {
11001100 fn b();
11011101}
11021102#bogus2("")
1103fn a() {}
1103fn a() => {}
11041104 )SOURCE", 2, ".tmp_source.zig:2:1: error: invalid directive: 'bogus1'",
11051105 ".tmp_source.zig:6:1: error: invalid directive: 'bogus2'");
11061106
11071107 add_compile_fail_case("unreachable with return", R"SOURCE(
1108fn a() -> unreachable {return;}
1108fn a() unreachable => {return;}
11091109 )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', got 'void'");
11101110
11111111 add_compile_fail_case("control reaches end of non-void function", R"SOURCE(
1112fn a() -> i32 {}
1112fn a() i32 => {}
11131113 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got 'void'");
11141114
11151115 add_compile_fail_case("undefined function call", R"SOURCE(
1116fn a() {
1116fn a() => {
11171117 b();
11181118}
11191119 )SOURCE", 1, ".tmp_source.zig:3:5: error: undefined function: 'b'");
11201120
11211121 add_compile_fail_case("wrong number of arguments", R"SOURCE(
1122fn a() {
1122fn a() => {
11231123 b(1);
11241124}
1125fn b(a: i32, b: i32, c: i32) { }
1125fn b(a: i32, b: i32, c: i32) => { }
11261126 )SOURCE", 1, ".tmp_source.zig:3:6: error: expected 3 arguments, got 1");
11271127
11281128 add_compile_fail_case("invalid type", R"SOURCE(
1129fn a() -> bogus {}
1130 )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid type name: 'bogus'");
1129fn a() bogus => {}
1130 )SOURCE", 1, ".tmp_source.zig:2:8: error: use of undeclared identifier 'bogus'");
11311131
11321132 add_compile_fail_case("pointer to unreachable", R"SOURCE(
1133fn a() -> &unreachable {}
1134 )SOURCE", 1, ".tmp_source.zig:2:11: error: pointer to unreachable not allowed");
1133fn a() &unreachable => {}
1134 )SOURCE", 1, ".tmp_source.zig:2:8: error: pointer to unreachable not allowed");
11351135
11361136 add_compile_fail_case("unreachable code", R"SOURCE(
1137fn a() {
1137fn a() => {
11381138 return;
11391139 b();
11401140}
11411141
1142fn b() {}
1142fn b() => {}
11431143 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
11441144
11451145 add_compile_fail_case("bad version string", R"SOURCE(
......@@ -1152,7 +1152,7 @@ use "bogus-does-not-exist.zig";
11521152 )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");
11531153
11541154 add_compile_fail_case("undeclared identifier", R"SOURCE(
1155fn a() {
1155fn a() => {
11561156 b +
11571157 c
11581158}
......@@ -1161,99 +1161,99 @@ fn a() {
11611161 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'");
11621162
11631163 add_compile_fail_case("goto cause unreachable code", R"SOURCE(
1164fn a() {
1164fn a() => {
11651165 goto done;
11661166 b();
11671167done:
11681168 return;
11691169}
1170fn b() {}
1170fn b() => {}
11711171 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
11721172
11731173 add_compile_fail_case("parameter redeclaration", R"SOURCE(
1174fn f(a : i32, a : i32) {
1174fn f(a : i32, a : i32) => {
11751175}
11761176 )SOURCE", 1, ".tmp_source.zig:2:1: error: redeclaration of parameter 'a'");
11771177
11781178 add_compile_fail_case("local variable redeclaration", R"SOURCE(
1179fn f() {
1179fn f() => {
11801180 const a : i32 = 0;
11811181 const a = 0;
11821182}
11831183 )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'");
11841184
11851185 add_compile_fail_case("local variable redeclares parameter", R"SOURCE(
1186fn f(a : i32) {
1186fn f(a : i32) => {
11871187 const a = 0;
11881188}
11891189 )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'");
11901190
11911191 add_compile_fail_case("variable has wrong type", R"SOURCE(
1192fn f() -> i32 {
1192fn f() i32 => {
11931193 const a = c"a";
11941194 a
11951195}
11961196 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', got '&const u8'");
11971197
11981198 add_compile_fail_case("if condition is bool, not int", R"SOURCE(
1199fn f() {
1199fn f() => {
12001200 if (0) {}
12011201}
12021202 )SOURCE", 1, ".tmp_source.zig:3:9: error: expected type 'bool', got '(u8 literal)'");
12031203
12041204 add_compile_fail_case("assign unreachable", R"SOURCE(
1205fn f() {
1205fn f() => {
12061206 const a = return;
12071207}
12081208 )SOURCE", 1, ".tmp_source.zig:3:5: error: variable initialization is unreachable");
12091209
12101210 add_compile_fail_case("unreachable variable", R"SOURCE(
1211fn f() {
1211fn f() => {
12121212 const a : unreachable = return;
12131213}
12141214 )SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");
12151215
12161216 add_compile_fail_case("unreachable parameter", R"SOURCE(
1217fn f(a : unreachable) {}
1217fn f(a : unreachable) => {}
12181218 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
12191219
12201220 add_compile_fail_case("exporting a void parameter", R"SOURCE(
1221export fn f(a : void) {}
1221export fn f(a : void) => {}
12221222 )SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions");
12231223
12241224 add_compile_fail_case("unused label", R"SOURCE(
1225fn f() {
1225fn f() => {
12261226a_label:
12271227}
12281228 )SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used");
12291229
12301230 add_compile_fail_case("bad assignment target", R"SOURCE(
1231fn f() {
1231fn f() => {
12321232 3 = 3;
12331233}
12341234 )SOURCE", 1, ".tmp_source.zig:3:5: error: invalid assignment target");
12351235
12361236 add_compile_fail_case("assign to constant variable", R"SOURCE(
1237fn f() {
1237fn f() => {
12381238 const a = 3;
12391239 a = 4;
12401240}
12411241 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");
12421242
12431243 add_compile_fail_case("use of undeclared identifier", R"SOURCE(
1244fn f() {
1244fn f() => {
12451245 b = 3;
12461246}
12471247 )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'");
12481248
12491249 add_compile_fail_case("const is a statement, not an expression", R"SOURCE(
1250fn f() {
1250fn f() => {
12511251 (const a = 0);
12521252}
12531253 )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'");
12541254
12551255 add_compile_fail_case("array access errors", R"SOURCE(
1256fn f() {
1256fn f() => {
12571257 var bad : bool;
12581258 i[i] = i[i];
12591259 bad[bad] = bad[bad];
......@@ -1268,19 +1268,19 @@ fn f() {
12681268 ".tmp_source.zig:5:20: error: expected type 'usize', got 'bool'");
12691269
12701270 add_compile_fail_case("variadic functions only allowed in extern", R"SOURCE(
1271fn f(...) {}
1271fn f(...) => {}
12721272 )SOURCE", 1, ".tmp_source.zig:2:1: error: variadic arguments only allowed in extern functions");
12731273
12741274 add_compile_fail_case("write to const global variable", R"SOURCE(
12751275const x : i32 = 99;
1276fn f() {
1276fn f() => {
12771277 x = 1;
12781278}
12791279 )SOURCE", 1, ".tmp_source.zig:4:5: error: cannot assign to constant");
12801280
12811281
12821282 add_compile_fail_case("missing else clause", R"SOURCE(
1283fn f() {
1283fn f() => {
12841284 const x : i32 = if (true) { 1 };
12851285 const y = if (true) { 1 as i32 };
12861286}
......@@ -1299,7 +1299,7 @@ struct C { a : A, }
12991299
13001300 add_compile_fail_case("invalid struct field", R"SOURCE(
13011301struct A { x : i32, }
1302fn f() {
1302fn f() => {
13031303 var a : A;
13041304 a.foo = 1;
13051305 const y = a.bar;
......@@ -1315,7 +1315,7 @@ struct A { y : i32, }
13151315
13161316 add_compile_fail_case("byvalue struct on exported functions", R"SOURCE(
13171317struct A { x : i32, }
1318export fn f(a : A) {}
1318export fn f(a : A) => {}
13191319 )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue struct parameters not yet supported on exported functions");
13201320
13211321 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE(
......@@ -1324,7 +1324,7 @@ struct A {
13241324 y : i32,
13251325 z : i32,
13261326}
1327fn f() {
1327fn f() => {
13281328 const a = A {
13291329 .z = 1,
13301330 .y = 2,
......@@ -1340,13 +1340,13 @@ struct A {
13401340 y : i32,
13411341 z : i32,
13421342}
1343fn f() {
1343fn f() => {
13441344 const a = A {
13451345 .z = 4,
13461346 .y = 2,
13471347 };
13481348}
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
13511351 add_compile_fail_case("invalid field in struct value expression", R"SOURCE(
13521352struct A {
......@@ -1354,7 +1354,7 @@ struct A {
13541354 y : i32,
13551355 z : i32,
13561356}
1357fn f() {
1357fn f() => {
13581358 const a = A {
13591359 .z = 4,
13601360 .y = 2,
......@@ -1364,37 +1364,37 @@ fn f() {
13641364 )SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'");
13651365
13661366 add_compile_fail_case("invalid break expression", R"SOURCE(
1367fn f() {
1367fn f() => {
13681368 break;
13691369}
13701370 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop");
13711371
13721372 add_compile_fail_case("invalid continue expression", R"SOURCE(
1373fn f() {
1373fn f() => {
13741374 continue;
13751375}
13761376 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop");
13771377
13781378 add_compile_fail_case("invalid maybe type", R"SOURCE(
1379fn f() {
1379fn f() => {
13801380 if (const x ?= true) { }
13811381}
13821382 )SOURCE", 1, ".tmp_source.zig:3:20: error: expected maybe type");
13831383
13841384 add_compile_fail_case("cast unreachable", R"SOURCE(
1385fn f() -> i32 {
1385fn f() i32 => {
13861386 (return 1) as i32
13871387}
13881388 )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(
1391fn f() -> #bogus(foo) {
1390 add_compile_fail_case("invalid builtin fn", R"SOURCE(
1391fn f() @bogus(foo) => {
13921392}
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
13951395 add_compile_fail_case("top level decl dependency loop", R"SOURCE(
1396const a : #typeof(b) = 0;
1397const b : #typeof(a) = 0;
1396const a : @typeof(b) = 0;
1397const b : @typeof(a) = 0;
13981398 )SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");
13991399}
14001400