Refactoring; Add tslint fwiw

This commit is contained in:
dcodeIO 2017-12-24 03:19:47 +01:00
parent d7c069b692
commit 4baff99125
15 changed files with 649 additions and 335 deletions

117
package-lock.json generated
View File

@ -57,7 +57,8 @@
"@types/node": {
"version": "8.5.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.5.1.tgz",
"integrity": "sha512-SrmAO+NhnsuG/6TychSl2VdxBZiw/d6V+8j+DFo8O3PwFi+QeYXWHhAw+b170aSc6zYab6/PjEWRZHIDN9mNUw=="
"integrity": "sha512-SrmAO+NhnsuG/6TychSl2VdxBZiw/d6V+8j+DFo8O3PwFi+QeYXWHhAw+b170aSc6zYab6/PjEWRZHIDN9mNUw==",
"dev": true
},
"@types/strip-bom": {
"version": "3.0.0",
@ -202,6 +203,44 @@
"integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
"dev": true
},
"babel-code-frame": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
"integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
"dev": true,
"requires": {
"chalk": "1.1.3",
"esutils": "2.0.2",
"js-tokens": "3.0.2"
},
"dependencies": {
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "2.2.1",
"escape-string-regexp": "1.0.5",
"has-ansi": "2.0.0",
"strip-ansi": "3.0.1",
"supports-color": "2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
}
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@ -441,6 +480,12 @@
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"commander": {
"version": "2.12.2",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz",
"integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -742,6 +787,12 @@
"integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
"dev": true
},
"esutils": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
"integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
"dev": true
},
"event-emitter": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
@ -920,6 +971,15 @@
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
"dev": true
},
"has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
"dev": true,
"requires": {
"ansi-regex": "2.1.1"
}
},
"has-flag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
@ -1138,6 +1198,12 @@
"isarray": "1.0.0"
}
},
"js-tokens": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
"integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
"dev": true
},
"json-loader": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz",
@ -1593,6 +1659,12 @@
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
"dev": true
},
"path-parse": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
"integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
"dev": true
},
"path-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
@ -1829,6 +1901,15 @@
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"resolve": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
"integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
"dev": true,
"requires": {
"path-parse": "1.0.5"
}
},
"right-align": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
@ -2112,6 +2193,40 @@
"strip-json-comments": "2.0.1"
}
},
"tslib": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.8.1.tgz",
"integrity": "sha1-aUavLR1lGnsYY7Ux1uWvpBqkTqw=",
"dev": true
},
"tslint": {
"version": "5.8.0",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-5.8.0.tgz",
"integrity": "sha1-H0mtWy53x2w69N3K5VKuTjYS6xM=",
"dev": true,
"requires": {
"babel-code-frame": "6.26.0",
"builtin-modules": "1.1.1",
"chalk": "2.3.0",
"commander": "2.12.2",
"diff": "3.4.0",
"glob": "7.1.2",
"minimatch": "3.0.4",
"resolve": "1.5.0",
"semver": "5.4.1",
"tslib": "1.8.1",
"tsutils": "2.14.0"
}
},
"tsutils": {
"version": "2.14.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.14.0.tgz",
"integrity": "sha512-f6axSMV0RoUufiKiRQgmRlN1c+Ag+mDaZjcd6bHdvplT/zyhuMCGqw3pJS8s3+0x4EVkdoQajs9PchdDZlguvw==",
"dev": true,
"requires": {
"tslib": "1.8.1"
}
},
"tty-browserify": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",

View File

