Parser fixes; Lib updates

This commit is contained in:
dcodeIO 2018-01-29 22:36:07 +01:00
parent 74498852f0
commit 1995bf9eb4
18 changed files with 282 additions and 103 deletions

View File

@ -13,5 +13,5 @@ var myModule = ...;
var helpers = utils(myModule); var helpers = utils(myModule);
var str = helpers.getString(myModule.exportReturningAString()); var str = helpers.string(myModule.exportReturningAString());
``` ```

View File

@ -1,21 +1,103 @@
module.exports = function(module) { function utils(module) {
return {
getI32: function(ptr) { var i8,
return new Int32Array(module.memory.buffer, ptr, 4)[0]; u8 = new Uint8Array(0),
}, i16,
getU32: function(ptr) { u16,
return new Uint32Array(module.memory.buffer, ptr, 4)[0]; i32,
}, u32,
getF32: function(ptr) { f32,
return new Float32Array(module.memory.buffer, ptr, 4)[0]; f64;
},
getF64: function(ptr) { function maybeUpdate() {
return new Float64Array(module.memory.buffer, ptr, 8)[0]; var mem = module.memory.buffer;
}, if (mem.byteLength === u8.length)
getString: function(ptr) { return;
var len = new Uint32Array(module.memory.buffer, ptr, 4)[0]; i8 = Int8Array(mem);
var str = new Uint16Array(module.memory.buffer, ptr + 4, len << 1); u8 = Uint8Array(mem);
return String.fromCharCode.apply(String, str); i16 = Int16Array(mem);
} u16 = Uint16Array(mem);
i32 = Int32Array(mem);
u32 = Uint32Array(mem);
f32 = Float32Array(mem);
f64 = Float64Array(mem);
} }
var helpers = {
i8: function(ptr) {
maybeUpdate();
return i8[ptr];
},
u8: function(ptr) {
maybeUpdate();
return u8[ptr];
},
i16: function(ptr) {
maybeUpdate();
return i16[ptr >>> 1];
},
u16: function(ptr) {
maybeUpdate();
return u16[ptr >>> 1];
},
i32: function(ptr) {
maybeUpdate();
return i32[ptr >>> 2];
},
u32: function(ptr) {
maybeUpdate();
return u32[ptr >>> 2];
},
i64: function(ptr) {
maybeUpdate();
return {
low: i32[ptr >>> 2],
high: i32[(ptr >>> 2) + 1]
};
},
u64: function(ptr) {
maybeUpdate();
return {
low: u32[ptr >>> 2],
high: u32[(ptr >>> 2) + 1]
};
},
bool: function(ptr) {
maybeUpdate();
return u8[ptr] === 1;
},
f32: function(ptr) {
maybeUpdate();
return f32[ptr >>> 2];
},
f64: function(ptr) {
maybeUpdate();
return f64[ptr >>> 3];
},
string: function(ptr) {
maybeUpdate();
var len = u32[ptr >>> 2];
var off = (ptr >>> 1) + 2;
return String.fromCharCode.apply(String, u16.subarray(off, off + len));
}
};
return helpers;
}; };
Object.defineProperties(module.exports = utils, {
__esModule: { value: true },
default: { value: utils }
});

View File

@ -11,3 +11,5 @@ import Module from "@assemblyscript/webpack!module.wasm";
var myModule = Module({ imports: { ... }}); var myModule = Module({ imports: { ... }});
``` ```
TODO: Wire .ts files to the compiler API, accepting options, but also keep raw .wasm support.

View File

