preserves_schema_nim: merged And patterns with optionals
This commit is contained in:
parent
a52e84dd70
commit
501d6cc012
|
@ -373,15 +373,28 @@ proc isDictionary(loc: Location; pat: Pattern): bool =
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc isDictionary(loc: Location; defAnd: DefinitionAnd): bool =
|
proc isDictionary(loc: Location; defAnd: DefinitionAnd): bool =
|
||||||
result = isDictionary(loc, defAnd.field0.pattern0.pattern)
|
result =
|
||||||
|
isDictionary(loc, defAnd.field0.pattern0.pattern) and
|
||||||
|
isDictionary(loc, defAnd.field0.pattern1.pattern)
|
||||||
|
for np in defAnd.field0.patternN:
|
||||||
|
if result: result = isDictionary(loc, np.pattern)
|
||||||
|
|
||||||
proc isDictionary(loc: Location; def: Definition): bool =
|
proc isDictionary(loc: Location; def: Definition): bool =
|
||||||
case def.orKind
|
case def.orKind
|
||||||
of DefinitionKind.Pattern:
|
of DefinitionKind.Pattern:
|
||||||
result = isDictionary(loc, def.pattern)
|
result = isDictionary(loc, def.pattern)
|
||||||
|
of DefinitionKind.or:
|
||||||
|
result =
|
||||||
|
isDictionary(loc, def.or.field0.pattern0.pattern) and
|
||||||
|
isDictionary(loc, def.or.field0.pattern1.pattern)
|
||||||
|
for np in def.or.field0.patternN:
|
||||||
|
if result: result = isDictionary(loc, np.pattern)
|
||||||
of DefinitionKind.and:
|
of DefinitionKind.and:
|
||||||
result = isDictionary(loc, def.and)
|
result =
|
||||||
else: discard
|
isDictionary(loc, def.and.field0.pattern0.pattern) and
|
||||||
|
isDictionary(loc, def.and.field0.pattern1.pattern)
|
||||||
|
for np in def.and.field0.patternN:
|
||||||
|
if result: result = isDictionary(loc, np.pattern)
|
||||||
|
|
||||||
proc isAny(loc: Location; def: Definition): bool =
|
proc isAny(loc: Location; def: Definition): bool =
|
||||||
case def.orKind
|
case def.orKind
|
||||||
|
@ -577,7 +590,9 @@ proc typeDef(loc: Location; name: string; def: Definition; ty: PNode): PNode =
|
||||||
newEmpty(),
|
newEmpty(),
|
||||||
ty)
|
ty)
|
||||||
of DefinitionKind.and:
|
of DefinitionKind.and:
|
||||||
let pragma = newEmpty()
|
var pragma = nkPragma.newNode
|
||||||
|
if isDictionary(loc, def):
|
||||||
|
pragma.add(ident"preservesDictionary")
|
||||||
nkTypeDef.newTree(
|
nkTypeDef.newTree(
|
||||||
nkPragmaExpr.newTree(
|
nkPragmaExpr.newTree(
|
||||||
name.ident.accQuote.toExport,
|
name.ident.accQuote.toExport,
|
||||||
|
@ -628,20 +643,25 @@ proc addField(recList: PNode; loc: Location; known: var TypeTable; parentName: s
|
||||||
known[typePath] = typeDef(loc, typeName, pattern, fieldSpec.node)
|
known[typePath] = typeDef(loc, typeName, pattern, fieldSpec.node)
|
||||||
recList.add identDef(loc.schema, id, ident(typeName), isEmbedded(loc, pattern))
|
recList.add identDef(loc.schema, id, ident(typeName), isEmbedded(loc, pattern))
|
||||||
|
|
||||||
proc addField(recList: PNode; loc: Location; known: var TypeTable; parentName: string; nsp: NamedSimplePattern; index = 0) =
|
proc addField(recList: PNode; loc: Location; known: var TypeTable; parentName: string; nsp: NamedSimplePattern; index: int; optional: bool) =
|
||||||
let
|
let
|
||||||
label = label(nsp, parentName, index)
|
label = label(nsp, parentName, index)
|
||||||
id = label.toFieldIdent
|
id = label.toFieldIdent
|
||||||
pattern = nsp.pattern
|
pattern = nsp.pattern
|
||||||
if pattern.isRef:
|
if pattern.isRef:
|
||||||
addField(recList, loc, known, pattern, label)
|
var node = typeIdent(loc, pattern).node
|
||||||
|
if optional:
|
||||||
|
node = nkBracketExpr.newTree(ident"Option", node)
|
||||||
|
recList.add identDef(loc.schema, id, node, false)
|
||||||
else:
|
else:
|
||||||
var
|
var
|
||||||
typeName = parentName & capitalizeAscii(label)
|
typeName = parentName & capitalizeAscii(label)
|
||||||
typePath = loc.schemaPath & @[Symbol typeName]
|
typePath = loc.schemaPath & @[Symbol typeName]
|
||||||
fieldSpec = nimTypeOf(loc, known, label, pattern)
|
fieldSpec = nimTypeOf(loc, known, label, pattern)
|
||||||
|
if optional:
|
||||||
|
fieldSpec.node = nkBracketExpr.newTree(ident"Option", fieldSpec.node)
|
||||||
known[typePath] = typeDef(loc, typeName, pattern, fieldSpec.node)
|
known[typePath] = typeDef(loc, typeName, pattern, fieldSpec.node)
|
||||||
recList.add identDef(loc.schema, id, ident(typeName), false)
|
recList.add identDef(loc.schema, id, fieldSpec.node, false)
|
||||||
|
|
||||||
proc addFields(recList: PNode; loc: Location; known: var TypeTable; parentName: string; cp: CompoundPattern): PNode {.discardable.} =
|
proc addFields(recList: PNode; loc: Location; known: var TypeTable; parentName: string; cp: CompoundPattern): PNode {.discardable.} =
|
||||||
let scm = loc.schema
|
let scm = loc.schema
|
||||||
|
@ -677,7 +697,7 @@ proc addFields(recList: PNode; loc: Location; known: var TypeTable; parentName:
|
||||||
variableType.isEmbedded)
|
variableType.isEmbedded)
|
||||||
of CompoundPatternKind.dict:
|
of CompoundPatternKind.dict:
|
||||||
for nameVal, nsp in cp.dict.entries:
|
for nameVal, nsp in cp.dict.entries:
|
||||||
recList.addField(loc, known, $nameVal, nsp)
|
recList.addField(loc, known, $nameVal, nsp, 0, false)
|
||||||
reclist
|
reclist
|
||||||
|
|
||||||
proc addFields(recList: PNode; loc: Location; known: var TypeTable; name: string; pat: SimplePattern): PNode {.discardable.} =
|
proc addFields(recList: PNode; loc: Location; known: var TypeTable; name: string; pat: SimplePattern): PNode {.discardable.} =
|
||||||
|
@ -800,9 +820,88 @@ proc nimTypeOf(loc: Location; known: var TypeTable; name: string; orDef: Definit
|
||||||
newEmpty(),
|
newEmpty(),
|
||||||
nkRecList.newTree(recCase))
|
nkRecList.newTree(recCase))
|
||||||
|
|
||||||
proc nimTypeOf(loc: Location; known: var TypeTable; name: string; def: DefinitionAnd): TypeSpec =
|
proc isAny(sp: SimplePattern): bool =
|
||||||
|
sp.orKind == SimplePatternKind.any
|
||||||
|
|
||||||
|
proc initSimpleAny: SimplePattern =
|
||||||
|
SimplePattern(orKind: SimplePatternKind.any)
|
||||||
|
|
||||||
|
proc asAny(nsp: NamedSimplePattern): NamedSimplePattern =
|
||||||
|
result = nsp
|
||||||
|
case result.orKind
|
||||||
|
of NamedSimplePatternKind.named:
|
||||||
|
if not result.named.pattern.isAny:
|
||||||
|
result.named.pattern = initSimpleAny()
|
||||||
|
of NamedSimplePatternKind.anonymous:
|
||||||
|
if not result.anonymous.isAny:
|
||||||
|
result.anonymous = initSimpleAny()
|
||||||
|
|
||||||
|
type
|
||||||
|
AndEntry = tuple[pattern: NamedSimplePattern, optional: bool]
|
||||||
|
AndEntries = OrderedTable[Value, AndEntry]
|
||||||
|
|
||||||
|
proc collect(entries: var AndEntries; loc: Location; def: Definition; optional: bool) {.gcsafe.}
|
||||||
|
|
||||||
|
proc collect(entries: var AndEntries; loc: Location; pat: SimplePattern; optional: bool) =
|
||||||
|
case pat.orKind
|
||||||
|
of SimplePatternKind.Ref:
|
||||||
|
let (loc, def) = deref(loc, pat.ref)
|
||||||
|
collect(entries, loc, def, optional)
|
||||||
|
else:
|
||||||
|
raiseAssert "cannot collect dictionary entries from " & $pat
|
||||||
|
|
||||||
|
proc collect(entries: var AndEntries; loc: Location; comp: CompoundPattern; optional: bool) =
|
||||||
|
case comp.orKind
|
||||||
|
of CompoundPatternKind.dict:
|
||||||
|
for key, nsp in comp.dict.entries.pairs:
|
||||||
|
if entries.hasKey(key):
|
||||||
|
entries[key] = (asAny nsp, optional)
|
||||||
|
else:
|
||||||
|
entries[key] = (nsp, optional)
|
||||||
|
else:
|
||||||
|
raiseAssert "cannot collect dictionary entries from " & $comp
|
||||||
|
|
||||||
|
proc collect(entries: var AndEntries; loc: Location; pat: Pattern; optional: bool) =
|
||||||
|
case pat.orKind
|
||||||
|
of PatternKind.SimplePattern:
|
||||||
|
collect(entries, loc, pat.simplepattern, optional)
|
||||||
|
of PatternKind.CompoundPattern:
|
||||||
|
collect(entries, loc, pat.compoundpattern, optional)
|
||||||
|
|
||||||
|
proc collect(entries: var AndEntries; loc: Location; def: Definition; optional: bool) =
|
||||||
|
case def.orKind
|
||||||
|
of DefinitionKind.or:
|
||||||
|
collect(entries, loc, def.or.field0.pattern0.pattern, true)
|
||||||
|
collect(entries, loc, def.or.field0.pattern1.pattern, true)
|
||||||
|
for np in def.or.field0.patternN:
|
||||||
|
collect(entries, loc, np.pattern, true)
|
||||||
|
of DefinitionKind.and:
|
||||||
|
collect(entries, loc, def.and.field0.pattern0.pattern, optional)
|
||||||
|
collect(entries, loc, def.and.field0.pattern1.pattern, optional)
|
||||||
|
for np in def.and.field0.patternN:
|
||||||
|
collect(entries, loc, np.pattern, optional)
|
||||||
|
of DefinitionKind.Pattern:
|
||||||
|
collect(entries, loc, def.pattern, optional)
|
||||||
|
|
||||||
|
proc toDef(a: DefinitionAnd): Definition =
|
||||||
|
Definition(orKind: DefinitionKind.and, `and`: a)
|
||||||
|
|
||||||
|
proc nimTypeOf(loc: Location; known: var TypeTable; name: string; andDef: DefinitionAnd): TypeSpec =
|
||||||
|
var def = andDef.toDef
|
||||||
if isDictionary(loc, def):
|
if isDictionary(loc, def):
|
||||||
result.node = nkBracketExpr.newTree(ident"Table", ident"Symbol", ident"Value")
|
var
|
||||||
|
recList = nkRecList.newNode
|
||||||
|
entries: AndEntries
|
||||||
|
collect(entries, loc, def, false)
|
||||||
|
sort(entries) do (x, y: (Value, AndEntry)) -> int:
|
||||||
|
preserves.cmp(x[0], y[0])
|
||||||
|
# TODO: sort the entries
|
||||||
|
var i = 0
|
||||||
|
for key, (nsp, opt) in entries.pairs:
|
||||||
|
recList.addField(loc, known, name, nsp, i, opt)
|
||||||
|
inc(i)
|
||||||
|
result.node = nkObjectTy.newTree(
|
||||||
|
newEmpty(), newEmpty(), recList)
|
||||||
else:
|
else:
|
||||||
result.node = ident"Value"
|
result.node = ident"Value"
|
||||||
|
|
||||||
|
@ -864,7 +963,7 @@ proc collectRefImports(imports: var StringSet; loc: Location; def: Definition) =
|
||||||
collectRefImports(imports, loc, na.pattern)
|
collectRefImports(imports, loc, na.pattern)
|
||||||
of DefinitionKind.and:
|
of DefinitionKind.and:
|
||||||
if isDictionary(loc, def):
|
if isDictionary(loc, def):
|
||||||
incl(imports, "std/tables")
|
incl(imports, "std/options")
|
||||||
collectRefImports(imports, loc, def.and.field0.pattern0.pattern)
|
collectRefImports(imports, loc, def.and.field0.pattern0.pattern)
|
||||||
collectRefImports(imports, loc, def.and.field0.pattern1.pattern)
|
collectRefImports(imports, loc, def.and.field0.pattern1.pattern)
|
||||||
for np in def.and.field0.patternN:
|
for np in def.and.field0.patternN:
|
||||||
|
|
Loading…
Reference in New Issue