@ -28,6 +28,7 @@
"long": "^3.2.0",
"ts-loader": "^3.2.0",
"ts-node": "^4.0.2",
"tslint": "^5.8.0",
"typescript": "^2.6.2",
"webpack": "^3.10.0"
},
@ -45,7 +46,8 @@
"test:config:src": "tsc --noEmit -p src --diagnostics --listFiles",
"test:parser": "node tests/parser",
"test:compiler": "node tests/compiler",
"test": "npm run test:config --scripts-prepend-node-path && npm run test:parser --scripts-prepend-node-path && npm run test:compiler --scripts-prepend-node-path"
"test": "npm run test:config --scripts-prepend-node-path && npm run test:parser --scripts-prepend-node-path && npm run test:compiler --scripts-prepend-node-path",
"lint": "tslint --project src"
},
"files": [
"bin/",

View File

@ -1,8 +1,27 @@
import { GETTER_PREFIX, SETTER_PREFIX, PATH_DELIMITER, PARENT_SUBST, STATIC_DELIMITER, INSTANCE_DELIMITER } from "./constants";
import { Token, Tokenizer, operatorTokenToString, Range } from "./tokenizer";
import { CharCode } from "./util/charcode";
import { I64 } from "./util/i64";
import { normalize as normalizePath, resolve as resolvePath } from "./util/path";
import {
PATH_DELIMITER,
STATIC_DELIMITER,
INSTANCE_DELIMITER
} from "./constants";
import {
Token,
Tokenizer,
Range
} from "./tokenizer";
import{
CharCode
} from "./util/charcode";
import {
I64
} from "./util/i64";
import {
normalize as normalizePath,
resolve as resolvePath
} from "./util/path";
export { Range } from "./tokenizer";
@ -489,7 +508,7 @@ export abstract class Node {
(stmt.name = identifier).parent = stmt;
for (i = 0, k = (stmt.typeParameters = typeParameters).length; i < k; ++i) typeParameters[i].parent = stmt;
for (i = 0, k = (stmt.parameters = parameters).length; i < k; ++i) parameters[i].parent = stmt;
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;;
if (stmt.returnType = returnType) (<TypeNode>returnType).parent = stmt;
if (stmt.statements = statements) for (i = 0, k = (<Statement[]>statements).length; i < k; ++i) (<Statement[]>statements)[i].parent = stmt;
if (stmt.modifiers = modifiers) for (i = 0, k = (<Modifier[]>modifiers).length; i < k; ++i) (<Modifier[]>modifiers)[i].parent = stmt;
if (stmt.decorators = decorators) for (i = 0, k = (<Decorator[]>decorators).length; i < k; ++i) (<Decorator[]>decorators)[i].parent = stmt;
@ -750,7 +769,7 @@ export class BinaryExpression extends Expression {
serialize(sb: string[]): void {
this.left.serialize(sb);
sb.push(" ");
sb.push(operatorTokenToString(this.operator));
sb.push(Token.operatorToString(this.operator));
sb.push(" ");
this.right.serialize(sb);
}
@ -995,7 +1014,7 @@ export class UnaryPrefixExpression extends UnaryExpression {
kind = NodeKind.UNARYPREFIX;
serialize(sb: string[]): void {
sb.push(operatorTokenToString(this.operator));
sb.push(Token.operatorToString(this.operator));
this.operand.serialize(sb);
}
}

View File

@ -1,9 +1,38 @@
import { Compiler, Target, ConversionKind, typeToNativeType, typeToNativeOne, typeToNativeZero } from "./compiler";
import { DiagnosticCode } from "./diagnostics";
import { Node, Expression, IdentifierExpression } from "./ast";
import { Type } from "./types";
import { Module, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType, FunctionTypeRef } from "./module";
import { Program, ElementFlags, Element, Global, FunctionPrototype, Local } from "./program";
import {
Compiler,
Target,
ConversionKind
} from "./compiler";
import {
DiagnosticCode
} from "./diagnostics";
import {
Node,
Expression
} from "./ast";
import {
Type
} from "./types";
import {
Module,
UnaryOp,
BinaryOp,
HostOp,
NativeType,
ExpressionRef,
FunctionTypeRef
} from "./module";
import {
Program,
Global,
FunctionPrototype,
Local
} from "./program";
/** Initializes the specified program with built-in functions. */
export function initialize(program: Program): void {
@ -149,7 +178,7 @@ export function compileGetGlobal(compiler: Compiler, global: Global): Expression
return compiler.module.createF64(Infinity);
case "HEAP_BASE": // constant, but never inlined
return compiler.module.createGetGlobal("HEAP_BASE", typeToNativeType(compiler.currentType = <Type>global.type));
return compiler.module.createGetGlobal("HEAP_BASE", (compiler.currentType = <Type>global.type).toNativeType());
default:
throw new Error("not implemented: " + global.internalName);
@ -539,7 +568,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
return module.createUnreachable();
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
if ((compiler.currentType = typeArguments[0]) != Type.void)
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].isSignedInteger, arg0, typeToNativeType(typeArguments[0]));
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].isSignedInteger, arg0, typeArguments[0].toNativeType());
break;
case "store": // store<T>(offset: usize, value: T) -> void
@ -550,7 +579,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
arg1 = compiler.compileExpression(operands[1], typeArguments[0]); // reports
compiler.currentType = Type.void;
if (typeArguments[0] != Type.void)
return module.createStore(typeArguments[0].byteSize, arg0, arg1, typeToNativeType(typeArguments[0]));
return module.createStore(typeArguments[0].byteSize, arg0, arg1, typeArguments[0].toNativeType());
break;
case "sizeof": // sizeof<T>() -> usize
@ -685,7 +714,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
return module.createUnreachable();
}
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
arg1 = operands.length > 1 ? compiler.compileExpression(operands[1], usizeType) : typeToNativeZero(module, usizeType); // TODO: string type
arg1 = operands.length > 1 ? compiler.compileExpression(operands[1], usizeType) : usizeType.toNativeZero(module); // TODO: string type
compiler.currentType = Type.void;
return compiler.options.noAssert
? module.createNop()

View File

