From 4baff991250693011520fed674ba2c96cf3918da Mon Sep 17 00:00:00 2001 From: dcodeIO Date: Sun, 24 Dec 2017 03:19:47 +0100 Subject: [PATCH] Refactoring; Add tslint fwiw --- package-lock.json | 117 ++++++++++++++++- package.json | 4 +- src/ast.ts | 35 ++++-- src/builtins.ts | 49 ++++++-- src/compiler.ts | 153 ++++++++-------------- src/decompiler.ts | 17 ++- src/diagnostics.ts | 32 +++-- src/index.ts | 33 ++++- src/module.ts | 11 +- src/parser.ts | 32 +++-- src/program.ts | 75 ++++++----- src/tokenizer.ts | 307 ++++++++++++++++++++++++--------------------- src/types.ts | 65 +++++++++- src/util/path.ts | 4 +- tslint.json | 50 ++++++++ 15 files changed, 649 insertions(+), 335 deletions(-) create mode 100644 tslint.json diff --git a/package-lock.json b/package-lock.json index 03e84af0..2b087a09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 9352d80a..e28f1afa 100644 --- a/package.json +++ b/package.json @@ -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/", diff --git a/src/ast.ts b/src/ast.ts index f4528850..43d3809b 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -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) (returnType).parent = stmt;; + if (stmt.returnType = returnType) (returnType).parent = stmt; if (stmt.statements = statements) for (i = 0, k = (statements).length; i < k; ++i) (statements)[i].parent = stmt; if (stmt.modifiers = modifiers) for (i = 0, k = (modifiers).length; i < k; ++i) (modifiers)[i].parent = stmt; if (stmt.decorators = decorators) for (i = 0, k = (decorators).length; i < k; ++i) (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); } } diff --git a/src/builtins.ts b/src/builtins.ts index 2e26046c..099f19e5 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -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 = global.type)); + return compiler.module.createGetGlobal("HEAP_BASE", (compiler.currentType = 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(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() -> 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() diff --git a/src/compiler.ts b/src/compiler.ts index 886323cb..731573ff 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -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((element).type); + const globalNativeType: NativeType = ((element).type).toNativeType(); return this.module.createBlock(null, [ // teeGlobal this.module.createSetGlobal((element).internalName, valueWithCorrectType), this.module.createGetGlobal((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 = (element).type; - return this.module.createGetLocal((element).index, typeToNativeType(this.currentType)); + return this.module.createGetLocal((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((element).internalName, typeToNativeType(this.currentType)); + return this.module.createGetGlobal((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((element).index, typeToNativeType(this.currentType = (element).type)); + return this.module.createGetLocal((element).index, (this.currentType = (element).type).toNativeType()); case ElementKind.GLOBAL: if (!this.compileGlobal(element)) @@ -2010,7 +2017,7 @@ export class Compiler extends DiagnosticEmitter { : this.currentType.isLongInteger ? this.module.createI64(((element).constantIntegerValue).lo, ((element).constantIntegerValue).hi) : this.module.createI32(((element).constantIntegerValue).lo); - return this.module.createGetGlobal((element).internalName, typeToNativeType(this.currentType)); + return this.module.createGetGlobal((element).internalName, this.currentType.toNativeType()); case ElementKind.FUNCTION: // getter if (!(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; diff --git a/src/decompiler.ts b/src/decompiler.ts index 482a4cb3..8905e484 100644 --- a/src/decompiler.ts +++ b/src/decompiler.ts @@ -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(") + this.push("rotl("); this.decompileExpression(_BinaryenBinaryGetLeft(expr)); this.push(", "); this.decompileExpression(_BinaryenBinaryGetRight(expr)); @@ -568,7 +567,7 @@ export class Decompiler { return; case BinaryOp.RotrI32: - this.push("rotr(") + this.push("rotr("); 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 { diff --git a/src/diagnostics.ts b/src/diagnostics.ts index b56b9250..b3e808f2 100644 --- a/src/diagnostics.ts +++ b/src/diagnostics.ts @@ -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; diff --git a/src/index.ts b/src/index.ts index 4ec1311e..c31ae28d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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 { diff --git a/src/module.ts b/src/module.ts index fa77a757..e802088b 100644 --- a/src/module.ts +++ b/src/module.ts @@ -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((u8s).length); let idx: usize = ptr; for (let i: i32 = 0, k: i32 = (u8s).length; i < k; ++i) - store(idx++, (u8s)[i]) + store(idx++, (u8s)[i]); return ptr; } diff --git a/src/parser.ts b/src/parser.ts index 7a6fdac7..0071c310 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -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) diff --git a/src/program.ts b/src/program.ts index 54e384f5..3f3ad61b 100644 --- a/src/program.ts +++ b/src/program.ts @@ -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((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, 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, contextualTypeArguments, true); // reports if (type) returnType = type; @@ -1265,7 +1282,7 @@ export class FunctionPrototype extends Element { resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map | 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); (this.breakStack).pop(); if (length > 1) { - this.breakContext = (this.breakStack)[length - 2].toString(10) + this.breakContext = (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); } } } diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 671f5264..5987db22 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -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,145 +182,148 @@ export enum Token { ENDOFFILE } -function textToKeywordToken(text: string): Token { - switch (text) { - case "abstract": return Token.ABSTRACT; - case "as": return Token.AS; - case "async": return Token.ASYNC; - case "await": return Token.AWAIT; - case "break": return Token.BREAK; - case "case": return Token.CASE; - case "catch": return Token.CATCH; - case "class": return Token.CLASS; - case "continue": return Token.CONTINUE; - case "const": return Token.CONST; - case "constructor": return Token.CONSTRUCTOR; - case "debugger": return Token.DEBUGGER; - case "declare": return Token.DECLARE; - case "default": return Token.DEFAULT; - case "delete": return Token.DELETE; - case "do": return Token.DO; - case "else": return Token.ELSE; - case "enum": return Token.ENUM; - case "export": return Token.EXPORT; - case "extends": return Token.EXTENDS; - case "false": return Token.FALSE; - case "finally": return Token.FINALLY; - case "for": return Token.FOR; - case "from": return Token.FROM; - case "function": return Token.FUNCTION; - case "get": return Token.GET; - case "if": return Token.IF; - case "implements": return Token.IMPLEMENTS; - case "import": return Token.IMPORT; - case "in": return Token.IN; - case "instanceof": return Token.INSTANCEOF; - case "interface": return Token.INTERFACE; - case "is": return Token.IS; - case "keyof": return Token.KEYOF; - case "let": return Token.LET; - case "module": return Token.MODULE; - case "namespace": return Token.NAMESPACE; - case "new": return Token.NEW; - case "null": return Token.NULL; - case "of": return Token.OF; - case "package": return Token.PACKAGE; - case "private": return Token.PRIVATE; - case "protected": return Token.PROTECTED; - case "public": return Token.PUBLIC; - case "readonly": return Token.READONLY; - case "return": return Token.RETURN; - case "set": return Token.SET; - case "static": return Token.STATIC; - case "super": return Token.SUPER; - case "switch": return Token.SWITCH; - case "this": return Token.THIS; - case "throw": return Token.THROW; - case "true": return Token.TRUE; - case "try": return Token.TRY; - case "type": return Token.TYPE; - case "typeof": return Token.TYPEOF; - case "var": return Token.VAR; - case "void": return Token.VOID; - case "while": return Token.WHILE; - case "with": return Token.WITH; - case "yield": return Token.YIELD; - default: return Token.INVALID; - } -} +export namespace Token { -export function operatorTokenToString(token: Token): string { - switch (token) { - case Token.DELETE: return "delete"; - case Token.IN: return "in"; - case Token.INSTANCEOF: return "instanceof"; - case Token.NEW: return "new"; - case Token.TYPEOF: return "typeof"; - case Token.VOID: return "void"; - case Token.YIELD: return "yield"; - case Token.DOT_DOT_DOT: return "..."; - case Token.COMMA: return ","; - case Token.LESSTHAN: return "<"; - case Token.GREATERTHAN: return ">"; - case Token.LESSTHAN_EQUALS: return "<="; - case Token.GREATERTHAN_EQUALS: return ">="; - case Token.EQUALS_EQUALS: return "=="; - case Token.EXCLAMATION_EQUALS: return "!="; - case Token.EQUALS_EQUALS_EQUALS: return "==="; - case Token.EXCLAMATION_EQUALS_EQUALS: return "!=="; - case Token.PLUS: return "+"; - case Token.MINUS: return "-"; - case Token.ASTERISK_ASTERISK: return "**"; - case Token.ASTERISK: return "*"; - case Token.SLASH: return "/"; - case Token.PERCENT: return "%"; - case Token.PLUS_PLUS: return "++"; - case Token.MINUS_MINUS: return "--"; - case Token.LESSTHAN_LESSTHAN: return "<<"; - case Token.GREATERTHAN_GREATERTHAN: return ">>"; - case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>"; - case Token.AMPERSAND: return "&"; - case Token.BAR: return "|"; - case Token.CARET: return "^"; - case Token.EXCLAMATION: return "!"; - case Token.TILDE: return "~"; - case Token.AMPERSAND_AMPERSAND: return "&&"; - case Token.BAR_BAR: return "||"; - case Token.EQUALS: return "="; - case Token.PLUS_EQUALS: return "+="; - case Token.MINUS_EQUALS: return "-="; - case Token.ASTERISK_EQUALS: return "*="; - case Token.ASTERISK_ASTERISK_EQUALS: return "**="; - case Token.SLASH_EQUALS: return "/="; - case Token.PERCENT_EQUALS: return "%="; - case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<="; - case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>="; - case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>="; - case Token.AMPERSAND_EQUALS: return "&="; - case Token.BAR_EQUALS: return "|="; - case Token.CARET_EQUALS: return "^="; - default: assert(false); return ""; + export function fromKeyword(text: string): Token { + switch (text) { + case "abstract": return Token.ABSTRACT; + case "as": return Token.AS; + case "async": return Token.ASYNC; + case "await": return Token.AWAIT; + case "break": return Token.BREAK; + case "case": return Token.CASE; + case "catch": return Token.CATCH; + case "class": return Token.CLASS; + case "continue": return Token.CONTINUE; + case "const": return Token.CONST; + case "constructor": return Token.CONSTRUCTOR; + case "debugger": return Token.DEBUGGER; + case "declare": return Token.DECLARE; + case "default": return Token.DEFAULT; + case "delete": return Token.DELETE; + case "do": return Token.DO; + case "else": return Token.ELSE; + case "enum": return Token.ENUM; + case "export": return Token.EXPORT; + case "extends": return Token.EXTENDS; + case "false": return Token.FALSE; + case "finally": return Token.FINALLY; + case "for": return Token.FOR; + case "from": return Token.FROM; + case "function": return Token.FUNCTION; + case "get": return Token.GET; + case "if": return Token.IF; + case "implements": return Token.IMPLEMENTS; + case "import": return Token.IMPORT; + case "in": return Token.IN; + case "instanceof": return Token.INSTANCEOF; + case "interface": return Token.INTERFACE; + case "is": return Token.IS; + case "keyof": return Token.KEYOF; + case "let": return Token.LET; + case "module": return Token.MODULE; + case "namespace": return Token.NAMESPACE; + case "new": return Token.NEW; + case "null": return Token.NULL; + case "of": return Token.OF; + case "package": return Token.PACKAGE; + case "private": return Token.PRIVATE; + case "protected": return Token.PROTECTED; + case "public": return Token.PUBLIC; + case "readonly": return Token.READONLY; + case "return": return Token.RETURN; + case "set": return Token.SET; + case "static": return Token.STATIC; + case "super": return Token.SUPER; + case "switch": return Token.SWITCH; + case "this": return Token.THIS; + case "throw": return Token.THROW; + case "true": return Token.TRUE; + case "try": return Token.TRY; + case "type": return Token.TYPE; + case "typeof": return Token.TYPEOF; + case "var": return Token.VAR; + case "void": return Token.VOID; + case "while": return Token.WHILE; + case "with": return Token.WITH; + case "yield": return Token.YIELD; + default: return Token.INVALID; + } } -} -function isPossibleIdentifier(token: Token): bool { - switch (token) { - case Token.ABSTRACT: - case Token.AS: - case Token.CONSTRUCTOR: - case Token.DECLARE: - case Token.FROM: - case Token.GET: - case Token.IS: - case Token.KEYOF: - case Token.MODULE: - case Token.NAMESPACE: - case Token.READONLY: - case Token.SET: - case Token.TYPE: - return true; - default: - return false; + export function operatorToString(token: Token): string { + switch (token) { + case Token.DELETE: return "delete"; + case Token.IN: return "in"; + case Token.INSTANCEOF: return "instanceof"; + case Token.NEW: return "new"; + case Token.TYPEOF: return "typeof"; + case Token.VOID: return "void"; + case Token.YIELD: return "yield"; + case Token.DOT_DOT_DOT: return "..."; + case Token.COMMA: return ","; + case Token.LESSTHAN: return "<"; + case Token.GREATERTHAN: return ">"; + case Token.LESSTHAN_EQUALS: return "<="; + case Token.GREATERTHAN_EQUALS: return ">="; + case Token.EQUALS_EQUALS: return "=="; + case Token.EXCLAMATION_EQUALS: return "!="; + case Token.EQUALS_EQUALS_EQUALS: return "==="; + case Token.EXCLAMATION_EQUALS_EQUALS: return "!=="; + case Token.PLUS: return "+"; + case Token.MINUS: return "-"; + case Token.ASTERISK_ASTERISK: return "**"; + case Token.ASTERISK: return "*"; + case Token.SLASH: return "/"; + case Token.PERCENT: return "%"; + case Token.PLUS_PLUS: return "++"; + case Token.MINUS_MINUS: return "--"; + case Token.LESSTHAN_LESSTHAN: return "<<"; + case Token.GREATERTHAN_GREATERTHAN: return ">>"; + case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>"; + case Token.AMPERSAND: return "&"; + case Token.BAR: return "|"; + case Token.CARET: return "^"; + case Token.EXCLAMATION: return "!"; + case Token.TILDE: return "~"; + case Token.AMPERSAND_AMPERSAND: return "&&"; + case Token.BAR_BAR: return "||"; + case Token.EQUALS: return "="; + case Token.PLUS_EQUALS: return "+="; + case Token.MINUS_EQUALS: return "-="; + case Token.ASTERISK_EQUALS: return "*="; + case Token.ASTERISK_ASTERISK_EQUALS: return "**="; + case Token.SLASH_EQUALS: return "/="; + case Token.PERCENT_EQUALS: return "%="; + case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<="; + case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>="; + case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>="; + case Token.AMPERSAND_EQUALS: return "&="; + case Token.BAR_EQUALS: return "|="; + case Token.CARET_EQUALS: return "^="; + default: assert(false); return ""; + } + } + + export function isAlsoIdentifier(token: Token): bool { + switch (token) { + case Token.ABSTRACT: + case Token.AS: + case Token.CONSTRUCTOR: + case Token.DECLARE: + case Token.FROM: + case Token.GET: + case Token.IS: + case Token.KEYOF: + case Token.MODULE: + case Token.NAMESPACE: + case Token.READONLY: + case Token.SET: + case Token.TYPE: + return true; + default: + return false; + } } } @@ -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; } diff --git a/src/types.ts b/src/types.ts index 935b7943..c1a66ef6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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; diff --git a/src/util/path.ts b/src/util/path.ts index a19c472a..9ed82c18 100644 --- a/src/util/path.ts +++ b/src/util/path.ts @@ -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 { diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..1ccde0fd --- /dev/null +++ b/tslint.json @@ -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"] + } +}