-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
extending metatype matching in sigmatch.nim #3234
Conversation
# because in that case there is no point in continuing. | ||
var bothMetaCounter = 0 | ||
var lastBindingsLength = -1 | ||
while r == isBothMetaConvertible and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you merge this into the 'of isBothMetaConvertible' branch below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might call typeRel(...)
several times, and once it returns something which is not isBothMetaConvertible
, we need to check what kind of TTypeRelation
it returned. I used the large case
statement for this. (Maybe in this special case the returned value can be only a couple of relation types and not all of them, but I didn't check this.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah I see.
That's really awesome @petermora. Could you shed some light on how you figured out how to do this? Do you have previous compiler hacking experience/knowledge? |
extending metatype matching in sigmatch.nim
I haven't done any compiler hacking so far. I found that many people would like to have this feature, so I spent many nights in the last several weeks to understand a little part of the complex compiler. I started to use |
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines used in branches and array construction expression earlier, which results in clearer error messages (`has no concrete type` vs. `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating generic routine as part of parameter matching, which allows for complex expression yielding anonymous generic procedures.
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines used in branches and array construction expression earlier, which results in clearer error messages (`has no concrete type` vs. `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating generic routine as part of parameter matching, which allows for complex expression yielding anonymous generic procedures.
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines earlier when used in branch and array constructor expressions, resulting in clearer error messages (`has no concrete type` instead of `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating a generic routine as part of parameter matching, which allows for complex expressions yielding un-instantiated generic routines (e.g.: `call((discard x; genericRoutine))`).
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines earlier when used in branch and array constructor expressions, resulting in clearer error messages (`has no concrete type` instead of `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating a generic routine as part of parameter matching, which allows for complex expressions yielding un-instantiated generic routines (e.g.: `call((discard x; genericRoutine))`).
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines earlier when used in branch and array constructor expressions, resulting in clearer error messages (`has no concrete type` instead of `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating a generic routine as part of parameter matching, which allows for complex expressions yielding un-instantiated generic routines (e.g.: `call((discard x; genericRoutine))`).
Summary ======= * simplify the logic for handling generic routines using `auto` as the return types * reject un-instantiated routines earlier when used in branch and array constructor expressions, resulting in clearer error messages (`has no concrete type` instead of `cannot instantiate`) * support lambda expressions coming from template expansions Details ======= Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Since meta types are possibly involved, the correct routine to use is `prepareMetatypeForSigmatch`. Testing that the produced type instance is not a meta type was also done incorrectly (`isMetaType` was used instead of `containsGenericType`). Finally, `nkStmtListExpr` nodes are now considered when instantiating a generic routine as part of parameter matching, which allows for complex expressions yielding un-instantiated generic routines (e.g.: `call((discard x; genericRoutine))`).
## Summary * simplify the logic for handling generic routines using `auto` as the return type * reject un-instantiated routines earlier when used in branch and array constructor expressions, resulting in clearer error messages (`has no concrete type` instead of `cannot instantiate`) * fix spurious `cannot instantiate` errors when passing generic routines as arguments to parameters that are also generic * support lambda expressions coming from template expansions ## Details Introduced by nim-lang/Nim#3234, when both the formal and actual type are unresolved meta types, the relation is considered to be `isBothMetaConvertible`. The intention seems to have been supporting passing `auto`-returning routines or lambda-expressions to generic procedure-type parameters, but the logic introduced by the aforementioned PR is not necessary for achieving that. `auto` return types now use dedicated handling in `procTypeRel`, both the formal and actual type being unresolved generics results in a mismatch again, and `typeRel` is no longer applied repeatedly for `isBothMetaConvertible` matches. There was also the issue of `generateTypeInstance` being misused, which could result in spurious `cannot instantiate` or internal compiler errors. Until type instantiation properly supports the case where it's not certain whether all used generic parameters have been inferred already, the `tryGenerateInstance` routine is introduced as a temporary solution. Finally, both `nkStmtListExpr` and `nkBlockExpr` nodes are now considered when instantiating a generic routine as part of parameter matching, which allows for complex expressions yielding un-instantiated generic routines (e.g.: `call((discard x; genericRoutine))`).
The motivation for this change is to enable
map(mySeq, x => $(x+1))
syntax. Unfortunately there is still an outstanding issue forauto
(see #3224) which is used inx => $(x+1)
, therefore the expressionmap(mySeq, x => $(x+1))
still won't work. However, the example below works with generics without providing any types.I tried not to increase the complexity of the code more than needed.
Thank you, Peter