From a9a3a8a66da6f39a5aafb88dad3469b21bcca8ce Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sun, 12 Dec 2021 23:54:22 +0100 Subject: [PATCH] Bring quasipattern syntax into line with constructor syntax for unary records --- packages/core/src/runtime/quasivalue.ts | 41 ++++++++++++++----------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/packages/core/src/runtime/quasivalue.ts b/packages/core/src/runtime/quasivalue.ts index 93cb5e7..1eaa899 100644 --- a/packages/core/src/runtime/quasivalue.ts +++ b/packages/core/src/runtime/quasivalue.ts @@ -2,13 +2,13 @@ /// SPDX-FileCopyrightText: Copyright © 2021 Tony Garnock-Jones import { AnyValue, Ref } from './actor.js'; -import { Pattern, fromPattern } from '../gen/dataspacePatterns.js'; +import { Pattern } from '../gen/dataspacePatterns.js'; import * as P from './pattern.js'; -import { Value, RecordConstructorInfo, stringify, is } from '@preserves/core'; -import { Meta } from '@preserves/schema'; +import { Value, RecordConstructorInfo, is } from '@preserves/core'; +import { Meta, Type, GenType } from '@preserves/schema'; export type DefinitionOrVariantInfo = { - schema: Value, + schema: Value, imports: unknown, definitionName: symbol, }; @@ -93,10 +93,11 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): const definfo = info.schema(); const schema = Meta.asSchema(definfo.schema); const def = schema.definitions.get(definfo.definitionName)!; + const defType = GenType.typeForDefinition(r => Type.Type.ref(r.name.description!, null), def); const defNameStr = definfo.definitionName.description!; const ctorArgs = items.slice(); - function qLiteral(p: Meta.NamedPattern): AnyValue { + function qLiteral(p: Meta.NamedPattern): AnyValue { if (p._variant === 'anonymous' && p.value._variant === 'SimplePattern' && p.value.value._variant === 'lit') @@ -114,44 +115,48 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): throw new Error("Only very simple record labels are supported"); } - function qNamed(p: Meta.NamedPattern): QuasiValue { + function qNamed(p: Meta.NamedPattern): QuasiValue { switch (p._variant) { case 'anonymous': return qPattern(p.value); case 'named': return qLookup(p.value); } } - function qNamedSimple(p: Meta.NamedSimplePattern): QuasiValue { + function qNamedSimple(p: Meta.NamedSimplePattern): QuasiValue { switch (p._variant) { case 'anonymous': return qSimple(p.value); case 'named': return qLookup(p.value); } } - function qLookup(b: Meta.Binding): QuasiValue { + function qLookup(b: Meta.Binding): QuasiValue { if (ctorArgs.length === 0) { throw new Error(`Missing dictionary argument to ${defNameStr}`); } const d = ctorArgs[0]; - if (d.type !== 'dict') { - throw new Error(`Dictionary argument needed to ${defNameStr}`); - } - for (const [k, p] of d.entries) { - if (is(k, b.name.description!)) { - return p; + if (defType.kind === 'record' && defType.fields.size !== 1) { + if (d.type !== 'dict') { + throw new Error(`Dictionary argument needed to ${defNameStr}`); } + for (const [k, p] of d.entries) { + if (is(k, b.name.description!)) { + return p; + } + } + return _; + } else { + return d; } - return _; } - function qPattern(p: Meta.Pattern): QuasiValue { + function qPattern(p: Meta.Pattern): QuasiValue { switch (p._variant) { case 'SimplePattern': return qSimple(p.value); case 'CompoundPattern': return qCompound(p.value); } } - function qSimple(p: Meta.SimplePattern): QuasiValue { + function qSimple(p: Meta.SimplePattern): QuasiValue { switch (p._variant) { case 'lit': return lit(p.value as AnyValue); // TODO: hate this cast @@ -166,7 +171,7 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]): } } - function qCompound(p: Meta.CompoundPattern): QuasiValue { + function qCompound(p: Meta.CompoundPattern): QuasiValue { switch (p._variant) { case 'rec': switch (p.fields._variant) {