Skip to content

Macros in 'when' clause don't capture variables #253

Description

@Kristopher38

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?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions