Macros in 'when' clause don't capture variables
Nobody has claimed this yet.
- Dominant language
- Lua
- Stars
- 613
- Forks
- 45
- PR merge metrics
- No merged PRs in 30d
Description
I want to have something at least resembling algebraic data types in Yuescript - these are called enums in Rust, variants in OCaml, tagged unions in C. These are types that you can construct and they carry the underlying variant and some fields that the variant has. An example of this in Rust can be seen here: https://doc.rust-lang.org/rust-by-example/custom_types/enum.html
To that end I've been trying to use existing pattern matching functionality and macros to get this behavior. For the sake of example, let's say we want to encode variants of an enum as an array ['VariantName', ...fields], for example:
lang =
BinOp: (lhs, op, rhs) => ['BinOp', lhs, op, rhs]
Var: (name, expr) => ['Var', name, expr]
Const: (val) => ['Const', val]
Then I'd like to do pattern matching on different variants, but have a bit nicer syntax:
macro binop = (x,y,z) -> {
code: "['Binop', #{x}, #{y}, #{z}]"
type: "yue"
}
switch e
when $binop a,b,c
print "foo"
But this compiles to:
if {
'Binop',
a,
b,
c
} == e then
return print("foo")
end
But this isn't what I want, as it does not assign a, b, c variables for me to use inside the 'when' block. If I use the expected output of the macro directly:
switch e
when ['Binop', a, b, c]
print "bar"
I get what I expected - a, b, c are assigned values of e[2..4]:
local _type_0 = type(e)
local _tab_0 = "table" == _type_0 or "userdata" == _type_0
if _tab_0 then
local a = e[2]
local b = e[3]
local c = e[4]
if 'Binop' == e[1] and a ~= nil and b ~= nil and c ~= nil then
return print("bar")
end
end
This behavior is a bit unexpected, seems like macro evaluation happens at some later stage of compilation so instead of variable capture I get table comparison. Is this a bug or working as intended?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the macro-expansion path for switch/when pattern matching and compare it with the direct array-pattern example. Reproduce the shown $binop case and trace whether identifiers are bound after expansion; done means macro-based patterns capture a, b, and c like the direct pattern, or the behavior is documented as intended.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- lua
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100