| 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 | 136 | NodeTypeArrayAccessExpr, |
| 137 | 137 | NodeTypeSliceExpr, |
| 138 | 138 | NodeTypeFieldAccessExpr, |
| 139 | NodeTypeUse, | |
| 139 | NodeTypeImport, | |
| 140 | NodeTypeCImport, | |
| 140 | 141 | NodeTypeBoolLiteral, |
| 141 | 142 | NodeTypeNullLiteral, |
| 142 | 143 | NodeTypeUndefinedLiteral, |
| ... | ... | @@ -410,7 +411,7 @@ struct AstNodePrefixOpExpr { |
| 410 | 411 | Expr resolved_expr; |
| 411 | 412 | }; |
| 412 | 413 | |
| 413 | struct AstNodeUse { | |
| 414 | struct AstNodeImport { | |
| 414 | 415 | Buf path; |
| 415 | 416 | ZigList<AstNode *> *directives; |
| 416 | 417 | VisibMod visib_mod; |
| ... | ... | @@ -419,6 +420,15 @@ struct AstNodeUse { |
| 419 | 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 | 432 | struct AstNodeIfBoolExpr { |
| 423 | 433 | AstNode *condition; |
| 424 | 434 | AstNode *then_block; |
| ... | ... | @@ -699,7 +709,8 @@ struct AstNode { |
| 699 | 709 | AstNodeFnCallExpr fn_call_expr; |
| 700 | 710 | AstNodeArrayAccessExpr array_access_expr; |
| 701 | 711 | AstNodeSliceExpr slice_expr; |
| 702 | AstNodeUse use; | |
| 712 | AstNodeImport import; | |
| 713 | AstNodeCImport c_import; | |
| 703 | 714 | AstNodeIfBoolExpr if_bool_expr; |
| 704 | 715 | AstNodeIfVarExpr if_var_expr; |
| 705 | 716 | AstNodeWhileExpr while_expr; |
| ... | ... | @@ -920,6 +931,9 @@ enum BuiltinFnId { |
| 920 | 931 | BuiltinFnIdAddWithOverflow, |
| 921 | 932 | BuiltinFnIdSubWithOverflow, |
| 922 | 933 | BuiltinFnIdMulWithOverflow, |
| 934 | BuiltinFnIdCInclude, | |
| 935 | BuiltinFnIdCDefine, | |
| 936 | BuiltinFnIdCUndef, | |
| 923 | 937 | }; |
| 924 | 938 | |
| 925 | 939 | struct BuiltinFnEntry { |
| ... | ... | @@ -1051,6 +1065,7 @@ struct BlockContext { |
| 1051 | 1065 | ZigList<VariableTableEntry *> variable_list; |
| 1052 | 1066 | AstNode *parent_loop_node; |
| 1053 | 1067 | LLVMZigDIScope *di_scope; |
| 1068 | Buf *c_import_buf; | |
| 1054 | 1069 | }; |
| 1055 | 1070 | |
| 1056 | 1071 | #endif |
src/analyze.cpp+102-14| ... | ... | @@ -21,6 +21,8 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B |
| 21 | 21 | AstNode *node); |
| 22 | 22 | static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import, |
| 23 | 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 | 27 | static AstNode *first_executing_node(AstNode *node) { |
| 26 | 28 | switch (node->type) { |
| ... | ... | @@ -54,7 +56,8 @@ static AstNode *first_executing_node(AstNode *node) { |
| 54 | 56 | case NodeTypeCharLiteral: |
| 55 | 57 | case NodeTypeSymbol: |
| 56 | 58 | case NodeTypePrefixOpExpr: |
| 57 | case NodeTypeUse: | |
| 59 | case NodeTypeImport: | |
| 60 | case NodeTypeCImport: | |
| 58 | 61 | case NodeTypeBoolLiteral: |
| 59 | 62 | case NodeTypeNullLiteral: |
| 60 | 63 | case NodeTypeUndefinedLiteral: |
| ... | ... | @@ -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 | 1043 | static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1022 | 1044 | switch (node->type) { |
| 1023 | 1045 | case NodeTypeFnProto: |
| ... | ... | @@ -1053,9 +1075,12 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 1053 | 1075 | case NodeTypeErrorValueDecl: |
| 1054 | 1076 | resolve_error_value_decl(g, import, node); |
| 1055 | 1077 | break; |
| 1056 | case NodeTypeUse: | |
| 1078 | case NodeTypeImport: | |
| 1057 | 1079 | // nothing to do here |
| 1058 | 1080 | break; |
| 1081 | case NodeTypeCImport: | |
| 1082 | resolve_c_import_decl(g, import, node); | |
| 1083 | break; | |
| 1059 | 1084 | case NodeTypeFnDef: |
| 1060 | 1085 | case NodeTypeDirective: |
| 1061 | 1086 | case NodeTypeParamDecl: |
| ... | ... | @@ -1501,6 +1526,7 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) { |
| 1501 | 1526 | |
| 1502 | 1527 | if (parent) { |
| 1503 | 1528 | context->parent_loop_node = parent->parent_loop_node; |
| 1529 | context->c_import_buf = parent->c_import_buf; | |
| 1504 | 1530 | } |
| 1505 | 1531 | |
| 1506 | 1532 | if (node && node->type == NodeTypeFnDef) { |
| ... | ... | @@ -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 | 2027 | bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2, |
| 2002 | 2028 | TypeTableEntry *resolved_type) |
| 2003 | 2029 | { |
| ... | ... | @@ -2521,7 +2547,7 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Block |
| 2521 | 2547 | if (name) { |
| 2522 | 2548 | buf_init_from_buf(&variable_entry->name, name); |
| 2523 | 2549 | VariableTableEntry *existing_var; |
| 2524 | ||
| 2550 | ||
| 2525 | 2551 | if (context->fn_entry) { |
| 2526 | 2552 | existing_var = find_local_variable(context, name); |
| 2527 | 2553 | } else { |
| ... | ... | @@ -3396,6 +3422,47 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 3396 | 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 | 3467 | zig_unreachable(); |
| 3401 | 3468 | } |
| ... | ... | @@ -4038,7 +4105,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 4038 | 4105 | case NodeTypeRoot: |
| 4039 | 4106 | case NodeTypeRootExportDecl: |
| 4040 | 4107 | case NodeTypeFnDef: |
| 4041 | case NodeTypeUse: | |
| 4108 | case NodeTypeImport: | |
| 4109 | case NodeTypeCImport: | |
| 4042 | 4110 | case NodeTypeLabel: |
| 4043 | 4111 | case NodeTypeStructDecl: |
| 4044 | 4112 | case NodeTypeStructField: |
| ... | ... | @@ -4140,7 +4208,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode |
| 4140 | 4208 | break; |
| 4141 | 4209 | } |
| 4142 | 4210 | case NodeTypeRootExportDecl: |
| 4143 | case NodeTypeUse: | |
| 4211 | case NodeTypeImport: | |
| 4212 | case NodeTypeCImport: | |
| 4144 | 4213 | case NodeTypeVariableDeclaration: |
| 4145 | 4214 | case NodeTypeErrorValueDecl: |
| 4146 | 4215 | case NodeTypeFnProto: |
| ... | ... | @@ -4340,7 +4409,8 @@ static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode |
| 4340 | 4409 | case NodeTypeFnDecl: |
| 4341 | 4410 | case NodeTypeParamDecl: |
| 4342 | 4411 | case NodeTypeDirective: |
| 4343 | case NodeTypeUse: | |
| 4412 | case NodeTypeImport: | |
| 4413 | case NodeTypeCImport: | |
| 4344 | 4414 | case NodeTypeLabel: |
| 4345 | 4415 | case NodeTypeStructDecl: |
| 4346 | 4416 | case NodeTypeStructField: |
| ... | ... | @@ -4486,9 +4556,24 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast |
| 4486 | 4556 | case NodeTypeRootExportDecl: |
| 4487 | 4557 | resolve_top_level_decl(g, import, node); |
| 4488 | 4558 | break; |
| 4489 | case NodeTypeUse: | |
| 4559 | case NodeTypeImport: | |
| 4490 | 4560 | // already taken care of |
| 4491 | 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 | 4577 | case NodeTypeErrorValueDecl: |
| 4493 | 4578 | // error value declarations do not depend on other top level decls |
| 4494 | 4579 | resolve_top_level_decl(g, import, node); |
| ... | ... | @@ -4619,15 +4704,15 @@ void semantic_analyze(CodeGen *g) { |
| 4619 | 4704 | |
| 4620 | 4705 | for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { |
| 4621 | 4706 | AstNode *child = import->root->data.root.top_level_decls.at(i); |
| 4622 | if (child->type == NodeTypeUse) { | |
| 4623 | for (int i = 0; i < child->data.use.directives->length; i += 1) { | |
| 4624 | AstNode *directive_node = child->data.use.directives->at(i); | |
| 4707 | if (child->type == NodeTypeImport) { | |
| 4708 | for (int i = 0; i < child->data.import.directives->length; i += 1) { | |
| 4709 | AstNode *directive_node = child->data.import.directives->at(i); | |
| 4625 | 4710 | Buf *name = &directive_node->data.directive.name; |
| 4626 | 4711 | add_node_error(g, directive_node, |
| 4627 | 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 | 4716 | assert(target_import); |
| 4632 | 4717 | |
| 4633 | 4718 | target_import->importers.append({import, child}); |
| ... | ... | @@ -4760,7 +4845,8 @@ Expr *get_resolved_expr(AstNode *node) { |
| 4760 | 4845 | case NodeTypeFnDecl: |
| 4761 | 4846 | case NodeTypeParamDecl: |
| 4762 | 4847 | case NodeTypeDirective: |
| 4763 | case NodeTypeUse: | |
| 4848 | case NodeTypeImport: | |
| 4849 | case NodeTypeCImport: | |
| 4764 | 4850 | case NodeTypeStructDecl: |
| 4765 | 4851 | case NodeTypeStructField: |
| 4766 | 4852 | case NodeTypeStructValueField: |
| ... | ... | @@ -4780,6 +4866,8 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 4780 | 4866 | return &node->data.struct_decl.top_level_decl; |
| 4781 | 4867 | case NodeTypeErrorValueDecl: |
| 4782 | 4868 | return &node->data.error_value_decl.top_level_decl; |
| 4869 | case NodeTypeCImport: | |
| 4870 | return &node->data.c_import.top_level_decl; | |
| 4783 | 4871 | case NodeTypeNumberLiteral: |
| 4784 | 4872 | case NodeTypeReturnExpr: |
| 4785 | 4873 | case NodeTypeBinOpExpr: |
| ... | ... | @@ -4808,7 +4896,7 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) { |
| 4808 | 4896 | case NodeTypeStringLiteral: |
| 4809 | 4897 | case NodeTypeCharLiteral: |
| 4810 | 4898 | case NodeTypeSymbol: |
| 4811 | case NodeTypeUse: | |
| 4899 | case NodeTypeImport: | |
| 4812 | 4900 | case NodeTypeBoolLiteral: |
| 4813 | 4901 | case NodeTypeNullLiteral: |
| 4814 | 4902 | case NodeTypeUndefinedLiteral: |
src/codegen.cpp+13-6| ... | ... | @@ -177,6 +177,9 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 177 | 177 | switch (builtin_fn->id) { |
| 178 | 178 | case BuiltinFnIdInvalid: |
| 179 | 179 | case BuiltinFnIdTypeof: |
| 180 | case BuiltinFnIdCInclude: | |
| 181 | case BuiltinFnIdCDefine: | |
| 182 | case BuiltinFnIdCUndef: | |
| 180 | 183 | zig_unreachable(); |
| 181 | 184 | case BuiltinFnIdAddWithOverflow: |
| 182 | 185 | case BuiltinFnIdSubWithOverflow: |
| ... | ... | @@ -2250,7 +2253,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) { |
| 2250 | 2253 | case NodeTypeFnDecl: |
| 2251 | 2254 | case NodeTypeParamDecl: |
| 2252 | 2255 | case NodeTypeDirective: |
| 2253 | case NodeTypeUse: | |
| 2256 | case NodeTypeImport: | |
| 2257 | case NodeTypeCImport: | |
| 2254 | 2258 | case NodeTypeStructDecl: |
| 2255 | 2259 | case NodeTypeStructField: |
| 2256 | 2260 | case NodeTypeStructValueField: |
| ... | ... | @@ -2930,6 +2934,9 @@ static void define_builtin_fns(CodeGen *g) { |
| 2930 | 2934 | create_builtin_fn_with_arg_count(g, BuiltinFnIdAddWithOverflow, "add_with_overflow", 4); |
| 2931 | 2935 | create_builtin_fn_with_arg_count(g, BuiltinFnIdSubWithOverflow, "sub_with_overflow", 4); |
| 2932 | 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 | 3145 | } |
| 3139 | 3146 | } |
| 3140 | 3147 | } |
| 3141 | } else if (top_level_decl->type == NodeTypeUse) { | |
| 3142 | Buf *import_target_path = &top_level_decl->data.use.path; | |
| 3148 | } else if (top_level_decl->type == NodeTypeImport) { | |
| 3149 | Buf *import_target_path = &top_level_decl->data.import.path; | |
| 3143 | 3150 | Buf full_path = BUF_INIT; |
| 3144 | 3151 | Buf *import_code = buf_alloc(); |
| 3145 | 3152 | bool found_it = false; |
| ... | ... | @@ -3163,7 +3170,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 3163 | 3170 | auto entry = g->import_table.maybe_get(abs_full_path); |
| 3164 | 3171 | if (entry) { |
| 3165 | 3172 | found_it = true; |
| 3166 | top_level_decl->data.use.import = entry->value; | |
| 3173 | top_level_decl->data.import.import = entry->value; | |
| 3167 | 3174 | } else { |
| 3168 | 3175 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { |
| 3169 | 3176 | if (err == ErrorFileNotFound) { |
| ... | ... | @@ -3175,8 +3182,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path, |
| 3175 | 3182 | goto done_looking_at_imports; |
| 3176 | 3183 | } |
| 3177 | 3184 | } |
| 3178 | top_level_decl->data.use.import = codegen_add_code(g, | |
| 3179 | abs_full_path, search_path, &top_level_decl->data.use.path, import_code); | |
| 3185 | top_level_decl->data.import.import = codegen_add_code(g, | |
| 3186 | abs_full_path, search_path, &top_level_decl->data.import.path, import_code); | |
| 3180 | 3187 | found_it = true; |
| 3181 | 3188 | } |
| 3182 | 3189 | break; |
src/parser.cpp+47-15| ... | ... | @@ -123,8 +123,10 @@ const char *node_type_str(NodeType node_type) { |
| 123 | 123 | return "Symbol"; |
| 124 | 124 | case NodeTypePrefixOpExpr: |
| 125 | 125 | return "PrefixOpExpr"; |
| 126 | case NodeTypeUse: | |
| 127 | return "Use"; | |
| 126 | case NodeTypeImport: | |
| 127 | return "Import"; | |
| 128 | case NodeTypeCImport: | |
| 129 | return "CImport"; | |
| 128 | 130 | case NodeTypeBoolLiteral: |
| 129 | 131 | return "BoolLiteral"; |
| 130 | 132 | case NodeTypeNullLiteral: |
| ... | ... | @@ -329,8 +331,12 @@ void ast_print(AstNode *node, int indent) { |
| 329 | 331 | case NodeTypeSymbol: |
| 330 | 332 | fprintf(stderr, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol)); |
| 331 | 333 | break; |
| 332 | case NodeTypeUse: | |
| 333 | fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.use.path)); | |
| 334 | case NodeTypeImport: | |
| 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 | 340 | break; |
| 335 | 341 | case NodeTypeBoolLiteral: |
| 336 | 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 | 2774 | return nullptr; |
| 2769 | 2775 | *token_index += 1; |
| 2770 | 2776 | |
| 2771 | Token *use_name = &pc->tokens->at(*token_index); | |
| 2772 | *token_index += 1; | |
| 2773 | ast_expect_token(pc, use_name, TokenIdStringLiteral); | |
| 2777 | Token *import_name = ast_eat_token(pc, token_index, 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 | 2799 | *token_index += 1; |
| 2777 | ast_expect_token(pc, semicolon, TokenIdSemicolon); | |
| 2778 | 2800 | |
| 2779 | AstNode *node = ast_create_node(pc, NodeTypeUse, import_kw); | |
| 2780 | node->data.use.visib_mod = visib_mod; | |
| 2781 | node->data.use.directives = directives; | |
| 2801 | AstNode *node = ast_create_node(pc, NodeTypeCImport, c_import_kw); | |
| 2802 | node->data.c_import.visib_mod = visib_mod; | |
| 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 | 2806 | normalize_parent_ptrs(node); |
| 2785 | 2807 | return node; |
| 2786 | 2808 | } |
| ... | ... | @@ -2953,6 +2975,12 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis |
| 2953 | 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 | 2984 | AstNode *struct_node = ast_parse_struct_decl(pc, token_index, directives, visib_mod); |
| 2957 | 2985 | if (struct_node) { |
| 2958 | 2986 | top_level_decls->append(struct_node); |
| ... | ... | @@ -3103,8 +3131,12 @@ void normalize_parent_ptrs(AstNode *node) { |
| 3103 | 3131 | case NodeTypeFieldAccessExpr: |
| 3104 | 3132 | set_field(&node->data.field_access_expr.struct_expr); |
| 3105 | 3133 | break; |
| 3106 | case NodeTypeUse: | |
| 3107 | set_list_fields(node->data.use.directives); | |
| 3134 | case NodeTypeImport: | |
| 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 | 3140 | break; |
| 3109 | 3141 | case NodeTypeBoolLiteral: |
| 3110 | 3142 | // none |
src/tokenizer.cpp+3| ... | ... | @@ -211,6 +211,8 @@ static void end_token(Tokenize *t) { |
| 211 | 211 | t->cur_tok->id = TokenIdKeywordPub; |
| 212 | 212 | } else if (mem_eql_str(token_mem, token_len, "export")) { |
| 213 | 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 | 216 | } else if (mem_eql_str(token_mem, token_len, "import")) { |
| 215 | 217 | t->cur_tok->id = TokenIdKeywordImport; |
| 216 | 218 | } else if (mem_eql_str(token_mem, token_len, "true")) { |
| ... | ... | @@ -1041,6 +1043,7 @@ const char * token_name(TokenId id) { |
| 1041 | 1043 | case TokenIdKeywordPub: return "pub"; |
| 1042 | 1044 | case TokenIdKeywordExport: return "export"; |
| 1043 | 1045 | case TokenIdKeywordImport: return "import"; |
| 1046 | case TokenIdKeywordCImport: return "c_import"; | |
| 1044 | 1047 | case TokenIdKeywordTrue: return "true"; |
| 1045 | 1048 | case TokenIdKeywordFalse: return "false"; |
| 1046 | 1049 | case TokenIdKeywordIf: return "if"; |
src/tokenizer.hpp+1| ... | ... | @@ -21,6 +21,7 @@ enum TokenId { |
| 21 | 21 | TokenIdKeywordPub, |
| 22 | 22 | TokenIdKeywordExport, |
| 23 | 23 | TokenIdKeywordImport, |
| 24 | TokenIdKeywordCImport, | |
| 24 | 25 | TokenIdKeywordTrue, |
| 25 | 26 | TokenIdKeywordFalse, |
| 26 | 27 | TokenIdKeywordIf, |