| author | |
| committer | |
| log | a73453a2680cdbe4decb946f5f8355e83b521aa2 |
| tree | 93922996fba980dc65d648f9dfae7ddc50fe0419 |
| parent | 5afe473a86c2fe32b6d7c472b71f88e70ac671c6 |
see #886 files changed, 184 insertions(+), 38 deletions(-)
src/all_types.hpp+18-3| ... | @@ -136,7 +136,8 @@ enum NodeType { | ... | @@ -136,7 +136,8 @@ enum NodeType { |
| 136 | NodeTypeArrayAccessExpr, | 136 | NodeTypeArrayAccessExpr, |
| 137 | NodeTypeSliceExpr, | 137 | NodeTypeSliceExpr, |
| 138 | NodeTypeFieldAccessExpr, | 138 | NodeTypeFieldAccessExpr, |
| 139 | NodeTypeUse, | 139 | NodeTypeImport, |
| 140 | NodeTypeCImport, | ||
| 140 | NodeTypeBoolLiteral, | 141 | NodeTypeBoolLiteral, |
| 141 | NodeTypeNullLiteral, | 142 | NodeTypeNullLiteral, |
| 142 | NodeTypeUndefinedLiteral, | 143 | NodeTypeUndefinedLiteral, |
| ... | @@ -410,7 +411,7 @@ struct AstNodePrefixOpExpr { | ... | @@ -410,7 +411,7 @@ struct AstNodePrefixOpExpr { |
| 410 | Expr resolved_expr; | 411 | Expr resolved_expr; |
| 411 | }; | 412 | }; |
| 412 | 413 | ||
| 413 | struct AstNodeUse { | 414 | struct AstNodeImport { |
| 414 | Buf path; | 415 | Buf path; |
| 415 | ZigList<AstNode *> *directives; | 416 | ZigList<AstNode *> *directives; |
| 416 | VisibMod visib_mod; | 417 | VisibMod visib_mod; |
| ... | @@ -419,6 +420,15 @@ struct AstNodeUse { | ... | @@ -419,6 +420,15 @@ struct AstNodeUse { |
| 419 | ImportTableEntry *import; | 420 | ImportTableEntry *import; |
| 420 | }; | 421 | }; |
| 421 | 422 | ||
| 423 | struct AstNodeCImport { | ||
| 424 | ZigList<AstNode *> *directives; | ||
| 425 | VisibMod visib_mod; | ||
| 426 | AstNode *block; | ||
| 427 | |||
| 428 | // populated by semantic analyzer | ||
| 429 | TopLevelDecl top_level_decl; | ||
| 430 | }; | ||
| 431 | |||
| 422 | struct AstNodeIfBoolExpr { | 432 | struct AstNodeIfBoolExpr { |
| 423 | AstNode *condition; | 433 | AstNode *condition; |
| 424 | AstNode *then_block; | 434 | AstNode *then_block; |
| ... | @@ -699,7 +709,8 @@ struct AstNode { | ... | @@ -699,7 +709,8 @@ struct AstNode { |
| 699 | AstNodeFnCallExpr fn_call_expr; | 709 | AstNodeFnCallExpr fn_call_expr; |
| 700 | AstNodeArrayAccessExpr array_access_expr; | 710 | AstNodeArrayAccessExpr array_access_expr; |
| 701 | AstNodeSliceExpr slice_expr; | 711 | AstNodeSliceExpr slice_expr; |
| 702 | AstNodeUse use; | 712 | AstNodeImport import; |
| 713 | AstNodeCImport c_import; | ||
| 703 | AstNodeIfBoolExpr if_bool_expr; | 714 | AstNodeIfBoolExpr if_bool_expr; |
| 704 | AstNodeIfVarExpr if_var_expr; | 715 | AstNodeIfVarExpr if_var_expr; |
| 705 | AstNodeWhileExpr while_expr; | 716 | AstNodeWhileExpr while_expr; |
| ... | @@ -920,6 +931,9 @@ enum BuiltinFnId { | ... | @@ -920,6 +931,9 @@ enum BuiltinFnId { |
| 920 | BuiltinFnIdAddWithOverflow, | 931 | BuiltinFnIdAddWithOverflow, |
| 921 | BuiltinFnIdSubWithOverflow, | 932 | BuiltinFnIdSubWithOverflow, |
| 922 | BuiltinFnIdMulWithOverflow, | 933 | BuiltinFnIdMulWithOverflow, |
| 934 | BuiltinFnIdCInclude, | ||
| 935 | BuiltinFnIdCDefine, | ||
| 936 | BuiltinFnIdCUndef, | ||
| 923 | }; | 937 | }; |
| 924 | 938 | ||
| 925 | struct BuiltinFnEntry { | 939 | struct BuiltinFnEntry { |
| ... | @@ -1051,6 +1065,7 @@ struct BlockContext { | ... | @@ -1051,6 +1065,7 @@ struct BlockContext { |
| 1051 | ZigList<VariableTableEntry *> variable_list; | 1065 | ZigList<VariableTableEntry *> variable_list; |
| 1052 | AstNode *parent_loop_node; | 1066 | AstNode *parent_loop_node; |
| 1053 | LLVMZigDIScope *di_scope; | 1067 | LLVMZigDIScope *di_scope; |
| 1068 | Buf *c_import_buf; | ||
| 1054 | }; | 1069 | }; |
| 1055 | 1070 | ||
| 1056 | #endif | 1071 | #endif |
src/analyze.cpp+102-14| ... | @@ -21,6 +21,8 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B | ... | @@ -21,6 +21,8 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 21 | AstNode *node); | 21 | AstNode *node); |
| 22 | static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, | 22 | static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, |
| 23 | BlockContext *context, AstNode *node, Buf *err_name); | 23 | BlockContext *context, AstNode *node, Buf *err_name); |
| 24 | static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, | ||
| 25 | TypeTableEntry *expected_type, AstNode *node); | ||
| 24 | 26 | ||
| 25 | static AstNode *first_executing_node(AstNode *node) { | 27 | static AstNode *first_executing_node(AstNode *node) { |
| 26 | switch (node->type) { | 28 | switch (node->type) { |
| ... | @@ -54,7 +56,8 @@ static AstNode *first_executing_node(AstNode *node) { | ... | @@ -54,7 +56,8 @@ static AstNode *first_executing_node(AstNode *node) { |
| 54 | case NodeTypeCharLiteral: | 56 | case NodeTypeCharLiteral: |
| 55 | case NodeTypeSymbol: | 57 | case NodeTypeSymbol: |
| 56 | case NodeTypePrefixOpExpr: | 58 | case NodeTypePrefixOpExpr: |
| 57 | case NodeTypeUse: | 59 | case NodeTypeImport: |
| 60 | case NodeTypeCImport: | ||
| 58 | case NodeTypeBoolLiteral: | 61 | case NodeTypeBoolLiteral: |
| 59 | case NodeTypeNullLiteral: | 62 | case NodeTypeNullLiteral: |
| 60 | case NodeTypeUndefinedLiteral: | 63 | case NodeTypeUndefinedLiteral: |
| ... | @@ -1018,6 +1021,25 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo | ... | @@ -1018,6 +1021,25 @@ static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNo |
| 1018 | } | 1021 | } |
| 1019 | } | 1022 | } |
| 1020 | 1023 | ||
| 1024 | static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { | ||
| 1025 | assert(node->type == NodeTypeCImport); | ||
| 1026 | |||
| 1027 | AstNode *block_node = node->data.c_import.block; | ||
| 1028 | |||
| 1029 | BlockContext *child_context = new_block_context(node, import->block_context); | ||
| 1030 | child_context->c_import_buf = buf_alloc(); | ||
| 1031 | |||
| 1032 | TypeTableEntry *resolved_type = analyze_block_expr(g, import, child_context, | ||
| 1033 | g->builtin_types.entry_void, block_node); | ||
| 1034 | |||
| 1035 | if (resolved_type->id == TypeTableEntryIdInvalid) { | ||
| 1036 | return; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | fprintf(stderr, "c import buf:\n%s\n", buf_ptr(child_context->c_import_buf)); | ||
| 1040 | zig_panic("TODO"); | ||
| 1041 | } | ||
| 1042 | |||
| 1021 | static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 1043 | static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1022 | switch (node->type) { | 1044 | switch (node->type) { |
| 1023 | case NodeTypeFnProto: | 1045 | case NodeTypeFnProto: |
| ... | @@ -1053,9 +1075,12 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -1053,9 +1075,12 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 1053 | case NodeTypeErrorValueDecl: | 1075 | case NodeTypeErrorValueDecl: |
| 1054 | resolve_error_value_decl(g, import, node); | 1076 | resolve_error_value_decl(g, import, node); |
| 1055 | break; | 1077 | break; |
| 1056 | case NodeTypeUse: | 1078 | case NodeTypeImport: |
| 1057 | // nothing to do here | 1079 | // nothing to do here |
| 1058 | break; | 1080 | break; |
| 1081 | case NodeTypeCImport: | ||
| 1082 | resolve_c_import_decl(g, import, node); | ||
| 1083 | break; | ||
| 1059 | case NodeTypeFnDef: | 1084 | case NodeTypeFnDef: |
| 1060 | case NodeTypeDirective: | 1085 | case NodeTypeDirective: |
| 1061 | case NodeTypeParamDecl: | 1086 | case NodeTypeParamDecl: |
| ... | @@ -1501,6 +1526,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { | ... | @@ -1501,6 +1526,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { |
| 1501 | 1526 | ||
| 1502 | if (parent) { | 1527 | if (parent) { |
| 1503 | context->parent_loop_node = parent->parent_loop_node; | 1528 | context->parent_loop_node = parent->parent_loop_node; |
| 1529 | context->c_import_buf = parent->c_import_buf; | ||
| 1504 | } | 1530 | } |
| 1505 | 1531 | ||
| 1506 | if (node && node->type == NodeTypeFnDef) { | 1532 | if (node && node->type == NodeTypeFnDef) { |
| ... | @@ -1997,7 +2023,7 @@ static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNo | ... | @@ -1997,7 +2023,7 @@ static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNo |
| 1997 | } | 2023 | } |
| 1998 | } | 2024 | } |
| 1999 | 2025 | ||
| 2000 | static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *node, | 2026 | static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *node, |
| 2001 | bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2, | 2027 | bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2, |
| 2002 | TypeTableEntry *resolved_type) | 2028 | TypeTableEntry *resolved_type) |
| 2003 | { | 2029 | { |
| ... | @@ -2521,7 +2547,7 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block | ... | @@ -2521,7 +2547,7 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block |
| 2521 | if (name) { | 2547 | if (name) { |
| 2522 | buf_init_from_buf(&variable_entry->name, name); | 2548 | buf_init_from_buf(&variable_entry->name, name); |
| 2523 | VariableTableEntry *existing_var; | 2549 | VariableTableEntry *existing_var; |
| 2524 | 2550 | ||
| 2525 | if (context->fn_entry) { | 2551 | if (context->fn_entry) { |
| 2526 | existing_var = find_local_variable(context, name); | 2552 | existing_var = find_local_variable(context, name); |
| 2527 | } else { | 2553 | } else { |
| ... | @@ -3396,6 +3422,47 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry | ... | @@ -3396,6 +3422,47 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 3396 | return resolve_expr_const_val_as_type(g, node, type_entry); | 3422 | return resolve_expr_const_val_as_type(g, node, type_entry); |
| 3397 | } | 3423 | } |
| 3398 | } | 3424 | } |
| 3425 | case BuiltinFnIdCInclude: | ||
| 3426 | { | ||
| 3427 | if (!context->c_import_buf) { | ||
| 3428 | add_node_error(g, node, buf_sprintf("@c_include valid only in c_import blocks")); | ||
| 3429 | return g->builtin_types.entry_invalid; | ||
| 3430 | } | ||
| 3431 | |||
| 3432 | AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; | ||
| 3433 | TypeTableEntry *str_type = get_unknown_size_array_type(g, g->builtin_types.entry_u8, true); | ||
| 3434 | TypeTableEntry *resolved_type = analyze_expression(g, import, context, str_type, *str_node); | ||
| 3435 | |||
| 3436 | if (resolved_type->id == TypeTableEntryIdInvalid) { | ||
| 3437 | return resolved_type; | ||
| 3438 | } | ||
| 3439 | |||
| 3440 | ConstExprValue *const_str_val = &get_resolved_expr(*str_node)->const_val; | ||
| 3441 | |||
| 3442 | if (!const_str_val->ok) { | ||
| 3443 | add_node_error(g, *str_node, buf_sprintf("@c_include requires constant expression")); | ||
| 3444 | return g->builtin_types.entry_void; | ||
| 3445 | } | ||
| 3446 | |||
| 3447 | buf_appendf(context->c_import_buf, "#include \""); | ||
| 3448 | ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0]; | ||
| 3449 | uint64_t len = ptr_field->data.x_ptr.len; | ||
| 3450 | for (uint64_t i = 0; i < len; i += 1) { | ||
| 3451 | ConstExprValue *char_val = ptr_field->data.x_ptr.ptr[i]; | ||
| 3452 | uint64_t big_c = char_val->data.x_bignum.data.x_uint; | ||
| 3453 | assert(big_c <= UINT8_MAX); | ||
| 3454 | uint8_t c = big_c; | ||
| 3455 | buf_appendf(context->c_import_buf, "%c", c); | ||
| 3456 | } | ||
| 3457 | buf_appendf(context->c_import_buf, "\"\n"); | ||
| 3458 | |||
| 3459 | return g->builtin_types.entry_void; | ||
| 3460 | } | ||
| 3461 | case BuiltinFnIdCDefine: | ||
| 3462 | zig_panic("TODO"); | ||
| 3463 | case BuiltinFnIdCUndef: | ||
| 3464 | zig_panic("TODO"); | ||
| 3465 | |||
| 3399 | } | 3466 | } |
| 3400 | zig_unreachable(); | 3467 | zig_unreachable(); |
| 3401 | } | 3468 | } |
| ... | @@ -4038,7 +4105,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, | ... | @@ -4038,7 +4105,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 4038 | case NodeTypeRoot: | 4105 | case NodeTypeRoot: |
| 4039 | case NodeTypeRootExportDecl: | 4106 | case NodeTypeRootExportDecl: |
| 4040 | case NodeTypeFnDef: | 4107 | case NodeTypeFnDef: |
| 4041 | case NodeTypeUse: | 4108 | case NodeTypeImport: |
| 4109 | case NodeTypeCImport: | ||
| 4042 | case NodeTypeLabel: | 4110 | case NodeTypeLabel: |
| 4043 | case NodeTypeStructDecl: | 4111 | case NodeTypeStructDecl: |
| 4044 | case NodeTypeStructField: | 4112 | case NodeTypeStructField: |
| ... | @@ -4140,7 +4208,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -4140,7 +4208,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 4140 | break; | 4208 | break; |
| 4141 | } | 4209 | } |
| 4142 | case NodeTypeRootExportDecl: | 4210 | case NodeTypeRootExportDecl: |
| 4143 | case NodeTypeUse: | 4211 | case NodeTypeImport: |
| 4212 | case NodeTypeCImport: | ||
| 4144 | case NodeTypeVariableDeclaration: | 4213 | case NodeTypeVariableDeclaration: |
| 4145 | case NodeTypeErrorValueDecl: | 4214 | case NodeTypeErrorValueDecl: |
| 4146 | case NodeTypeFnProto: | 4215 | case NodeTypeFnProto: |
| ... | @@ -4340,7 +4409,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode | ... | @@ -4340,7 +4409,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 4340 | case NodeTypeFnDecl: | 4409 | case NodeTypeFnDecl: |
| 4341 | case NodeTypeParamDecl: | 4410 | case NodeTypeParamDecl: |
| 4342 | case NodeTypeDirective: | 4411 | case NodeTypeDirective: |
| 4343 | case NodeTypeUse: | 4412 | case NodeTypeImport: |
| 4413 | case NodeTypeCImport: | ||
| 4344 | case NodeTypeLabel: | 4414 | case NodeTypeLabel: |
| 4345 | case NodeTypeStructDecl: | 4415 | case NodeTypeStructDecl: |
| 4346 | case NodeTypeStructField: | 4416 | case NodeTypeStructField: |
| ... | @@ -4486,9 +4556,24 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast | ... | @@ -4486,9 +4556,24 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 4486 | case NodeTypeRootExportDecl: | 4556 | case NodeTypeRootExportDecl: |
| 4487 | resolve_top_level_decl(g, import, node); | 4557 | resolve_top_level_decl(g, import, node); |
| 4488 | break; | 4558 | break; |
| 4489 | case NodeTypeUse: | 4559 | case NodeTypeImport: |
| 4490 | // already taken care of | 4560 | // already taken care of |
| 4491 | break; | 4561 | break; |
| 4562 | case NodeTypeCImport: | ||
| 4563 | { | ||
| 4564 | TopLevelDecl *decl_node = &node->data.c_import.top_level_decl; | ||
| 4565 | decl_node->deps.init(1); | ||
| 4566 | collect_expr_decl_deps(g, import, node->data.c_import.block, decl_node); | ||
| 4567 | |||
| 4568 | decl_node->name = buf_sprintf("c_import_%" PRIu32, node->create_index); | ||
| 4569 | decl_node->import = import; | ||
| 4570 | if (decl_node->deps.size() > 0) { | ||
| 4571 | g->unresolved_top_level_decls.put(decl_node->name, node); | ||
| 4572 | } else { | ||
| 4573 | resolve_top_level_decl(g, import, node); | ||
| 4574 | } | ||
| 4575 | break; | ||
| 4576 | } | ||
| 4492 | case NodeTypeErrorValueDecl: | 4577 | case NodeTypeErrorValueDecl: |
| 4493 | // error value declarations do not depend on other top level decls | 4578 | // error value declarations do not depend on other top level decls |
| 4494 | resolve_top_level_decl(g, import, node); | 4579 | resolve_top_level_decl(g, import, node); |
| ... | @@ -4619,15 +4704,15 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -4619,15 +4704,15 @@ void semantic_analyze(CodeGen *g) { |
| 4619 | 4704 | ||
| 4620 | for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { | 4705 | for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { |
| 4621 | AstNode *child = import->root->data.root.top_level_decls.at(i); | 4706 | AstNode *child = import->root->data.root.top_level_decls.at(i); |
| 4622 | if (child->type == NodeTypeUse) { | 4707 | if (child->type == NodeTypeImport) { |
| 4623 | for (int i = 0; i < child->data.use.directives->length; i += 1) { | 4708 | for (int i = 0; i < child->data.import.directives->length; i += 1) { |
| 4624 | AstNode *directive_node = child->data.use.directives->at(i); | 4709 | AstNode *directive_node = child->data.import.directives->at(i); |
| 4625 | Buf *name = &directive_node->data.directive.name; | 4710 | Buf *name = &directive_node->data.directive.name; |
| 4626 | add_node_error(g, directive_node, | 4711 | add_node_error(g, directive_node, |
| 4627 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); | 4712 | buf_sprintf("invalid directive: '%s'", buf_ptr(name))); |
| 4628 | } | 4713 | } |
| 4629 | 4714 | ||
| 4630 | ImportTableEntry *target_import = child->data.use.import; | 4715 | ImportTableEntry *target_import = child->data.import.import; |
| 4631 | assert(target_import); | 4716 | assert(target_import); |
| 4632 | 4717 | ||
| 4633 | target_import->importers.append({import, child}); | 4718 | target_import->importers.append({import, child}); |
| ... | @@ -4760,7 +4845,8 @@ Expr *get_resolved_expr(AstNode *node) { | ... | @@ -4760,7 +4845,8 @@ Expr *get_resolved_expr(AstNode *node) { |
| 4760 | case NodeTypeFnDecl: | 4845 | case NodeTypeFnDecl: |
| 4761 | case NodeTypeParamDecl: | 4846 | case NodeTypeParamDecl: |
| 4762 | case NodeTypeDirective: | 4847 | case NodeTypeDirective: |
| 4763 | case NodeTypeUse: | 4848 | case NodeTypeImport: |
| 4849 | case NodeTypeCImport: | ||
| 4764 | case NodeTypeStructDecl: | 4850 | case NodeTypeStructDecl: |
| 4765 | case NodeTypeStructField: | 4851 | case NodeTypeStructField: |
| 4766 | case NodeTypeStructValueField: | 4852 | case NodeTypeStructValueField: |
| ... | @@ -4780,6 +4866,8 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { | ... | @@ -4780,6 +4866,8 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 4780 | return &node->data.struct_decl.top_level_decl; | 4866 | return &node->data.struct_decl.top_level_decl; |
| 4781 | case NodeTypeErrorValueDecl: | 4867 | case NodeTypeErrorValueDecl: |
| 4782 | return &node->data.error_value_decl.top_level_decl; | 4868 | return &node->data.error_value_decl.top_level_decl; |
| 4869 | case NodeTypeCImport: | ||
| 4870 | return &node->data.c_import.top_level_decl; | ||
| 4783 | case NodeTypeNumberLiteral: | 4871 | case NodeTypeNumberLiteral: |
| 4784 | case NodeTypeReturnExpr: | 4872 | case NodeTypeReturnExpr: |
| 4785 | case NodeTypeBinOpExpr: | 4873 | case NodeTypeBinOpExpr: |
| ... | @@ -4808,7 +4896,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { | ... | @@ -4808,7 +4896,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 4808 | case NodeTypeStringLiteral: | 4896 | case NodeTypeStringLiteral: |
| 4809 | case NodeTypeCharLiteral: | 4897 | case NodeTypeCharLiteral: |
| 4810 | case NodeTypeSymbol: | 4898 | case NodeTypeSymbol: |
| 4811 | case NodeTypeUse: | 4899 | case NodeTypeImport: |
| 4812 | case NodeTypeBoolLiteral: | 4900 | case NodeTypeBoolLiteral: |
| 4813 | case NodeTypeNullLiteral: | 4901 | case NodeTypeNullLiteral: |
| 4814 | case NodeTypeUndefinedLiteral: | 4902 | case NodeTypeUndefinedLiteral: |
src/codegen.cpp+13-6| ... | @@ -177,6 +177,9 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { | ... | @@ -177,6 +177,9 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 177 | switch (builtin_fn->id) { | 177 | switch (builtin_fn->id) { |
| 178 | case BuiltinFnIdInvalid: | 178 | case BuiltinFnIdInvalid: |
| 179 | case BuiltinFnIdTypeof: | 179 | case BuiltinFnIdTypeof: |
| 180 | case BuiltinFnIdCInclude: | ||
| 181 | case BuiltinFnIdCDefine: | ||
| 182 | case BuiltinFnIdCUndef: | ||
| 180 | zig_unreachable(); | 183 | zig_unreachable(); |
| 181 | case BuiltinFnIdAddWithOverflow: | 184 | case BuiltinFnIdAddWithOverflow: |
| 182 | case BuiltinFnIdSubWithOverflow: | 185 | case BuiltinFnIdSubWithOverflow: |
| ... | @@ -2250,7 +2253,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { | ... | @@ -2250,7 +2253,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 2250 | case NodeTypeFnDecl: | 2253 | case NodeTypeFnDecl: |
| 2251 | case NodeTypeParamDecl: | 2254 | case NodeTypeParamDecl: |
| 2252 | case NodeTypeDirective: | 2255 | case NodeTypeDirective: |
| 2253 | case NodeTypeUse: | 2256 | case NodeTypeImport: |
| 2257 | case NodeTypeCImport: | ||
| 2254 | case NodeTypeStructDecl: | 2258 | case NodeTypeStructDecl: |
| 2255 | case NodeTypeStructField: | 2259 | case NodeTypeStructField: |
| 2256 | case NodeTypeStructValueField: | 2260 | case NodeTypeStructValueField: |
| ... | @@ -2930,6 +2934,9 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -2930,6 +2934,9 @@ static void define_builtin_fns(CodeGen *g) { |
| 2930 | create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4); | 2934 | create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4); |
| 2931 | create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4); | 2935 | create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4); |
| 2932 | create_builtin_fn_with_arg_count(g, BuiltinFnIdMulWithOverflow, "mul_with_overflow", 4); | 2936 | create_builtin_fn_with_arg_count(g, BuiltinFnIdMulWithOverflow, "mul_with_overflow", 4); |
| 2937 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCInclude, "c_include", 1); | ||
| 2938 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2); | ||
| 2939 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1); | ||
| 2933 | } | 2940 | } |
| 2934 | 2941 | ||
| 2935 | 2942 | ||
| ... | @@ -3138,8 +3145,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, | ... | @@ -3138,8 +3145,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 3138 | } | 3145 | } |
| 3139 | } | 3146 | } |
| 3140 | } | 3147 | } |
| 3141 | } else if (top_level_decl->type == NodeTypeUse) { | 3148 | } else if (top_level_decl->type == NodeTypeImport) { |
| 3142 | Buf *import_target_path = &top_level_decl->data.use.path; | 3149 | Buf *import_target_path = &top_level_decl->data.import.path; |
| 3143 | Buf full_path = BUF_INIT; | 3150 | Buf full_path = BUF_INIT; |
| 3144 | Buf *import_code = buf_alloc(); | 3151 | Buf *import_code = buf_alloc(); |
| 3145 | bool found_it = false; | 3152 | bool found_it = false; |
| ... | @@ -3163,7 +3170,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, | ... | @@ -3163,7 +3170,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 3163 | auto entry = g->import_table.maybe_get(abs_full_path); | 3170 | auto entry = g->import_table.maybe_get(abs_full_path); |
| 3164 | if (entry) { | 3171 | if (entry) { |
| 3165 | found_it = true; | 3172 | found_it = true; |
| 3166 | top_level_decl->data.use.import = entry->value; | 3173 | top_level_decl->data.import.import = entry->value; |
| 3167 | } else { | 3174 | } else { |
| 3168 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { | 3175 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { |
| 3169 | if (err == ErrorFileNotFound) { | 3176 | if (err == ErrorFileNotFound) { |
| ... | @@ -3175,8 +3182,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, | ... | @@ -3175,8 +3182,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 3175 | goto done_looking_at_imports; | 3182 | goto done_looking_at_imports; |
| 3176 | } | 3183 | } |
| 3177 | } | 3184 | } |
| 3178 | top_level_decl->data.use.import = codegen_add_code(g, | 3185 | top_level_decl->data.import.import = codegen_add_code(g, |
| 3179 | abs_full_path, search_path, &top_level_decl->data.use.path, import_code); | 3186 | abs_full_path, search_path, &top_level_decl->data.import.path, import_code); |
| 3180 | found_it = true; | 3187 | found_it = true; |
| 3181 | } | 3188 | } |
| 3182 | break; | 3189 | break; |
src/parser.cpp+47-15| ... | @@ -123,8 +123,10 @@ const char *node_type_str(NodeType node_type) { | ... | @@ -123,8 +123,10 @@ const char *node_type_str(NodeType node_type) { |
| 123 | return "Symbol"; | 123 | return "Symbol"; |
| 124 | case NodeTypePrefixOpExpr: | 124 | case NodeTypePrefixOpExpr: |
| 125 | return "PrefixOpExpr"; | 125 | return "PrefixOpExpr"; |
| 126 | case NodeTypeUse: | 126 | case NodeTypeImport: |
| 127 | return "Use"; | 127 | return "Import"; |
| 128 | case NodeTypeCImport: | ||
| 129 | return "CImport"; | ||
| 128 | case NodeTypeBoolLiteral: | 130 | case NodeTypeBoolLiteral: |
| 129 | return "BoolLiteral"; | 131 | return "BoolLiteral"; |
| 130 | case NodeTypeNullLiteral: | 132 | case NodeTypeNullLiteral: |
| ... | @@ -329,8 +331,12 @@ void ast_print(AstNode *node, int indent) { | ... | @@ -329,8 +331,12 @@ void ast_print(AstNode *node, int indent) { |
| 329 | case NodeTypeSymbol: | 331 | case NodeTypeSymbol: |
| 330 | fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); | 332 | fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); |
| 331 | break; | 333 | break; |
| 332 | case NodeTypeUse: | 334 | case NodeTypeImport: |
| 333 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path)); | 335 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path)); |
| 336 | break; | ||
| 337 | case NodeTypeCImport: | ||
| 338 | fprintf(stderr, "%s\n", node_type_str(node->type)); | ||
| 339 | ast_print(node->data.c_import.block, indent + 2); | ||
| 334 | break; | 340 | break; |
| 335 | case NodeTypeBoolLiteral: | 341 | case NodeTypeBoolLiteral: |
| 336 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), | 342 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), |
| ... | @@ -2768,19 +2774,35 @@ static AstNode *ast_parse_import(ParseContext *pc, int *token_index, | ... | @@ -2768,19 +2774,35 @@ static AstNode *ast_parse_import(ParseContext *pc, int *token_index, |
| 2768 | return nullptr; | 2774 | return nullptr; |
| 2769 | *token_index += 1; | 2775 | *token_index += 1; |
| 2770 | 2776 | ||
| 2771 | Token *use_name = &pc->tokens->at(*token_index); | 2777 | Token *import_name = ast_eat_token(pc, token_index, TokenIdStringLiteral); |
| 2772 | *token_index += 1; | ||
| 2773 | ast_expect_token(pc, use_name, TokenIdStringLiteral); | ||
| 2774 | 2778 | ||
| 2775 | Token *semicolon = &pc->tokens->at(*token_index); | 2779 | ast_eat_token(pc, token_index, TokenIdSemicolon); |
| 2780 | |||
| 2781 | AstNode *node = ast_create_node(pc, NodeTypeImport, import_kw); | ||
| 2782 | node->data.import.visib_mod = visib_mod; | ||
| 2783 | node->data.import.directives = directives; | ||
| 2784 | |||
| 2785 | parse_string_literal(pc, import_name, &node->data.import.path, nullptr, nullptr); | ||
| 2786 | normalize_parent_ptrs(node); | ||
| 2787 | return node; | ||
| 2788 | } | ||
| 2789 | |||
| 2790 | /* | ||
| 2791 | CImportDecl : "c_import" Block | ||
| 2792 | */ | ||
| 2793 | static AstNode *ast_parse_c_import(ParseContext *pc, int *token_index, | ||
| 2794 | ZigList<AstNode*> *directives, VisibMod visib_mod) | ||
| 2795 | { | ||
| 2796 | Token *c_import_kw = &pc->tokens->at(*token_index); | ||
| 2797 | if (c_import_kw->id != TokenIdKeywordCImport) | ||
| 2798 | return nullptr; | ||
| 2776 | *token_index += 1; | 2799 | *token_index += 1; |
| 2777 | ast_expect_token(pc, semicolon, TokenIdSemicolon); | ||
| 2778 | 2800 | ||
| 2779 | AstNode *node = ast_create_node(pc, NodeTypeUse, import_kw); | 2801 | AstNode *node = ast_create_node(pc, NodeTypeCImport, c_import_kw); |
| 2780 | node->data.use.visib_mod = visib_mod; | 2802 | node->data.c_import.visib_mod = visib_mod; |
| 2781 | node->data.use.directives = directives; | 2803 | node->data.c_import.directives = directives; |
| 2804 | node->data.c_import.block = ast_parse_block(pc, token_index, true); | ||
| 2782 | 2805 | ||
| 2783 | parse_string_literal(pc, use_name, &node->data.use.path, nullptr, nullptr); | ||
| 2784 | normalize_parent_ptrs(node); | 2806 | normalize_parent_ptrs(node); |
| 2785 | return node; | 2807 | return node; |
| 2786 | } | 2808 | } |
| ... | @@ -2953,6 +2975,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis | ... | @@ -2953,6 +2975,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 2953 | continue; | 2975 | continue; |
| 2954 | } | 2976 | } |
| 2955 | 2977 | ||
| 2978 | AstNode *c_import_node = ast_parse_c_import(pc, token_index, directives, visib_mod); | ||
| 2979 | if (c_import_node) { | ||
| 2980 | top_level_decls->append(c_import_node); | ||
| 2981 | continue; | ||
| 2982 | } | ||
| 2983 | |||
| 2956 | AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod); | 2984 | AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod); |
| 2957 | if (struct_node) { | 2985 | if (struct_node) { |
| 2958 | top_level_decls->append(struct_node); | 2986 | top_level_decls->append(struct_node); |
| ... | @@ -3103,8 +3131,12 @@ void normalize_parent_ptrs(AstNode *node) { | ... | @@ -3103,8 +3131,12 @@ void normalize_parent_ptrs(AstNode *node) { |
| 3103 | case NodeTypeFieldAccessExpr: | 3131 | case NodeTypeFieldAccessExpr: |
| 3104 | set_field(&node->data.field_access_expr.struct_expr); | 3132 | set_field(&node->data.field_access_expr.struct_expr); |
| 3105 | break; | 3133 | break; |
| 3106 | case NodeTypeUse: | 3134 | case NodeTypeImport: |
| 3107 | set_list_fields(node->data.use.directives); | 3135 | set_list_fields(node->data.import.directives); |
| 3136 | break; | ||
| 3137 | case NodeTypeCImport: | ||
| 3138 | set_list_fields(node->data.c_import.directives); | ||
| 3139 | set_field(&node->data.c_import.block); | ||
| 3108 | break; | 3140 | break; |
| 3109 | case NodeTypeBoolLiteral: | 3141 | case NodeTypeBoolLiteral: |
| 3110 | // none | 3142 | // none |
src/tokenizer.cpp+3| ... | @@ -211,6 +211,8 @@ static void end_token(Tokenize *t) { | ... | @@ -211,6 +211,8 @@ static void end_token(Tokenize *t) { |
| 211 | t->cur_tok->id = TokenIdKeywordPub; | 211 | t->cur_tok->id = TokenIdKeywordPub; |
| 212 | } else if (mem_eql_str(token_mem, token_len, "export")) { | 212 | } else if (mem_eql_str(token_mem, token_len, "export")) { |
| 213 | t->cur_tok->id = TokenIdKeywordExport; | 213 | t->cur_tok->id = TokenIdKeywordExport; |
| 214 | } else if (mem_eql_str(token_mem, token_len, "c_import")) { | ||
| 215 | t->cur_tok->id = TokenIdKeywordCImport; | ||
| 214 | } else if (mem_eql_str(token_mem, token_len, "import")) { | 216 | } else if (mem_eql_str(token_mem, token_len, "import")) { |
| 215 | t->cur_tok->id = TokenIdKeywordImport; | 217 | t->cur_tok->id = TokenIdKeywordImport; |
| 216 | } else if (mem_eql_str(token_mem, token_len, "true")) { | 218 | } else if (mem_eql_str(token_mem, token_len, "true")) { |
| ... | @@ -1041,6 +1043,7 @@ const char * token_name(TokenId id) { | ... | @@ -1041,6 +1043,7 @@ const char * token_name(TokenId id) { |
| 1041 | case TokenIdKeywordPub: return "pub"; | 1043 | case TokenIdKeywordPub: return "pub"; |
| 1042 | case TokenIdKeywordExport: return "export"; | 1044 | case TokenIdKeywordExport: return "export"; |
| 1043 | case TokenIdKeywordImport: return "import"; | 1045 | case TokenIdKeywordImport: return "import"; |
| 1046 | case TokenIdKeywordCImport: return "c_import"; | ||
| 1044 | case TokenIdKeywordTrue: return "true"; | 1047 | case TokenIdKeywordTrue: return "true"; |
| 1045 | case TokenIdKeywordFalse: return "false"; | 1048 | case TokenIdKeywordFalse: return "false"; |
| 1046 | case TokenIdKeywordIf: return "if"; | 1049 | case TokenIdKeywordIf: return "if"; |
src/tokenizer.hpp+1| ... | @@ -21,6 +21,7 @@ enum TokenId { | ... | @@ -21,6 +21,7 @@ enum TokenId { |
| 21 | TokenIdKeywordPub, | 21 | TokenIdKeywordPub, |
| 22 | TokenIdKeywordExport, | 22 | TokenIdKeywordExport, |
| 23 | TokenIdKeywordImport, | 23 | TokenIdKeywordImport, |
| 24 | TokenIdKeywordCImport, | ||
| 24 | TokenIdKeywordTrue, | 25 | TokenIdKeywordTrue, |
| 25 | TokenIdKeywordFalse, | 26 | TokenIdKeywordFalse, |
| 26 | TokenIdKeywordIf, | 27 | TokenIdKeywordIf, |