On this page:
6.1 Exercise
8.18.0.18

6 Implicit Forms🔗

A form such as

1 + f(2)

appears to be an addition expression to add the number 1 to the result of calling f on the argument 2. That is almost certainly the right interpretation of the form as a Rhombus expression. But if this form is in an enviornment where + has been shadowed by a macro definition, then it may mean something very different.

Could the 1 by itself mean anything different? If f is just a variable, might f(2) be something other than a function call? And in a space other than the expression space, how would the meaning of a number or a function-call form get a meaning appropriate to that space?

Rhombus answers these questions through implicit forms that are used as prefix or infix forms when no identifier or operator is apparent as a target to expand. When a literal number or string is found by itself, for example, the #%literal implicit prefix form is tried in the appropriate space. When a form is followed by a parenthesized form, the #%call implicit infix form is tried. Implicit form names starts with #%, which is allowed in general at the start of Rhombus identifiers, but intended for use by bindings that are not normally seen.

Here’s a contrived example that locally binds #%literal to treat each integer as 10 times its normal value:

> block:

    import rhombus.#%literal as orig_literal

    expr.macro '#%literal $(n :: Int)':

                  'orig_literal $(n.unwrap() * 10)'

    2 + 5 - 1

60

The use of orig_literal in the example’s expansion is important, otherwise the expansion would be a lone integer, which would trigger the implicit #%literal form again.

See Implicit Forms for a table of implicit forms and the patterns that trigger each form. If an implicit form is tried but not bound, a syntax error is reported.

6.1 Exercise🔗

See the end of interp_space.rhm, which has the same example interp calls as interp1.rhm, but instead of using constructors like Id and Fun directly, a prog form is used to write expressions that look similar to Rhombus syntax. Those expressions could have been quoted and parsed as in interp3.rhm, but they are instead parsed in the definition of prog by using the pattern 'prog: $(lc :: lc_meta.Parsed)'.

The lc_meta namespace is created by using space.enforest within interp_space.rhm. The use of space.enforest binds lc.macro to enable binding macros in the new space, and lc_meta.Parsed to trigger parsing via those macros.

Each use of lc_meta in interp_space.rhm creates a parsing point that translates a λ-calculus form to a use of a constructor like Id and Fun. In the end, prog directly uses a parsed result via lc_meta.Parsed as its result expression.

Add a substraction and conditional form this this interpreter and its parser, the same as in an earlier exercise with interp1.rhm.