aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp47
-rw-r--r--src/analyze.cpp47
-rw-r--r--src/ast_render.cpp3
-rw-r--r--src/buffer.hpp6
-rw-r--r--src/codegen.cpp9
-rw-r--r--src/dump_analysis.cpp393
-rw-r--r--src/ir.cpp54
-rw-r--r--src/main.cpp4
-rw-r--r--src/parser.cpp49
-rw-r--r--src/tokenizer.cpp53
-rw-r--r--src/tokenizer.hpp1
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,