| author | |
| committer | |
| log | fa6e3eec464227a2c20ca949e2fd12f3ab649960 |
| tree | 6ac09e0230a70cd9473f067fb6fe50f55c614594 |
| parent | b453345554cf7a48061e0cb43a6e8b45641cb4c3 |
8 files changed, 148 insertions(+), 29 deletions(-)
doc/langref.md+3-1| ... | ... | @@ -60,7 +60,9 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen) |
| 60 | 60 | |
| 61 | 61 | ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis) |
| 62 | 62 | |
| 63 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | |
| 63 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompileTimeFnCall | |
| 64 | ||
| 65 | CompileTimeFnCall : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) | |
| 64 | 66 | |
| 65 | 67 | PointerType : token(Ampersand) option(token(Const)) Type |
| 66 | 68 |
example/rand/main.zig+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | const ARRAY_SIZE : u16 = 624; |
| 3 | 3 | |
| 4 | 4 | /// Use `rand_init` to initialize this state. |
| 5 | pub struct Rand { | |
| 5 | struct Rand { | |
| 6 | 6 | array: [u32; ARRAY_SIZE], |
| 7 | 7 | index: #typeof(ARRAY_SIZE), |
| 8 | 8 |
src/analyze.cpp+34-14| ... | ... | @@ -59,6 +59,7 @@ static AstNode *first_executing_node(AstNode *node) { |
| 59 | 59 | case NodeTypeStructValueExpr: |
| 60 | 60 | case NodeTypeStructValueField: |
| 61 | 61 | case NodeTypeWhileExpr: |
| 62 | case NodeTypeCompilerFnCall: | |
| 62 | 63 | return node; |
| 63 | 64 | } |
| 64 | 65 | zig_panic("unreachable"); |
| ... | ... | @@ -208,7 +209,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui |
| 208 | 209 | } |
| 209 | 210 | } |
| 210 | 211 | |
| 211 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | |
| 212 | static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node, ImportTableEntry *import, BlockContext *context) { | |
| 212 | 213 | assert(node->type == NodeTypeType); |
| 213 | 214 | alloc_codegen_node(node); |
| 214 | 215 | TypeNode *type_node = &node->codegen_node->data.type_node; |
| ... | ... | @@ -228,7 +229,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 228 | 229 | } |
| 229 | 230 | case AstNodeTypeTypePointer: |
| 230 | 231 | { |
| 231 | resolve_type(g, node->data.type.child_type); | |
| 232 | resolve_type(g, node->data.type.child_type, import, context); | |
| 232 | 233 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 233 | 234 | assert(child_type); |
| 234 | 235 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| ... | ... | @@ -242,7 +243,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 242 | 243 | } |
| 243 | 244 | case AstNodeTypeTypeArray: |
| 244 | 245 | { |
| 245 | resolve_type(g, node->data.type.child_type); | |
| 246 | resolve_type(g, node->data.type.child_type, import, context); | |
| 246 | 247 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 247 | 248 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 248 | 249 | add_node_error(g, node, |
| ... | ... | @@ -263,7 +264,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 263 | 264 | } |
| 264 | 265 | case AstNodeTypeTypeMaybe: |
| 265 | 266 | { |
| 266 | resolve_type(g, node->data.type.child_type); | |
| 267 | resolve_type(g, node->data.type.child_type, import, context); | |
| 267 | 268 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 268 | 269 | assert(child_type); |
| 269 | 270 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| ... | ... | @@ -275,11 +276,26 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 275 | 276 | type_node->entry = get_maybe_type(g, child_type); |
| 276 | 277 | return type_node->entry; |
| 277 | 278 | } |
| 279 | case AstNodeTypeTypeCompilerExpr: | |
| 280 | { | |
| 281 | AstNode *compiler_expr_node = node->data.type.compiler_expr; | |
| 282 | Buf *fn_name = &compiler_expr_node->data.compiler_fn_call.name; | |
| 283 | if (buf_eql_str(fn_name, "typeof")) { | |
| 284 | return analyze_expression(g, import, context, nullptr, | |
| 285 | compiler_expr_node->data.compiler_fn_call.expr); | |
| 286 | } else { | |
| 287 | add_node_error(g, node, | |
| 288 | buf_sprintf("invalid compiler function: '%s'", buf_ptr(fn_name))); | |
| 289 | return g->builtin_types.entry_invalid; | |
| 290 | } | |
| 291 | } | |
| 278 | 292 | } |
| 279 | 293 | zig_unreachable(); |
| 280 | 294 | } |
| 281 | 295 | |
| 282 | static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { | |
| 296 | static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry, | |
| 297 | ImportTableEntry *import) | |
| 298 | { | |
| 283 | 299 | assert(node->type == NodeTypeFnProto); |
| 284 | 300 | |
| 285 | 301 | for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) { |
| ... | ... | @@ -310,7 +326,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 310 | 326 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 311 | 327 | AstNode *child = node->data.fn_proto.params.at(i); |
| 312 | 328 | assert(child->type == NodeTypeParamDecl); |
| 313 | TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type); | |
| 329 | TypeTableEntry *type_entry = resolve_type(g, child->data.param_decl.type, import, import->block_context); | |
| 314 | 330 | if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 315 | 331 | add_node_error(g, child->data.param_decl.type, |
| 316 | 332 | buf_sprintf("parameter of type 'unreachable' not allowed")); |
| ... | ... | @@ -322,7 +338,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 322 | 338 | } |
| 323 | 339 | } |
| 324 | 340 | |
| 325 | resolve_type(g, node->data.fn_proto.return_type); | |
| 341 | resolve_type(g, node->data.fn_proto.return_type, import, import->block_context); | |
| 326 | 342 | } |
| 327 | 343 | |
| 328 | 344 | static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { |
| ... | ... | @@ -383,7 +399,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 383 | 399 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 384 | 400 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 385 | 401 | type_struct_field->name = &field_node->data.struct_field.name; |
| 386 | type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type); | |
| 402 | type_struct_field->type_entry = resolve_type(g, field_node->data.struct_field.type, import, import->block_context); | |
| 387 | 403 | |
| 388 | 404 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { |
| 389 | 405 | resolve_struct_type(g, import, type_struct_field->type_entry); |
| ... | ... | @@ -453,7 +469,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 453 | 469 | fn_table_entry->import_entry = import; |
| 454 | 470 | fn_table_entry->label_table.init(8); |
| 455 | 471 | |
| 456 | resolve_function_proto(g, fn_proto, fn_table_entry); | |
| 472 | resolve_function_proto(g, fn_proto, fn_table_entry, import); | |
| 457 | 473 | |
| 458 | 474 | Buf *name = &fn_proto->data.fn_proto.name; |
| 459 | 475 | g->fn_protos.append(fn_table_entry); |
| ... | ... | @@ -512,7 +528,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 512 | 528 | g->fn_table.put(proto_name, fn_table_entry); |
| 513 | 529 | } |
| 514 | 530 | |
| 515 | resolve_function_proto(g, proto_node, fn_table_entry); | |
| 531 | resolve_function_proto(g, proto_node, fn_table_entry, import); | |
| 516 | 532 | |
| 517 | 533 | |
| 518 | 534 | alloc_codegen_node(proto_node); |
| ... | ... | @@ -609,6 +625,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 609 | 625 | case NodeTypeStructField: |
| 610 | 626 | case NodeTypeStructValueExpr: |
| 611 | 627 | case NodeTypeStructValueField: |
| 628 | case NodeTypeCompilerFnCall: | |
| 612 | 629 | zig_unreachable(); |
| 613 | 630 | } |
| 614 | 631 | } |
| ... | ... | @@ -681,6 +698,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 681 | 698 | case NodeTypeStructField: |
| 682 | 699 | case NodeTypeStructValueExpr: |
| 683 | 700 | case NodeTypeStructValueField: |
| 701 | case NodeTypeCompilerFnCall: | |
| 684 | 702 | zig_unreachable(); |
| 685 | 703 | } |
| 686 | 704 | } |
| ... | ... | @@ -1132,7 +1150,7 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 1132 | 1150 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1133 | 1151 | TypeTableEntry *expected_type, AstNode *node) |
| 1134 | 1152 | { |
| 1135 | TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type); | |
| 1153 | TypeTableEntry *wanted_type = resolve_type(g, node->data.cast_expr.type, import, context); | |
| 1136 | 1154 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); |
| 1137 | 1155 | |
| 1138 | 1156 | if (wanted_type->id == TypeTableEntryIdInvalid || |
| ... | ... | @@ -1328,7 +1346,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 1328 | 1346 | { |
| 1329 | 1347 | TypeTableEntry *explicit_type = nullptr; |
| 1330 | 1348 | if (variable_declaration->type != nullptr) { |
| 1331 | explicit_type = resolve_type(g, variable_declaration->type); | |
| 1349 | explicit_type = resolve_type(g, variable_declaration->type, import, context); | |
| 1332 | 1350 | if (explicit_type->id == TypeTableEntryIdUnreachable) { |
| 1333 | 1351 | add_node_error(g, variable_declaration->type, |
| 1334 | 1352 | buf_sprintf("variable of type 'unreachable' not allowed")); |
| ... | ... | @@ -1428,7 +1446,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1428 | 1446 | |
| 1429 | 1447 | AstNodeStructValueExpr *struct_val_expr = &node->data.struct_val_expr; |
| 1430 | 1448 | |
| 1431 | TypeTableEntry *type_entry = resolve_type(g, struct_val_expr->type); | |
| 1449 | TypeTableEntry *type_entry = resolve_type(g, struct_val_expr->type, import, context); | |
| 1432 | 1450 | |
| 1433 | 1451 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 1434 | 1452 | return g->builtin_types.entry_invalid; |
| ... | ... | @@ -1655,7 +1673,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1655 | 1673 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); |
| 1656 | 1674 | if (asm_output->return_type) { |
| 1657 | 1675 | node->data.asm_expr.return_count += 1; |
| 1658 | return_type = resolve_type(g, asm_output->return_type); | |
| 1676 | return_type = resolve_type(g, asm_output->return_type, import, context); | |
| 1659 | 1677 | if (node->data.asm_expr.return_count > 1) { |
| 1660 | 1678 | add_node_error(g, node, |
| 1661 | 1679 | buf_sprintf("inline assembly allows up to one output value")); |
| ... | ... | @@ -1848,6 +1866,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1848 | 1866 | case NodeTypeStructDecl: |
| 1849 | 1867 | case NodeTypeStructField: |
| 1850 | 1868 | case NodeTypeStructValueField: |
| 1869 | case NodeTypeCompilerFnCall: | |
| 1851 | 1870 | zig_unreachable(); |
| 1852 | 1871 | } |
| 1853 | 1872 | assert(return_type); |
| ... | ... | @@ -1996,6 +2015,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 1996 | 2015 | case NodeTypeStructField: |
| 1997 | 2016 | case NodeTypeStructValueExpr: |
| 1998 | 2017 | case NodeTypeStructValueField: |
| 2018 | case NodeTypeCompilerFnCall: | |
| 1999 | 2019 | zig_unreachable(); |
| 2000 | 2020 | } |
| 2001 | 2021 | } |
src/analyze.hpp+2| ... | ... | @@ -159,9 +159,11 @@ struct CodeGen { |
| 159 | 159 | struct { |
| 160 | 160 | TypeTableEntry *entry_bool; |
| 161 | 161 | TypeTableEntry *entry_u8; |
| 162 | TypeTableEntry *entry_u16; | |
| 162 | 163 | TypeTableEntry *entry_u32; |
| 163 | 164 | TypeTableEntry *entry_u64; |
| 164 | 165 | TypeTableEntry *entry_i8; |
| 166 | TypeTableEntry *entry_i16; | |
| 165 | 167 | TypeTableEntry *entry_i32; |
| 166 | 168 | TypeTableEntry *entry_i64; |
| 167 | 169 | TypeTableEntry *entry_isize; |
src/codegen.cpp+27| ... | ... | @@ -1326,6 +1326,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1326 | 1326 | case NodeTypeStructDecl: |
| 1327 | 1327 | case NodeTypeStructField: |
| 1328 | 1328 | case NodeTypeStructValueField: |
| 1329 | case NodeTypeCompilerFnCall: | |
| 1329 | 1330 | zig_unreachable(); |
| 1330 | 1331 | } |
| 1331 | 1332 | zig_unreachable(); |
| ... | ... | @@ -1685,6 +1686,19 @@ static void define_builtin_types(CodeGen *g) { |
| 1685 | 1686 | g->type_table.put(&entry->name, entry); |
| 1686 | 1687 | g->builtin_types.entry_u8 = entry; |
| 1687 | 1688 | } |
| 1689 | { | |
| 1690 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | |
| 1691 | entry->type_ref = LLVMInt16Type(); | |
| 1692 | buf_init_from_str(&entry->name, "u16"); | |
| 1693 | entry->size_in_bits = 16; | |
| 1694 | entry->align_in_bits = 16; | |
| 1695 | entry->data.integral.is_signed = false; | |
| 1696 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | |
| 1697 | entry->size_in_bits, entry->align_in_bits, | |
| 1698 | LLVMZigEncoding_DW_ATE_unsigned()); | |
| 1699 | g->type_table.put(&entry->name, entry); | |
| 1700 | g->builtin_types.entry_u16 = entry; | |
| 1701 | } | |
| 1688 | 1702 | { |
| 1689 | 1703 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 1690 | 1704 | entry->type_ref = LLVMInt32Type(); |
| ... | ... | @@ -1725,6 +1739,19 @@ static void define_builtin_types(CodeGen *g) { |
| 1725 | 1739 | g->type_table.put(&entry->name, entry); |
| 1726 | 1740 | g->builtin_types.entry_i8 = entry; |
| 1727 | 1741 | } |
| 1742 | { | |
| 1743 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | |
| 1744 | entry->type_ref = LLVMInt16Type(); | |
| 1745 | buf_init_from_str(&entry->name, "i16"); | |
| 1746 | entry->size_in_bits = 16; | |
| 1747 | entry->align_in_bits = 16; | |
| 1748 | entry->data.integral.is_signed = true; | |
| 1749 | entry->di_type = LLVMZigCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), | |
| 1750 | entry->size_in_bits, entry->align_in_bits, | |
| 1751 | LLVMZigEncoding_DW_ATE_signed()); | |
| 1752 | g->type_table.put(&entry->name, entry); | |
| 1753 | g->builtin_types.entry_i16 = entry; | |
| 1754 | } | |
| 1728 | 1755 | { |
| 1729 | 1756 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 1730 | 1757 | entry->type_ref = LLVMInt32Type(); |
src/parser.cpp+46-3| ... | ... | @@ -142,6 +142,8 @@ const char *node_type_str(NodeType node_type) { |
| 142 | 142 | return "StructValueExpr"; |
| 143 | 143 | case NodeTypeStructValueField: |
| 144 | 144 | return "StructValueField"; |
| 145 | case NodeTypeCompilerFnCall: | |
| 146 | return "CompilerFnCall"; | |
| 145 | 147 | } |
| 146 | 148 | zig_unreachable(); |
| 147 | 149 | } |
| ... | ... | @@ -233,6 +235,12 @@ void ast_print(AstNode *node, int indent) { |
| 233 | 235 | ast_print(node->data.type.child_type, indent + 2); |
| 234 | 236 | break; |
| 235 | 237 | } |
| 238 | case AstNodeTypeTypeCompilerExpr: | |
| 239 | { | |
| 240 | fprintf(stderr, "CompilerExprType\n"); | |
| 241 | ast_print(node->data.type.compiler_expr, indent + 2); | |
| 242 | break; | |
| 243 | } | |
| 236 | 244 | } |
| 237 | 245 | break; |
| 238 | 246 | case NodeTypeReturnExpr: |
| ... | ... | @@ -402,6 +410,9 @@ void ast_print(AstNode *node, int indent) { |
| 402 | 410 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); |
| 403 | 411 | ast_print(node->data.struct_val_field.expr, indent + 2); |
| 404 | 412 | break; |
| 413 | case NodeTypeCompilerFnCall: | |
| 414 | fprintf(stderr, "%s\n", node_type_str(node->type)); | |
| 415 | break; | |
| 405 | 416 | } |
| 406 | 417 | } |
| 407 | 418 | |
| ... | ... | @@ -985,16 +996,48 @@ static void ast_parse_type_assume_amp(ParseContext *pc, int *token_index, AstNod |
| 985 | 996 | } |
| 986 | 997 | |
| 987 | 998 | /* |
| 988 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | |
| 999 | CompileTimeFnCall : token(NumberSign) token(Symbol) token(LParen) Expression token(RParen) | |
| 1000 | */ | |
| 1001 | static AstNode *ast_parse_compiler_fn_call(ParseContext *pc, int *token_index, bool mandatory) { | |
| 1002 | Token *token = &pc->tokens->at(*token_index); | |
| 1003 | ||
| 1004 | if (token->id == TokenIdNumberSign) { | |
| 1005 | *token_index += 1; | |
| 1006 | } else if (mandatory) { | |
| 1007 | ast_invalid_token_error(pc, token); | |
| 1008 | } else { | |
| 1009 | return nullptr; | |
| 1010 | } | |
| 1011 | ||
| 1012 | Token *name_symbol = ast_eat_token(pc, token_index, TokenIdSymbol); | |
| 1013 | ast_eat_token(pc, token_index, TokenIdLParen); | |
| 1014 | ||
| 1015 | AstNode *node = ast_create_node(pc, NodeTypeCompilerFnCall, token); | |
| 1016 | ast_buf_from_token(pc, name_symbol, &node->data.compiler_fn_call.name); | |
| 1017 | node->data.compiler_fn_call.expr = ast_parse_expression(pc, token_index, true); | |
| 1018 | ||
| 1019 | ast_eat_token(pc, token_index, TokenIdRParen); | |
| 1020 | return node; | |
| 1021 | } | |
| 1022 | ||
| 1023 | /* | |
| 1024 | Type : token(Symbol) | token(Unreachable) | token(Void) | PointerType | ArrayType | MaybeType | CompileTimeFnCall | |
| 989 | 1025 | PointerType : token(Ampersand) option(token(Const)) Type |
| 990 | 1026 | ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket) |
| 991 | 1027 | */ |
| 992 | 1028 | static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { |
| 993 | 1029 | Token *token = &pc->tokens->at(*token_index); |
| 994 | *token_index += 1; | |
| 995 | ||
| 996 | 1030 | AstNode *node = ast_create_node(pc, NodeTypeType, token); |
| 997 | 1031 | |
| 1032 | AstNode *compiler_fn_call = ast_parse_compiler_fn_call(pc, token_index, false); | |
| 1033 | if (compiler_fn_call) { | |
| 1034 | node->data.type.type = AstNodeTypeTypeCompilerExpr; | |
| 1035 | node->data.type.compiler_expr = compiler_fn_call; | |
| 1036 | return node; | |
| 1037 | } | |
| 1038 | ||
| 1039 | *token_index += 1; | |
| 1040 | ||
| 998 | 1041 | if (token->id == TokenIdKeywordUnreachable) { |
| 999 | 1042 | node->data.type.type = AstNodeTypeTypePrimitive; |
| 1000 | 1043 | buf_init_from_str(&node->data.type.primitive_name, "unreachable"); |
src/parser.hpp+9| ... | ... | @@ -57,6 +57,7 @@ enum NodeType { |
| 57 | 57 | NodeTypeStructField, |
| 58 | 58 | NodeTypeStructValueExpr, |
| 59 | 59 | NodeTypeStructValueField, |
| 60 | NodeTypeCompilerFnCall, | |
| 60 | 61 | }; |
| 61 | 62 | |
| 62 | 63 | struct AstNodeRoot { |
| ... | ... | @@ -97,6 +98,7 @@ enum AstNodeTypeType { |
| 97 | 98 | AstNodeTypeTypePointer, |
| 98 | 99 | AstNodeTypeTypeArray, |
| 99 | 100 | AstNodeTypeTypeMaybe, |
| 101 | AstNodeTypeTypeCompilerExpr, | |
| 100 | 102 | }; |
| 101 | 103 | |
| 102 | 104 | struct AstNodeType { |
| ... | ... | @@ -105,6 +107,7 @@ struct AstNodeType { |
| 105 | 107 | AstNode *child_type; |
| 106 | 108 | AstNode *array_size; |
| 107 | 109 | bool is_const; |
| 110 | AstNode *compiler_expr; | |
| 108 | 111 | }; |
| 109 | 112 | |
| 110 | 113 | struct AstNodeBlock { |
| ... | ... | @@ -329,6 +332,11 @@ struct AstNodeStructValueExpr { |
| 329 | 332 | ZigList<AstNode *> fields; |
| 330 | 333 | }; |
| 331 | 334 | |
| 335 | struct AstNodeCompilerFnCall { | |
| 336 | Buf name; | |
| 337 | AstNode *expr; | |
| 338 | }; | |
| 339 | ||
| 332 | 340 | struct AstNode { |
| 333 | 341 | enum NodeType type; |
| 334 | 342 | int line; |
| ... | ... | @@ -368,6 +376,7 @@ struct AstNode { |
| 368 | 376 | AstNodeNumberLiteral number_literal; |
| 369 | 377 | AstNodeStructValueExpr struct_val_expr; |
| 370 | 378 | AstNodeStructValueField struct_val_field; |
| 379 | AstNodeCompilerFnCall compiler_fn_call; | |
| 371 | 380 | Buf symbol; |
| 372 | 381 | bool bool_literal; |
| 373 | 382 | } data; |
test/run_tests.cpp+26-10| ... | ... | @@ -347,7 +347,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 347 | 347 | add_simple_case("hello world without libc", R"SOURCE( |
| 348 | 348 | use "std.zig"; |
| 349 | 349 | |
| 350 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 350 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 351 | 351 | print_str("Hello, world!\n"); |
| 352 | 352 | return 0; |
| 353 | 353 | } |
| ... | ... | @@ -357,7 +357,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 357 | 357 | add_simple_case("a + b + c", R"SOURCE( |
| 358 | 358 | use "std.zig"; |
| 359 | 359 | |
| 360 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 360 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 361 | 361 | if (false || false || false) { print_str("BAD 1\n"); } |
| 362 | 362 | if (true && true && false) { print_str("BAD 2\n"); } |
| 363 | 363 | if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); } |
| ... | ... | @@ -379,7 +379,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 379 | 379 | add_simple_case("short circuit", R"SOURCE( |
| 380 | 380 | use "std.zig"; |
| 381 | 381 | |
| 382 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 382 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 383 | 383 | if (true || { print_str("BAD 1\n"); false }) { |
| 384 | 384 | print_str("OK 1\n"); |
| 385 | 385 | } |
| ... | ... | @@ -402,7 +402,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 402 | 402 | add_simple_case("modify operators", R"SOURCE( |
| 403 | 403 | use "std.zig"; |
| 404 | 404 | |
| 405 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 405 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 406 | 406 | var i : i32 = 0; |
| 407 | 407 | i += 5; if (i != 5) { print_str("BAD +=\n"); } |
| 408 | 408 | i -= 2; if (i != 3) { print_str("BAD -=\n"); } |
| ... | ... | @@ -554,7 +554,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 554 | 554 | add_simple_case("structs", R"SOURCE( |
| 555 | 555 | use "std.zig"; |
| 556 | 556 | |
| 557 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 557 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 558 | 558 | var foo : Foo; |
| 559 | 559 | foo.a += 1; |
| 560 | 560 | foo.b = foo.a == 1; |
| ... | ... | @@ -628,7 +628,7 @@ use "std.zig"; |
| 628 | 628 | const g1 : i32 = 1233 + 1; |
| 629 | 629 | var g2 : i32; |
| 630 | 630 | |
| 631 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 631 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 632 | 632 | if (g2 != 0) { print_str("BAD\n"); } |
| 633 | 633 | g2 = g1; |
| 634 | 634 | if (g2 != 1234) { print_str("BAD\n"); } |
| ... | ... | @@ -639,7 +639,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 639 | 639 | |
| 640 | 640 | add_simple_case("while loop", R"SOURCE( |
| 641 | 641 | use "std.zig"; |
| 642 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 642 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 643 | 643 | var i : i32 = 0; |
| 644 | 644 | while (i < 4) { |
| 645 | 645 | print_str("loop\n"); |
| ... | ... | @@ -651,7 +651,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 651 | 651 | |
| 652 | 652 | add_simple_case("continue and break", R"SOURCE( |
| 653 | 653 | use "std.zig"; |
| 654 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 654 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 655 | 655 | var i : i32 = 0; |
| 656 | 656 | while (true) { |
| 657 | 657 | print_str("loop\n"); |
| ... | ... | @@ -667,7 +667,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 667 | 667 | |
| 668 | 668 | add_simple_case("maybe type", R"SOURCE( |
| 669 | 669 | use "std.zig"; |
| 670 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 670 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 671 | 671 | const x : ?bool = true; |
| 672 | 672 | |
| 673 | 673 | if (const y ?= x) { |
| ... | ... | @@ -685,7 +685,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 685 | 685 | |
| 686 | 686 | add_simple_case("implicit cast after unreachable", R"SOURCE( |
| 687 | 687 | use "std.zig"; |
| 688 | export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 688 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 689 | 689 | const x = outer(); |
| 690 | 690 | if (x == 1234) { |
| 691 | 691 | print_str("OK\n"); |
| ... | ... | @@ -695,6 +695,17 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 695 | 695 | fn inner() -> i32 { 1234 } |
| 696 | 696 | fn outer() -> isize { |
| 697 | 697 | return inner(); |
| 698 | } | |
| 699 | )SOURCE", "OK\n"); | |
| 700 | ||
| 701 | add_simple_case("#typeof()", R"SOURCE( | |
| 702 | use "std.zig"; | |
| 703 | const x: u16 = 13; | |
| 704 | const z: #typeof(x) = 19; | |
| 705 | pub fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | |
| 706 | const y: #typeof(x) = 120; | |
| 707 | print_str("OK\n"); | |
| 708 | return 0; | |
| 698 | 709 | } |
| 699 | 710 | )SOURCE", "OK\n"); |
| 700 | 711 | } |
| ... | ... | @@ -999,6 +1010,11 @@ fn f() -> i32 { |
| 999 | 1010 | (return 1) as i32 |
| 1000 | 1011 | } |
| 1001 | 1012 | )SOURCE", 1, ".tmp_source.zig:3:16: error: invalid cast from type 'unreachable' to 'i32'"); |
| 1013 | ||
| 1014 | add_compile_fail_case("invalid compiler fn", R"SOURCE( | |
| 1015 | fn f() -> #bogus(foo) { | |
| 1016 | } | |
| 1017 | )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid compiler function: 'bogus'"); | |
| 1002 | 1018 | } |
| 1003 | 1019 | |
| 1004 | 1020 | static void print_compiler_invocation(TestCase *test_case) { |