stdlib icon indicating copy to clipboard operation
stdlib copied to clipboard

[RFC]: add support for defining and using macros in the REPL

Open kgryte opened this issue 1 year ago • 0 comments

Description

This RFC proposes adding macro support in the REPL. To allow users to define macros, we could add a command having the following signature:

macro( name, body )

where

  • name: macro name (e.g., FOR) and may include named parameters
  • body: macro body

E.g.,

In [1]: macro( 'FOR', 'for ( let i = 0; i < 10; i++ ) {' );

would define a macro for define the conditions of a for loop. To use, a user would type

In [2]: FOR

followed by ENTER in order to expand the macro. Note, in this proposal, hitting ENTER should not cause the macro body to execute; only for the macro to expand.

To parameterize the above macro, we could do

In [3]: macro( 'FORN(N)', 'for ( let i = 0; i < N; i++ ) {' );

where N is a macro parameter. To use,

In [4]: FORN( 100 )

would, after hitting ENTER, expand to

In [5]: for ( let i = 0; i < 100; i++ ) {<|>

where <|> is the cursor.

Related Issues

No.

Questions

  • Do we want to support recursive macro definitions? My guess is no, at least to start, as that makes things rather complex. It is doable, I suppose. Just keep performing macro substitution until one can no longer find macro definitions.

  • What should happen when a user embeds a MACRO among other expressions:

    In [1]: foo; FOR console.log( i ); }; beep
    

    Presumably, we'd need to check for the presence of macros BEFORE attempting to evaluate a line. If a macro is found, then we must expand and then the user needs to press ENTER again in order to execute.

  • Are there any built-in macros we'd want to support?

  • Longer term, we'd probably want to support allowing a user to define macros at REPL instantiation (e.g., through configuration or a startup file).

  • IPython also allows defining macros based on line number(s). Would we want to support something similar? This assumes that line numbers are displayed (i.e., that a user has not changed the input prompt). If we chose to support, would we support via a different API or overload the same API?

  • We'd want to be careful regarding substitution. For example, if a macro has a parameter N, we'd need to avoid replacing the N in fooNbar. This may be tricky to get right, so may be worth studying how C macro parameter substitution works and consider emulating. As another idea, we could support a macro string syntax similar to template strings or @stdlib/string/format, where there's a special markup for placeholders which should be replaced by provided arguments.

Other

  • Magic support in IPython: https://ipython.readthedocs.io/en/stable/interactive/magics.html?highlight=magic#magic-macro
  • C style macros:
    • https://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC10
    • https://gcc.gnu.org/onlinedocs/cppinternals/Macro-Expansion.html

Checklist

  • [X] I have read and understood the Code of Conduct.
  • [X] Searched for existing issues and pull requests.
  • [X] The issue name begins with RFC:.

kgryte avatar Mar 27 '24 06:03 kgryte