Skip to content

Commit 4929fca

Browse files
committed
Move some numeric builtins to stdlib; Minor refactoring
1 parent 6d0b5d9 commit 4929fca

26 files changed

+1990
-1749
lines changed

dist/asc.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/asc.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/assemblyscript.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ast.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,23 +1767,17 @@ export class WhileStatement extends Statement {
17671767
statement: Statement;
17681768
}
17691769

1770-
/** Gets the first decorator by name within at set of decorators, if present. */
1771-
export function getFirstDecorator(name: string, decorators: DecoratorNode[] | null): DecoratorNode | null {
1770+
/** Tests if a specific decorator is present within the specified decorators. */
1771+
export function hasDecorator(name: string, decorators: DecoratorNode[] | null): bool {
17721772
if (decorators) {
17731773
for (let i = 0, k = decorators.length; i < k; ++i) {
1774-
let decorator = decorators[i];
1775-
let expression = decorator.name;
1774+
let expression = decorators[i].name;
17761775
if (expression.kind == NodeKind.IDENTIFIER && (<IdentifierExpression>expression).text == name) {
1777-
return decorator;
1776+
return true;
17781777
}
17791778
}
17801779
}
1781-
return null;
1782-
}
1783-
1784-
/** Tests if a specific decorator is present within the specified decorators. */
1785-
export function hasDecorator(name: string, decorators: DecoratorNode[] | null): bool {
1786-
return getFirstDecorator(name, decorators) != null;
1780+
return false;
17871781
}
17881782

17891783
/** Mangles a declaration's name to an internal name. */

src/builtins.ts

Lines changed: 0 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,6 @@ export function compileGetConstant(
5454
reportNode: Node
5555
): ExpressionRef {
5656
switch (global.internalName) {
57-
case "NaN": { // context-sensitive
58-
if (compiler.currentType == Type.f32) {
59-
return compiler.module.createF32(NaN);
60-
} else {
61-
compiler.currentType = Type.f64;
62-
return compiler.module.createF64(NaN);
63-
}
64-
}
65-
case "Infinity": { // context-sensitive
66-
if (compiler.currentType == Type.f32) {
67-
return compiler.module.createF32(Infinity);
68-
} else {
69-
compiler.currentType = Type.f64;
70-
return compiler.module.createF64(Infinity);
71-
}
72-
}
7357
case "HEAP_BASE": { // never inlined for linking purposes
7458
compiler.currentType = compiler.options.usizeType;
7559
return compiler.module.createGetGlobal("HEAP_BASE", compiler.currentType.toNativeType());
@@ -154,143 +138,6 @@ export function compileCall(
154138

155139
// math
156140

157-
case "isNaN": { // isNaN<T?>(value: T) -> bool
158-
compiler.currentType = Type.bool;
159-
if (operands.length != 1) {
160-
if (typeArguments && typeArguments.length != 1) {
161-
compiler.error(
162-
DiagnosticCode.Expected_0_type_arguments_but_got_1,
163-
reportNode.range, "1", typeArguments.length.toString(10)
164-
);
165-
}
166-
compiler.error(
167-
DiagnosticCode.Expected_0_arguments_but_got_1,
168-
reportNode.range, "1", operands.length.toString(10)
169-
);
170-
return module.createUnreachable();
171-
}
172-
if (typeArguments) {
173-
if (typeArguments.length != 1) {
174-
compiler.error(
175-
DiagnosticCode.Expected_0_type_arguments_but_got_1,
176-
reportNode.range, "1", typeArguments.length.toString(10)
177-
);
178-
return module.createUnreachable();
179-
}
180-
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
181-
} else {
182-
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
183-
}
184-
185-
switch (compiler.currentType.kind) {
186-
case TypeKind.F32: {
187-
ret = module.createBinary(
188-
BinaryOp.GtU32,
189-
module.createBinary(
190-
BinaryOp.AndI32,
191-
module.createUnary(UnaryOp.ReinterpretF32, arg0),
192-
module.createI32(0x7FFFFFFF)
193-
),
194-
module.createI32(0x7F800000)
195-
);
196-
break;
197-
}
198-
case TypeKind.F64: {
199-
ret = module.createBinary(
200-
BinaryOp.GtU64,
201-
module.createBinary(
202-
BinaryOp.AndI64,
203-
module.createUnary(UnaryOp.ReinterpretF64, arg0),
204-
module.createI64(0xFFFFFFFF, 0x7FFFFFFF)
205-
),
206-
module.createI64(0, 0x7FF00000)
207-
);
208-
break;
209-
}
210-
case TypeKind.VOID: {
211-
compiler.error(
212-
DiagnosticCode.Operation_not_supported,
213-
reportNode.range
214-
);
215-
ret = module.createUnreachable();
216-
break;
217-
}
218-
default: { // every other type is never NaN
219-
ret = module.createI32(0);
220-
break;
221-
}
222-
}
223-
compiler.currentType = Type.bool;
224-
return ret;
225-
}
226-
case "isFinite": { // isFinite<T?>(value: T) -> bool
227-
compiler.currentType = Type.bool;
228-
if (operands.length != 1) {
229-
if (typeArguments && typeArguments.length != 1) {
230-
compiler.error(
231-
DiagnosticCode.Expected_0_type_arguments_but_got_1,
232-
reportNode.range, "1", typeArguments.length.toString(10)
233-
);
234-
}
235-
compiler.error(
236-
DiagnosticCode.Expected_0_arguments_but_got_1,
237-
reportNode.range, "1", operands.length.toString(10)
238-
);
239-
return module.createUnreachable();
240-
}
241-
if (typeArguments) {
242-
if (typeArguments.length != 1) {
243-
compiler.error(
244-
DiagnosticCode.Expected_0_type_arguments_but_got_1,
245-
reportNode.range, "1", typeArguments.length.toString(10)
246-
);
247-
return module.createUnreachable();
248-
}
249-
arg0 = compiler.compileExpression(operands[0], typeArguments[0]);
250-
} else {
251-
arg0 = compiler.compileExpression(operands[0], Type.f64, ConversionKind.NONE);
252-
}
253-
switch (compiler.currentType.kind) {
254-
case TypeKind.F32: {
255-
ret = module.createBinary(
256-
BinaryOp.LtU32,
257-
module.createBinary(
258-
BinaryOp.AndI32,
259-
module.createUnary(UnaryOp.ReinterpretF32, arg0),
260-
module.createI32(0x7FFFFFFF)
261-
),
262-
module.createI32(0x7F800000)
263-
);
264-
break;
265-
}
266-
case TypeKind.F64: {
267-
ret = module.createBinary(
268-
BinaryOp.LtU64,
269-
module.createBinary(
270-
BinaryOp.AndI64,
271-
module.createUnary(UnaryOp.ReinterpretF64, arg0),
272-
module.createI64(0xFFFFFFFF, 0x7FFFFFFF)
273-
),
274-
module.createI64(0, 0x7FF00000)
275-
);
276-
break;
277-
}
278-
case TypeKind.VOID: {
279-
compiler.error(
280-
DiagnosticCode.Operation_not_supported,
281-
reportNode.range
282-
);
283-
ret = module.createUnreachable();
284-
break;
285-
}
286-
default: { // every other type is always finite
287-
ret = module.createI32(1);
288-
break;
289-
}
290-
}
291-
compiler.currentType = Type.bool;
292-
return ret;
293-
}
294141
case "clz": { // clz<T?>(value: T) -> T
295142
if (operands.length != 1) {
296143
if (typeArguments) {

src/compiler.ts

Lines changed: 26 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -266,12 +266,10 @@ export class Compiler extends DiagnosticEmitter {
266266
this.startFunction = startFunctionInstance;
267267
this.currentFunction = startFunctionInstance;
268268

269-
// compile entry file(s) while traversing to reachable elements
269+
// compile entry file(s) while traversing reachable elements
270270
var sources = program.sources;
271271
for (let i = 0, k = sources.length; i < k; ++i) {
272-
if (sources[i].isEntry) {
273-
this.compileSource(sources[i]);
274-
}
272+
if (sources[i].isEntry) this.compileSource(sources[i]);
275273
}
276274

277275
// compile the start function if not empty
@@ -326,7 +324,7 @@ export class Compiler extends DiagnosticEmitter {
326324
);
327325
}
328326

329-
// import memory if requested
327+
// import memory if requested (default memory is named '0' by Binaryen)
330328
if (options.importMemory) module.addMemoryImport("0", "env", "memory");
331329

332330
// set up function table
@@ -343,7 +341,7 @@ export class Compiler extends DiagnosticEmitter {
343341
functionTableExported = true;
344342
}
345343

346-
// import table if requested
344+
// import table if requested (default table is named '0' by Binaryen)
347345
if (options.importTable) {
348346
module.addTableImport("0", "env", "table");
349347
if (!functionTableExported) module.addTableExport("0", "table");
@@ -354,6 +352,7 @@ export class Compiler extends DiagnosticEmitter {
354352

355353
// sources
356354

355+
/** Compiles a source by looking it up by path first. */
357356
compileSourceByPath(normalizedPathWithoutExtension: string, reportNode: Node): void {
358357
var source = this.program.lookupSourceByPath(normalizedPathWithoutExtension);
359358
if (!source) {
@@ -366,8 +365,9 @@ export class Compiler extends DiagnosticEmitter {
366365
this.compileSource(source);
367366
}
368367

368+
/** Compiles a source. */
369369
compileSource(source: Source): void {
370-
if (source.is(CommonFlags.COMPILED)) return;
370+
if (source.is(CommonFlags.COMPILED)) return;
371371
source.set(CommonFlags.COMPILED);
372372

373373
// compile top-level statements
@@ -2098,12 +2098,16 @@ export class Compiler extends DiagnosticEmitter {
20982098
)
20992099
: this.module.createI64(0);
21002100
}
2101+
case TypeKind.F64: {
2102+
if (!(element.is(CommonFlags.BUILTIN) && contextualType == Type.f32)) {
2103+
return this.module.createF64((<VariableLikeElement>element).constantFloatValue);
2104+
}
2105+
// otherwise fall-through: basically precomputes f32.demote/f64 of NaN / Infinity
2106+
this.currentType = Type.f32;
2107+
}
21012108
case TypeKind.F32: {
21022109
return this.module.createF32((<VariableLikeElement>element).constantFloatValue);
21032110
}
2104-
case TypeKind.F64: {
2105-
return this.module.createF64((<VariableLikeElement>element).constantFloatValue);
2106-
}
21072111
default: {
21082112
assert(false);
21092113
return this.module.createUnreachable();
@@ -2324,18 +2328,14 @@ export class Compiler extends DiagnosticEmitter {
23242328
expr = module.createUnary(UnaryOp.TruncF32ToI64, expr);
23252329
} else {
23262330
expr = module.createUnary(UnaryOp.TruncF32ToI32, expr);
2327-
if (toType.is(TypeFlags.SMALL)) {
2328-
expr = makeSmallIntegerWrap(expr, toType, module);
2329-
}
2331+
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
23302332
}
23312333
} else {
23322334
if (toType.is(TypeFlags.LONG)) {
23332335
expr = module.createUnary(UnaryOp.TruncF32ToU64, expr);
23342336
} else {
23352337
expr = module.createUnary(UnaryOp.TruncF32ToU32, expr);
2336-
if (toType.is(TypeFlags.SMALL)) {
2337-
expr = makeSmallIntegerWrap(expr, toType, module);
2338-
}
2338+
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
23392339
}
23402340
}
23412341

@@ -2346,18 +2346,14 @@ export class Compiler extends DiagnosticEmitter {
23462346
expr = module.createUnary(UnaryOp.TruncF64ToI64, expr);
23472347
} else {
23482348
expr = module.createUnary(UnaryOp.TruncF64ToI32, expr);
2349-
if (toType.is(TypeFlags.SMALL)) {
2350-
expr = makeSmallIntegerWrap(expr, toType, module);
2351-
}
2349+
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
23522350
}
23532351
} else {
23542352
if (toType.is(TypeFlags.LONG)) {
23552353
expr = module.createUnary(UnaryOp.TruncF64ToU64, expr);
23562354
} else {
23572355
expr = module.createUnary(UnaryOp.TruncF64ToU32, expr);
2358-
if (toType.is(TypeFlags.SMALL)) {
2359-
expr = makeSmallIntegerWrap(expr, toType, module);
2360-
}
2356+
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
23612357
}
23622358
}
23632359
}
@@ -2415,9 +2411,7 @@ export class Compiler extends DiagnosticEmitter {
24152411
// i64 to i32
24162412
if (!toType.is(TypeFlags.LONG)) {
24172413
expr = module.createUnary(UnaryOp.WrapI64, expr); // discards upper bits
2418-
if (toType.is(TypeFlags.SMALL)) {
2419-
expr = makeSmallIntegerWrap(expr, toType, module);
2420-
}
2414+
if (toType.is(TypeFlags.SHORT)) expr = makeSmallIntegerWrap(expr, toType, module);
24212415
}
24222416

24232417
// i32 to i64
@@ -2426,7 +2420,7 @@ export class Compiler extends DiagnosticEmitter {
24262420

24272421
// i32 or smaller to even smaller or same size int with change of sign
24282422
} else if (
2429-
toType.is(TypeFlags.SMALL) &&
2423+
toType.is(TypeFlags.SHORT) &&
24302424
(
24312425
fromType.size > toType.size ||
24322426
(
@@ -4097,7 +4091,7 @@ export class Compiler extends DiagnosticEmitter {
40974091
leftExpr = module.createTeeLocal(tempLocal.index, leftExpr);
40984092
}
40994093

4100-
possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER);
4094+
possiblyOverflows = this.currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER);
41014095
condExpr = makeIsTrueish(leftExpr, this.currentType, module);
41024096

41034097
// simplify when cloning left without side effects was successful
@@ -4143,7 +4137,7 @@ export class Compiler extends DiagnosticEmitter {
41434137
leftExpr = module.createTeeLocal(tempLocal.index, leftExpr);
41444138
}
41454139

4146-
possiblyOverflows = this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if right did
4140+
possiblyOverflows = this.currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER); // if right did
41474141
condExpr = makeIsTrueish(leftExpr, this.currentType, module);
41484142

41494143
// simplify when cloning left without side effects was successful
@@ -4179,7 +4173,7 @@ export class Compiler extends DiagnosticEmitter {
41794173
}
41804174
}
41814175
if (possiblyOverflows && wrapSmallIntegers) {
4182-
assert(this.currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER)); // must be a small int
4176+
assert(this.currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER)); // must be a small int
41834177
expr = makeSmallIntegerWrap(expr, this.currentType, module);
41844178
}
41854179
return compound
@@ -6201,7 +6195,7 @@ export class Compiler extends DiagnosticEmitter {
62016195
}
62026196

62036197
if (possiblyOverflows) {
6204-
assert(currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER));
6198+
assert(currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER));
62056199
setValue = makeSmallIntegerWrap(setValue, currentType, module);
62066200
}
62076201

@@ -6252,7 +6246,7 @@ export class Compiler extends DiagnosticEmitter {
62526246
false // wrapped below
62536247
);
62546248
currentType = this.currentType;
6255-
possiblyOverflows = currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER); // if operand already did
6249+
possiblyOverflows = currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER); // if operand already did
62566250
break;
62576251
}
62586252
case Token.MINUS: {
@@ -6553,7 +6547,7 @@ export class Compiler extends DiagnosticEmitter {
65536547
}
65546548
}
65556549
if (possiblyOverflows && wrapSmallIntegers) {
6556-
assert(currentType.is(TypeFlags.SMALL | TypeFlags.INTEGER));
6550+
assert(currentType.is(TypeFlags.SHORT | TypeFlags.INTEGER));
65576551
expr = makeSmallIntegerWrap(expr, currentType, module);
65586552
}
65596553
return compound

0 commit comments

Comments
 (0)