Fix some compilation errors

This commit is contained in:
Sam Vervaeck 2020-05-23 15:04:32 +02:00
parent 98ddad8562
commit 831ae626c3
4 changed files with 115 additions and 74 deletions

View file

@ -84,10 +84,6 @@ node BoltQualName {
name: BoltSymbol,
}
node BoltSentence > BoltSourceElement {
tokens: Vec<BoltToken>,
}
node BoltTypeExpression;
node BoltReferenceTypeExpression > BoltTypeExpression {
@ -177,7 +173,7 @@ node BoltConstantExpression > BoltExpression {
value: BoltValue,
}
node BoltStatement > BoltSourceElement;
node BoltStatement > BoltFunctionBodyElement, BoltSourceElement;
node BoltReturnStatement > BoltStatement {
value: Option<BoltExpression>,
@ -213,16 +209,18 @@ node BoltModule > BoltDeclaration {
elements: Vec<BoltSourceElement>,
}
node BoltFunctionDeclaration > BoltDeclaration {
node BoltFunctionBodyElement;
node BoltFunctionDeclaration > BoltFunctionBodyElement, BoltDeclaration {
modifiers: BoltDeclarationModifiers,
target: String,
name: BoltSymbol,
params: Vec<BoltParameter>,
returnType: Option<BoltTypeExpression>,
body: Vec<BoltStatement>,
body: Vec<BoltFunctionBodyElement>,
}
node BoltVariableDeclaration > BoltDeclaration {
node BoltVariableDeclaration > BoltFunctionBodyElement, BoltDeclaration {
modifiers: BoltDeclarationModifiers,
bindings: BoltPattern,
type: Option<BoltTypeExpression>,
@ -262,7 +260,9 @@ node BoltTypeAliasDeclaration > BoltDeclaration {
typeExpr: BoltTypeExpression,
}
node BoltRecordDeclarationField {
node BoltRecordMember;
node BoltRecordField > BoltRecordMember {
name: BoltIdentifier,
type: BoltTypeExpression,
}
@ -271,11 +271,16 @@ node BoltRecordDeclaration > BoltDeclaration {
modifiers: BoltDeclarationModifiers,
name: BoltQualName,
typeParms: Option<Vec<BoltTypeParameter>>,
fields: Vec<BoltRecordDeclarationField>,
members: Option<Vec<BoltRecordMember>>,
}
node BoltSourceElement;
node BoltMacroCall > BoltRecordMember, BoltStatement, BoltDeclaration, BoltExpression {
name: BoltIdentifier,
text: String,
}
// JavaScript AST definitions
type JSValue = Int | String | Bool | Void;

4
src/ast.d.ts vendored
View file

@ -583,7 +583,7 @@ export interface BoltFunctionDeclaration extends SyntaxBase<SyntaxKind.BoltFunct
name: BoltSymbol;
params: BoltParameter[];
returnType: BoltTypeExpression | null;
body: BoltStatement[];
body: BoltFunctionBodyElement[];
}
export interface BoltVariableDeclaration extends SyntaxBase<SyntaxKind.BoltVariableDeclaration> {
@ -1403,7 +1403,7 @@ export function createBoltResumeStatement(value: BoltExpression, span?: TextSpan
export function createBoltExpressionStatement(expression: BoltExpression, span?: TextSpan | null): BoltExpressionStatement;
export function createBoltParameter(index: number, bindings: BoltPattern, type: BoltTypeExpression | null, defaultValue: BoltExpression | null, span?: TextSpan | null): BoltParameter;
export function createBoltModule(modifiers: BoltDeclarationModifiers, name: BoltQualName, elements: BoltSourceElement[], span?: TextSpan | null): BoltModule;
export function createBoltFunctionDeclaration(modifiers: BoltDeclarationModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeExpression | null, body: BoltStatement[], span?: TextSpan | null): BoltFunctionDeclaration;
export function createBoltFunctionDeclaration(modifiers: BoltDeclarationModifiers, target: string, name: BoltSymbol, params: BoltParameter[], returnType: BoltTypeExpression | null, body: BoltFunctionBodyElement[], span?: TextSpan | null): BoltFunctionDeclaration;
export function createBoltVariableDeclaration(modifiers: BoltDeclarationModifiers, bindings: BoltPattern, type: BoltTypeExpression | null, value: BoltExpression | null, span?: TextSpan | null): BoltVariableDeclaration;
export function createBoltPlainImportSymbol(name: BoltQualName, span?: TextSpan | null): BoltPlainImportSymbol;
export function createBoltImportDeclaration(file: string, symbols: BoltImportSymbol[], span?: TextSpan | null): BoltImportDeclaration;

View file

@ -5,6 +5,8 @@ import {
SyntaxKind,
BoltImportDeclaration,
BoltPattern,
isBoltTypeAliasDeclaration,
BoltFunctionBodyElement,
} from "./ast"
import { FastStringMap, getFullTextOfQualName } from "./util"
@ -45,13 +47,13 @@ export const noneType = new PrimType();
export class RecordType {
fieldTypes: FastStringMap<Type> = Object.create(null);
private fieldTypes = new FastStringMap<string, Type>();
constructor(
iterable: IterableIterator<[string, Type]>,
) {
for (const [name, typ] of iterable) {
this.fieldTypes[name] = typ;
for (const [name, type] of iterable) {
this.fieldTypes.set(name, type);
}
}
@ -60,18 +62,47 @@ export class RecordType {
}
getTypeOfField(name: string) {
if (name in this.fieldTypes) {
return this.fieldTypes[name]
}
throw new Error(`Field '${name}' does not exist on this record type.`)
return this.fieldTypes.get(name);
}
}
interface SymbolInfo {
type: Type | null;
definitions: Syntax[];
}
export class Scope {
constructor(public origin: Syntax) {
private symbolsByLocalName = new FastStringMap<string, SymbolInfo>();
constructor(
public originatingNode: Syntax,
public parentScope?: Scope | null
) {
}
public getSymbolNamed(name: string): SymbolInfo | null {
let currScope: Scope | null = this;
while (true) {
if (currScope.symbolsByLocalName.has(name)) {
return currScope.symbolsByLocalName.get(name);
}
currScope = currScope.parentScope;
if (currScope === null) {
break;
}
}
return null;
}
public getTypeNamed(name: string): Type | null {
const sym = this.getSymbolNamed(name);
if (sym === null || !introducesNewType(sym.definitions[0].kind)) {
return null;
}
return sym.type!;
}
}
@ -87,6 +118,16 @@ function* map<T, R>(iterable: Iterable<T>, proc: (value: T) => R): IterableItera
}
}
function introducesNewType(kind: SyntaxKind): boolean {
return kind === SyntaxKind.BoltRecordDeclaration
|| kind === SyntaxKind.BoltTypeAliasDeclaration;
}
function introducesNewScope(kind: SyntaxKind): boolean {
return kind === SyntaxKind.BoltFunctionDeclaration
|| kind === SyntaxKind.BoltSourceFile;
}
function getFullName(node: Syntax) {
let out = []
let curr: Syntax | null = node;
@ -112,22 +153,19 @@ function getFullName(node: Syntax) {
export class TypeChecker {
protected symbols: FastStringMap<Type> = Object.create(null)
protected types = new Map<Syntax, Type>();
protected scopes = new Map<Syntax, Scope>();
private symbols = new FastStringMap<string, Type>();
private types = new Map<Syntax, Type>();
private scopes = new Map<Syntax, Scope>();
constructor() {
}
protected inferTypeFromUsage(bindings: BoltPattern, body: Body) {
private inferTypeFromUsage(bindings: BoltPattern, body: BoltFunctionBodyElement[]) {
return anyType;
}
protected getTypeOfBody(body: Body) {
private getTypeOfBody(body: BoltFunctionBodyElement[]) {
return anyType;
}
protected createType(node: Syntax): Type {
private createType(node: Syntax): Type {
console.error(`creating type for ${kindToString(node.kind)}`);
@ -139,11 +177,6 @@ export class TypeChecker {
case SyntaxKind.BoltConstantExpression:
return node.value.type;
case SyntaxKind.BoltNewTypeDeclaration:
console.log(getFullName(node.name))
this.symbols[getFullName(node.name)] = new PrimType();
return noneType;
case SyntaxKind.BoltExpressionStatement:
return voidType;
@ -171,21 +204,29 @@ export class TypeChecker {
})
return new FunctionType(paramTypes, returnType);
case SyntaxKind.BoltReferenceTypeNode:
case SyntaxKind.BoltReferenceTypeExpression:
const name = getFullTextOfQualName(node.name);
const reffed = this.getTypeNamed(name);
const scope = this.getScope(node);
let reffed = scope.getTypeNamed(name);
if (reffed === null) {
throw new Error(`Could not find a type named '${name}'`);
reffed = anyType;
}
return reffed;
case SyntaxKind.BoltRecordDeclaration:
const typ = new RecordType(map(node.fields, field => ([field.name.text, this.getTypeOfNode(field.type)])));
const fullName = getFullName(node);
let type;
this.symbols[getFullName(node)] = typ;
if (node.members === null) {
type = new PrimType();
this.symbols.set(fullName, type);
} else {
type = new RecordType(map(node.members, member => ([field.name.text, this.getTypeOfNode(field.type)])));
this.symbols.set(fullName, type);
}
return typ;
return type;
case SyntaxKind.BoltParameter:
if (node.type !== null) {
@ -200,13 +241,14 @@ export class TypeChecker {
}
getTypeNamed(name: string) {
return name in this.symbols
? this.symbols[name]
: null
public getSymbolNamed(name: string) {
if (!this.symbols.has(name)) {
return null;
}
return this.symbols.get(name);
}
getTypeOfNode(node: Syntax): Type {
public getTypeOfNode(node: Syntax): Type {
if (this.types.has(node)) {
return this.types.get(node)!
}
@ -215,15 +257,13 @@ export class TypeChecker {
return newType;
}
check(node: Syntax) {
public check(node: Syntax) {
this.getTypeOfNode(node);
switch (node.kind) {
case SyntaxKind.BoltSentence:
case SyntaxKind.BoltRecordDeclaration:
case SyntaxKind.BoltNewTypeDeclaration:
case SyntaxKind.BoltConstantExpression:
break;
@ -267,12 +307,8 @@ export class TypeChecker {
}
getImportedSymbols(node: BoltImportDeclaration) {
return [{ name: 'fac' }]
}
getScope(node: Syntax): Scope {
while (node.kind !== SyntaxKind.BoltFunctionDeclaration && node.kind !== SyntaxKind.BoltSourceFile) {
public getScope(node: Syntax): Scope {
while (!introducesNewScope(node.kind)) {
node = node.parentNode!;
}
if (this.scopes.has(node)) {
@ -283,7 +319,7 @@ export class TypeChecker {
return scope
}
protected intersectTypes(a: Type, b: Type): Type {
private intersectTypes(a: Type, b: Type): Type {
if (a === noneType || b == noneType) {
return noneType;
}
@ -304,9 +340,5 @@ export class TypeChecker {
return noneType;
}
// getMapperForNode(target: string, node: Syntax): Mapper {
// return this.getScope(node).getMapper(target)
// }
}

View file

@ -1,5 +1,5 @@
import { Syntax, SyntaxKind, Expr, isNode } from "./ast"
import { Syntax, SyntaxKind, Expr, isNode, BoltQualName } from "./ast"
import { TypeChecker, Type, RecordType, PrimType, boolType } from "./checker"
import { FastStringMap } from "./util"
@ -65,28 +65,32 @@ export class RecordWrapper extends RecordValue {
}
function getDeclarationPath(node: BoltQualName) {
return [...node.modulePath.map(id => id.text), node.name.text];
}
class Environment {
private symbols: FastStringMap<Value> = Object.create(null);
private symbols = FastStringMap<string, Value>();
constructor(public parentEnv: Environment | null = null) {
}
setValue(name: string, value: Value) {
public setValue(name: string, value: Value) {
if (name in this.symbols) {
throw new Error(`A variable with the name '${name}' already exists.`);
}
this.symbols[name] = value;
}
updateValue(name: string, newValue: Value) {
public updateValue(name: string, newValue: Value) {
if (!(name in this.symbols)) {
throw new Error(`Trying to update a variable '${name}' that has not been declared.`);
}
}
lookup(name: string) {
public lookup(name: string) {
let curr = this as Environment;
while (true) {
if (name in curr.symbols) {
@ -136,26 +140,26 @@ export class Evaluator {
}
}
eval(node: Syntax, env: Environment = new Environment()): Value {
public eval(node: Syntax, env: Environment = new Environment()): Value {
switch (node.kind) {
case SyntaxKind.SourceFile:
case SyntaxKind.Module:
case SyntaxKind.BoltSourceFile:
case SyntaxKind.BoltModule:
for (const element of node.elements) {
this.eval(element, env);
}
break;
case SyntaxKind.RefExpr:
return env.lookup(node.name.fullText);
case SyntaxKind.BoltReferenceTypeExpression:
// FIXME
return env.lookup(node.name.name.text);
case SyntaxKind.NewTypeDecl:
case SyntaxKind.RecordDecl:
case SyntaxKind.FuncDecl:
case SyntaxKind.BoltRecordDeclaration:
case SyntaxKind.BoltFunctionDeclaration:
break;
case SyntaxKind.MatchExpr:
case SyntaxKind.BoltMatchExpression:
const value = this.eval(node.value, env);
for (const [pattern, result] of node.arms) {
if (this.match(value, pattern)) {
@ -164,7 +168,7 @@ export class Evaluator {
}
return new PrimValue(this.checker.getTypeNamed('Void')!, null);
case SyntaxKind.ConstExpr:
case SyntaxKind.BoltConstantExpression:
return new PrimValue(this.checker.getTypeOfNode(node), node.value)
default: