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