What have I created?

I am creating an interpreted game scripting language. Not having the theoretical background to help me develop and then implement a syntax, after a few attempts in that direction I decided to start from a register machine model, thinking that I would end up with something like a high-level assembler. Then, because my implementation language is haXe, which allows for dynamic types, I made a major change to the model:

There is no longer a separate space between program data and registers. Instead, thinking of how I can provide an infinite number of registers in my machine, I merged the ideas into one data structure. The first term that came to mind to describe this was "codeblock."

The codeblock contains both an integer opcode and data; the data is dynamic and can contain any haXe type. Passing data from one block to another is done at the source level, by making the relevant code all point to a third-party codeblock which has been agreed upon as a storage device. No specific ordering of codeblocks is dictated, but for practical convenience a "next" reference to a subsequent code block is also included for linear execution.

What I realized, as I built this system, was that the source code format was going to end up being tied to a customized editor which can deal with the data structures directly. At first I thought I would simply be mapping some of the higher level data structures in haXe to opcodes, and allowing the user to mark "variables" that get turned into codeblocks in a compilation step, but I gradually realized that with the editor's ability to browse, inspect, and link up references between codeblocks, there's a lot of potential power.

I added a stack for subroutine calls. Then, thinking a little more, I added a separate stack and a new referencing field in the codeblock for macros; as I envision it now, before executing the opcode of a codeblock, the interpreter looks to see if a macro codeblock is available. If it is, it jumps to that code and runs it first. The block that returns from a macro copies the contents of its data, which is itself another codeblock, to the caller. I don't have a lot of experience with constructs like this, though, so this may turn out to be wrongheaded.

This is all in very early stages. I've been sticking to writing stuff I can implement; my reference implementation to execute the above described is currently very small(under 200 lines) and surprisingly straightforward. I need to test it, work out the bugs, and start writing an editor. For the practical purposes I set out to achieve, I think I have something workable.

But my question is whether anyone knows of similar concepts to mine. It seems like any dynamic language could easily implement the same behavior, yet I know of nothing quite like this.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Might be of interest

Though I'm not sure if it is quite the same thing, some of what you are describing reminds me of the system described here

Deriving an answer

If you haven't already, it's worth taking a look at some of the work that relates to deriving virtual/abstract machines from higher level specifications. Here's a recent blog post by Shin-Cheng Mu which gives an example and provides some references, including to the paper by Ager et al.

The latter paper shows the connections between classic low-level abstract machines and functional evaluators, which covers a fairly broad space of possible machine designs. Your design probably falls outside that space, but this kind of work might help put your design in context.

[Edit: The above may only be relevant to the extent that your design resembles a low-level virtual machine (or, as you say, a high-level assembler). A high-level interpreter - particularly one implemented with haXe, which itself provides a fairly high-level language - doesn't necessarily have to deal with low-level details like registers and stacks directly. But again, the above work could help with figuring out appropriate abstraction levels for your design.]

Not sure

I'm not sure I really understand what you're suggesting. In particular, I'm not sure I really understand the relationship between opcodes and data. Frankly, it sounds a lot like an assembly language for a regular von Neumann computer with a flat memory hierarchy (and without data/text memory segmentation). It's also perhaps a bit reminiscent of something like Forth. Maybe?

No specific ordering of

No specific ordering of codeblocks is dictated, but for practical convenience a "next" reference to a subsequent code block is also included for linear execution.

That instantly reminded me of CPS, am I right? A bit like "current continuation is NEXT unless I tell you it isn't."

Neumann computer with a flat memory hierarchy

I short-circuted to something pointer-based as soon as I read "types"... not to mention that macros need something at least a bit flexible to work on.



If your opcodes are valid types and you have some way to construct lists and lambdas and, preferably, some way to convert CPS-convoluted code into NEXT-chains I would say that you just wrote a macro-based, JITing lisp.



Five Blind programmers met a Machine. "Look, it must be a lisp, it's all flexible!", said the first, touching the power chord. "No, you're wrong, it's an Ada, all big and stable!", complained the first, embracing the huge metal casing. "No, it must be a Haskell, all abstract and quite non-existent!", the third exclaimed, feeling the air flow of the CPU fan. "Nope, it's a Pascal, as I feared. All spiky and strangely ordered.", the fourth despaired, touching the soldering of various extension cards. "I dare to say it is an yet unknown thing.", the fifth compromised, feeling for the ashtray on top of the case.

"No, you are all wrong", exclaimed its owner, "it's my new toy, get your hands off."