Skip to content

Implement resolveBinaryExpression #689

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

bowenwang1996
Copy link
Contributor

An attempt to implement resolveBinaryExpression to further improve the resolver and fix bugs like #625. The function is implemented by resolving to the common denominator of left expression and right expression and then checking operator overloading. However, I noticed that the helper function commonDenominator is not properly implemented and does not resolve to the common superclass of two subclasses, if the two subclasses are different. This limitation can probably be addressed later. For now, expressions like (a + b).toString() can be properly resolved, even if it involves operator overloading.

let right = expression.right;
let leftElement = this.resolveExpression(left, flow, contextualType, reportMode);
if (!leftElement) return null;
let leftType = (<TypedElement>leftElement!).type;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's always a TypedElement, I think resolveExpression should have it as the return type. Unless it's not always one, ofc, which would mean it misses something here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I thought, but what's an example of something that does not resolve to a typedElement?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What can happen there for example is that if an expression referencing a class name is resolved, the element is a static ClassPrototype without a type. The same should be true for function names, because the function can be generic with multiple instances so a FunctionPrototype is returned. There might be others that I forgot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Is it possible to circumvent this by using resolveType here instead of resolveExpression?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resolveType is meant for type nodes exclusively here, so I think it isn't applicable. If I'm not mistaken the resolver should actually return the ClassPrototype respectively FunctionProtoype here (since we want the element), and whatever the caller of resolveExpression is would deal with it appropriately.

if (!rightElement) return null;
let rightType = (<TypedElement>rightElement!).type;
let commonType: Type | null;
if (commonType = Type.commonDenominator(leftType, rightType, true)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some occasions where it doesn't work this way, like for shifts which always prefer the LHS. I think there should be a switch over all possible operators here that mimics what compileExpression etc. do. In this case, binaryOperatorKindFromToken can possibly be incorporated into the switch.

@dcodeIO
Copy link
Member

dcodeIO commented Jun 24, 2019

Thanks for giving this a shot, this is definitely something we have to improve. I'm also currently in the process of doing a cleanup pass over the resolver, and while doing this I figured that your idea for linking basic type classes with their respective basic types is most likely a basic building block here, because this way, every expression being resolved can resolve to a concrete Element. Seems, though, that changing this requires to update the compiler code accordingly.

@jtenner
Copy link
Contributor

jtenner commented Jun 27, 2019

Not sure if this is related, but it looks like binary expressions have a problem :).

  ERROR AS100: Operation not supported.

   assert("ABCDE" == ("a" + "b" + "cde").toUpperCase(), "v8 test 19");
                      ~~~~~~~~~~~~~~~~~
   in std/string.ts(549,19)

Do you think this is fixed here?

@bowenwang1996
Copy link
Contributor Author

Should be. But my fix is not proper. I'll rework it sometime soon

@MaxGraey
Copy link
Member

@bowenwang1996 Thanks for PR but I guess all proposed changes already in master. So I guess we could close this PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants