diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/all_types.hpp | 47 | ||||
| -rw-r--r-- | src/analyze.cpp | 47 | ||||
| -rw-r--r-- | src/ast_render.cpp | 3 | ||||
| -rw-r--r-- | src/buffer.hpp | 6 | ||||
| -rw-r--r-- | src/codegen.cpp | 9 | ||||
| -rw-r--r-- | src/dump_analysis.cpp | 393 | ||||
| -rw-r--r-- | src/ir.cpp | 54 | ||||
| -rw-r--r-- | src/main.cpp | 4 | ||||
| -rw-r--r-- | src/parser.cpp | 49 | ||||
| -rw-r--r-- | src/tokenizer.cpp | 53 | ||||
| -rw-r--r-- | src/tokenizer.hpp | 1 |
11 files changed, 615 insertions, 51 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp index 1119d2bf4e..c9f905118f 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -589,6 +589,7 @@ enum NodeType { NodeTypeIfErrorExpr, NodeTypeIfOptional, NodeTypeErrorSetDecl, + NodeTypeErrorSetField, NodeTypeResume, NodeTypeAwaitExpr, NodeTypeSuspend, @@ -612,16 +613,10 @@ enum FnInline { }; struct AstNodeFnProto { - VisibMod visib_mod; Buf *name; ZigList<AstNode *> params; AstNode *return_type; Token *return_var_token; - bool is_var_args; - bool is_extern; - bool is_export; - FnInline fn_inline; - CallingConvention cc; AstNode *fn_def_node; // populated if this is an extern declaration Buf *lib_name; @@ -629,8 +624,16 @@ struct AstNodeFnProto { AstNode *align_expr; // populated if the "section(S)" is present AstNode *section_expr; + Buf doc_comments; + FnInline fn_inline; + CallingConvention cc; + + VisibMod visib_mod; bool auto_err_set; + bool is_var_args; + bool is_extern; + bool is_export; }; struct AstNodeFnDef { @@ -642,6 +645,7 @@ struct AstNodeParamDecl { Buf *name; AstNode *type; Token *var_token; + Buf doc_comments; bool is_noalias; bool is_comptime; bool is_var_args; @@ -684,6 +688,7 @@ struct AstNodeVariableDeclaration { // populated if the "section(S)" is present AstNode *section_expr; Token *threadlocal_tok; + Buf doc_comments; VisibMod visib_mod; bool is_const; @@ -957,25 +962,35 @@ enum ContainerLayout { }; struct AstNodeContainerDecl { - ContainerKind kind; + AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) ZigList<AstNode *> fields; ZigList<AstNode *> decls; + + ContainerKind kind; ContainerLayout layout; - AstNode *init_arg_expr; // enum(T), struct(endianness), or union(T), or union(enum(T)) + bool auto_enum, is_root; // union(enum) }; +struct AstNodeErrorSetField { + Buf doc_comments; + AstNode *field_name; +}; + struct AstNodeErrorSetDecl { + // Each AstNode could be AstNodeErrorSetField or just AstNodeSymbolExpr to save memory ZigList<AstNode *> decls; }; struct AstNodeStructField { - VisibMod visib_mod; Buf *name; AstNode *type; AstNode *value; // populated if the "align(A)" is present AstNode *align_expr; + Buf doc_comments; + + VisibMod visib_mod; }; struct AstNodeStringLiteral { @@ -1126,6 +1141,7 @@ struct AstNode { AstNodeInferredArrayType inferred_array_type; AstNodeErrorType error_type; AstNodeErrorSetDecl err_set_decl; + AstNodeErrorSetField err_set_field; AstNodeResumeExpr resume_expr; AstNodeAwaitExpr await_expr; AstNodeSuspend suspend; @@ -1274,9 +1290,10 @@ struct ZigTypeErrorUnion { }; struct ZigTypeErrorSet { - uint32_t err_count; ErrorTableEntry **errors; ZigFn *infer_fn; + uint32_t err_count; + bool incomplete; }; struct ZigTypeEnum { @@ -1306,6 +1323,15 @@ bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b); uint32_t tld_ptr_hash(const Tld *ptr); bool tld_ptr_eql(const Tld *a, const Tld *b); +uint32_t node_ptr_hash(const AstNode *ptr); +bool node_ptr_eql(const AstNode *a, const AstNode *b); + +uint32_t fn_ptr_hash(const ZigFn *ptr); +bool fn_ptr_eql(const ZigFn *a, const ZigFn *b); + +uint32_t err_ptr_hash(const ErrorTableEntry *ptr); +bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b); + struct ZigTypeUnion { AstNode *decl_node; TypeUnionField *fields; @@ -2120,6 +2146,7 @@ struct ErrorTableEntry { Buf name; uint32_t value; AstNode *decl_node; + ErrorTableEntry *other; // null, or another error decl that was merged into this ZigType *set_with_only_this_in_it; // If we generate a constant error name value for this error, we memoize it here. // The type of this is array diff --git a/src/analyze.cpp b/src/analyze.cpp index cca239c275..82b09175d3 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -913,7 +913,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { if (type_is_c_abi_int(g, fn_type_id->return_type)) { return false; } - if (g->zig_target->arch == ZigLLVM_x86_64) { + if (g->zig_target->arch == ZigLLVM_x86) { + X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); + return abi_class == X64CABIClass_MEMORY; + } else if (g->zig_target->arch == ZigLLVM_x86_64) { X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); return abi_class == X64CABIClass_MEMORY; } else if (target_is_arm(g->zig_target) || target_is_riscv(g->zig_target)) { @@ -1633,6 +1636,7 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) { err_set_type->data.error_set.err_count = 0; err_set_type->data.error_set.errors = nullptr; err_set_type->data.error_set.infer_fn = fn_entry; + err_set_type->data.error_set.incomplete = true; err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits; err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align; err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size; @@ -3572,6 +3576,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { case NodeTypeSuspend: case NodeTypeEnumLiteral: case NodeTypeAnyFrameType: + case NodeTypeErrorSetField: zig_unreachable(); } } @@ -4276,12 +4281,12 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node) { assert(err_set_type->id == ZigTypeIdErrorSet); ZigFn *infer_fn = err_set_type->data.error_set.infer_fn; - if (infer_fn != nullptr) { + if (infer_fn != nullptr && err_set_type->data.error_set.incomplete) { if (infer_fn->anal_state == FnAnalStateInvalid) { return false; } else if (infer_fn->anal_state == FnAnalStateReady) { analyze_fn_body(g, infer_fn); - if (err_set_type->data.error_set.infer_fn != nullptr) { + if (err_set_type->data.error_set.incomplete) { assert(g->errors.length != 0); return false; } @@ -4508,7 +4513,9 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { if (fn_type_id->return_type->id == ZigTypeIdErrorUnion) { ZigType *return_err_set_type = fn_type_id->return_type->data.error_union.err_set_type; - if (return_err_set_type->data.error_set.infer_fn != nullptr) { + if (return_err_set_type->data.error_set.infer_fn != nullptr && + return_err_set_type->data.error_set.incomplete) + { ZigType *inferred_err_set_type; if (fn->src_implicit_return_type->id == ZigTypeIdErrorSet) { inferred_err_set_type = fn->src_implicit_return_type; @@ -4521,14 +4528,16 @@ static void analyze_fn_ir(CodeGen *g, ZigFn *fn, AstNode *return_type_node) { return; } - if (inferred_err_set_type->data.error_set.infer_fn != nullptr) { + if (inferred_err_set_type->data.error_set.infer_fn != nullptr && + inferred_err_set_type->data.error_set.incomplete) + { if (!resolve_inferred_error_set(g, inferred_err_set_type, return_type_node)) { fn->anal_state = FnAnalStateInvalid; return; } } - return_err_set_type->data.error_set.infer_fn = nullptr; + return_err_set_type->data.error_set.incomplete = false; if (type_is_global_error_set(inferred_err_set_type)) { return_err_set_type->data.error_set.err_count = UINT32_MAX; } else { @@ -7319,6 +7328,30 @@ bool tld_ptr_eql(const Tld *a, const Tld *b) { return a == b; } +uint32_t node_ptr_hash(const AstNode *ptr) { + return hash_ptr((void*)ptr); +} + +bool node_ptr_eql(const AstNode *a, const AstNode *b) { + return a == b; +} + +uint32_t fn_ptr_hash(const ZigFn *ptr) { + return hash_ptr((void*)ptr); +} + +bool fn_ptr_eql(const ZigFn *a, const ZigFn *b) { + return a == b; +} + +uint32_t err_ptr_hash(const ErrorTableEntry *ptr) { + return hash_ptr((void*)ptr); +} + +bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b) { + return a == b; +} + ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name)); resolve_top_level_decl(codegen, tld, nullptr, false); @@ -7331,7 +7364,7 @@ ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { bool type_is_global_error_set(ZigType *err_set_type) { assert(err_set_type->id == ZigTypeIdErrorSet); - assert(err_set_type->data.error_set.infer_fn == nullptr); + assert(!err_set_type->data.error_set.incomplete); return err_set_type->data.error_set.err_count == UINT32_MAX; } diff --git a/src/ast_render.cpp b/src/ast_render.cpp index 537a74d7b1..18940c4b80 100644 --- a/src/ast_render.cpp +++ b/src/ast_render.cpp @@ -266,6 +266,8 @@ static const char *node_type_str(NodeType node_type) { return "AnyFrameType"; case NodeTypeEnumLiteral: return "EnumLiteral"; + case NodeTypeErrorSetField: + return "ErrorSetField"; } zig_unreachable(); } @@ -1177,6 +1179,7 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) { case NodeTypeTestDecl: case NodeTypeStructField: case NodeTypeUsingNamespace: + case NodeTypeErrorSetField: zig_panic("TODO more ast rendering"); } } diff --git a/src/buffer.hpp b/src/buffer.hpp index 251b5c2f27..6442e4f123 100644 --- a/src/buffer.hpp +++ b/src/buffer.hpp @@ -38,6 +38,12 @@ static inline char *buf_ptr(Buf *buf) { return buf->list.items; } +static inline const char *buf_ptr(const Buf *buf) { + assert(buf); + assert(buf->list.length); + return buf->list.items; +} + static inline void buf_resize(Buf *buf, size_t new_len) { buf->list.resize(new_len + 1); buf->list.at(buf_len(buf)) = 0; diff --git a/src/codegen.cpp b/src/codegen.cpp index 88ff179ca7..3dbd0b8538 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8727,6 +8727,9 @@ static void init(CodeGen *g) { // Be aware of https://github.com/ziglang/zig/issues/3275 target_specific_cpu_args = ""; target_specific_features = riscv_default_features; + } else if (g->zig_target->arch == ZigLLVM_x86) { + target_specific_cpu_args = "pentium4"; + target_specific_features = ""; } else { target_specific_cpu_args = ""; target_specific_features = ""; @@ -10355,15 +10358,15 @@ void codegen_build_and_link(CodeGen *g) { } } if (g->enable_doc_generation) { - Buf *doc_dir_path = buf_sprintf("%s" OS_SEP "doc", buf_ptr(g->output_dir)); + Buf *doc_dir_path = buf_sprintf("%s" OS_SEP "docs", buf_ptr(g->output_dir)); if ((err = os_make_path(doc_dir_path))) { fprintf(stderr, "Unable to create directory %s: %s\n", buf_ptr(doc_dir_path), err_str(err)); exit(1); } - Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "doc" OS_SEP "index.html", + Buf *index_html_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "docs" OS_SEP "index.html", buf_ptr(g->zig_std_dir)); Buf *index_html_dest_path = buf_sprintf("%s" OS_SEP "index.html", buf_ptr(doc_dir_path)); - Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "doc" OS_SEP "main.js", + Buf *main_js_src_path = buf_sprintf("%s" OS_SEP "special" OS_SEP "docs" OS_SEP "main.js", buf_ptr(g->zig_std_dir)); Buf *main_js_dest_path = buf_sprintf("%s" OS_SEP "main.js", buf_ptr(doc_dir_path)); diff --git a/src/dump_analysis.cpp b/src/dump_analysis.cpp index 220019c184..168d86a21f 100644 --- a/src/dump_analysis.cpp +++ b/src/dump_analysis.cpp @@ -351,6 +351,15 @@ struct AnalDumpCtx { ZigList<Tld *> decl_list; HashMap<const Tld *, uint32_t, tld_ptr_hash, tld_ptr_eql> decl_map; + + ZigList<ZigFn *> fn_list; + HashMap<const ZigFn *, uint32_t, fn_ptr_hash, fn_ptr_eql> fn_map; + + ZigList<AstNode *> node_list; + HashMap<const AstNode *, uint32_t, node_ptr_hash, node_ptr_eql> node_map; + + ZigList<ErrorTableEntry *> err_list; + HashMap<const ErrorTableEntry *, uint32_t, err_ptr_hash, err_ptr_eql> err_map; }; static uint32_t anal_dump_get_type_id(AnalDumpCtx *ctx, ZigType *ty); @@ -416,6 +425,39 @@ static uint32_t anal_dump_get_file_id(AnalDumpCtx *ctx, Buf *file) { return file_id; } +static uint32_t anal_dump_get_node_id(AnalDumpCtx *ctx, AstNode *node) { + uint32_t node_id = ctx->node_list.length; + auto existing_entry = ctx->node_map.put_unique(node, node_id); + if (existing_entry == nullptr) { + ctx->node_list.append(node); + } else { + node_id = existing_entry->value; + } + return node_id; +} + +static uint32_t anal_dump_get_fn_id(AnalDumpCtx *ctx, ZigFn *fn) { + uint32_t fn_id = ctx->fn_list.length; + auto existing_entry = ctx->fn_map.put_unique(fn, fn_id); + if (existing_entry == nullptr) { + ctx->fn_list.append(fn); + } else { + fn_id = existing_entry->value; + } + return fn_id; +} + +static uint32_t anal_dump_get_err_id(AnalDumpCtx *ctx, ErrorTableEntry *err) { + uint32_t err_id = ctx->err_list.length; + auto existing_entry = ctx->err_map.put_unique(err, err_id); + if (existing_entry == nullptr) { + ctx->err_list.append(err); + } else { + err_id = existing_entry->value; + } + return err_id; +} + static uint32_t anal_dump_get_decl_id(AnalDumpCtx *ctx, Tld *tld) { uint32_t decl_id = ctx->decl_list.length; auto existing_entry = ctx->decl_map.put_unique(tld, decl_id); @@ -475,6 +517,21 @@ static void anal_dump_file_ref(AnalDumpCtx *ctx, Buf *file) { jw_int(&ctx->jw, file_id); } +static void anal_dump_node_ref(AnalDumpCtx *ctx, AstNode *node) { + uint32_t node_id = anal_dump_get_node_id(ctx, node); + jw_int(&ctx->jw, node_id); +} + +static void anal_dump_fn_ref(AnalDumpCtx *ctx, ZigFn *fn) { + uint32_t fn_id = anal_dump_get_fn_id(ctx, fn); + jw_int(&ctx->jw, fn_id); +} + +static void anal_dump_err_ref(AnalDumpCtx *ctx, ErrorTableEntry *err) { + uint32_t err_id = anal_dump_get_err_id(ctx, err); + jw_int(&ctx->jw, err_id); +} + static void anal_dump_decl_ref(AnalDumpCtx *ctx, Tld *tld) { uint32_t decl_id = anal_dump_get_decl_id(ctx, tld); jw_int(&ctx->jw, decl_id); @@ -536,11 +593,8 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) { jw_object_field(jw, "import"); anal_dump_type_ref(ctx, tld->import); - jw_object_field(jw, "line"); - jw_int(jw, tld->source_node->line); - - jw_object_field(jw, "col"); - jw_int(jw, tld->source_node->column); + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, tld->source_node); jw_object_field(jw, "name"); jw_string(jw, buf_ptr(tld->name)); @@ -584,8 +638,10 @@ static void anal_dump_decl(AnalDumpCtx *ctx, Tld *tld) { jw_object_field(jw, "type"); anal_dump_type_ref(ctx, fn->type_entry); - } + jw_object_field(jw, "value"); + anal_dump_fn_ref(ctx, fn); + } break; } default: @@ -626,6 +682,19 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, anal_dump_type_ref(ctx, val_ty); return; } + case ZigTypeIdFn: { + if (value->data.x_ptr.special == ConstPtrSpecialFunction) { + ZigFn *val_fn = value->data.x_ptr.data.fn.fn_entry; + if (val_fn->type_entry->data.fn.is_generic) { + anal_dump_node_ref(ctx, val_fn->proto_node); + } else { + anal_dump_fn_ref(ctx, val_fn); + } + } else { + jw_null(&ctx->jw); + } + return; + } default: jw_null(&ctx->jw); return; @@ -633,24 +702,75 @@ static void anal_dump_value(AnalDumpCtx *ctx, AstNode *source_node, ZigType *ty, zig_unreachable(); } -static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { +static void anal_dump_pointer_attrs(AnalDumpCtx *ctx, ZigType *ty) { JsonWriter *jw = &ctx->jw; - jw_array_elem(jw); + if (ty->data.pointer.explicit_alignment != 0) { + jw_object_field(jw, "align"); + jw_int(jw, ty->data.pointer.explicit_alignment); + } + if (ty->data.pointer.is_const) { + jw_object_field(jw, "const"); + jw_bool(jw, true); + } + if (ty->data.pointer.is_volatile) { + jw_object_field(jw, "volatile"); + jw_bool(jw, true); + } + if (ty->data.pointer.allow_zero) { + jw_object_field(jw, "allowZero"); + jw_bool(jw, true); + } + if (ty->data.pointer.host_int_bytes != 0) { + jw_object_field(jw, "hostIntBytes"); + jw_int(jw, ty->data.pointer.host_int_bytes); + + jw_object_field(jw, "bitOffsetInHost"); + jw_int(jw, ty->data.pointer.bit_offset_in_host); + } + + jw_object_field(jw, "elem"); + anal_dump_type_ref(ctx, ty->data.pointer.child_type); +} + +static void anal_dump_struct_field(AnalDumpCtx *ctx, const TypeStructField *struct_field) { + JsonWriter *jw = &ctx->jw; + jw_begin_object(jw); jw_object_field(jw, "name"); - jw_string(jw, buf_ptr(&ty->name)); + jw_string(jw, buf_ptr(struct_field->name)); + + jw_object_field(jw, "type"); + anal_dump_type_ref(ctx, struct_field->type_entry); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, struct_field->decl_node); + + jw_end_object(jw); +} + +static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { + JsonWriter *jw = &ctx->jw; + jw_array_elem(jw); + jw_begin_object(jw); jw_object_field(jw, "kind"); jw_int(jw, type_id_index(ty)); switch (ty->id) { + case ZigTypeIdMetaType: + case ZigTypeIdBool: + break; case ZigTypeIdStruct: { if (ty->data.structure.is_slice) { - // TODO + jw_object_field(jw, "len"); + jw_int(jw, 2); + anal_dump_pointer_attrs(ctx, ty->data.structure.fields[slice_ptr_index].type_entry); break; } + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); { jw_object_field(jw, "pubDecls"); jw_begin_array(jw); @@ -691,6 +811,17 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_end_array(jw); } + { + jw_object_field(jw, "fields"); + jw_begin_array(jw); + + for(size_t i = 0; i < ty->data.structure.src_field_count; i += 1) { + jw_array_elem(jw); + anal_dump_struct_field(ctx, &ty->data.structure.fields[i]); + } + jw_end_array(jw); + } + if (ty->data.structure.root_struct != nullptr) { Buf *path_buf = ty->data.structure.root_struct->path; @@ -705,13 +836,167 @@ static void anal_dump_type(AnalDumpCtx *ctx, ZigType *ty) { jw_int(jw, ty->data.floating.bit_count); break; } + case ZigTypeIdInt: { + if (ty->data.integral.is_signed) { + jw_object_field(jw, "i"); + } else { + jw_object_field(jw, "u"); + } + jw_int(jw, ty->data.integral.bit_count); + break; + } + case ZigTypeIdFn: { + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); + + jw_object_field(jw, "generic"); + jw_bool(jw, ty->data.fn.is_generic); + + if (ty->data.fn.fn_type_id.return_type != nullptr) { + jw_object_field(jw, "ret"); + anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.return_type); + } + + if (ty->data.fn.fn_type_id.param_count != 0) { + jw_object_field(jw, "args"); + jw_begin_array(jw); + for (size_t i = 0; i < ty->data.fn.fn_type_id.param_count; i += 1) { + jw_array_elem(jw); + if (ty->data.fn.fn_type_id.param_info[i].type != nullptr) { + anal_dump_type_ref(ctx, ty->data.fn.fn_type_id.param_info[i].type); + } else { + jw_null(jw); + } + } + jw_end_array(jw); + } + break; + } + case ZigTypeIdPointer: { + switch (ty->data.pointer.ptr_len) { + case PtrLenSingle: + break; + case PtrLenUnknown: + jw_object_field(jw, "len"); + jw_int(jw, 1); + break; + case PtrLenC: + jw_object_field(jw, "len"); + jw_int(jw, 3); + break; + } + anal_dump_pointer_attrs(ctx, ty); + break; + } + case ZigTypeIdErrorSet: { + if (type_is_global_error_set(ty)) { + break; + } + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); + + if (ty->data.error_set.infer_fn != nullptr) { + jw_object_field(jw, "fn"); + anal_dump_fn_ref(ctx, ty->data.error_set.infer_fn); + } + jw_object_field(jw, "errors"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ty->data.error_set.err_count; i += 1) { + jw_array_elem(jw); + ErrorTableEntry *err = ty->data.error_set.errors[i]; + anal_dump_err_ref(ctx, err); + } + jw_end_array(jw); + break; + } + case ZigTypeIdErrorUnion: { + jw_object_field(jw, "err"); + anal_dump_type_ref(ctx, ty->data.error_union.err_set_type); + + jw_object_field(jw, "payload"); + anal_dump_type_ref(ctx, ty->data.error_union.payload_type); + + break; + } default: - // TODO + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&ty->name)); break; } jw_end_object(jw); } +static void anal_dump_node(AnalDumpCtx *ctx, const AstNode *node) { + JsonWriter *jw = &ctx->jw; + + jw_begin_object(jw); + + jw_object_field(jw, "file"); + anal_dump_file_ref(ctx, node->owner->data.structure.root_struct->path); + + jw_object_field(jw, "line"); + jw_int(jw, node->line); + + jw_object_field(jw, "col"); + jw_int(jw, node->column); + + const Buf *doc_comments_buf; + switch (node->type) { + case NodeTypeParamDecl: + doc_comments_buf = &node->data.param_decl.doc_comments; + break; + case NodeTypeFnProto: + doc_comments_buf = &node->data.fn_proto.doc_comments; + break; + case NodeTypeVariableDeclaration: + doc_comments_buf = &node->data.variable_declaration.doc_comments; + break; + case NodeTypeErrorSetField: + doc_comments_buf = &node->data.err_set_field.doc_comments; + break; + case NodeTypeStructField: + doc_comments_buf = &node->data.struct_field.doc_comments; + break; + default: + doc_comments_buf = nullptr; + break; + } + if (doc_comments_buf != nullptr && doc_comments_buf->list.length != 0) { + jw_object_field(jw, "docs"); + jw_string(jw, buf_ptr(doc_comments_buf)); + } + + jw_end_object(jw); +} + +static void anal_dump_err(AnalDumpCtx *ctx, const ErrorTableEntry *err) { + JsonWriter *jw = &ctx->jw; + + jw_begin_object(jw); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, err->decl_node); + + jw_object_field(jw, "name"); + jw_string(jw, buf_ptr(&err->name)); + + jw_end_object(jw); +} + +static void anal_dump_fn(AnalDumpCtx *ctx, ZigFn *fn) { + JsonWriter *jw = &ctx->jw; + + jw_begin_object(jw); + + jw_object_field(jw, "src"); + anal_dump_node_ref(ctx, fn->proto_node); + + jw_object_field(jw, "type"); + anal_dump_type_ref(ctx, fn->type_entry); + + jw_end_object(jw); +} + void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const char *nl) { Error err; AnalDumpCtx ctx = {}; @@ -722,6 +1007,9 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const ctx.pkg_map.init(16); ctx.file_map.init(16); ctx.decl_map.init(16); + ctx.node_map.init(16); + ctx.fn_map.init(16); + ctx.err_map.init(16); jw_begin_object(jw); @@ -761,6 +1049,71 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const jw_object_field(jw, "rootPkg"); anal_dump_pkg_ref(&ctx, g->root_package); + // Poke the functions + for (size_t i = 0; i < g->fn_defs.length; i += 1) { + ZigFn *fn = g->fn_defs.at(i); + (void)anal_dump_get_fn_id(&ctx, fn); + } + + jw_object_field(jw, "calls"); + jw_begin_array(jw); + { + auto it = g->memoized_fn_eval_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + jw_array_elem(jw); + jw_begin_object(jw); + + jw_object_field(jw, "args"); + jw_begin_object(jw); + + Scope *scope = entry->key; + while (scope != nullptr) { + if (scope->id == ScopeIdVarDecl) { + ZigVar *var = reinterpret_cast<ScopeVarDecl *>(scope)->var; + jw_object_field(jw, var->name); + jw_begin_object(jw); + jw_object_field(jw, "type"); + anal_dump_type_ref(&ctx, var->var_type); + jw_object_field(jw, "value"); + anal_dump_value(&ctx, scope->source_node, var->var_type, var->const_value); + jw_end_object(jw); + } else if (scope->id == ScopeIdFnDef) { + jw_end_object(jw); + + jw_object_field(jw, "fn"); + ZigFn *fn = reinterpret_cast<ScopeFnDef *>(scope)->fn_entry; + anal_dump_fn_ref(&ctx, fn); + + ConstExprValue *result = entry->value; + jw_object_field(jw, "result"); + jw_begin_object(jw); + jw_object_field(jw, "type"); + anal_dump_type_ref(&ctx, result->type); + jw_object_field(jw, "value"); + anal_dump_value(&ctx, scope->source_node, result->type, result); + jw_end_object(jw); + break; + } + scope = scope->parent; + } + jw_end_object(jw); + } + } + jw_end_array(jw); + + jw_object_field(jw, "fns"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ctx.fn_list.length; i += 1) { + ZigFn *fn = ctx.fn_list.at(i); + jw_array_elem(jw); + anal_dump_fn(&ctx, fn); + } + jw_end_array(jw); + jw_object_field(jw, "packages"); jw_begin_array(jw); for (uint32_t i = 0; i < ctx.pkg_list.length; i += 1) { @@ -794,5 +1147,23 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const } jw_end_array(jw); + jw_object_field(jw, "errors"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ctx.err_list.length; i += 1) { + const ErrorTableEntry *err = ctx.err_list.at(i); + jw_array_elem(jw); + anal_dump_err(&ctx, err); + } + jw_end_array(jw); + + jw_object_field(jw, "astNodes"); + jw_begin_array(jw); + for (uint32_t i = 0; i < ctx.node_list.length; i += 1) { + const AstNode *node = ctx.node_list.at(i); + jw_array_elem(jw); + anal_dump_node(&ctx, node); + } + jw_end_array(jw); + jw_end_object(jw); } diff --git a/src/ir.cpp b/src/ir.cpp index 52b59ddcad..f29870e039 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -7892,11 +7892,14 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp } uint32_t index = set1->data.error_set.err_count; + bool need_comma = false; for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) { ErrorTableEntry *error_entry = set2->data.error_set.errors[i]; if (errors[error_entry->value] == nullptr) { errors[error_entry->value] = error_entry; - buf_appendf(&err_set_type->name, "%s,", buf_ptr(&error_entry->name)); + const char *comma = need_comma ? "," : ""; + need_comma = true; + buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&error_entry->name)); err_set_type->data.error_set.errors[index] = error_entry; index += 1; } @@ -7927,6 +7930,17 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN return err_set_type; } +static AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node) { + if (err_set_field_node->type == NodeTypeSymbol) { + return err_set_field_node; + } else if (err_set_field_node->type == NodeTypeErrorSetField) { + assert(err_set_field_node->data.err_set_field.field_name->type == NodeTypeSymbol); + return err_set_field_node->data.err_set_field.field_name; + } else { + return err_set_field_node; + } +} + static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) { assert(node->type == NodeTypeErrorSetDecl); @@ -7945,11 +7959,11 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A ErrorTableEntry **errors = allocate<ErrorTableEntry *>(irb->codegen->errors_by_index.length + err_count); for (uint32_t i = 0; i < err_count; i += 1) { - AstNode *symbol_node = node->data.err_set_decl.decls.at(i); - assert(symbol_node->type == NodeTypeSymbol); + AstNode *field_node = node->data.err_set_decl.decls.at(i); + AstNode *symbol_node = ast_field_to_symbol_node(field_node); Buf *err_name = symbol_node->data.symbol_expr.symbol; ErrorTableEntry *err = allocate<ErrorTableEntry>(1); - err->decl_node = symbol_node; + err->decl_node = field_node; buf_init_from_buf(&err->name, err_name); auto existing_entry = irb->codegen->error_table.put_unique(err_name, err); @@ -7965,8 +7979,10 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A ErrorTableEntry *prev_err = errors[err->value]; if (prev_err != nullptr) { - ErrorMsg *msg = add_node_error(irb->codegen, err->decl_node, buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); - add_error_note(irb->codegen, msg, prev_err->decl_node, buf_sprintf("other error here")); + ErrorMsg *msg = add_node_error(irb->codegen, ast_field_to_symbol_node(err->decl_node), + buf_sprintf("duplicate error: '%s'", buf_ptr(&err->name))); + add_error_note(irb->codegen, msg, ast_field_to_symbol_node(prev_err->decl_node), + buf_sprintf("other error here")); return irb->codegen->invalid_instruction; } errors[err->value] = err; @@ -8116,6 +8132,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop case NodeTypeSwitchProng: case NodeTypeSwitchRange: case NodeTypeStructField: + case NodeTypeErrorSetField: case NodeTypeFnDef: case NodeTypeTestDecl: zig_unreachable(); @@ -9470,6 +9487,14 @@ static void populate_error_set_table(ErrorTableEntry **errors, ZigType *set) { } } +static ErrorTableEntry *better_documented_error(ErrorTableEntry *preferred, ErrorTableEntry *other) { + if (preferred->decl_node->type == NodeTypeErrorSetField) + return preferred; + if (other->decl_node->type == NodeTypeErrorSetField) + return other; + return preferred; +} + static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigType *set2, AstNode *source_node) { @@ -9496,12 +9521,17 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp buf_resize(&err_set_type->name, 0); buf_appendf(&err_set_type->name, "error{"); + bool need_comma = false; for (uint32_t i = 0; i < set2->data.error_set.err_count; i += 1) { ErrorTableEntry *error_entry = set2->data.error_set.errors[i]; ErrorTableEntry *existing_entry = errors[error_entry->value]; if (existing_entry != nullptr) { - intersection_list.append(existing_entry); - buf_appendf(&err_set_type->name, "%s,", buf_ptr(&existing_entry->name)); + // prefer the one with docs + const char *comma = need_comma ? "," : ""; + need_comma = true; + ErrorTableEntry *existing_entry_with_docs = better_documented_error(existing_entry, error_entry); + intersection_list.append(existing_entry_with_docs); + buf_appendf(&err_set_type->name, "%s%s", comma, buf_ptr(&existing_entry_with_docs->name)); } } free(errors); @@ -9683,7 +9713,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted ZigType *container_set = wanted_type; // if the container set is inferred, then this will always work. - if (container_set->data.error_set.infer_fn != nullptr) { + if (container_set->data.error_set.infer_fn != nullptr && container_set->data.error_set.incomplete) { return result; } // if the container set is the global one, it will always work. @@ -12049,7 +12079,7 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa ZigList<ErrorTableEntry *> *missing_errors = &cast_result->data.error_set_mismatch->missing_errors; for (size_t i = 0; i < missing_errors->length; i += 1) { ErrorTableEntry *error_entry = missing_errors->at(i); - add_error_note(ira->codegen, parent_msg, error_entry->decl_node, + add_error_note(ira->codegen, parent_msg, ast_field_to_symbol_node(error_entry->decl_node), buf_sprintf("'error.%s' not a member of destination error set", buf_ptr(&error_entry->name))); } break; @@ -16148,7 +16178,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c UndefOk); if (inferred_err_set_type != nullptr) { - inferred_err_set_type->data.error_set.infer_fn = nullptr; + inferred_err_set_type->data.error_set.incomplete = false; if (result->type->id == ZigTypeIdErrorUnion) { ErrorTableEntry *err = result->data.x_err_union.error_set->data.x_err_set; if (err != nullptr) { @@ -23608,7 +23638,7 @@ static IrInstruction *ir_analyze_instruction_test_err(IrAnalyze *ira, IrInstruct if (!type_is_global_error_set(err_set_type) && err_set_type->data.error_set.err_count == 0) { - assert(err_set_type->data.error_set.infer_fn == nullptr); + assert(!err_set_type->data.error_set.incomplete); return ir_const_bool(ira, &instruction->base, false); } } diff --git a/src/main.cpp b/src/main.cpp index 9b8bddabd7..fb2881f3a3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,7 +34,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " build-exe [source] create executable from source or object files\n" " build-lib [source] create library from source or object files\n" " build-obj [source] create object from source or assembly\n" - " builtin show the source code of that @import(\"builtin\")\n" + " builtin show the source code of @import(\"builtin\")\n" " cc C compiler\n" " fmt parse files and render in canonical zig format\n" " id print the base64-encoded compiler id\n" @@ -65,7 +65,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " -ftime-report print timing diagnostics\n" " -fstack-report print stack size diagnostics\n" " -fdump-analysis write analysis.json file with type information\n" - " -fgenerate-docs create a doc/ dir with html documentation\n" + " -fgenerate-docs create a docs/ dir with html documentation\n" " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output-dir [dir] override output directory (defaults to cwd)\n" diff --git a/src/parser.cpp b/src/parser.cpp index 96071daa07..9fcf233e2d 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -37,7 +37,7 @@ static AstNode *ast_parse_root(ParseContext *pc); static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc); static AstNode *ast_parse_test_decl(ParseContext *pc); static AstNode *ast_parse_top_level_comptime(ParseContext *pc); -static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod); +static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments); static AstNode *ast_parse_fn_proto(ParseContext *pc); static AstNode *ast_parse_var_decl(ParseContext *pc); static AstNode *ast_parse_container_field(ParseContext *pc); @@ -497,6 +497,23 @@ static AstNode *ast_parse_root(ParseContext *pc) { return node; } +static Token *ast_parse_doc_comments(ParseContext *pc, Buf *buf) { + Token *first_doc_token = nullptr; + Token *doc_token = nullptr; + while ((doc_token = eat_token_if(pc, TokenIdDocComment))) { + if (first_doc_token == nullptr) { + first_doc_token = doc_token; + } + if (buf->list.length == 0) { + buf_resize(buf, 0); + } + // chops off '///' but leaves '\n' + buf_append_mem(buf, buf_ptr(pc->buf) + doc_token->start_pos + 3, + doc_token->end_pos - doc_token->start_pos - 3); + } + return first_doc_token; +} + // ContainerMembers // <- TestDecl ContainerMembers // / TopLevelComptime ContainerMembers @@ -519,10 +536,13 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { continue; } + Buf doc_comment_buf = BUF_INIT; + ast_parse_doc_comments(pc, &doc_comment_buf); + Token *visib_token = eat_token_if(pc, TokenIdKeywordPub); VisibMod visib_mod = visib_token != nullptr ? VisibModPub : VisibModPrivate; - AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod); + AstNode *top_level_decl = ast_parse_top_level_decl(pc, visib_mod, &doc_comment_buf); if (top_level_decl != nullptr) { res.decls.append(top_level_decl); continue; @@ -532,6 +552,7 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) { if (container_field != nullptr) { assert(container_field->type == NodeTypeStructField); container_field->data.struct_field.visib_mod = visib_mod; + container_field->data.struct_field.doc_comments = doc_comment_buf; res.fields.append(container_field); if (eat_token_if(pc, TokenIdComma) != nullptr) { continue; @@ -581,7 +602,7 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) { // <- (KEYWORD_export / KEYWORD_extern STRINGLITERAL? / (KEYWORD_inline / KEYWORD_noinline))? FnProto (SEMICOLON / Block) // / (KEYWORD_export / KEYWORD_extern STRINGLITERAL?)? KEYWORD_threadlocal? VarDecl // / KEYWORD_use Expr SEMICOLON -static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { +static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, Buf *doc_comments) { Token *first = eat_token_if(pc, TokenIdKeywordExport); if (first == nullptr) first = eat_token_if(pc, TokenIdKeywordExtern); @@ -603,6 +624,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { var_decl->column = first->start_column; var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; var_decl->data.variable_declaration.visib_mod = visib_mod; + var_decl->data.variable_declaration.doc_comments = *doc_comments; var_decl->data.variable_declaration.is_extern = first->id == TokenIdKeywordExtern; var_decl->data.variable_declaration.is_export = first->id == TokenIdKeywordExport; var_decl->data.variable_declaration.lib_name = token_buf(lib_name); @@ -623,6 +645,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { fn_proto->line = first->start_line; fn_proto->column = first->start_column; fn_proto->data.fn_proto.visib_mod = visib_mod; + fn_proto->data.fn_proto.doc_comments = *doc_comments; fn_proto->data.fn_proto.is_extern = first->id == TokenIdKeywordExtern; fn_proto->data.fn_proto.is_export = first->id == TokenIdKeywordExport; switch (first->id) { @@ -657,6 +680,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { if (var_decl != nullptr) { assert(var_decl->type == NodeTypeVariableDeclaration); var_decl->data.variable_declaration.visib_mod = visib_mod; + var_decl->data.variable_declaration.doc_comments = *doc_comments; var_decl->data.variable_declaration.threadlocal_tok = thread_local_kw; return var_decl; } @@ -672,6 +696,7 @@ static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod) { assert(fn_proto->type == NodeTypeFnProto); fn_proto->data.fn_proto.visib_mod = visib_mod; + fn_proto->data.fn_proto.doc_comments = *doc_comments; AstNode *res = fn_proto; if (body != nullptr) { res = ast_create_node_copy_line_info(pc, NodeTypeFnDef, fn_proto); @@ -1719,11 +1744,20 @@ static AstNode *ast_parse_error_set_decl(ParseContext *pc) { } ZigList<AstNode *> decls = ast_parse_list<AstNode>(pc, TokenIdComma, [](ParseContext *context) { + Buf doc_comment_buf = BUF_INIT; + Token *doc_token = ast_parse_doc_comments(context, &doc_comment_buf); Token *ident = eat_token_if(context, TokenIdSymbol); if (ident == nullptr) return (AstNode*)nullptr; - return token_symbol(context, ident); + AstNode *symbol_node = token_symbol(context, ident); + if (doc_token == nullptr) + return symbol_node; + + AstNode *field_node = ast_create_node(context, NodeTypeErrorSetField, doc_token); + field_node->data.err_set_field.field_name = symbol_node; + field_node->data.err_set_field.doc_comments = doc_comment_buf; + return field_node; }); expect_token(pc, TokenIdRBrace); @@ -2057,6 +2091,9 @@ static Optional<AstNodeFnProto> ast_parse_fn_cc(ParseContext *pc) { // ParamDecl <- (KEYWORD_noalias / KEYWORD_comptime)? (IDENTIFIER COLON)? ParamType static AstNode *ast_parse_param_decl(ParseContext *pc) { + Buf doc_comments = BUF_INIT; + ast_parse_doc_comments(pc, &doc_comments); + Token *first = eat_token_if(pc, TokenIdKeywordNoAlias); if (first == nullptr) first = eat_token_if(pc, TokenIdKeywordCompTime); @@ -2089,6 +2126,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc) { res->line = first->start_line; res->column = first->start_column; res->data.param_decl.name = token_buf(name); + res->data.param_decl.doc_comments = doc_comments; res->data.param_decl.is_noalias = first->id == TokenIdKeywordNoAlias; res->data.param_decl.is_comptime = first->id == TokenIdKeywordCompTime; return res; @@ -3029,6 +3067,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont case NodeTypeErrorSetDecl: visit_node_list(&node->data.err_set_decl.decls, visit, context); break; + case NodeTypeErrorSetField: + visit_field(&node->data.err_set_field.field_name, visit, context); + break; case NodeTypeResume: visit_field(&node->data.resume_expr.expr, visit, context); break; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 11824bd871..475c284d27 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -197,6 +197,8 @@ enum TokenizeState { TokenizeStateSawStar, TokenizeStateSawStarPercent, TokenizeStateSawSlash, + TokenizeStateSawSlash2, + TokenizeStateSawSlash3, TokenizeStateSawBackslash, TokenizeStateSawPercent, TokenizeStateSawPlus, @@ -207,6 +209,7 @@ enum TokenizeState { TokenizeStateSawCaret, TokenizeStateSawBar, TokenizeStateSawBarBar, + TokenizeStateDocComment, TokenizeStateLineComment, TokenizeStateLineString, TokenizeStateLineStringEnd, @@ -912,8 +915,7 @@ void tokenize(Buf *buf, Tokenization *out) { case TokenizeStateSawSlash: switch (c) { case '/': - cancel_token(&t); - t.state = TokenizeStateLineComment; + t.state = TokenizeStateSawSlash2; break; case '=': set_token_id(&t, t.cur_tok, TokenIdDivEq); @@ -927,6 +929,38 @@ void tokenize(Buf *buf, Tokenization *out) { continue; } break; + case TokenizeStateSawSlash2: + switch (c) { + case '/': + t.state = TokenizeStateSawSlash3; + break; + case '\n': + cancel_token(&t); + t.state = TokenizeStateStart; + break; + default: + cancel_token(&t); + t.state = TokenizeStateLineComment; + break; + } + break; + case TokenizeStateSawSlash3: + switch (c) { + case '/': + cancel_token(&t); + t.state = TokenizeStateLineComment; + break; + case '\n': + set_token_id(&t, t.cur_tok, TokenIdDocComment); + end_token(&t); + t.state = TokenizeStateStart; + break; + default: + set_token_id(&t, t.cur_tok, TokenIdDocComment); + t.state = TokenizeStateDocComment; + break; + } + break; case TokenizeStateSawBackslash: switch (c) { case '\\': @@ -1006,6 +1040,17 @@ void tokenize(Buf *buf, Tokenization *out) { break; } break; + case TokenizeStateDocComment: + switch (c) { + case '\n': + end_token(&t); + t.state = TokenizeStateStart; + break; + default: + // do nothing + break; + } + break; case TokenizeStateSymbolFirstC: switch (c) { case '"': @@ -1495,6 +1540,7 @@ void tokenize(Buf *buf, Tokenization *out) { case TokenizeStateLineStringEnd: case TokenizeStateSawBarBar: case TokenizeStateLBracket: + case TokenizeStateDocComment: end_token(&t); break; case TokenizeStateSawDotDot: @@ -1507,6 +1553,8 @@ void tokenize(Buf *buf, Tokenization *out) { tokenize_error(&t, "unexpected EOF"); break; case TokenizeStateLineComment: + case TokenizeStateSawSlash2: + case TokenizeStateSawSlash3: break; } if (t.state != TokenizeStateError) { @@ -1553,6 +1601,7 @@ const char * token_name(TokenId id) { case TokenIdComma: return ","; case TokenIdDash: return "-"; case TokenIdDivEq: return "/="; + case TokenIdDocComment: return "DocComment"; case TokenIdDot: return "."; case TokenIdEllipsis2: return ".."; case TokenIdEllipsis3: return "..."; diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp index a3d1a60008..e33a82f31d 100644 --- a/src/tokenizer.hpp +++ b/src/tokenizer.hpp @@ -42,6 +42,7 @@ enum TokenId { TokenIdComma, TokenIdDash, TokenIdDivEq, + TokenIdDocComment, TokenIdDot, TokenIdEllipsis2, TokenIdEllipsis3, |
