mirror of
https://github.com/Noratrieb/riverdelta.git
synced 2026-01-16 09:25:03 +01:00
Start lowering
This commit is contained in:
parent
8b424c0add
commit
87f081a4fe
5 changed files with 33 additions and 25 deletions
18
src/ast.ts
18
src/ast.ts
|
|
@ -20,9 +20,10 @@ export type Item = ItemKind & {
|
||||||
|
|
||||||
export type FunctionDef = {
|
export type FunctionDef = {
|
||||||
name: string;
|
name: string;
|
||||||
args: FunctionArg[];
|
params: FunctionArg[];
|
||||||
body: Expr;
|
body: Expr;
|
||||||
returnType?: Type;
|
returnType?: Type;
|
||||||
|
ty?: TyFn;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FunctionArg = {
|
export type FunctionArg = {
|
||||||
|
|
@ -253,6 +254,11 @@ export function tyIsUnit(ty: Ty): ty is TyUnit {
|
||||||
return ty.kind === "tuple" && ty.elems.length === 0;
|
return ty.kind === "tuple" && ty.elems.length === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const TY_UNIT: Ty = { kind: "tuple", elems: [] };
|
||||||
|
export const TY_STRING: Ty = { kind: "string" };
|
||||||
|
export const TY_BOOL: Ty = { kind: "bool" };
|
||||||
|
export const TY_INT: Ty = { kind: "int" };
|
||||||
|
|
||||||
// folders
|
// folders
|
||||||
|
|
||||||
export type FoldFn<T> = (value: T) => T;
|
export type FoldFn<T> = (value: T) => T;
|
||||||
|
|
@ -279,14 +285,14 @@ export const DEFAULT_FOLDER: Folder = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function fold_ast(ast: Ast, folder: Folder): Ast {
|
export function foldAst(ast: Ast, folder: Folder): Ast {
|
||||||
return ast.map((item) => folder.item(item));
|
return ast.map((item) => folder.item(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function superFoldItem(item: Item, folder: Folder): Item {
|
export function superFoldItem(item: Item, folder: Folder): Item {
|
||||||
switch (item.kind) {
|
switch (item.kind) {
|
||||||
case "function": {
|
case "function": {
|
||||||
const args = item.node.args.map(({ name, type, span }) => ({
|
const args = item.node.params.map(({ name, type, span }) => ({
|
||||||
name,
|
name,
|
||||||
type: folder.type(type),
|
type: folder.type(type),
|
||||||
span,
|
span,
|
||||||
|
|
@ -297,7 +303,7 @@ export function superFoldItem(item: Item, folder: Folder): Item {
|
||||||
span: item.span,
|
span: item.span,
|
||||||
node: {
|
node: {
|
||||||
name: item.node.name,
|
name: item.node.name,
|
||||||
args,
|
params: args,
|
||||||
body: folder.expr(item.node.body),
|
body: folder.expr(item.node.body),
|
||||||
returnType: item.node.returnType && folder.type(item.node.returnType),
|
returnType: item.node.returnType && folder.type(item.node.returnType),
|
||||||
},
|
},
|
||||||
|
|
@ -399,3 +405,7 @@ export function superFoldType(type: Type, folder: Folder): Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function varUnreachable(): never {
|
||||||
|
throw new Error("Type variables must not occur after type checking");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ function parseItem(t: Token[]): [Token[], Item] {
|
||||||
|
|
||||||
const def: FunctionDef = {
|
const def: FunctionDef = {
|
||||||
name: name.ident,
|
name: name.ident,
|
||||||
args,
|
params: args,
|
||||||
returnType,
|
returnType,
|
||||||
body,
|
body,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ function printItem(item: Item): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
function printFunction(func: FunctionDef): string {
|
function printFunction(func: FunctionDef): string {
|
||||||
const args = func.args
|
const args = func.params
|
||||||
.map(({ name, type }) => `${name}: ${printType(type)}`)
|
.map(({ name, type }) => `${name}: ${printType(type)}`)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
const ret = func.returnType ? `: ${printType(func.returnType)}` : "";
|
const ret = func.returnType ? `: ${printType(func.returnType)}` : "";
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import {
|
||||||
Folder,
|
Folder,
|
||||||
Identifier,
|
Identifier,
|
||||||
Resolution,
|
Resolution,
|
||||||
fold_ast,
|
foldAst,
|
||||||
superFoldExpr,
|
superFoldExpr,
|
||||||
superFoldItem,
|
superFoldItem,
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
@ -78,7 +78,7 @@ export function resolve(ast: Ast): Ast {
|
||||||
item(item) {
|
item(item) {
|
||||||
switch (item.kind) {
|
switch (item.kind) {
|
||||||
case "function": {
|
case "function": {
|
||||||
const args = item.node.args.map(({ name, span, type }) => ({
|
const params = item.node.params.map(({ name, span, type }) => ({
|
||||||
name,
|
name,
|
||||||
span,
|
span,
|
||||||
type: this.type(type),
|
type: this.type(type),
|
||||||
|
|
@ -86,16 +86,16 @@ export function resolve(ast: Ast): Ast {
|
||||||
const returnType =
|
const returnType =
|
||||||
item.node.returnType && this.type(item.node.returnType);
|
item.node.returnType && this.type(item.node.returnType);
|
||||||
|
|
||||||
item.node.args.forEach(({ name }) => scopes.push(name));
|
item.node.params.forEach(({ name }) => scopes.push(name));
|
||||||
const body = superFoldExpr(item.node.body, this);
|
const body = superFoldExpr(item.node.body, this);
|
||||||
item.node.args.forEach(({ name }) => popScope(name));
|
item.node.params.forEach(({ name }) => popScope(name));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
kind: "function",
|
kind: "function",
|
||||||
span: item.span,
|
span: item.span,
|
||||||
node: {
|
node: {
|
||||||
name: item.node.name,
|
name: item.node.name,
|
||||||
args,
|
params,
|
||||||
returnType,
|
returnType,
|
||||||
body,
|
body,
|
||||||
},
|
},
|
||||||
|
|
@ -132,7 +132,7 @@ export function resolve(ast: Ast): Ast {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolved = fold_ast(ast, resolver);
|
const resolved = foldAst(ast, resolver);
|
||||||
|
|
||||||
return resolved;
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,35 @@
|
||||||
import {
|
import {
|
||||||
Ast,
|
Ast,
|
||||||
|
binaryExprPrecedenceClass,
|
||||||
COMPARISON_KINDS,
|
COMPARISON_KINDS,
|
||||||
DEFAULT_FOLDER,
|
DEFAULT_FOLDER,
|
||||||
EQUALITY_KINDS,
|
EQUALITY_KINDS,
|
||||||
Expr,
|
Expr,
|
||||||
ExprBinary,
|
ExprBinary,
|
||||||
ExprUnary,
|
ExprUnary,
|
||||||
|
foldAst,
|
||||||
Folder,
|
Folder,
|
||||||
Identifier,
|
Identifier,
|
||||||
LOGICAL_KINDS,
|
LOGICAL_KINDS,
|
||||||
Resolution,
|
Resolution,
|
||||||
Ty,
|
Ty,
|
||||||
|
TY_BOOL,
|
||||||
|
TY_INT,
|
||||||
|
TY_STRING,
|
||||||
|
TY_UNIT,
|
||||||
TyFn,
|
TyFn,
|
||||||
Type,
|
Type,
|
||||||
binaryExprPrecedenceClass,
|
|
||||||
fold_ast,
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
import { CompilerError, Span } from "./error";
|
import { CompilerError, Span } from "./error";
|
||||||
import { printTy } from "./printer";
|
import { printTy } from "./printer";
|
||||||
|
|
||||||
const TY_UNIT: Ty = { kind: "tuple", elems: [] };
|
|
||||||
const TY_STRING: Ty = { kind: "string" };
|
|
||||||
const TY_BOOL: Ty = { kind: "bool" };
|
|
||||||
const TY_INT: Ty = { kind: "int" };
|
|
||||||
|
|
||||||
function builtinAsTy(name: string, span: Span): Ty {
|
function builtinAsTy(name: string, span: Span): Ty {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "String": {
|
case "String": {
|
||||||
return TY_STRING;
|
return TY_STRING;
|
||||||
}
|
}
|
||||||
case "Int": {
|
case "Int": {
|
||||||
return TY_INT;
|
return TY_BOOL;
|
||||||
}
|
}
|
||||||
case "Bool": {
|
case "Bool": {
|
||||||
return TY_BOOL;
|
return TY_BOOL;
|
||||||
|
|
@ -105,7 +104,7 @@ export function typeck(ast: Ast): Ast {
|
||||||
const item = ast[index];
|
const item = ast[index];
|
||||||
switch (item.kind) {
|
switch (item.kind) {
|
||||||
case "function": {
|
case "function": {
|
||||||
const args = item.node.args.map((arg) => lowerAstTy(arg.type));
|
const args = item.node.params.map((arg) => lowerAstTy(arg.type));
|
||||||
const returnTy: Ty = item.node.returnType
|
const returnTy: Ty = item.node.returnType
|
||||||
? lowerAstTy(item.node.returnType)
|
? lowerAstTy(item.node.returnType)
|
||||||
: TY_UNIT;
|
: TY_UNIT;
|
||||||
|
|
@ -153,7 +152,7 @@ export function typeck(ast: Ast): Ast {
|
||||||
kind: "function",
|
kind: "function",
|
||||||
node: {
|
node: {
|
||||||
name: item.node.name,
|
name: item.node.name,
|
||||||
args: item.node.args.map((arg, i) => ({
|
params: item.node.params.map((arg, i) => ({
|
||||||
...arg,
|
...arg,
|
||||||
type: { ...arg.type, ty: fnTy.params[i] },
|
type: { ...arg.type, ty: fnTy.params[i] },
|
||||||
})),
|
})),
|
||||||
|
|
@ -162,15 +161,14 @@ export function typeck(ast: Ast): Ast {
|
||||||
},
|
},
|
||||||
span: item.span,
|
span: item.span,
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
ty: fnTy,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const withTypes = fold_ast(ast, checker);
|
return foldAst(ast, checker);
|
||||||
|
|
||||||
return withTypes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TyVarRes =
|
type TyVarRes =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue