Skip to content

Commit 017efc7

Browse files
committed
Fixes; Builtins; Testing in the interpreter
1 parent 032ae37 commit 017efc7

33 files changed

+791
-68
lines changed

β€ŽREADME.mdβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ AssemblyScript NEXT
33

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

6-
This repository contains compiler component prototypes for the next iteration of the AssemblyScript compiler written in AssemblyScript itself.
6+
This repository contains compiler components for the next iteration of the AssemblyScript compiler written in AssemblyScript itself.
77

88
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.
99

β€Žassembly.d.tsβ€Ž

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ declare type f64 = number;
3030
// builtins
3131

3232
/** Performs the sign-agnostic count leading zero bits operation on a 32-bit or 64-bit integer. All zero bits are considered leading if the value is zero. */
33-
declare function clz<T>(value: T): T;
33+
declare function clz<T extends number>(value: T): T;
3434
/** Performs the sign-agnostic count tailing zero bits operation on a 32-bit or 64-bit integer. All zero bits are considered trailing if the value is zero. */
3535
declare function ctz<T>(value: T): T;
3636
/** Performs the sign-agnostic count number of one bits operation on a 32-bit or 64-bit integer. */
@@ -84,6 +84,8 @@ declare const Infinity: number;
8484
declare function isNaN<T>(value: T): bool;
8585
/** Tests if a 32-bit or 64-bit float is finite, that is not NaN or +/-Infinity. */
8686
declare function isFinite<T>(value: T): bool;
87+
/** Traps if the specified value is `false`. */
88+
declare function assert(isTrue: bool): void;
8789

8890
// internal decorators
8991

