forked from syndicate-lang/preserves
Compare commits
1 Commits
main
...
js_typed_r
Author | SHA1 | Date |
---|---|---|
Tony Garnock-Jones | cff1a3d318 |
|
@ -69,9 +69,9 @@ export function strip<T extends object = DefaultPointer>(v: Value<T>, depth: num
|
||||||
function walk(v: Value<T>): Value<T> { return step(v, nextDepth); }
|
function walk(v: Value<T>): Value<T> { return step(v, nextDepth); }
|
||||||
|
|
||||||
if (Record.isRecord<T>(v.item)) {
|
if (Record.isRecord<T>(v.item)) {
|
||||||
return new Record(step(v.item.label, depth), v.item.map(walk));
|
return Record(step(v.item.label, depth), v.item.map(walk));
|
||||||
} else if (Array.isArray(v.item)) {
|
} else if (Array.isArray(v.item)) {
|
||||||
return v.item.map(walk);
|
return (v.item as Array<Value<T>>).map(walk);
|
||||||
} else if (Set.isSet<T>(v.item)) {
|
} else if (Set.isSet<T>(v.item)) {
|
||||||
return v.item.map(walk);
|
return v.item.map(walk);
|
||||||
} else if (Dictionary.isDictionary<Value<T>, T>(v.item)) {
|
} else if (Dictionary.isDictionary<Value<T>, T>(v.item)) {
|
||||||
|
|
|
@ -178,7 +178,7 @@ export class Decoder<T extends object> {
|
||||||
case Tag.Record: {
|
case Tag.Record: {
|
||||||
const vs = this.nextvalues();
|
const vs = this.nextvalues();
|
||||||
if (vs.length === 0) throw new DecodeError("Too few elements in encoded record");
|
if (vs.length === 0) throw new DecodeError("Too few elements in encoded record");
|
||||||
return this.wrap(new Record(vs[0], vs.slice(1)));
|
return this.wrap(Record(vs[0], vs.slice(1)));
|
||||||
}
|
}
|
||||||
case Tag.Sequence: return this.wrap(this.nextvalues());
|
case Tag.Sequence: return this.wrap(this.nextvalues());
|
||||||
case Tag.Set: return this.wrap(new Set(this.nextvalues()));
|
case Tag.Set: return this.wrap(new Set(this.nextvalues()));
|
||||||
|
|
|
@ -11,7 +11,7 @@ export interface FoldMethods<T extends object, R> {
|
||||||
bytes(b: Bytes): R;
|
bytes(b: Bytes): R;
|
||||||
symbol(s: symbol): R;
|
symbol(s: symbol): R;
|
||||||
|
|
||||||
record(r: Record<T>, k: Fold<T, R>): R;
|
record(r: Record<any, any, T>, k: Fold<T, R>): R;
|
||||||
array(a: Array<Value<T>>, k: Fold<T, R>): R;
|
array(a: Array<Value<T>>, k: Fold<T, R>): R;
|
||||||
set(s: Set<T>, k: Fold<T, R>): R;
|
set(s: Set<T>, k: Fold<T, R>): R;
|
||||||
dictionary(d: Dictionary<Value<T>, T>, k: Fold<T, R>): R;
|
dictionary(d: Dictionary<Value<T>, T>, k: Fold<T, R>): R;
|
||||||
|
@ -43,8 +43,8 @@ export abstract class ValueFold<T extends object, R extends object = T> implemen
|
||||||
symbol(s: symbol): Value<R> {
|
symbol(s: symbol): Value<R> {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
record(r: Record<T>, k: Fold<T, Value<R>>): Value<R> {
|
record(r: Record<any, any, T>, k: Fold<T, Value<R>>): Value<R> {
|
||||||
return new Record(k(r.label), r.map(k));
|
return Record(k(r.label), r.map(k));
|
||||||
}
|
}
|
||||||
array(a: Value<T>[], k: Fold<T, Value<R>>): Value<R> {
|
array(a: Value<T>[], k: Fold<T, Value<R>>): Value<R> {
|
||||||
return a.map(k);
|
return a.map(k);
|
||||||
|
|
|
@ -1,14 +1,78 @@
|
||||||
import { Tag } from "./constants";
|
import { Tag } from "./constants";
|
||||||
import { Encoder } from "./codec";
|
import { Encoder } from "./codec";
|
||||||
import { PreserveOn } from "./symbols";
|
import { PreserveOn } from "./symbols";
|
||||||
import { DefaultPointer, fromJS, is, Value } from "./values";
|
import { DefaultPointer, is, Value } from "./values";
|
||||||
|
import { Tuple, TupleMap } from "./tuple";
|
||||||
|
|
||||||
export const IsPreservesRecord = Symbol.for('IsPreservesRecord');
|
export const IsPreservesRecord = Symbol.for('IsPreservesRecord');
|
||||||
|
|
||||||
export class Record<T extends object = DefaultPointer> extends Array<Value<T>> {
|
export type Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>
|
||||||
|
= { readonly label: LabelType } & FieldsType & RecordImpl<T>;
|
||||||
|
|
||||||
|
export interface RecordConstructor<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer> {
|
||||||
|
(...fields: FieldsType): Record<LabelType, FieldsType, T>;
|
||||||
|
constructorInfo: RecordConstructorInfo<LabelType, T>;
|
||||||
|
isClassOf(v: any): v is Record<LabelType, FieldsType, T>;
|
||||||
|
_: { [getter: string]: (r: any) => Value<T> | undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RecordConstructorInfo<LabelType extends Value<T>, T extends object = DefaultPointer> {
|
||||||
|
label: LabelType;
|
||||||
|
arity: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Record<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>
|
||||||
|
(label: LabelType, fields: FieldsType)
|
||||||
|
: Record<LabelType, FieldsType, T>
|
||||||
|
{
|
||||||
|
return new RecordImpl(label, fields) as unknown as Record<LabelType, FieldsType, T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Record {
|
||||||
|
export function fallbackToString(_f: Value<any>): string {
|
||||||
|
return '<unprintable_preserves_field_value>';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeConstructor<T extends object = DefaultPointer>(): <LabelType extends Value<T>, FieldNamesType extends Tuple<string>, FieldsType extends TupleMap<FieldNamesType, Value<T>>>(label: LabelType, fieldNames: FieldNamesType) => RecordConstructor<LabelType, FieldsType, T> {
|
||||||
|
return <LabelType extends Value<T>, FieldNamesType extends Tuple<string>, FieldsType extends TupleMap<FieldNamesType, Value<T>>>(label: LabelType, fieldNames: FieldNamesType) => {
|
||||||
|
const arity = fieldNames.length;
|
||||||
|
const ctor: RecordConstructor<LabelType, FieldsType, T> = (...fields: FieldsType): Record<LabelType, FieldsType, T> => {
|
||||||
|
if (fields.length !== arity) {
|
||||||
|
throw new Error("Record: cannot instantiate " + (label && (label as any).toString()) +
|
||||||
|
" expecting " + arity + " fields with " + fields.length + " fields");
|
||||||
|
}
|
||||||
|
return Record(label, fields);
|
||||||
|
};
|
||||||
|
const constructorInfo = { label, arity };
|
||||||
|
ctor.constructorInfo = constructorInfo;
|
||||||
|
ctor.isClassOf = (v: any): v is Record<LabelType, FieldsType, T> => Record.isClassOf(constructorInfo, v);
|
||||||
|
ctor._ = {};
|
||||||
|
fieldNames.forEach((name, i) => {
|
||||||
|
ctor._[name] = function (r: any): Value<T> | undefined {
|
||||||
|
if (!ctor.isClassOf(r)) {
|
||||||
|
throw new Error("Record: attempt to retrieve field "+(label as any).toString()+"."+name+
|
||||||
|
" from non-"+(label as any).toString()+": "+(r && r.toString()));
|
||||||
|
}
|
||||||
|
return r[i];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return ctor;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isRecord<T extends object = DefaultPointer>(x: any): x is Record<Value<T>, Tuple<Value<T>>, T> {
|
||||||
|
return !!x?.[IsPreservesRecord];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isClassOf<LabelType extends Value<T>, FieldsType extends Tuple<Value<T>>, T extends object = DefaultPointer>(ci: RecordConstructorInfo<LabelType, T>, v: any): v is Record<LabelType, FieldsType, T> {
|
||||||
|
return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RecordImpl<T extends object = DefaultPointer> extends Array<Value<T>> {
|
||||||
readonly label: Value<T>;
|
readonly label: Value<T>;
|
||||||
|
|
||||||
constructor(label: Value<T>, fieldsJS: any[]) {
|
constructor(label: Value<T>, fields: Array<Value<T>>) {
|
||||||
if (arguments.length === 1) {
|
if (arguments.length === 1) {
|
||||||
// Using things like someRecord.map() involves the runtime
|
// Using things like someRecord.map() involves the runtime
|
||||||
// apparently instantiating instances of this.constructor
|
// apparently instantiating instances of this.constructor
|
||||||
|
@ -20,8 +84,8 @@ export class Record<T extends object = DefaultPointer> extends Array<Value<T>> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
super(fieldsJS.length);
|
super(fields.length);
|
||||||
fieldsJS.forEach((f, i) => this[i] = fromJS(f));
|
fields.forEach((f, i) => this[i] = f);
|
||||||
this.label = label;
|
this.label = label;
|
||||||
Object.freeze(this);
|
Object.freeze(this);
|
||||||
}
|
}
|
||||||
|
@ -30,18 +94,18 @@ export class Record<T extends object = DefaultPointer> extends Array<Value<T>> {
|
||||||
return (index < this.length) ? this[index] : defaultValue;
|
return (index < this.length) ? this[index] : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
set(index: number, newValue: Value<T>): Record<T> {
|
set(index: number, newValue: Value<T>): this {
|
||||||
return new Record(this.label, this.map((f, i) => (i === index) ? newValue : f));
|
return <this> new RecordImpl(this.label, this.map((f, i) => (i === index) ? newValue : f));
|
||||||
}
|
}
|
||||||
|
|
||||||
getConstructorInfo(): RecordConstructorInfo<T> {
|
getConstructorInfo(): RecordConstructorInfo<Value<T>, T> {
|
||||||
return { label: this.label, arity: this.length };
|
return { label: this.label, arity: this.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
equals(other: any): boolean {
|
equals(other: any): boolean {
|
||||||
return Record.isRecord(other) &&
|
return Record.isRecord(other) &&
|
||||||
is(this.label, other.label) &&
|
is(this.label, other.label) &&
|
||||||
this.every((f, i) => is(f, other.get(i)));
|
this.every((f, i) => is(f, other[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// hashCode(): number {
|
// hashCode(): number {
|
||||||
|
@ -50,8 +114,6 @@ export class Record<T extends object = DefaultPointer> extends Array<Value<T>> {
|
||||||
// return h;
|
// return h;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
static fallbackToString: (f: Value<any>) => string = (_f) => '<unprintable_preserves_field_value>';
|
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
return this.asPreservesText();
|
return this.asPreservesText();
|
||||||
}
|
}
|
||||||
|
@ -71,36 +133,6 @@ export class Record<T extends object = DefaultPointer> extends Array<Value<T>> {
|
||||||
}).join(', ') + ')';
|
}).join(', ') + ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
static makeConstructor<T extends object = DefaultPointer>(labelSymbolText: string, fieldNames: string[]): RecordConstructor<T> {
|
|
||||||
return Record.makeBasicConstructor(Symbol.for(labelSymbolText), fieldNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
static makeBasicConstructor<T extends object = DefaultPointer>(label0: any, fieldNames: string[]): RecordConstructor<T> {
|
|
||||||
const label = fromJS<T>(label0);
|
|
||||||
const arity = fieldNames.length;
|
|
||||||
const ctor: RecordConstructor<T> = (...fields: any[]): Record<T> => {
|
|
||||||
if (fields.length !== arity) {
|
|
||||||
throw new Error("Record: cannot instantiate " + (label && label.toString()) +
|
|
||||||
" expecting " + arity + " fields with " + fields.length + " fields");
|
|
||||||
}
|
|
||||||
return new Record<T>(label, fields);
|
|
||||||
};
|
|
||||||
const constructorInfo = { label, arity };
|
|
||||||
ctor.constructorInfo = constructorInfo;
|
|
||||||
ctor.isClassOf = (v: any): v is Record<T> => Record.isClassOf(constructorInfo, v);
|
|
||||||
ctor._ = {};
|
|
||||||
fieldNames.forEach((name, i) => {
|
|
||||||
ctor._[name] = function (r: any): Value<T> | undefined {
|
|
||||||
if (!ctor.isClassOf(r)) {
|
|
||||||
throw new Error("Record: attempt to retrieve field "+label.toString()+"."+name+
|
|
||||||
" from non-"+label.toString()+": "+(r && r.toString()));
|
|
||||||
}
|
|
||||||
return r.get(i);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return ctor;
|
|
||||||
}
|
|
||||||
|
|
||||||
[PreserveOn](encoder: Encoder<T>) {
|
[PreserveOn](encoder: Encoder<T>) {
|
||||||
encoder.emitbyte(Tag.Record);
|
encoder.emitbyte(Tag.Record);
|
||||||
encoder.push(this.label);
|
encoder.push(this.label);
|
||||||
|
@ -111,24 +143,4 @@ export class Record<T extends object = DefaultPointer> extends Array<Value<T>> {
|
||||||
get [IsPreservesRecord](): boolean {
|
get [IsPreservesRecord](): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isRecord<T extends object = DefaultPointer>(x: any): x is Record<T> {
|
|
||||||
return !!x?.[IsPreservesRecord];
|
|
||||||
}
|
|
||||||
|
|
||||||
static isClassOf<T extends object = DefaultPointer>(ci: RecordConstructorInfo<T>, v: any): v is Record<T> {
|
|
||||||
return (Record.isRecord(v)) && is(ci.label, v.label) && (ci.arity === v.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RecordConstructor<T extends object = DefaultPointer> {
|
|
||||||
(...fields: any[]): Record<T>;
|
|
||||||
constructorInfo: RecordConstructorInfo<T>;
|
|
||||||
isClassOf(v: any): v is Record<T>;
|
|
||||||
_: { [getter: string]: (r: any) => Value<T> | undefined };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RecordConstructorInfo<T extends object = DefaultPointer> {
|
|
||||||
label: Value<T>;
|
|
||||||
arity: number;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
// This Tuple type (and tuple() function) is a hack to induce
|
||||||
|
// TypeScript to infer tuple types rather than array types. (Source:
|
||||||
|
// https://github.com/microsoft/TypeScript/issues/27179#issuecomment-422606990)
|
||||||
|
//
|
||||||
|
// Without it, [123, 'hi', true] will often get the type (string |
|
||||||
|
// number | boolean)[] instead of [number, string, boolean].
|
||||||
|
|
||||||
|
export type Tuple<T> = T[] | [T];
|
||||||
|
export const tuple = <T, A extends Tuple<T>>(... args: A) => args;
|
||||||
|
|
||||||
|
export const Tuple = Array;
|
||||||
|
|
||||||
|
export type TupleMap<T extends Tuple<any>, V> = Tuple<V> & {
|
||||||
|
[K in keyof T]: V;
|
||||||
|
}
|
|
@ -6,18 +6,20 @@ import { DoubleFloat, SingleFloat } from './float';
|
||||||
import { Record } from './record';
|
import { Record } from './record';
|
||||||
import { Annotated } from './annotated';
|
import { Annotated } from './annotated';
|
||||||
import { Set, Dictionary } from './dictionary';
|
import { Set, Dictionary } from './dictionary';
|
||||||
|
import { Tuple } from './tuple';
|
||||||
|
|
||||||
export * from './bytes';
|
export * from './bytes';
|
||||||
export * from './float';
|
export * from './float';
|
||||||
export * from './record';
|
export * from './record';
|
||||||
export * from './annotated';
|
export * from './annotated';
|
||||||
export * from './dictionary';
|
export * from './dictionary';
|
||||||
|
export * from './tuple';
|
||||||
|
|
||||||
export type DefaultPointer = object
|
export type DefaultPointer = object
|
||||||
|
|
||||||
export type Value<T extends object = DefaultPointer> = Atom | Compound<T> | T | Annotated<T>;
|
export type Value<T extends object = DefaultPointer> = Atom | Compound<T> | T | Annotated<T>;
|
||||||
export type Atom = boolean | SingleFloat | DoubleFloat | number | string | Bytes | symbol;
|
export type Atom = boolean | SingleFloat | DoubleFloat | number | string | Bytes | symbol;
|
||||||
export type Compound<T extends object = DefaultPointer> = Record<T> | Array<Value<T>> | Set<T> | Dictionary<Value<T>, T>;
|
export type Compound<T extends object = DefaultPointer> = Record<any, Tuple<any>, T> | Array<Value<T>> | Set<T> | Dictionary<Value<T>, T>;
|
||||||
|
|
||||||
export function fromJS<T extends object = DefaultPointer>(x: any): Value<T> {
|
export function fromJS<T extends object = DefaultPointer>(x: any): Value<T> {
|
||||||
switch (typeof x) {
|
switch (typeof x) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
preserves,
|
preserves,
|
||||||
fromJS,
|
fromJS,
|
||||||
Constants,
|
Constants,
|
||||||
|
tuple,
|
||||||
} from '../src/index';
|
} from '../src/index';
|
||||||
const { Tag } = Constants;
|
const { Tag } = Constants;
|
||||||
import './test-utils';
|
import './test-utils';
|
||||||
|
@ -35,9 +36,9 @@ function encodePointer(w: Pointer): Value<Pointer> {
|
||||||
return w.v;
|
return w.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Discard = Record.makeConstructor<Pointer>('discard', []);
|
const Discard = Record.makeConstructor<Pointer>()(Symbol.for('discard'), []);
|
||||||
const Capture = Record.makeConstructor<Pointer>('capture', ['pattern']);
|
const Capture = Record.makeConstructor<Pointer>()(Symbol.for('capture'), ['pattern']);
|
||||||
const Observe = Record.makeConstructor<Pointer>('observe', ['pattern']);
|
const Observe = Record.makeConstructor<Pointer>()(Symbol.for('observe'), ['pattern']);
|
||||||
|
|
||||||
describe('record constructors', () => {
|
describe('record constructors', () => {
|
||||||
it('should have constructorInfo', () => {
|
it('should have constructorInfo', () => {
|
||||||
|
@ -51,8 +52,8 @@ describe('record constructors', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('RecordConstructorInfo', () => {
|
describe('RecordConstructorInfo', () => {
|
||||||
const C1 = Record.makeBasicConstructor([1], ['x', 'y']);
|
const C1 = Record.makeConstructor()(tuple(1), ['x', 'y']);
|
||||||
const C2 = Record.makeBasicConstructor([1], ['z', 'w']);
|
const C2 = Record.makeConstructor()(tuple(1), ['z', 'w']);
|
||||||
it('instance comparison should ignore pointer and fieldname differences', () => {
|
it('instance comparison should ignore pointer and fieldname differences', () => {
|
||||||
expect(C1(9,9)).is(C2(9,9));
|
expect(C1(9,9)).is(C2(9,9));
|
||||||
expect(C1(9,9)).not.is(C2(9,8));
|
expect(C1(9,9)).not.is(C2(9,8));
|
||||||
|
@ -167,7 +168,7 @@ describe('common test suite', () => {
|
||||||
const samples_bin = fs.readFileSync(__dirname + '/../../../tests/samples.bin');
|
const samples_bin = fs.readFileSync(__dirname + '/../../../tests/samples.bin');
|
||||||
const samples = decodeWithAnnotations(samples_bin, { decodePointer });
|
const samples = decodeWithAnnotations(samples_bin, { decodePointer });
|
||||||
|
|
||||||
const TestCases = Record.makeConstructor('TestCases', ['cases']);
|
const TestCases = Record.makeConstructor()(Symbol.for('TestCases'), ['cases']);
|
||||||
|
|
||||||
function DS(bs: Bytes) {
|
function DS(bs: Bytes) {
|
||||||
return decode(bs, { decodePointer });
|
return decode(bs, { decodePointer });
|
||||||
|
@ -192,21 +193,21 @@ describe('common test suite', () => {
|
||||||
annotate<Pointer>(2, 1),
|
annotate<Pointer>(2, 1),
|
||||||
annotate<Pointer>(4, 3)),
|
annotate<Pointer>(4, 3)),
|
||||||
back: 5 },
|
back: 5 },
|
||||||
annotation5: { forward: annotate(new Record<Pointer>(Symbol.for('R'),
|
annotation5: { forward: annotate(Record(Symbol.for('R'),
|
||||||
[annotate(Symbol.for('f'),
|
[annotate(Symbol.for('f'),
|
||||||
Symbol.for('af'))]),
|
Symbol.for('af'))]),
|
||||||
Symbol.for('ar')),
|
Symbol.for('ar')),
|
||||||
back: new Record<Pointer>(Symbol.for('R'), [Symbol.for('f')]) },
|
back: Record(Symbol.for('R'), [Symbol.for('f')]) },
|
||||||
annotation6: { forward: new Record<Pointer>(annotate<Pointer>(Symbol.for('R'),
|
annotation6: { forward: Record(annotate<Pointer>(Symbol.for('R'),
|
||||||
Symbol.for('ar')),
|
Symbol.for('ar')),
|
||||||
[annotate(Symbol.for('f'),
|
[annotate(Symbol.for('f'),
|
||||||
Symbol.for('af'))]),
|
Symbol.for('af'))]),
|
||||||
back: new Record<Pointer>(Symbol.for('R'), [Symbol.for('f')]) },
|
back: Record(Symbol.for('R'), [Symbol.for('f')]) },
|
||||||
annotation7: { forward: annotate<Pointer>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
|
annotation7: { forward: annotate<Pointer>([], Symbol.for('a'), Symbol.for('b'), Symbol.for('c')),
|
||||||
back: [] },
|
back: [] },
|
||||||
list1: { forward: [1, 2, 3, 4],
|
list1: { forward: [1, 2, 3, 4],
|
||||||
back: [1, 2, 3, 4] },
|
back: [1, 2, 3, 4] },
|
||||||
record2: { value: Observe(new Record(Symbol.for("speak"), [
|
record2: { value: Observe(Record(Symbol.for("speak"), [
|
||||||
Discard(),
|
Discard(),
|
||||||
Capture(Discard())
|
Capture(Discard())
|
||||||
])) },
|
])) },
|
||||||
|
@ -244,7 +245,7 @@ describe('common test suite', () => {
|
||||||
const tests = peel(TestCases._.cases(peel(samples))!) as Dictionary<Value<Pointer>, Pointer>;
|
const tests = peel(TestCases._.cases(peel(samples))!) as Dictionary<Value<Pointer>, Pointer>;
|
||||||
tests.forEach((t0: Value<Pointer>, tName0: Value<Pointer>) => {
|
tests.forEach((t0: Value<Pointer>, tName0: Value<Pointer>) => {
|
||||||
const tName = Symbol.keyFor(strip(tName0) as symbol)!;
|
const tName = Symbol.keyFor(strip(tName0) as symbol)!;
|
||||||
const t = peel(t0) as Record<Pointer>;
|
const t = peel(t0) as Record<any, any>;
|
||||||
switch (t.label) {
|
switch (t.label) {
|
||||||
case Symbol.for('Test'):
|
case Symbol.for('Test'):
|
||||||
runTestCase('normal', tName, strip(t[0]) as Bytes, t[1]);
|
runTestCase('normal', tName, strip(t[0]) as Bytes, t[1]);
|
||||||
|
|
Loading…
Reference in New Issue