Skip to content
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

Merged
merged 6 commits into from
Sep 28, 2023

Conversation

cameel
Copy link
Member

@cameel cameel commented Sep 18, 2023

This PR removes hard-coded built-in type definitions and introduces the __builtin() construct for explicitly registering them.

It also renames the integer class to Integer to resolve the ambiguity with the integer type.

To do:

  • Builtin-types
  • Decide how to parse __builtin()

@cameel cameel requested a review from ekpyron September 18, 2023 17:03
@cameel cameel self-assigned this Sep 18, 2023
Comment on lines 1839 to 1848
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);
Copy link
Member Author

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 the BuiltinDefinition 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");
Copy link
Member Author

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.

Comment on lines -315 to -335
TypeSystemHelpers helper{m_typeSystem};
expressionAnnotation.type =
helper.typeFunctionType(
helper.tupleType(arguments),
m_typeSystem.type(*constructor, arguments)
);
Copy link
Member Author

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?

Copy link
Member

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)

Copy link
Member Author

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.

Copy link
Member

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 ElementaryTypeNameExpressions and the new one based on Identifiers 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.

@cameel cameel force-pushed the new-analysis-defining-builtins branch from fb10148 to aae85e8 Compare September 19, 2023 13:46
@cameel cameel marked this pull request as ready for review September 19, 2023 13:53
@cameel
Copy link
Member Author

cameel commented Sep 19, 2023

Since we decided to do type classes in a separate PR, this is now ready.

@ekpyron
Copy link
Member

ekpyron commented Sep 19, 2023

By the way, I originally imagined to get rid of the PrimitiveType enum entirely with this and to keep TypeSystem completely oblivious to the notion of primitive types - but looking at it again now, I agree that it's better to keep this around - it doesn't exactly hurt there either and the TypeSystemHelpers would become a pain, if we got rid of TypeSystems awareness of those types entirely.
So let's keep it like this!

@@ -1,5 +1,9 @@
pragma experimental solidity;

type word = __builtin("word");
type bool = __builtin("bool");
Copy link
Member

@ekpyron ekpyron Sep 20, 2023

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 ifs 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)

@ekpyron
Copy link
Member

ekpyron commented Sep 20, 2023

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.
@cameel cameel force-pushed the new-analysis-defining-builtins branch from 7111950 to 0819e31 Compare September 28, 2023 15:45
@cameel cameel merged commit bdd2f02 into newAnalysis Sep 28, 2023
@cameel cameel deleted the new-analysis-defining-builtins branch September 28, 2023 19:10
cameel added a commit that referenced this pull request Oct 10, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Oct 12, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Oct 13, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Oct 17, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Oct 23, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Dec 8, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Dec 13, 2023
Defining built-ins in experimental analysis
cameel added a commit that referenced this pull request Dec 13, 2023
Defining built-ins in experimental analysis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants