Switching to ML style type annotations. not separate statement from the expression
This commit is contained in:
parent
6acec5641c
commit
f3c3a76671
6 changed files with 35 additions and 36 deletions
|
|
@ -325,9 +325,9 @@ export function prettyPrint(ast: AST, indent = 0): string {
|
|||
|
||||
case 'definition':
|
||||
const ann = ast.annotation
|
||||
? `${ast.name} : ${prettyPrintType(ast.annotation.type)};\n`
|
||||
? ` : ${prettyPrintType(ast.annotation.type)}`
|
||||
: '';
|
||||
return `${ann}${ast.name} = ${prettyPrint(ast.body, indent)};`;
|
||||
return `${ast.name}${ann} = ${prettyPrint(ast.body, indent)};`;
|
||||
|
||||
default:
|
||||
return `Unknown AST kind: ${i}${(ast as any).kind}`
|
||||
|
|
@ -373,7 +373,7 @@ function prettyPrintPattern(pattern: Pattern): string {
|
|||
}
|
||||
}
|
||||
|
||||
function prettyPrintType(type: TypeAST): string {
|
||||
export function prettyPrintType(type: TypeAST): string {
|
||||
switch (type.kind) {
|
||||
case 'type-name':
|
||||
case 'type-var':
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ Maybe a = None | Some a;
|
|||
# | [0, [x, ...xs]] \ (Some x)
|
||||
# | [n, [x, ...xs]] \ nth (n - 1) xs;
|
||||
|
||||
map : (a \ b) \ List a \ List b;
|
||||
map = f list \ list
|
||||
map : (a \ b) \ List a \ List b = f list \ list
|
||||
| [] \ []
|
||||
| [x, ...xs] \ [f x, ...map f xs];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
myFontBackup = { glyphs = {
|
||||
myFont = { glyphs = {
|
||||
"0" = {
|
||||
w = 7,
|
||||
h = 12,
|
||||
|
|
@ -5836,7 +5836,7 @@ myFontBackup = { glyphs = {
|
|||
}
|
||||
} };
|
||||
|
||||
myFont2Backup = { glyphs = {
|
||||
myFont2 = { glyphs = {
|
||||
"0" = {
|
||||
w = 5,
|
||||
h = 12,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ type CompileCtx = {
|
|||
};
|
||||
const defaultCtx: CompileCtx = { useStore: true, bound: new Set(), topLevel: new Set() };
|
||||
|
||||
export const definitions: Map<string, AST> = new Map();
|
||||
export const definitions: Map<string, Definition> = new Map();
|
||||
export const dependencies: Map<string, Set<string>> = new Map();
|
||||
export const dependents: Map<string, Set<string>> = new Map();
|
||||
export const astRegistry = new Map<number, AST>();
|
||||
|
|
@ -226,7 +226,7 @@ export function compileAndRun(defs: Definition[]) {
|
|||
const topLevel = new Set(defs.map(d => d.name));
|
||||
|
||||
for (const def of defs) {
|
||||
definitions.set(def.name, def.body);
|
||||
definitions.set(def.name, def);
|
||||
const free = freeVars(def.body);
|
||||
const deps = new Set([...free].filter(v => topLevel.has(v)));
|
||||
dependencies.set(def.name, deps);
|
||||
|
|
@ -364,7 +364,9 @@ function patternVars(pattern: Pattern): string[] {
|
|||
}
|
||||
|
||||
export function recompile(name: string, newAst: AST) {
|
||||
definitions.set(name, newAst);
|
||||
const existing = definitions.get(name);
|
||||
definitions.set(name, { kind: 'definition', name, body: newAst, annotation: existing?.annotation });;
|
||||
// definitions.set(name, newAst);
|
||||
|
||||
const topLevel = new Set(definitions.keys());
|
||||
const free = freeVars(newAst);
|
||||
|
|
@ -394,7 +396,7 @@ export function recompile(name: string, newAst: AST) {
|
|||
collectDependents(name);
|
||||
|
||||
for (const defName of toRecompile) {
|
||||
const ast = definitions.get(defName)!;
|
||||
const ast = definitions.get(defName)!.body;
|
||||
const compiled = compile(ast);
|
||||
|
||||
const fn = new Function('store', `return ${compiled}`);
|
||||
|
|
|
|||
|
|
@ -160,21 +160,6 @@ export class Parser {
|
|||
continue;
|
||||
}
|
||||
|
||||
// type annotation
|
||||
if (this.current().kind === 'ident' && this.peek().kind === 'colon') {
|
||||
this.advance(); // eat ident
|
||||
|
||||
this.advance();
|
||||
const type = this.parseType();
|
||||
this.expect('semicolon');
|
||||
|
||||
// parse definition
|
||||
const def = this.parseDefinition();
|
||||
def.annotation = { constraints: [], type };
|
||||
|
||||
definitions.push(def);
|
||||
continue;
|
||||
}
|
||||
definitions.push(this.parseDefinition());
|
||||
}
|
||||
|
||||
|
|
@ -185,6 +170,12 @@ export class Parser {
|
|||
const nameToken = this.expect('ident');
|
||||
const name = (nameToken as { value: string }).value;
|
||||
|
||||
let annotation: Annotation | undefined;
|
||||
if (this.current().kind === 'colon') {
|
||||
this.advance();
|
||||
annotation = { constraints: [], type: this.parseType() };
|
||||
}
|
||||
|
||||
this.expect('equals');
|
||||
|
||||
const body = this.parseExpression();
|
||||
|
|
@ -193,7 +184,7 @@ export class Parser {
|
|||
this.expect('semicolon');
|
||||
}
|
||||
|
||||
return { kind: 'definition', name, body, ...this.getPos(nameToken) };
|
||||
return { kind: 'definition', name, body, annotation, ...this.getPos(nameToken) };
|
||||
}
|
||||
|
||||
private parseExpression(): AST {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { tokenize } from './lexer'
|
||||
import { Parser } from './parser'
|
||||
import { compile, recompile, definitions, freeVars, dependencies, dependents, astRegistry } from './compiler'
|
||||
import { prettyPrint } from './ast'
|
||||
import { prettyPrint, prettyPrintType } from './ast'
|
||||
import type { AST } from './ast'
|
||||
import { measure } from './ui';
|
||||
|
||||
|
|
@ -118,10 +118,9 @@ export const _rt = {
|
|||
return obj === undefined ? { _tag: 'None' } : { _tag: 'Some', _0: obj };
|
||||
},
|
||||
getSource: (name: string) => {
|
||||
const ast = definitions.get(name);
|
||||
if (!ast) return "";
|
||||
const printed = prettyPrint(ast);
|
||||
return printed;
|
||||
const def = definitions.get(name);
|
||||
if (!def) return "";
|
||||
return prettyPrint(def);
|
||||
},
|
||||
"saveImage!": () => {
|
||||
const saved: Record<string, string> = {};
|
||||
|
|
@ -259,8 +258,8 @@ export const _rt = {
|
|||
|
||||
export function saveDefinitions() {
|
||||
const saved: Record<string, string> = {};
|
||||
for (const [name, ast] of definitions) {
|
||||
const source = prettyPrint({ kind: 'definition', name, body: ast });
|
||||
for (const [name, def] of definitions) {
|
||||
const source = prettyPrint(def);
|
||||
saved[name] = source;
|
||||
}
|
||||
localStorage.setItem(STORAGE_KEY, JSON.stringify(saved));
|
||||
|
|
@ -356,8 +355,16 @@ function valueToAst(value: any): AST {
|
|||
export function syncToAst(name: string) {
|
||||
// if (definitions.has(name)) {
|
||||
if (name in store) {
|
||||
definitions.set(name, valueToAst(store[name]));
|
||||
const source = prettyPrint({ kind: 'definition', name, body: definitions.get(name)! });
|
||||
const existing = definitions.get(name);
|
||||
const newDef: Definition = {
|
||||
kind: 'definition',
|
||||
name,
|
||||
body: valueToAst(store[name]),
|
||||
annotation: existing?.annotation,
|
||||
};
|
||||
definitions.set(name, newDef); // valueToAst(store[name]));
|
||||
// const source = prettyPrint({ kind: 'definition', name, body: definitions.get(name)! });
|
||||
const source = prettyPrint(definitions.get(name)!);
|
||||
appendChangeLog(name, source);
|
||||
saveDefinitions();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue