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 keep-syntax and keep-syntax! functions #1095

Merged
merged 1 commit into from
Apr 8, 2023
Merged

Conversation

ml-2
Copy link
Contributor

@ml-2 ml-2 commented Apr 8, 2023

These functions are designed to make it easier to properly preserve the sourcemap and tuple type in macros. This commit also modifies the threading macros to make use of these functions.


I've been really enjoying Janet and while working on a DSL I've come across the problem that this pull request attempts to improve. Here is the explanation of the problem and my proposed solution.

Various macros in boot.janet lose the sourcemap information of their arguments due to creating a new modified tuple. This simple program shows an example of this:

(-> "String"
    (identity)
    (+ 1))
# error: could not find method :+ for "String"
#   in _thunk [example.janet] (tailcall) on line 1, column 1

The error message points to line 1, where the threading macro starts, instead of line 3, where the error actually occurs. When the threading macro is modified to preserve the sourcemaps, the error message is corrected:

# error: could not find method :+ for "String"
#   in _thunk [example.janet] (tailcall) on line 3, column 5

While this bug can be fixed for these macros individually, I think it's worth providing easy-to-use functions to handle sourcemaps correctly, because this problem arises for any user of Janet writing any macro that modifies an ast. So I'd like to propose the following two functions to make it easier to handle this.

(keep-syntax before after)

Creates a tuple with the tuple type and sourcemap of `before` but the
elements of `after`. If either one of its argements is not a tuple, returns
`after` unmodified. Useful to preserve syntactic information when transforming
an ast in macros.
(keep-syntax! before after)

Like `keep-syntax`, but if `after` is an array, it is coerced into a tuple.
Useful to preserve syntactic information when transforming an ast in macros.

The common case is when you have an ast and a function f transforming the ast, and you want (f ast) to have the same sourcemap as ast. Then you can use (keep-syntax ast (f ast)) to automatically handle this, without having to add conditionals for cases where ast or (f ast) might not be a tuple. And when f is a function that accepts a tuple but returns an array, then you can use keep-syntax! instead to automatically coerce.

This pull request includes implementations of these functions in boot.janet, uses them to preserve sourcemaps in the threading macros, and adds tests for some of these changes.

These functions are designed to make it easier to properly preserve the
sourcemap and tuple type in macros. This commit also modifies the threading
macros to make use of these functions.
@pepe
Copy link
Member

pepe commented Apr 8, 2023

I see this as a good idea. I am not able to test it ATM, but it looks fine.

@bakpakin
Copy link
Member

bakpakin commented Apr 8, 2023

LGTM, seems like a simple solution for this problem.

@bakpakin bakpakin merged commit bef5bd7 into janet-lang:master Apr 8, 2023
@ml-2 ml-2 deleted the ml branch April 15, 2023 02:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants