mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 15:12:12 +00:00
Parser fixes; Lib updates
This commit is contained in:
parent
74498852f0
commit
1995bf9eb4
@ -13,5 +13,5 @@ var myModule = ...;
|
||||
|
||||
var helpers = utils(myModule);
|
||||
|
||||
var str = helpers.getString(myModule.exportReturningAString());
|
||||
var str = helpers.string(myModule.exportReturningAString());
|
||||
```
|
||||
|
@ -1,21 +1,103 @@
|
||||
module.exports = function(module) {
|
||||
return {
|
||||
getI32: function(ptr) {
|
||||
return new Int32Array(module.memory.buffer, ptr, 4)[0];
|
||||
},
|
||||
getU32: function(ptr) {
|
||||
return new Uint32Array(module.memory.buffer, ptr, 4)[0];
|
||||
},
|
||||
getF32: function(ptr) {
|
||||
return new Float32Array(module.memory.buffer, ptr, 4)[0];
|
||||
},
|
||||
getF64: function(ptr) {
|
||||
return new Float64Array(module.memory.buffer, ptr, 8)[0];
|
||||
},
|
||||
getString: function(ptr) {
|
||||
var len = new Uint32Array(module.memory.buffer, ptr, 4)[0];
|
||||
var str = new Uint16Array(module.memory.buffer, ptr + 4, len << 1);
|
||||
return String.fromCharCode.apply(String, str);
|
||||
function utils(module) {
|
||||
|
||||
var i8,
|
||||
u8 = new Uint8Array(0),
|
||||
i16,
|
||||
u16,
|
||||
i32,
|
||||
u32,
|
||||
f32,
|
||||
f64;
|
||||
|
||||
function maybeUpdate() {
|
||||
var mem = module.memory.buffer;
|
||||
if (mem.byteLength === u8.length)
|
||||
return;
|
||||
i8 = Int8Array(mem);
|
||||
u8 = Uint8Array(mem);
|
||||
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 }
|
||||
});
|
||||
|
@ -11,3 +11,5 @@ import Module from "@assemblyscript/webpack!module.wasm";
|
||||
|
||||
var myModule = Module({ imports: { ... }});
|
||||
```
|
||||
|
||||
TODO: Wire .ts files to the compiler API, accepting options, but also keep raw .wasm support.
|
||||
|
@ -7,23 +7,23 @@ module.exports = function(string) {
|
||||
// determine buffer length
|
||||
var length = string.length;
|
||||
if (length) {
|
||||
var n = 0;
|
||||
while (--length % 4 > 1 && string.charCodeAt(p) === 61) ++n;
|
||||
length = Math.ceil(string.length * 3) / 4 - n;
|
||||
var n = 0, p = length;
|
||||
while (--p % 4 > 1 && string.charCodeAt(p) === 61) ++n;
|
||||
length = Math.ceil(length * 3) / 4 - n;
|
||||
}
|
||||
|
||||
// decode to buffer
|
||||
var buffer = new Uint8Array(length);
|
||||
var j = 0, t;
|
||||
var j = 0, o = 0, t;
|
||||
for (var i = 0, k = string.length; i < k;) {
|
||||
var c = string.charCodeAt(i++);
|
||||
if (c === 61 && j > 1) break;
|
||||
if ((c = s64[c]) === undefined) throw Error();
|
||||
switch (j) {
|
||||
case 0: t = c; j = 1; break;
|
||||
case 1: buffer[offset++] = 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 3: buffer[offset++] = (t & 3) << 6 | c; j = 0; break;
|
||||
case 1: buffer[o++] = t << 2 | (c & 48) >> 4; t = c; j = 2; break;
|
||||
case 2: buffer[o++] = (t & 15) << 4 | (c & 60) >> 2; t = c; j = 3; break;
|
||||
case 3: buffer[o++] = (t & 3) << 6 | c; j = 0; break;
|
||||
}
|
||||
}
|
||||
if (j === 1) throw Error();
|
||||
|
@ -1,6 +1,6 @@
|
||||
var base64 = require("@protobufjs/base64");
|
||||
|
||||
(module.exports = function(buffer) {
|
||||
function loader(buffer) {
|
||||
var data = base64.encode(buffer, 0, buffer.length);
|
||||
var code = [
|
||||
'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 code.join("\n");
|
||||
}).raw = true;
|
||||
return code.join("\n") + "\n";
|
||||
}
|
||||
|
||||
loader.raw = true;
|
||||
|
||||
Object.defineProperties(module.exports = loader, {
|
||||
__esModule: { value: true },
|
||||
default: { value: loader }
|
||||
});
|
||||
|
@ -36,6 +36,7 @@ import {
|
||||
Expression,
|
||||
AssertionKind,
|
||||
CallExpression,
|
||||
ElementAccessExpression,
|
||||
IdentifierExpression,
|
||||
StringLiteralExpression,
|
||||
|
||||
@ -1467,7 +1468,7 @@ export class Parser extends DiagnosticEmitter {
|
||||
var elementExpressions = new Array<Expression | null>();
|
||||
if (!tn.skip(Token.CLOSEBRACKET)) {
|
||||
do {
|
||||
if (tn.peek() == Token.COMMA || tn.peek() == Token.CLOSEBRACKET)
|
||||
if (tn.peek() == Token.COMMA)
|
||||
expr = null; // omitted
|
||||
else {
|
||||
expr = this.parseExpression(tn, Precedence.COMMA + 1);
|
||||
@ -1475,6 +1476,8 @@ export class Parser extends DiagnosticEmitter {
|
||||
return null;
|
||||
}
|
||||
elementExpressions.push(expr);
|
||||
if (tn.peek() == Token.CLOSEBRACKET)
|
||||
break;
|
||||
} while (tn.skip(Token.COMMA));
|
||||
if (!tn.skip(Token.CLOSEBRACKET)) {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), "]");
|
||||
@ -1588,19 +1591,6 @@ export class Parser extends DiagnosticEmitter {
|
||||
|
||||
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
|
||||
var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn); // skips '(' on success
|
||||
// there might be better ways to distinguish a LESSTHAN from a CALL with type arguments
|
||||
@ -1617,21 +1607,38 @@ export class Parser extends DiagnosticEmitter {
|
||||
while ((nextPrecedence = determinePrecedence(token = tn.peek())) >= precedence) { // precedence climbing
|
||||
tn.next();
|
||||
|
||||
switch (token) {
|
||||
|
||||
// AssertionExpression
|
||||
if (token == Token.AS) {
|
||||
case Token.AS:
|
||||
var toType = this.parseType(tn);
|
||||
if (!toType)
|
||||
return null;
|
||||
expr = Node.createAssertionExpression(AssertionKind.AS, expr, toType, tn.range(startPos, tn.pos));
|
||||
break;
|
||||
|
||||
// ElementAccessExpression
|
||||
case Token.OPENBRACKET:
|
||||
next = this.parseExpression(tn);
|
||||
if (!next)
|
||||
return null;
|
||||
if (!tn.skip(Token.CLOSEBRACKET)) {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), "]");
|
||||
return null;
|
||||
}
|
||||
expr = Node.createElementAccessExpression(<Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
|
||||
break;
|
||||
|
||||
// UnaryPostfixExpression
|
||||
} else if (token == Token.PLUS_PLUS || token == Token.MINUS_MINUS) {
|
||||
case Token.PLUS_PLUS:
|
||||
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
|
||||
} else if (token == Token.QUESTION) {
|
||||
case Token.QUESTION:
|
||||
var ifThen = this.parseExpression(tn);
|
||||
if (!ifThen)
|
||||
return null;
|
||||
@ -1644,9 +1651,10 @@ export class Parser extends DiagnosticEmitter {
|
||||
this.error(DiagnosticCode._0_expected, tn.range(), ":");
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
|
||||
// CommaExpression
|
||||
} else if (token == Token.COMMA) {
|
||||
case Token.COMMA:
|
||||
var commaExprs = new Array<Expression>(1);
|
||||
commaExprs[0] = <Expression>expr;
|
||||
do {
|
||||
@ -1656,22 +1664,25 @@ export class Parser extends DiagnosticEmitter {
|
||||
commaExprs.push(expr);
|
||||
} while (tn.skip(Token.COMMA));
|
||||
expr = Node.createCommaExpression(commaExprs, tn.range(startPos, tn.pos));
|
||||
break;
|
||||
|
||||
} else {
|
||||
default:
|
||||
next = this.parseExpression(tn, isRightAssociative(token) ? nextPrecedence : 1 + nextPrecedence);
|
||||
if (!next)
|
||||
return null;
|
||||
|
||||
// PropertyAccessExpression
|
||||
if (token == Token.DOT) {
|
||||
if (next.kind == NodeKind.IDENTIFIER) {
|
||||
if (next.kind == NodeKind.IDENTIFIER)
|
||||
expr = Node.createPropertyAccessExpression(<Expression>expr, <IdentifierExpression>next, tn.range(startPos, tn.pos));
|
||||
} else if (next.kind == NodeKind.CALL) { // amend
|
||||
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
|
||||
throw new Error("unexpected expression kind");
|
||||
} else {
|
||||
this.error(DiagnosticCode.Identifier_expected, propertyCall.expression.range);
|
||||
return null;
|
||||
}
|
||||
expr = propertyCall;
|
||||
} else {
|
||||
this.error(DiagnosticCode.Identifier_expected, next.range);
|
||||
@ -1681,6 +1692,8 @@ export class Parser extends DiagnosticEmitter {
|
||||
// BinaryExpression
|
||||
} else
|
||||
expr = Node.createBinaryExpression(token, <Expression>expr, <Expression>next, tn.range(startPos, tn.pos));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
@ -1820,6 +1833,7 @@ function determinePrecedence(kind: Token): i32 {
|
||||
|
||||
case Token.DOT:
|
||||
case Token.NEW:
|
||||
case Token.OPENBRACKET:
|
||||
return Precedence.MEMBERACCESS;
|
||||
|
||||
default:
|
||||
|
@ -33,10 +33,12 @@ import {
|
||||
DecoratorKind,
|
||||
|
||||
Expression,
|
||||
AssertionExpression,
|
||||
ElementAccessExpression,
|
||||
IdentifierExpression,
|
||||
LiteralExpression,
|
||||
LiteralKind,
|
||||
ParenthesizedExpression,
|
||||
PropertyAccessExpression,
|
||||
StringLiteralExpression,
|
||||
SuperExpression,
|
||||
@ -66,7 +68,8 @@ import {
|
||||
hasDecorator,
|
||||
hasModifier,
|
||||
mangleInternalName,
|
||||
getFirstDecorator
|
||||
getFirstDecorator,
|
||||
BinaryExpression
|
||||
} from "./ast";
|
||||
|
||||
import {
|
||||
@ -1156,8 +1159,22 @@ export class Program extends DiagnosticEmitter {
|
||||
|
||||
resolveExpression(expression: Expression, contextualFunction: Function): ResolvedElement | null {
|
||||
var classType: Class | null;
|
||||
|
||||
while (expression.kind == NodeKind.PARENTHESIZED)
|
||||
expression = (<ParenthesizedExpression>expression).expression;
|
||||
|
||||
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
|
||||
if (classType = contextualFunction.instanceMethodOf)
|
||||
return (resolvedElement || (resolvedElement = new ResolvedElement())).set(classType);
|
||||
|
4
std/assembly/iterator.ts
Normal file
4
std/assembly/iterator.ts
Normal file
@ -0,0 +1,4 @@
|
||||
// export abstract class Iterator<T> {
|
||||
// abstract get done(): bool;
|
||||
// abstract next(): T;
|
||||
// }
|
@ -1,3 +1,37 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -66,3 +66,14 @@ export class Set<T> {
|
||||
|
||||
// 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");
|
||||
// }
|
||||
// }
|
||||
|
@ -4052,6 +4052,7 @@
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
PROPERTY: std:map/Map#size
|
||||
CLASS_PROTOTYPE: Map
|
||||
FUNCTION_PROTOTYPE: std:memory/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:memory/move_memory
|
||||
|
@ -259,6 +259,7 @@
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
PROPERTY: std:map/Map#size
|
||||
CLASS_PROTOTYPE: Map
|
||||
FUNCTION_PROTOTYPE: std:memory/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:memory/move_memory
|
||||
|
@ -2868,6 +2868,7 @@
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
PROPERTY: std:map/Map#size
|
||||
CLASS_PROTOTYPE: Map
|
||||
FUNCTION_PROTOTYPE: std:memory/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:memory/move_memory
|
||||
|
@ -209,6 +209,7 @@
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
PROPERTY: std:map/Map#size
|
||||
CLASS_PROTOTYPE: Map
|
||||
FUNCTION_PROTOTYPE: std:memory/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:memory/move_memory
|
||||
|
@ -2777,6 +2777,7 @@
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
PROPERTY: std:map/Map#size
|
||||
CLASS_PROTOTYPE: Map
|
||||
FUNCTION_PROTOTYPE: std:memory/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:memory/move_memory
|
||||
|
@ -1504,6 +1504,7 @@
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: RangeError
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
PROPERTY: std:map/Map#size
|
||||
CLASS_PROTOTYPE: Map
|
||||
FUNCTION_PROTOTYPE: std:memory/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:memory/move_memory
|
||||
|
1
tests/parser/propertyelementaccess.ts
Normal file
1
tests/parser/propertyelementaccess.ts
Normal file
@ -0,0 +1 @@
|
||||
(((this).values[0].prop1.prop2.another[1]).prop)[2];
|
1
tests/parser/propertyelementaccess.ts.fixture.ts
Normal file
1
tests/parser/propertyelementaccess.ts.fixture.ts
Normal file
@ -0,0 +1 @@
|
||||
(((this).values[0].prop1.prop2.another[1]).prop)[2];
|
Loading…
x
Reference in New Issue
Block a user