Bring quasipattern syntax into line with constructor syntax for unary records

This commit is contained in:
Tony Garnock-Jones 2021-12-12 23:54:22 +01:00
parent 2940b80563
commit a9a3a8a66d
1 changed files with 23 additions and 18 deletions

View File

@ -2,13 +2,13 @@
/// SPDX-FileCopyrightText: Copyright © 2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com> /// SPDX-FileCopyrightText: Copyright © 2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
import { AnyValue, Ref } from './actor.js'; 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 * as P from './pattern.js';
import { Value, RecordConstructorInfo, stringify, is } from '@preserves/core'; import { Value, RecordConstructorInfo, is } from '@preserves/core';
import { Meta } from '@preserves/schema'; import { Meta, Type, GenType } from '@preserves/schema';
export type DefinitionOrVariantInfo = { export type DefinitionOrVariantInfo = {
schema: Value<unknown>, schema: Value,
imports: unknown, imports: unknown,
definitionName: symbol, definitionName: symbol,
}; };
@ -93,10 +93,11 @@ export function ctor(info: QuasiValueConstructorInfo, ... items: QuasiValue[]):
const definfo = info.schema(); const definfo = info.schema();
const schema = Meta.asSchema(definfo.schema); const schema = Meta.asSchema(definfo.schema);
const def = schema.definitions.get(definfo.definitionName)!; 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 defNameStr = definfo.definitionName.description!;
const ctorArgs = items.slice(); const ctorArgs = items.slice();
function qLiteral(p: Meta.NamedPattern<unknown>): AnyValue { function qLiteral(p: Meta.NamedPattern): AnyValue {
if (p._variant === 'anonymous' && if (p._variant === 'anonymous' &&
p.value._variant === 'SimplePattern' && p.value._variant === 'SimplePattern' &&
p.value.value._variant === 'lit') 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"); throw new Error("Only very simple record labels are supported");
} }
function qNamed(p: Meta.NamedPattern<unknown>): QuasiValue { function qNamed(p: Meta.NamedPattern): QuasiValue {
switch (p._variant) { switch (p._variant) {
case 'anonymous': return qPattern(p.value); case 'anonymous': return qPattern(p.value);
case 'named': return qLookup(p.value); case 'named': return qLookup(p.value);
} }
} }
function qNamedSimple(p: Meta.NamedSimplePattern<unknown>): QuasiValue { function qNamedSimple(p: Meta.NamedSimplePattern): QuasiValue {
switch (p._variant) { switch (p._variant) {
case 'anonymous': return qSimple(p.value); case 'anonymous': return qSimple(p.value);
case 'named': return qLookup(p.value); case 'named': return qLookup(p.value);
} }
} }
function qLookup(b: Meta.Binding<unknown>): QuasiValue { function qLookup(b: Meta.Binding): QuasiValue {
if (ctorArgs.length === 0) { if (ctorArgs.length === 0) {
throw new Error(`Missing dictionary argument to ${defNameStr}`); throw new Error(`Missing dictionary argument to ${defNameStr}`);
} }
const d = ctorArgs[0]; const d = ctorArgs[0];
if (d.type !== 'dict') { if (defType.kind === 'record' && defType.fields.size !== 1) {
throw new Error(`Dictionary argument needed to ${defNameStr}`); 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;
} }
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<unknown>): QuasiValue { function qPattern(p: Meta.Pattern): QuasiValue {
switch (p._variant) { switch (p._variant) {
case 'SimplePattern': return qSimple(p.value); case 'SimplePattern': return qSimple(p.value);
case 'CompoundPattern': return qCompound(p.value); case 'CompoundPattern': return qCompound(p.value);
} }
} }
function qSimple(p: Meta.SimplePattern<unknown>): QuasiValue { function qSimple(p: Meta.SimplePattern): QuasiValue {
switch (p._variant) { switch (p._variant) {
case 'lit': case 'lit':
return lit(p.value as AnyValue); // TODO: hate this cast 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<unknown>): QuasiValue { function qCompound(p: Meta.CompoundPattern): QuasiValue {
switch (p._variant) { switch (p._variant) {
case 'rec': case 'rec':
switch (p.fields._variant) { switch (p.fields._variant) {