A MoonBit port of ATD (Adaptable Type Definitions) with a MoonBit code generator
Dependencies
| Package | Description |
|---|---|
| bobzhang/atd (src/) | The ATD library: lexer, parser, AST, annotations, semantic checks, inherit expansion, monomorphization, pretty-printing, documentation format, JSON Schema export. Port of upstream atd/src. |
| bobzhang/atd/format | Port of the pretty-printing engine of OCaml's Format module. |
| bobzhang/atd/easy_format | Port of the easy-format library. |
| bobzhang/atd/yojson | Yojson-compatible JSON pretty-printer. |
| bobzhang/atd/atdcat | The atdcat tool as a library. |
| bobzhang/atd/mbtgen | The MoonBit code generator. |
| bobzhang/atd/runtime | Runtime library used by the generated MoonBit code. |
| cmd/atdcat, cmd/atdmbt | Command-line tools (wasm and native), runnable with moonx. |
moonx bobzhang/atd/cmd/atdcat foo.atd
moonx bobzhang/atd/cmd/atdmbt foo.atdmoon add bobzhang/atdmoon run src/cmd/atdcat -- foo.atd
moon build --target native # _build/native/debug/build/cmd/{atdcat,atdmbt}/*.exeatdcat foo.atd # check and pretty-print
atdcat -x foo.atd # monomorphize (expand parametrized types)
atdcat -i foo.atd # expand 'inherit' statements
atdcat -jsonschema root foo.atd # translate to JSON Schema
atdcat -help # all optionsatdmbt foo.atd # creates foo.mbt
atdmbt -o - foo.atd # prints to stdoutimport {
"bobzhang/atd/runtime" @atd_runtime,
}type point = { x : float; ~y <mbt default="1.0"> : float }
type shape = [ Dot | Circle of (point * float) ]pub(all) struct Point {
x : Double
y : Double
} derive(Eq, Debug)
pub fn Point::new(x~ : Double, y? : Double = 1.0) -> Point
pub(all) enum Shape {
Dot
Circle(Point, Double)
} derive(Eq, Debug)
pub fn write_shape(x : Shape) -> Json
pub fn read_shape(x : Json, path : @atd_runtime.Path) -> Shape raise @atd_runtime.JsonError
pub fn shape_of_json(x : Json) -> Shape raise @atd_runtime.JsonError
pub fn shape_of_string(s : StringView) -> Shape raise @atd_runtime.JsonError
pub fn string_of_shape(x : Shape, indent? : Int = 0) -> String
pub impl ToJson for Shapelet s = string_of_shape(Circle(Point::new(x=0), 2.5))
// ["Circle",[{"x":0,"y":1},2.5]]
let shape = shape_of_string(s)| ATD | MoonBit | JSON |
|---|---|---|
| unit | Unit | null |
| bool | Bool | boolean |
| int | Int (range-checked) | number; <json repr="string">: string |
| int <mbt repr="int64"> | Int64 (all digits preserved) | number or string |
| float | Double | number; <json repr="int"> and <json precision="N"> (N significant digits, like atdgen) supported |
| string | String | string |
| abstract | Json | any |
| t list | Array[T] | array |
| (string * t) list <json repr="object"> | Array[(String, T)] | object |
| ... <mbt repr="map"> | Map[K, V] | object or array of pairs |
| t option | T? | "None" or ["Some", x] |
| t nullable | T? | null or x |
| (a * b) | (A, B) | array; (a) is A, () is Unit |
| record | pub(all) struct | object |
| sum type | pub(all) enum | "Tag" or ["Tag", x]; {"Tag": x} with <json repr="object"> |
| t wrap | T, or the type given by <mbt t=...> | same as t |
| mod.t (imported) | @mod.T | |
| 'a t (parametrized) | monomorphized, e.g. (string, int) entry → StringIntEntry |
| Annotation | Position | Meaning |
|---|---|---|
| <mbt name="alias"> | from m <mbt name="alias"> import ... | package alias of an imported module (default: the module's local name) |
| <mbt name="T"> | from m import t <mbt name="T"> | MoonBit name of an imported type, if not the default |
| <mbt name="n"> | field, variant | MoonBit name of a field or constructor |
| <mbt default="expr"> | ~field | default value, a MoonBit expression |
| <mbt repr="map"> | (k * v) list | represent as Map[K, V] |
| <mbt repr="int64"> | int | represent as Int64 |
| <mbt t="T" wrap="f" unwrap="g"> | wrap | custom MoonBit type T, with f : (Inner) -> T and g : (T) -> Inner |
| <mbt derive="Eq, Show"> | type definition | traits to derive (default: Eq, Debug; empty for none) |
let m = @atd.load_string(
"type t = { x : int list }",
inherit_fields=true,
inherit_variants=true,
)
println(@atd.to_string(Module(m)))
println(@atd.print_jsonschema(m, src_name="t.atd", root_type="t"))
let code = @mbtgen.generate_module(m, atd_filename="t.atd")git clone https://github.com/ahrefs/atd .repos/atdmoon test # also with --target native|js|wasm
moonx scripts/regen_fixtures.mbtx # regenerate the code of src/tests/*moonx scripts/gen_compat_tests.mbtx path/to/atdcat.exe && moon fmt
moon build --target native
moonx scripts/fuzz_atdcat.mbtx path/to/atdcat.exe 1000pub(all) struct AnnotSection {
name : String
loc : Loc
fields : Array[AnnotField]
} derive(Eq, Debug)pub(all) struct Import {
loc : Loc
path : Array[String]
annot : Array[AnnotSection]
alias_ : String?
name : String
types : Array[ImportedType]
} derive(Eq, Debug)fn Import::new(loc~ : Loc, path~ : Array[String], annot~ : Array[AnnotSection], alias_? : String, types~ : Array[ImportedType]) -> Importpub(all) struct ImportedType {
params : Array[String]
name : String
annot : Array[AnnotSection]
} derive(Eq, Debug)pub(all) struct JsonAdapter {
ocaml_adapter : OcamlAdapter?
java_adapter : String?
} derive(Eq, Debug)pub(all) struct JsonRecord {
json_keep_nulls : Bool
json_record_adapter : JsonAdapter
} derive(Eq, Debug)pub(all) struct JsonSum {
json_sum_adapter : JsonAdapter
json_open_enum : Bool
json_lowercase_tags : Bool
json_sum_repr : JsonSumRepr
} derive(Eq, Debug)pub(all) enum TypeExpr {
Sum(Loc, Array[Variant], Array[AnnotSection])
Record(Loc, Array[Field], Array[AnnotSection])
Tuple(Loc, Array[Cell], Array[AnnotSection])
List(Loc, TypeExpr, Array[AnnotSection])
Option(Loc, TypeExpr, Array[AnnotSection])
Nullable(Loc, TypeExpr, Array[AnnotSection])
Shared(Loc, TypeExpr, Array[AnnotSection])
Wrap(Loc, TypeExpr, Array[AnnotSection])
Name(Loc, TypeInst, Array[AnnotSection])
Tvar(Loc, String)
} derive(Eq, Debug)fn TypeExpr::map_annot(self : TypeExpr, f : (Array[AnnotSection]) -> Array[AnnotSection] raise AtdError) -> TypeExpr raise AtdErrorfn UniqueNames::new(reserved_identifiers~ : Array[String], reserved_prefixes~ : Array[String], safe_prefix~ : String) -> UniqueNamesfn UniqueNames::translate(self : UniqueNames, src : String, preferred_translation? : String) -> Stringpub(all) struct VisitorHooks {
module_ : ((Module) -> Unit raise AtdError, Module) -> Unit raise AtdError
import_ : ((Import) -> Unit raise AtdError, Import) -> Unit raise AtdError
imported_type : ((ImportedType) -> Unit raise AtdError, ImportedType) -> Unit raise AtdError
type_def : ((TypeDef) -> Unit raise AtdError, TypeDef) -> Unit raise AtdError
type_expr : ((TypeExpr) -> Unit raise AtdError, TypeExpr) -> Unit raise AtdError
variant : ((Variant) -> Unit raise AtdError, Variant) -> Unit raise AtdError
cell : ((Cell) -> Unit raise AtdError, Cell) -> Unit raise AtdError
field : ((Field) -> Unit raise AtdError, Field) -> Unit raise AtdError
}fn annot_create_id() -> Stringfn annot_field(l : Array[AnnotSection], section~ : String, field~ : String) -> (Loc, String?)? raise AtdErrorfn annot_fields(l : Array[AnnotSection], section~ : String, field~ : String) -> Array[(Loc, String?)]fn[T] annot_get_field(l : Array[AnnotSection], parse~ : (String) -> T?, default~ : T, sections~ : Array[String], field~ : String) -> T raise AtdErrorfn[T] annot_get_fields(l : Array[AnnotSection], parse~ : (String) -> T?, sections~ : Array[String], field~ : String) -> Array[T] raise AtdErrorfn annot_get_flag(l : Array[AnnotSection], sections~ : Array[String], field~ : String) -> Bool raise AtdErrorfn annot_get_loc(l : Array[AnnotSection], sections~ : Array[String], field~ : String) -> Loc? raise AtdErrorfn[T] annot_get_opt_field(l : Array[AnnotSection], parse~ : (String) -> T?, sections~ : Array[String], field~ : String) -> T? raise AtdErrorfn annot_get_string(l : Array[AnnotSection], sections~ : Array[String], field~ : String) -> String? raise AtdErrorfn annot_has_field(l : Array[AnnotSection], sections~ : Array[String], field~ : String) -> Bool raise AtdErrorfn annot_reset_ids() -> Unitfn annot_set_field(l : Array[AnnotSection], loc~ : Loc, section~ : String, field~ : String, value : String?) -> Array[AnnotSection]fn compare_strings(a : StringView, b : StringView) -> Intfn jsonschema_of_module(module_ : Module, src_name~ : String, root_type~ : String, version? : JsonschemaVersion, xprop? : Bool) -> Json raise AtdErrorfn load_bytes(src : BytesView, annot_schema? : Array[SchemaSection], expand? : Bool, keep_builtins? : Bool, keep_poly? : Bool, xdebug? : Bool, inherit_fields? : Bool, inherit_variants? : Bool, pos_fname? : String, pos_lnum? : Int, on_warning? : (String) -> Unit) -> Module raise AtdErrorfn load_string(s : String, annot_schema? : Array[SchemaSection], expand? : Bool, keep_builtins? : Bool, keep_poly? : Bool, xdebug? : Bool, inherit_fields? : Bool, inherit_variants? : Bool, pos_fname? : String, pos_lnum? : Int, on_warning? : (String) -> Unit) -> Module raise AtdErrorfn ocaml_escaped(s : StringView) -> Stringfn print_jsonschema(module_ : Module, src_name~ : String, root_type~ : String, version? : JsonschemaVersion, xprop? : Bool) -> String raise AtdErrorfn visit(module_? : ((Module) -> Unit raise AtdError, Module) -> Unit raise AtdError, import_? : ((Import) -> Unit raise AtdError, Import) -> Unit raise AtdError, imported_type? : ((ImportedType) -> Unit raise AtdError, ImportedType) -> Unit raise AtdError, type_def? : ((TypeDef) -> Unit raise AtdError, TypeDef) -> Unit raise AtdError, type_expr? : ((TypeExpr) -> Unit raise AtdError, TypeExpr) -> Unit raise AtdError, variant? : ((Variant) -> Unit raise AtdError, Variant) -> Unit raise AtdError, cell? : ((Cell) -> Unit raise AtdError, Cell) -> Unit raise AtdError, field? : ((Field) -> Unit raise AtdError, Field) -> Unit raise AtdError) -> ((Any) -> Unit raise AtdError)Install
Download zipA MoonBit port of ATD (Adaptable Type Definitions) with a MoonBit code generator
Dependencies