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>
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<unknown>,
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<unknown>): 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<unknown>): 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<unknown>): 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<unknown>): 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<unknown>): 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<unknown>): 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<unknown>): QuasiValue {
function qCompound(p: Meta.CompoundPattern): QuasiValue {
switch (p._variant) {
case 'rec':
switch (p.fields._variant) {