Skip to content

Commit 02dce5a

Browse files
committed
Add importMemory option to asc, see AssemblyScript#36
1 parent 56bc1be commit 02dce5a

12 files changed

+158
-70
lines changed

bin/asc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ exports.main = function main(argv, options, callback) {
277277
assemblyscript.setNoTreeShaking(compilerOptions, !!args.noTreeShaking);
278278
assemblyscript.setNoAssert(compilerOptions, !!args.noAssert);
279279
assemblyscript.setNoMemory(compilerOptions, !!args.noMemory);
280+
assemblyscript.setImportMemory(compilerOptions, !!args.importMemory);
280281
assemblyscript.setMemoryBase(compilerOptions, args.memoryBase >>> 0);
281282
assemblyscript.setSourceMap(compilerOptions, args.sourceMap != null);
282283

bin/asc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@
8989
"desc": "Does not set up a memory. Useful for low-level WebAssembly.",
9090
"type": "boolean"
9191
},
92+
"importMemory": {
93+
"desc": "Imports the memory instance provided by the embedder.",
94+
"type": "boolean"
95+
},
9296
"memoryBase": {
9397
"desc": "Sets the start offset of compiler-generated static memory.",
9498
"type": "number"

dist/asc.js

Lines changed: 2 additions & 2 deletions
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/compiler.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ export class Options {
132132
noAssert: bool = false;
133133
/** If true, does not set up a memory. */
134134
noMemory: bool = false;
135+
/** If true, imports the memory provided by the embedder. */
136+
importMemory: bool = false;
135137
/** Static memory start offset. */
136138
memoryBase: u32 = 0;
137139
/** Memory allocation implementation to use. */
@@ -299,6 +301,11 @@ export class Compiler extends DiagnosticEmitter {
299301
);
300302
}
301303

304+
// import memory if requested
305+
if (this.options.importMemory) {
306+
this.module.addMemoryImport("memory", "env", "memory");
307+
}
308+
302309
// set up function table
303310
if (k = this.functionTable.length) {
304311
var entries = new Array<FunctionRef>(k);
@@ -2030,6 +2037,16 @@ export class Compiler extends DiagnosticEmitter {
20302037
return expr;
20312038
}
20322039

2040+
/** Computes the common compatible type of two types. Returns `null` if incompatible. */
2041+
computeCommonType(leftType: Type, rightType: Type): Type | null {
2042+
if (leftType.isAssignableTo(rightType)) {
2043+
return rightType;
2044+
} else if (rightType.isAssignableTo(leftType)) {
2045+
return leftType;
2046+
}
2047+
return null;
2048+
}
2049+
20332050
compileAssertionExpression(expression: AssertionExpression, contextualType: Type): ExpressionRef {
20342051
var toType = this.program.resolveType( // reports
20352052
expression.toType,
@@ -2046,6 +2063,38 @@ export class Compiler extends DiagnosticEmitter {
20462063
): ExpressionRef {
20472064
var left: ExpressionRef;
20482065
var right: ExpressionRef;
2066+
2067+
// TODO: Currently, the common type of any binary expression is the first operand's type. This
2068+
// differs from C and other languages where comparing an int to a long, in this order, upcasts
2069+
// left to a long before comparison, instead of failing when trying to downcast right to an int.
2070+
// NOTE that if we change the current behaviour, some examples, tests and wiki pages will have
2071+
// to be updated, while compound binary operations must retain the previous behavior.
2072+
2073+
// var left = this.compileExpression(
2074+
// expression.left,
2075+
// contextualType == Type.void
2076+
// ? Type.i32
2077+
// : contextualType,
2078+
// ConversionKind.NONE
2079+
// );
2080+
// var leftType = this.currentType;
2081+
// var right = this.compileExpression(
2082+
// expression.right,
2083+
// leftType,
2084+
// ConversionKind.NONE
2085+
// );
2086+
// var rightType = this.currentType;
2087+
// var commonType = this.computeCommonType(leftType, rightType);
2088+
// if (!commonType) {
2089+
// this.error(
2090+
// DiagnosticCode.Operator_0_cannot_be_applied_to_types_1_and_2,
2091+
// expression.range,
2092+
// Token.operatorToString(expression.operator), leftType.toString(), rightType.toString()
2093+
// );
2094+
// this.currentType = contextualType;
2095+
// return this.module.createUnreachable();
2096+
// }
2097+
20492098
var condition: ExpressionRef;
20502099
var expr: ExpressionRef;
20512100

@@ -3828,6 +3877,8 @@ export class Compiler extends DiagnosticEmitter {
38283877
var instance = this.compileFunctionUsingTypeArguments(prototype, [], null, declaration);
38293878
if (!instance) return this.module.createUnreachable();
38303879
this.currentType = Type.u32.asFunction(instance);
3880+
// NOTE that, in order to make this work in every case, the function must be represented by a
3881+
// value, so we add it and rely on the optimizer to figure out where it can be called directly.
38313882
var index = this.addFunctionTableEntry(instance);
38323883
if (index < 0) return this.module.createUnreachable();
38333884
return this.module.createI32(index);

src/diagnosticMessages.generated.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,11 +80,13 @@ export enum DiagnosticCode {
8080
A_function_whose_declared_type_is_not_void_must_return_a_value = 2355,
8181
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357,
8282
The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access = 2364,
83+
Operator_0_cannot_be_applied_to_types_1_and_2 = 2365,
8384
_get_and_set_accessor_must_have_the_same_type = 2380,
8485
Constructor_implementation_is_missing = 2390,
8586
Function_implementation_is_missing_or_not_immediately_following_the_declaration = 2391,
8687
Multiple_constructor_implementations_are_not_allowed = 2392,
8788
Duplicate_function_implementation = 2393,
89+
The_0_operator_cannot_be_applied_to_type_1 = 2469,
8890
Export_declaration_conflicts_with_exported_declaration_of_0 = 2484,
8991
Cannot_assign_to_0_because_it_is_a_constant_or_a_read_only_property = 2540,
9092
The_target_of_an_assignment_must_be_a_variable_or_a_property_access = 2541,
@@ -177,11 +179,13 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
177179
case 2355: return "A function whose declared type is not 'void' must return a value.";
178180
case 2357: return "The operand of an increment or decrement operator must be a variable or a property access.";
179181
case 2364: return "The left-hand side of an assignment expression must be a variable or a property access.";
182+
case 2365: return "Operator '{0}' cannot be applied to types '{1}' and '{2}'.";
180183
case 2380: return "'get' and 'set' accessor must have the same type.";
181184
case 2390: return "Constructor implementation is missing.";
182185
case 2391: return "Function implementation is missing or not immediately following the declaration.";
183186
case 2392: return "Multiple constructor implementations are not allowed.";
184187
case 2393: return "Duplicate function implementation.";
188+
case 2469: return "The '{0}' operator cannot be applied to type '{1}'.";
185189
case 2484: return "Export declaration conflicts with exported declaration of '{0}'.";
186190
case 2540: return "Cannot assign to '{0}' because it is a constant or a read-only property.";
187191
case 2541: return "The target of an assignment must be a variable or a property access.";

src/diagnosticMessages.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,13 @@
7979
"A function whose declared type is not 'void' must return a value.": 2355,
8080
"The operand of an increment or decrement operator must be a variable or a property access.": 2357,
8181
"The left-hand side of an assignment expression must be a variable or a property access.": 2364,
82+
"Operator '{0}' cannot be applied to types '{1}' and '{2}'.": 2365,
8283
"'get' and 'set' accessor must have the same type.": 2380,
8384
"Constructor implementation is missing.": 2390,
8485
"Function implementation is missing or not immediately following the declaration.": 2391,
8586
"Multiple constructor implementations are not allowed.": 2392,
8687
"Duplicate function implementation.": 2393,
88+
"The '{0}' operator cannot be applied to type '{1}'.": 2469,
8789
"Export declaration conflicts with exported declaration of '{0}'.": 2484,
8890
"Cannot assign to '{0}' because it is a constant or a read-only property.": 2540,
8991
"The target of an assignment must be a variable or a property access.": 2541,

src/diagnostics.ts

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@ export class DiagnosticMessage {
6262
code: DiagnosticCode,
6363
category: DiagnosticCategory,
6464
arg0: string | null = null,
65-
arg1: string | null = null
65+
arg1: string | null = null,
66+
arg2: string | null = null
6667
): DiagnosticMessage {
6768
var message = diagnosticCodeToString(code);
6869
if (arg0 != null) message = message.replace("{0}", arg0);
6970
if (arg1 != null) message = message.replace("{1}", arg1);
71+
if (arg2 != null) message = message.replace("{2}", arg2);
7072
return new DiagnosticMessage(code, category, message);
7173
}
7274

@@ -211,23 +213,42 @@ export abstract class DiagnosticEmitter {
211213
category: DiagnosticCategory,
212214
range: Range,
213215
arg0: string | null = null,
214-
arg1: string | null = null
216+
arg1: string | null = null,
217+
arg2: string | null = null
215218
) {
216-
var message = DiagnosticMessage.create(code, category, arg0, arg1).withRange(range);
219+
var message = DiagnosticMessage.create(code, category, arg0, arg1, arg2).withRange(range);
217220
this.diagnostics.push(message);
218221
// console.log(formatDiagnosticMessage(message, true, true) + "\n"); // temporary
219222
// console.log(<string>new Error("stack").stack);
220223
}
221224

222-
error(code: DiagnosticCode, range: Range, arg0: string | null = null, arg1: string | null = null): void {
223-
this.emitDiagnostic(code, DiagnosticCategory.ERROR, range, arg0, arg1);
225+
error(
226+
code: DiagnosticCode,
227+
range: Range,
228+
arg0: string | null = null,
229+
arg1: string | null = null,
230+
arg2: string | null = null
231+
): void {
232+
this.emitDiagnostic(code, DiagnosticCategory.ERROR, range, arg0, arg1, arg2);
224233
}
225234

226-
info(code: DiagnosticCode, range: Range, arg0: string | null = null, arg1: string | null = null): void {
227-
this.emitDiagnostic(code, DiagnosticCategory.INFO, range, arg0, arg1);
235+
info(
236+
code: DiagnosticCode,
237+
range: Range,
238+
arg0: string | null = null,
239+
arg1: string | null = null,
240+
arg2: string | null = null
241+
): void {
242+
this.emitDiagnostic(code, DiagnosticCategory.INFO, range, arg0, arg1, arg2);
228243
}
229244

230-
warning(code: DiagnosticCode, range: Range, arg0: string | null = null, arg1: string | null = null): void {
231-
this.emitDiagnostic(code, DiagnosticCategory.WARNING, range, arg0, arg1);
245+
warning(
246+
code: DiagnosticCode,
247+
range: Range,
248+
arg0: string | null = null,
249+
arg1: string | null = null,
250+
arg2: string | null = null
251+
): void {
252+
this.emitDiagnostic(code, DiagnosticCategory.WARNING, range, arg0, arg1, arg2);
232253
}
233254
}

src/extra/ast.ts

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ export function serializeAssertionExpression(node: AssertionExpression, sb: stri
373373
export function serializeBinaryExpression(node: BinaryExpression, sb: string[]): void {
374374
serializeExpression(node.left, sb);
375375
sb.push(" ");
376-
sb.push(operatorToString(node.operator));
376+
sb.push(Token.operatorToString(node.operator));
377377
sb.push(" ");
378378
serializeExpression(node.right, sb);
379379
}
@@ -613,11 +613,11 @@ export function serializeUnaryExpression(node: UnaryExpression, sb: string[]): v
613613

614614
export function serializeUnaryPostfixExpression(node: UnaryPostfixExpression, sb: string[]): void {
615615
serializeExpression(node.operand, sb);
616-
sb.push(operatorToString(node.operator));
616+
sb.push(Token.operatorToString(node.operator));
617617
}
618618

619619
export function serializeUnaryPrefixExpression(node: UnaryPrefixExpression, sb: string[]): void {
620-
sb.push(operatorToString(node.operator));
620+
sb.push(Token.operatorToString(node.operator));
621621
serializeExpression(node.operand, sb);
622622
}
623623

@@ -1245,60 +1245,6 @@ export function serializeParameter(node: Parameter, sb: string[]): void {
12451245

12461246
// helpers
12471247

1248-
export function operatorToString(token: Token): string {
1249-
switch (token) {
1250-
case Token.DELETE: return "delete";
1251-
case Token.IN: return "in";
1252-
case Token.INSTANCEOF: return "instanceof";
1253-
case Token.NEW: return "new";
1254-
case Token.TYPEOF: return "typeof";
1255-
case Token.VOID: return "void";
1256-
case Token.YIELD: return "yield";
1257-
case Token.DOT_DOT_DOT: return "...";
1258-
case Token.COMMA: return ",";
1259-
case Token.LESSTHAN: return "<";
1260-
case Token.GREATERTHAN: return ">";
1261-
case Token.LESSTHAN_EQUALS: return "<=";
1262-
case Token.GREATERTHAN_EQUALS: return ">=";
1263-
case Token.EQUALS_EQUALS: return "==";
1264-
case Token.EXCLAMATION_EQUALS: return "!=";
1265-
case Token.EQUALS_EQUALS_EQUALS: return "===";
1266-
case Token.EXCLAMATION_EQUALS_EQUALS: return "!==";
1267-
case Token.PLUS: return "+";
1268-
case Token.MINUS: return "-";
1269-
case Token.ASTERISK_ASTERISK: return "**";
1270-
case Token.ASTERISK: return "*";
1271-
case Token.SLASH: return "/";
1272-
case Token.PERCENT: return "%";
1273-
case Token.PLUS_PLUS: return "++";
1274-
case Token.MINUS_MINUS: return "--";
1275-
case Token.LESSTHAN_LESSTHAN: return "<<";
1276-
case Token.GREATERTHAN_GREATERTHAN: return ">>";
1277-
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>";
1278-
case Token.AMPERSAND: return "&";
1279-
case Token.BAR: return "|";
1280-
case Token.CARET: return "^";
1281-
case Token.EXCLAMATION: return "!";
1282-
case Token.TILDE: return "~";
1283-
case Token.AMPERSAND_AMPERSAND: return "&&";
1284-
case Token.BAR_BAR: return "||";
1285-
case Token.EQUALS: return "=";
1286-
case Token.PLUS_EQUALS: return "+=";
1287-
case Token.MINUS_EQUALS: return "-=";
1288-
case Token.ASTERISK_EQUALS: return "*=";
1289-
case Token.ASTERISK_ASTERISK_EQUALS: return "**=";
1290-
case Token.SLASH_EQUALS: return "/=";
1291-
case Token.PERCENT_EQUALS: return "%=";
1292-
case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<=";
1293-
case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>=";
1294-
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>=";
1295-
case Token.AMPERSAND_EQUALS: return "&=";
1296-
case Token.BAR_EQUALS: return "|=";
1297-
case Token.CARET_EQUALS: return "^=";
1298-
default: assert(false); return "";
1299-
}
1300-
}
1301-
13021248
export function modifierToString(node: Modifier): string {
13031249
switch (node.modifierKind) {
13041250
case ModifierKind.ASYNC: return "async";

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ export function setNoMemory(options: Options, noMemory: bool): void {
9292
options.noMemory = noMemory;
9393
}
9494

95+
/** Sets the `importMemory` option. */
96+
export function setImportMemory(options: Options, importMemory: bool): void {
97+
options.importMemory = importMemory;
98+
}
99+
95100
/** Sets the `sourceMap` option. */
96101
export function setSourceMap(options: Options, sourceMap: bool): void {
97102
options.sourceMap = sourceMap;

src/tokenizer.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,60 @@ export namespace Token {
266266
return false;
267267
}
268268
}
269+
270+
export function operatorToString(token: Token): string {
271+
switch (token) {
272+
case Token.DELETE: return "delete";
273+
case Token.IN: return "in";
274+
case Token.INSTANCEOF: return "instanceof";
275+
case Token.NEW: return "new";
276+
case Token.TYPEOF: return "typeof";
277+
case Token.VOID: return "void";
278+
case Token.YIELD: return "yield";
279+
case Token.DOT_DOT_DOT: return "...";
280+
case Token.COMMA: return ",";
281+
case Token.LESSTHAN: return "<";
282+
case Token.GREATERTHAN: return ">";
283+
case Token.LESSTHAN_EQUALS: return "<=";
284+
case Token.GREATERTHAN_EQUALS: return ">=";
285+
case Token.EQUALS_EQUALS: return "==";
286+
case Token.EXCLAMATION_EQUALS: return "!=";
287+
case Token.EQUALS_EQUALS_EQUALS: return "===";
288+
case Token.EXCLAMATION_EQUALS_EQUALS: return "!==";
289+
case Token.PLUS: return "+";
290+
case Token.MINUS: return "-";
291+
case Token.ASTERISK_ASTERISK: return "**";
292+
case Token.ASTERISK: return "*";
293+
case Token.SLASH: return "/";
294+
case Token.PERCENT: return "%";
295+
case Token.PLUS_PLUS: return "++";
296+
case Token.MINUS_MINUS: return "--";
297+
case Token.LESSTHAN_LESSTHAN: return "<<";
298+
case Token.GREATERTHAN_GREATERTHAN: return ">>";
299+
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN: return ">>>";
300+
case Token.AMPERSAND: return "&";
301+
case Token.BAR: return "|";
302+
case Token.CARET: return "^";
303+
case Token.EXCLAMATION: return "!";
304+
case Token.TILDE: return "~";
305+
case Token.AMPERSAND_AMPERSAND: return "&&";
306+
case Token.BAR_BAR: return "||";
307+
case Token.EQUALS: return "=";
308+
case Token.PLUS_EQUALS: return "+=";
309+
case Token.MINUS_EQUALS: return "-=";
310+
case Token.ASTERISK_EQUALS: return "*=";
311+
case Token.ASTERISK_ASTERISK_EQUALS: return "**=";
312+
case Token.SLASH_EQUALS: return "/=";
313+
case Token.PERCENT_EQUALS: return "%=";
314+
case Token.LESSTHAN_LESSTHAN_EQUALS: return "<<=";
315+
case Token.GREATERTHAN_GREATERTHAN_EQUALS: return ">>=";
316+
case Token.GREATERTHAN_GREATERTHAN_GREATERTHAN_EQUALS: return ">>>=";
317+
case Token.AMPERSAND_EQUALS: return "&=";
318+
case Token.BAR_EQUALS: return "|=";
319+
case Token.CARET_EQUALS: return "^=";
320+
default: assert(false); return "";
321+
}
322+
}
269323
}
270324

271325
export class Range {

0 commit comments

Comments
 (0)