β€Žsrc/compiler.tsβ€Ž

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PATH_DELIMITER } from "./constants";
22
import { DiagnosticCode, DiagnosticMessage, DiagnosticEmitter } from "./diagnostics";
3-
import { Module, MemorySegment, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType, FunctionTypeRef } from "./module";
3+
import { Module, MemorySegment, ExpressionRef, UnaryOp, BinaryOp, HostOp, NativeType, FunctionTypeRef, getExpressionId, ExpressionId } from "./module";
44
import { Program, ClassPrototype, Class, Element, ElementKind, Enum, FunctionPrototype, Function, Global, Local, Namespace, Parameter } from "./program";
55
import { CharCode, I64, U64, normalizePath, sb } from "./util";
66
import { Token, Range } from "./tokenizer";
@@ -286,11 +286,13 @@ export class Compiler extends DiagnosticEmitter {
286286

287287
// globals
288288

289-
compileGlobalDeclaration(declaration: VariableDeclaration, isConst: bool): bool {
289+
compileGlobalDeclaration(declaration: VariableDeclaration, isConst: bool): Global | null {
290290
const element: Element | null = <Element | null>this.program.elements.get(declaration.internalName);
291291
if (!element || element.kind != ElementKind.GLOBAL)
292292
throw new Error("unexpected missing global");
293-
return this.compileGlobal(<Global>element);
293+
return this.compileGlobal(<Global>element)
294+
? <Global>element
295+
: null;
294296
}
295297

296298
compileGlobal(element: Global): bool {
@@ -333,7 +335,7 @@ export class Compiler extends DiagnosticEmitter {
333335
} else if (declaration) {
334336
if (declaration.initializer) {
335337
initializer = this.compileExpression(declaration.initializer, type);
336-
initializeInStart = declaration.initializer.kind != NodeKind.LITERAL; // MVP doesn't support complex initializers
338+
initializeInStart = getExpressionId(initializer) != ExpressionId.Const; // MVP doesn't support complex initializers
337339
} else {
338340
initializer = typeToNativeZero(this.module, type);
339341
initializeInStart = false;
@@ -342,12 +344,14 @@ export class Compiler extends DiagnosticEmitter {
342344
throw new Error("unexpected missing declaration or constant value");
343345
const internalName: string = element.internalName;
344346
if (initializeInStart) {
345-
this.module.addGlobal(internalName, nativeType, true, this.module.createI32(-1));
347+
this.module.addGlobal(internalName, nativeType, true, typeToNativeZero(this.module, type));
346348
this.startFunctionBody.push(this.module.createSetGlobal(internalName, initializer));
347-
} else
349+
} else {
348350
this.module.addGlobal(internalName, nativeType, element.isMutable, initializer);
349-
// if (element.globalExportName != null && element.hasConstantValue && !initializeInStart)
350-
// this.module.addGlobalExport(element.internalName, element.globalExportName);
351+
if (!element.isMutable) {
352+
// TODO: check export, requires updated binaryen.js with Module#addGlobalExport
353+
}
354+
}
351355
return element.isCompiled = true;
352356
}
353357

@@ -373,7 +377,7 @@ export class Compiler extends DiagnosticEmitter {
373377
let initializeInStart: bool = false;
374378
if (declaration.value) {
375379
initializer = this.compileExpression(<Expression>declaration.value, Type.i32);
376-
initializeInStart = declaration.value.kind != NodeKind.LITERAL; // MVP doesn't support complex initializers
380+
initializeInStart = getExpressionId(initializer) != ExpressionId.Const; // MVP doesn't support complex initializers
377381
} else if (previousInternalName == null) {
378382
initializer = this.module.createI32(0);
379383
initializeInStart = false;
@@ -385,10 +389,12 @@ export class Compiler extends DiagnosticEmitter {
385389
initializeInStart = true;
386390
}
387391
if (initializeInStart) {
388-
this.module.addGlobal(val.internalName, NativeType.I32, true, this.module.createI32(-1));
392+
this.module.addGlobal(val.internalName, NativeType.I32, true, this.module.createI32(0));
389393
this.startFunctionBody.push(this.module.createSetGlobal(val.internalName, initializer));
390-
} else
394+
} else {
391395
this.module.addGlobal(val.internalName, NativeType.I32, false, initializer);
396+
// TODO: check export, requires updated binaryen.js with Module#addGlobalExport
397+
}
392398
} else
393399
throw new Error("unexpected missing declaration or constant value");
394400
previousInternalName = val.internalName;
@@ -1183,6 +1189,20 @@ export class Compiler extends DiagnosticEmitter {
11831189
this.currentType = Type.bool;
11841190
break;
11851191

1192+
case Token.EXCLAMATION_EQUALS:
1193+
case Token.EXCLAMATION_EQUALS_EQUALS:
1194+
left = this.compileExpression(expression.left, contextualType, ConversionKind.NONE);
1195+
right = this.compileExpression(expression.right, this.currentType);
1196+
op = this.currentType == Type.f32
1197+
? BinaryOp.NeF32
1198+
: this.currentType == Type.f64
1199+
? BinaryOp.NeF64
1200+
: this.currentType.isLongInteger
1201+
? BinaryOp.NeI64
1202+
: BinaryOp.NeI32;
1203+
this.currentType = Type.bool;
1204+
break;
1205+
11861206
case Token.EQUALS:
11871207
return this.compileAssignment(expression.left, expression.right, contextualType);
11881208

@@ -1544,7 +1564,7 @@ export class Compiler extends DiagnosticEmitter {
15441564
return this.module.createHost(HostOp.CurrentMemory);
15451565

15461566
case "grow_memory":
1547-
this.warning(DiagnosticCode.Operation_is_unsafe, reportNode.range); // unsure
1567+
// this.warning(DiagnosticCode.Operation_is_unsafe, reportNode.range); // unsure
15481568
return this.module.createHost(HostOp.GrowMemory, null, operands);
15491569

15501570
case "unreachable":
@@ -1566,7 +1586,7 @@ export class Compiler extends DiagnosticEmitter {
15661586
tempLocal = this.currentFunction.addLocal(Type.f32);
15671587
return this.module.createBinary(BinaryOp.NeF32,
15681588
this.module.createTeeLocal(tempLocal.index, operands[0]),
1569-
this.module.createGetLocal(tempLocal.index, NativeType.F64)
1589+
this.module.createGetLocal(tempLocal.index, NativeType.F32)
15701590
);
15711591
}
15721592
break;
@@ -1604,6 +1624,12 @@ export class Compiler extends DiagnosticEmitter {
16041624
);
16051625
}
16061626
break;
1627+
1628+
case "assert":
1629+
return this.module.createIf(
1630+
this.module.createUnary(UnaryOp.EqzI32, operands[0]),
1631+
this.module.createUnreachable()
1632+
);
16071633
}
16081634
this.error(DiagnosticCode.Operation_not_supported, reportNode.range);
16091635
return this.module.createUnreachable();

β€Žsrc/diagnostics.tsβ€Ž

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Range } from "./ast";
2-
import { isLineBreak, sb } from "./util";
2+
import { CharCode, isLineBreak, sb } from "./util";
33
import { DiagnosticCode, diagnosticCodeToString } from "./diagnosticMessages.generated";
44

55
export { DiagnosticCode, diagnosticCodeToString } from "./diagnosticMessages.generated";
@@ -100,9 +100,9 @@ export function formatDiagnosticMessage(message: DiagnosticMessage, useColors: b
100100
sb.push("\n");
101101
let pos: i32 = range.start;
102102
let line: i32 = 1;
103-
let column: i32 = 0;
103+
let column: i32 = 1;
104104
while (pos-- > 0)
105-
if (isLineBreak(text.charCodeAt(pos)))
105+
if (text.charCodeAt(pos) == CharCode.LINEFEED)
106106
line++;
107107
else if (line == 1)
108108
column++;

β€Žsrc/module.tsβ€Ž

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,10 @@ export class Module {
613613
return _BinaryenModuleValidate(this.ref) == 1;
614614
}
615615

616+
interpret(): void {
617+
return _BinaryenModuleInterpret(this.ref);
618+
}
619+
616620
toBinary(): Uint8Array {
617621
throw new Error("not implemented");
618622
}
@@ -726,6 +730,10 @@ export class Relooper {
726730
}
727731
}
728732

733+
// export function setAPITracing(on: bool): void {
734+
// _BinaryenSetAPITracing(on ? 1 : 0);
735+
// }
736+
729737
// helpers
730738
// can't do stack allocation here: STACKTOP is a global in WASM but a hidden variable in asm.js
731739

β€Žsrc/program.tsβ€Ž

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,6 +1131,7 @@ function initializeBuiltins(program: Program): void {
11311131

11321132
const genericInt: Type[] = [ Type.i32, Type.i64 ];
11331133
const genericFloat: Type[] = [ Type.f32, Type.f64 ];
1134+
const usize: Type = program.target == Target.WASM64 ? Type.usize64 : Type.usize32;
11341135

11351136
addGenericUnaryBuiltin(program, "clz", genericInt);
11361137
addGenericUnaryBuiltin(program, "ctz", genericInt);
@@ -1140,20 +1141,21 @@ function initializeBuiltins(program: Program): void {
11401141

11411142
addGenericUnaryBuiltin(program, "abs", genericFloat);
11421143
addGenericUnaryBuiltin(program, "ceil", genericFloat);
1143-
addGenericUnaryBuiltin(program, "copysign", genericFloat);
1144+
addGenericBinaryBuiltin(program, "copysign", genericFloat);
11441145
addGenericUnaryBuiltin(program, "floor", genericFloat);
11451146
addGenericBinaryBuiltin(program, "max", genericFloat);
11461147
addGenericBinaryBuiltin(program, "min", genericFloat);
11471148
addGenericUnaryBuiltin(program, "nearest", genericFloat);
11481149
addGenericUnaryBuiltin(program, "sqrt", genericFloat);
11491150
addGenericUnaryBuiltin(program, "trunc", genericFloat);
11501151

1151-
addBuiltin(program, "current_memory", [], Type.i32);
1152-
addBuiltin(program, "grow_memory", [ Type.i32 ], Type.i32);
1152+
addBuiltin(program, "current_memory", [], usize);
1153+
addBuiltin(program, "grow_memory", [ usize ], usize);
11531154
addBuiltin(program, "unreachable", [], Type.void);
11541155

11551156
addGenericUnaryTestBuiltin(program, "isNaN", genericFloat);
11561157
addGenericUnaryTestBuiltin(program, "isFinite", genericFloat);
1158+
addBuiltin(program, "assert", [ Type.bool ], Type.void);
11571159

11581160
// TODO: load, store, sizeof
11591161
// sizeof, for example, has varying Ts but really shouldn't provide an instance for each class
@@ -1167,7 +1169,8 @@ function addBuiltin(program: Program, name: string, parameterTypes: Type[], retu
11671169
const parameters: Parameter[] = new Array(k);
11681170
for (let i: i32 = 0; i < k; ++i)
11691171
parameters[i] = new Parameter("arg" + i, parameterTypes[i], null);
1170-
prototype.instances.set("", new Function(prototype, name, [], parameters, Type.bool, null));
1172+
prototype.instances.set("", new Function(prototype, name, [], parameters, returnType, null));
1173+
program.elements.set(name, prototype);
11711174
}
11721175

11731176
function addGenericUnaryBuiltin(program: Program, name: string, types: Type[]): void {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// <reference path="../assembly.d.ts" />
1+
/// <reference path="../../assembly.d.ts" />
22

33
@global()
44
class Array<T> {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// <reference path="../assembly.d.ts" />
1+
/// <reference path="../../assembly.d.ts" />
22

33
@global()
44
class Error {

std/map.ts renamed to std/impl/map.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// <reference path="../assembly.d.ts" />
1+
/// <reference path="../../assembly.d.ts" />
22

33
@global()
44
class Map<K,V> {

β€Žstd/impl/math.tsβ€Ž

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// <reference path="../../assembly.d.ts" />
2+
3+
@global()
4+
class Math {
5+
}

0 commit comments

Comments
Β (0)