import { SimpleType, Type } from "./type"; import { anglebrackets, braces, Item, keyvalue, opseq, seq } from "./block"; import { ModuleContext } from "./context"; export function variantInitFor(variantName: string | undefined) : Item[] { return variantName === void 0 ? [] : [variantFor(variantName)]; } export function variantFor(variantName: string): Item { return keyvalue('_variant', JSON.stringify(variantName)); } function simpleTypeFields(ctxt: ModuleContext, t: SimpleType): Item[] { switch (t.kind) { case 'unit': return []; case 'ref': case 'set': case 'dictionary': case 'array': return [keyvalue('value', renderType(ctxt, t))]; case 'record': return Array.from(t.fields).map(([nn, tt]) => keyvalue(nn, renderType(ctxt, tt))); default: ((_: never) => {})(t); throw new Error("Unreachable"); } } export function renderVariant( ctxt: ModuleContext, [variantName, t]: [string, SimpleType], ): Item { let fields = simpleTypeFields(ctxt, t); return braces(variantFor(variantName), ... fields); } export function renderType(ctxt: ModuleContext, t: Type): Item { switch (t.kind) { case 'union': return opseq('never', ' | ', ... Array.from(t.variants).flatMap(entry => renderVariant(ctxt, entry))); case 'unit': return braces(... simpleTypeFields(ctxt, t)); case 'ref': if (t.ref === null && t.typeName === '_embedded') { return t.typeName; } else { return seq(t.typeName, ctxt.genericArgsFor(t)); } case 'set': return seq('_.EncodableSet', anglebrackets( renderType(ctxt, t.type), '_embedded')); case 'dictionary': return seq('_.EncodableDictionary', anglebrackets( renderType(ctxt, t.key), renderType(ctxt, t.value), '_embedded')); case 'array': return seq('Array', anglebrackets(renderType(ctxt, t.type))); case 'record': return braces(... simpleTypeFields(ctxt, t)); default: ((_: never) => {})(t); throw new Error("Unreachable"); } } export function renderTypeWithConversionMixins(ctxt: ModuleContext, t: Type): Item { if (t.kind === 'unit' || t.kind === 'record' || t.kind === 'union') { return opseq('any', ' & ', renderType(ctxt, t), seq('_.Preservable', ctxt.hasEmbedded(t) ? ctxt.genericArgs() : ''), seq('_.PreserveWritable', ctxt.hasEmbedded(t) ? ctxt.genericArgs() : ''), braces(seq('__as_preserve__', ctxt.hasEmbedded(t) ? '' : ctxt.genericParameters(), '()', ': _.Value', ctxt.genericArgs()))); } else { return renderType(ctxt, t); } }