Skip to content

Commit 7cf879f

Browse files
committed
Type limits
1 parent 8085a02 commit 7cf879f

35 files changed

+911
-86
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
AssemblyScript NEXT
2-
===================
1+
![](https://s.gravatar.com/avatar/f105de3decfafc734b8eabe9a960b25d?size=64) AssemblyScript NEXT
2+
=================
33

4-
[![Build Status](https://travis-ci.org/AssemblyScript/next.svg?branch=master)](https://travis-ci.org/AssemblyScript/next)
4+
[![Build Status](https://travis-ci.org/AssemblyScript/assemblyscript.svg?branch=master)](https://travis-ci.org/AssemblyScript/assemblyscript)
55

66
**AssemblyScript** is a new compiler targeting [WebAssembly](http://webassembly.org) while utilizing [TypeScript](http://www.typescriptlang.org)'s syntax and [node](https://nodejs.org)'s vibrant ecosystem. Instead of requiring complex toolchains to set up, you can simply `npm install` it - or run it in a browser.
77

8-
By compiling syntactially (not necessarily semantically) valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill.
9-
108
Note, though, that this version of the compiler (0.5.0, NEXT) is relatively new and does not yet support some features a TypeScript programmer might expect, e.g., strings, arrays and classes.
119

1210
See [the AssemblyScript wiki](https://github.com/AssemblyScript/assemblyscript/wiki) for additional information and documentation.
1311

12+
How does it work?
13+
-----------------
14+
15+
By compiling syntactially (not necessarily semantically) valid TypeScript to [Binaryen](https://github.com/WebAssembly/binaryen) IR, the resulting module can be validated, optimized, emitted in WebAssembly text or binary format and converted to [asm.js](http://asmjs.org) as a polyfill.
16+
1417
Examples
1518
--------
1619

@@ -22,7 +25,7 @@ A few early examples to get an idea:
2225
Getting started
2326
---------------
2427

25-
If you'd like to try it today or even plan to contribute, this is how you do it:
28+
This version of the compiler is not on [npm](https://www.npmjs.com/package/assemblyscript), yet, but if you'd like to try it today or even plan to contribute, this is how you do it:
2629

2730
```
2831
$> git clone https://github.com/AssemblyScript/next.git

src/builtins.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { DiagnosticCode } from "./diagnostics";
33
import { Node, Expression } from "./ast";
44
import { Type } from "./types";
55
import { Module, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType, FunctionTypeRef } from "./module";
6-
import { Program, ElementFlags, FunctionPrototype, Local } from "./program";
6+
import { Program, ElementFlags, Element, Global, FunctionPrototype, Local } from "./program";
77

88
/** Initializes the specified program with built-in functions. */
99
export function initialize(program: Program): void {
@@ -35,14 +35,67 @@ export function initialize(program: Program): void {
3535
addFunction(program, "assert");
3636
addFunction(program, "parseInt");
3737
addFunction(program, "parseFloat");
38+
39+
addFunction(program, "i8").members = new Map([
40+
[ "MIN_VALUE", new Global(program, "i8.MIN_VALUE", null, Type.i8).withConstantIntegerValue(-128, -1) ],
41+
[ "MAX_VALUE", new Global(program, "i8.MAX_VALUE", null, Type.i8).withConstantIntegerValue(127, 0) ]
42+
]);
43+
addFunction(program, "i16").members = new Map([
44+
[ "MIN_VALUE", new Global(program, "i16.MIN_VALUE", null, Type.i16).withConstantIntegerValue(-32768, -1) ],
45+
[ "MAX_VALUE", new Global(program, "i16.MAX_VALUE", null, Type.i16).withConstantIntegerValue(32767, 0) ]
46+
]);
47+
addFunction(program, "i32").members = new Map([
48+
[ "MIN_VALUE", new Global(program, "i32.MIN_VALUE", null, Type.i32).withConstantIntegerValue(-2147483648, -1) ],
49+
[ "MAX_VALUE", new Global(program, "i32.MAX_VALUE", null, Type.i32).withConstantIntegerValue(2147483647, 0) ]
50+
]);
51+
addFunction(program, "i64").members = new Map([
52+
[ "MIN_VALUE", new Global(program, "i64.MIN_VALUE", null, Type.i64).withConstantIntegerValue(0, -2147483648) ],
53+
[ "MAX_VALUE", new Global(program, "i64.MAX_VALUE", null, Type.i64).withConstantIntegerValue(-1, 2147483647) ]
54+
]);
55+
addFunction(program, "u8").members = new Map([
56+
[ "MIN_VALUE", new Global(program, "u8.MIN_VALUE", null, Type.u8).withConstantIntegerValue(0, 0) ],
57+
[ "MAX_VALUE", new Global(program, "u8.MAX_VALUE", null, Type.u8).withConstantIntegerValue(255, 0) ]
58+
]);
59+
addFunction(program, "u16").members = new Map([
60+
[ "MIN_VALUE", new Global(program, "u16.MIN_VALUE", null, Type.u16).withConstantIntegerValue(0, 0) ],
61+
[ "MAX_VALUE", new Global(program, "u16.MAX_VALUE", null, Type.u16).withConstantIntegerValue(65535, 0) ]
62+
]);
63+
addFunction(program, "u32").members = new Map([
64+
[ "MIN_VALUE", new Global(program, "u32.MIN_VALUE", null, Type.u32).withConstantIntegerValue(0, 0) ],
65+
[ "MAX_VALUE", new Global(program, "u32.MAX_VALUE", null, Type.u32).withConstantIntegerValue(-1, 0) ]
66+
]);
67+
addFunction(program, "u64").members = new Map([
68+
[ "MIN_VALUE", new Global(program, "u64.MIN_VALUE", null, Type.u64).withConstantIntegerValue(0, 0) ],
69+
[ "MAX_VALUE", new Global(program, "u64.MAX_VALUE", null, Type.i64).withConstantIntegerValue(-1, -1) ]
70+
]);
71+
addFunction(program, "bool").members = new Map([
72+
[ "MIN_VALUE", new Global(program, "bool.MIN_VALUE", null, Type.bool).withConstantIntegerValue(0, 0) ],
73+
[ "MAX_VALUE", new Global(program, "bool.MAX_VALUE", null, Type.bool).withConstantIntegerValue(1, 0) ]
74+
]);
75+
addFunction(program, "f32").members = new Map([
76+
[ "MIN_SAFE_INTEGER", new Global(program, "f32.MIN_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(-16777215) ],
77+
[ "MAX_SAFE_INTEGER", new Global(program, "f32.MAX_SAFE_INTEGER", null, Type.f32).withConstantFloatValue(16777215) ]
78+
]);
79+
addFunction(program, "f64").members = new Map([
80+
[ "MIN_SAFE_INTEGER", new Global(program, "f64.MIN_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(-9007199254740991) ],
81+
[ "MAX_SAFE_INTEGER", new Global(program, "f64.MAX_SAFE_INTEGER", null, Type.f64).withConstantFloatValue(9007199254740991) ]
82+
]);
83+
if (program.target == Target.WASM64) {
84+
program.elements.set("isize", <Element>program.elements.get("i64"));
85+
program.elements.set("usize", <Element>program.elements.get("u64"));
86+
} else {
87+
program.elements.set("isize", <Element>program.elements.get("i32"));
88+
program.elements.set("usize", <Element>program.elements.get("u32"));
89+
}
3890
}
3991

4092
/** Adds a built-in function to the specified program. */
41-
function addFunction(program: Program, name: string, isGeneric: bool = false): void {
42-
let prototype: FunctionPrototype = new FunctionPrototype(program, name, null, null);
93+
function addFunction(program: Program, name: string, isGeneric: bool = false): FunctionPrototype {
94+
let prototype: FunctionPrototype = new FunctionPrototype(program, name, name, null, null);
4395
prototype.isBuiltIn = true;
4496
if (isGeneric) prototype.isGeneric = true;
4597
program.elements.set(name, prototype);
98+
return prototype;
4699
}
47100

48101
/** Compiles a call to a built-in function. */

src/compiler.ts

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ import {
9393
UnaryPrefixExpression,
9494

9595
// utility
96-
hasModifier
96+
hasModifier,
97+
InterfaceDeclaration
9798

9899
} from "./ast";
99100
import {
@@ -179,7 +180,7 @@ export class Compiler extends DiagnosticEmitter {
179180
this.program = program;
180181
this.options = options ? options : new Options();
181182
this.module = this.options.noEmit ? Module.createStub() : Module.create();
182-
const startFunctionTemplate: FunctionPrototype = new FunctionPrototype(program, "start", null);
183+
const startFunctionTemplate: FunctionPrototype = new FunctionPrototype(program, "start", "start", null);
183184
const startFunctionInstance: Function = new Function(startFunctionTemplate, startFunctionTemplate.internalName, [], [], Type.void, null);
184185
this.currentFunction = this.startFunction = startFunctionInstance;
185186
this.memoryOffset = new U64(this.options.target == Target.WASM64 ? 8 : 4, 0); // leave space for `null`
@@ -544,6 +545,7 @@ export class Compiler extends DiagnosticEmitter {
544545
} else {
545546
this.module.addFunction(internalName, typeRef, typesToNativeTypes(instance.additionalLocals), this.module.createBlock(null, <ExpressionRef[]>stmts, NativeType.None));
546547
}
548+
instance.finalize();
547549
return true;
548550
}
549551

@@ -561,6 +563,11 @@ export class Compiler extends DiagnosticEmitter {
561563
this.compileClassDeclaration(<ClassDeclaration>member, []);
562564
break;
563565

566+
case NodeKind.INTERFACE:
567+
if ((noTreeShaking || hasModifier(ModifierKind.EXPORT, (<InterfaceDeclaration>member).modifiers)) && !(<InterfaceDeclaration>member).typeParameters.length)
568+
this.compileInterfaceDeclaration(<InterfaceDeclaration>member, []);
569+
break;
570+
564571
case NodeKind.ENUM:
565572
if (noTreeShaking || hasModifier(ModifierKind.EXPORT, (<EnumDeclaration>member).modifiers))
566573
this.compileEnumDeclaration(<EnumDeclaration>member);
@@ -684,6 +691,10 @@ export class Compiler extends DiagnosticEmitter {
684691
throw new Error("not implemented");
685692
}
686693

694+
compileInterfaceDeclaration(declaration: InterfaceDeclaration, typeArguments: TypeNode[], contextualTypeArguments: Map<string,Type> | null = null, alternativeReportNode: Node | null = null): void {
695+
throw new Error("not implemented");
696+
}
697+
687698
// memory
688699

689700
/** Adds a static memory segment with the specified data. */
@@ -1896,30 +1907,6 @@ export class Compiler extends DiagnosticEmitter {
18961907
let expr: ExpressionRef;
18971908
switch (target.kind) {
18981909

1899-
case ElementKind.ENUM:
1900-
case ElementKind.CLASS_PROTOTYPE:
1901-
case ElementKind.CLASS:
1902-
case ElementKind.NAMESPACE:
1903-
if (target.members) {
1904-
element = target.members.get(propertyName);
1905-
if (!element) {
1906-
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
1907-
return this.module.createUnreachable();
1908-
}
1909-
1910-
// handle enum values right away
1911-
if (element.kind == ElementKind.ENUMVALUE) {
1912-
this.currentType = Type.i32;
1913-
return (<EnumValue>element).hasConstantValue
1914-
? this.module.createI32((<EnumValue>element).constantValue)
1915-
: this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
1916-
}
1917-
} else {
1918-
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
1919-
return this.module.createUnreachable();
1920-
}
1921-
break;
1922-
19231910
case ElementKind.LOCAL:
19241911
element = (<Local>target).type.classType;
19251912
if (!element) {
@@ -1941,7 +1928,25 @@ export class Compiler extends DiagnosticEmitter {
19411928
break;
19421929

19431930
default:
1944-
throw new Error("unexpected target kind");
1931+
if (target.members) {
1932+
element = target.members.get(propertyName);
1933+
if (!element) {
1934+
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
1935+
return this.module.createUnreachable();
1936+
}
1937+
1938+
// handle enum values right away
1939+
if (element.kind == ElementKind.ENUMVALUE) {
1940+
this.currentType = Type.i32;
1941+
return (<EnumValue>element).hasConstantValue
1942+
? this.module.createI32((<EnumValue>element).constantValue)
1943+
: this.module.createGetGlobal((<EnumValue>element).internalName, NativeType.I32);
1944+
}
1945+
} else {
1946+
this.error(DiagnosticCode.Property_0_does_not_exist_on_type_1, propertyAccess.property.range, propertyName);
1947+
return this.module.createUnreachable();
1948+
}
1949+
break;
19451950
}
19461951

19471952
// handle the element
@@ -1951,8 +1956,18 @@ export class Compiler extends DiagnosticEmitter {
19511956
return this.module.createGetLocal((<Local>element).index, typeToNativeType(this.currentType = (<Local>element).type));
19521957

19531958
case ElementKind.GLOBAL:
1954-
this.compileGlobal(<Global>element);
1955-
return this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType = <Type>(<Global>element).type));
1959+
if (!this.compileGlobal(<Global>element))
1960+
return this.module.createUnreachable();
1961+
this.currentType = <Type>(<Global>element).type;
1962+
if ((<Global>element).hasConstantValue)
1963+
return this.currentType== Type.f32
1964+
? this.module.createF32((<Global>element).constantFloatValue)
1965+
: this.currentType == Type.f64
1966+
? this.module.createF64((<Global>element).constantFloatValue)
1967+
: this.currentType.isLongInteger
1968+
? this.module.createI64((<I64>(<Global>element).constantIntegerValue).lo, (<I64>(<Global>element).constantIntegerValue).hi)
1969+
: this.module.createI32((<I64>(<Global>element).constantIntegerValue).lo);
1970+
return this.module.createGetGlobal((<Global>element).internalName, typeToNativeType(this.currentType));
19561971

19571972
case ElementKind.FUNCTION: // getter
19581973
if (!(<Function>element).prototype.isGetter) {

src/decompiler.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ export class Decompiler {
4747
this.push("(");
4848
let k: Index = _BinaryenFunctionGetNumParams(func);
4949
for (let i: Index = 0; i < k; ++i) {
50-
console.log("rat");
5150
if (i > 0)
5251
this.push(", ");
5352
this.push("$");

0 commit comments

Comments
 (0)