Fixed a function expression parsing issue

Also uncovered a yet-to-be-fixed issue when immediately calling a returned function
This commit is contained in:
dcodeIO 2018-03-12 19:39:05 +01:00
parent 7870e3ac18
commit c93f0bb1fe
10 changed files with 51 additions and 65 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

@ -124,6 +124,10 @@ export function serializeNode(node: Node, sb: string[]): void {
serializeCallExpression(<CallExpression>node, sb); serializeCallExpression(<CallExpression>node, sb);
break; break;
} }
case NodeKind.COMMA: {
serializeCommaExpression(<CommaExpression>node, sb);
break;
}
case NodeKind.ELEMENTACCESS: { case NodeKind.ELEMENTACCESS: {
serializeElementAccessExpression(<ElementAccessExpression>node, sb); serializeElementAccessExpression(<ElementAccessExpression>node, sb);
break; break;

View File

@ -2810,11 +2810,14 @@ export class Parser extends DiagnosticEmitter {
if (!expr) return null; if (!expr) return null;
var startPos = expr.range.start; var startPos = expr.range.start;
// CallExpression // CallExpression with type arguments
var typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn); // skips '(' on success var typeArguments: CommonTypeNode[] | null;
// there might be better ways to distinguish a LESSTHAN from a CALL with type arguments while (
if (typeArguments || tn.skip(Token.OPENPAREN)) { // there might be better ways to distinguish a LESSTHAN from a CALL with type arguments
var args = this.parseArguments(tn); (typeArguments = this.tryParseTypeArgumentsBeforeArguments(tn)) ||
tn.skip(Token.OPENPAREN)
) {
let args = this.parseArguments(tn);
if (!args) return null; if (!args) return null;
expr = Node.createCallExpression(expr, typeArguments, args, tn.range(startPos, tn.pos)); expr = Node.createCallExpression(expr, typeArguments, args, tn.range(startPos, tn.pos));
} }

View File

@ -1697,16 +1697,18 @@ export class Program extends DiagnosticEmitter {
expression: Expression, expression: Expression,
contextualFunction: Function contextualFunction: Function
): ResolvedElement | null { ): ResolvedElement | null {
var classType: Class | null;
while (expression.kind == NodeKind.PARENTHESIZED) { while (expression.kind == NodeKind.PARENTHESIZED) {
expression = (<ParenthesizedExpression>expression).expression; expression = (<ParenthesizedExpression>expression).expression;
} }
switch (expression.kind) { switch (expression.kind) {
case NodeKind.ASSERTION: { case NodeKind.ASSERTION: {
var type = this.resolveType((<AssertionExpression>expression).toType); // reports let type = this.resolveType((<AssertionExpression>expression).toType); // reports
if (type && (classType = type.classType)) { if (type) {
if (!resolvedElement) resolvedElement = new ResolvedElement(); let classType = type.classType;
return resolvedElement.set(classType); if (classType) {
if (!resolvedElement) resolvedElement = new ResolvedElement();
return resolvedElement.set(classType);
}
} }
return null; return null;
} }
@ -1714,7 +1716,8 @@ export class Program extends DiagnosticEmitter {
throw new Error("not implemented"); throw new Error("not implemented");
} }
case NodeKind.THIS: { // -> Class case NodeKind.THIS: { // -> Class
if (classType = contextualFunction.instanceMethodOf) { let classType = contextualFunction.instanceMethodOf;
if (classType) {
if (!resolvedElement) resolvedElement = new ResolvedElement(); if (!resolvedElement) resolvedElement = new ResolvedElement();
return resolvedElement.set(classType); return resolvedElement.set(classType);
} }
@ -1725,7 +1728,8 @@ export class Program extends DiagnosticEmitter {
return null; return null;
} }
case NodeKind.SUPER: { // -> Class case NodeKind.SUPER: { // -> Class
if ((classType = contextualFunction.instanceMethodOf) && (classType = classType.base)) { let classType = contextualFunction.instanceMethodOf;
if (classType && (classType = classType.base)) {
if (!resolvedElement) resolvedElement = new ResolvedElement(); if (!resolvedElement) resolvedElement = new ResolvedElement();
return resolvedElement.set(classType); return resolvedElement.set(classType);
} }
@ -1751,21 +1755,31 @@ export class Program extends DiagnosticEmitter {
); );
} }
case NodeKind.CALL: { case NodeKind.CALL: {
var resolved = this.resolveExpression( let resolved = this.resolveExpression(
(<CallExpression>expression).expression, (<CallExpression>expression).expression,
contextualFunction contextualFunction
); );
if (resolved) { if (resolved) {
var element = resolved.element; let element = resolved.element;
if (element && element.kind == ElementKind.FUNCTION_PROTOTYPE) { if (element && element.kind == ElementKind.FUNCTION_PROTOTYPE) {
var instance = (<FunctionPrototype>element).resolveUsingTypeArguments( let instance = (<FunctionPrototype>element).resolveUsingTypeArguments(
(<CallExpression>expression).typeArguments, (<CallExpression>expression).typeArguments,
null, null,
expression expression
); );
if (instance && (classType = instance.signature.returnType.classType)) { if (instance) {
if (!resolvedElement) resolvedElement = new ResolvedElement(); let returnType = instance.signature.returnType;
return resolvedElement.set(classType); let classType = returnType.classType;
if (classType) {
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");
}
}
} }
} }
} }

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
a = fn()(1, 2);

View File

@ -0,0 +1 @@
a = fn()(1, 2);