mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 23:12:19 +00:00
Initial instance methods and field layout; More cleanup
This commit is contained in:
parent
2888ba14ad
commit
3add4624c5
@ -12,8 +12,9 @@ To build [assembly/pson.ts](./assembly/pson.ts) to an untouched and an optimized
|
|||||||
$> npm run build
|
$> npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
Afterwards, to run the included test, do:
|
Afterwards, to run the included [test](./tests/index.js):
|
||||||
|
|
||||||
```
|
```
|
||||||
|
$> npm install
|
||||||
$> npm test
|
$> npm test
|
||||||
```
|
```
|
||||||
|
43
src/ast.ts
43
src/ast.ts
@ -152,12 +152,13 @@ export abstract class Node {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createCall(expression: Expression, typeArguments: TypeNode[], args: Expression[], range: Range): CallExpression {
|
static createCall(expression: Expression, typeArguments: TypeNode[] | null, args: Expression[], range: Range): CallExpression {
|
||||||
var expr = new CallExpression();
|
var expr = new CallExpression();
|
||||||
expr.range = range;
|
expr.range = range;
|
||||||
(expr.expression = expression).parent = expr;
|
(expr.expression = expression).parent = expr;
|
||||||
for (var i = 0, k = (expr.typeArguments = typeArguments).length; i < k; ++i)
|
if (expr.typeArguments = typeArguments)
|
||||||
typeArguments[i].parent = expr;
|
for (var i = 0, k = (<TypeNode[]>typeArguments).length; i < k; ++i)
|
||||||
|
(<TypeNode[]>typeArguments)[i].parent = expr;
|
||||||
for (i = 0, k = (expr.arguments = args).length; i < k; ++i)
|
for (i = 0, k = (expr.arguments = args).length; i < k; ++i)
|
||||||
args[i].parent = expr;
|
args[i].parent = expr;
|
||||||
return expr;
|
return expr;
|
||||||
@ -197,12 +198,13 @@ export abstract class Node {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createNew(expression: Expression, typeArguments: TypeNode[], args: Expression[], range: Range): NewExpression {
|
static createNew(expression: Expression, typeArguments: TypeNode[] | null, args: Expression[], range: Range): NewExpression {
|
||||||
var expr = new NewExpression();
|
var expr = new NewExpression();
|
||||||
expr.range = range;
|
expr.range = range;
|
||||||
(expr.expression = expression).parent = expr;
|
(expr.expression = expression).parent = expr;
|
||||||
for (var i = 0, k = (expr.typeArguments = typeArguments).length; i < k; ++i)
|
if (expr.typeArguments = typeArguments)
|
||||||
typeArguments[i].parent = expr;
|
for (var i = 0, k = (<TypeNode[]>typeArguments).length; i < k; ++i)
|
||||||
|
(<TypeNode[]>typeArguments)[i].parent = expr;
|
||||||
for (i = 0, k = (expr.arguments = args).length; i < k; ++i)
|
for (i = 0, k = (expr.arguments = args).length; i < k; ++i)
|
||||||
args[i].parent = expr;
|
args[i].parent = expr;
|
||||||
return expr;
|
return expr;
|
||||||
@ -333,12 +335,13 @@ export abstract class Node {
|
|||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static createDecorator(expression: Expression, args: Expression[], range: Range): Decorator {
|
static createDecorator(expression: Expression, args: Expression[] | null, range: Range): Decorator {
|
||||||
var stmt = new Decorator();
|
var stmt = new Decorator();
|
||||||
stmt.range = range;
|
stmt.range = range;
|
||||||
(stmt.name = expression).parent = stmt;
|
(stmt.name = expression).parent = stmt;
|
||||||
for (var i: i32 = 0, k: i32 = (stmt.arguments = args).length; i < k; ++i)
|
if (stmt.arguments = args)
|
||||||
args[i].parent = stmt;
|
for (var i: i32 = 0, k: i32 = (<Expression[]>args).length; i < k; ++i)
|
||||||
|
(<Expression[]>args)[i].parent = stmt;
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -857,14 +860,14 @@ export class CallExpression extends Expression {
|
|||||||
/** Called expression. Usually an identifier or property access expression. */
|
/** Called expression. Usually an identifier or property access expression. */
|
||||||
expression: Expression;
|
expression: Expression;
|
||||||
/** Provided type arguments. */
|
/** Provided type arguments. */
|
||||||
typeArguments: TypeNode[];
|
typeArguments: TypeNode[] | null;
|
||||||
/** Provided arguments. */
|
/** Provided arguments. */
|
||||||
arguments: Expression[];
|
arguments: Expression[];
|
||||||
|
|
||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
this.expression.serialize(sb);
|
this.expression.serialize(sb);
|
||||||
var k = this.typeArguments.length;
|
var k: i32;
|
||||||
if (k) {
|
if (this.typeArguments && (k = this.typeArguments.length)) {
|
||||||
sb.push("<");
|
sb.push("<");
|
||||||
for (var i = 0; i < k; ++i) {
|
for (var i = 0; i < k; ++i) {
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
@ -1311,18 +1314,20 @@ export class Decorator extends Statement {
|
|||||||
/** Name expression. */
|
/** Name expression. */
|
||||||
name: Expression;
|
name: Expression;
|
||||||
/** Argument expressions. */
|
/** Argument expressions. */
|
||||||
arguments: Expression[];
|
arguments: Expression[] | null;
|
||||||
|
|
||||||
serialize(sb: string[]): void {
|
serialize(sb: string[]): void {
|
||||||
sb.push("@");
|
sb.push("@");
|
||||||
this.name.serialize(sb);
|
this.name.serialize(sb);
|
||||||
sb.push("(");
|
if (this.arguments) {
|
||||||
for (var i = 0, k = this.arguments.length; i < k; ++i) {
|
sb.push("(");
|
||||||
if (i > 0)
|
for (var i = 0, k = this.arguments.length; i < k; ++i) {
|
||||||
sb.push(", ");
|
if (i > 0)
|
||||||
this.arguments[i].serialize(sb);
|
sb.push(", ");
|
||||||
|
this.arguments[i].serialize(sb);
|
||||||
|
}
|
||||||
|
sb.push(")");
|
||||||
}
|
}
|
||||||
sb.push(")");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
226
src/builtins.ts
226
src/builtins.ts
@ -10,7 +10,8 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Node,
|
Node,
|
||||||
Expression
|
Expression,
|
||||||
|
BinaryExpression
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -187,7 +188,7 @@ export function compileGetConstant(compiler: Compiler, global: Global): Expressi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Compiles a call to a built-in function. */
|
/** Compiles a call to a built-in function. */
|
||||||
export function compileCall(compiler: Compiler, prototype: FunctionPrototype, typeArguments: Type[], operands: Expression[], reportNode: Node): ExpressionRef {
|
export function compileCall(compiler: Compiler, prototype: FunctionPrototype, typeArguments: Type[] | null, operands: Expression[], reportNode: Node): ExpressionRef {
|
||||||
var module = compiler.module;
|
var module = compiler.module;
|
||||||
var usizeType = select<Type>(Type.usize64, Type.usize32, compiler.options.target == Target.WASM64);
|
var usizeType = select<Type>(Type.usize64, Type.usize32, compiler.options.target == Target.WASM64);
|
||||||
var nativeUsizeType = select<NativeType>(NativeType.I64, NativeType.I32, compiler.options.target == Target.WASM64);
|
var nativeUsizeType = select<NativeType>(NativeType.I64, NativeType.I32, compiler.options.target == Target.WASM64);
|
||||||
@ -209,12 +210,12 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
compiler.currentType = Type.bool;
|
compiler.currentType = Type.bool;
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if (typeArguments[0].isAnyInteger)
|
if ((<Type[]>typeArguments)[0].isAnyInteger)
|
||||||
return module.createI32(0);
|
return module.createI32(0);
|
||||||
if (typeArguments[0].isAnyFloat) {
|
if ((<Type[]>typeArguments)[0].isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]); // reports
|
||||||
compiler.currentType = Type.bool;
|
compiler.currentType = Type.bool;
|
||||||
if (typeArguments[0] == Type.f32) {
|
if ((<Type[]>typeArguments)[0] == Type.f32) {
|
||||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
||||||
return module.createBinary(BinaryOp.NeF32,
|
return module.createBinary(BinaryOp.NeF32,
|
||||||
module.createTeeLocal(tempLocal0.index, arg0),
|
module.createTeeLocal(tempLocal0.index, arg0),
|
||||||
@ -234,12 +235,12 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
compiler.currentType = Type.bool;
|
compiler.currentType = Type.bool;
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if (typeArguments[0].isAnyInteger)
|
if ((<Type[]>typeArguments)[0].isAnyInteger)
|
||||||
return module.createI32(1);
|
return module.createI32(1);
|
||||||
if (typeArguments[0].isAnyFloat) {
|
if ((<Type[]>typeArguments)[0].isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]); // reports
|
||||||
compiler.currentType = Type.bool;
|
compiler.currentType = Type.bool;
|
||||||
if (typeArguments[0] == Type.f32) {
|
if ((<Type[]>typeArguments)[0] == Type.f32) {
|
||||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(Type.f32);
|
||||||
return module.createSelect(
|
return module.createSelect(
|
||||||
module.createBinary(BinaryOp.NeF32,
|
module.createBinary(BinaryOp.NeF32,
|
||||||
@ -276,14 +277,14 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "clz": // clz<T>(value: T) -> T
|
case "clz": // clz<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyInteger) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]).isLongInteger // sic
|
||||||
? module.createUnary(UnaryOp.ClzI64, arg0)
|
? module.createUnary(UnaryOp.ClzI64, arg0)
|
||||||
: typeArguments[0].isSmallInteger
|
: (<Type[]>typeArguments)[0].isSmallInteger
|
||||||
? module.createBinary(BinaryOp.AndI32,
|
? module.createBinary(BinaryOp.AndI32,
|
||||||
module.createUnary(UnaryOp.ClzI32, arg0),
|
module.createUnary(UnaryOp.ClzI32, arg0),
|
||||||
module.createI32(typeArguments[0].smallIntegerMask)
|
module.createI32((<Type[]>typeArguments)[0].smallIntegerMask)
|
||||||
)
|
)
|
||||||
: module.createUnary(UnaryOp.ClzI32, arg0);
|
: module.createUnary(UnaryOp.ClzI32, arg0);
|
||||||
}
|
}
|
||||||
@ -292,14 +293,14 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "ctz": // ctz<T>(value: T) -> T
|
case "ctz": // ctz<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyInteger) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]).isLongInteger // sic
|
||||||
? module.createUnary(UnaryOp.CtzI64, arg0)
|
? module.createUnary(UnaryOp.CtzI64, arg0)
|
||||||
: typeArguments[0].isSmallInteger
|
: (<Type[]>typeArguments)[0].isSmallInteger
|
||||||
? module.createBinary(BinaryOp.AndI32,
|
? module.createBinary(BinaryOp.AndI32,
|
||||||
module.createUnary(UnaryOp.CtzI32, arg0),
|
module.createUnary(UnaryOp.CtzI32, arg0),
|
||||||
module.createI32(typeArguments[0].smallIntegerMask)
|
module.createI32((<Type[]>typeArguments)[0].smallIntegerMask)
|
||||||
)
|
)
|
||||||
: module.createUnary(UnaryOp.CtzI32, arg0);
|
: module.createUnary(UnaryOp.CtzI32, arg0);
|
||||||
}
|
}
|
||||||
@ -308,14 +309,14 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "popcnt": // popcnt<T>(value: T) -> T
|
case "popcnt": // popcnt<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyInteger) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]).isLongInteger // sic
|
||||||
? module.createUnary(UnaryOp.PopcntI64, arg0)
|
? module.createUnary(UnaryOp.PopcntI64, arg0)
|
||||||
: typeArguments[0].isSmallInteger
|
: (<Type[]>typeArguments)[0].isSmallInteger
|
||||||
? module.createBinary(BinaryOp.AndI32,
|
? module.createBinary(BinaryOp.AndI32,
|
||||||
module.createUnary(UnaryOp.PopcntI32, arg0),
|
module.createUnary(UnaryOp.PopcntI32, arg0),
|
||||||
module.createI32(typeArguments[0].smallIntegerMask)
|
module.createI32((<Type[]>typeArguments)[0].smallIntegerMask)
|
||||||
)
|
)
|
||||||
: module.createUnary(UnaryOp.PopcntI32, arg0);
|
: module.createUnary(UnaryOp.PopcntI32, arg0);
|
||||||
}
|
}
|
||||||
@ -324,15 +325,15 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "rotl": // rotl<T>(value: T, shift: T) -> T
|
case "rotl": // rotl<T>(value: T, shift: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyInteger) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]).isLongInteger // sic
|
||||||
? module.createBinary(BinaryOp.RotlI64, arg0, arg1)
|
? module.createBinary(BinaryOp.RotlI64, arg0, arg1)
|
||||||
: typeArguments[0].isSmallInteger
|
: (<Type[]>typeArguments)[0].isSmallInteger
|
||||||
? module.createBinary(BinaryOp.AndI32,
|
? module.createBinary(BinaryOp.AndI32,
|
||||||
module.createBinary(BinaryOp.RotlI32, arg0, arg1),
|
module.createBinary(BinaryOp.RotlI32, arg0, arg1),
|
||||||
module.createI32(typeArguments[0].smallIntegerMask)
|
module.createI32((<Type[]>typeArguments)[0].smallIntegerMask)
|
||||||
)
|
)
|
||||||
: module.createBinary(BinaryOp.RotlI32, arg0, arg1);
|
: module.createBinary(BinaryOp.RotlI32, arg0, arg1);
|
||||||
}
|
}
|
||||||
@ -341,15 +342,15 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "rotr": // rotr<T>(value: T, shift: T) -> T
|
case "rotr": // rotr<T>(value: T, shift: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyInteger) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyInteger) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]).isLongInteger // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]).isLongInteger // sic
|
||||||
? module.createBinary(BinaryOp.RotrI64, arg0, arg1)
|
? module.createBinary(BinaryOp.RotrI64, arg0, arg1)
|
||||||
: typeArguments[0].isSmallInteger
|
: (<Type[]>typeArguments)[0].isSmallInteger
|
||||||
? module.createBinary(BinaryOp.AndI32,
|
? module.createBinary(BinaryOp.AndI32,
|
||||||
module.createBinary(BinaryOp.RotrI32, arg0, arg1),
|
module.createBinary(BinaryOp.RotrI32, arg0, arg1),
|
||||||
module.createI32(typeArguments[0].smallIntegerMask)
|
module.createI32((<Type[]>typeArguments)[0].smallIntegerMask)
|
||||||
)
|
)
|
||||||
: module.createBinary(BinaryOp.RotrI32, arg0, arg1);
|
: module.createBinary(BinaryOp.RotrI32, arg0, arg1);
|
||||||
}
|
}
|
||||||
@ -358,16 +359,16 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "abs": // abs<T>(value: T) -> T
|
case "abs": // abs<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]) != Type.void) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]) != Type.void) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) // sic
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) // sic
|
||||||
return typeArguments[0] == Type.f32
|
return (<Type[]>typeArguments)[0] == Type.f32
|
||||||
? module.createUnary(UnaryOp.AbsF32, arg0)
|
? module.createUnary(UnaryOp.AbsF32, arg0)
|
||||||
: module.createUnary(UnaryOp.AbsF64, arg0);
|
: module.createUnary(UnaryOp.AbsF64, arg0);
|
||||||
if (typeArguments[0].isAnyInteger) {
|
if ((<Type[]>typeArguments)[0].isAnyInteger) {
|
||||||
if (typeArguments[0].isSignedInteger) {
|
if ((<Type[]>typeArguments)[0].isSignedInteger) {
|
||||||
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal(typeArguments[0]);
|
tempLocal0 = compiler.currentFunction.getAndFreeTempLocal((<Type[]>typeArguments)[0]);
|
||||||
if (typeArguments[0].isLongInteger)
|
if ((<Type[]>typeArguments)[0].isLongInteger)
|
||||||
return module.createSelect(
|
return module.createSelect(
|
||||||
module.createBinary(BinaryOp.SubI64,
|
module.createBinary(BinaryOp.SubI64,
|
||||||
module.createI64(0, 0),
|
module.createI64(0, 0),
|
||||||
@ -400,22 +401,22 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "max": // max<T>(left: T, right: T) -> T
|
case "max": // max<T>(left: T, right: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]) != Type.void) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]) != Type.void) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]);
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) // sic
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) // sic
|
||||||
return typeArguments[0] == Type.f32
|
return (<Type[]>typeArguments)[0] == Type.f32
|
||||||
? module.createBinary(BinaryOp.MaxF32, arg0, arg1)
|
? module.createBinary(BinaryOp.MaxF32, arg0, arg1)
|
||||||
: module.createBinary(BinaryOp.MaxF64, arg0, arg1);
|
: module.createBinary(BinaryOp.MaxF64, arg0, arg1);
|
||||||
if (typeArguments[0].isAnyInteger) {
|
if ((<Type[]>typeArguments)[0].isAnyInteger) {
|
||||||
tempLocal0 = compiler.currentFunction.getTempLocal(typeArguments[0]);
|
tempLocal0 = compiler.currentFunction.getTempLocal((<Type[]>typeArguments)[0]);
|
||||||
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(typeArguments[0]);
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal((<Type[]>typeArguments)[0]);
|
||||||
compiler.currentFunction.freeTempLocal(tempLocal0);
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
||||||
if (typeArguments[0].isLongInteger)
|
if ((<Type[]>typeArguments)[0].isLongInteger)
|
||||||
return module.createSelect(
|
return module.createSelect(
|
||||||
module.createTeeLocal(tempLocal0.index, arg0),
|
module.createTeeLocal(tempLocal0.index, arg0),
|
||||||
module.createTeeLocal(tempLocal1.index, arg1),
|
module.createTeeLocal(tempLocal1.index, arg1),
|
||||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.GtI64 : BinaryOp.GtU64,
|
module.createBinary((<Type[]>typeArguments)[0].isSignedInteger ? BinaryOp.GtI64 : BinaryOp.GtU64,
|
||||||
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||||
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
||||||
)
|
)
|
||||||
@ -424,7 +425,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
return module.createSelect(
|
return module.createSelect(
|
||||||
module.createTeeLocal(tempLocal0.index, arg0),
|
module.createTeeLocal(tempLocal0.index, arg0),
|
||||||
module.createTeeLocal(tempLocal1.index, arg1),
|
module.createTeeLocal(tempLocal1.index, arg1),
|
||||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.GtI32 : BinaryOp.GtU32,
|
module.createBinary((<Type[]>typeArguments)[0].isSignedInteger ? BinaryOp.GtI32 : BinaryOp.GtU32,
|
||||||
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||||
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
||||||
)
|
)
|
||||||
@ -436,22 +437,22 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "min": // min<T>(left: T, right: T) -> T
|
case "min": // min<T>(left: T, right: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]) != Type.void) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]) != Type.void) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]);
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) // sic
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) // sic
|
||||||
return typeArguments[0] == Type.f32
|
return (<Type[]>typeArguments)[0] == Type.f32
|
||||||
? module.createBinary(BinaryOp.MinF32, arg0, arg1)
|
? module.createBinary(BinaryOp.MinF32, arg0, arg1)
|
||||||
: module.createBinary(BinaryOp.MinF64, arg0, arg1);
|
: module.createBinary(BinaryOp.MinF64, arg0, arg1);
|
||||||
if (typeArguments[0].isAnyInteger) {
|
if ((<Type[]>typeArguments)[0].isAnyInteger) {
|
||||||
tempLocal0 = compiler.currentFunction.getTempLocal(typeArguments[0]);
|
tempLocal0 = compiler.currentFunction.getTempLocal((<Type[]>typeArguments)[0]);
|
||||||
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal(typeArguments[0]);
|
tempLocal1 = compiler.currentFunction.getAndFreeTempLocal((<Type[]>typeArguments)[0]);
|
||||||
compiler.currentFunction.freeTempLocal(tempLocal0);
|
compiler.currentFunction.freeTempLocal(tempLocal0);
|
||||||
if (typeArguments[0].isLongInteger)
|
if ((<Type[]>typeArguments)[0].isLongInteger)
|
||||||
return module.createSelect(
|
return module.createSelect(
|
||||||
module.createTeeLocal(tempLocal0.index, arg0),
|
module.createTeeLocal(tempLocal0.index, arg0),
|
||||||
module.createTeeLocal(tempLocal1.index, arg1),
|
module.createTeeLocal(tempLocal1.index, arg1),
|
||||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.LtI64 : BinaryOp.LtU64,
|
module.createBinary((<Type[]>typeArguments)[0].isSignedInteger ? BinaryOp.LtI64 : BinaryOp.LtU64,
|
||||||
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
module.createGetLocal(tempLocal0.index, NativeType.I64),
|
||||||
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
module.createGetLocal(tempLocal1.index, NativeType.I64)
|
||||||
)
|
)
|
||||||
@ -460,7 +461,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
return module.createSelect(
|
return module.createSelect(
|
||||||
module.createTeeLocal(tempLocal0.index, arg0),
|
module.createTeeLocal(tempLocal0.index, arg0),
|
||||||
module.createTeeLocal(tempLocal1.index, arg1),
|
module.createTeeLocal(tempLocal1.index, arg1),
|
||||||
module.createBinary(typeArguments[0].isSignedInteger ? BinaryOp.LtI32 : BinaryOp.LtU32,
|
module.createBinary((<Type[]>typeArguments)[0].isSignedInteger ? BinaryOp.LtI32 : BinaryOp.LtU32,
|
||||||
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
module.createGetLocal(tempLocal0.index, NativeType.I32),
|
||||||
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
module.createGetLocal(tempLocal1.index, NativeType.I32)
|
||||||
)
|
)
|
||||||
@ -472,9 +473,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "ceil": // ceil<T>(value: T) -> T
|
case "ceil": // ceil<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]) == Type.f32 // sic
|
||||||
? module.createUnary(UnaryOp.CeilF32, arg0)
|
? module.createUnary(UnaryOp.CeilF32, arg0)
|
||||||
: module.createUnary(UnaryOp.CeilF64, arg0);
|
: module.createUnary(UnaryOp.CeilF64, arg0);
|
||||||
}
|
}
|
||||||
@ -483,9 +484,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "floor": // floor<T>(value: T) -> T
|
case "floor": // floor<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]) == Type.f32 // sic
|
||||||
? module.createUnary(UnaryOp.FloorF32, arg0)
|
? module.createUnary(UnaryOp.FloorF32, arg0)
|
||||||
: module.createUnary(UnaryOp.FloorF64, arg0);
|
: module.createUnary(UnaryOp.FloorF64, arg0);
|
||||||
}
|
}
|
||||||
@ -494,10 +495,10 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "copysign": // copysign<T>(left: T, right: T) -> T
|
case "copysign": // copysign<T>(left: T, right: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]);
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]) == Type.f32 // sic
|
||||||
? module.createBinary(BinaryOp.CopysignF32, arg0, arg1)
|
? module.createBinary(BinaryOp.CopysignF32, arg0, arg1)
|
||||||
: module.createBinary(BinaryOp.CopysignF64, arg0, arg1);
|
: module.createBinary(BinaryOp.CopysignF64, arg0, arg1);
|
||||||
}
|
}
|
||||||
@ -506,9 +507,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "nearest": // nearest<T>(value: T) -> T
|
case "nearest": // nearest<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]) == Type.f32 // sic
|
||||||
? module.createUnary(UnaryOp.NearestF32, arg0)
|
? module.createUnary(UnaryOp.NearestF32, arg0)
|
||||||
: module.createUnary(UnaryOp.NearestF64, arg0);
|
: module.createUnary(UnaryOp.NearestF64, arg0);
|
||||||
}
|
}
|
||||||
@ -517,25 +518,25 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "reinterpret": // reinterpret<T1,T2>(value: T1) -> T2
|
case "reinterpret": // reinterpret<T1,T2>(value: T1) -> T2
|
||||||
if (!validateCall(compiler, typeArguments, 2, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 2, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
compiler.currentType = typeArguments[1];
|
compiler.currentType = (<Type[]>typeArguments)[1];
|
||||||
if (typeArguments[0].isLongInteger && typeArguments[1] == Type.f64) {
|
if ((<Type[]>typeArguments)[0].isLongInteger && (<Type[]>typeArguments)[1] == Type.f64) {
|
||||||
arg0 = compiler.compileExpression(operands[0], Type.i64); // reports
|
arg0 = compiler.compileExpression(operands[0], Type.i64); // reports
|
||||||
compiler.currentType = Type.f64;
|
compiler.currentType = Type.f64;
|
||||||
return module.createUnary(UnaryOp.ReinterpretI64, arg0);
|
return module.createUnary(UnaryOp.ReinterpretI64, arg0);
|
||||||
}
|
}
|
||||||
if (typeArguments[0].isAnyInteger && typeArguments[0].byteSize == 4 && typeArguments[1] == Type.f32) {
|
if ((<Type[]>typeArguments)[0].isAnyInteger && (<Type[]>typeArguments)[0].byteSize == 4 && (<Type[]>typeArguments)[1] == Type.f32) {
|
||||||
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
arg0 = compiler.compileExpression(operands[0], Type.i32); // reports
|
||||||
compiler.currentType = Type.f32;
|
compiler.currentType = Type.f32;
|
||||||
return module.createUnary(UnaryOp.ReinterpretI32, arg0);
|
return module.createUnary(UnaryOp.ReinterpretI32, arg0);
|
||||||
}
|
}
|
||||||
if (typeArguments[0] == Type.f64 && typeArguments[1].isLongInteger) {
|
if ((<Type[]>typeArguments)[0] == Type.f64 && (<Type[]>typeArguments)[1].isLongInteger) {
|
||||||
arg0 = compiler.compileExpression(operands[0], Type.f64); // reports
|
arg0 = compiler.compileExpression(operands[0], Type.f64); // reports
|
||||||
compiler.currentType = typeArguments[1];
|
compiler.currentType = (<Type[]>typeArguments)[1];
|
||||||
return module.createUnary(UnaryOp.ReinterpretF64, arg0);
|
return module.createUnary(UnaryOp.ReinterpretF64, arg0);
|
||||||
}
|
}
|
||||||
if (typeArguments[0] == Type.f32 && typeArguments[1].isAnyInteger && typeArguments[1].byteSize == 4) {
|
if ((<Type[]>typeArguments)[0] == Type.f32 && (<Type[]>typeArguments)[1].isAnyInteger && (<Type[]>typeArguments)[1].byteSize == 4) {
|
||||||
arg0 = compiler.compileExpression(operands[0], Type.f32); // reports
|
arg0 = compiler.compileExpression(operands[0], Type.f32); // reports
|
||||||
compiler.currentType = typeArguments[1];
|
compiler.currentType = (<Type[]>typeArguments)[1];
|
||||||
return module.createUnary(UnaryOp.ReinterpretF32, arg0);
|
return module.createUnary(UnaryOp.ReinterpretF32, arg0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -543,9 +544,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "sqrt": // sqrt<T>(value: T) -> T
|
case "sqrt": // sqrt<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]) == Type.f32 // sic
|
||||||
? module.createUnary(UnaryOp.SqrtF32, arg0)
|
? module.createUnary(UnaryOp.SqrtF32, arg0)
|
||||||
: module.createUnary(UnaryOp.SqrtF64, arg0);
|
: module.createUnary(UnaryOp.SqrtF64, arg0);
|
||||||
}
|
}
|
||||||
@ -554,9 +555,9 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
case "trunc": // trunc<T>(value: T) -> T
|
case "trunc": // trunc<T>(value: T) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if ((compiler.currentType = typeArguments[0]).isAnyFloat) {
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]).isAnyFloat) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]);
|
||||||
return (compiler.currentType = typeArguments[0]) == Type.f32 // sic
|
return (compiler.currentType = (<Type[]>typeArguments)[0]) == Type.f32 // sic
|
||||||
? module.createUnary(UnaryOp.TruncF32, arg0)
|
? module.createUnary(UnaryOp.TruncF32, arg0)
|
||||||
: module.createUnary(UnaryOp.TruncF64, arg0);
|
: module.createUnary(UnaryOp.TruncF64, arg0);
|
||||||
}
|
}
|
||||||
@ -568,8 +569,8 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
|
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
|
||||||
if ((compiler.currentType = typeArguments[0]) != Type.void)
|
if ((compiler.currentType = (<Type[]>typeArguments)[0]) != Type.void)
|
||||||
return module.createLoad(typeArguments[0].byteSize, typeArguments[0].isSignedInteger, arg0, typeArguments[0].toNativeType());
|
return module.createLoad((<Type[]>typeArguments)[0].byteSize, (<Type[]>typeArguments)[0].isSignedInteger, arg0, (<Type[]>typeArguments)[0].toNativeType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "store": // store<T>(offset: usize, value: T) -> void
|
case "store": // store<T>(offset: usize, value: T) -> void
|
||||||
@ -577,10 +578,10 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 2, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
|
arg0 = compiler.compileExpression(operands[0], usizeType); // reports
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]); // reports
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]); // reports
|
||||||
compiler.currentType = Type.void;
|
compiler.currentType = Type.void;
|
||||||
if (typeArguments[0] != Type.void)
|
if ((<Type[]>typeArguments)[0] != Type.void)
|
||||||
return module.createStore(typeArguments[0].byteSize, arg0, arg1, typeArguments[0].toNativeType());
|
return module.createStore((<Type[]>typeArguments)[0].byteSize, arg0, arg1, (<Type[]>typeArguments)[0].toNativeType());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "sizeof": // sizeof<T>() -> usize
|
case "sizeof": // sizeof<T>() -> usize
|
||||||
@ -588,19 +589,19 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
if (!validateCall(compiler, typeArguments, 1, operands, 0, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 0, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
return usizeType.isLongInteger
|
return usizeType.isLongInteger
|
||||||
? module.createI64(typeArguments[0].byteSize, 0)
|
? module.createI64((<Type[]>typeArguments)[0].byteSize, 0)
|
||||||
: module.createI32(typeArguments[0].byteSize);
|
: module.createI32((<Type[]>typeArguments)[0].byteSize);
|
||||||
|
|
||||||
// control flow
|
// control flow
|
||||||
|
|
||||||
case "select": // select<T>(ifTrue: T, ifFalse: T, condition: bool) -> T
|
case "select": // select<T>(ifTrue: T, ifFalse: T, condition: bool) -> T
|
||||||
if (!validateCall(compiler, typeArguments, 1, operands, 3, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 3, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
if (typeArguments[0] != Type.void) {
|
if ((<Type[]>typeArguments)[0] != Type.void) {
|
||||||
arg0 = compiler.compileExpression(operands[0], typeArguments[0]); // reports
|
arg0 = compiler.compileExpression(operands[0], (<Type[]>typeArguments)[0]); // reports
|
||||||
arg1 = compiler.compileExpression(operands[1], typeArguments[0]); // reports
|
arg1 = compiler.compileExpression(operands[1], (<Type[]>typeArguments)[0]); // reports
|
||||||
arg2 = compiler.compileExpression(operands[2], Type.i32); // reports
|
arg2 = compiler.compileExpression(operands[2], Type.i32); // reports
|
||||||
compiler.currentType = typeArguments[0];
|
compiler.currentType = (<Type[]>typeArguments)[0];
|
||||||
return module.createSelect(arg0, arg1, arg2);
|
return module.createSelect(arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -652,7 +653,7 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
|
|
||||||
case "parseInt": // takes a pointer to the string
|
case "parseInt": // takes a pointer to the string
|
||||||
compiler.currentType = Type.f64;
|
compiler.currentType = Type.f64;
|
||||||
if (typeArguments.length != 0) {
|
if (typeArguments && typeArguments.length) {
|
||||||
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "0", typeArguments.length.toString(10));
|
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "0", typeArguments.length.toString(10));
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
}
|
}
|
||||||
@ -693,16 +694,16 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
if (!validateCall(compiler, typeArguments, 1, operands, 1, reportNode))
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
arg0 = compiler.compileExpression(operands[0], Type.void, ConversionKind.NONE);
|
arg0 = compiler.compileExpression(operands[0], Type.void, ConversionKind.NONE);
|
||||||
if ((compiler.currentType == usizeType && typeArguments[1].classType) || (compiler.currentType.classType && typeArguments[1] == usizeType)) {
|
if ((compiler.currentType == usizeType && (<Type[]>typeArguments)[1].classType) || (compiler.currentType.classType && (<Type[]>typeArguments)[1] == usizeType)) {
|
||||||
compiler.currentType = typeArguments[1];
|
compiler.currentType = (<Type[]>typeArguments)[1];
|
||||||
return arg0;
|
return arg0;
|
||||||
}
|
}
|
||||||
compiler.error(DiagnosticCode.Type_0_cannot_be_changed_to_type_1, reportNode.range, typeArguments[0].toString(), typeArguments[1].toString());
|
compiler.error(DiagnosticCode.Type_0_cannot_be_changed_to_type_1, reportNode.range, (<Type[]>typeArguments)[0].toString(), (<Type[]>typeArguments)[1].toString());
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
|
|
||||||
case "assert": // assert(isTrue: bool) -> void
|
case "assert": // assert(isTrue: bool) -> void
|
||||||
compiler.currentType = Type.void;
|
compiler.currentType = Type.void;
|
||||||
if (typeArguments.length != 0) {
|
if (typeArguments && typeArguments.length) {
|
||||||
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "0", typeArguments.length.toString(10));
|
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, "0", typeArguments.length.toString(10));
|
||||||
return module.createUnreachable();
|
return module.createUnreachable();
|
||||||
}
|
}
|
||||||
@ -795,9 +796,10 @@ export function compileCall(compiler: Compiler, prototype: FunctionPrototype, ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Pre-validates a call to a built-in function. */
|
/** Pre-validates a call to a built-in function. */
|
||||||
function validateCall(compiler: Compiler, typeArguments: Type[], expectedTypeArguments: i32, operands: Expression[], expectedOperands: i32, reportNode: Node): bool {
|
function validateCall(compiler: Compiler, typeArguments: Type[] | null, expectedTypeArguments: i32, operands: Expression[], expectedOperands: i32, reportNode: Node): bool {
|
||||||
if (typeArguments.length != expectedTypeArguments) {
|
var numTypeArguments = typeArguments && typeArguments.length || 0;
|
||||||
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, expectedTypeArguments.toString(10), typeArguments.length.toString(10));
|
if (numTypeArguments != expectedTypeArguments) {
|
||||||
|
compiler.error(DiagnosticCode.Expected_0_type_arguments_but_got_1, reportNode.range, expectedTypeArguments.toString(10), numTypeArguments.toString(10));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (operands.length != expectedOperands) {
|
if (operands.length != expectedOperands) {
|
||||||
|
1081
src/compiler.ts
1081
src/compiler.ts
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
// code below is generated from diagnosticsMessages.json by scripts/build-diagnostics
|
// code below is generated from diagnosticsMessages.json by scripts/build-diagnostics
|
||||||
|
|
||||||
export enum DiagnosticCode {
|
export enum DiagnosticCode {
|
||||||
Conversion_from_type_0_to_1_requires_an_explicit_cast = 100,
|
Conversion_from_type_0_to_1_possibly_loses_information_and_thus_requires_an_explicit_cast = 100,
|
||||||
Basic_type_0_cannot_be_nullable = 101,
|
Basic_type_0_cannot_be_nullable = 101,
|
||||||
Operation_not_supported = 102,
|
Operation_not_supported = 102,
|
||||||
Operation_is_unsafe = 103,
|
Operation_is_unsafe = 103,
|
||||||
@ -82,7 +82,7 @@ export enum DiagnosticCode {
|
|||||||
|
|
||||||
export function diagnosticCodeToString(code: DiagnosticCode): string {
|
export function diagnosticCodeToString(code: DiagnosticCode): string {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case 100: return "Conversion from type '{0}' to '{1}' requires an explicit cast.";
|
case 100: return "Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.";
|
||||||
case 101: return "Basic type '{0}' cannot be nullable.";
|
case 101: return "Basic type '{0}' cannot be nullable.";
|
||||||
case 102: return "Operation not supported.";
|
case 102: return "Operation not supported.";
|
||||||
case 103: return "Operation is unsafe.";
|
case 103: return "Operation is unsafe.";
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"Conversion from type '{0}' to '{1}' requires an explicit cast.": 100,
|
"Conversion from type '{0}' to '{1}' possibly loses information and thus requires an explicit cast.": 100,
|
||||||
"Basic type '{0}' cannot be nullable.": 101,
|
"Basic type '{0}' cannot be nullable.": 101,
|
||||||
"Operation not supported.": 102,
|
"Operation not supported.": 102,
|
||||||
"Operation is unsafe.": 103,
|
"Operation is unsafe.": 103,
|
||||||
|
@ -68,9 +68,9 @@ export function nextFile(parser: Parser): string | null {
|
|||||||
/** Obtains the next diagnostic message. Returns `null` once there are no more messages. */
|
/** Obtains the next diagnostic message. Returns `null` once there are no more messages. */
|
||||||
export function nextDiagnostic(parser: Parser): DiagnosticMessage | null {
|
export function nextDiagnostic(parser: Parser): DiagnosticMessage | null {
|
||||||
var program = parser.program;
|
var program = parser.program;
|
||||||
if (program.diagnosticsOffset < program.diagnostics.length)
|
return program.diagnosticsOffset < program.diagnostics.length
|
||||||
return program.diagnostics[program.diagnosticsOffset++];
|
? program.diagnostics[program.diagnosticsOffset++]
|
||||||
return null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Formats a diagnostic message to a string. */
|
/** Formats a diagnostic message to a string. */
|
||||||
|
@ -372,12 +372,13 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var args: Expression[] | null;
|
||||||
if (tn.skip(Token.OPENPAREN)) {
|
if (tn.skip(Token.OPENPAREN)) {
|
||||||
var args = this.parseArguments(tn);
|
args = this.parseArguments(tn);
|
||||||
if (args)
|
if (args)
|
||||||
return Node.createDecorator(expression, <Expression[]>args, tn.range(startPos, tn.pos));
|
return Node.createDecorator(expression, args, tn.range(startPos, tn.pos));
|
||||||
} else
|
} else
|
||||||
this.error(DiagnosticCode._0_expected, tn.range(), "(");
|
return Node.createDecorator(expression, null, tn.range(startPos, tn.pos));
|
||||||
} else
|
} else
|
||||||
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
this.error(DiagnosticCode.Identifier_expected, tn.range());
|
||||||
return null;
|
return null;
|
||||||
@ -1515,7 +1516,7 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tryParseTypeArgumentsBeforeArguments(tn: Tokenizer): TypeNode[] | null {
|
tryParseTypeArgumentsBeforeArguments(tn: Tokenizer): TypeNode[] | null {
|
||||||
// at '<': Identifier (',' Identifier)* '>' '('
|
// at '<': Type (',' Type)* '>' '('
|
||||||
tn.mark();
|
tn.mark();
|
||||||
if (!tn.skip(Token.LESSTHAN))
|
if (!tn.skip(Token.LESSTHAN))
|
||||||
return null;
|
return null;
|
||||||
@ -1529,11 +1530,12 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
typeArguments.push(type);
|
typeArguments.push(type);
|
||||||
} while (tn.skip(Token.COMMA));
|
} while (tn.skip(Token.COMMA));
|
||||||
if (!(tn.skip(Token.GREATERTHAN) && tn.skip(Token.OPENPAREN))) {
|
|
||||||
tn.reset();
|
if (tn.skip(Token.GREATERTHAN) && tn.skip(Token.OPENPAREN))
|
||||||
return null;
|
return typeArguments;
|
||||||
}
|
|
||||||
return typeArguments;
|
tn.reset();
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseArguments(tn: Tokenizer): Expression[] | null {
|
parseArguments(tn: Tokenizer): Expression[] | null {
|
||||||
@ -1562,13 +1564,13 @@ export class Parser extends DiagnosticEmitter {
|
|||||||
var startPos = expr.range.start;
|
var startPos = expr.range.start;
|
||||||
|
|
||||||
// CallExpression
|
// CallExpression
|
||||||
var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn);
|
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
|
||||||
if (typeArguments || tn.skip(Token.OPENPAREN)) {
|
if (typeArguments || tn.skip(Token.OPENPAREN)) {
|
||||||
var args = this.parseArguments(tn);
|
var args = this.parseArguments(tn);
|
||||||
if (!args)
|
if (!args)
|
||||||
return null;
|
return null;
|
||||||
expr = Node.createCall(expr, <TypeNode[]>(typeArguments ? typeArguments : []), args, tn.range(startPos, tn.pos));
|
expr = Node.createCall(expr, typeArguments, args, tn.range(startPos, tn.pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
var token: Token;
|
var token: Token;
|
||||||
|
280
src/program.ts
280
src/program.ts
@ -44,6 +44,7 @@ import {
|
|||||||
PropertyAccessExpression,
|
PropertyAccessExpression,
|
||||||
StringLiteralExpression,
|
StringLiteralExpression,
|
||||||
CallExpression,
|
CallExpression,
|
||||||
|
NewExpression,
|
||||||
|
|
||||||
Statement,
|
Statement,
|
||||||
ClassDeclaration,
|
ClassDeclaration,
|
||||||
@ -64,6 +65,7 @@ import {
|
|||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
VariableStatement,
|
VariableStatement,
|
||||||
|
|
||||||
|
hasDecorator,
|
||||||
hasModifier,
|
hasModifier,
|
||||||
mangleInternalName
|
mangleInternalName
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
@ -175,7 +177,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.TYPEDECLARATION:
|
case NodeKind.TYPEDECLARATION:
|
||||||
this.initializeType(<TypeDeclaration>statement);
|
this.initializeTypeAlias(<TypeDeclaration>statement);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.VARIABLE:
|
case NodeKind.VARIABLE:
|
||||||
@ -746,7 +748,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.TYPEDECLARATION:
|
case NodeKind.TYPEDECLARATION:
|
||||||
this.initializeType(<TypeDeclaration>members[i], namespace);
|
this.initializeTypeAlias(<TypeDeclaration>members[i], namespace);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NodeKind.VARIABLE:
|
case NodeKind.VARIABLE:
|
||||||
@ -759,7 +761,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeType(declaration: TypeDeclaration, namespace: Element | null = null): void {
|
private initializeTypeAlias(declaration: TypeDeclaration, namespace: Element | null = null): void {
|
||||||
// type aliases are program globals
|
// type aliases are program globals
|
||||||
// TODO: what about namespaced types?
|
// TODO: what about namespaced types?
|
||||||
var name = declaration.name.name;
|
var name = declaration.name.name;
|
||||||
@ -811,6 +813,19 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
/** Resolves a {@link TypeNode} to a concrete {@link Type}. */
|
/** Resolves a {@link TypeNode} to a concrete {@link Type}. */
|
||||||
resolveType(node: TypeNode, contextualTypeArguments: Map<string,Type> | null = null, reportNotFound: bool = true): Type | null {
|
resolveType(node: TypeNode, contextualTypeArguments: Map<string,Type> | null = null, reportNotFound: bool = true): Type | null {
|
||||||
|
var globalName = node.identifier.name;
|
||||||
|
var localName = node.range.source.internalPath + PATH_DELIMITER + node.identifier.name;
|
||||||
|
|
||||||
|
var element: Element | null;
|
||||||
|
|
||||||
|
// check file-global / program-global element
|
||||||
|
if ((element = this.elements.get(localName)) || (element = this.elements.get(globalName))) {
|
||||||
|
switch (element.kind) {
|
||||||
|
case ElementKind.CLASS_PROTOTYPE:
|
||||||
|
var instance = (<ClassPrototype>element).resolveInclTypeArguments(node.typeArguments, contextualTypeArguments, null); // reports
|
||||||
|
return instance ? instance.type : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// resolve parameters
|
// resolve parameters
|
||||||
var k = node.typeArguments.length;
|
var k = node.typeArguments.length;
|
||||||
@ -822,10 +837,13 @@ export class Program extends DiagnosticEmitter {
|
|||||||
paramTypes[i] = paramType;
|
paramTypes[i] = paramType;
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalName = node.identifier.name;
|
if (k) { // can't be a placeholder if it has parameters
|
||||||
if (k) // can't be a placeholder if it has parameters
|
var instanceKey = typesToString(paramTypes);
|
||||||
globalName += typesToString(paramTypes);
|
if (instanceKey.length) {
|
||||||
else if (contextualTypeArguments) {
|
localName += "<" + instanceKey + ">";
|
||||||
|
globalName += "<" + instanceKey + ">";
|
||||||
|
}
|
||||||
|
} else if (contextualTypeArguments) {
|
||||||
var placeholderType = contextualTypeArguments.get(globalName);
|
var placeholderType = contextualTypeArguments.get(globalName);
|
||||||
if (placeholderType)
|
if (placeholderType)
|
||||||
return placeholderType;
|
return placeholderType;
|
||||||
@ -833,12 +851,8 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
var type: Type | null;
|
var type: Type | null;
|
||||||
|
|
||||||
// check file-global type
|
// check file-global / program-global type
|
||||||
if (type = this.types.get(node.range.source.internalPath + PATH_DELIMITER + globalName))
|
if ((type = this.types.get(localName)) || (type = this.types.get(globalName)))
|
||||||
return type;
|
|
||||||
|
|
||||||
// check program-global type
|
|
||||||
if (type = this.types.get(globalName))
|
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
// check type alias
|
// check type alias
|
||||||
@ -904,7 +918,7 @@ export class Program extends DiagnosticEmitter {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resolves a property access the element it refers to. */
|
/** Resolves a property access to the element it refers to. */
|
||||||
resolvePropertyAccess(propertyAccess: PropertyAccessExpression, contextualFunction: Function): Element | null {
|
resolvePropertyAccess(propertyAccess: PropertyAccessExpression, contextualFunction: Function): Element | null {
|
||||||
var expression = propertyAccess.expression;
|
var expression = propertyAccess.expression;
|
||||||
var target: Element | null = null;
|
var target: Element | null = null;
|
||||||
@ -917,12 +931,27 @@ export class Program extends DiagnosticEmitter {
|
|||||||
if (!target)
|
if (!target)
|
||||||
return null;
|
return null;
|
||||||
var propertyName = propertyAccess.property.name;
|
var propertyName = propertyAccess.property.name;
|
||||||
if (target.members) {
|
switch (target.kind) {
|
||||||
var member = target.members.get(propertyName);
|
|
||||||
if (member)
|
case ElementKind.GLOBAL:
|
||||||
return member;
|
case ElementKind.LOCAL:
|
||||||
|
var type = (<VariableLikeElement>target).type;
|
||||||
|
assert(type != null);
|
||||||
|
if ((<Type>type).classType) {
|
||||||
|
target = <Class>(<Type>type).classType;
|
||||||
|
// fall-through
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (target.members) {
|
||||||
|
var member = target.members.get(propertyName);
|
||||||
|
if (member)
|
||||||
|
return member;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, expression.range, (<PropertyAccessExpression>expression).property.name, target.internalName);
|
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyAccess.property.name, target.internalName);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,24 +975,13 @@ export class Program extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// instantiation
|
// instantiation
|
||||||
} else if (expression.kind == NodeKind.NEW) {
|
} else if (expression.kind == NodeKind.NEW) {
|
||||||
return this.resolveElement((<CallExpression>expression).expression, contextualFunction);
|
return this.resolveElement((<NewExpression>expression).expression, contextualFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("not implemented");
|
throw new Error("not implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasDecorator(name: string, decorators: Decorator[] | null): bool {
|
|
||||||
if (decorators)
|
|
||||||
for (var i = 0, k = decorators.length; i < k; ++i) {
|
|
||||||
var decorator = decorators[i];
|
|
||||||
var expression = decorator.name;
|
|
||||||
if (expression.kind == NodeKind.IDENTIFIER && decorator.arguments.length <= 1 && (<IdentifierExpression>expression).name == name)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates the specific kind of an {@link Element}. */
|
/** Indicates the specific kind of an {@link Element}. */
|
||||||
export enum ElementKind {
|
export enum ElementKind {
|
||||||
/** A {@link Global}. */
|
/** A {@link Global}. */
|
||||||
@ -1274,6 +1292,8 @@ export class FunctionPrototype extends Element {
|
|||||||
classPrototype: ClassPrototype | null;
|
classPrototype: ClassPrototype | null;
|
||||||
/** Resolved instances. */
|
/** Resolved instances. */
|
||||||
instances: Map<string,Function> = new Map();
|
instances: Map<string,Function> = new Map();
|
||||||
|
/** Class type arguments, if a partially resolved method of a generic class. */
|
||||||
|
classTypeArguments: Type[] | null = null;
|
||||||
|
|
||||||
/** Constructs a new function prototype. */
|
/** Constructs a new function prototype. */
|
||||||
constructor(program: Program, simpleName: string, internalName: string, declaration: FunctionDeclaration | null, classPrototype: ClassPrototype | null = null) {
|
constructor(program: Program, simpleName: string, internalName: string, declaration: FunctionDeclaration | null, classPrototype: ClassPrototype | null = null) {
|
||||||
@ -1298,9 +1318,8 @@ export class FunctionPrototype extends Element {
|
|||||||
if (this.declaration.typeParameters.length)
|
if (this.declaration.typeParameters.length)
|
||||||
this.isGeneric = true;
|
this.isGeneric = true;
|
||||||
}
|
}
|
||||||
if (this.classPrototype = classPrototype) {
|
if (this.classPrototype = classPrototype)
|
||||||
this.isInstance = true;
|
this.isInstance = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether a getter function or not. */
|
/** Whether a getter function or not. */
|
||||||
@ -1314,8 +1333,8 @@ export class FunctionPrototype extends Element {
|
|||||||
// Whether a getter/setter function or not.
|
// Whether a getter/setter function or not.
|
||||||
get isAccessor(): bool { return (this.flags & (ElementFlags.GETTER | ElementFlags.SETTER)) != 0; }
|
get isAccessor(): bool { return (this.flags & (ElementFlags.GETTER | ElementFlags.SETTER)) != 0; }
|
||||||
|
|
||||||
resolve(typeArguments: Type[] | null = null, contextualTypeArguments: Map<string,Type> | null = null): Function | null {
|
resolve(functionTypeArguments: Type[] | null = null, contextualTypeArguments: Map<string,Type> | null = null): Function | null {
|
||||||
var instanceKey = typeArguments ? typesToString(typeArguments, "", "") : "";
|
var instanceKey = functionTypeArguments ? typesToString(functionTypeArguments) : "";
|
||||||
var instance = this.instances.get(instanceKey);
|
var instance = this.instances.get(instanceKey);
|
||||||
if (instance)
|
if (instance)
|
||||||
return instance;
|
return instance;
|
||||||
@ -1323,16 +1342,34 @@ export class FunctionPrototype extends Element {
|
|||||||
if (!declaration)
|
if (!declaration)
|
||||||
throw new Error("declaration expected"); // cannot resolve built-ins
|
throw new Error("declaration expected"); // cannot resolve built-ins
|
||||||
|
|
||||||
// override call specific contextual type arguments
|
// inherit contextual type arguments
|
||||||
|
var inheritedTypeArguments = contextualTypeArguments;
|
||||||
|
contextualTypeArguments = new Map();
|
||||||
|
if (inheritedTypeArguments)
|
||||||
|
for (var [inheritedName, inheritedType] of inheritedTypeArguments)
|
||||||
|
contextualTypeArguments.set(inheritedName, inheritedType);
|
||||||
|
|
||||||
var i: i32, k: i32;
|
var i: i32, k: i32;
|
||||||
if (typeArguments && (k = typeArguments.length)) {
|
|
||||||
var inheritedTypeArguments = contextualTypeArguments;
|
// inherit class type arguments if a partially resolved instance method
|
||||||
contextualTypeArguments = new Map();
|
if (this.classPrototype && this.classTypeArguments) {
|
||||||
if (inheritedTypeArguments)
|
var classDeclaration = this.classPrototype.declaration;
|
||||||
for (var [inheritedName, inheritedType] of inheritedTypeArguments)
|
if (!classDeclaration)
|
||||||
contextualTypeArguments.set(inheritedName, inheritedType);
|
throw new Error("declaration expected"); // cannot resolve built-ins
|
||||||
|
var classTypeParameters = classDeclaration.typeParameters;
|
||||||
|
if ((k = this.classTypeArguments.length) != classTypeParameters.length)
|
||||||
|
throw new Error("unexpected type argument count mismatch");
|
||||||
for (i = 0; i < k; ++i)
|
for (i = 0; i < k; ++i)
|
||||||
contextualTypeArguments.set(declaration.typeParameters[i].identifier.name, typeArguments[i]);
|
contextualTypeArguments.set(classTypeParameters[i].identifier.name, this.classTypeArguments[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// override call specific contextual type arguments
|
||||||
|
var functionTypeParameters = declaration.typeParameters;
|
||||||
|
if (functionTypeArguments && (k = functionTypeArguments.length)) {
|
||||||
|
if (k != functionTypeParameters.length)
|
||||||
|
throw new Error("unexpected type argument count mismatch");
|
||||||
|
for (i = 0; i < k; ++i)
|
||||||
|
contextualTypeArguments.set(functionTypeParameters[i].identifier.name, functionTypeArguments[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve parameters
|
// resolve parameters
|
||||||
@ -1370,13 +1407,20 @@ export class FunctionPrototype extends Element {
|
|||||||
var internalName = this.internalName;
|
var internalName = this.internalName;
|
||||||
if (instanceKey.length)
|
if (instanceKey.length)
|
||||||
internalName += "<" + instanceKey + ">";
|
internalName += "<" + instanceKey + ">";
|
||||||
instance = new Function(this, internalName, typeArguments, parameters, returnType, null); // TODO: class
|
var classInstance: Class | null = null;
|
||||||
|
if (this.classPrototype) {
|
||||||
|
classInstance = this.classPrototype.resolve(this.classTypeArguments, contextualTypeArguments); // reports
|
||||||
|
if (!classInstance)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
instance = new Function(this, internalName, functionTypeArguments, parameters, returnType, classInstance);
|
||||||
|
instance.contextualTypeArguments = contextualTypeArguments;
|
||||||
this.instances.set(instanceKey, instance);
|
this.instances.set(instanceKey, instance);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null, alternativeReportNode: Node | null): Function | null {
|
resolveInclTypeArguments(typeArgumentNodes: TypeNode[] | null, contextualTypeArguments: Map<string,Type> | null, alternativeReportNode: Node | null): Function | null {
|
||||||
var resolvedTypeArguments: Type[] | null;
|
var resolvedTypeArguments: Type[] | null = null;
|
||||||
if (this.isGeneric) {
|
if (this.isGeneric) {
|
||||||
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
|
assert(typeArgumentNodes != null && typeArgumentNodes.length != 0);
|
||||||
if (!this.declaration)
|
if (!this.declaration)
|
||||||
@ -1384,13 +1428,21 @@ export class FunctionPrototype extends Element {
|
|||||||
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, alternativeReportNode);
|
resolvedTypeArguments = this.program.resolveTypeArguments(this.declaration.typeParameters, typeArgumentNodes, contextualTypeArguments, alternativeReportNode);
|
||||||
if (!resolvedTypeArguments)
|
if (!resolvedTypeArguments)
|
||||||
return null;
|
return null;
|
||||||
} else {
|
|
||||||
assert(typeArgumentNodes == null || typeArgumentNodes.length == 0);
|
|
||||||
resolvedTypeArguments = [];
|
|
||||||
}
|
}
|
||||||
return this.resolve(resolvedTypeArguments, contextualTypeArguments);
|
return this.resolve(resolvedTypeArguments, contextualTypeArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resolvePartial(classTypeArguments: Type[] | null): FunctionPrototype | null {
|
||||||
|
assert(this.classPrototype != null);
|
||||||
|
if (classTypeArguments && classTypeArguments.length) {
|
||||||
|
var partialPrototype = new FunctionPrototype(this.program, this.simpleName, this.internalName, this.declaration, this.classPrototype);
|
||||||
|
partialPrototype.flags = this.flags;
|
||||||
|
partialPrototype.classTypeArguments = classTypeArguments;
|
||||||
|
return partialPrototype;
|
||||||
|
}
|
||||||
|
return this; // no need to clone
|
||||||
|
}
|
||||||
|
|
||||||
toString(): string { return this.simpleName; }
|
toString(): string { return this.simpleName; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1435,9 +1487,10 @@ export class Function extends Element {
|
|||||||
assert(this.isInstance);
|
assert(this.isInstance);
|
||||||
this.locals.set("this", new Local(prototype.program, "this", localIndex++, instanceMethodOf.type));
|
this.locals.set("this", new Local(prototype.program, "this", localIndex++, instanceMethodOf.type));
|
||||||
if (instanceMethodOf.contextualTypeArguments) {
|
if (instanceMethodOf.contextualTypeArguments) {
|
||||||
if (!this.contextualTypeArguments) this.contextualTypeArguments = new Map();
|
if (!this.contextualTypeArguments)
|
||||||
for (var [name, type] of instanceMethodOf.contextualTypeArguments)
|
this.contextualTypeArguments = new Map();
|
||||||
this.contextualTypeArguments.set(name, type);
|
for (var [inheritedName, inheritedType] of instanceMethodOf.contextualTypeArguments)
|
||||||
|
this.contextualTypeArguments.set(inheritedName, inheritedType);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
assert(!this.isInstance);
|
assert(!this.isInstance);
|
||||||
@ -1477,9 +1530,9 @@ export class Function extends Element {
|
|||||||
case NativeType.F64: temps = this.tempF64s; break;
|
case NativeType.F64: temps = this.tempF64s; break;
|
||||||
default: throw new Error("unexpected type");
|
default: throw new Error("unexpected type");
|
||||||
}
|
}
|
||||||
if (temps && temps.length > 0)
|
return temps && temps.length > 0
|
||||||
return temps.pop();
|
? temps.pop()
|
||||||
return this.addLocal(type);
|
: this.addLocal(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Frees the temporary local for reuse. */
|
/** Frees the temporary local for reuse. */
|
||||||
@ -1584,6 +1637,12 @@ export class FieldPrototype extends Element {
|
|||||||
/** Whether the field is read-only or not. */
|
/** Whether the field is read-only or not. */
|
||||||
get isReadonly(): bool { return (this.flags & ElementFlags.READONLY) != 0; }
|
get isReadonly(): bool { return (this.flags & ElementFlags.READONLY) != 0; }
|
||||||
set isReadonly(is: bool) { if (is) this.flags |= ElementFlags.READONLY; else this.flags &= ~ElementFlags.READONLY; }
|
set isReadonly(is: bool) { if (is) this.flags |= ElementFlags.READONLY; else this.flags &= ~ElementFlags.READONLY; }
|
||||||
|
|
||||||
|
// resolve(contextualTypeArguments: Map<string,Type> | null = null): Field {
|
||||||
|
// if (!this.declaration)
|
||||||
|
// throw new Error("declaration expected");
|
||||||
|
// this.declaration.type
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A resolved instance field. */
|
/** A resolved instance field. */
|
||||||
@ -1595,10 +1654,12 @@ export class Field extends Element {
|
|||||||
prototype: FieldPrototype;
|
prototype: FieldPrototype;
|
||||||
/** Resolved type. */
|
/** Resolved type. */
|
||||||
type: Type;
|
type: Type;
|
||||||
/** Constant integer value, if applicable. */
|
/** Constant integer value, if a constant static integer. */
|
||||||
constantIntegerValue: I64 | null = null;
|
constantIntegerValue: I64 | null = null;
|
||||||
/** Constant float value, if applicable. */
|
/** Constant float value, if a constant static float. */
|
||||||
constantFloatValue: f64 = 0;
|
constantFloatValue: f64 = 0;
|
||||||
|
/** Field memory offset, if an instance field. */
|
||||||
|
memoryOffset: i32 = -1;
|
||||||
|
|
||||||
/** Constructs a new field. */
|
/** Constructs a new field. */
|
||||||
constructor(prototype: FieldPrototype, internalName: string, type: Type) {
|
constructor(prototype: FieldPrototype, internalName: string, type: Type) {
|
||||||
@ -1657,36 +1718,31 @@ export class ClassPrototype extends Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(typeArguments: Type[], contextualTypeArguments: Map<string,Type> | null): Class {
|
resolve(typeArguments: Type[] | null, contextualTypeArguments: Map<string,Type> | null = null): Class {
|
||||||
var instanceKey = typesToString(typeArguments, "", "");
|
var instanceKey = typeArguments ? typesToString(typeArguments) : "";
|
||||||
var instance = this.instances.get(instanceKey);
|
var instance = this.instances.get(instanceKey);
|
||||||
if (instance)
|
if (instance)
|
||||||
return instance;
|
return instance;
|
||||||
|
|
||||||
var declaration = this.declaration;
|
var declaration = this.declaration;
|
||||||
if (!declaration)
|
if (!declaration)
|
||||||
throw new Error("declaration expected"); // cannot resolve built-ins
|
throw new Error("declaration expected"); // cannot resolve built-ins
|
||||||
|
|
||||||
// override call specific contextual type arguments
|
// inherit contextual type arguments
|
||||||
var i: i32, k = typeArguments.length;
|
var inheritedTypeArguments = contextualTypeArguments;
|
||||||
if (k) {
|
contextualTypeArguments = new Map();
|
||||||
var inheritedTypeArguments = contextualTypeArguments;
|
if (inheritedTypeArguments)
|
||||||
contextualTypeArguments = new Map();
|
for (var [inheritedName, inheritedType] of inheritedTypeArguments)
|
||||||
if (inheritedTypeArguments)
|
contextualTypeArguments.set(inheritedName, inheritedType);
|
||||||
for (var [inheritedName, inheritedType] of inheritedTypeArguments)
|
|
||||||
contextualTypeArguments.set(inheritedName, inheritedType);
|
|
||||||
for (i = 0; i < k; ++i)
|
|
||||||
contextualTypeArguments.set(declaration.typeParameters[i].identifier.name, typeArguments[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: set up instance fields and methods
|
if (declaration.extendsType) // TODO: base class
|
||||||
if (this.instanceMembers)
|
throw new Error("not implemented");
|
||||||
for (var member of this.instanceMembers.values()) {
|
|
||||||
switch (member.kind) {
|
// override call specific contextual type arguments if provided
|
||||||
case ElementKind.FIELD_PROTOTYPE: break;
|
var i: i32, k: i32;
|
||||||
case ElementKind.FUNCTION_PROTOTYPE: break;
|
if (typeArguments)
|
||||||
default: throw new Error("unexpected instance member");
|
for (var i = 0, k = typeArguments.length; i < k; ++i)
|
||||||
}
|
contextualTypeArguments.set(declaration.typeParameters[i].identifier.name, typeArguments[i]);
|
||||||
}
|
|
||||||
|
|
||||||
var internalName = this.internalName;
|
var internalName = this.internalName;
|
||||||
if (instanceKey.length)
|
if (instanceKey.length)
|
||||||
@ -1694,6 +1750,51 @@ export class ClassPrototype extends Element {
|
|||||||
instance = new Class(this, internalName, typeArguments, null); // TODO: base class
|
instance = new Class(this, internalName, typeArguments, null); // TODO: base class
|
||||||
instance.contextualTypeArguments = contextualTypeArguments;
|
instance.contextualTypeArguments = contextualTypeArguments;
|
||||||
this.instances.set(instanceKey, instance);
|
this.instances.set(instanceKey, instance);
|
||||||
|
|
||||||
|
var memoryOffset: i32 = 0;
|
||||||
|
|
||||||
|
if (this.instanceMembers)
|
||||||
|
for (var member of this.instanceMembers.values()) {
|
||||||
|
switch (member.kind) {
|
||||||
|
|
||||||
|
case ElementKind.FIELD_PROTOTYPE: // fields are layed out in advance
|
||||||
|
if (!instance.members)
|
||||||
|
instance.members = new Map();
|
||||||
|
var fieldDeclaration = (<FieldPrototype>member).declaration;
|
||||||
|
if (!fieldDeclaration)
|
||||||
|
throw new Error("declaration expected");
|
||||||
|
if (!fieldDeclaration.type)
|
||||||
|
throw new Error("type expected"); // TODO: check if parent class defines a type for it already
|
||||||
|
var fieldType = this.program.resolveType(fieldDeclaration.type, instance.contextualTypeArguments); // reports
|
||||||
|
if (fieldType) {
|
||||||
|
var fieldInstance = new Field(<FieldPrototype>member, (<FieldPrototype>member).internalName, fieldType);
|
||||||
|
switch (fieldType.byteSize) { // align
|
||||||
|
case 1: break;
|
||||||
|
case 2: if (memoryOffset & 1) ++memoryOffset; break;
|
||||||
|
case 4: if (memoryOffset & 3) memoryOffset = (memoryOffset | 3) + 1; break;
|
||||||
|
case 8: if (memoryOffset & 7) memoryOffset = (memoryOffset | 7) + 1; break;
|
||||||
|
default: assert(false);
|
||||||
|
}
|
||||||
|
fieldInstance.memoryOffset = memoryOffset;
|
||||||
|
memoryOffset += fieldType.byteSize;
|
||||||
|
instance.members.set(member.simpleName, fieldInstance);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ElementKind.FUNCTION_PROTOTYPE: // instance methods remain partially resolved prototypes until compiled
|
||||||
|
if (!instance.members)
|
||||||
|
instance.members = new Map();
|
||||||
|
var methodPrototype = (<FunctionPrototype>member).resolvePartial(typeArguments); // reports
|
||||||
|
if (methodPrototype)
|
||||||
|
instance.members.set(member.simpleName, methodPrototype);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error("instance member expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.type.byteSize = memoryOffset;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1724,7 +1825,7 @@ export class Class extends Element {
|
|||||||
/** Prototype reference. */
|
/** Prototype reference. */
|
||||||
prototype: ClassPrototype;
|
prototype: ClassPrototype;
|
||||||
/** Resolved type arguments. */
|
/** Resolved type arguments. */
|
||||||
typeArguments: Type[];
|
typeArguments: Type[] | null;
|
||||||
/** Resolved class type. */
|
/** Resolved class type. */
|
||||||
type: Type;
|
type: Type;
|
||||||
/** Base class, if applicable. */
|
/** Base class, if applicable. */
|
||||||
@ -1733,7 +1834,7 @@ export class Class extends Element {
|
|||||||
contextualTypeArguments: Map<string,Type> | null = null;
|
contextualTypeArguments: Map<string,Type> | null = null;
|
||||||
|
|
||||||
/** Constructs a new class. */
|
/** Constructs a new class. */
|
||||||
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] = [], base: Class | null = null) {
|
constructor(prototype: ClassPrototype, internalName: string, typeArguments: Type[] | null = null, base: Class | null = null) {
|
||||||
super(prototype.program, prototype.simpleName, internalName);
|
super(prototype.program, prototype.simpleName, internalName);
|
||||||
this.prototype = prototype;
|
this.prototype = prototype;
|
||||||
this.flags = prototype.flags;
|
this.flags = prototype.flags;
|
||||||
@ -1750,17 +1851,20 @@ export class Class extends Element {
|
|||||||
|
|
||||||
// apply instance-specific contextual type arguments
|
// apply instance-specific contextual type arguments
|
||||||
var declaration = this.prototype.declaration;
|
var declaration = this.prototype.declaration;
|
||||||
|
var i: i32, k: i32;
|
||||||
if (declaration) { // irrelevant for built-ins
|
if (declaration) { // irrelevant for built-ins
|
||||||
var typeParameters = declaration.typeParameters;
|
var typeParameters = declaration.typeParameters;
|
||||||
if (typeParameters.length != typeArguments.length)
|
if (typeArguments) {
|
||||||
|
if (typeParameters.length != typeArguments.length)
|
||||||
|
throw new Error("unexpected type argument count mismatch");
|
||||||
|
if (k = typeArguments.length) {
|
||||||
|
if (!this.contextualTypeArguments)
|
||||||
|
this.contextualTypeArguments = new Map();
|
||||||
|
for (i = 0; i < k; ++i)
|
||||||
|
this.contextualTypeArguments.set(typeParameters[i].identifier.name, typeArguments[i]);
|
||||||
|
}
|
||||||
|
} else
|
||||||
throw new Error("unexpected type argument count mismatch");
|
throw new Error("unexpected type argument count mismatch");
|
||||||
var k = typeArguments.length;
|
|
||||||
if (k) {
|
|
||||||
if (!this.contextualTypeArguments)
|
|
||||||
this.contextualTypeArguments = new Map();
|
|
||||||
for (var i = 0; i < k; ++i)
|
|
||||||
this.contextualTypeArguments.set(typeParameters[i].identifier.name, typeArguments[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
187
src/tokenizer.ts
187
src/tokenizer.ts
@ -380,13 +380,13 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
|
|
||||||
// skip bom
|
// skip bom
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.BYTEORDERMARK)
|
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.BYTEORDERMARK)
|
||||||
this.pos++;
|
++this.pos;
|
||||||
|
|
||||||
// skip shebang
|
// skip shebang
|
||||||
if (this.pos + 1 < this.end && text.charCodeAt(this.pos) == CharCode.HASH && text.charCodeAt(this.pos + 1) == CharCode.EXCLAMATION) {
|
if (this.pos + 1 < this.end && text.charCodeAt(this.pos) == CharCode.HASH && text.charCodeAt(this.pos + 1) == CharCode.EXCLAMATION) {
|
||||||
this.pos += 2;
|
this.pos += 2;
|
||||||
while (this.pos < this.end && text.charCodeAt(this.pos) != CharCode.LINEFEED)
|
while (this.pos < this.end && text.charCodeAt(this.pos) != CharCode.LINEFEED)
|
||||||
this.pos++;
|
++this.pos;
|
||||||
// 'next' now starts at lf or eof
|
// 'next' now starts at lf or eof
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,7 +396,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
return this.token = this.unsafeNext(preferIdentifier);
|
return this.token = this.unsafeNext(preferIdentifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafeNext(preferIdentifier: bool = false): Token {
|
private unsafeNext(preferIdentifier: bool = false, maxCompoundLength: i32 = i32.MAX_VALUE): Token {
|
||||||
var text = this.source.text;
|
var text = this.source.text;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.pos >= this.end)
|
if (this.pos >= this.end)
|
||||||
@ -408,7 +408,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
|
|
||||||
case CharCode.CARRIAGERETURN:
|
case CharCode.CARRIAGERETURN:
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.LINEFEED)
|
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.LINEFEED)
|
||||||
this.pos++;
|
++this.pos;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CharCode.LINEFEED:
|
case CharCode.LINEFEED:
|
||||||
@ -416,13 +416,15 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
case CharCode.VERTICALTAB:
|
case CharCode.VERTICALTAB:
|
||||||
case CharCode.FORMFEED:
|
case CharCode.FORMFEED:
|
||||||
case CharCode.SPACE:
|
case CharCode.SPACE:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CharCode.EXCLAMATION:
|
case CharCode.EXCLAMATION:
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
++this.pos;
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (maxCompoundLength > 1 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 2 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
|
++this.pos;
|
||||||
return Token.EXCLAMATION_EQUALS_EQUALS;
|
return Token.EXCLAMATION_EQUALS_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.EXCLAMATION_EQUALS;
|
return Token.EXCLAMATION_EQUALS;
|
||||||
@ -435,42 +437,46 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
return Token.STRINGLITERAL; // expects a call to readString
|
return Token.STRINGLITERAL; // expects a call to readString
|
||||||
|
|
||||||
case CharCode.PERCENT:
|
case CharCode.PERCENT:
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
++this.pos;
|
||||||
this.pos++;
|
if (maxCompoundLength > 1 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
|
++this.pos;
|
||||||
return Token.PERCENT_EQUALS;
|
return Token.PERCENT_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.PERCENT;
|
return Token.PERCENT;
|
||||||
|
|
||||||
case CharCode.AMPERSAND:
|
case CharCode.AMPERSAND:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.AMPERSAND) {
|
if (text.charCodeAt(this.pos) == CharCode.AMPERSAND) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.AMPERSAND_AMPERSAND;
|
return Token.AMPERSAND_AMPERSAND;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.AMPERSAND_EQUALS;
|
return Token.AMPERSAND_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.AMPERSAND;
|
return Token.AMPERSAND;
|
||||||
|
|
||||||
case CharCode.OPENPAREN:
|
case CharCode.OPENPAREN:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.OPENPAREN;
|
return Token.OPENPAREN;
|
||||||
|
|
||||||
case CharCode.CLOSEPAREN:
|
case CharCode.CLOSEPAREN:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.CLOSEPAREN;
|
return Token.CLOSEPAREN;
|
||||||
|
|
||||||
case CharCode.ASTERISK:
|
case CharCode.ASTERISK:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.ASTERISK_EQUALS;
|
return Token.ASTERISK_EQUALS;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.ASTERISK) {
|
if (text.charCodeAt(this.pos) == CharCode.ASTERISK) {
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
++this.pos;
|
||||||
this.pos++;
|
if (maxCompoundLength > 2 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
|
++this.pos;
|
||||||
return Token.ASTERISK_ASTERISK_EQUALS;
|
return Token.ASTERISK_ASTERISK_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.ASTERISK_ASTERISK;
|
return Token.ASTERISK_ASTERISK;
|
||||||
@ -479,42 +485,45 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
return Token.ASTERISK;
|
return Token.ASTERISK;
|
||||||
|
|
||||||
case CharCode.PLUS:
|
case CharCode.PLUS:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.PLUS) {
|
if (text.charCodeAt(this.pos) == CharCode.PLUS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.PLUS_PLUS;
|
return Token.PLUS_PLUS;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.PLUS_EQUALS;
|
return Token.PLUS_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.PLUS;
|
return Token.PLUS;
|
||||||
|
|
||||||
case CharCode.COMMA:
|
case CharCode.COMMA:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.COMMA;
|
return Token.COMMA;
|
||||||
|
|
||||||
case CharCode.MINUS:
|
case CharCode.MINUS:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.MINUS) {
|
if (text.charCodeAt(this.pos) == CharCode.MINUS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.MINUS_MINUS;
|
return Token.MINUS_MINUS;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.MINUS_EQUALS;
|
return Token.MINUS_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.MINUS;
|
return Token.MINUS;
|
||||||
|
|
||||||
case CharCode.DOT:
|
case CharCode.DOT:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (isDecimalDigit(text.charCodeAt(this.pos))) {
|
if (isDecimalDigit(text.charCodeAt(this.pos))) {
|
||||||
this.pos--;
|
--this.pos;
|
||||||
return Token.FLOATLITERAL; // expects a call to readFloat
|
return Token.FLOATLITERAL; // expects a call to readFloat
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.DOT && this.pos + 1 < this.end && text.charCodeAt(this.pos + 1) == CharCode.DOT) {
|
if (maxCompoundLength > 2 && text.charCodeAt(this.pos) == CharCode.DOT && this.pos + 1 < this.end && text.charCodeAt(this.pos + 1) == CharCode.DOT) {
|
||||||
this.pos += 2;
|
this.pos += 2;
|
||||||
return Token.DOT_DOT_DOT;
|
return Token.DOT_DOT_DOT;
|
||||||
}
|
}
|
||||||
@ -522,7 +531,8 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
return Token.DOT;
|
return Token.DOT;
|
||||||
|
|
||||||
case CharCode.SLASH:
|
case CharCode.SLASH:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.SLASH) { // single-line comment
|
if (text.charCodeAt(this.pos) == CharCode.SLASH) { // single-line comment
|
||||||
if (this.pos + 1 < this.end && text.charCodeAt(this.pos + 1) == CharCode.SLASH) {
|
if (this.pos + 1 < this.end && text.charCodeAt(this.pos + 1) == CharCode.SLASH) {
|
||||||
// TODO: triple-slash directives, i.e. '/// <reference path="some.d.ts" />'
|
// TODO: triple-slash directives, i.e. '/// <reference path="some.d.ts" />'
|
||||||
@ -548,7 +558,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.SLASH_EQUALS;
|
return Token.SLASH_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,120 +581,125 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
: Token.FLOATLITERAL; // expects a call to readFloat
|
: Token.FLOATLITERAL; // expects a call to readFloat
|
||||||
|
|
||||||
case CharCode.COLON:
|
case CharCode.COLON:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.COLON;
|
return Token.COLON;
|
||||||
|
|
||||||
case CharCode.SEMICOLON:
|
case CharCode.SEMICOLON:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.SEMICOLON;
|
return Token.SEMICOLON;
|
||||||
|
|
||||||
case CharCode.LESSTHAN:
|
case CharCode.LESSTHAN:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.LESSTHAN) {
|
if (text.charCodeAt(this.pos) == CharCode.LESSTHAN) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (maxCompoundLength > 2 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.LESSTHAN_LESSTHAN_EQUALS;
|
return Token.LESSTHAN_LESSTHAN_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.LESSTHAN_LESSTHAN;
|
return Token.LESSTHAN_LESSTHAN;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.LESSTHAN_EQUALS;
|
return Token.LESSTHAN_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.LESSTHAN;
|
return Token.LESSTHAN;
|
||||||
|
|
||||||
case CharCode.EQUALS:
|
case CharCode.EQUALS:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (maxCompoundLength > 2 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.EQUALS_EQUALS_EQUALS;
|
return Token.EQUALS_EQUALS_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.EQUALS_EQUALS;
|
return Token.EQUALS_EQUALS;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
|
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.EQUALS_GREATERTHAN;
|
return Token.EQUALS_GREATERTHAN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.EQUALS;
|
return Token.EQUALS;
|
||||||
|
|
||||||
case CharCode.GREATERTHAN:
|
case CharCode.GREATERTHAN:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
|
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
if (this.pos < this.end) {
|
if (maxCompoundLength > 2 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
|
if (text.charCodeAt(this.pos) == CharCode.GREATERTHAN) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (maxCompoundLength > 3 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS;
|
return Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.GREATERTHAN_GREATERTHAN_GREATERTHAN;
|
return Token.GREATERTHAN_GREATERTHAN_GREATERTHAN;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.GREATERTHAN_GREATERTHAN_EQUALS;
|
return Token.GREATERTHAN_GREATERTHAN_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.GREATERTHAN_GREATERTHAN;
|
return Token.GREATERTHAN_GREATERTHAN;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.GREATERTHAN_EQUALS;
|
return Token.GREATERTHAN_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.GREATERTHAN;
|
return Token.GREATERTHAN;
|
||||||
|
|
||||||
case CharCode.QUESTION:
|
case CharCode.QUESTION:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.QUESTION;
|
return Token.QUESTION;
|
||||||
|
|
||||||
case CharCode.OPENBRACKET:
|
case CharCode.OPENBRACKET:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.OPENBRACKET;
|
return Token.OPENBRACKET;
|
||||||
|
|
||||||
case CharCode.CLOSEBRACKET:
|
case CharCode.CLOSEBRACKET:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.CLOSEBRACKET;
|
return Token.CLOSEBRACKET;
|
||||||
|
|
||||||
case CharCode.CARET:
|
case CharCode.CARET:
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
++this.pos;
|
||||||
this.pos++;
|
if (maxCompoundLength > 1 && this.pos < this.end && text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
|
++this.pos;
|
||||||
return Token.CARET_EQUALS;
|
return Token.CARET_EQUALS;
|
||||||
}
|
}
|
||||||
return Token.CARET;
|
return Token.CARET;
|
||||||
|
|
||||||
case CharCode.OPENBRACE:
|
case CharCode.OPENBRACE:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.OPENBRACE;
|
return Token.OPENBRACE;
|
||||||
|
|
||||||
case CharCode.BAR:
|
case CharCode.BAR:
|
||||||
if (++this.pos < this.end) {
|
++this.pos;
|
||||||
|
if (maxCompoundLength > 1 && this.pos < this.end) {
|
||||||
if (text.charCodeAt(this.pos) == CharCode.BAR) {
|
if (text.charCodeAt(this.pos) == CharCode.BAR) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.BAR_BAR;
|
return Token.BAR_BAR;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
if (text.charCodeAt(this.pos) == CharCode.EQUALS) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.BAR_EQUALS;
|
return Token.BAR_EQUALS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Token.BAR;
|
return Token.BAR;
|
||||||
|
|
||||||
case CharCode.CLOSEBRACE:
|
case CharCode.CLOSEBRACE:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.CLOSEBRACE;
|
return Token.CLOSEBRACE;
|
||||||
|
|
||||||
case CharCode.TILDE:
|
case CharCode.TILDE:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.TILDE;
|
return Token.TILDE;
|
||||||
|
|
||||||
case CharCode.AT:
|
case CharCode.AT:
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.AT;
|
return Token.AT;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -705,11 +720,11 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
return Token.IDENTIFIER; // expects a call to readIdentifier
|
return Token.IDENTIFIER; // expects a call to readIdentifier
|
||||||
} else if (isWhiteSpace(c)) {
|
} else if (isWhiteSpace(c)) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.error(DiagnosticCode.Invalid_character, this.range(this.pos, this.pos + 1));
|
this.error(DiagnosticCode.Invalid_character, this.range(this.pos, this.pos + 1));
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return Token.INVALID;
|
return Token.INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -742,7 +757,13 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
var posBefore = this.pos;
|
var posBefore = this.pos;
|
||||||
var tokenBefore = this.token;
|
var tokenBefore = this.token;
|
||||||
var tokenPosBefore = this.tokenPos;
|
var tokenPosBefore = this.tokenPos;
|
||||||
if ((this.token = this.unsafeNext(token == Token.IDENTIFIER)) == token) {
|
var maxCompoundLength = i32.MAX_VALUE;
|
||||||
|
switch (token) {
|
||||||
|
case Token.GREATERTHAN: // where parsing type arguments
|
||||||
|
maxCompoundLength = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((this.token = this.unsafeNext(token == Token.IDENTIFIER, maxCompoundLength)) == token) {
|
||||||
this.nextToken = -1;
|
this.nextToken = -1;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@ -820,7 +841,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
this.error(DiagnosticCode.Unterminated_string_literal, this.range(start - 1, this.pos));
|
this.error(DiagnosticCode.Unterminated_string_literal, this.range(start - 1, this.pos));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -864,7 +885,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
|
|
||||||
case CharCode.u: {
|
case CharCode.u: {
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.OPENBRACE) {
|
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.OPENBRACE) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
return this.readExtendedUnicodeEscape(); // \u{DDDDDDDD}
|
return this.readExtendedUnicodeEscape(); // \u{DDDDDDDD}
|
||||||
}
|
}
|
||||||
return this.readUnicodeEscape(); // \uDDDD
|
return this.readUnicodeEscape(); // \uDDDD
|
||||||
@ -872,7 +893,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
|
|
||||||
case CharCode.CARRIAGERETURN:
|
case CharCode.CARRIAGERETURN:
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.LINEFEED)
|
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.LINEFEED)
|
||||||
this.pos++;
|
++this.pos;
|
||||||
// fall through
|
// fall through
|
||||||
|
|
||||||
case CharCode.LINEFEED:
|
case CharCode.LINEFEED:
|
||||||
@ -901,14 +922,14 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (text.charCodeAt(this.pos) == CharCode.BACKSLASH) {
|
if (text.charCodeAt(this.pos) == CharCode.BACKSLASH) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
escaped = true;
|
escaped = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var c = text.charCodeAt(this.pos);
|
var c = text.charCodeAt(this.pos);
|
||||||
if (c == CharCode.SLASH) {
|
if (c == CharCode.SLASH) {
|
||||||
result += text.substring(start, this.pos);
|
result += text.substring(start, this.pos);
|
||||||
this.pos++;
|
++this.pos;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isLineBreak(c)) {
|
if (isLineBreak(c)) {
|
||||||
@ -916,7 +937,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
this.error(DiagnosticCode.Unterminated_regular_expression_literal, this.range(start, this.pos));
|
this.error(DiagnosticCode.Unterminated_regular_expression_literal, this.range(start, this.pos));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -965,7 +986,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
if (isOctalDigit(text.charCodeAt(this.pos + 1))) {
|
if (isOctalDigit(text.charCodeAt(this.pos + 1))) {
|
||||||
var start = this.pos;
|
var start = this.pos;
|
||||||
this.pos++;
|
++this.pos;
|
||||||
var value = this.readOctalInteger();
|
var value = this.readOctalInteger();
|
||||||
this.error(DiagnosticCode.Octal_literals_are_not_allowed_in_strict_mode, this.range(start, this.pos));
|
this.error(DiagnosticCode.Octal_literals_are_not_allowed_in_strict_mode, this.range(start, this.pos));
|
||||||
return value;
|
return value;
|
||||||
@ -994,7 +1015,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
value.add32(10 + c - CharCode.a);
|
value.add32(10 + c - CharCode.a);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
if (this.pos == start)
|
if (this.pos == start)
|
||||||
this.error(DiagnosticCode.Hexadecimal_digit_expected, this.range(start));
|
this.error(DiagnosticCode.Hexadecimal_digit_expected, this.range(start));
|
||||||
@ -1013,7 +1034,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
value.add32(c - CharCode._0);
|
value.add32(c - CharCode._0);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
if (this.pos == start)
|
if (this.pos == start)
|
||||||
this.error(DiagnosticCode.Digit_expected, this.range(start));
|
this.error(DiagnosticCode.Digit_expected, this.range(start));
|
||||||
@ -1032,7 +1053,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
value.add32(c - CharCode._0);
|
value.add32(c - CharCode._0);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
if (this.pos == start)
|
if (this.pos == start)
|
||||||
this.error(DiagnosticCode.Octal_digit_expected, this.range(start));
|
this.error(DiagnosticCode.Octal_digit_expected, this.range(start));
|
||||||
@ -1055,7 +1076,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
if (this.pos == start)
|
if (this.pos == start)
|
||||||
this.error(DiagnosticCode.Binary_digit_expected, this.range(start));
|
this.error(DiagnosticCode.Binary_digit_expected, this.range(start));
|
||||||
@ -1066,19 +1087,19 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
var start = this.pos;
|
var start = this.pos;
|
||||||
var text = this.source.text;
|
var text = this.source.text;
|
||||||
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
|
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
|
||||||
this.pos++;
|
++this.pos;
|
||||||
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.DOT) {
|
if (this.pos < this.end && text.charCodeAt(this.pos) == CharCode.DOT) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
|
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
if (this.pos < this.end) {
|
if (this.pos < this.end) {
|
||||||
var c = text.charCodeAt(this.pos);
|
var c = text.charCodeAt(this.pos);
|
||||||
if (c == CharCode.E || c == CharCode.e) {
|
if (c == CharCode.E || c == CharCode.e) {
|
||||||
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.MINUS)
|
if (++this.pos < this.end && text.charCodeAt(this.pos) == CharCode.MINUS)
|
||||||
this.pos++;
|
++this.pos;
|
||||||
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
|
while (this.pos < this.end && isDecimalDigit(text.charCodeAt(this.pos)))
|
||||||
this.pos++;
|
++this.pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return parseFloat(text.substring(start, this.pos));
|
return parseFloat(text.substring(start, this.pos));
|
||||||
@ -1126,7 +1147,7 @@ export class Tokenizer extends DiagnosticEmitter {
|
|||||||
this.error(DiagnosticCode.Unexpected_end_of_text, this.range(start, this.end));
|
this.error(DiagnosticCode.Unexpected_end_of_text, this.range(start, this.end));
|
||||||
invalid = true;
|
invalid = true;
|
||||||
} else if (text.charCodeAt(this.pos) == CharCode.CLOSEBRACE) {
|
} else if (text.charCodeAt(this.pos) == CharCode.CLOSEBRACE) {
|
||||||
this.pos++;
|
++this.pos;
|
||||||
} else {
|
} else {
|
||||||
this.error(DiagnosticCode.Unterminated_Unicode_escape_sequence, this.range(start, this.pos));
|
this.error(DiagnosticCode.Unterminated_Unicode_escape_sequence, this.range(start, this.pos));
|
||||||
invalid = true;
|
invalid = true;
|
||||||
|
67
src/types.ts
67
src/types.ts
@ -12,7 +12,9 @@ import {
|
|||||||
} from "./util/sb";
|
} from "./util/sb";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NativeType, ExpressionRef, Module
|
NativeType,
|
||||||
|
ExpressionRef,
|
||||||
|
Module
|
||||||
} from "./module";
|
} from "./module";
|
||||||
|
|
||||||
/** Indicates the kind of a type. */
|
/** Indicates the kind of a type. */
|
||||||
@ -39,7 +41,6 @@ export const enum TypeKind {
|
|||||||
|
|
||||||
// other
|
// other
|
||||||
VOID
|
VOID
|
||||||
// SYMBOL ?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents a resolved type. */
|
/** Represents a resolved type. */
|
||||||
@ -87,6 +88,10 @@ export class Type {
|
|||||||
get isAnySize(): bool { return this.kind == TypeKind.ISIZE || this.kind == TypeKind.USIZE; }
|
get isAnySize(): bool { return this.kind == TypeKind.ISIZE || this.kind == TypeKind.USIZE; }
|
||||||
/** Tests if this type is of any float kind, i.e., `f32` or `f64`. */
|
/** Tests if this type is of any float kind, i.e., `f32` or `f64`. */
|
||||||
get isAnyFloat(): bool { return this.kind == TypeKind.F32 || this.kind == TypeKind.F64; }
|
get isAnyFloat(): bool { return this.kind == TypeKind.F32 || this.kind == TypeKind.F64; }
|
||||||
|
/** Tests if this type is a class type. */
|
||||||
|
get isClass(): bool { return this.classType != null; }
|
||||||
|
/** Tests if this type is a function type. */
|
||||||
|
get isFunction(): bool { return this.functionType != null; }
|
||||||
|
|
||||||
/** Composes a class type from this type and a class. */
|
/** Composes a class type from this type and a class. */
|
||||||
asClass(classType: Class): Type {
|
asClass(classType: Class): Type {
|
||||||
@ -164,13 +169,30 @@ export class Type {
|
|||||||
: module.createI32(1);
|
: module.createI32(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converts this type to its signature name. */
|
/** Converts this type to its signature string. */
|
||||||
toSignatureName(): string {
|
toSignatureString(): string {
|
||||||
return this.kind == TypeKind.VOID ? "v"
|
switch (this.kind) {
|
||||||
: this.kind == TypeKind.F32 ? "f"
|
|
||||||
: this.kind == TypeKind.F64 ? "F"
|
default:
|
||||||
: this.isLongInteger ? "I"
|
return "i";
|
||||||
: "i";
|
|
||||||
|
case TypeKind.I64:
|
||||||
|
case TypeKind.U64:
|
||||||
|
return "I";
|
||||||
|
|
||||||
|
case TypeKind.ISIZE:
|
||||||
|
case TypeKind.USIZE:
|
||||||
|
return select<string>("I", "i", this.size == 64);
|
||||||
|
|
||||||
|
case TypeKind.F32:
|
||||||
|
return "f";
|
||||||
|
|
||||||
|
case TypeKind.F64:
|
||||||
|
return "F";
|
||||||
|
|
||||||
|
case TypeKind.VOID:
|
||||||
|
return "v";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
@ -184,9 +206,9 @@ export class Type {
|
|||||||
/** A 64-bit signed integer. */
|
/** A 64-bit signed integer. */
|
||||||
static readonly i64: Type = new Type(TypeKind.I64, 64);
|
static readonly i64: Type = new Type(TypeKind.I64, 64);
|
||||||
/** A 32-bit signed size. WASM32 only. */
|
/** A 32-bit signed size. WASM32 only. */
|
||||||
static readonly isize32: Type = new Type(TypeKind.I32, 32);
|
static readonly isize32: Type = new Type(TypeKind.ISIZE, 32);
|
||||||
/** A 64-bit signed size. WASM64 only. */
|
/** A 64-bit signed size. WASM64 only. */
|
||||||
static readonly isize64: Type = new Type(TypeKind.I64, 64);
|
static readonly isize64: Type = new Type(TypeKind.ISIZE, 64);
|
||||||
/** An 8-bit unsigned integer. */
|
/** An 8-bit unsigned integer. */
|
||||||
static readonly u8: Type = new Type(TypeKind.U8, 8);
|
static readonly u8: Type = new Type(TypeKind.U8, 8);
|
||||||
/** A 16-bit unsigned integer. */
|
/** A 16-bit unsigned integer. */
|
||||||
@ -196,9 +218,9 @@ export class Type {
|
|||||||
/** A 64-bit unsigned integer. */
|
/** A 64-bit unsigned integer. */
|
||||||
static readonly u64: Type = new Type(TypeKind.U64, 64);
|
static readonly u64: Type = new Type(TypeKind.U64, 64);
|
||||||
/** A 32-bit unsigned size. WASM32 only. */
|
/** A 32-bit unsigned size. WASM32 only. */
|
||||||
static readonly usize32: Type = new Type(TypeKind.U32, 32);
|
static readonly usize32: Type = new Type(TypeKind.USIZE, 32);
|
||||||
/** A 64-bit unsigned size. WASM64 only. */
|
/** A 64-bit unsigned size. WASM64 only. */
|
||||||
static readonly usize64: Type = new Type(TypeKind.U64, 64);
|
static readonly usize64: Type = new Type(TypeKind.USIZE, 64);
|
||||||
/** A 1-bit unsigned integer. */
|
/** A 1-bit unsigned integer. */
|
||||||
static readonly bool: Type = new Type(TypeKind.BOOL, 1);
|
static readonly bool: Type = new Type(TypeKind.BOOL, 1);
|
||||||
/** A 32-bit float. */
|
/** A 32-bit float. */
|
||||||
@ -209,19 +231,6 @@ export class Type {
|
|||||||
static readonly void: Type = new Type(TypeKind.VOID, 0);
|
static readonly void: Type = new Type(TypeKind.VOID, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// export class ClassType extends Type {
|
|
||||||
// constructor(cls: Class) {
|
|
||||||
// super(TypeKind.USIZE, /* clz.size */ 4); // TODO
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // TODO: what about 'type fun = <T>(a: T) => T;' ?
|
|
||||||
// export class FunctionType extends Type {
|
|
||||||
// constructor(fun: Function) {
|
|
||||||
// super(TypeKind.USIZE, fun.program.target == Target.WASM64 ? 8 : 4);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/** Converts an array of types to an array of native types. */
|
/** Converts an array of types to an array of native types. */
|
||||||
export function typesToNativeTypes(types: Type[]): NativeType[] {
|
export function typesToNativeTypes(types: Type[]): NativeType[] {
|
||||||
var k = types.length;
|
var k = types.length;
|
||||||
@ -232,12 +241,12 @@ export function typesToNativeTypes(types: Type[]): NativeType[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Converts an array of types to its combined string representation. Usually type arguments. */
|
/** Converts an array of types to its combined string representation. Usually type arguments. */
|
||||||
export function typesToString(types: Type[], prefix: string = "<", postfix: string = ">"): string {
|
export function typesToString(types: Type[]): string {
|
||||||
var k = types.length;
|
var k = types.length;
|
||||||
if (!k)
|
if (!k)
|
||||||
return "";
|
return "";
|
||||||
sb.length = 0;
|
var sb = new Array<string>(k);
|
||||||
for (var i = 0; i < k; ++i)
|
for (var i = 0; i < k; ++i)
|
||||||
sb[i] = types[i].toString();
|
sb[i] = types[i].toString();
|
||||||
return prefix + sb.join(", ") + postfix;
|
return sb.join(", ");
|
||||||
}
|
}
|
||||||
|
4
std/assembly.d.ts
vendored
4
std/assembly.d.ts
vendored
@ -272,10 +272,10 @@ interface RegExp {}
|
|||||||
// Internal decorators (not yet implemented)
|
// Internal decorators (not yet implemented)
|
||||||
|
|
||||||
/** Annotates an element being part of the global namespace. */
|
/** Annotates an element being part of the global namespace. */
|
||||||
declare function global(): any;
|
declare function global(target: Function): any;
|
||||||
|
|
||||||
/** Annotates a method being an operator overload. */
|
/** Annotates a method being an operator overload. */
|
||||||
declare function operator(token: string): any;
|
declare function operator(token: string): any;
|
||||||
|
|
||||||
declare function struct(): any;
|
declare function struct(target: Function): any;
|
||||||
declare function size(size: usize): any;
|
declare function size(size: usize): any;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@global()
|
@global
|
||||||
export class Array<T> {
|
export class Array<T> {
|
||||||
|
|
||||||
private ptr: usize;
|
private ptr: usize;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@global()
|
@global
|
||||||
export class Error {
|
export class Error {
|
||||||
|
|
||||||
name: string = "Error";
|
name: string = "Error";
|
||||||
@ -10,7 +10,7 @@ export class Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@global()
|
@global
|
||||||
export class RangeError extends Error {
|
export class RangeError extends Error {
|
||||||
name: string = "RangeError";
|
name: string = "RangeError";
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ var HEAP_OFFSET: usize = HEAP_BASE; // HEAP_BASE is a constant generated by the
|
|||||||
|
|
||||||
// TODO: maybe tlsf
|
// TODO: maybe tlsf
|
||||||
|
|
||||||
@global()
|
@global
|
||||||
export class Heap {
|
export class Heap {
|
||||||
|
|
||||||
static get used(): usize { return HEAP_OFFSET - HEAP_BASE; }
|
static get used(): usize { return HEAP_OFFSET - HEAP_BASE; }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@global()
|
@global
|
||||||
export class Map<K,V> {
|
export class Map<K,V> {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
@global()
|
@global
|
||||||
export class Set<T> {
|
export class Set<T> {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const EMPTY: String = changetype<String>("");
|
const EMPTY: String = changetype<String>("");
|
||||||
|
|
||||||
@global()
|
@global
|
||||||
export class String {
|
export class String {
|
||||||
// [key: number]: string;
|
// [key: number]: string;
|
||||||
|
|
||||||
|
2
std/portable.d.ts
vendored
2
std/portable.d.ts
vendored
@ -136,6 +136,8 @@ declare class Array<T> {
|
|||||||
constructor(capacity?: i32);
|
constructor(capacity?: i32);
|
||||||
push(value: T): void;
|
push(value: T): void;
|
||||||
pop(): T;
|
pop(): T;
|
||||||
|
unshift(value: T): void;
|
||||||
|
shift(): T;
|
||||||
join(delim: string): string;
|
join(delim: string): string;
|
||||||
slice(from: i32, to?: i32): T[];
|
slice(from: i32, to?: i32): T[];
|
||||||
splice(index: i32, count: i32): T[];
|
splice(index: i32, count: i32): T[];
|
||||||
|
@ -9,8 +9,9 @@ var func = mod.addFunction("test", funcType, [],
|
|||||||
)
|
)
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
mod.addExport("test", func);
|
mod.addFunctionExport("test", "test", func);
|
||||||
|
|
||||||
|
console.log(mod.emitText());
|
||||||
if (mod.validate())
|
if (mod.validate())
|
||||||
console.log("-> validates");
|
console.log("-> validates");
|
||||||
mod.emitBinary(); // -> Assertion failed: mappedGlobals.count(name), at: binaryen/src/wasm/wasm-binary.cpp,355,getGlobalIndex at Error
|
mod.emitBinary(); // -> Assertion failed: mappedGlobals.count(name), at: binaryen/src/wasm/wasm-binary.cpp,355,getGlobalIndex at Error
|
||||||
|
19
tests/binaryen/get_local-missing.js
Normal file
19
tests/binaryen/get_local-missing.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
var binaryen = require("binaryen");
|
||||||
|
|
||||||
|
var mod = new binaryen.Module();
|
||||||
|
var funcType = mod.addFunctionType("v", binaryen.void, []);
|
||||||
|
var func = mod.addFunction("test", funcType, [],
|
||||||
|
mod.block("", [
|
||||||
|
mod.drop(
|
||||||
|
mod.getLocal(0, binaryen.i32)
|
||||||
|
)
|
||||||
|
])
|
||||||
|
);
|
||||||
|
mod.addFunctionExport("test", "test", func);
|
||||||
|
|
||||||
|
console.log(mod.emitText());
|
||||||
|
if (mod.validate()) {
|
||||||
|
console.log("-> validates");
|
||||||
|
var binary = mod.emitBinary();
|
||||||
|
new WebAssembly.Module(binary); // CompileError: WebAssembly.Module(): Compiling wasm function #0:test failed: invalid local index: 0 @+34
|
||||||
|
}
|
@ -1,11 +1,70 @@
|
|||||||
(module
|
(module
|
||||||
(type $iii (func (param i32 i32) (result i32)))
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
(type $fff (func (param f32 f32) (result f32)))
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||||
|
(type $ifff (func (param i32 f32 f32) (result f32)))
|
||||||
|
(type $iv (func (param i32)))
|
||||||
(type $v (func))
|
(type $v (func))
|
||||||
|
(global $class/Animal.ONE (mut i32) (i32.const 1))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
|
(export "test" (func $class/test))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $start (; 0 ;) (type $v)
|
(func $class/test (; 0 ;) (type $iv) (param $0 i32)
|
||||||
|
(local $1 i32)
|
||||||
|
(local $2 i32)
|
||||||
|
(local $3 i32)
|
||||||
|
(local $4 i32)
|
||||||
|
(local $5 f32)
|
||||||
|
(local $6 f32)
|
||||||
|
(drop
|
||||||
|
(block (result i32)
|
||||||
|
(block $__inlined_func$class/Animal#instanceAdd (result i32)
|
||||||
|
(set_local $1
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(set_local $2
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $3
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(i32.add
|
||||||
|
(i32.add
|
||||||
|
(get_local $2)
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f32)
|
||||||
|
(block $__inlined_func$class/Animal#instanceSub<f32> (result f32)
|
||||||
|
(set_local $4
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(set_local $5
|
||||||
|
(f32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $6
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
(f32.add
|
||||||
|
(f32.sub
|
||||||
|
(get_local $5)
|
||||||
|
(get_local $6)
|
||||||
|
)
|
||||||
|
(f32.convert_s/i32
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 1 ;) (type $v)
|
||||||
(local $0 i32)
|
(local $0 i32)
|
||||||
(local $1 i32)
|
(local $1 i32)
|
||||||
(local $2 f32)
|
(local $2 f32)
|
||||||
@ -20,8 +79,11 @@
|
|||||||
(i32.const 2)
|
(i32.const 2)
|
||||||
)
|
)
|
||||||
(i32.add
|
(i32.add
|
||||||
(get_local $0)
|
(i32.add
|
||||||
(get_local $1)
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -35,9 +97,14 @@
|
|||||||
(set_local $3
|
(set_local $3
|
||||||
(f32.const 2)
|
(f32.const 2)
|
||||||
)
|
)
|
||||||
(f32.sub
|
(f32.add
|
||||||
(get_local $2)
|
(f32.sub
|
||||||
(get_local $3)
|
(get_local $2)
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
(f32.convert_s/i32
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -1,23 +1,72 @@
|
|||||||
(module
|
(module
|
||||||
(type $iii (func (param i32 i32) (result i32)))
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
(type $fff (func (param f32 f32) (result f32)))
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||||
|
(type $ifff (func (param i32 f32 f32) (result f32)))
|
||||||
|
(type $iv (func (param i32)))
|
||||||
(type $v (func))
|
(type $v (func))
|
||||||
|
(global $class/Animal.ONE (mut i32) (i32.const 1))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
|
(export "test" (func $class/test))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $class/Animal.add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
(func $class/Animal.add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
(i32.add
|
(i32.add
|
||||||
(get_local $0)
|
(i32.add
|
||||||
(get_local $1)
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(func $class/Animal.sub<f32> (; 1 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
(func $class/Animal.sub<f32> (; 1 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||||
(f32.sub
|
(f32.add
|
||||||
(get_local $0)
|
(f32.sub
|
||||||
(get_local $1)
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(f32.convert_s/i32
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(func $start (; 2 ;) (type $v)
|
(func $class/Animal#instanceAdd (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||||
|
(i32.add
|
||||||
|
(i32.add
|
||||||
|
(get_local $1)
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $class/Animal#instanceSub<f32> (; 3 ;) (type $ifff) (param $0 i32) (param $1 f32) (param $2 f32) (result f32)
|
||||||
|
(f32.add
|
||||||
|
(f32.sub
|
||||||
|
(get_local $1)
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(f32.convert_s/i32
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $class/test (; 4 ;) (type $iv) (param $0 i32)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal#instanceAdd
|
||||||
|
(get_local $0)
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal#instanceSub<f32>
|
||||||
|
(get_local $0)
|
||||||
|
(f32.const 1)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 5 ;) (type $v)
|
||||||
(drop
|
(drop
|
||||||
(call $class/Animal.add
|
(call $class/Animal.add
|
||||||
(i32.const 1)
|
(i32.const 1)
|
||||||
|
@ -1,9 +1,22 @@
|
|||||||
class Animal {
|
class Animal<T> {
|
||||||
static MAX: i32 = 1;
|
static ONE: i32 = 1;
|
||||||
static add(a: i32, b: i32): i32 { return a + b; }
|
static add(a: i32, b: i32): i32 { return a + b + Animal.ONE; }
|
||||||
static sub<T>(a: T, b: T): T { return a - b; } // tsc does not allow this
|
static sub<T>(a: T, b: T): T { return a - b + <T>Animal.ONE; } // tsc does not allow this
|
||||||
|
|
||||||
|
one: i32 = 1; // 4
|
||||||
|
two: i16 = 2; // 6
|
||||||
|
three: i8 = 3; // 7
|
||||||
|
instanceAdd(a: i32, b: i32): i32 { return a + b + Animal.ONE; }
|
||||||
|
instanceSub<T>(a: T, b: T): T { return a - b + <T>Animal.ONE; } // tsc does not allow this
|
||||||
}
|
}
|
||||||
|
|
||||||
Animal.MAX;
|
assert(sizeof<Animal<f64>>() == 7);
|
||||||
|
|
||||||
|
Animal.ONE;
|
||||||
Animal.add(1,2);
|
Animal.add(1,2);
|
||||||
Animal.sub<f32>(1.0, 2.0);
|
Animal.sub<f32>(1, 2);
|
||||||
|
|
||||||
|
export function test(animal: Animal<f64>): void {
|
||||||
|
animal.instanceAdd(1, 2);
|
||||||
|
animal.instanceSub<f32>(1, 2);
|
||||||
|
}
|
||||||
|
@ -1,31 +1,92 @@
|
|||||||
(module
|
(module
|
||||||
(type $iii (func (param i32 i32) (result i32)))
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
(type $fff (func (param f32 f32) (result f32)))
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||||
|
(type $ifff (func (param i32 f32 f32) (result f32)))
|
||||||
|
(type $iv (func (param i32)))
|
||||||
(type $v (func))
|
(type $v (func))
|
||||||
(global $class/Animal.MAX (mut i32) (i32.const 1))
|
(global $class/Animal.ONE (mut i32) (i32.const 1))
|
||||||
(global $HEAP_BASE i32 (i32.const 4))
|
(global $HEAP_BASE i32 (i32.const 4))
|
||||||
(memory $0 1)
|
(memory $0 1)
|
||||||
|
(export "test" (func $class/test))
|
||||||
(export "memory" (memory $0))
|
(export "memory" (memory $0))
|
||||||
(start $start)
|
(start $start)
|
||||||
(func $class/Animal.add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
(func $class/Animal.add (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
(return
|
(return
|
||||||
(i32.add
|
(i32.add
|
||||||
(get_local $0)
|
(i32.add
|
||||||
(get_local $1)
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(func $class/Animal.sub<f32> (; 1 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
(func $class/Animal.sub<f32> (; 1 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||||
(return
|
(return
|
||||||
(f32.sub
|
(f32.add
|
||||||
(get_local $0)
|
(f32.sub
|
||||||
(get_local $1)
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
(f32.convert_s/i32
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(func $start (; 2 ;) (type $v)
|
(func $class/Animal#instanceAdd (; 2 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||||
|
(return
|
||||||
|
(i32.add
|
||||||
|
(i32.add
|
||||||
|
(get_local $1)
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $class/Animal#instanceSub<f32> (; 3 ;) (type $ifff) (param $0 i32) (param $1 f32) (param $2 f32) (result f32)
|
||||||
|
(return
|
||||||
|
(f32.add
|
||||||
|
(f32.sub
|
||||||
|
(get_local $1)
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
(f32.convert_s/i32
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $class/test (; 4 ;) (type $iv) (param $0 i32)
|
||||||
(drop
|
(drop
|
||||||
(get_global $class/Animal.MAX)
|
(call $class/Animal#instanceAdd
|
||||||
|
(get_local $0)
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $class/Animal#instanceSub<f32>
|
||||||
|
(get_local $0)
|
||||||
|
(f32.const 1)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 5 ;) (type $v)
|
||||||
|
(if
|
||||||
|
(i32.eqz
|
||||||
|
(i32.eq
|
||||||
|
(i32.const 7)
|
||||||
|
(i32.const 7)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(unreachable)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(get_global $class/Animal.ONE)
|
||||||
)
|
)
|
||||||
(drop
|
(drop
|
||||||
(call $class/Animal.add
|
(call $class/Animal.add
|
||||||
@ -88,9 +149,10 @@
|
|||||||
FUNCTION_PROTOTYPE: usize
|
FUNCTION_PROTOTYPE: usize
|
||||||
GLOBAL: HEAP_BASE
|
GLOBAL: HEAP_BASE
|
||||||
CLASS_PROTOTYPE: class/Animal
|
CLASS_PROTOTYPE: class/Animal
|
||||||
GLOBAL: class/Animal.MAX
|
GLOBAL: class/Animal.ONE
|
||||||
FUNCTION_PROTOTYPE: class/Animal.add
|
FUNCTION_PROTOTYPE: class/Animal.add
|
||||||
FUNCTION_PROTOTYPE: class/Animal.sub
|
FUNCTION_PROTOTYPE: class/Animal.sub
|
||||||
|
FUNCTION_PROTOTYPE: class/test
|
||||||
[program.exports]
|
[program.exports]
|
||||||
|
FUNCTION_PROTOTYPE: class/test
|
||||||
;)
|
;)
|
||||||
|
195
tests/compiler/function.optimized-inlined.wast
Normal file
195
tests/compiler/function.optimized-inlined.wast
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
(module
|
||||||
|
(type $v (func))
|
||||||
|
(type $i (func (result i32)))
|
||||||
|
(type $I (func (result i64)))
|
||||||
|
(type $f (func (result f32)))
|
||||||
|
(type $F (func (result f64)))
|
||||||
|
(type $iv (func (param i32)))
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $II (func (param i64) (result i64)))
|
||||||
|
(type $ff (func (param f32) (result f32)))
|
||||||
|
(type $FF (func (param f64) (result f64)))
|
||||||
|
(type $iiv (func (param i32 i32)))
|
||||||
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $IiI (func (param i64 i32) (result i64)))
|
||||||
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $FFF (func (param f64 f64) (result f64)))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $start (; 0 ;) (type $v)
|
||||||
|
(local $0 i32)
|
||||||
|
(local $1 i32)
|
||||||
|
(local $2 i64)
|
||||||
|
(local $3 f32)
|
||||||
|
(local $4 f64)
|
||||||
|
(local $5 i32)
|
||||||
|
(local $6 i32)
|
||||||
|
(local $7 i32)
|
||||||
|
(local $8 i32)
|
||||||
|
(local $9 i64)
|
||||||
|
(local $10 i32)
|
||||||
|
(local $11 f32)
|
||||||
|
(local $12 f32)
|
||||||
|
(local $13 f64)
|
||||||
|
(local $14 f64)
|
||||||
|
(block
|
||||||
|
(block $__inlined_func$function/v
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result i32)
|
||||||
|
(block $__inlined_func$function/i (result i32)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result i64)
|
||||||
|
(block $__inlined_func$function/I (result i64)
|
||||||
|
(i64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f32)
|
||||||
|
(block $__inlined_func$function/f (result f32)
|
||||||
|
(f32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f64)
|
||||||
|
(block $__inlined_func$function/F (result f64)
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(block $__inlined_func$function/iv
|
||||||
|
(set_local $0
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result i32)
|
||||||
|
(block $__inlined_func$function/ii (result i32)
|
||||||
|
(set_local $1
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result i64)
|
||||||
|
(block $__inlined_func$function/II (result i64)
|
||||||
|
(set_local $2
|
||||||
|
(i64.const 0)
|
||||||
|
)
|
||||||
|
(get_local $2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f32)
|
||||||
|
(block $__inlined_func$function/ff (result f32)
|
||||||
|
(set_local $3
|
||||||
|
(f32.const 0)
|
||||||
|
)
|
||||||
|
(get_local $3)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f64)
|
||||||
|
(block $__inlined_func$function/FF (result f64)
|
||||||
|
(set_local $4
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
(get_local $4)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(block
|
||||||
|
(block $__inlined_func$function/iiv
|
||||||
|
(set_local $5
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $6
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result i32)
|
||||||
|
(block $__inlined_func$function/iii (result i32)
|
||||||
|
(set_local $7
|
||||||
|
(i32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $8
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(i32.add
|
||||||
|
(get_local $7)
|
||||||
|
(get_local $8)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result i64)
|
||||||
|
(block $__inlined_func$function/III (result i64)
|
||||||
|
(set_local $9
|
||||||
|
(i64.const 1)
|
||||||
|
)
|
||||||
|
(set_local $10
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(i64.add
|
||||||
|
(get_local $9)
|
||||||
|
(i64.extend_s/i32
|
||||||
|
(get_local $10)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f32)
|
||||||
|
(block $__inlined_func$function/fff (result f32)
|
||||||
|
(set_local $11
|
||||||
|
(f32.const 1)
|
||||||
|
)
|
||||||
|
(set_local $12
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
(f32.add
|
||||||
|
(get_local $11)
|
||||||
|
(get_local $12)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(block (result f64)
|
||||||
|
(block $__inlined_func$function/FFF (result f64)
|
||||||
|
(set_local $13
|
||||||
|
(f64.const 1)
|
||||||
|
)
|
||||||
|
(set_local $14
|
||||||
|
(f64.const 2)
|
||||||
|
)
|
||||||
|
(f64.add
|
||||||
|
(get_local $13)
|
||||||
|
(get_local $14)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
145
tests/compiler/function.optimized.wast
Normal file
145
tests/compiler/function.optimized.wast
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
(module
|
||||||
|
(type $v (func))
|
||||||
|
(type $i (func (result i32)))
|
||||||
|
(type $I (func (result i64)))
|
||||||
|
(type $f (func (result f32)))
|
||||||
|
(type $F (func (result f64)))
|
||||||
|
(type $iv (func (param i32)))
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $II (func (param i64) (result i64)))
|
||||||
|
(type $ff (func (param f32) (result f32)))
|
||||||
|
(type $FF (func (param f64) (result f64)))
|
||||||
|
(type $iiv (func (param i32 i32)))
|
||||||
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $IiI (func (param i64 i32) (result i64)))
|
||||||
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $FFF (func (param f64 f64) (result f64)))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $function/v (; 0 ;) (type $v)
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
(func $function/i (; 1 ;) (type $i) (result i32)
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(func $function/I (; 2 ;) (type $I) (result i64)
|
||||||
|
(i64.const 0)
|
||||||
|
)
|
||||||
|
(func $function/f (; 3 ;) (type $f) (result f32)
|
||||||
|
(f32.const 0)
|
||||||
|
)
|
||||||
|
(func $function/F (; 4 ;) (type $F) (result f64)
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
(func $function/iv (; 5 ;) (type $iv) (param $0 i32)
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
(func $function/ii (; 6 ;) (type $ii) (param $0 i32) (result i32)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(func $function/II (; 7 ;) (type $II) (param $0 i64) (result i64)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(func $function/ff (; 8 ;) (type $ff) (param $0 f32) (result f32)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(func $function/FF (; 9 ;) (type $FF) (param $0 f64) (result f64)
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
(func $function/iiv (; 10 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||||
|
(nop)
|
||||||
|
)
|
||||||
|
(func $function/iii (; 11 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
|
(i32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/III (; 12 ;) (type $IiI) (param $0 i64) (param $1 i32) (result i64)
|
||||||
|
(i64.add
|
||||||
|
(get_local $0)
|
||||||
|
(i64.extend_s/i32
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/fff (; 13 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||||
|
(f32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/FFF (; 14 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
|
||||||
|
(f64.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 15 ;) (type $v)
|
||||||
|
(call $function/v)
|
||||||
|
(drop
|
||||||
|
(call $function/i)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/I)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/f)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/F)
|
||||||
|
)
|
||||||
|
(call $function/iv
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/ii
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/II
|
||||||
|
(i64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/ff
|
||||||
|
(f32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/FF
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(call $function/iiv
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/iii
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/III
|
||||||
|
(i64.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/fff
|
||||||
|
(f32.const 1)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/FFF
|
||||||
|
(f64.const 1)
|
||||||
|
(f64.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
35
tests/compiler/function.ts
Normal file
35
tests/compiler/function.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
function v(): void {}
|
||||||
|
function i(): i32 { return 0; }
|
||||||
|
function I(): i64 { return 0; }
|
||||||
|
function f(): f32 { return 0; }
|
||||||
|
function F(): f64 { return 0; }
|
||||||
|
|
||||||
|
v();
|
||||||
|
i();
|
||||||
|
I();
|
||||||
|
f();
|
||||||
|
F();
|
||||||
|
|
||||||
|
function iv(a: i32): void {}
|
||||||
|
function ii(a: i32): i32 { return a; }
|
||||||
|
function II(a: i64): i64 { return a; }
|
||||||
|
function ff(a: f32): f32 { return a; }
|
||||||
|
function FF(a: f64): f64 { return a; }
|
||||||
|
|
||||||
|
iv(0);
|
||||||
|
ii(0);
|
||||||
|
II(0);
|
||||||
|
ff(0);
|
||||||
|
FF(0);
|
||||||
|
|
||||||
|
function iiv(a: i32, b: i32): void {}
|
||||||
|
function iii(a: i32, b: i32): i32 { return a + b; }
|
||||||
|
function III(a: i64, b: i32): i64 { return a + b; }
|
||||||
|
function fff(a: f32, b: f32): f32 { return a + b; }
|
||||||
|
function FFF(a: f64, b: f64): f64 { return a + b; }
|
||||||
|
|
||||||
|
iiv(1, 2);
|
||||||
|
iii(1, 2);
|
||||||
|
III(1, 2);
|
||||||
|
fff(1, 2);
|
||||||
|
FFF(1, 2);
|
231
tests/compiler/function.wast
Normal file
231
tests/compiler/function.wast
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
(module
|
||||||
|
(type $v (func))
|
||||||
|
(type $i (func (result i32)))
|
||||||
|
(type $I (func (result i64)))
|
||||||
|
(type $f (func (result f32)))
|
||||||
|
(type $F (func (result f64)))
|
||||||
|
(type $iv (func (param i32)))
|
||||||
|
(type $ii (func (param i32) (result i32)))
|
||||||
|
(type $II (func (param i64) (result i64)))
|
||||||
|
(type $ff (func (param f32) (result f32)))
|
||||||
|
(type $FF (func (param f64) (result f64)))
|
||||||
|
(type $iiv (func (param i32 i32)))
|
||||||
|
(type $iii (func (param i32 i32) (result i32)))
|
||||||
|
(type $IiI (func (param i64 i32) (result i64)))
|
||||||
|
(type $fff (func (param f32 f32) (result f32)))
|
||||||
|
(type $FFF (func (param f64 f64) (result f64)))
|
||||||
|
(global $HEAP_BASE i32 (i32.const 4))
|
||||||
|
(memory $0 1)
|
||||||
|
(export "memory" (memory $0))
|
||||||
|
(start $start)
|
||||||
|
(func $function/v (; 0 ;) (type $v)
|
||||||
|
)
|
||||||
|
(func $function/i (; 1 ;) (type $i) (result i32)
|
||||||
|
(return
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/I (; 2 ;) (type $I) (result i64)
|
||||||
|
(return
|
||||||
|
(i64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/f (; 3 ;) (type $f) (result f32)
|
||||||
|
(return
|
||||||
|
(f32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/F (; 4 ;) (type $F) (result f64)
|
||||||
|
(return
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/iv (; 5 ;) (type $iv) (param $0 i32)
|
||||||
|
)
|
||||||
|
(func $function/ii (; 6 ;) (type $ii) (param $0 i32) (result i32)
|
||||||
|
(return
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/II (; 7 ;) (type $II) (param $0 i64) (result i64)
|
||||||
|
(return
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/ff (; 8 ;) (type $ff) (param $0 f32) (result f32)
|
||||||
|
(return
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/FF (; 9 ;) (type $FF) (param $0 f64) (result f64)
|
||||||
|
(return
|
||||||
|
(get_local $0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/iiv (; 10 ;) (type $iiv) (param $0 i32) (param $1 i32)
|
||||||
|
)
|
||||||
|
(func $function/iii (; 11 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||||
|
(return
|
||||||
|
(i32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/III (; 12 ;) (type $IiI) (param $0 i64) (param $1 i32) (result i64)
|
||||||
|
(return
|
||||||
|
(i64.add
|
||||||
|
(get_local $0)
|
||||||
|
(i64.extend_s/i32
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/fff (; 13 ;) (type $fff) (param $0 f32) (param $1 f32) (result f32)
|
||||||
|
(return
|
||||||
|
(f32.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $function/FFF (; 14 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
|
||||||
|
(return
|
||||||
|
(f64.add
|
||||||
|
(get_local $0)
|
||||||
|
(get_local $1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(func $start (; 15 ;) (type $v)
|
||||||
|
(call $function/v)
|
||||||
|
(drop
|
||||||
|
(call $function/i)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/I)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/f)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/F)
|
||||||
|
)
|
||||||
|
(call $function/iv
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/ii
|
||||||
|
(i32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/II
|
||||||
|
(i64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/ff
|
||||||
|
(f32.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/FF
|
||||||
|
(f64.const 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(call $function/iiv
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/iii
|
||||||
|
(i32.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/III
|
||||||
|
(i64.const 1)
|
||||||
|
(i32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/fff
|
||||||
|
(f32.const 1)
|
||||||
|
(f32.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(drop
|
||||||
|
(call $function/FFF
|
||||||
|
(f64.const 1)
|
||||||
|
(f64.const 2)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(;
|
||||||
|
[program.elements]
|
||||||
|
GLOBAL: NaN
|
||||||
|
GLOBAL: Infinity
|
||||||
|
FUNCTION_PROTOTYPE: isNaN
|
||||||
|
FUNCTION_PROTOTYPE: isFinite
|
||||||
|
FUNCTION_PROTOTYPE: clz
|
||||||
|
FUNCTION_PROTOTYPE: ctz
|
||||||
|
FUNCTION_PROTOTYPE: popcnt
|
||||||
|
FUNCTION_PROTOTYPE: rotl
|
||||||
|
FUNCTION_PROTOTYPE: rotr
|
||||||
|
FUNCTION_PROTOTYPE: abs
|
||||||
|
FUNCTION_PROTOTYPE: max
|
||||||
|
FUNCTION_PROTOTYPE: min
|
||||||
|
FUNCTION_PROTOTYPE: ceil
|
||||||
|
FUNCTION_PROTOTYPE: floor
|
||||||
|
FUNCTION_PROTOTYPE: copysign
|
||||||
|
FUNCTION_PROTOTYPE: nearest
|
||||||
|
FUNCTION_PROTOTYPE: reinterpret
|
||||||
|
FUNCTION_PROTOTYPE: sqrt
|
||||||
|
FUNCTION_PROTOTYPE: trunc
|
||||||
|
FUNCTION_PROTOTYPE: load
|
||||||
|
FUNCTION_PROTOTYPE: store
|
||||||
|
FUNCTION_PROTOTYPE: sizeof
|
||||||
|
FUNCTION_PROTOTYPE: select
|
||||||
|
FUNCTION_PROTOTYPE: unreachable
|
||||||
|
FUNCTION_PROTOTYPE: current_memory
|
||||||
|
FUNCTION_PROTOTYPE: grow_memory
|
||||||
|
FUNCTION_PROTOTYPE: parseInt
|
||||||
|
FUNCTION_PROTOTYPE: parseFloat
|
||||||
|
FUNCTION_PROTOTYPE: changetype
|
||||||
|
FUNCTION_PROTOTYPE: assert
|
||||||
|
FUNCTION_PROTOTYPE: i8
|
||||||
|
FUNCTION_PROTOTYPE: i16
|
||||||
|
FUNCTION_PROTOTYPE: i32
|
||||||
|
FUNCTION_PROTOTYPE: i64
|
||||||
|
FUNCTION_PROTOTYPE: u8
|
||||||
|
FUNCTION_PROTOTYPE: u16
|
||||||
|
FUNCTION_PROTOTYPE: u32
|
||||||
|
FUNCTION_PROTOTYPE: u64
|
||||||
|
FUNCTION_PROTOTYPE: bool
|
||||||
|
FUNCTION_PROTOTYPE: f32
|
||||||
|
FUNCTION_PROTOTYPE: f64
|
||||||
|
FUNCTION_PROTOTYPE: isize
|
||||||
|
FUNCTION_PROTOTYPE: usize
|
||||||
|
GLOBAL: HEAP_BASE
|
||||||
|
FUNCTION_PROTOTYPE: function/v
|
||||||
|
FUNCTION_PROTOTYPE: function/i
|
||||||
|
FUNCTION_PROTOTYPE: function/I
|
||||||
|
FUNCTION_PROTOTYPE: function/f
|
||||||
|
FUNCTION_PROTOTYPE: function/F
|
||||||
|
FUNCTION_PROTOTYPE: function/iv
|
||||||
|
FUNCTION_PROTOTYPE: function/ii
|
||||||
|
FUNCTION_PROTOTYPE: function/II
|
||||||
|
FUNCTION_PROTOTYPE: function/ff
|
||||||
|
FUNCTION_PROTOTYPE: function/FF
|
||||||
|
FUNCTION_PROTOTYPE: function/iiv
|
||||||
|
FUNCTION_PROTOTYPE: function/iii
|
||||||
|
FUNCTION_PROTOTYPE: function/III
|
||||||
|
FUNCTION_PROTOTYPE: function/fff
|
||||||
|
FUNCTION_PROTOTYPE: function/FFF
|
||||||
|
[program.exports]
|
||||||
|
|
||||||
|
;)
|
Loading…
x
Reference in New Issue
Block a user