diff --git a/preserves.nimble b/preserves.nimble index 68c508f..29d948f 100644 --- a/preserves.nimble +++ b/preserves.nimble @@ -1,6 +1,6 @@ # Package -version = "20230512" +version = "20230514" author = "Emery Hemingway" description = "data model and serialization format" license = "Unlicense" diff --git a/src/preserves/preserves_schema_nim.nim b/src/preserves/preserves_schema_nim.nim index 29257ce..44b64d0 100644 --- a/src/preserves/preserves_schema_nim.nim +++ b/src/preserves/preserves_schema_nim.nim @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2021 ☭ Emery Hemingway +# SPDX-FileCopyrightText: ☭ Emery Hemingway # SPDX-License-Identifier: Unlicense ## This module implements Nim code generation from Preserves schemas. @@ -25,6 +25,7 @@ type attrs: Attributes TypeTable = OrderedTable[schema.ModulePath, PNode] Location = tuple[bundle: Bundle, schemaPath: ModulePath] + StringSet = HashSet[string] proc schema(loc: Location): Schema = loc.bundle.modules[loc.schemaPath] @@ -300,7 +301,8 @@ proc isSymbolEnum(loc: Location; sp: SimplePattern): bool = else: discard proc isAny(loc: Location; def: Definition): bool = - if def.orKind == DefinitionKind.Pattern: + case def.orKind + of DefinitionKind.Pattern: if def.pattern.orKind == PatternKind.SimplePattern: case def.pattern.simplePattern.orKind of SimplePatternKind.Ref: @@ -309,6 +311,10 @@ proc isAny(loc: Location; def: Definition): bool = of SimplePatternKind.any: result = true else: discard + of DefinitionKind.and: + # not actually "any" but it will be a Preserve[E] type + result = true + else: discard proc typeIdent(atom: AtomKind): PNode = case atom @@ -684,56 +690,56 @@ proc generateConstProcs(result: var seq[PNode]; scm: Schema, name: string; def: proc generateProcs(result: var seq[PNode]; scm: Schema; name: string; def: Definition) = discard -proc collectRefImports(loc: Location; imports: PNode; pat: Pattern) +proc collectRefImports(imports: var StringSet; loc: Location; pat: Pattern) -proc collectRefImports(loc: Location; imports: PNode; sp: SimplePattern) = +proc collectRefImports(imports: var StringSet; loc: Location; sp: SimplePattern) = case sp.orKind of SimplePatternKind.dictof: - imports.add ident"std/tables" + incl(imports, "std/tables") of SimplePatternKind.Ref: if sp.ref.module != @[] and sp.ref.module != loc.schemaPath: - imports.add ident(string sp.ref.module[0]) + incl(imports, string sp.ref.module[0]) else: discard -proc collectRefImports(loc: Location; imports: PNode; cp: CompoundPattern) = +proc collectRefImports(imports: var StringSet; loc: Location; cp: CompoundPattern) = case cp.orKind of CompoundPatternKind.rec: - collectRefImports(loc, imports, cp.rec.label.pattern) - collectRefImports(loc, imports, cp.rec.fields.pattern) + collectRefImports(imports, loc, cp.rec.label.pattern) + collectRefImports(imports, loc, cp.rec.fields.pattern) of CompoundPatternKind.tuple: - for p in cp.tuple.patterns: collectRefImports(loc, imports, p.pattern) + for p in cp.tuple.patterns: collectRefImports(imports, loc, p.pattern) of CompoundPatternKind.tupleprefix: - for np in cp.tupleprefix.fixed: collectRefImports(loc, imports, np.pattern) - collectRefImports(loc, imports, cp.tupleprefix.variable.pattern) + for np in cp.tupleprefix.fixed: collectRefImports(imports, loc, np.pattern) + collectRefImports(imports, loc, cp.tupleprefix.variable.pattern) of CompoundPatternKind.dict: for nsp in cp.dict.entries.values: - collectRefImports(loc, imports, nsp.pattern) + collectRefImports(imports, loc, nsp.pattern) -proc collectRefImports(loc: Location; imports: PNode; pat: Pattern) = +proc collectRefImports(imports: var StringSet; loc: Location; pat: Pattern) = case pat.orKind of PatternKind.SimplePattern: - collectRefImports(loc, imports, pat.simplePattern) + collectRefImports(imports, loc, pat.simplePattern) of PatternKind.CompoundPattern: - collectRefImports(loc, imports, pat.compoundPattern) + collectRefImports(imports, loc, pat.compoundPattern) -proc collectRefImports(loc: Location; imports: PNode; def: Definition) = +proc collectRefImports(imports: var StringSet; loc: Location; def: Definition) = case def.orKind of DefinitionKind.or: - collectRefImports(loc, imports, def.or.data.pattern0.pattern) - collectRefImports(loc, imports, def.or.data.pattern1.pattern) + collectRefImports(imports, loc, def.or.data.pattern0.pattern) + collectRefImports(imports, loc, def.or.data.pattern1.pattern) for na in def.or.data.patternN: - collectRefImports(loc, imports, na.pattern) + collectRefImports(imports, loc, na.pattern) of DefinitionKind.and: - collectRefImports(loc, imports, def.and.data.pattern0.pattern) - collectRefImports(loc, imports, def.and.data.pattern1.pattern) + collectRefImports(imports, loc, def.and.data.pattern0.pattern) + collectRefImports(imports, loc, def.and.data.pattern1.pattern) for np in def.and.data.patternN: - collectRefImports(loc, imports, np.pattern) + collectRefImports(imports, loc, np.pattern) of DefinitionKind.Pattern: - collectRefImports(loc, imports, def.pattern) + collectRefImports(imports, loc, def.pattern) -proc collectRefImports(loc: Location; imports: PNode; scm: Schema) = +proc collectRefImports(imports: var StringSet; loc: Location; scm: Schema) = for _, def in scm.data.definitions: - collectRefImports(loc, imports, def) + collectRefImports(imports, loc, def) proc mergeType(x: var PNode; y: PNode) = if x.isNil: x = y @@ -774,10 +780,13 @@ proc renderNimBundle*(bundle: Bundle): Table[string, string] = if typepath.hasPrefix(scmPath): add(typeSection, typeDef) - var imports = nkImportStmt.newNode.add( - ident"std/typetraits", - ident"preserves") - collectRefImports(loc, imports, scm) + + let imports = nkImportStmt.newNode.add(ident"preserves") + block: + var importSet: HashSet[string] + collectRefImports(importSet, loc, scm) + for module in importSet: + add(imports, ident(module)) if not embeddableType.isNil: let genericParams = nn(nkGenericParams, nn(nkIdentDefs, embeddedIdent(scm), newEmpty(), newEmpty()))