[Feature request] Detect the type of a given piece of code (basic reflection or pattern matching)
- Dominant language
- C++
- Stars
- 1.6k
- Forks
- 193
- Avg merge
- 1d 33m
- Merged PRs (30d)
- 23
Description
*(I'm still exploring what this feature would involve; maybe it's not practical. But the problems from lacking something like this are real, even if there's a better solution than this.)*
A problem that repeatedly comes up when writing macros is: how to tell what type an argument is?
Maybe you want to take a number *or* a string, and act differently based on which one it is. Maybe you want to take an 8- *or* 16-bit register. Maybe you want to take a label *or* a numeric literal.
Workarounds common in current asm macros are basically "string inspection". Want to know if it's a number or string? Check `STRFIND("\1", "\"") == 0`... but that only works if `\1` was a literal quoted string, not e.g. `STRCAT("hel", "lo")`. Want to know if it's an 8-bit register? Check if `STRLWR("\1")` is `"a"`, `"b"`, `"c"`, etc... but that fails for `LOW(bc)`. Want to know if it's a condition code? Check against `"c"`, `"nc"`, `"z"`, `"nz"`... but that fails for `!!!z`, or for `cy` if you did `DEF cy EQUS "c"`.
Basically I'd like a `DATATYPE()` function that takes pretty much any argument and returns something indicating its type. `EQUS` expansion *would* occur inside the argument, which solves problems like `DEF cy EQUS "c"`, or string-detection issues. (I'm writing up this request because I ran into a case where `#name` was *not* an appropriate substitute for `"{name}"` -- when a macro is inspecting it for a leading `"`.)
I think `DATATYPE` returning a string would be clear to the user and easy for us to extend in future, like [JS `typeof`](). As for what types it should recognize:
- `"directive"`: `SECTION`, `assert`, `MACRO`, etc
- `"instruction"`: `jp`, `call`, `Halt`, etc
- `"rl"`: `rl`... it can be a directive *or* an instruction
- `"reg8"`: `A`, `LOW(de)`, etc
- `"reg16"`: `bc`, `DE`, `hl`, `sp`, `Af`
- `"condition"`: `z`, `!nc`, `!!!z`, etc
- `"c"`: `c`... it can be a register *or* a condition
- Note that this would only apply to literal `c` (or `EQUS` expanding out to `c`). `LOW(bc)` is *not* usable as a condition code in `call/jp/jr`.
- `"number"`: `42`, `$beef`, `%1001`, `BANK(x)`, etc
- `"string"`: `"hello"`, `"""world"""`, `STRCAT("a", "b")`, etc
- `"identifier"`: `Foo`, `bar`, `.`, etc
- `"local"`: `.foo`, `Global.local`, `..`, etc
- `"other"`: Anything not matching a well-defined pattern (`*`, `SECTION UNION`, `z + 2`, etc)
- I'm not sure whether too-wild things should be supported and detected as `"other"`, or just be syntax errors. The actual real-world use cases don't need such flexibility, so we'd be fine making them syntax errors and maybe in future allowing broader input.
Contributor guide
Assessment
This issue has not been assessed yet.