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

@ -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: {

@ -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 {

@ -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,

@ -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>)
)
)
)
)

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

@ -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>)
)
)
)
)