So in introduce a new FNF function that takes takes two parameter for the macro to call so that I can create expressions like m(m(m(x,y),y),y) etc. That makes multiplication pretty easy to implement. It's a bit like functional programming (atleast from what I can remember) cause you can't use control loops of jumps in a flow of commands. You can only rely on inserting functions into other functions and so on. For cases like multiplicating or adding zero, I added another parameter with an expression called when a "null iteration" is inserted. So you can safely use MUL(0,3) or ADD(0,0) with no problems or whatever.

And I was also able to remove the NOT table! I only have 6 basic macros so far: MAXNUM, MINNUM. DEC, CAT, FINF an FINFDP where the last one is the macro explained above. CAT is used for concatenation and macro evaluation before it gets concatenated with the ## operator. It seems that this is the key nested loops. You must to make sure that you ALWAYS evaluate macros before they get inserted into their own body (and thus beeing not reachable cause the compiler cuts out the currently executed macro. If you carefully code around this limitation, it's possible to define linear command sequences as opposed to FOR loops that depend on a counter values and thus on evaluation during another macro evaluation. If you can evaluate them before you get into a macro they also need to evaluate, then it's totally possible to nest them. If not, we have to define different loops. It's interesting how this also reflects the call stack of higher programming languages (atleast higher than C's preprocessor): each evaluation of a macro inside a loop bears a new jump to another place, pushing a return address on the stack. Currently, I only have one loop with n possible iterations, as every iteration is composed of all it's next/previous iterations. Therefore, you need to evaluate a huge set of macros! Even more complete in explanation: Each macro evaluation is a jump. Thus, each iteration is a jump and each iteration requires it's own place on the stack. If the stack is full, then you've probably reached your loop end. Additionally, you can't jump to a position placed on the stack, it forbids recursion by default. So what can you do then? Right, add more macros and thus more possible jumps and loop iterations. And cause you can't just call stuff that's already on the stack, you can't nest loops with only one set of loop iterations.

It's quite an interesting concept in theory. It seems that it's a Turing complete (though if limited) system. Reading about on stackoverflow.com, someone has actually proven this. Hey, I could create an esoteric language out of this! But I'm afraid there does also exist one (and no, I don't mean the preprocessor itself). However, this makes my Lego computer less complex in creation. You I only need some kind of memory tape, decrementing, conditional jumping to address x and and input data tape for instructions! Yeah, I think that should be possible to make. Maybe I can even decrease this to a pure Turing machine and let it run on belt-fed jump system. A Turing machine seems to be just a systems of two belts for reading on belt one, deciding, writing to belt two, moving belt one, moving belt two. But programming it could be hard, as I'd need to figure out how to translate subtraction etc to those commands. However, Rome wasn't build in one day. And the only possible way to comfortably feed this mechanic is to translate higher commands like adding, multiplying or even dividing (algorithm, watch out!) into those instructions.

No comments: