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

View File

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

View File

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

View File

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