From 72ca625635e9b707b6da82f7ef4cdcf06132104e Mon Sep 17 00:00:00 2001 From: Betterlol <12311024@mail.sustech.edu.cn> Date: Sun, 12 Jul 2026 22:00:42 +0800 Subject: [PATCH] [docs & fix]: fix trait any/unknow/tuple/preprocess fn; add exporters/README.md; update docs. --- CHANGELOG.md | 1 + README.mbt.md | 10 +-- README_zh.mbt.md | 10 +-- docs/en/INFO.md | 9 +-- docs/en/README_TEMPLATE.md | 1 + docs/zh/INFO.md | 9 +-- docs/zh/README_TEMPLATE.md | 1 + exporters/README.md | 115 +++++++++++++++++++++++++++++ exporters/json_schema.mbt | 53 +++++++++++++ exporters/json_schema_renderer.mbt | 26 ++----- exporters/prompt.mbt | 55 ++++++++++++++ exporters/prompt_renderer.mbt | 36 ++++----- 12 files changed, 267 insertions(+), 59 deletions(-) create mode 100644 exporters/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d27db4..9e88e70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ ### C — Code Exporter Fixes - `schema_to_moon_zod_code()` now handles `any()`, `unknown()`, `tuple()`, `preprocess()` with valid code output - Fixed `json_to_literal` for boolean/null values (no longer uses non-existent `Json::boolean()` / `Json::null()` constructors) +- `schema_to_moonbit_struct_named()` and `schema_to_moonbit_struct_named_full()` removed from public API (deferred: moonbit_struct exporter not yet hardened to Phase 41 standard for tuple/any/unknown) **470 tests** (all passing, 0 warnings) diff --git a/README.mbt.md b/README.mbt.md index 40aba7b..8c9093f 100644 --- a/README.mbt.md +++ b/README.mbt.md @@ -17,6 +17,7 @@ | [CLI Reference](./docs/en/CLI.md) | Command-line usage | | [Benchmark](./docs/en/BENCHMARK.md) | Performance comparison with other validation libraries | | [Examples](./docs/en/EXAMPLES.md) | Practical usage examples | +| [Exporters](./exporters/README.md) | moon_zod exporters documentation | --- @@ -126,8 +127,7 @@ moon_zod/ │ └── moon_zod_wbtest.mbt # White-box tests (path stack invariants) │ ├── combinators/ # Schema combinator utilities -│ ├── schema_combinators.mbt # Schema composition helpers -│ └── reexporter.mbt # Re-exports +│ └── schema_combinators.mbt # Schema composition helpers │ ├── exporters/ # Code/schema export tools │ ├── prompt.mbt # schema_to_prompt() / schema_to_prompt_named() @@ -135,12 +135,10 @@ moon_zod/ │ ├── json_schema.mbt # to_json_schema() / to_json_schema_named() │ ├── json_schema_renderer.mbt # Trait-based JSON Schema rendering │ ├── moonbit_struct.mbt # schema_to_moonbit_struct() + static to_schema() generation -│ ├── schema_exporter.mbt # Shared exporter utilities -│ └── reexporter.mbt # Module re-exports +│ └── schema_exporter.mbt # Shared exporter utilities │ ├── importers/ # Schema import tools -│ ├── from_json_schema.mbt # json_schema_to_moon_zod() — reverse JSON Schema → moon_zod code generation -│ └── reexporter.mbt # Module re-exports +│ └── from_json_schema.mbt # json_schema_to_moon_zod() — reverse JSON Schema → moon_zod code generation │ ├── tests/ # Test suite (466 tests) │ ├── test_string.mbt # string() validator tests (trim, to_lower, to_upper, nonempty) diff --git a/README_zh.mbt.md b/README_zh.mbt.md index 2f0d4b4..a3c477b 100644 --- a/README_zh.mbt.md +++ b/README_zh.mbt.md @@ -17,6 +17,7 @@ | [CLI 参考](./docs/zh/CLI.md) | 命令行使用说明 | | [性能基准](./docs/zh/BENCHMARK.md) | 与其他校验库的性能对比 | | [使用示例](./docs/zh/EXAMPLES.md) | 实际使用示例 | +| [导出器说明](./exporters/README.md) | moon_zod 的导出器说明 | --- @@ -126,8 +127,7 @@ moon_zod/ │ └── moon_zod_wbtest.mbt # 白盒测试(路径栈不变量) │ ├── combinators/ # Schema 组合器工具 -│ ├── schema_combinators.mbt # Schema 组合辅助函数 -│ └── reexporter.mbt # 重新导出 +│ └── schema_combinators.mbt # Schema 组合辅助函数 │ ├── exporters/ # 代码/Schema 导出工具 │ ├── prompt.mbt # schema_to_prompt() / schema_to_prompt_named() @@ -135,12 +135,10 @@ moon_zod/ │ ├── json_schema.mbt # to_json_schema() / to_json_schema_named() │ ├── json_schema_renderer.mbt # 基于特性的 JSON Schema 渲染 │ ├── moonbit_struct.mbt # schema_to_moonbit_struct() + 静态 to_schema() 生成 -│ ├── schema_exporter.mbt # 共享导出器工具 -│ └── reexporter.mbt # 模块重新导出 +│ └── schema_exporter.mbt # 共享导出器工具 │ ├── importers/ # Schema 导入工具 -│ ├── from_json_schema.mbt # json_schema_to_moon_zod() —— 反向 JSON Schema → moon_zod 代码生成 -│ └── reexporter.mbt # 模块重新导出 +│ └── from_json_schema.mbt # json_schema_to_moon_zod() —— 反向 JSON Schema → moon_zod 代码生成 │ ├── tests/ # 测试套件(466 个测试) │ ├── test_string.mbt # string() 校验器测试(trim、to_lower、to_upper、nonempty) diff --git a/docs/en/INFO.md b/docs/en/INFO.md index fb3cf04..4ef2ceb 100644 --- a/docs/en/INFO.md +++ b/docs/en/INFO.md @@ -43,8 +43,7 @@ moon_zod/ │ └── moon_zod_wbtest.mbt # White-box tests (path stack invariants) │ ├── combinators/ # Schema combinator utilities -│ ├── schema_combinators.mbt # Schema composition helpers -│ └── reexporter.mbt # Re-exports +│ └── schema_combinators.mbt # Schema composition helpers │ ├── exporters/ # Code/schema export tools │ ├── prompt.mbt # schema_to_prompt() / schema_to_prompt_named() @@ -52,12 +51,10 @@ moon_zod/ │ ├── json_schema.mbt # to_json_schema() / to_json_schema_named() │ ├── json_schema_renderer.mbt # Trait-based JSON Schema rendering │ ├── moonbit_struct.mbt # schema_to_moonbit_struct() + static to_schema() generation -│ ├── schema_exporter.mbt # Shared exporter utilities -│ └── reexporter.mbt # Module re-exports +│ └── schema_exporter.mbt # Shared exporter utilities │ ├── importers/ # Schema import tools -│ ├── from_json_schema.mbt # json_schema_to_moon_zod() — reverse JSON Schema → moon_zod code generation -│ └── reexporter.mbt # Module re-exports +│ └── from_json_schema.mbt # json_schema_to_moon_zod() — reverse JSON Schema → moon_zod code generation │ ├── tests/ # Test suite (466 tests) │ ├── test_string.mbt # string() validator tests (trim, to_lower, to_upper, nonempty) diff --git a/docs/en/README_TEMPLATE.md b/docs/en/README_TEMPLATE.md index b684940..27b7a93 100644 --- a/docs/en/README_TEMPLATE.md +++ b/docs/en/README_TEMPLATE.md @@ -17,6 +17,7 @@ | [CLI Reference](./docs/en/CLI.md) | Command-line usage | | [Benchmark](./docs/en/BENCHMARK.md) | Performance comparison with other validation libraries | | [Examples](./docs/en/EXAMPLES.md) | Practical usage examples | +| [Exporters](./exporters/README.md) | moon_zod exporters documentation | --- diff --git a/docs/zh/INFO.md b/docs/zh/INFO.md index 4af58f2..b93ec2c 100644 --- a/docs/zh/INFO.md +++ b/docs/zh/INFO.md @@ -43,8 +43,7 @@ moon_zod/ │ └── moon_zod_wbtest.mbt # 白盒测试(路径栈不变量) │ ├── combinators/ # Schema 组合器工具 -│ ├── schema_combinators.mbt # Schema 组合辅助函数 -│ └── reexporter.mbt # 重新导出 +│ └── schema_combinators.mbt # Schema 组合辅助函数 │ ├── exporters/ # 代码/Schema 导出工具 │ ├── prompt.mbt # schema_to_prompt() / schema_to_prompt_named() @@ -52,12 +51,10 @@ moon_zod/ │ ├── json_schema.mbt # to_json_schema() / to_json_schema_named() │ ├── json_schema_renderer.mbt # 基于特性的 JSON Schema 渲染 │ ├── moonbit_struct.mbt # schema_to_moonbit_struct() + 静态 to_schema() 生成 -│ ├── schema_exporter.mbt # 共享导出器工具 -│ └── reexporter.mbt # 模块重新导出 +│ └── schema_exporter.mbt # 共享导出器工具 │ ├── importers/ # Schema 导入工具 -│ ├── from_json_schema.mbt # json_schema_to_moon_zod() —— 反向 JSON Schema → moon_zod 代码生成 -│ └── reexporter.mbt # 模块重新导出 +│ └── from_json_schema.mbt # json_schema_to_moon_zod() —— 反向 JSON Schema → moon_zod 代码生成 │ ├── tests/ # 测试套件(466 个测试) │ ├── test_string.mbt # string() 校验器测试(trim、to_lower、to_upper、nonempty) diff --git a/docs/zh/README_TEMPLATE.md b/docs/zh/README_TEMPLATE.md index d873254..deedd66 100644 --- a/docs/zh/README_TEMPLATE.md +++ b/docs/zh/README_TEMPLATE.md @@ -17,6 +17,7 @@ | [CLI 参考](./docs/zh/CLI.md) | 命令行使用说明 | | [性能基准](./docs/zh/BENCHMARK.md) | 与其他校验库的性能对比 | | [使用示例](./docs/zh/EXAMPLES.md) | 实际使用示例 | +| [导出器说明](./exporters/README.md) | moon_zod 的导出器说明 | --- diff --git a/exporters/README.md b/exporters/README.md new file mode 100644 index 0000000..5b9b002 --- /dev/null +++ b/exporters/README.md @@ -0,0 +1,115 @@ +# exporters + +Schema → String / Json / MoonBit source code 导出工具包。 + +本包提供多条独立导出管线(Prompt / JSON Schema / MoonBit struct / MoonZod Schema)。每条管线对 `@core.SchemaType` 的 17 个变体做逐一渲染,支持内联展开和命名引用两种模式。 + +--- + +## 公开 API + +### Prompt 导出 + +- `schema_to_prompt(schema) -> String` — 将 Schema 渲染为 TypeScript-interface 风格的提示文本(全内联) +- `schema_to_prompt_named(schema, include_names?) -> String` — 提取带 `name` 的 Schema 生成模块化接口,带拓扑排序和类型引用 + +### JSON Schema 导出 + +- `to_json_schema(schema) -> Json` — 标准 JSON Schema(完整约束注释) +- `to_json_schema_skeleton(schema) -> Json` — 轻量级骨架(仅类型结构,无约束) +- `to_json_schema_named(schema, include_names?) -> Json` — 命名 Schema 导出为 `$defs` + `$ref` + +### MoonBit 结构导出 + +- `schema_to_moonbit_struct(schema) -> String` — 生成 MoonBit `pub struct` / `pub enum` 定义 +- `schema_to_moonbit_struct_full(schema) -> String` — 生成定义 + 静态 `Type::to_schema()` 方法 + +### 代码生成 + +- `schema_to_moon_zod_code(schema) -> String` — 将 Schema 反转为可 copy-paste 的 moon_zod 源码 +- `schema_to_moon_zod_code_named(schema, include_names?) -> String` — 带命名 Schema 引用的源码生成 +- `schema_to_moon_zod_code_inline_with_refs(schema, include_names) -> String` — 内联渲染,可选命名引用替换 + +--- + +## 文件结构 + +``` +exporters/ +├── prompt.mbt # schema_to_prompt / schema_to_prompt_named 公共 API +├── prompt_renderer.mbt # StringRenderer trait + NamedPromptRenderer 实现 +├── json_schema.mbt # to_json_schema / to_json_schema_named / to_json_schema_skeleton 公共 API +├── json_schema_renderer.mbt # JsonSchemaRenderer trait + NamedJsonRenderer 实现 +├── moonbit_struct.mbt # schema_to_moonbit_struct / _full 公共 API +├── schema_exporter.mbt # schema_to_moon_zod_code / _named / _inline 公共 API +└── pkg.generated.mbti # moon info 生成的接口描述(勿手动编辑) +``` + +--- + +## 实现说明 + +### 渲染器架构 + +导出管线统一采用 **trait 分发** 模式: + +1. 每个 `SchemaType` 变体对应 trait 中的一个方法 +2. 顶层的 `render_type` / `render_json_type` 做单点分发 +3. 渲染器只负责「类型 → 文本/Json」的转换,约束注释、命名引用、描述文本由各模块独立处理 + +``` +Schema ──► render_type(renderer, schema) ──► StringRenderer ──► String + └── render_json_type(renderer, schema) ──► JsonSchemaRenderer ──► Json +``` + +#### Prompt 导出(`prompt.mbt` + `prompt_renderer.mbt`) + +- `schema_to_prompt()` 内部复用 `NamedPromptRenderer([])`,named 集合为空 → 全内联展开 +- `schema_to_prompt_named()` 收集所有带 `name` 的 Schema,拓扑排序后生成 `export interface / export type` 定义 +- `include_names?` 参数支持选择性导出(`None` = 全部,`Some([])` = 无,`Some([...])` = 指定) +- named wrapper schemas(primitive、array、optional、default、transform、tuple、any、unknown、preprocess)统一生成 `export type X = T` +- named intersection 当包含非 object 分支时输出 `export type X = A & B`,否则合并 object 字段 + +#### JSON Schema 导出(`json_schema.mbt` + `json_schema_renderer.mbt`) + +- `NamedJsonRenderer` 的 `include_annotations` 参数统一三种模式: + - `include_annotations=true` → `to_json_schema()`(完整约束) + - `include_annotations=false` → `to_json_schema_skeleton()`(仅结构) +- `optional()` / `default()` 导出 nullable 语义:`anyOf: [inner, {"type": "null"}]` +- `Strip` 模式导出 `additionalProperties: false`(与运行时幻觉防御对齐) +- object intersection 合并为单个 closed object;同名字段用属性级 `allOf` 保留各自约束 +- `$defs` 渲染时排除自引用(`ref_names.filter(n => n != ns.name)`) + +### 代码生成架构 + +本包包含两条**反向代码生成**管线,均不采用 trait 分发,而是直接 match `SchemaType` 生成目标语言源码。 + +#### MoonBit 结构导出(`moonbit_struct.mbt`) + +- `schema_to_moonbit_struct()` 将 `ObjectType` 映射为 `pub struct`,`EnumType` 映射为 `pub enum` +- `schema_to_moonbit_struct_full()` 额外生成静态 `Type::to_schema() -> @moon_zod.Schema` 方法,实现 struct ↔ Schema 往返 +- 基础类型映射:`String → String`,`Number → Int64 / Double`(按 `.int()` 规则区分),`Boolean → Bool` +- `ArrayType → Array[T]`,可空 `UnionType` 剥除 `null` 后映射 +- `AnyType / UnknownType` 当前回退为 `Json` +- `TupleType` / 非可空 `UnionType` / `IntersectionType` 当前回退为 `Json // TODO` +- 字段名和类型名自动转义(MoonBit 关键字、保留字、首字母数字) +- 约束注释以行内注释形式附加在 struct field 上 + +#### MoonZod 代码导出(`schema_exporter.mbt`) + +- `schema_to_moon_zod_code()` 将运行时 Schema 反转为可 copy-paste 的 moon_zod 方法链源码 +- 输出格式:`let name = @moon_zod.string().min(3).describe("...").name("name")` +- 根 Schema 无 `name` 时自动赋予 `"Root"` +- `schema_to_moon_zod_code_named()` 提取所有命名 Schema,拓扑排序后输出 `let name = ...` 定义列表 +- 规则注释通过 `Rule.annotation` 反推 `.min()` / `.max()` / `.email()` / `.url()` / `.int()` 等 +- `json_to_literal()` 将 Json 值转为 MoonBit 构造函数调用(`Json::string(...)` / `Json::number(...)` / `true` / `false` / `null`) +- `PreprocessType` / `TransformType` 输出占位闭包 `fn(x) { Ok(x) }`,标记为最佳代码输出(自定义闭包无法序列化) +- `.required_error()` / `.invalid_type_error()` 链式方法仍会输出代码,但当前 `Schema` 工厂 API 未暴露这两个参数——round-trip 不安全 + +--- + +## 已知限制 + +- 当前 `moonbit_struct.mbt` 中 `TupleType` 仍回退为 `Json`,`any/unknown` 仅做最低限度映射。待后续整体重构时重新评估。 +- MoonBit 结构导出尚不支持 `tuple` / `intersection` / `union` 等复杂类型的精确类型映射,当前回退为 `Json // TODO`。 +- MoonZod 代码导出对 `TransformType` / `PreprocessType` 输出占位闭包 `fn(x) { Ok(x) }`,自定义闭包无法序列化;`.required_error()` / `.invalid_type_error()` round-trip 不安全(工厂 API 未暴露这两个参数)。 \ No newline at end of file diff --git a/exporters/json_schema.mbt b/exporters/json_schema.mbt index 13a7455..a2a4d09 100644 --- a/exporters/json_schema.mbt +++ b/exporters/json_schema.mbt @@ -183,6 +183,21 @@ fn[R : JsonSchemaRenderer] render_intersection_schema( ) } +///| +fn[R : JsonSchemaRenderer] render_json_tuple_type( + renderer : R, + items : Array[@core.Schema], +) -> Json { + Json::object({ + "type": Json::string("array"), + "prefixItems": Json::array( + items.map(fn(item) { render_json_type(renderer, item) }), + ), + "minItems": Json::number(items.length().to_double()), + "maxItems": Json::number(items.length().to_double()), + }) +} + ///| fn can_merge_object_intersection(schemas : Array[@core.Schema]) -> Bool { for schema in schemas { @@ -499,6 +514,44 @@ pub impl JsonSchemaRenderer for NamedJsonRenderer with fn render_literal( ) } +///| +#warnings("-unused_value") +pub impl JsonSchemaRenderer for NamedJsonRenderer with fn render_any( + self : NamedJsonRenderer, + _schema : @core.Schema, +) -> Json { + Json::object({}) +} + +///| +#warnings("-unused_value") +pub impl JsonSchemaRenderer for NamedJsonRenderer with fn render_unknown( + self : NamedJsonRenderer, + _schema : @core.Schema, +) -> Json { + Json::object({}) +} + +///| +#warnings("-unused_value") +pub impl JsonSchemaRenderer for NamedJsonRenderer with fn render_tuple( + self : NamedJsonRenderer, + items : Array[@core.Schema], + _schema : @core.Schema, +) -> Json { + render_json_tuple_type(self, items) +} + +///| +#warnings("-unused_value") +pub impl JsonSchemaRenderer for NamedJsonRenderer with fn render_preprocess( + self : NamedJsonRenderer, + inner : @core.Schema, + _schema : @core.Schema, +) -> Json { + render_json_type(self, inner) +} + // ── Public API ── ///| diff --git a/exporters/json_schema_renderer.mbt b/exporters/json_schema_renderer.mbt index d46c783..9253670 100644 --- a/exporters/json_schema_renderer.mbt +++ b/exporters/json_schema_renderer.mbt @@ -36,6 +36,10 @@ pub(open) trait JsonSchemaRenderer { schema : @core.Schema, ) -> Json fn render_literal(Self, value : Json, schema : @core.Schema) -> Json + fn render_any(Self, schema : @core.Schema) -> Json + fn render_unknown(Self, schema : @core.Schema) -> Json + fn render_tuple(Self, items : Array[@core.Schema], schema : @core.Schema) -> Json + fn render_preprocess(Self, inner : @core.Schema, schema : @core.Schema) -> Json } ///| @@ -49,38 +53,24 @@ pub fn[R : JsonSchemaRenderer] render_json_type( NumberType => renderer.render_number(schema) BooleanType => renderer.render_boolean(schema) NullType => renderer.render_null(schema) - AnyType | UnknownType => Json::object({}) + AnyType => renderer.render_any(schema) + UnknownType => renderer.render_unknown(schema) ObjectType(spec, mode) => renderer.render_object(spec, mode, schema) ArrayType(elem) => renderer.render_array(elem, schema) - TupleType(items) => render_json_tuple_type(renderer, items) + TupleType(items) => renderer.render_tuple(items, schema) OptionalType(inner) => renderer.render_optional(inner, schema) DefaultType(inner, default_val) => renderer.render_default(inner, default_val, schema) EnumType(values) => renderer.render_enum(values, schema) UnionType(schemas) => renderer.render_union(schemas, schema) IntersectionType(schemas) => renderer.render_intersection(schemas, schema) - PreprocessType(_, inner) => render_json_type(renderer, inner) + PreprocessType(_, inner) => renderer.render_preprocess(inner, schema) TransformType(inner, closure) => renderer.render_transform(inner, closure, schema) LiteralType(value) => renderer.render_literal(value, schema) } } -///| -fn[R : JsonSchemaRenderer] render_json_tuple_type( - renderer : R, - items : Array[@core.Schema], -) -> Json { - Json::object({ - "type": Json::string("array"), - "prefixItems": Json::array( - items.map(fn(item) { render_json_type(renderer, item) }), - ), - "minItems": Json::number(items.length().to_double()), - "maxItems": Json::number(items.length().to_double()), - }) -} - ///| /// Named-aware version: emits a `$ref` if schema has a name in the list. pub fn[R : JsonSchemaRenderer] render_json_type_ref( diff --git a/exporters/prompt.mbt b/exporters/prompt.mbt index 4530c46..6d5f9cd 100644 --- a/exporters/prompt.mbt +++ b/exporters/prompt.mbt @@ -250,6 +250,48 @@ pub impl StringRenderer for NamedPromptRenderer with fn render_literal( } } +///| +#warnings("-unused_value") +pub impl StringRenderer for NamedPromptRenderer with fn render_any( + self : NamedPromptRenderer, + _schema : @core.Schema, + _indent : Int, +) -> String { + "any" +} + +///| +#warnings("-unused_value") +pub impl StringRenderer for NamedPromptRenderer with fn render_unknown( + self : NamedPromptRenderer, + _schema : @core.Schema, + _indent : Int, +) -> String { + "unknown" +} + +///| +#warnings("-unused_value") +pub impl StringRenderer for NamedPromptRenderer with fn render_tuple( + self : NamedPromptRenderer, + items : Array[@core.Schema], + _schema : @core.Schema, + indent : Int, +) -> String { + render_tuple_type(self, items, indent) +} + +///| +#warnings("-unused_value") +pub impl StringRenderer for NamedPromptRenderer with fn render_preprocess( + self : NamedPromptRenderer, + inner : @core.Schema, + _schema : @core.Schema, + indent : Int, +) -> String { + render_type(self, inner, indent) +} + ///| /// Public API: convert a schema to a TypeScript-interface-style prompt @core.string. pub fn schema_to_prompt(schema : @core.Schema) -> String { @@ -551,6 +593,19 @@ fn enum_values_to_string(values : Array[String]) -> String { result } +///| +fn[R : StringRenderer] render_tuple_type( + renderer : R, + items : Array[@core.Schema], + indent : Int, +) -> String { + let parts : Array[String] = [] + for item in items { + parts.push(render_type(renderer, item, indent)) + } + "[" + parts.join(", ") + "]" +} + ///| /// Helper: check if a schema has a name present in the named schemas list. fn has_name_in( diff --git a/exporters/prompt_renderer.mbt b/exporters/prompt_renderer.mbt index f847718..89b69d5 100644 --- a/exporters/prompt_renderer.mbt +++ b/exporters/prompt_renderer.mbt @@ -60,6 +60,20 @@ pub(open) trait StringRenderer { indent : Int, ) -> String fn render_literal(Self, value : Json, schema : @core.Schema, indent : Int) -> String + fn render_any(Self, schema : @core.Schema, indent : Int) -> String + fn render_unknown(Self, schema : @core.Schema, indent : Int) -> String + fn render_tuple( + Self, + items : Array[@core.Schema], + schema : @core.Schema, + indent : Int, + ) -> String + fn render_preprocess( + Self, + inner : @core.Schema, + schema : @core.Schema, + indent : Int, + ) -> String } ///| @@ -74,11 +88,11 @@ pub fn[R : StringRenderer] render_type( NumberType => renderer.render_number(schema, indent) BooleanType => renderer.render_boolean(schema, indent) NullType => renderer.render_null(schema, indent) - AnyType => "any" - UnknownType => "unknown" + AnyType => renderer.render_any(schema, indent) + UnknownType => renderer.render_unknown(schema, indent) ObjectType(spec, mode) => renderer.render_object(spec, mode, schema, indent) ArrayType(elem) => renderer.render_array(elem, schema, indent) - TupleType(items) => render_tuple_type(renderer, items, indent) + TupleType(items) => renderer.render_tuple(items, schema, indent) OptionalType(inner) => renderer.render_optional(inner, schema, indent) DefaultType(inner, default_val) => renderer.render_default(inner, default_val, schema, indent) @@ -86,26 +100,14 @@ pub fn[R : StringRenderer] render_type( UnionType(schemas) => renderer.render_union(schemas, schema, indent) IntersectionType(schemas) => renderer.render_intersection(schemas, schema, indent) - PreprocessType(_, inner) => render_type(renderer, inner, indent) + PreprocessType(_, inner) => + renderer.render_preprocess(inner, schema, indent) TransformType(inner, closure) => renderer.render_transform(inner, closure, schema, indent) LiteralType(value) => renderer.render_literal(value, schema, indent) } } -///| -fn[R : StringRenderer] render_tuple_type( - renderer : R, - items : Array[@core.Schema], - indent : Int, -) -> String { - let parts : Array[String] = [] - for item in items { - parts.push(render_type(renderer, item, indent)) - } - "[" + parts.join(", ") + "]" -} - ///| /// Named-aware version: renders a name reference if the schema has a name /// present in the named schemas list, otherwise dispatches normally.