schema: use Preserve[E] for records without literal labels

This commit is contained in:
Emery Hemingway 2023-05-17 09:12:08 +01:00
parent b3f40347e8
commit 03876850e5
3 changed files with 38 additions and 15 deletions

View File

@ -1,6 +1,6 @@
# Package
version = "20230516"
version = "20230517"
author = "Emery Hemingway"
description = "data model and serialization format"
license = "Unlicense"

View File

@ -1,4 +1,4 @@
include_rules
: foreach preserves_schema_nim.nim schemac.nim |> !nim |> $(BIN_DIR)/%B | $(BIN_DIR)/<%B>
NIM_FLAGS += --path:$(TUP_CWD)/..
: foreach preserves_schema_nim.nim schemac.nim schemaparse.nim |> !nim_bin |> $(BIN_DIR)/%B | $(BIN_DIR)/<%B>
: foreach *hooks.nim |> !nim_check |>

View File

@ -240,6 +240,7 @@ proc isRecursive(loc: Location; p: Definition|DefinitionOr|Pattern|CompoundPatte
recursive in attrs(loc, p)
proc isLiteral(loc: Location; def: Definition): bool {.gcsafe.}
proc isLiteral(loc: Location; pat: Pattern): bool {.gcsafe.}
proc isLiteral(loc: Location; sp: SimplePattern): bool =
case sp.orKind
@ -253,6 +254,13 @@ proc isLiteral(loc: Location; sp: SimplePattern): bool =
result = isLiteral(loc, sp.embedded.interface)
else: discard
proc isLiteral(loc: Location; np: NamedPattern): bool =
case np.orKind
of NamedPatternKind.named:
isLiteral(loc, np.named.pattern)
of NamedPatternKind.anonymous:
isLiteral(loc, np.anonymous)
proc isLiteral(loc: Location; pat: Pattern): bool =
case pat.orKind
of PatternKind.SimplePattern:
@ -303,7 +311,8 @@ proc isSymbolEnum(loc: Location; sp: SimplePattern): bool =
proc isAny(loc: Location; def: Definition): bool =
case def.orKind
of DefinitionKind.Pattern:
if def.pattern.orKind == PatternKind.SimplePattern:
case def.pattern.orKind
of PatternKind.SimplePattern:
case def.pattern.simplePattern.orKind
of SimplePatternKind.Ref:
var (loc, def) = deref(loc, def.pattern.simplePattern.ref)
@ -311,6 +320,11 @@ proc isAny(loc: Location; def: Definition): bool =
of SimplePatternKind.any:
result = true
else: discard
of PatternKind.CompoundPattern:
case def.pattern.compoundpattern.orKind
of CompoundPatternKind.rec:
result = not isLiteral(loc, def.pattern.compoundpattern.rec.label)
else: discard
of DefinitionKind.and:
# not actually "any" but it will be a Preserve[E] type
result = true
@ -458,15 +472,18 @@ proc typeDef(loc: Location; name: string; pat: Pattern; ty: PNode): PNode =
of PatternKind.CompoundPattern:
case pat.compoundPattern.orKind
of CompoundPatternKind.rec:
nn(nkTypeDef,
nn(nkPragmaExpr,
id,
nn(nkPragma,
nn(nkExprColonExpr,
ident"preservesRecord",
PNode(kind: nkStrLit, strVal: pat.compoundPattern.rec.label.idStr)))),
embedParams,
ty)
if isLiteral(loc, pat.compoundPattern.rec.label):
nn(nkTypeDef,
nn(nkPragmaExpr,
id,
nn(nkPragma,
nn(nkExprColonExpr,
ident"preservesRecord",
PNode(kind: nkStrLit, strVal: pat.compoundPattern.rec.label.idStr)))),
embedParams,
ty)
else:
nn(nkTypeDef, name.ident.toExport, embedParams, ty)
of CompoundPatternKind.tuple, CompoundPatternKind.tuplePrefix:
nn(nkTypeDef,
nn(nkPragmaExpr, id, nn(nkPragma, ident"preservesTuple")),
@ -584,12 +601,18 @@ proc nimTypeOf(loc: Location; known: var TypeTable; nsp: NamedSimplePattern; nam
of NamedsimplepatternKind.anonymous:
nimTypeOf(loc, known, nsp.anonymous, name)
proc nimTypeOf(loc: Location; known: var TypeTable; rec: CompoundPatternRec; name: string): TypeSpec =
if isLiteral(loc, rec.label):
result.node = nn(nkObjectTy,
newEmpty(), newEmpty(),
nn(nkRecList).addFields(loc, known, rec.fields.pattern, name))
else:
result.node = preserveIdent(loc.schema)
proc nimTypeOf(loc: Location; known: var TypeTable; cp: CompoundPattern; name: string): TypeSpec =
case cp.orKind
of CompoundPatternKind.`rec`:
result.node = nn(nkObjectTy,
newEmpty(), newEmpty(),
nn(nkRecList).addFields(loc, known, cp.rec.fields.pattern, name))
result = nimTypeOf(loc, known, cp.rec, name)
of CompoundPatternKind.`tuple`, CompoundPatternKind.`tupleprefix`:
result.node = nn(nkObjectTy,
newEmpty(), newEmpty(),