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

Add magic constants: __FILE__ and __LINE__ #36

Closed
faultyserver opened this issue Nov 10, 2017 · 2 comments
Closed

Add magic constants: __FILE__ and __LINE__ #36

faultyserver opened this issue Nov 10, 2017 · 2 comments
Labels
feature-request Any request for a new feature of the language. Includes both syntax and library features. good first issue An issue that provides a good intro to working with the Myst codebase. Be helpful! syntax Any issue relating to the syntax of Myst.
Milestone

Comments

@faultyserver
Copy link
Member

Magic constants are useful for many things. In particular, __FILE__ is great for making portable scripts, and __LINE__ can help debug tooling and reporting to end users.

A simple description of their behavior:

  • __FILE__ returns the absolute path to the file that it appears in. For example, in a file ~/test.mt, the constant might resolve to /home/user/test.mt. The path is always the file containing the constant, not affected by require statements or likewise.

  • __LINE__ returns an integer representing the line number of the current file that the constant appears on, starting from 1. For example, the constant in the following code will evaluate to 3.

1 + 2
3 + 4
__LINE__

The implementation of these constants can be easily done using the location property that all nodes already have. A new node type, MagicConstant can be introduced, that has a type property indicating what the constant is (probably :line for __LINE__, or :file for __FILE__).

@faultyserver faultyserver added feature-request Any request for a new feature of the language. Includes both syntax and library features. syntax Any issue relating to the syntax of Myst. labels Nov 10, 2017
@faultyserver faultyserver modified the milestone: Next Nov 10, 2017
@faultyserver faultyserver added the good first issue An issue that provides a good intro to working with the Myst codebase. Be helpful! label Nov 13, 2017
@faultyserver
Copy link
Member Author

faultyserver commented Nov 13, 2017

There are some advanced semantics for this that can be added later (evaluating to call-er location information when used as a method parameter, etc). The initial implementation, though, should actually be fairly straightforward. However, there are a lot of changes that will need to be made.

The MagicConstant AST node can be added here: https://github.com/myst-lang/myst/blob/master/src/myst/syntax/ast.cr#L269 (the line number is just my suggestion. Feel free to add it elsewhere in the file if it feels better). The format for the comments above each node type generally follows this structure:

# Node summary as a noun. Some descriptive text about the uses of the
# node type and any special notes about them.
#
#   syntax example a-la an EBNF production rule and/or regex.
class NodeName < Node
  ...
end

Some hints toward what the comment could look like for MagicConstant: MagicConstants are constants whose values are determined dynamically by the interpreter. They are often used for meta-programming or tooling for libraries to better support end users. All MagicConstants are written in SCREAMING_CASE, and are surrounded by double underscores (__).

The syntax for a MagicConstant is __[A-Z][_A-Z]*__.

The parser will then need changing to identify constants that fit this syntax. Currently, they are tokenized as Token::Type::IDENT by the lexer. If you would like to change the lexer to tokenize them differently, feel free :)

Depending on your choice, a good place to create the MagicConstant nodes is either in parse_primary if they are lexed as separate token types, or in parse_var_or_call in the receiver.nil? conditional block if they are kept as IDENTs. In either case, it'd be best to add a new method, parse_magic_constant, to determine the value of the type property described above. Be sure to call .at(token.location) when you create the node, otherwise you won't have the location information available in the interpreter!

Finally, in the interpreter, create a new file src/myst/interpreter/nodes/magic_constant.cr with a visit(node : MagicConstant) method that checks the type property of the node and pushes the appropriate value onto the stack. As described in the OP, all of the information needed for __FILE__ and __LINE__ is available in node.location, which is a Location instance. These values will need to be wrapped in the appropriate Myst type (TString and TInteger, respectively) before being pushed to the stack.

That should be it for the implementation, just be sure to add specs for everything (parser specs can go here and interpreter specs can go in a new file at spec/interpreter/nodes/magic_constant_spec.cr. Also add Lexer specs here if you add the new token type).

As always, if you have any questions, feel free to ask them here or let me know directly so I can help out :) Good luck!

@faultyserver
Copy link
Member Author

This was implemented in #36. Thanks, @bmulvihill! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request Any request for a new feature of the language. Includes both syntax and library features. good first issue An issue that provides a good intro to working with the Myst codebase. Be helpful! syntax Any issue relating to the syntax of Myst.
Projects
None yet
Development

No branches or pull requests

1 participant