Crystal: Add top-level has_constant? macro method (or expose Program type)

Created on 18 Mar 2020  路  16Comments  路  Source: crystal-lang/crystal

In #1585 has_constant? was added and allows you to check if a constant is defined within a type. But I think there is no hay to check if a top-level constant exists.

Adding a top-level macro method to check if the constant is defined in the internal Program type that holds the top level could look like:

{{ has_constant?(:MyShard) }}

Or if we expose the top level as an alias we could directly use.

{{ Program.has_constant?(:MyShard) }}

It can be useful to check if a shard is required or not. And to use feature checks instead of comparing versions.

feature topicmacros

Most helpful comment

How about another "macro instance var" like @toplevel? having it as a method on @type somehow irks me since it's not really a property of a type node. And indeed Program isn't very explicit about what it is either.

All 16 comments

I think the latter would be better, as this is also an issue with like "getting methods on the top level", etc.

Actually, you can do this right now :-D

{% puts @type.has_constant?(:Int32) %}
{% puts @type.has_constant?(:Int256) %}

https://play.crystal-lang.org/#/r/8qfs

@type at the top-level refers to the program.

That said, it's true that there's no way to explicitly refer to the top level...

But maybe we can add @type.top_level to access the top level from any type? That way we don't need to replicate all of the methods on TypeNode on the top level.

Ahhh yes, the issue was more so having access to top level constants/methods when the macro itself is _NOT_ in the top level as well.

Then I still think it makes sense to expose the top level as @type.top_level. Program _could_ work but it can be quite confusing if there's an actual type called Program.

How about another "macro instance var" like @toplevel? having it as a method on @type somehow irks me since it's not really a property of a type node. And indeed Program isn't very explicit about what it is either.

Yeah, another macro instance var sounds good too.

@program?

Why Program? Seems strange to tie the name to a badly named god object in the compiler. Top-level is what we call it everywhere else.

That being said, the way you reference top-level functions in crystal is ::puts. How about ::has_constant?

Program is probably a leak from the compiler internals. @top_level sounds about right.

The main benefit of @top_level vs ::has_constant? is that this will allow other methods defined in TypeNode to be applied to the top level.

@bcardiff :: should refer to the top-level type, and it should be a TypeNode. Just like String.has_constant? works right now, but with :: referring to the top level.

I don't follow @RX14. If :: is a value, then the syntax should be ::.has_constant?. If :: works in the same way as in the non-macro land, then is not a value; but a syntax that affect the constant resolution.

I'm just saying make ::foo access foo on the top-level type node, just like String.foo would.

I initially thought it could be a good idea. However, if you do this at the top level:

{% has_constant? :Foo %}
{% ::has_constant? :Foo %}

my initial thought would be that they are equivalent, since we are already at the top-level. So making :: mean "but call it on the top level" is a bit confusing.

I think introducing a @top_level macro instance var is clearer.

@asterite why wouldn't they be equivalent? At the top level those should be equivalent. :: is only solving the problem of making the top-level accessible when you're not at the top-level scope.

But that means that in the compiler we'll have to do this:

  • check if the method is a macro method for Crystal::Macros. Like debug, puts, etc.
  • otherwise, check if the method is a macro method for the program TypeNode

I think it's a bit confusing. Specially if later on there's a TypeNode method that has the same name as ones in the top-level right now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

grosser picture grosser  路  3Comments

oprypin picture oprypin  路  3Comments

Papierkorb picture Papierkorb  路  3Comments

ArthurZ picture ArthurZ  路  3Comments

nabeelomer picture nabeelomer  路  3Comments