ERR/E0.1: error-set decls + ! / !Named type exprs (parser)

Parser-only first step of the error-handling stream. No sema/codegen.

- token: `kw_error` keyword (`!` reuses existing `.bang`).
- ast: `ErrorSetDecl { name, tag_names }` + `ErrorTypeExpr { name: ?[] }`
  (null = inferred `!`, non-null = `!Named`); wired into Node.Data and
  declName.
- parser: `parseErrorSetDecl` (comma-separated tags, optional trailing
  comma/`;`) dispatched from parseConstBinding; `!` / `!Named` parsed in
  parseTypeExpr; result-list loop enforces error type as trailing-only;
  hasFnBodyAfterArrow skips `.bang` so failable-return fns are recognised.
- print: new focused AST round-trip printer (decls + type exprs); loud
  `error.UnsupportedNode` otherwise. Registered in root.zig.
- sema/lsp: exhaustive switch arms for the two new nodes.
- tests: 11 inline parser unit tests (shapes + 3 round-trip prints + 2
  trailing-position rejections).

zig build, zig build test, and 254/254 examples green.
This commit is contained in:
agra
2026-05-31 16:40:22 +03:00
parent f7f9def0e7
commit e88ee66953
7 changed files with 300 additions and 1 deletions

View File

@@ -37,6 +37,7 @@ pub const Node = struct {
struct_decl: StructDecl,
struct_literal: StructLiteral,
union_decl: UnionDecl,
error_set_decl: ErrorSetDecl,
lambda: Lambda,
type_expr: TypeExpr,
param: Param,
@@ -56,6 +57,7 @@ pub const Node = struct {
pointer_type_expr: PointerTypeExpr,
many_pointer_type_expr: ManyPointerTypeExpr,
optional_type_expr: OptionalTypeExpr,
error_type_expr: ErrorTypeExpr,
pack_index_type_expr: PackIndexTypeExpr,
comptime_pack_ref: ComptimePackRef,
force_unwrap: ForceUnwrap,
@@ -94,6 +96,7 @@ pub const Node = struct {
.enum_decl => |d| d.name,
.struct_decl => |d| d.name,
.union_decl => |d| d.name,
.error_set_decl => |d| d.name,
.namespace_decl => |d| d.name,
.ufcs_alias => |d| d.name,
.c_import_decl => |d| d.name,
@@ -324,6 +327,13 @@ pub const UnionDecl = struct {
field_types: []const *Node,
};
/// `Foo :: error { TagA, TagB }` — a named error set. Tags are bare
/// identifiers (no payload, no explicit value), unlike enum variants.
pub const ErrorSetDecl = struct {
name: []const u8,
tag_names: []const []const u8,
};
pub const StructTypeParam = struct {
name: []const u8, // e.g. "N" or "T" (without $)
constraint: *Node, // type_expr: "u32" for value param, "Type" for type param
@@ -461,6 +471,15 @@ pub const OptionalTypeExpr = struct {
inner_type: *Node,
};
/// The error channel of a multi-return result list: bare `!` (inferred
/// set) or `!Named` (a declared `error { ... }` set). Appears only as
/// the trailing result element; the parser enforces the position and
/// sema (E1) restricts it to return positions.
pub const ErrorTypeExpr = struct {
/// `null` = inferred set (bare `!`); non-null = named set (`!Named`).
name: ?[]const u8 = null,
};
pub const ForceUnwrap = struct {
operand: *Node,
};