- cheeryParticipantApril 24, 2014 at 8:28 pmPost count: 7
Would like to know if you have anything to add into this line of thought.
I got a parser working for my programming language yesterday. Progressed to write
an evaluator for the code. After thinking about it on paper a small while, I thought
Mill might inspire up an interesting choice for bytecode.
I know that bytecode is not required to implement an interpreter. You could just
directly evaluate the trees you get from your parser. Converting it to bytecode will reduce away lot of calls from runtime, that would be required if evaluting the parse tree directly.
Bytecode will require some model for representing motion of values in the code. I could just go traditional and have destination, source virtual registers for every op. What if I used the belt model here? The operations would feed their values into a belt. It feels simple, but questions arise how to handle conditional branches and loops. Each block of operations will feed fixed count of values into the belt. The belt would be a finite array of virtual registers. It wouldn’t function like FIFO though, since you can scale the amount of virtual registers in bytecode. Unlike in Mill, it would be indexed from the beginning, with end -pointer pointing out where the values go to.
The bytecode implementation could ‘pull’ the belt backwards. Every simple could set the position of the belt and copy values from anywhere in the belt, ending up to resemble a copying garbage collector as long living values would end up to the bottom of the belt. One would use dominator tree to calculate where the belt must shed out values to not fill up. The copying would work like phi-nodes. Branches are tagged with number, which is used to index out which values to copy over while reseting the belt.
If you have better idea on how to do it, I’ll listen. Though I’ll try this one this weekend.
- Ivan GodardKeymasterApril 24, 2014 at 9:17 pmPost count: 629
This sounds like a plausible approach, at least for the start. It is certainly not a Mill, but we don’t mind if you describe it as “inspired by the Mill architecture” 🙂 Please let the Forum know how you progress.
BTW, a personal bias in designing and implementing language front-ends: I never use a separate parser. Instead I write a recursive-descent LL1 recognizer that does semantics (and frequently at least the front of optimization and code generation) on the fly. I find that this approach is significantly cleaner and easier to maintain and extend than separate parsets (especially those produced by parser-generators), and give much better error messages for the user. YMMV 🙂
You must be logged in to reply to this topic.