Fix compilation of immediate called function expressions

This commit is contained in:
dcodeIO 2018-03-12 22:34:40 +01:00
parent c93f0bb1fe
commit 7ee6e1cf7b
8 changed files with 92 additions and 19 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -31,6 +31,7 @@ import {
Field,
FunctionPrototype,
Function,
FunctionTarget,
Global,
Local,
Namespace,
@ -3876,8 +3877,9 @@ export class Compiler extends DiagnosticEmitter {
}
}
case ElementKind.FIELD: {
if (signature = (<Field>element).type.functionType) {
let targetExpr = this.compileExpression(assert(resolved.targetExpression), Type.u32);
let type = (<Field>element).type;
if (signature = type.functionType) {
let targetExpr = this.compileExpression(assert(resolved.targetExpression), type);
indexArg = this.module.createLoad(
4,
false,
@ -3894,9 +3896,12 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createUnreachable();
}
}
case ElementKind.PROPERTY: {
// TODO
case ElementKind.FUNCTION_TARGET: {
signature = (<FunctionTarget>element).signature;
indexArg = this.compileExpression(expression.expression, (<FunctionTarget>element).type);
break;
}
case ElementKind.PROPERTY: // TODO
// not supported
default: {

View File

@ -1774,10 +1774,15 @@ export class Program extends DiagnosticEmitter {
if (!resolvedElement) resolvedElement = new ResolvedElement();
return resolvedElement.set(classType);
} else {
let functionType = returnType.functionType;
if (functionType) {
// TODO: Signatures aren't elements but probably should be
throw new Error("not implemented");
let signature = returnType.functionType;
if (signature) {
let functionTarget = signature.cachedFunctionTarget;
if (!functionTarget) {
functionTarget = new FunctionTarget(this, signature);
signature.cachedFunctionTarget = functionTarget;
}
if (!resolvedElement) resolvedElement = new ResolvedElement();
return resolvedElement.set(functionTarget);
}
}
}
@ -1846,6 +1851,8 @@ export enum ElementKind {
FUNCTION_PROTOTYPE,
/** A {@link Function}. */
FUNCTION,
/** A {@link FunctionTarget}. */
FUNCTION_TARGET,
/** A {@link ClassPrototype}. */
CLASS_PROTOTYPE,
/** A {@link Class}. */
@ -2671,6 +2678,27 @@ export class Function extends Element {
toString(): string { return this.prototype.simpleName; }
}
/** A resolved function table entry, that is an function called by an index and signature. */
export class FunctionTarget extends Element {
kind = ElementKind.FUNCTION_TARGET;
/** Underlying signature. */
signature: Signature;
/** Function type. */
type: Type;
/** Constructs a new function target. */
constructor(program: Program, signature: Signature) {
super(program, "", "");
var simpleName = signature.toSignatureString();
this.simpleName = simpleName;
this.internalName = simpleName;
this.signature = signature;
this.type = Type.u32.asFunction(signature);
}
}
/** A yet unresolved instance field prototype. */
export class FieldPrototype extends Element {

View File

@ -1,5 +1,6 @@
import {
Class
Class,
FunctionTarget
} from "./program";
import {
@ -452,6 +453,8 @@ export class Signature {
thisType: Type | null;
/** Whether the last parameter is a rest parameter. */
hasRest: bool;
/** Cached {@link FunctionTarget}. */
cachedFunctionTarget: FunctionTarget | null = null;
constructor(
parameterTypes: Type[] | null = null,

View File

@ -2,11 +2,12 @@
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $III (func (param i64 i64) (result i64)))
(type $FFF (func (param f64 f64) (result f64)))
(type $v (func))
(global $function-types/i32Adder (mut i32) (i32.const 0))
(global $function-types/i64Adder (mut i32) (i32.const 0))
(table 2 2 anyfunc)
(elem (i32.const 0) $function-types/makeAdder<i32>~anonymous|0 $function-types/makeAdder<i64>~anonymous|1)
(table 3 3 anyfunc)
(elem (i32.const 0) $function-types/makeAdder<i32>~anonymous|0 $function-types/makeAdder<i64>~anonymous|1 $function-types/makeAdder<f64>~anonymous|2)
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -28,7 +29,16 @@
(func $function-types/makeAdder<i64> (; 3 ;) (type $i) (result i32)
(i32.const 1)
)
(func $start (; 4 ;) (type $v)
(func $function-types/makeAdder<f64>~anonymous|2 (; 4 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
(f64.add
(get_local $0)
(get_local $1)
)
)
(func $function-types/makeAdder<f64> (; 5 ;) (type $i) (result i32)
(i32.const 2)
)
(func $start (; 6 ;) (type $v)
(set_global $function-types/i32Adder
(call $function-types/makeAdder<i32>)
)
@ -49,5 +59,12 @@
(get_global $function-types/i64Adder)
)
)
(drop
(call_indirect (type $FFF)
(f64.const 1)
(f64.const 2)
(call $function-types/makeAdder<f64>)
)
)
)
)

View File

@ -12,5 +12,4 @@ i32Adder(1, 2);
var i64Adder = makeAdder<i64>();
i64Adder(1, 2);
// TODO:
// makeAdder<f64>()(1, 2);
makeAdder<f64>()(1, 2);

View File

@ -2,12 +2,13 @@
(type $i (func (result i32)))
(type $iii (func (param i32 i32) (result i32)))
(type $III (func (param i64 i64) (result i64)))
(type $FFF (func (param f64 f64) (result f64)))
(type $v (func))
(global $function-types/i32Adder (mut i32) (i32.const 0))
(global $function-types/i64Adder (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 4))
(table 2 2 anyfunc)
(elem (i32.const 0) $function-types/makeAdder<i32>~anonymous|0 $function-types/makeAdder<i64>~anonymous|1)
(table 3 3 anyfunc)
(elem (i32.const 0) $function-types/makeAdder<i32>~anonymous|0 $function-types/makeAdder<i64>~anonymous|1 $function-types/makeAdder<f64>~anonymous|2)
(memory $0 1)
(export "memory" (memory $0))
(start $start)
@ -37,7 +38,20 @@
(i32.const 1)
)
)
(func $start (; 4 ;) (type $v)
(func $function-types/makeAdder<f64>~anonymous|2 (; 4 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
(return
(f64.add
(get_local $0)
(get_local $1)
)
)
)
(func $function-types/makeAdder<f64> (; 5 ;) (type $i) (result i32)
(return
(i32.const 2)
)
)
(func $start (; 6 ;) (type $v)
(nop)
(set_global $function-types/i32Adder
(call $function-types/makeAdder<i32>)
@ -59,5 +73,12 @@
(get_global $function-types/i64Adder)
)
)
(drop
(call_indirect (type $FFF)
(f64.const 1)
(f64.const 2)
(call $function-types/makeAdder<f64>)
)
)
)
)