-
Notifications
You must be signed in to change notification settings - Fork 6k
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
Defining built-ins in experimental analysis #14566
Conversation
libsolidity/parsing/Parser.cpp
Outdated
expectToken(Token::Builtin); | ||
expectToken(Token::LParen); | ||
|
||
// TMP: Do I need to guard this? | ||
//if (m_scanner->currentToken() == Token::StringLiteral) | ||
expression = nodeFactory.createNode<BuiltinDefinition>( | ||
std::make_shared<std::string>(m_scanner->currentLiteral()), | ||
// TMP: Verify that it's the right location | ||
m_scanner->currentLocation() | ||
); | ||
|
||
expectToken(Token::StringLiteral); | ||
expectToken(Token::RParen); |
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.
Not sure if this is the best way to parse it:
- Maybe I should allow arbitrary arguments and only reject invalid ones in the analysis?
- Even if not, maybe the name of the builtin should be parsed into a
Literal
node? Currently I only expect a string and pass it as such to theBuiltinDefinition
AST node.- If it's a literal, I can make AST visit it. Not sure if that would be useful though.
type unit = __builtin("unit"); | ||
|
||
type fun(T, U) = __builtin("fun"); | ||
type pair(T, U) = __builtin("pair"); |
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.
Since this is a built-in and the type variables will never be used for anything, maybe it would be better to omit them in the definition?
type fun = __builtin("fun");
I could also do this, just to keep them connected to something:
type fun(T, U) = __builtin("fun", T, U);
not sure if it makes sense though.
TypeSystemHelpers helper{m_typeSystem}; | ||
expressionAnnotation.type = | ||
helper.typeFunctionType( | ||
helper.tupleType(arguments), | ||
m_typeSystem.type(*constructor, arguments) | ||
); |
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.
Do I still need this? I suspect I should now be doing this in visit(Identifier)
when the identifier is a type name, but (at least in my simple tests) everything seems to be working just fine without it.
But maybe that's because I need more complex examples? Some expressions on types in variable declarations? Are those even implemented?
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.
All this becoming obsolete is kind of the point in making these types defined as usual - so it should work fine (and if it doesn't yet in all cases, we'll fix that elsewhere)
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.
But I meant this specific part of the function that I highlighted above. The assignment of a type annotation in term context is indeed handled when visiting the type definition now, but it does nothing in type context.
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.
I'm not sure I follow exactly :-). There is (may be) some difference between the old handling as ElementaryTypeNameExpression
s and the new one based on Identifier
s that refer to a type declaration (which are handled in handleIdentifierByReferencedDeclaration
).
But I think the new handling in Identifier
should be the correct one. The old version may not even have worked for "function calls" to elementary type names in type expressions (not sure that even parsed), while the new one should.
In any case (without digging into it completely myself now), I think this is fine and if we notice that anything is missing later on, we can then fix it in the identifier visit.
fb10148
to
aae85e8
Compare
Since we decided to do type classes in a separate PR, this is now ready. |
By the way, I originally imagined to get rid of the |
@@ -1,5 +1,9 @@ | |||
pragma experimental solidity; | |||
|
|||
type word = __builtin("word"); | |||
type bool = __builtin("bool"); |
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.
For booleans, it's funny that we could actually define them completely as user-defined type, i.e.
type bool = word;
Or later, more precisely, as an ADT
data bool = true | false;
The interesting part about booleans is rather that we have "truthiness" and "falsiness" on them, allowing them to work in conditionals.
Which is a bit of a chicken and egg problem: how to define truthiness without a boolean to indicate whether something is truthy :-)? (For the ADT representation we could just mark the true
constructor as truthy and the false
constructor as falsy, but this would still take some doing) So let's keep it builtin for now, but down the road it may be interesting to think about how to improve upon that.
Funnily, we wouldn't even actually need "truthiness"/"falsiness", if we defined if
s and loops in-language, which would actually work with higher-order functions and the ability to call Solidity functions from Yul if they take only types that involve "Yul-types" - but for that we'd among others need lambdas and what-not, so let's don't go there for now :-).
We might keep them as builtin permanently anyways, especially if we, in the future, introduce a boolean type in Yul (which would be one option for addressing stuff like #13750, which I moved to the optimizer ideas hackmd, but would also complicate things quite a bit, so also nothing we'd target soon)
I'd say it'd be nice to address #14566 (comment), but then feel free to just merge this! |
- Using the same name causes syntax ambiguities. It's also not allowed for user-defined classes and types.
aae85e8
to
7111950
Compare
7111950
to
0819e31
Compare
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
Defining built-ins in experimental analysis
This PR removes hard-coded built-in type definitions and introduces the
__builtin()
construct for explicitly registering them.It also renames the
integer
class toInteger
to resolve the ambiguity with theinteger
type.To do:
__builtin()