This commit is contained in:
dcodeIO 2017-12-02 20:58:39 +01:00
parent b9edfb5185
commit 9e053f311e
7 changed files with 226 additions and 9 deletions

10
.travis.yml Normal file
View File

@ -0,0 +1,10 @@
dist: trusty
language: node_js
node_js:
- 8
jobs:
include:
- stage: test
script: npm test
- stage: build
script: npm run build

View File

@ -1,6 +1,8 @@
AssemblyScript NEXT
===================
[![Build Status](https://travis-ci.org/AssemblyScript/next.svg?branch=master)](https://travis-ci.org/AssemblyScript/next)
This repository contains compiler component prototypes for the next iteration of the AssemblyScript compiler written in AssemblyScript itself.
Note that the code uses some features and standard library components that are not yet supported by any version of asc. To account for this, the code has been written in "portable AssemblyScript", a TypeScript-compatible subset of a subset of a superset of JavaScript, that also compiles to JavaScript using TSC.

View File

@ -766,17 +766,18 @@ export class Compiler extends DiagnosticEmitter {
const breaks: ExpressionRef[] = new Array(1 + k);
breaks[0] = this.module.createSetLocal(local.index, this.compileExpression(statement.expression, Type.i32)); // initializer
// make one br_if per (possibly dynamic) labeled case
// TODO: take advantage of br_table where labels are known to be (sequential) constant (ideally the optimizer would)
// make one br_if per (possibly dynamic) labeled case (binaryen optimizes to br_table where possible)
let breakIndex: i32 = 1;
let defaultIndex: i32 = -1;
for (i = 0; i < k; ++i) {
const case_: SwitchCase = statement.cases[i];
if (case_.label) {
breaks[breakIndex++] = this.module.createBreak("case" + i.toString(10) + "$" + context, this.module.createBinary(BinaryOp.EqI32,
this.module.createGetLocal(local.index, NativeType.I32),
this.compileExpression(case_.label, Type.i32)
));
breaks[breakIndex++] = this.module.createBreak("case" + i.toString(10) + "$" + context,
this.module.createBinary(BinaryOp.EqI32,
this.module.createGetLocal(local.index, NativeType.I32),
this.compileExpression(case_.label, Type.i32)
)
);
} else
defaultIndex = i;
}

View File

@ -1118,8 +1118,7 @@ export class Parser extends DiagnosticEmitter {
this.error(DiagnosticCode._0_expected, tn.range(), ":");
// 'default' ':' Statement*
} else if (tn.nextToken == Token.DEFAULT) {
tn.next();
} else if (tn.skip(Token.DEFAULT)) {
if (tn.skip(Token.COLON)) {
const statements: Statement[] = new Array();
while (tn.peek() != Token.CASE && tn.nextToken != Token.DEFAULT && tn.nextToken != Token.CLOSEBRACE) {

View File

@ -28,7 +28,7 @@
"glue/js.d.ts",
"glue/js.ts",
"index.ts",
"moddule.ts",
"module.ts",
"parser.ts",
"program.ts",
"tokenizer.ts",

35
tests/compiler/switch.ts Normal file
View File

@ -0,0 +1,35 @@
export function doSwitch(n: i32): i32 {
switch (n) {
case 1:
return 1;
case 0:
default:
return 0;
case 2:
case 3:
return 23;
}
}
export function doSwitchDefaultFirst(n: i32): i32 {
switch (n) {
default:
return 0;
case 1:
return 1;
case 2:
case 3:
return 23;
}
}
export function doSwitchDefaultOmitted(n: i32): i32 {
switch (n) {
case 1:
return 1;
case 2:
case 3:
return 23;
}
return 0;
}

170
tests/compiler/switch.wast Normal file
View File

@ -0,0 +1,170 @@
(module
(type $ii (func (param i32) (result i32)))
(memory $0 1)
(data (i32.const 4) "\08\00\00\00")
(export "memory" (memory $0))
(func $switch/doSwitch (; 0 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(block $break$1.1
(block $case4$1.1
(block $case3$1.1
(block $case2$1.1
(block $case1$1.1
(block $case0$1.1
(set_local $1
(get_local $0)
)
(br_if $case0$1.1
(i32.eq
(get_local $1)
(i32.const 1)
)
)
(br_if $case1$1.1
(i32.eq
(get_local $1)
(i32.const 0)
)
)
(br_if $case3$1.1
(i32.eq
(get_local $1)
(i32.const 2)
)
)
(br_if $case4$1.1
(i32.eq
(get_local $1)
(i32.const 3)
)
)
(br $case2$1.1)
)
(return
(i32.const 1)
)
)
)
(return
(i32.const 0)
)
)
)
(return
(i32.const 23)
)
)
)
(func $switch/doSwitchDefaultFirst (; 1 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(block $break$1.1
(block $case3$1.1
(block $case2$1.1
(block $case1$1.1
(block $case0$1.1
(set_local $1
(get_local $0)
)
(br_if $case1$1.1
(i32.eq
(get_local $1)
(i32.const 1)
)
)
(br_if $case2$1.1
(i32.eq
(get_local $1)
(i32.const 2)
)
)
(br_if $case3$1.1
(i32.eq
(get_local $1)
(i32.const 3)
)
)
(br $case0$1.1)
)
(return
(i32.const 0)
)
)
(return
(i32.const 1)
)
)
)
(return
(i32.const 23)
)
)
)
(func $switch/doSwitchDefaultOmitted (; 2 ;) (type $ii) (param $0 i32) (result i32)
(local $1 i32)
(block $break$1.1
(block $case2$1.1
(block $case1$1.1
(block $case0$1.1
(set_local $1
(get_local $0)
)
(br_if $case0$1.1
(i32.eq
(get_local $1)
(i32.const 1)
)
)
(br_if $case1$1.1
(i32.eq
(get_local $1)
(i32.const 2)
)
)
(br_if $case2$1.1
(i32.eq
(get_local $1)
(i32.const 3)
)
)
(br $break$1.1)
)
(return
(i32.const 1)
)
)
)
(return
(i32.const 23)
)
)
(return
(i32.const 0)
)
)
)
(;
[program.elements]
clz
ctz
popcnt
rotl
rotr
abs
ceil
copysign
floor
max
min
nearest
sqrt
trunc
isNaN
isFinite
switch/doSwitch
switch/doSwitchDefaultFirst
switch/doSwitchDefaultOmitted
[program.exports]
switch/doSwitch
switch/doSwitchDefaultFirst
switch/doSwitchDefaultOmitted
;)