2021-05-24 10:05:02 +00:00
|
|
|
import * as M from "../meta";
|
2021-05-23 22:15:31 +00:00
|
|
|
import { ANY_TYPE, FieldType, FieldMap, SimpleType, Type } from "./type";
|
2021-03-19 22:42:43 +00:00
|
|
|
|
2021-05-23 22:15:31 +00:00
|
|
|
export type RefResolver = (ref: M.Ref) => FieldType;
|
2021-05-21 13:49:06 +00:00
|
|
|
|
|
|
|
export function typeForDefinition(resolver: RefResolver, d: M.Definition): Type {
|
2021-05-20 20:34:20 +00:00
|
|
|
switch (d._variant) {
|
|
|
|
case 'or':
|
|
|
|
return Type.union(
|
2021-05-21 09:20:25 +00:00
|
|
|
new Map([d.pattern0, d.pattern1, ... d.patternN].map(a =>
|
2021-05-21 13:49:06 +00:00
|
|
|
[a.variantLabel, typeFor(resolver, a.pattern)])));
|
2021-05-20 20:34:20 +00:00
|
|
|
case 'and':
|
2021-05-21 13:49:06 +00:00
|
|
|
return typeForIntersection(resolver, [d.pattern0, d.pattern1, ... d.patternN]);
|
2021-05-20 20:34:20 +00:00
|
|
|
case 'Pattern':
|
2021-05-21 13:49:06 +00:00
|
|
|
return typeFor(resolver, d.value);
|
2021-03-19 22:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-21 13:49:06 +00:00
|
|
|
export function typeForIntersection(resolver: RefResolver, ps: M.NamedPattern[]): SimpleType {
|
2021-05-20 20:34:20 +00:00
|
|
|
const fs = new Map();
|
2021-05-21 13:49:06 +00:00
|
|
|
ps.forEach(p => gatherFields(fs, resolver, p));
|
2021-05-20 20:34:20 +00:00
|
|
|
return fs.size > 0 ? Type.record(fs) : Type.unit();
|
2021-03-19 22:42:43 +00:00
|
|
|
}
|
|
|
|
|
2021-05-21 13:49:06 +00:00
|
|
|
export function typeFor(resolver: RefResolver, p: M.Pattern): SimpleType {
|
2021-03-22 11:13:34 +00:00
|
|
|
if (p._variant === 'SimplePattern') {
|
2021-05-21 13:49:06 +00:00
|
|
|
return simpleType(resolver, p.value);
|
2021-03-19 22:42:43 +00:00
|
|
|
} else {
|
2021-05-23 22:15:31 +00:00
|
|
|
return typeForIntersection(resolver, [M.NamedPattern.anonymous(p)]);
|
2021-03-19 22:42:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-23 22:15:31 +00:00
|
|
|
export function simpleType(resolver: RefResolver, p: M.SimplePattern): FieldType {
|
2021-03-22 11:13:34 +00:00
|
|
|
switch (p._variant) {
|
|
|
|
case 'any':
|
2021-03-19 22:42:43 +00:00
|
|
|
return ANY_TYPE;
|
2021-03-22 11:13:34 +00:00
|
|
|
case 'atom':
|
|
|
|
switch (p.atomKind._variant) {
|
2021-10-11 10:56:53 +00:00
|
|
|
case 'Boolean': return Type.ref(`boolean`, null);
|
|
|
|
case 'Float': return Type.ref(`number`, null);
|
|
|
|
case 'Double': return Type.ref(`number`, null);
|
|
|
|
case 'SignedInteger': return Type.ref(`number`, null);
|
|
|
|
case 'String': return Type.ref(`string`, null);
|
|
|
|
case 'ByteString': return Type.ref(`_.Bytes`, null);
|
|
|
|
case 'Symbol': return Type.ref(`symbol`, null);
|
2021-03-19 22:42:43 +00:00
|
|
|
}
|
2021-05-17 12:54:06 +00:00
|
|
|
case 'embedded':
|
2021-10-11 10:56:53 +00:00
|
|
|
return Type.ref(`_embedded`, null);
|
2021-03-22 11:13:34 +00:00
|
|
|
case 'lit':
|
2021-03-19 22:42:43 +00:00
|
|
|
return Type.unit();
|
2021-05-23 22:15:31 +00:00
|
|
|
case 'seqof':
|
|
|
|
return Type.array(simpleType(resolver, p.pattern));
|
|
|
|
case 'setof':
|
|
|
|
return Type.set(simpleType(resolver, p.pattern));
|
|
|
|
case 'dictof':
|
|
|
|
return Type.dictionary(simpleType(resolver, p.key), simpleType(resolver, p.value));
|
2021-03-22 11:13:34 +00:00
|
|
|
case 'Ref':
|
2021-05-21 13:49:06 +00:00
|
|
|
return resolver(p.value);
|
2021-03-19 22:42:43 +00:00
|
|
|
default:
|
|
|
|
((_p: never) => {})(p);
|
|
|
|
throw new Error("Unreachable");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-21 13:49:06 +00:00
|
|
|
function compoundFields(fs: FieldMap, resolver: RefResolver, p: M.CompoundPattern): void {
|
2021-03-22 11:13:34 +00:00
|
|
|
switch (p._variant) {
|
|
|
|
case 'rec':
|
2021-05-21 13:49:06 +00:00
|
|
|
gatherFields(fs, resolver, p.label);
|
|
|
|
gatherFields(fs, resolver, p.fields);
|
2021-03-19 22:42:43 +00:00
|
|
|
break;
|
2021-03-22 11:13:34 +00:00
|
|
|
case 'tuple':
|
2021-05-21 13:49:06 +00:00
|
|
|
p.patterns.forEach(pp => gatherFields(fs, resolver, pp));
|
2021-03-19 22:42:43 +00:00
|
|
|
break;
|
2021-06-25 07:45:07 +00:00
|
|
|
case 'tuplePrefix':
|
2021-05-21 13:49:06 +00:00
|
|
|
p.fixed.forEach(pp => gatherFields(fs, resolver, pp));
|
2021-05-23 22:15:31 +00:00
|
|
|
gatherFields(fs, resolver, M.promoteNamedSimplePattern(p.variable));
|
2021-03-19 22:42:43 +00:00
|
|
|
break;
|
2021-03-22 11:13:34 +00:00
|
|
|
case 'dict':
|
2021-05-25 09:01:55 +00:00
|
|
|
p.entries.forEach((n, _k) =>
|
|
|
|
gatherFields(fs, resolver, M.promoteNamedSimplePattern(n)));
|
2021-03-19 22:42:43 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
((_p: never) => {})(p);
|
|
|
|
throw new Error("Unreachable");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-21 13:49:06 +00:00
|
|
|
function gatherFields(fs: FieldMap, resolver: RefResolver, n: M.NamedPattern): void {
|
2021-03-22 11:13:34 +00:00
|
|
|
if (n._variant === 'named') {
|
2021-05-23 22:15:31 +00:00
|
|
|
const t = simpleType(resolver, n.value.pattern);
|
|
|
|
if (t.kind !== 'unit') {
|
|
|
|
fs.set(n.value.name.description!, t);
|
|
|
|
}
|
2021-03-22 11:13:34 +00:00
|
|
|
} else if (n.value._variant === 'CompoundPattern') {
|
2021-05-21 13:49:06 +00:00
|
|
|
compoundFields(fs, resolver, n.value.value);
|
2021-03-19 22:42:43 +00:00
|
|
|
}
|
|
|
|
}
|