import type { CodePointSpan } from 'source-region'; export type ConcreteSyntax = Expr<{ span: CodePointSpan }> export type Expr = | { tag: "literal", value: Literal } & A | { tag: "list", values: Expr[] } & A export namespace ConcreteSyntax { export function number(value: number, span: CodePointSpan): ConcreteSyntax { return { tag: "literal", value: { tag: "number", value }, span }; } export function identifier(value: Identifier, span: CodePointSpan): ConcreteSyntax { return { tag: "literal", value: { tag: "identifier", value }, span }; } export function list(values: ConcreteSyntax[], span: CodePointSpan): ConcreteSyntax { return { tag: "list", values, span }; } } export namespace Expr { export function number(value: number): Expr { return { tag: "literal", value: { tag: "number", value } }; } export function identifier(value: Identifier): Expr { return { tag: "literal", value: { tag: "identifier", value } }; } export function list(values: Expr[]): Expr { return { tag: "list", values }; } export function show(e: Expr): string { switch (e.tag) { case "literal": return showLiteral(e.value); case "list": return `(${e.values.map(show).join(" ")})`; } } function showLiteral(e: Literal): string { switch (e.tag) { case "number": return `${e.value}`; case "identifier": return `${e.value}`; } } } type Literal = | { tag: "number", value: number } | { tag: "identifier", value: Identifier } type Identifier = string