schema: every function a fn value can name, not only zero-argument ones - fn_type is the type a field sees with the states stripped, spelled as a field's type is (fn(A,B)->R), with params beside states; reseeded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
863b9712f9
commit
b647964839
7 changed files with 18325 additions and 18333 deletions
|
|
@ -661,8 +661,10 @@ object with `"schema_version": 1`:
|
|||
"index": 0, "file": ..., "line": ..., "col": ..., "fields": [{"name", "value", "file", "line",
|
||||
"col"}]}`), with `contributors`: which resource file or file of `def`s brought which keys in;
|
||||
- `consts` - every const: its type, its value as written, its module and doc;
|
||||
- `functions` - every function a `fn` value can name with no arguments (the states it takes are the
|
||||
runtime's to supply): its return type, `fn_type` and signature.
|
||||
- `functions` - every function a `fn` value can name, exported or not: its module, return type,
|
||||
`params` (the arguments a caller passes), `states` (what the runtime supplies), `signature`, and
|
||||
`fn_type` - the type a `fn` field sees, the states stripped, spelled as a field's type is
|
||||
(`fn(NpcPerson,float)->bool`), so matching a function to a field is comparing two strings.
|
||||
|
||||
Each list is sorted by name (then file and line), a registry's entries are in index order, and the
|
||||
paths are the ones the compiler read, so two runs over the same source write the same file. The
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ schema [file] [-o FILE]`) writes what the compiler resolved once the program typ
|
|||
record with its fields' types, defaults, doc comments and places; every registry with its record,
|
||||
prefix, resource file, openness and its entries in their final order after the open-registry merge
|
||||
(key, constant, index, file:line:col of the entry and of each field value, and which file brought
|
||||
which entries in); every const; and the functions a `fn` value can name with no arguments.
|
||||
which entries in); every const; and every function a `fn` value can name, with the `fn_type` a field sees (its states stripped).
|
||||
Deterministic, `"schema_version": 1`. Fields and registries carry editor attributes on the existing
|
||||
`@` syntax - `@Ref(Registry)`, `@OneOf(PREFIX_)`, `@Range(lo, hi)`, `@Unit("m/s")`, `@Asset("gltf")`,
|
||||
`@Color`, and `@AppendOnly` / `@ByKey` on a registry - which change nothing but go into the schema;
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ program Attributes {
|
|||
const CAMP_TOOLS: int = 2 * VD_COUNT # how many a camp can carry
|
||||
# the tool a new camp starts with
|
||||
function first_tool() -> string { return Tools[0].name }
|
||||
# what a pack of n of a tool weighs - a fn(Tool,int)->float an editor can offer a field of that type
|
||||
function pack_weight(t: Tool, n: int) -> float { return t.weight * float(n) }
|
||||
entry {
|
||||
print(`{TL_COUNT} {Tools[TL_LANTERN].seller} {Tools[TL_LANTERN].name} {CAMP_TOOLS / 2}`)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
# entries in their final order - key, constant, index, where each entry and each of its
|
||||
# field values is written - with which file contributed which entries
|
||||
# consts every const: its type and its value as written
|
||||
# functions every function a `fn` value can name with no arguments (the states it takes are the
|
||||
# runtime's to supply)
|
||||
# functions every function a `fn` value can name: fn_type is the type a field sees, the states
|
||||
# stripped (the runtime supplies them), written as a field's type is ("fn(A,B)->R")
|
||||
#
|
||||
# Deterministic: each list sorted by name (then file and line), an entry list in index order, the
|
||||
# paths as the compiler read them, and nothing about the run. The engine's runtime is left out.
|
||||
|
|
@ -529,13 +529,6 @@ function sc_functions(b: Buf) -> void {
|
|||
let d = prog[i]
|
||||
var ok = d.kind == N_FN and d.s != null and d.tps == null and sc_written(d)
|
||||
if ok { ok = not sc_generic_fn(gens, d.s) }
|
||||
if ok {
|
||||
var k = 0
|
||||
while k < len(d.kids) {
|
||||
if d.kids[k].kind == N_PARAM and not sc_is_state_param(d.kids[k]) { ok = false }
|
||||
k += 1
|
||||
}
|
||||
}
|
||||
if ok { push(xs, i); push(keys, sc_key(sc_name(d.s), d.file, d.line)) }
|
||||
else { push(keys, "") }
|
||||
i += 1
|
||||
|
|
@ -550,6 +543,8 @@ function sc_functions(b: Buf) -> void {
|
|||
function sc_function(b: Buf, d: Node, first: bool) -> void {
|
||||
let ret = sc_ty(d.ty)
|
||||
var ps: pointer = ""
|
||||
var args: pointer = ""
|
||||
var params: pointer = ""
|
||||
var states: pointer = ""
|
||||
var k = 0
|
||||
while k < len(d.kids) {
|
||||
|
|
@ -561,8 +556,15 @@ function sc_function(b: Buf, d: Node, first: bool) -> void {
|
|||
ps = ps + p.s + ": " + mt + sc_ty(p.ty)
|
||||
let bq = buf_new()
|
||||
jq_put(bq, sc_ty(p.ty))
|
||||
if sc_is_state_param(p) {
|
||||
if len(states) > 0 { states = states + ", " }
|
||||
states = states + buf_str(bq)
|
||||
} else {
|
||||
if len(args) > 0 { args = args + "," }
|
||||
args = args + sc_ty(p.ty)
|
||||
if len(params) > 0 { params = params + ", " }
|
||||
params = params + buf_str(bq)
|
||||
}
|
||||
}
|
||||
k += 1
|
||||
}
|
||||
|
|
@ -578,7 +580,10 @@ function sc_function(b: Buf, d: Node, first: bool) -> void {
|
|||
buf_puts(b, ", \"returns\": ")
|
||||
jq_put(b, ret)
|
||||
buf_puts(b, ", \"fn_type\": ")
|
||||
jq_put(b, `fn() -> {ret}`)
|
||||
jq_put(b, "fn(" + args + ")->" + ret)
|
||||
buf_puts(b, ", \"params\": [")
|
||||
buf_puts(b, params)
|
||||
buf_puts(b, "]")
|
||||
buf_puts(b, ", \"signature\": ")
|
||||
jq_put(b, `function {sc_name(d.s)}({ps}) -> {ret}`)
|
||||
buf_puts(b, ", \"states\": [")
|
||||
|
|
|
|||
17835
selfhost/ludicc.seed.ll
17835
selfhost/ludicc.seed.ll
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -1234,6 +1234,7 @@ function cmd_dev_test() -> int {
|
|||
reject_case("rejected/ref_unknown", "field Tool.seller: @Ref(Vendorz) names no registry", "@Ref names a registry that exists")
|
||||
schema_case("lang/attributes", "{\"name\": \"weight\", \"type\": \"float\", \"default\": \"1.0\", \"file\": \"examples/lang/attributes.ludic\", \"line\": 24, \"col\": 33, \"attributes\": [{\"name\": \"Range\", \"args\": [0, 20.5]}, {\"name\": \"Unit\", \"args\": [\"kg\"]}]", "--emit-schema: a field's type, default, place and attributes")
|
||||
schema_case("lang/attributes", "{\"key\": \"lantern\", \"constant\": \"TL_LANTERN\", \"index\": 1, \"file\": \"examples/lang/data/attr_tools.lres\", \"line\": 3, \"col\": 1", "--emit-schema: a resource entry's constant, index and place")
|
||||
schema_case("lang/attributes", "\"fn_type\": \"fn(Tool,int)->float\", \"params\": [\"Tool\", \"int\"]", "--emit-schema: a function with arguments, its fn_type spelled as a field's")
|
||||
reject_case("rejected/registry_twice", "def Furnishings crate is declared twice", "a registry's key is declared once")
|
||||
reject_case("rejected/registry_field", "Furnishing has no field colour", "a def's fields are the record's")
|
||||
feat_case("modules/open_registry", "", "clock animals weather / 2 2 3", "open_registry.ludic (L8+L3: an open registry takes other modules' defs; its own entries first, then by module name)")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue