Torque is a meta-assembler: instead of having an instruction set built into the assembler, you use macros to build up a small language that decribes an instruction set and then you use that to write your program. It's designed to work for any microcontroller/processor architecture, you build from the bit level upwards so there aren't any assumptions around word widths, instruction formats, or endianness.
I created Torque initially to write programs for a PIC microcontroller, after running into difficulties with the official assembler. I've also used it to write programs for the Z80 processor inside an old TRS-80 computer.
Let me know if you try it out or have any questions!
sitkack•3d ago
Did you get inspiration from other assemblers or macro processors?
You have it running on a TRS-80, how does that work? I had no idea Rust could target a TRS-80.
I am getting hints of Forth, Lisp and TCL.
How would you go about laying out structs in memory?
I am sure you considered an internal DSL, what caused you go with something stand alone?
Any thoughts on adding a constraint solver, like Z3 and allowing end users to set constraints on things like the size of a jump.
I could see taking this an growing it into a compiler by making macro(macro(macros txt)))
Is there an internal IR?
Projects for inspiration
https://github.com/mattbierner/Template-Assembly
Specifying representations of machine instructions https://dl.acm.org/doi/pdf/10.1145/256167.256225
https://www.semanticscholar.org/paper/Specifying-representat...
Typed Assembly Language (TAL) https://www.cs.cornell.edu/talc/
And you haven't come across it, you are in for a treat https://en.wikipedia.org/wiki/META_II has spawned a whole trove of clones
https://en.wikipedia.org/wiki/OMeta
https://github.com/DalekBaldwin/clometa
benbridle•3d ago
Rust isn't involved past implementing the Torque executable; you write your program with the Torque language and then run the assembler on it to convert it to machine code. You can see the whole process of running code on the TRS-80 from start to finish here [1].
For laying out structs, I'd build a macro that expands to the memory representation of the struct. If I wanted a struct representing, say, a 2D point with signed 16-bit little-endian integers for the x and y coords, I would build it from scratch like this (this is a valid program, you can assemble it with Torque):
If I want the address of a field, I can add an offset to the struct address, using macros to name the offset values: Creating a DSL for an existing language wasn't something I'd ever considered. By being a standalone executable it's really easy to use and share, people don't have to install a whole language toolchain in order to use it.Regarding constraints solving and jumping, Torque already throws an error if you try to pack too large a value into too small a field. This works really well for things like relative jumps, because jumping too far will create a value that can't fit in the instruction. I'm planning on adding an error-throwing token to the language that could be used alongside expressions and conditions to further constrain the values accepted by a macro, but I'm really happy with the simplicity of the language so far.
The actual internal representation isn't what I'd call an 'IR' per se, nothing like with a C compiler. It's all very pedestrian; the syntax tree is baked down across multiple passes, with macros acting as a glorified copy-paste system.
Thanks for the interest and the links, every one of those linked projects is new to me.
[0] https://wiki.xxiivv.com/site/uxn.html
[1] https://benbridle.com/articles/torque-programming-the-trs-80...