diff --git a/bin/asc.js b/bin/asc.js index df27a44b..6f2378bc 100644 --- a/bin/asc.js +++ b/bin/asc.js @@ -7,7 +7,7 @@ var assemblyscript; var isDev = true; try { assemblyscript = require("../dist/assemblyscript.js"); - require("source-map-support").install(); + try { require("source-map-support").install(); } catch (e) {} // optional isDev = false; } catch (e) { require("ts-node").register({ project: require("path").join(__dirname, "..", "src") }); diff --git a/package.json b/package.json index 9de25cd5..5476d439 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,7 @@ "dependencies": { "binaryen": "40.0.0-nightly.20171209", "glob": "^7.1.2", - "minimist": "^1.2.0", - "source-map-support": "^0.5.0" + "minimist": "^1.2.0" }, "devDependencies": { "@types/chalk": "^2.2.0", @@ -26,6 +25,7 @@ "chalk": "^2.3.0", "diff": "^3.4.0", "long": "^3.2.0", + "source-map-support": "^0.5.0", "ts-loader": "^3.2.0", "ts-node": "^4.0.2", "tslint": "^5.8.0", @@ -42,15 +42,15 @@ }, "scripts": { "build": "webpack", - "clean": "rm dist/assemblyscript.*", + "clean": "node scripts/clean", + "lint": "tslint --project src", "test:config": "npm run test:config:assembly --scripts-prepend-node-path && npm run test:config:portable --scripts-prepend-node-path && npm run test:config:src --scripts-prepend-node-path", "test:config:assembly": "tsc --noEmit -p std/assembly --diagnostics --listFiles", "test:config:portable": "tsc --noEmit -p std/portable --diagnostics --listFiles", "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", - "lint": "tslint --project src" + "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" }, "files": [ "bin/", diff --git a/scripts/clean.js b/scripts/clean.js new file mode 100644 index 00000000..956dea95 --- /dev/null +++ b/scripts/clean.js @@ -0,0 +1,16 @@ +var fs = require("fs"); +var glob = require("glob"); + +glob("*", { cwd: __dirname + "/../dist" }, (err, matches) => { + if (err) + console.log("Failed to list files in 'dist/': " + err.message); + else + matches.forEach(match => { + fs.unlink(__dirname + "/../dist/" + match, err => { + if (err) + console.log("Failed to delete 'dist/" + match + "': " + err.message); + else + console.log("Deleted 'dist/" + match + "'"); + }); + }); +}); diff --git a/src/ast.ts b/src/ast.ts index 65ddded5..0c369463 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -2185,15 +2185,14 @@ function builderEndsWith(sb: string[], code: CharCode): bool { export function escapeString(str: string): string { var k = str.length; var ret = new Array(k); - ret.length = 0; for (var i = 0, c: string; i < k; ++i) { switch (c = str.charAt(i)) { - case "\\": ret.push("\\\\"); break; - case "\"": ret.push("\\\""); break; - case "\r": ret.push("\\r"); break; - case "\n": ret.push("\\n"); break; - case "\0": ret.push("\\0"); break; - default: ret.push(c); + case "\\": ret[i] = "\\\\"; break; + case "\"": ret[i] = "\\\""; break; + case "\r": ret[i] = "\\r"; break; + case "\n": ret[i] = "\\n"; break; + case "\0": ret[i] = "\\0"; break; + default: ret[i] = c; } } return "\"" + ret.join("") + "\""; diff --git a/src/builtins.ts b/src/builtins.ts index c118e589..8985aac5 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -689,11 +689,11 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty // other - case "changetype": // changetype(value: T1) -> T2 - if (!validateCall(compiler, typeArguments, 2, operands, 1, reportNode)) + case "changetype": // changetype(value: *) -> T + if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode)) return module.createUnreachable(); - if ((typeArguments[0] == usizeType && typeArguments[1].classType) || (typeArguments[0].classType && typeArguments[1] == usizeType)) { - arg0 = compiler.compileExpression(operands[0], typeArguments[0]); + arg0 = compiler.compileExpression(operands[0], Type.void, ConversionKind.NONE); + if ((compiler.currentType == usizeType && typeArguments[1].classType) || (compiler.currentType.classType && typeArguments[1] == usizeType)) { compiler.currentType = typeArguments[1]; return arg0; } diff --git a/src/compiler.ts b/src/compiler.ts index f54b85dd..df6e287b 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -386,7 +386,7 @@ export class Compiler extends DiagnosticEmitter { if (!global.isMutable) { initExpr = this.precomputeExpressionRef(initExpr); if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) { - this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range); + this.warning(DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable, declaration.range); initializeInStart = true; } } else @@ -461,7 +461,7 @@ export class Compiler extends DiagnosticEmitter { initExpr = this.precomputeExpressionRef(initExpr); if (_BinaryenExpressionGetId(initExpr) != ExpressionId.Const) { if (element.isConstant) - this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range); + this.warning(DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable, declaration.range); initInStart = true; } } @@ -476,7 +476,7 @@ export class Compiler extends DiagnosticEmitter { this.module.createI32(1) ); if (element.isConstant) - this.warning(DiagnosticCode.Compiling_constant_global_with_non_constant_initializer_as_mutable, declaration.range); + this.warning(DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable, declaration.range); initInStart = true; } if (initInStart) { @@ -1029,7 +1029,8 @@ export class Compiler extends DiagnosticEmitter { } this.currentFunction.locals.set(name, local); continue; - } + } else + this.warning(DiagnosticCode.Compiling_constant_with_non_constant_initializer_as_mutable, declaration.range); } else { this.error(DiagnosticCode._const_declarations_must_be_initialized, declaration.range); } diff --git a/src/diagnosticMessages.generated.ts b/src/diagnosticMessages.generated.ts index fa8388bb..3d1e7118 100644 --- a/src/diagnosticMessages.generated.ts +++ b/src/diagnosticMessages.generated.ts @@ -6,7 +6,7 @@ export enum DiagnosticCode { Operation_not_supported = 102, Operation_is_unsafe = 103, Cannot_export_a_mutable_global = 104, - Compiling_constant_global_with_non_constant_initializer_as_mutable = 105, + Compiling_constant_with_non_constant_initializer_as_mutable = 105, Type_0_cannot_be_changed_to_type_1 = 106, Unterminated_string_literal = 1002, Identifier_expected = 1003, @@ -87,7 +87,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string { case 102: return "Operation not supported."; case 103: return "Operation is unsafe."; case 104: return "Cannot export a mutable global."; - case 105: return "Compiling constant global with non-constant initializer as mutable."; + case 105: return "Compiling constant with non-constant initializer as mutable."; case 106: return "Type '{0}' cannot be changed to type '{1}'."; case 1002: return "Unterminated string literal."; case 1003: return "Identifier expected."; diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 612ce7bd..2a4444f8 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -4,7 +4,7 @@ "Operation not supported.": 102, "Operation is unsafe.": 103, "Cannot export a mutable global.": 104, - "Compiling constant global with non-constant initializer as mutable.": 105, + "Compiling constant with non-constant initializer as mutable.": 105, "Type '{0}' cannot be changed to type '{1}'.": 106, "Unterminated string literal.": 1002, diff --git a/src/module.ts b/src/module.ts index 445f8058..45381f28 100644 --- a/src/module.ts +++ b/src/module.ts @@ -264,7 +264,7 @@ export class Module { static create(): Module { var module = new Module(); module.ref = _BinaryenModuleCreate(); - module.lit = changetype(Heap.allocate(16)); + module.lit = changetype(Heap.allocate(16)); module.noEmit = false; return module; } @@ -274,18 +274,18 @@ export class Module { try { var module = new Module(); module.ref = _BinaryenModuleRead(cArr, buffer.length); - module.lit = changetype(Heap.allocate(16)); + module.lit = changetype(Heap.allocate(16)); module.noEmit = false; return module; } finally { - Heap.dispose(changetype(cArr)); + Heap.dispose(changetype(cArr)); } } static createStub(): Module { var module = new Module(); module.ref = 0; - module.lit = changetype(0); + module.lit = changetype(0); module.noEmit = true; return module; } @@ -806,7 +806,7 @@ export class Module { dispose(): void { if (!this.ref) return; // sic _BinaryenModuleDispose(this.ref); - Heap.dispose(changetype(this.lit)); + Heap.dispose(changetype(this.lit)); } createRelooper(): Relooper { diff --git a/std/assembly.d.ts b/std/assembly.d.ts index 01f618b0..a475268c 100644 --- a/std/assembly.d.ts +++ b/std/assembly.d.ts @@ -162,7 +162,7 @@ declare const HEAP_BASE: usize; /** Determines the byte size of the specified core or class type. Compiles to a constant. */ declare function sizeof(): usize; /** Changes the type of a value to another one. Useful for casting class instances to their pointer values and vice-versa. */ -declare function changetype(value: T1): T2; +declare function changetype(value: any): T; /** Tests if a 32-bit or 64-bit float is `NaN`. */ declare function isNaN(value: T): bool; /** Tests if a 32-bit or 64-bit float is finite, that is not `NaN` or +/-`Infinity`. */ diff --git a/std/assembly/array.ts b/std/assembly/array.ts index 394ec3a0..498fa8fb 100644 --- a/std/assembly/array.ts +++ b/std/assembly/array.ts @@ -18,10 +18,10 @@ export class Array { } dispose(): void { - store(changetype(this), 0); + store(changetype(this), 0); Heap.dispose(this.ptr); this.ptr = 0; - Heap.dispose(changetype(this)); + Heap.dispose(changetype(this)); } // TODO diff --git a/std/assembly/heap.ts b/std/assembly/heap.ts index e0181545..a33e4bd9 100644 --- a/std/assembly/heap.ts +++ b/std/assembly/heap.ts @@ -2,7 +2,7 @@ const ALIGN_LOG2: usize = 3; const ALIGN_SIZE: usize = 1 << ALIGN_LOG2; const ALIGN_MASK: usize = ALIGN_SIZE - 1; -let HEAP_OFFSET: usize = HEAP_BASE; // HEAP_BASE is a constant generated by the compiler +var HEAP_OFFSET: usize = HEAP_BASE; // HEAP_BASE is a constant generated by the compiler // TODO: maybe tlsf @@ -15,11 +15,11 @@ export class Heap { static allocate(size: usize): usize { if (!size) return 0; - const len: i32 = current_memory(); + var len: i32 = current_memory(); if (HEAP_OFFSET + size > len << 16) if(grow_memory(max(ceil(size / 65536), len * 2 - len)) < 0) unreachable(); - const ptr: usize = HEAP_OFFSET; + var ptr: usize = HEAP_OFFSET; if ((HEAP_OFFSET += size) & ALIGN_MASK) // align next offset HEAP_OFFSET = (HEAP_OFFSET | ALIGN_MASK) + 1; return ptr; @@ -33,8 +33,8 @@ export class Heap { assert(dest >= HEAP_BASE); // the following is based on musl's implementation of memcpy - let dst: usize = dest; - let w: u32, x: u32; + var dst: usize = dest; + var w: u32, x: u32; // copy 1 byte each until src is aligned to 4 bytes while (n && src % 4) { @@ -180,7 +180,7 @@ export class Heap { // the following is based on musl's implementation of memset if (!n) return dest; - let s: usize = dest; + var s: usize = dest; // Fill head and tail with minimal branching store(s, c); store(s + n - 1, c); @@ -192,12 +192,12 @@ export class Heap { if (n <= 8) return dest; // Align to 4 bytes - let k: usize = -s & 3; + var k: usize = -s & 3; s += k; n -= k; n &= -4; - let c32: u32 = -1 / 255 * c; + var c32: u32 = -1 / 255 * c; // Fill head and tail in preparation of setting 32 bytes at a time store(s, c32); @@ -223,7 +223,7 @@ export class Heap { n -= k; // Set 32 bytes at a time - let c64: u64 = c32 | (c32 << 32); + var c64: u64 = c32 | (c32 << 32); while (n >= 32) { store(s, c64); store(s + 8, c64); diff --git a/std/assembly/string.ts b/std/assembly/string.ts index 734220c8..ec546071 100644 --- a/std/assembly/string.ts +++ b/std/assembly/string.ts @@ -1,4 +1,4 @@ -const EMPTY: String = changetype(""); +const EMPTY: String = changetype(""); @global() export class String { @@ -29,10 +29,10 @@ export class String { assert(this != null); if (pos < 0 || pos >= this.length) return -1; // undefined - let first: i32 = load(this.ptr + (pos << 1)); + var first = load(this.ptr + (pos << 1)); if (first < 0xD800 || first > 0xDBFF || pos + 1 == this.length) return first; - let second: i32 = load(this.ptr + ((pos + 1) << 1)); + var second = load(this.ptr + ((pos + 1) << 1)); if (second < 0xDC00 || second > 0xDFFF) return first; return ((first - 0xD800) << 10) + (second - 0xDC00) + 0x10000; @@ -42,9 +42,9 @@ export class String { concat(other: String): String { assert(this != null); assert(other != null); - const thisLen: isize = this.length; - const otherLen: isize = other.length; - const len: usize = thisLen + otherLen; + var thisLen: isize = this.length; + var otherLen: isize = other.length; + var len: usize = thisLen + otherLen; return new String( Heap.copy( Heap.copy( @@ -62,9 +62,9 @@ export class String { endsWith(searchString: String, endPosition: i32 = 0x7fffffff): bool { assert(this != null); assert(searchString != null); - let end: isize = min(max(endPosition, 0), this.length); - let searchLength: isize = searchString.length; - let start: isize = end - searchLength; + var end: isize = min(max(endPosition, 0), this.length); + var searchLength: isize = searchString.length; + var start: isize = end - searchLength; if (start < 0) return false; return !Heap.compare(this.ptr + (start << 1), searchString.ptr, searchLength << 1); @@ -85,11 +85,11 @@ export class String { indexOf(searchString: String, position: i32 = 0): i32 { assert(this != null); assert(searchString != null); - let pos: isize = position; - let len: isize = this.length; - let start: isize = min(max(pos, 0), len); - let searchLen: isize = searchString.length; - for (let k: usize = start; k + searchLen <= len; ++k) + var pos: isize = position; + var len: isize = this.length; + var start: isize = min(max(pos, 0), len); + var searchLen: isize = searchString.length; + for (var k: usize = start; k + searchLen <= len; ++k) if (!Heap.compare(this.ptr + (k << 1), searchString.ptr, searchLen << 1)) return k; return -1; @@ -98,10 +98,10 @@ export class String { startsWith(searchString: String, position: i32 = 0): bool { assert(this != null); assert(searchString != null); - let pos: isize = position; - let len: isize = this.length; - let start: isize = min(max(position, 0), len); - let searchLength: isize = searchString.length; + var pos: isize = position; + var len: isize = this.length; + var start: isize = min(max(position, 0), len); + var searchLength: isize = searchString.length; if (searchLength + start > len) return false; return !Heap.compare(this.ptr + (start << 1), searchString.ptr, searchLength << 1); @@ -109,12 +109,12 @@ export class String { substr(start: i32, length: i32 = i32.MAX_VALUE): String { assert(this != null); - let intStart: isize = start; - let end: isize = length; - let size: isize = this.length; + var intStart: isize = start; + var end: isize = length; + var size: isize = this.length; if (intStart < 0) intStart = max(size + intStart, 0); - let resultLength: isize = min(max(end, 0), size - intStart); + var resultLength: isize = min(max(end, 0), size - intStart); if (resultLength < 0) return EMPTY; return new String(this.ptr + (intStart << 1), resultLength); @@ -122,11 +122,11 @@ export class String { substring(start: i32, end: i32 = i32.MAX_VALUE): String { assert(this != null); - let len: i32 = this.length; - let finalStart: i32 = min(max(start, 0), len); - let finalEnd: i32 = min(max(end, 0), len); - let from: i32 = min(finalStart, finalEnd); - let to: i32 = max(finalStart, finalEnd); + var len = this.length; + var finalStart = min(max(start, 0), len); + var finalEnd = min(max(end, 0), len); + var from = min(finalStart, finalEnd); + var to = max(finalStart, finalEnd); len = to - from; if (!len) return EMPTY; @@ -137,10 +137,10 @@ export class String { trim(): String { assert(this != null); - let length: usize = this.length; + var length: usize = this.length; while (length && isWhiteSpaceOrLineTerminator(load(this.ptr + (length << 1)))) --length; - let start: usize = 0; + var start: usize = 0; while (start < length && isWhiteSpaceOrLineTerminator(load(this.ptr + (start << 1)))) { ++start; --length; } @@ -153,8 +153,8 @@ export class String { trimLeft(): String { assert(this != null); - let start: isize = 0; - let len: isize = this.length; + var start: isize = 0; + var len: isize = this.length; while (start < len && isWhiteSpaceOrLineTerminator(load(this.ptr + (start << 1)))) ++start; if (!start) @@ -164,7 +164,7 @@ export class String { trimRight(): String { assert(this != null); - let len: isize = this.length; + var len: isize = this.length; while (len > 0 && isWhiteSpaceOrLineTerminator(load(this.ptr + (len << 1)))) --len; if (len <= 0) diff --git a/std/portable.d.ts b/std/portable.d.ts index e7b20cd6..3f03257c 100644 --- a/std/portable.d.ts +++ b/std/portable.d.ts @@ -116,7 +116,7 @@ declare function store(offset: usize, value: T): void; declare function unreachable(): any; // sic /** Changes the type of a value to another one. Useful for casting class instances to their pointer values and vice-versa. */ -declare function changetype(value: T1): T2; +declare function changetype(value: any): T; /** Traps if the specified value evaluates to `false`. */ declare function assert(isTrue: bool, message?: string): void; /** Parses an integer string to a 64-bit float. */