UI and a Lisp experiment

This commit is contained in:
Yura Dupyn 2026-04-25 01:10:49 +02:00
parent 38ff06ea45
commit f55b437037
24 changed files with 2746 additions and 89 deletions

59
src/syntax.ts Normal file
View file

@ -0,0 +1,59 @@
import type { CodePointSpan } from 'source-region';
export type ConcreteSyntax = Expr<{ span: CodePointSpan }>
export type Expr<A> =
| { tag: "literal", value: Literal } & A
| { tag: "list", values: Expr<A>[] } & 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<void> {
return { tag: "literal", value: { tag: "number", value } };
}
export function identifier(value: Identifier): Expr<void> {
return { tag: "literal", value: { tag: "identifier", value } };
}
export function list(values: Expr<void>[]): Expr<void> {
return { tag: "list", values };
}
export function show<A>(e: Expr<A>): 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