diff --git a/implementations/javascript/packages/core/src/fold.ts b/implementations/javascript/packages/core/src/fold.ts index 87b002c..7c418fc 100644 --- a/implementations/javascript/packages/core/src/fold.ts +++ b/implementations/javascript/packages/core/src/fold.ts @@ -6,6 +6,22 @@ import { annotate, Annotated } from "./annotated"; import { Double, Float, Single } from "./float"; import { Embedded } from "./embedded"; +export enum ValueClass { + Boolean, + Float, + Double, + SignedInteger, + String, + ByteString, + Symbol, + Record, + Sequence, + Set, + Dictionary, + Embedded, + Annotated, // quasi-class +} + export type Fold> = (v: Value) => R; export interface FoldMethods { @@ -86,6 +102,45 @@ export class MapFold extends ValueFold { } } +export function valueClass(v: Value): ValueClass { + switch (typeof v) { + case 'boolean': + return ValueClass.Boolean; + case 'number': + if (!Number.isInteger(v)) { + throw new Error("Non-integer number in Preserves valueClass; missing SingleFloat/DoubleFloat wrapper?"); + } else { + return ValueClass.SignedInteger; + } + case 'string': + return ValueClass.String; + case 'symbol': + return ValueClass.Symbol; + case 'object': + if (Record.isRecord, Tuple>, T>(v)) { + return ValueClass.Record; + } else if (Array.isArray(v)) { + return ValueClass.Sequence; + } else if (Set.isSet(v)) { + return ValueClass.Set; + } else if (Dictionary.isDictionary(v)) { + return ValueClass.Dictionary; + } else if (Annotated.isAnnotated(v)) { + return ValueClass.Annotated; + } else if (Bytes.isBytes(v)) { + return ValueClass.ByteString; + } else if (Float.isSingle(v)) { + return ValueClass.Float; + } else if (Float.isDouble(v)) { + return ValueClass.Double; + } else { + return ValueClass.Embedded; + } + default: + ((_v: never): never => { throw new Error("Internal error"); })(v); + } +} + export const IDENTITY_FOLD = new IdentityFold(); export function fold(v: Value, o: FoldMethods): R {