Skip to content

Commit

Permalink
Infer array type from elements in auto context (AssemblyScript#1021)
Browse files Browse the repository at this point in the history
  • Loading branch information
dcodeIO authored Dec 27, 2019
1 parent fc3ee10 commit 3c59bd4
Show file tree
Hide file tree
Showing 5 changed files with 2,353 additions and 13 deletions.
67 changes: 54 additions & 13 deletions src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7455,17 +7455,33 @@ export class Compiler extends DiagnosticEmitter {
switch (expression.literalKind) {
case LiteralKind.ARRAY: {
assert(!implicitlyNegate);
let classType = contextualType.classReference;
if (classType) {
if (classType.prototype == this.program.arrayPrototype) {
return this.compileArrayLiteral(
assert(classType.typeArguments)[0],
(<ArrayLiteralExpression>expression).elementExpressions,
constraints,
expression
);
let elementExpressions = (<ArrayLiteralExpression>expression).elementExpressions;

// Infer from first element in auto contexts
if (contextualType == Type.auto) {
return this.compileArrayLiteral(
Type.auto,
elementExpressions,
constraints,
expression
);
}

// Use contextual type if an array
if (contextualType.is(TypeFlags.REFERENCE)) {
let classType = contextualType.classReference;
if (classType) {
if (classType.prototype == this.program.arrayPrototype) {
return this.compileArrayLiteral(
assert(classType.typeArguments)[0],
elementExpressions,
constraints,
expression
);
}
}
}

this.error(
DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
expression.range, "T"
Expand Down Expand Up @@ -7544,17 +7560,42 @@ export class Compiler extends DiagnosticEmitter {
var module = this.module;
var program = this.program;
var arrayPrototype = assert(program.arrayPrototype);
var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
var arrayBufferInstance = assert(program.arrayBufferInstance);
var arrayType = arrayInstance.type;
var flow = this.currentFlow;

// block those here so compiling expressions doesn't conflict
var tempThis = flow.getTempLocal(arrayType);
var tempThis = flow.getTempLocal(this.options.usizeType);
var tempDataStart = flow.getTempLocal(arrayBufferInstance.type);

// compile value expressions and find out whether all are constant
// infer common element type in auto contexts
var length = expressions.length;
if (elementType == Type.auto) {
for (let i = 0; i < length; ++i) {
let expression = expressions[i];
if (expression) {
let currentType = this.resolver.resolveExpression(expression, this.currentFlow, elementType);
if (!currentType) return module.unreachable();
if (elementType == Type.auto) elementType = currentType;
else if (currentType != elementType) {
let commonType = Type.commonDenominator(elementType, currentType, false);
if (commonType) elementType = commonType;
// otherwise triggers error further down
}
}
}
if (elementType /* still */ == Type.auto) {
this.error(
DiagnosticCode.The_type_argument_for_type_parameter_0_cannot_be_inferred_from_the_usage_Consider_specifying_the_type_arguments_explicitly,
reportNode.range, "T"
);
return module.unreachable();
}
}

var arrayInstance = assert(this.resolver.resolveClass(arrayPrototype, [ elementType ]));
var arrayType = arrayInstance.type;

// compile value expressions and find out whether all are constant
var values = new Array<ExpressionRef>(length);
var isStatic = true;
var nativeElementType = elementType.toNativeType();
Expand Down
5 changes: 5 additions & 0 deletions tests/compiler/infer-array.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"asc_flags": [
"--runtime none"
]
}
Loading

0 comments on commit 3c59bd4

Please sign in to comment.