@ -1,8 +1,18 @@
import { compileCall as compileBuiltinCall, compileGetGlobal as compileBuiltinGetGlobal, initialize } from "./builtins";
import { PATH_DELIMITER } from "./constants";
import { DiagnosticCode, DiagnosticEmitter } from "./diagnostics";
import {
compileCall as compileBuiltinCall,
compileGetGlobal as compileBuiltinGetGlobal
} from "./builtins";
import {
PATH_DELIMITER
} from "./constants";
import {
DiagnosticCode,
DiagnosticEmitter
} from "./diagnostics";
import {
Module,
MemorySegment,
ExpressionRef,
@ -12,15 +22,14 @@ import {
FunctionTypeRef,
FunctionRef,
ExpressionId
} from "./module";
import {
import {
Program,
ClassPrototype,
Class, Element,
Class,
Element,
ElementKind,
ElementFlags,
Enum,
FunctionPrototype,
Function,
@ -29,17 +38,17 @@ import {
Namespace,
Parameter,
EnumValue
} from "./program";
import { Token } from "./tokenizer";
import {
import {
Token
} from "./tokenizer";
import {
Node,
NodeKind,
TypeNode,
TypeParameter,
Source,
// statements
BlockStatement,
BreakStatement,
@ -53,13 +62,11 @@ import {
ExportMember,
ExportStatement,
ExpressionStatement,
FieldDeclaration,
FunctionDeclaration,
ForStatement,
IfStatement,
ImportStatement,
InterfaceDeclaration,
MethodDeclaration,
ModifierKind,
NamespaceDeclaration,
ReturnStatement,
@ -72,9 +79,7 @@ import {
VariableDeclaration,
VariableStatement,
WhileStatement,
// expressions
ArrayLiteralExpression,
AssertionExpression,
BinaryExpression,
CallExpression,
@ -92,19 +97,24 @@ import {
StringLiteralExpression,
UnaryPostfixExpression,
UnaryPrefixExpression,
// utility
hasModifier
} from "./ast";
import {
import {
Type,
TypeKind,
typesToNativeTypes
} from "./types";
import { I64, U64 } from "./util/i64";
import { sb } from "./util/sb";
import {
I64,
U64
} from "./util/i64";
import {
sb
} from "./util/sb";
/** Compilation target. */
export enum Target {
@ -331,7 +341,6 @@ export class Compiler extends DiagnosticEmitter {
return true;
const declaration: VariableLikeDeclarationStatement | null = global.declaration;
let type: Type | null = null;
let initExpr: ExpressionRef = 0;
if (!global.type) { // infer type
@ -353,7 +362,7 @@ export class Compiler extends DiagnosticEmitter {
throw new Error("declaration expected");
}
const nativeType: NativeType = typeToNativeType(global.type);
const nativeType: NativeType = global.type.toNativeType();
let initializeInStart: bool = false;
if (global.hasConstantValue) {
@ -386,13 +395,13 @@ export class Compiler extends DiagnosticEmitter {
initializeInStart = true;
}
} else
initExpr = typeToNativeZero(this.module, global.type);
initExpr = global.type.toNativeZero(this.module);
} else
throw new Error("declaration expected");
const internalName: string = global.internalName;
if (initializeInStart) {
this.module.addGlobal(internalName, nativeType, true, typeToNativeZero(this.module, global.type));
this.module.addGlobal(internalName, nativeType, true, global.type.toNativeZero(this.module));
const setExpr: ExpressionRef = this.module.createSetGlobal(internalName, initExpr);
if (!this.module.noEmit)
this.startFunctionBody.push(setExpr);
@ -547,14 +556,14 @@ export class Compiler extends DiagnosticEmitter {
// create the function type
let k: i32 = instance.parameters.length;
const nativeResultType: NativeType = typeToNativeType(instance.returnType);
const nativeResultType: NativeType = instance.returnType.toNativeType();
const nativeParamTypes: NativeType[] = new Array(k);
const signatureNameParts: string[] = new Array(k + 1);
for (let i: i32 = 0; i < k; ++i) {
nativeParamTypes[i] = typeToNativeType(instance.parameters[i].type);
signatureNameParts[i] = typeToSignatureNamePart(instance.parameters[i].type);
nativeParamTypes[i] = instance.parameters[i].type.toNativeType();
signatureNameParts[i] = instance.parameters[i].type.toSignatureName();
}
signatureNameParts[k] = typeToSignatureNamePart(instance.returnType);
signatureNameParts[k] = instance.returnType.toSignatureName();
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(nativeResultType, nativeParamTypes);
if (!typeRef)
typeRef = this.module.addFunctionType(signatureNameParts.join(""), nativeResultType, nativeParamTypes);
@ -1101,10 +1110,10 @@ export class Compiler extends DiagnosticEmitter {
}
precomputeExpressionRef(expr: ExpressionRef): ExpressionRef {
const nativeType: NativeType = typeToNativeType(this.currentType);
const nativeType: NativeType = this.currentType.toNativeType();
let typeRef: FunctionTypeRef = this.module.getFunctionTypeBySignature(nativeType, []);
if (!typeRef)
typeRef = this.module.addFunctionType(typeToSignatureNamePart(this.currentType), nativeType, []);
typeRef = this.module.addFunctionType(this.currentType.toSignatureName(), nativeType, []);
const funcRef: FunctionRef = this.module.addFunction("__precompute", typeRef, [], expr);
this.module.runPasses([ "precompute" ], funcRef);
const ret: ExpressionRef = _BinaryenFunctionGetBody(funcRef);
@ -1564,7 +1573,7 @@ export class Compiler extends DiagnosticEmitter {
? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
: this.module.createTeeLocal(tempLocal.index, left),
right,
this.module.createGetLocal(tempLocal.index, typeToNativeType(tempLocal.type))
this.module.createGetLocal(tempLocal.index, tempLocal.type.toNativeType())
);
case Token.BAR_BAR: // left || right
@ -1596,7 +1605,7 @@ export class Compiler extends DiagnosticEmitter {
: this.currentType == Type.f32
? this.module.createBinary(BinaryOp.NeF32, condition, this.module.createF32(0))
: this.module.createTeeLocal(tempLocal.index, left),
this.module.createGetLocal(tempLocal.index, typeToNativeType(tempLocal.type)),
this.module.createGetLocal(tempLocal.index, tempLocal.type.toNativeType()),
right
);
@ -1665,7 +1674,7 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createUnreachable();
}
if (tee) {
const globalNativeType: NativeType = typeToNativeType(<Type>(<Global>element).type);
const globalNativeType: NativeType = (<Type>(<Global>element).type).toNativeType();
return this.module.createBlock(null, [ // teeGlobal
this.module.createSetGlobal((<Global>element).internalName, valueWithCorrectType),
this.module.createGetGlobal((<Global>element).internalName, globalNativeType)
@ -1724,7 +1733,6 @@ export class Compiler extends DiagnosticEmitter {
/** Compiles a call to a function. If an instance method, `this` is the first element in `argumentExpressions`. */
compileCall(functionInstance: Function, argumentExpressions: Expression[], reportNode: Node): ExpressionRef {
const previousType: Type = this.currentType;
// validate and compile arguments
const parameters: Parameter[] = functionInstance.parameters;
@ -1765,10 +1773,10 @@ export class Compiler extends DiagnosticEmitter {
// imported function
if (functionInstance.isDeclared)
return this.module.createCallImport(functionInstance.internalName, operands, typeToNativeType(functionInstance.returnType));
return this.module.createCallImport(functionInstance.internalName, operands, functionInstance.returnType.toNativeType());
// internal function
return this.module.createCall(functionInstance.internalName, operands, typeToNativeType(functionInstance.returnType));
return this.module.createCall(functionInstance.internalName, operands, functionInstance.returnType.toNativeType());
}
compileElementAccessExpression(expression: ElementAccessExpression, contextualType: Type): ExpressionRef {
@ -1820,7 +1828,7 @@ export class Compiler extends DiagnosticEmitter {
// local
if (element.kind == ElementKind.LOCAL) {
this.currentType = (<Local>element).type;
return this.module.createGetLocal((<Local>element).index, typeToNativeType(this.currentType));
return this.module.createGetLocal((<Local>element).index, this.currentType.toNativeType());
}
// global
@ -1844,7 +1852,7 @@ export class Compiler extends DiagnosticEmitter {
else
throw new Error("unexpected global type");
} else
return this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType));
return this.module.createGetGlobal((<Global>element).internalName, this.currentType.toNativeType());
}
// field
@ -1947,7 +1955,6 @@ export class Compiler extends DiagnosticEmitter {
// look up the property within the target to obtain the actual element
let element: Element | null;
let expr: ExpressionRef;
switch (target.kind) {
case ElementKind.LOCAL:
@ -1996,7 +2003,7 @@ export class Compiler extends DiagnosticEmitter {
switch (element.kind) {
case ElementKind.LOCAL:
return this.module.createGetLocal((<Local>element).index, typeToNativeType(this.currentType = (<Local>element).type));
return this.module.createGetLocal((<Local>element).index, (this.currentType = (<Local>element).type).toNativeType());
case ElementKind.GLOBAL:
if (!this.compileGlobal(<Global>element))
@ -2010,7 +2017,7 @@ export class Compiler extends DiagnosticEmitter {
: this.currentType.isLongInteger
? this.module.createI64((<I64>(<Global>element).constantIntegerValue).lo, (<I64>(<Global>element).constantIntegerValue).hi)
: this.module.createI32((<I64>(<Global>element).constantIntegerValue).lo);
return this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType));
return this.module.createGetGlobal((<Global>element).internalName, this.currentType.toNativeType());
case ElementKind.FUNCTION: // getter
if (!(<Function>element).prototype.isGetter) {
@ -2157,66 +2164,6 @@ export class Compiler extends DiagnosticEmitter {
// helpers
export function typeToNativeType(type: Type): NativeType {
return type.kind == TypeKind.F32
? NativeType.F32
: type.kind == TypeKind.F64
? NativeType.F64
: type.isLongInteger
? NativeType.I64
: type.isAnyInteger || type.kind == TypeKind.BOOL
? NativeType.I32
: NativeType.None;
}
export function typesToNativeTypes(types: Type[]): NativeType[] {
const k: i32 = types.length;
const ret: NativeType[] = new Array(k);
for (let i: i32 = 0; i < k; ++i)
ret[i] = typeToNativeType(types[i]);
return ret;
}
export function typeToNativeZero(module: Module, type: Type): ExpressionRef {
return type.kind == TypeKind.F32
? module.createF32(0)
: type.kind == TypeKind.F64
? module.createF64(0)
: type.isLongInteger
? module.createI64(0, 0)
: module.createI32(0);
}
export function typeToNativeOne(module: Module, type: Type): ExpressionRef {
return type.kind == TypeKind.F32
? module.createF32(1)
: type.kind == TypeKind.F64
? module.createF64(1)
: type.isLongInteger
? module.createI64(1, 0)
: module.createI32(1);
}
function typeToSignatureNamePart(type: Type): string {
return type.kind == TypeKind.VOID
? "v"
: type.kind == TypeKind.F32
? "f"
: type.kind == TypeKind.F64
? "F"
: type.isLongInteger
? "I"
: "i";
}
function typesToSignatureName(paramTypes: Type[], returnType: Type): string {
sb.length = 0;
for (let i: i32 = 0, k: i32 = paramTypes.length; i < k; ++i)
sb.push(typeToSignatureNamePart(paramTypes[i]));
sb.push(typeToSignatureNamePart(returnType));
return sb.join("");
}
function isModuleExport(element: Element, declaration: DeclarationStatement): bool {
if (!element.isExported)
return false;

View File

@ -1,20 +1,19 @@
import {
Module,
NativeType,
ExpressionId,
UnaryOp,
BinaryOp,
HostOp,
FunctionTypeRef,
FunctionRef,
ExpressionRef,
Index,
readString
} from "./module";
import { I64 } from "./util/i64";
import {
I64
} from "./util/i64";
// TODO :-)
@ -40,7 +39,7 @@ export class Decompiler {
}
decompileFunction(func: FunctionRef): void {
const name: string = readString(_BinaryenFunctionGetName(func)) || "$" + this.functionId.toString(10)
const name: string = readString(_BinaryenFunctionGetName(func)) || "$" + this.functionId.toString(10);
const body: ExpressionRef = _BinaryenFunctionGetBody(func);
this.push("function ");
this.push(name);
@ -560,7 +559,7 @@ export class Decompiler {
return;
case BinaryOp.RotlI32:
this.push("rotl<i32>(")
this.push("rotl<i32>(");
this.decompileExpression(_BinaryenBinaryGetLeft(expr));
this.push(", ");
this.decompileExpression(_BinaryenBinaryGetRight(expr));
@ -568,7 +567,7 @@ export class Decompiler {
return;
case BinaryOp.RotrI32:
this.push("rotr<i32>(")
this.push("rotr<i32>(");
this.decompileExpression(_BinaryenBinaryGetLeft(expr));
this.push(", ");
this.decompileExpression(_BinaryenBinaryGetRight(expr));
@ -821,7 +820,7 @@ export class Decompiler {
case ExpressionId.AtomicWake:
}
throw new Error("not implemented: " + id);
throw new Error("not implemented");
}
private push(text: string): void {

View File

@ -1,9 +1,25 @@
import { Range } from "./ast";
import { DiagnosticCode, diagnosticCodeToString } from "./diagnosticMessages.generated";
import { CharCode, isLineBreak } from "./util/charcode";
import { sb } from "./util/sb";
import {
Range
} from "./ast";
export { DiagnosticCode, diagnosticCodeToString } from "./diagnosticMessages.generated";
import {
DiagnosticCode,
diagnosticCodeToString
} from "./diagnosticMessages.generated";
import {
CharCode,
isLineBreak
} from "./util/charcode";
import {
sb
} from "./util/sb";
export {
DiagnosticCode,
diagnosticCodeToString
} from "./diagnosticMessages.generated";
export enum DiagnosticCategory {
INFO,
@ -75,8 +91,8 @@ export class DiagnosticMessage {
toString(): string {
if (this.range)
return diagnosticCategoryToString(this.category) + " " + this.code + ": \"" + this.message + "\" in " + this.range.source.path + " @ " + this.range.start + "," + this.range.end;
return diagnosticCategoryToString(this.category) + " " + this.code + ": " + this.message;
return diagnosticCategoryToString(this.category) + " " + this.code.toString(10) + ": \"" + this.message + "\" in " + this.range.source.path + " @ " + this.range.start.toString(10) + "," + this.range.end.toString(10);
return diagnosticCategoryToString(this.category) + " " + this.code.toString(10) + ": " + this.message;
}
}
@ -84,7 +100,7 @@ export function formatDiagnosticMessage(message: DiagnosticMessage, useColors: b
// format context first (uses same string builder)
let context: string = "";
if (message.range && showContext)
context = formatDiagnosticContext(message.range, useColors)
context = formatDiagnosticContext(message.range, useColors);
// general information
sb.length = 0;

View File

@ -22,12 +22,33 @@
*/
import { Module } from "./module";
import { Compiler, Options, Target } from "./compiler";
import { DiagnosticMessage, DiagnosticCategory, formatDiagnosticMessage } from "./diagnostics";
import { Parser } from "./parser";
import { Program } from "./program";
import { Decompiler } from "./decompiler";
import {
Module
} from "./module";
import {
Compiler,
Options,
Target
} from "./compiler";
import {
DiagnosticMessage,
DiagnosticCategory,
formatDiagnosticMessage
} from "./diagnostics";
import {
Parser
} from "./parser";
import {
Program
} from "./program";
import {
Decompiler
} from "./decompiler";
/** Parses a single source file. If `parser` has been omitted a new one is created. */
export function parseFile(text: string, path: string, parser: Parser | null = null, isEntry: bool = false): Parser {

View File

@ -1,5 +1,10 @@
import { Target } from "./compiler";
import { I64, U64 } from "./util/i64";
import {
Target
} from "./compiler";
import {
U64
} from "./util/i64";
export type ModuleRef = usize;
export type FunctionTypeRef = usize;
@ -917,7 +922,7 @@ function allocU8Array(u8s: Uint8Array | null): usize {
const ptr: usize = Heap.allocate((<Uint8Array>u8s).length);
let idx: usize = ptr;
for (let i: i32 = 0, k: i32 = (<Uint8Array>u8s).length; i < k; ++i)
store<u8>(idx++, (<Uint8Array>u8s)[i])
store<u8>(idx++, (<Uint8Array>u8s)[i]);
return ptr;
}

View File

@ -7,27 +7,36 @@
*/
import { Program } from "./program";
import { Tokenizer, Token, Range } from "./tokenizer";
import { DiagnosticCode, DiagnosticEmitter } from "./diagnostics";
import { I64 } from "./util/i64";
import { normalize as normalizePath } from "./util/path";
import {
Program
} from "./program";
import {
Tokenizer,
Token,
Range
} from "./tokenizer";
import {
DiagnosticCode,
DiagnosticEmitter
} from "./diagnostics";
import {
normalize as normalizePath
} from "./util/path";
import {
Node,
NodeKind,
Source,
// types
TypeNode,
// expressions
AssertionKind,
CallExpression,
Expression,
IdentifierExpression,
StringLiteralExpression,
// statements
BlockStatement,
BreakStatement,
@ -64,12 +73,11 @@ import {
VariableStatement,
VariableDeclaration,
WhileStatement,
// utility
addModifier,
getModifier,
hasModifier,
setReusableModifiers
} from "./ast";
/** Parser interface. */
@ -1402,7 +1410,7 @@ export class Parser extends DiagnosticEmitter {
let p: Precedence = determinePrecedenceStart(token);
if (p != Precedence.INVALID) {
let operand: Expression | null
let operand: Expression | null;
// TODO: SpreadExpression, YieldExpression (currently become unsupported UnaryPrefixExpressions)

View File

@ -1,29 +1,49 @@
import { initialize as initializeBuiltins } from "./builtins";
import { Target, typeToNativeType } from "./compiler";
import { GETTER_PREFIX, SETTER_PREFIX, PATH_DELIMITER } from "./constants";
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
import { Type, typesToString } from "./types";
import { I64 } from "./util/i64";
import {
initialize as initializeBuiltins
} from "./builtins";
import {
Target
} from "./compiler";
import {
PATH_DELIMITER
} from "./constants";
import {
DiagnosticCode,
DiagnosticMessage,
DiagnosticEmitter
} from "./diagnostics";
import {
Type,
typesToString
} from "./types";
import {
I64
} from "./util/i64";
import {
ModifierKind,
Node,
NodeKind,
Source,
Range,
TypeNode,
TypeParameter,
Decorator,
Expression,
IdentifierExpression,
LiteralExpression,
LiteralKind,
PropertyAccessExpression,
StringLiteralExpression,
CallExpression,
Statement,
ClassDeclaration,
DeclarationStatement,
Decorator,
EnumDeclaration,
EnumValueDeclaration,
ExportMember,
@ -34,20 +54,18 @@ import {
ImportStatement,
InterfaceDeclaration,
MethodDeclaration,
Modifier,
NamespaceDeclaration,
Statement,
TypeDeclaration,
TypeParameter,
VariableLikeDeclarationStatement,
VariableDeclaration,
VariableStatement,
hasModifier,
mangleInternalName
hasModifier
} from "./ast";
import { NativeType } from "./module";
import {
NativeType
} from "./module";
class QueuedExport {
isReExport: bool;
@ -845,7 +863,7 @@ export class Program extends DiagnosticEmitter {
return this.resolveElement((<CallExpression>expression).expression, contextualFunction);
}
throw new Error("not implemented: " + expression.kind);
throw new Error("not implemented");
}
}
@ -1229,9 +1247,9 @@ export class FunctionPrototype extends Element {
k = declaration.parameters.length;
const parameters: Parameter[] = new Array(k);
const parameterTypes: Type[] = new Array(k);
for (let i = 0; i < k; ++i) {
const typeNode: TypeNode | null = declaration.parameters[i].type;
if (typeNode) {
let typeNode: TypeNode | null ;
for (i = 0; i < k; ++i) {
if (typeNode = declaration.parameters[i].type) {
const type: Type | null = this.program.resolveType(<TypeNode>typeNode, contextualTypeArguments, true); // reports
if (type) {
parameters[i] = new Parameter(declaration.parameters[i].name.name, type);
@ -1243,9 +1261,8 @@ export class FunctionPrototype extends Element {
}
// resolve return type
const typeNode: TypeNode | null = declaration.returnType;
let returnType: Type;
if (typeNode) {
if (typeNode = declaration.returnType) {
const type: Type | null = this.program.resolveType(<TypeNode>typeNode, contextualTypeArguments, true); // reports
if (type)
returnType = <Type>type;
@ -1265,7 +1282,7 @@ export class FunctionPrototype extends Element {
resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null, alternativeReportNode: Node | null): Function | null {
let resolvedTypeArguments: Type[] | null;
if (this.isGeneric) {
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0, "" + this);
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
if (!this.declaration)
throw new Error("missing declaration");
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, alternativeReportNode);
@ -1357,7 +1374,7 @@ export class Function extends Element {
/** Gets a free temporary local of the specified type. */
getTempLocal(type: Type): Local {
let temps: Local[] | null;
switch (typeToNativeType(type)) {
switch (type.toNativeType()) {
case NativeType.I32: temps = this.tempI32s; break;
case NativeType.I64: temps = this.tempI64s; break;
case NativeType.F32: temps = this.tempF32s; break;
@ -1372,7 +1389,7 @@ export class Function extends Element {
/** Frees the temporary local for reuse. */
freeTempLocal(local: Local): void {
let temps: Local[];
switch (typeToNativeType(local.type)) {
switch (local.type.toNativeType()) {
case NativeType.I32: temps = this.tempI32s || (this.tempI32s = []); break;
case NativeType.I64: temps = this.tempI64s || (this.tempI64s = []); break;
case NativeType.F32: temps = this.tempF32s || (this.tempF32s = []); break;
@ -1385,7 +1402,7 @@ export class Function extends Element {
/** Gets and immediately frees a temporary local of the specified type. */
getAndFreeTempLocal(type: Type): Local {
let temps: Local[];
switch (typeToNativeType(type)) {
switch (type.toNativeType()) {
case NativeType.I32: temps = this.tempI32s || (this.tempI32s = []); break;
case NativeType.I64: temps = this.tempI64s || (this.tempI64s = []); break;
case NativeType.F32: temps = this.tempF32s || (this.tempF32s = []); break;
@ -1416,7 +1433,7 @@ export class Function extends Element {
assert(length > 0);
(<i32[]>this.breakStack).pop();
if (length > 1) {
this.breakContext = (<i32[]>this.breakStack)[length - 2].toString(10)
this.breakContext = (<i32[]>this.breakStack)[length - 2].toString(10);
} else {
this.breakContext = null;
this.breakStack = null;
@ -1461,7 +1478,7 @@ export class FieldPrototype extends Element {
case ModifierKind.PROTECTED:
case ModifierKind.PUBLIC:
case ModifierKind.STATIC: break; // already handled
default: throw new Error("unexpected modifier: " + this.declaration.modifiers[i]);
default: assert(false);
}
}
}

View File

@ -19,10 +19,30 @@
*/
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter, formatDiagnosticMessage } from "./diagnostics";
import { Source } from "./ast";
import { CharCode, isLineBreak, isWhiteSpace, isIdentifierStart, isIdentifierPart, isDecimalDigit, isOctalDigit, isKeywordCharacter } from "./util/charcode";
import { I64 } from "./util/i64";
import {
DiagnosticCode,
DiagnosticMessage,
DiagnosticEmitter
} from "./diagnostics";
import {
Source
} from "./ast";
import {
CharCode,
isLineBreak,
isWhiteSpace,
isIdentifierStart,
isIdentifierPart,
isDecimalDigit,
isOctalDigit,
isKeywordCharacter
} from "./util/charcode";
import {
I64
} from "./util/i64";
/** Named token types. */
export enum Token {
@ -162,7 +182,9 @@ export enum Token {
ENDOFFILE
}
function textToKeywordToken(text: string): Token {
export namespace Token {
export function fromKeyword(text: string): Token {
switch (text) {
case "abstract": return Token.ABSTRACT;
case "as": return Token.AS;
@ -229,7 +251,7 @@ function textToKeywordToken(text: string): Token {
}
}
export function operatorTokenToString(token: Token): string {
export function operatorToString(token: Token): string {
switch (token) {
case Token.DELETE: return "delete";
case Token.IN: return "in";
@ -283,7 +305,7 @@ export function operatorTokenToString(token: Token): string {
}
}
function isPossibleIdentifier(token: Token): bool {
export function isAlsoIdentifier(token: Token): bool {
switch (token) {
case Token.ABSTRACT:
case Token.AS:
@ -303,6 +325,7 @@ function isPossibleIdentifier(token: Token): bool {
return false;
}
}
}
export class Range {
@ -675,8 +698,8 @@ export class Tokenizer extends DiagnosticEmitter {
}
}
const keywordText: string = text.substring(posBefore, this.pos);
const keywordToken: Token = textToKeywordToken(keywordText);
if (keywordToken != Token.INVALID && !(preferIdentifier && isPossibleIdentifier(keywordToken)))
const keywordToken: Token = Token.fromKeyword(keywordText);
if (keywordToken != Token.INVALID && !(preferIdentifier && Token.isAlsoIdentifier(keywordToken)))
return keywordToken;
this.pos = posBefore;
}

View File

@ -1,5 +1,15 @@
import { Class, Function } from "./program";
import { sb } from "./util/sb";
import {
Class,
Function
} from "./program";
import {
sb
} from "./util/sb";
import {
NativeType, ExpressionRef, Module
} from "./module";
/** Indicates the kind of a type. */
export const enum TypeKind {
@ -123,6 +133,48 @@ export class Type {
}
}
// Binaryen specific
/** Converts this type to its respective native type. */
toNativeType(): NativeType {
return this.kind == TypeKind.F32
? NativeType.F32
: this.kind == TypeKind.F64
? NativeType.F64
: this.isLongInteger
? NativeType.I64
: this.isAnyInteger || this.kind == TypeKind.BOOL
? NativeType.I32
: NativeType.None;
}
/** Converts this type to its native `0` value. */
toNativeZero(module: Module): ExpressionRef {
return this.kind == TypeKind.F32 ? module.createF32(0)
: this.kind == TypeKind.F64 ? module.createF64(0)
: this.isLongInteger ? module.createI64(0, 0)
: module.createI32(0);
}
/** Converts this type to its native `1` value. */
toNativeOne(module: Module): ExpressionRef {
return this.kind == TypeKind.F32 ? module.createF32(1)
: this.kind == TypeKind.F64 ? module.createF64(1)
: this.isLongInteger ? module.createI64(1, 0)
: module.createI32(1);
}
/** Converts this type to its signature name. */
toSignatureName(): string {
return this.kind == TypeKind.VOID ? "v"
: this.kind == TypeKind.F32 ? "f"
: this.kind == TypeKind.F64 ? "F"
: this.isLongInteger ? "I"
: "i";
}
// Types
/** An 8-bit signed integer. */
static readonly i8: Type = new Type(TypeKind.I8, 8);
/** A 16-bit signed integer. */
@ -157,6 +209,15 @@ export class Type {
static readonly void: Type = new Type(TypeKind.VOID, 0);
}
/** Converts an array of types to an array of native types. */
export function typesToNativeTypes(types: Type[]): NativeType[] {
const k: i32 = types.length;
const ret: NativeType[] = new Array(k);
for (let i: i32 = 0; i < k; ++i)
ret[i] = types[i].toNativeType();
return ret;
}
/** Converts an array of types to its combined string representation. Usually type arguments. */
export function typesToString(types: Type[], prefix: string = "<", postfix: string = ">"): string {
const k: i32 = types.length;

View File

@ -1,4 +1,6 @@
import { CharCode } from "./charcode";
import {
CharCode
} from "./charcode";
/** Normalizes the specified path, removing interior placeholders. Expects a posix-formatted string / not Windows compatible. */
export function normalize(path: string, trimExtension: bool = false, separator: CharCode = CharCode.SLASH): string {

50
tslint.json Normal file
View File

@ -0,0 +1,50 @@
{
"defaultSeverity": "warning",
"rules": {
"adjacent-overload-signatures": true,
"ban-types": [ true, ["Object"], ["any"], ["undefined"], ["never"] ],
"deprecation": true,
"encoding": true,
"eofline": true,
"indent": [true, "spaces", 2],
"label-position": true,
"member-access": [ true, "no-public" ],
"new-parens": true,
"no-any": true,
"no-arg": true,
"no-consecutive-blank-lines": true,
"no-debugger": true,
"no-default-export": true,
"no-duplicate-imports": true,
"no-duplicate-super": true,
"no-duplicate-switch-case": true,
"no-duplicate-variable": true,
"no-eval": true,
"no-inferred-empty-object-type": true,
"no-internal-module": true,
"no-invalid-template-strings": true,
"no-invalid-this": true,
"no-irregular-whitespace": true,
"no-mergeable-namespace": true,
"no-misused-new": true,
"no-object-literal-type-assertion": true,
"no-parameter-properties": true,
"no-require-imports": true,
"no-shadowed-variable": true,
"no-sparse-arrays": true,
"no-string-literal": true,
"no-string-throw": true,
"no-this-assignment": true,
"no-trailing-whitespace": true,
"no-unbound-method": true,
"no-unsafe-any": true,
"no-unused-variable": true,
"no-void-expression": true,
"object-literal-shorthand": [true, "never"],
"prefer-method-signature": true,
"quotemark": [true, "double"],
"radix": true,
"restrict-plus-operands": true,
"semicolon": [true, "always"]
}
}