| 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,7 +60,9 @@ ParamDeclList : token(LParen) list(ParamDecl, token(Comma)) token(RParen) |
| 60 | 60 | ||
| 61 | ParamDecl : token(Symbol) token(Colon) Type | token(Ellipsis) | 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 | PointerType : token(Ampersand) option(token(Const)) Type | 67 | PointerType : token(Ampersand) option(token(Const)) Type |
| 66 | 68 |
example/rand/main.zig+1-1| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | const ARRAY_SIZE : u16 = 624; | 2 | const ARRAY_SIZE : u16 = 624; |
| 3 | 3 | ||
| 4 | /// Use `rand_init` to initialize this state. | 4 | /// Use `rand_init` to initialize this state. |
| 5 | pub struct Rand { | 5 | struct Rand { |
| 6 | array: [u32; ARRAY_SIZE], | 6 | array: [u32; ARRAY_SIZE], |
| 7 | index: #typeof(ARRAY_SIZE), | 7 | index: #typeof(ARRAY_SIZE), |
| 8 | 8 |
src/analyze.cpp+34-14| ... | @@ -59,6 +59,7 @@ static AstNode *first_executing_node(AstNode *node) { | ... | @@ -59,6 +59,7 @@ static AstNode *first_executing_node(AstNode *node) { |
| 59 | case NodeTypeStructValueExpr: | 59 | case NodeTypeStructValueExpr: |
| 60 | case NodeTypeStructValueField: | 60 | case NodeTypeStructValueField: |
| 61 | case NodeTypeWhileExpr: | 61 | case NodeTypeWhileExpr: |
| 62 | case NodeTypeCompilerFnCall: | ||
| 62 | return node; | 63 | return node; |
| 63 | } | 64 | } |
| 64 | zig_panic("unreachable"); | 65 | zig_panic("unreachable"); |
| ... | @@ -208,7 +209,7 @@ static TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, ui | ... | @@ -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 | assert(node->type == NodeTypeType); | 213 | assert(node->type == NodeTypeType); |
| 213 | alloc_codegen_node(node); | 214 | alloc_codegen_node(node); |
| 214 | TypeNode *type_node = &node->codegen_node->data.type_node; | 215 | TypeNode *type_node = &node->codegen_node->data.type_node; |
| ... | @@ -228,7 +229,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -228,7 +229,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 228 | } | 229 | } |
| 229 | case AstNodeTypeTypePointer: | 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 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 233 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 233 | assert(child_type); | 234 | assert(child_type); |
| 234 | if (child_type->id == TypeTableEntryIdUnreachable) { | 235 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| ... | @@ -242,7 +243,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -242,7 +243,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 242 | } | 243 | } |
| 243 | case AstNodeTypeTypeArray: | 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 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 247 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 247 | if (child_type->id == TypeTableEntryIdUnreachable) { | 248 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| 248 | add_node_error(g, node, | 249 | add_node_error(g, node, |
| ... | @@ -263,7 +264,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -263,7 +264,7 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 263 | } | 264 | } |
| 264 | case AstNodeTypeTypeMaybe: | 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 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; | 268 | TypeTableEntry *child_type = node->data.type.child_type->codegen_node->data.type_node.entry; |
| 268 | assert(child_type); | 269 | assert(child_type); |
| 269 | if (child_type->id == TypeTableEntryIdUnreachable) { | 270 | if (child_type->id == TypeTableEntryIdUnreachable) { |
| ... | @@ -275,11 +276,26 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { | ... | @@ -275,11 +276,26 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) { |
| 275 | type_node->entry = get_maybe_type(g, child_type); | 276 | type_node->entry = get_maybe_type(g, child_type); |
| 276 | return type_node->entry; | 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 | zig_unreachable(); | 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 | assert(node->type == NodeTypeFnProto); | 299 | assert(node->type == NodeTypeFnProto); |
| 284 | 300 | ||
| 285 | for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) { | 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,7 +326,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t |
| 310 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { | 326 | for (int i = 0; i < node->data.fn_proto.params.length; i += 1) { |
| 311 | AstNode *child = node->data.fn_proto.params.at(i); | 327 | AstNode *child = node->data.fn_proto.params.at(i); |
| 312 | assert(child->type == NodeTypeParamDecl); | 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 | if (type_entry->id == TypeTableEntryIdUnreachable) { | 330 | if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 315 | add_node_error(g, child->data.param_decl.type, | 331 | add_node_error(g, child->data.param_decl.type, |
| 316 | buf_sprintf("parameter of type 'unreachable' not allowed")); | 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,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 | static void preview_function_labels(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry) { | 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,7 +399,7 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 383 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); | 399 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 384 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; | 400 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 385 | type_struct_field->name = &field_node->data.struct_field.name; | 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 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { | 404 | if (type_struct_field->type_entry->id == TypeTableEntryIdStruct) { |
| 389 | resolve_struct_type(g, import, type_struct_field->type_entry); | 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,7 +469,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 453 | fn_table_entry->import_entry = import; | 469 | fn_table_entry->import_entry = import; |
| 454 | fn_table_entry->label_table.init(8); | 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 | Buf *name = &fn_proto->data.fn_proto.name; | 474 | Buf *name = &fn_proto->data.fn_proto.name; |
| 459 | g->fn_protos.append(fn_table_entry); | 475 | g->fn_protos.append(fn_table_entry); |
| ... | @@ -512,7 +528,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -512,7 +528,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 512 | g->fn_table.put(proto_name, fn_table_entry); | 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 | alloc_codegen_node(proto_node); | 534 | alloc_codegen_node(proto_node); |
| ... | @@ -609,6 +625,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, | ... | @@ -609,6 +625,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import, |
| 609 | case NodeTypeStructField: | 625 | case NodeTypeStructField: |
| 610 | case NodeTypeStructValueExpr: | 626 | case NodeTypeStructValueExpr: |
| 611 | case NodeTypeStructValueField: | 627 | case NodeTypeStructValueField: |
| 628 | case NodeTypeCompilerFnCall: | ||
| 612 | zig_unreachable(); | 629 | zig_unreachable(); |
| 613 | } | 630 | } |
| 614 | } | 631 | } |
| ... | @@ -681,6 +698,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ... | @@ -681,6 +698,7 @@ static void preview_types(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 681 | case NodeTypeStructField: | 698 | case NodeTypeStructField: |
| 682 | case NodeTypeStructValueExpr: | 699 | case NodeTypeStructValueExpr: |
| 683 | case NodeTypeStructValueField: | 700 | case NodeTypeStructValueField: |
| 701 | case NodeTypeCompilerFnCall: | ||
| 684 | zig_unreachable(); | 702 | zig_unreachable(); |
| 685 | } | 703 | } |
| 686 | } | 704 | } |
| ... | @@ -1132,7 +1150,7 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { | ... | @@ -1132,7 +1150,7 @@ static bool is_op_allowed(TypeTableEntry *type, BinOpType op) { |
| 1132 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 1150 | static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 1133 | TypeTableEntry *expected_type, AstNode *node) | 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 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); | 1154 | TypeTableEntry *actual_type = analyze_expression(g, import, context, nullptr, node->data.cast_expr.expr); |
| 1137 | 1155 | ||
| 1138 | if (wanted_type->id == TypeTableEntryIdInvalid || | 1156 | if (wanted_type->id == TypeTableEntryIdInvalid || |
| ... | @@ -1328,7 +1346,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa | ... | @@ -1328,7 +1346,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa |
| 1328 | { | 1346 | { |
| 1329 | TypeTableEntry *explicit_type = nullptr; | 1347 | TypeTableEntry *explicit_type = nullptr; |
| 1330 | if (variable_declaration->type != nullptr) { | 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 | if (explicit_type->id == TypeTableEntryIdUnreachable) { | 1350 | if (explicit_type->id == TypeTableEntryIdUnreachable) { |
| 1333 | add_node_error(g, variable_declaration->type, | 1351 | add_node_error(g, variable_declaration->type, |
| 1334 | buf_sprintf("variable of type 'unreachable' not allowed")); | 1352 | buf_sprintf("variable of type 'unreachable' not allowed")); |
| ... | @@ -1428,7 +1446,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp | ... | @@ -1428,7 +1446,7 @@ static TypeTableEntry *analyze_struct_val_expr(CodeGen *g, ImportTableEntry *imp |
| 1428 | 1446 | ||
| 1429 | AstNodeStructValueExpr *struct_val_expr = &node->data.struct_val_expr; | 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 | if (type_entry->id == TypeTableEntryIdInvalid) { | 1451 | if (type_entry->id == TypeTableEntryIdInvalid) { |
| 1434 | return g->builtin_types.entry_invalid; | 1452 | return g->builtin_types.entry_invalid; |
| ... | @@ -1655,7 +1673,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -1655,7 +1673,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1655 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); | 1673 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); |
| 1656 | if (asm_output->return_type) { | 1674 | if (asm_output->return_type) { |
| 1657 | node->data.asm_expr.return_count += 1; | 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 | if (node->data.asm_expr.return_count > 1) { | 1677 | if (node->data.asm_expr.return_count > 1) { |
| 1660 | add_node_error(g, node, | 1678 | add_node_error(g, node, |
| 1661 | buf_sprintf("inline assembly allows up to one output value")); | 1679 | buf_sprintf("inline assembly allows up to one output value")); |
| ... | @@ -1848,6 +1866,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -1848,6 +1866,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 1848 | case NodeTypeStructDecl: | 1866 | case NodeTypeStructDecl: |
| 1849 | case NodeTypeStructField: | 1867 | case NodeTypeStructField: |
| 1850 | case NodeTypeStructValueField: | 1868 | case NodeTypeStructValueField: |
| 1869 | case NodeTypeCompilerFnCall: | ||
| 1851 | zig_unreachable(); | 1870 | zig_unreachable(); |
| 1852 | } | 1871 | } |
| 1853 | assert(return_type); | 1872 | assert(return_type); |
| ... | @@ -1996,6 +2015,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, | ... | @@ -1996,6 +2015,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 1996 | case NodeTypeStructField: | 2015 | case NodeTypeStructField: |
| 1997 | case NodeTypeStructValueExpr: | 2016 | case NodeTypeStructValueExpr: |
| 1998 | case NodeTypeStructValueField: | 2017 | case NodeTypeStructValueField: |
| 2018 | case NodeTypeCompilerFnCall: | ||
| 1999 | zig_unreachable(); | 2019 | zig_unreachable(); |
| 2000 | } | 2020 | } |
| 2001 | } | 2021 | } |
src/analyze.hpp+2| ... | @@ -159,9 +159,11 @@ struct CodeGen { | ... | @@ -159,9 +159,11 @@ struct CodeGen { |
| 159 | struct { | 159 | struct { |
| 160 | TypeTableEntry *entry_bool; | 160 | TypeTableEntry *entry_bool; |
| 161 | TypeTableEntry *entry_u8; | 161 | TypeTableEntry *entry_u8; |
| 162 | TypeTableEntry *entry_u16; | ||
| 162 | TypeTableEntry *entry_u32; | 163 | TypeTableEntry *entry_u32; |
| 163 | TypeTableEntry *entry_u64; | 164 | TypeTableEntry *entry_u64; |
| 164 | TypeTableEntry *entry_i8; | 165 | TypeTableEntry *entry_i8; |
| 166 | TypeTableEntry *entry_i16; | ||
| 165 | TypeTableEntry *entry_i32; | 167 | TypeTableEntry *entry_i32; |
| 166 | TypeTableEntry *entry_i64; | 168 | TypeTableEntry *entry_i64; |
| 167 | TypeTableEntry *entry_isize; | 169 | TypeTableEntry *entry_isize; |
src/codegen.cpp+27| ... | @@ -1326,6 +1326,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { | ... | @@ -1326,6 +1326,7 @@ static LLVMValueRef gen_expr_no_cast(CodeGen *g, AstNode *node) { |
| 1326 | case NodeTypeStructDecl: | 1326 | case NodeTypeStructDecl: |
| 1327 | case NodeTypeStructField: | 1327 | case NodeTypeStructField: |
| 1328 | case NodeTypeStructValueField: | 1328 | case NodeTypeStructValueField: |
| 1329 | case NodeTypeCompilerFnCall: | ||
| 1329 | zig_unreachable(); | 1330 | zig_unreachable(); |
| 1330 | } | 1331 | } |
| 1331 | zig_unreachable(); | 1332 | zig_unreachable(); |
| ... | @@ -1685,6 +1686,19 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -1685,6 +1686,19 @@ static void define_builtin_types(CodeGen *g) { |
| 1685 | g->type_table.put(&entry->name, entry); | 1686 | g->type_table.put(&entry->name, entry); |
| 1686 | g->builtin_types.entry_u8 = entry; | 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 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | 1703 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 1690 | entry->type_ref = LLVMInt32Type(); | 1704 | entry->type_ref = LLVMInt32Type(); |
| ... | @@ -1725,6 +1739,19 @@ static void define_builtin_types(CodeGen *g) { | ... | @@ -1725,6 +1739,19 @@ static void define_builtin_types(CodeGen *g) { |
| 1725 | g->type_table.put(&entry->name, entry); | 1739 | g->type_table.put(&entry->name, entry); |
| 1726 | g->builtin_types.entry_i8 = entry; | 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 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); | 1756 | TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt); |
| 1730 | entry->type_ref = LLVMInt32Type(); | 1757 | entry->type_ref = LLVMInt32Type(); |
src/parser.cpp+46-3| ... | @@ -142,6 +142,8 @@ const char *node_type_str(NodeType node_type) { | ... | @@ -142,6 +142,8 @@ const char *node_type_str(NodeType node_type) { |
| 142 | return "StructValueExpr"; | 142 | return "StructValueExpr"; |
| 143 | case NodeTypeStructValueField: | 143 | case NodeTypeStructValueField: |
| 144 | return "StructValueField"; | 144 | return "StructValueField"; |
| 145 | case NodeTypeCompilerFnCall: | ||
| 146 | return "CompilerFnCall"; | ||
| 145 | } | 147 | } |
| 146 | zig_unreachable(); | 148 | zig_unreachable(); |
| 147 | } | 149 | } |
| ... | @@ -233,6 +235,12 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -233,6 +235,12 @@ void ast_print(AstNode *node, int indent) { |
| 233 | ast_print(node->data.type.child_type, indent + 2); | 235 | ast_print(node->data.type.child_type, indent + 2); |
| 234 | break; | 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 | break; | 245 | break; |
| 238 | case NodeTypeReturnExpr: | 246 | case NodeTypeReturnExpr: |
| ... | @@ -402,6 +410,9 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -402,6 +410,9 @@ void ast_print(AstNode *node, int indent) { |
| 402 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); | 410 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name)); |
| 403 | ast_print(node->data.struct_val_field.expr, indent + 2); | 411 | ast_print(node->data.struct_val_field.expr, indent + 2); |
| 404 | break; | 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,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 | PointerType : token(Ampersand) option(token(Const)) Type | 1025 | PointerType : token(Ampersand) option(token(Const)) Type |
| 990 | ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket) | 1026 | ArrayType : token(LBracket) Type token(Semicolon) token(Number) token(RBracket) |
| 991 | */ | 1027 | */ |
| 992 | static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { | 1028 | static AstNode *ast_parse_type(ParseContext *pc, int *token_index) { |
| 993 | Token *token = &pc->tokens->at(*token_index); | 1029 | Token *token = &pc->tokens->at(*token_index); |
| 994 | *token_index += 1; | ||
| 995 | |||
| 996 | AstNode *node = ast_create_node(pc, NodeTypeType, token); | 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 | if (token->id == TokenIdKeywordUnreachable) { | 1041 | if (token->id == TokenIdKeywordUnreachable) { |
| 999 | node->data.type.type = AstNodeTypeTypePrimitive; | 1042 | node->data.type.type = AstNodeTypeTypePrimitive; |
| 1000 | buf_init_from_str(&node->data.type.primitive_name, "unreachable"); | 1043 | buf_init_from_str(&node->data.type.primitive_name, "unreachable"); |
src/parser.hpp+9| ... | @@ -57,6 +57,7 @@ enum NodeType { | ... | @@ -57,6 +57,7 @@ enum NodeType { |
| 57 | NodeTypeStructField, | 57 | NodeTypeStructField, |
| 58 | NodeTypeStructValueExpr, | 58 | NodeTypeStructValueExpr, |
| 59 | NodeTypeStructValueField, | 59 | NodeTypeStructValueField, |
| 60 | NodeTypeCompilerFnCall, | ||
| 60 | }; | 61 | }; |
| 61 | 62 | ||
| 62 | struct AstNodeRoot { | 63 | struct AstNodeRoot { |
| ... | @@ -97,6 +98,7 @@ enum AstNodeTypeType { | ... | @@ -97,6 +98,7 @@ enum AstNodeTypeType { |
| 97 | AstNodeTypeTypePointer, | 98 | AstNodeTypeTypePointer, |
| 98 | AstNodeTypeTypeArray, | 99 | AstNodeTypeTypeArray, |
| 99 | AstNodeTypeTypeMaybe, | 100 | AstNodeTypeTypeMaybe, |
| 101 | AstNodeTypeTypeCompilerExpr, | ||
| 100 | }; | 102 | }; |
| 101 | 103 | ||
| 102 | struct AstNodeType { | 104 | struct AstNodeType { |
| ... | @@ -105,6 +107,7 @@ struct AstNodeType { | ... | @@ -105,6 +107,7 @@ struct AstNodeType { |
| 105 | AstNode *child_type; | 107 | AstNode *child_type; |
| 106 | AstNode *array_size; | 108 | AstNode *array_size; |
| 107 | bool is_const; | 109 | bool is_const; |
| 110 | AstNode *compiler_expr; | ||
| 108 | }; | 111 | }; |
| 109 | 112 | ||
| 110 | struct AstNodeBlock { | 113 | struct AstNodeBlock { |
| ... | @@ -329,6 +332,11 @@ struct AstNodeStructValueExpr { | ... | @@ -329,6 +332,11 @@ struct AstNodeStructValueExpr { |
| 329 | ZigList<AstNode *> fields; | 332 | ZigList<AstNode *> fields; |
| 330 | }; | 333 | }; |
| 331 | 334 | ||
| 335 | struct AstNodeCompilerFnCall { | ||
| 336 | Buf name; | ||
| 337 | AstNode *expr; | ||
| 338 | }; | ||
| 339 | |||
| 332 | struct AstNode { | 340 | struct AstNode { |
| 333 | enum NodeType type; | 341 | enum NodeType type; |
| 334 | int line; | 342 | int line; |
| ... | @@ -368,6 +376,7 @@ struct AstNode { | ... | @@ -368,6 +376,7 @@ struct AstNode { |
| 368 | AstNodeNumberLiteral number_literal; | 376 | AstNodeNumberLiteral number_literal; |
| 369 | AstNodeStructValueExpr struct_val_expr; | 377 | AstNodeStructValueExpr struct_val_expr; |
| 370 | AstNodeStructValueField struct_val_field; | 378 | AstNodeStructValueField struct_val_field; |
| 379 | AstNodeCompilerFnCall compiler_fn_call; | ||
| 371 | Buf symbol; | 380 | Buf symbol; |
| 372 | bool bool_literal; | 381 | bool bool_literal; |
| 373 | } data; | 382 | } data; |
test/run_tests.cpp+26-10| ... | @@ -347,7 +347,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { | ... | @@ -347,7 +347,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 { |
| 347 | add_simple_case("hello world without libc", R"SOURCE( | 347 | add_simple_case("hello world without libc", R"SOURCE( |
| 348 | use "std.zig"; | 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 | print_str("Hello, world!\n"); | 351 | print_str("Hello, world!\n"); |
| 352 | return 0; | 352 | return 0; |
| 353 | } | 353 | } |
| ... | @@ -357,7 +357,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -357,7 +357,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 357 | add_simple_case("a + b + c", R"SOURCE( | 357 | add_simple_case("a + b + c", R"SOURCE( |
| 358 | use "std.zig"; | 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 | if (false || false || false) { print_str("BAD 1\n"); } | 361 | if (false || false || false) { print_str("BAD 1\n"); } |
| 362 | if (true && true && false) { print_str("BAD 2\n"); } | 362 | if (true && true && false) { print_str("BAD 2\n"); } |
| 363 | if (1 | 2 | 4 != 7) { print_str("BAD 3\n"); } | 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,7 +379,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 379 | add_simple_case("short circuit", R"SOURCE( | 379 | add_simple_case("short circuit", R"SOURCE( |
| 380 | use "std.zig"; | 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 | if (true || { print_str("BAD 1\n"); false }) { | 383 | if (true || { print_str("BAD 1\n"); false }) { |
| 384 | print_str("OK 1\n"); | 384 | print_str("OK 1\n"); |
| 385 | } | 385 | } |
| ... | @@ -402,7 +402,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -402,7 +402,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 402 | add_simple_case("modify operators", R"SOURCE( | 402 | add_simple_case("modify operators", R"SOURCE( |
| 403 | use "std.zig"; | 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 | var i : i32 = 0; | 406 | var i : i32 = 0; |
| 407 | i += 5; if (i != 5) { print_str("BAD +=\n"); } | 407 | i += 5; if (i != 5) { print_str("BAD +=\n"); } |
| 408 | i -= 2; if (i != 3) { print_str("BAD -=\n"); } | 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,7 +554,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 554 | add_simple_case("structs", R"SOURCE( | 554 | add_simple_case("structs", R"SOURCE( |
| 555 | use "std.zig"; | 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 | var foo : Foo; | 558 | var foo : Foo; |
| 559 | foo.a += 1; | 559 | foo.a += 1; |
| 560 | foo.b = foo.a == 1; | 560 | foo.b = foo.a == 1; |
| ... | @@ -628,7 +628,7 @@ use "std.zig"; | ... | @@ -628,7 +628,7 @@ use "std.zig"; |
| 628 | const g1 : i32 = 1233 + 1; | 628 | const g1 : i32 = 1233 + 1; |
| 629 | var g2 : i32; | 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 | if (g2 != 0) { print_str("BAD\n"); } | 632 | if (g2 != 0) { print_str("BAD\n"); } |
| 633 | g2 = g1; | 633 | g2 = g1; |
| 634 | if (g2 != 1234) { print_str("BAD\n"); } | 634 | if (g2 != 1234) { print_str("BAD\n"); } |
| ... | @@ -639,7 +639,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -639,7 +639,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 639 | 639 | ||
| 640 | add_simple_case("while loop", R"SOURCE( | 640 | add_simple_case("while loop", R"SOURCE( |
| 641 | use "std.zig"; | 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 | var i : i32 = 0; | 643 | var i : i32 = 0; |
| 644 | while (i < 4) { | 644 | while (i < 4) { |
| 645 | print_str("loop\n"); | 645 | print_str("loop\n"); |
| ... | @@ -651,7 +651,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -651,7 +651,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 651 | 651 | ||
| 652 | add_simple_case("continue and break", R"SOURCE( | 652 | add_simple_case("continue and break", R"SOURCE( |
| 653 | use "std.zig"; | 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 | var i : i32 = 0; | 655 | var i : i32 = 0; |
| 656 | while (true) { | 656 | while (true) { |
| 657 | print_str("loop\n"); | 657 | print_str("loop\n"); |
| ... | @@ -667,7 +667,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -667,7 +667,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 667 | 667 | ||
| 668 | add_simple_case("maybe type", R"SOURCE( | 668 | add_simple_case("maybe type", R"SOURCE( |
| 669 | use "std.zig"; | 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 | const x : ?bool = true; | 671 | const x : ?bool = true; |
| 672 | 672 | ||
| 673 | if (const y ?= x) { | 673 | if (const y ?= x) { |
| ... | @@ -685,7 +685,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -685,7 +685,7 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 685 | 685 | ||
| 686 | add_simple_case("implicit cast after unreachable", R"SOURCE( | 686 | add_simple_case("implicit cast after unreachable", R"SOURCE( |
| 687 | use "std.zig"; | 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 | const x = outer(); | 689 | const x = outer(); |
| 690 | if (x == 1234) { | 690 | if (x == 1234) { |
| 691 | print_str("OK\n"); | 691 | print_str("OK\n"); |
| ... | @@ -695,6 +695,17 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { | ... | @@ -695,6 +695,17 @@ export fn main(argc : isize, argv : &&u8, env : &&u8) -> i32 { |
| 695 | fn inner() -> i32 { 1234 } | 695 | fn inner() -> i32 { 1234 } |
| 696 | fn outer() -> isize { | 696 | fn outer() -> isize { |
| 697 | return inner(); | 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 | )SOURCE", "OK\n"); | 710 | )SOURCE", "OK\n"); |
| 700 | } | 711 | } |
| ... | @@ -999,6 +1010,11 @@ fn f() -> i32 { | ... | @@ -999,6 +1010,11 @@ fn f() -> i32 { |
| 999 | (return 1) as i32 | 1010 | (return 1) as i32 |
| 1000 | } | 1011 | } |
| 1001 | )SOURCE", 1, ".tmp_source.zig:3:16: error: invalid cast from type 'unreachable' to 'i32'"); | 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 | static void print_compiler_invocation(TestCase *test_case) { | 1020 | static void print_compiler_invocation(TestCase *test_case) { |