@ -7,23 +7,23 @@ module.exports = function(string) {
// determine buffer length // determine buffer length
var length = string.length; var length = string.length;
if (length) { if (length) {
var n = 0; var n = 0, p = length;
while (--length % 4 > 1 && string.charCodeAt(p) === 61) ++n; while (--p % 4 > 1 && string.charCodeAt(p) === 61) ++n;
length = Math.ceil(string.length * 3) / 4 - n; length = Math.ceil(length * 3) / 4 - n;
} }
// decode to buffer // decode to buffer
var buffer = new Uint8Array(length); var buffer = new Uint8Array(length);
var j = 0, t; var j = 0, o = 0, t;
for (var i = 0, k = string.length; i < k;) { for (var i = 0, k = string.length; i < k;) {
var c = string.charCodeAt(i++); var c = string.charCodeAt(i++);
if (c === 61 && j > 1) break; if (c === 61 && j > 1) break;
if ((c = s64[c]) === undefined) throw Error(); if ((c = s64[c]) === undefined) throw Error();
switch (j) { switch (j) {
case 0: t = c; j = 1; break; case 0: t = c; j = 1; break;
case 1: buffer[offset++] = t << 2 | (c & 48) >> 4; t = c; j = 2; break; case 1: buffer[o++] = t << 2 | (c & 48) >> 4; t = c; j = 2; break;
case 2: buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2; t = c; j = 3; break; case 2: buffer[o++] = (t & 15) << 4 | (c & 60) >> 2; t = c; j = 3; break;
case 3: buffer[offset++] = (t & 3) << 6 | c; j = 0; break; case 3: buffer[o++] = (t & 3) << 6 | c; j = 0; break;
} }
} }
if (j === 1) throw Error(); if (j === 1) throw Error();

View File

@ -1,6 +1,6 @@
var base64 = require("@protobufjs/base64"); var base64 = require("@protobufjs/base64");
(module.exports = function(buffer) { function loader(buffer) {
var data = base64.encode(buffer, 0, buffer.length); var data = base64.encode(buffer, 0, buffer.length);
var code = [ var code = [
'var data = "' + data + '", wasm;', 'var data = "' + data + '", wasm;',
@ -9,5 +9,12 @@ var base64 = require("@protobufjs/base64");
' return new WebAssembly.Instance(new WebAssembly.Module(wasm), options && options.imports || {}).exports;', ' return new WebAssembly.Instance(new WebAssembly.Module(wasm), options && options.imports || {}).exports;',
'};' '};'
]; ];
return code.join("\n"); return code.join("\n") + "\n";
}).raw = true; }
loader.raw = true;
Object.defineProperties(module.exports = loader, {
__esModule: { value: true },
default: { value: loader }
});

View File

@ -36,6 +36,7 @@ import {
Expression, Expression,
AssertionKind, AssertionKind,
CallExpression, CallExpression,
ElementAccessExpression,
IdentifierExpression, IdentifierExpression,
StringLiteralExpression, StringLiteralExpression,
@ -1467,7 +1468,7 @@ export class Parser extends DiagnosticEmitter {
var elementExpressions = new Array<Expression | null>(); var elementExpressions = new Array<Expression | null>();
if (!tn.skip(Token.CLOSEBRACKET)) { if (!tn.skip(Token.CLOSEBRACKET)) {
do { do {
if (tn.peek() == Token.COMMA || tn.peek() == Token.CLOSEBRACKET) if (tn.peek() == Token.COMMA)
expr = null; // omitted expr = null; // omitted
else { else {
expr = this.parseExpression(tn, Precedence.COMMA + 1); expr = this.parseExpression(tn, Precedence.COMMA + 1);
@ -1475,6 +1476,8 @@ export class Parser extends DiagnosticEmitter {
return null; return null;
} }
elementExpressions.push(expr); elementExpressions.push(expr);
if (tn.peek() == Token.CLOSEBRACKET)
break;
} while (tn.skip(Token.COMMA)); } while (tn.skip(Token.COMMA));
if (!tn.skip(Token.CLOSEBRACKET)) { if (!tn.skip(Token.CLOSEBRACKET)) {
this.error(DiagnosticCode._0_expected, tn.range(), "]"); this.error(DiagnosticCode._0_expected, tn.range(), "]");
@ -1588,19 +1591,6 @@ export class Parser extends DiagnosticEmitter {
var startPos = expr.range.start; var startPos = expr.range.start;
// ElementAccessExpression
if (tn.skip(Token.OPENBRACKET)) {
next = this.parseExpression(tn); // resets precedence
if (!next)
return null;
if (tn.skip(Token.CLOSEBRACKET))
expr = Node.createElementAccessExpression(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
else {
this.error(DiagnosticCode._0_expected, tn.range(), "]");
return null;
}
}
// CallExpression // CallExpression
var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn); // skips '(' on success var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn); // skips '(' on success
// there might be better ways to distinguish a LESSTHAN from a CALL with type arguments // there might be better ways to distinguish a LESSTHAN from a CALL with type arguments
@ -1617,70 +1607,93 @@ export class Parser extends DiagnosticEmitter {
while ((nextPrecedence = determinePrecedence(token = tn.peek())) >= precedence) { // precedence climbing while ((nextPrecedence = determinePrecedence(token = tn.peek())) >= precedence) { // precedence climbing
tn.next(); tn.next();
// AssertionExpression switch (token) {
if (token == Token.AS) {
var toType = this.parseType(tn);
if (!toType)
return null;
expr = Node.createAssertionExpression(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos));
// UnaryPostfixExpression // AssertionExpression
} else if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS) { case Token.AS:
if (expr.kind != NodeKind.IDENTIFIER && expr.kind != NodeKind.ELEMENTACCESS && expr.kind != NodeKind.PROPERTYACCESS) var toType = this.parseType(tn);
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, expr.range); if (!toType)
expr = Node.createUnaryPostfixExpression(token, expr, tn.range(startPos, tn.pos));
// TernaryExpression
} else if (token == Token.QUESTION) {
var ifThen = this.parseExpression(tn);
if (!ifThen)
return null;
if (tn.skip(Token.COLON)) {
var ifElse = this.parseExpression(tn);
if (!ifElse)
return null; return null;
expr = Node.createTernaryExpression(<Expression>expr, <Expression>ifThen, <Expression>ifElse, tn.range(startPos, tn.pos)); expr = Node.createAssertionExpression(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos));
} else { break;
this.error(DiagnosticCode._0_expected, tn.range(), ":");
return null;
}
// CommaExpression // ElementAccessExpression
} else if (token == Token.COMMA) { case Token.OPENBRACKET:
var commaExprs = new Array<Expression>(1); next = this.parseExpression(tn);
commaExprs[0] = <Expression>expr; if (!next)
do {
expr = this.parseExpression(tn, Precedence.COMMA + 1);
if (!expr)
return null; return null;
commaExprs.push(expr); if (!tn.skip(Token.CLOSEBRACKET)) {
} while (tn.skip(Token.COMMA)); this.error(DiagnosticCode._0_expected, tn.range(), "]");
expr = Node.createCommaExpression(commaExprs, tn.range(startPos, tn.pos));
} else {
next = this.parseExpression(tn, isRightAssociative(token) ? nextPrecedence : 1 + nextPrecedence);
if (!next)
return null;
// PropertyAccessExpression
if (token == Token.DOT) {
if (next.kind == NodeKind.IDENTIFIER) {
expr = Node.createPropertyAccessExpression(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
} else if (next.kind == NodeKind.CALL) { // amend
var propertyCall = <CallExpression>next;
if (propertyCall.expression.kind == NodeKind.IDENTIFIER) {
propertyCall.expression = Node.createPropertyAccessExpression(<Expression>expr, <IdentifierExpression>propertyCall.expression, tn.range(startPos, tn.pos));
} else
throw new Error("unexpected expression kind");
expr = propertyCall;
} else {
this.error(DiagnosticCode.Identifier_expected, next.range);
return null; return null;
} }
expr = Node.createElementAccessExpression(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
break;
// BinaryExpression // UnaryPostfixExpression
} else case Token.PLUS_PLUS:
expr = Node.createBinaryExpression(token, <Expression>expr, <Expression>next, tn.range(startPos, tn.pos)); case Token.MINUS_MINUS:
if (expr.kind != NodeKind.IDENTIFIER && expr.kind != NodeKind.ELEMENTACCESS && expr.kind != NodeKind.PROPERTYACCESS)
this.error(DiagnosticCode.The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access, expr.range);
expr = Node.createUnaryPostfixExpression(token, expr, tn.range(startPos, tn.pos));
break;
// TernaryExpression
case Token.QUESTION:
var ifThen = this.parseExpression(tn);
if (!ifThen)
return null;
if (tn.skip(Token.COLON)) {
var ifElse = this.parseExpression(tn);
if (!ifElse)
return null;
expr = Node.createTernaryExpression(<Expression>expr, <Expression>ifThen, <Expression>ifElse, tn.range(startPos, tn.pos));
} else {
this.error(DiagnosticCode._0_expected, tn.range(), ":");
return null;
}
break;
// CommaExpression
case Token.COMMA:
var commaExprs = new Array<Expression>(1);
commaExprs[0] = <Expression>expr;
do {
expr = this.parseExpression(tn, Precedence.COMMA + 1);
if (!expr)
return null;
commaExprs.push(expr);
} while (tn.skip(Token.COMMA));
expr = Node.createCommaExpression(commaExprs, tn.range(startPos, tn.pos));
break;
default:
next = this.parseExpression(tn, isRightAssociative(token) ? nextPrecedence : 1 + nextPrecedence);
if (!next)
return null;
// PropertyAccessExpression
if (token == Token.DOT) {
if (next.kind == NodeKind.IDENTIFIER)
expr = Node.createPropertyAccessExpression(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
else if (next.kind == NodeKind.CALL) { // join
var propertyCall = <CallExpression>next;
if (propertyCall.expression.kind == NodeKind.IDENTIFIER) {
propertyCall.expression = Node.createPropertyAccessExpression(<Expression>expr, <IdentifierExpression>propertyCall.expression, tn.range(startPos, tn.pos));
} else {
this.error(DiagnosticCode.Identifier_expected, propertyCall.expression.range);
return null;
}
expr = propertyCall;
} else {
this.error(DiagnosticCode.Identifier_expected, next.range);
return null;
}
// BinaryExpression
} else
expr = Node.createBinaryExpression(token, <Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
break;
} }
} }
return expr; return expr;
@ -1820,6 +1833,7 @@ function determinePrecedence(kind: Token): i32 {
case Token.DOT: case Token.DOT:
case Token.NEW: case Token.NEW:
case Token.OPENBRACKET:
return Precedence.MEMBERACCESS; return Precedence.MEMBERACCESS;
default: default:

View File

@ -33,10 +33,12 @@ import {
DecoratorKind, DecoratorKind,
Expression, Expression,
AssertionExpression,
ElementAccessExpression, ElementAccessExpression,
IdentifierExpression, IdentifierExpression,
LiteralExpression, LiteralExpression,
LiteralKind, LiteralKind,
ParenthesizedExpression,
PropertyAccessExpression, PropertyAccessExpression,
StringLiteralExpression, StringLiteralExpression,
SuperExpression, SuperExpression,
@ -66,7 +68,8 @@ import {
hasDecorator, hasDecorator,
hasModifier, hasModifier,
mangleInternalName, mangleInternalName,
getFirstDecorator getFirstDecorator,
BinaryExpression
} from "./ast"; } from "./ast";
import { import {
@ -1156,8 +1159,22 @@ export class Program extends DiagnosticEmitter {
resolveExpression(expression: Expression, contextualFunction: Function): ResolvedElement | null { resolveExpression(expression: Expression, contextualFunction: Function): ResolvedElement | null {
var classType: Class | null; var classType: Class | null;
while (expression.kind == NodeKind.PARENTHESIZED)
expression = (<ParenthesizedExpression>expression).expression;
switch (expression.kind) { switch (expression.kind) {
case NodeKind.ASSERTION:
var type = this.resolveType((<AssertionExpression>expression).toType); // reports
if (type && (classType = type.classType))
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(classType);
return null;
case NodeKind.BINARY:
// TODO: string concatenation, mostly
throw new Error("not implemented");
case NodeKind.THIS: // -> Class case NodeKind.THIS: // -> Class
if (classType = contextualFunction.instanceMethodOf) if (classType = contextualFunction.instanceMethodOf)
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(classType); return (resolvedElement || (resolvedElement = new ResolvedElement())).set(classType);

4
std/assembly/iterator.ts Normal file
View File

@ -0,0 +1,4 @@
// export abstract class Iterator<T> {
// abstract get done(): bool;
// abstract next(): T;
// }

View File

@ -1,3 +1,37 @@
export class Map<K,V> { export class Map<K,V> {
// TODO
private __keys: K[] = [];
private __values: V[] = [];
// FIXME: not a proper map implementation, just a filler
get size(): i32 {
return this.__keys.length;
}
get(key: K): V | null {
var keys = this.__keys;
for (var i = 0, k = keys.length; i < k; ++i)
if (keys[i] == key)
return this.__values[i];
return null;
}
has(key: K): bool {
var keys = this.__keys;
for (var i = 0, k = keys.length; i < k; ++i)
if (keys[i] == key)
return true;
return false;
}
set(key: K, value: V): void {
this.__keys.push(key);
this.__values.push(value);
}
clear(): void {
this.__keys.length = 0;
this.__values.length = 0;
}
} }

View File

@ -66,3 +66,14 @@ export class Set<T> {
// TODO: think about iterators // TODO: think about iterators
} }
// class SetIterator<T> extends Iterator<T> {
// get done(): bool {
// throw new Error("not implemented");
// }
// next(): T {
// throw new Error("not implemented");
// }
// }

View File

@ -4052,6 +4052,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
PROPERTY: std:map/Map#size
CLASS_PROTOTYPE: Map CLASS_PROTOTYPE: Map
FUNCTION_PROTOTYPE: std:memory/copy_memory FUNCTION_PROTOTYPE: std:memory/copy_memory
FUNCTION_PROTOTYPE: std:memory/move_memory FUNCTION_PROTOTYPE: std:memory/move_memory

View File

@ -259,6 +259,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
PROPERTY: std:map/Map#size
CLASS_PROTOTYPE: Map CLASS_PROTOTYPE: Map
FUNCTION_PROTOTYPE: std:memory/copy_memory FUNCTION_PROTOTYPE: std:memory/copy_memory
FUNCTION_PROTOTYPE: std:memory/move_memory FUNCTION_PROTOTYPE: std:memory/move_memory

View File

@ -2868,6 +2868,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
PROPERTY: std:map/Map#size
CLASS_PROTOTYPE: Map CLASS_PROTOTYPE: Map
FUNCTION_PROTOTYPE: std:memory/copy_memory FUNCTION_PROTOTYPE: std:memory/copy_memory
FUNCTION_PROTOTYPE: std:memory/move_memory FUNCTION_PROTOTYPE: std:memory/move_memory

View File

@ -209,6 +209,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
PROPERTY: std:map/Map#size
CLASS_PROTOTYPE: Map CLASS_PROTOTYPE: Map
FUNCTION_PROTOTYPE: std:memory/copy_memory FUNCTION_PROTOTYPE: std:memory/copy_memory
FUNCTION_PROTOTYPE: std:memory/move_memory FUNCTION_PROTOTYPE: std:memory/move_memory

View File

@ -2777,6 +2777,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
PROPERTY: std:map/Map#size
CLASS_PROTOTYPE: Map CLASS_PROTOTYPE: Map
FUNCTION_PROTOTYPE: std:memory/copy_memory FUNCTION_PROTOTYPE: std:memory/copy_memory
FUNCTION_PROTOTYPE: std:memory/move_memory FUNCTION_PROTOTYPE: std:memory/move_memory

View File

@ -1504,6 +1504,7 @@
CLASS_PROTOTYPE: std:error/RangeError CLASS_PROTOTYPE: std:error/RangeError
CLASS_PROTOTYPE: RangeError CLASS_PROTOTYPE: RangeError
CLASS_PROTOTYPE: std:map/Map CLASS_PROTOTYPE: std:map/Map
PROPERTY: std:map/Map#size
CLASS_PROTOTYPE: Map CLASS_PROTOTYPE: Map
FUNCTION_PROTOTYPE: std:memory/copy_memory FUNCTION_PROTOTYPE: std:memory/copy_memory
FUNCTION_PROTOTYPE: std:memory/move_memory FUNCTION_PROTOTYPE: std:memory/move_memory

View File

@ -0,0 +1 @@
(((this).values[0].prop1.prop2.another[1]).prop)[2];

View File

@ -0,0 +1 @@
(((this).values[0].prop1.prop2.another[1]).prop)[2];