import { GenericEmbedded, is, Value } from '@preserves/core'; import * as M from './gen/schema'; import { isJsKeyword } from './compiler/jskw'; export * from './gen/schema'; export type Input = Value; export type InputEmbedded = GenericEmbedded; export function qidLast(s: string): string { const m = s.match(/^(.*\.)?([^.]+)$/); return m![2]; } export function isValidToken(s: string): boolean { return /^[a-zA-Z][a-zA-Z_0-9]*$/.test(s); } export function isValidQid(s: string): boolean { return s.split('.').every(isValidToken); } export function isValidJsId(s: string): boolean { return /^[$_a-zA-Z][$_a-zA-Z0-9]*$/.test(s) && !isJsKeyword(s); } export function jsId(v: string, kf?: () => string): string { return jsToken(v.replace('$', '$$'), kf); } export function jsToken(s: string, kf?: () => string): string { if (isValidJsId(s)) return s; if (isValidJsId('$' + s)) return '$' + s; if (kf !== void 0) return kf(); throw new Error(`Internal error: jsToken needs to be completed (${s})`); } export const ANDSYM = Symbol.for('&'); export const DOT = Symbol.for('.'); export const DOTDOTDOT = Symbol.for('...'); export const EQUALS = Symbol.for('='); export const INCLUDE = Symbol.for('include'); export const ORSYM = Symbol.for('/'); export type SchemaEnvEntry = { schemaModulePath: M.ModulePath, typescriptModulePath: string, typescriptModuleExpr: string | null, schema: M.Schema | null, // null means it's an artificial one, not corresponding to an input }; export type Environment = Array; export function envLookup(env: Environment, soughtModule: M.ModulePath): SchemaEnvEntry | null { for (const e of env) { if (is(e.schemaModulePath, soughtModule)) { return e; } } return null; } export function modsymFor(e: SchemaEnvEntry): string { return '_i_' + e.schemaModulePath.map(s => s.description!).join('$'); } export function formatModulePath(p: M.ModulePath): string { return p.map(s => s.description!).join('.'); } export function formatRef(r: M.Ref): string { return [... r.module, r.name].map(s => s.description!).join('.'); } export function unnamePattern(p: M.NamedPattern): M.Pattern { return (p._variant === 'named') ? M.Pattern.SimplePattern(p.value.pattern) : p.value; } export function unnameSimplePattern(p: M.NamedSimplePattern): M.SimplePattern { return (p._variant === 'named') ? p.value.pattern : p.value; } export function promoteNamedSimplePattern(p: M.NamedSimplePattern): M.NamedPattern { return (p._variant === 'named') ? p : M.NamedPattern.anonymous(M.Pattern.SimplePattern(p.value)); } export function nameFor(p: M.NamedSimplePattern | M.NamedPattern) : string | undefined { return (p._variant === 'named') ? p.value.name.description! : void 0; } export function anonymousSimplePattern(p: M.SimplePattern): M.NamedPattern { return M.NamedPattern.anonymous(M.Pattern.SimplePattern(p)); } export function namelike(x: Input): string | undefined { if (typeof x === 'string') return x; if (typeof x === 'symbol') return x.description!; if (typeof x === 'boolean') return x ? 'true' : 'false'; return void 0; }