How do you compose switches with macro reifiaction

Say I have the enum:

enum Item {
  Sword(damage:Int);
  Shield:
  None;
}

How would I go about automatically generating a switch like this:

switch(value) {
  case Sword(damage):

  case Shield:

  case None:
}

The closest I got to generating a case was this:

var sw = macro {switch($value) {
  case None:  

  case _:
  }
}

switch (sw.expr) {
	case EBlock(exprs):
		switch (exprs[0].expr) {
			case ESwitch(e, cases, edef):
				cases.push({
                  values: {values: [{pos: Context.currentPos, expr: EConst(CIdent("Shield"))}]}
                })
			case _:
		}
	case _:
}

But I get an error saying that the case is unused. I assume it has something with the position being wrong because I have no idea how that works. currentPos() returns {file:"Main.hx"}' so I assume that to get the correct position you need to do something like PositionTools.make(). I would really appreciate some pointers. Maybe there is a way to do this with a little more expression reification?
Thanks in advance!

You’re on the right track with constructing your switch expression. First you need to inspect the Type of $value to get its EnumType which then allows you to access an array of names and a map
of the constructs.

Take a look at this Try Haxe sample which hopefully helps.

1 Like

The error you get is because you add the case to your switch, resulting in the following:

switch(value) {
  case None:  
  case _:
  case Shield:
}

but since the second case is a catch all, the third is marked as an unused pattern. You would have the same error if you had this switch without a macro.

Context.currentPos() is the correct thing to use here.

I got the macro working the way I wanted. Thanks for the help!

1 Like