I'm designing a fairly simplistic stack-based programming language, and implementing it in Python. (no link, because it's not fully implemented yet.)

The language itself is essentially intended to be the actually usable lovechild of Forth and Joy, but JIT-compiled (mainly so I can learn to write a compiler).

Being Python, there is no "Virtual Machine" to speak of in the normal sense, but the runtime is a communication between a stack machine (a module's worth of classes implementing various features) and the lexerless "parser" which really just turns bytes into function calls at runtime.

Real native code does not have an idea of exceptions (obviously, being physical instructions, they don't really care either way), but the kernel can tell when things get out of hand, and so it and the memmapper are in a way the handler for errors in platform-native code.

By the language's nature, a large portion of Python's control flow is implemented through exceptions and handling them. However, the stack machine is meant to closely resemble a real Stack Machine in that giving it bad instructions will get you a slap in the face. In my opinion while code littered with try; except; else may well be Pythonic, sometimes it gets a bit much, especially if they're nested.

Do the exception handlers go nearest the raw data and functions, making them possibly easier to debug, or do they go alongside the (minimal) type-checking done by the runner, leaving the stack machine to be a Stupid Machine that returns None sometimes?

  • 1
    What makes you think that your stack machine isn't a virtual machine in the normal sense? Are you saying that Python's control flow is implemented via exceptions, or your language is? Jan 30, 2016 at 16:40
  • @WinstonEwert 1) because I don't have mappable memory, and I'm not loading a VM image. It doesn't seem like one to me, but correct me if I'm wrong. 2) I'm saying much of Python's is, sorry that was unclear. I'm asking about how close to the "metal" error handling should go, where the metal is the functions that deal with the raw data at runtime.
    – cat
    Jan 30, 2016 at 17:02
  • 3
    Not saying your wrong, but there are operating systems for machines without MMUs (where there's no memory isolation, and "memory mapping" is more about allocation and cleanup); the DOS era machines didn't have them, and IIRC Linux can be compiled with no-MMU support. Jan 30, 2016 at 17:14
  • Is the type-checking done by the runner static or dynamic? Jan 30, 2016 at 17:40
  • @WinstonEwert It's static, and adding two strings is a separate function from adding two numbers, and the decision about which to call is made by the runner.
    – cat
    Jan 30, 2016 at 17:45

1 Answer 1


You've chosen an unusual architecture.

What you are calling a stack machine isn't really what we typically call a stack machine. A stack machine is a type of computer architecture. Since your stack machines cannot execute a program, they aren't an instance of computer architecture, and thus what you are implementing is not properly a stack machine.

But, they are not quite stacks either. A stack is a data structure, and would typically only implement operations related to that structure. So it would support pop, add, rotate, etc. but not add, mul, sub, etc. But you've put all manner of operations into your stack machines. In a more typical implementation, those would be part of the runner.

Your actual question is only coming up because of your architecture. In most situations, there would be no question, the error handling has to exist in the runner because the stack is restricted to operations on its data structure.

Of course, you are free to explore architectures different from the typical. But since you are doing something unusual, I can't possibly tell you what way of handling errors will turn out to be better.

  • I've implemented it in this way because it makes it a lot easier to write the runner if everything is just a call. Thanks for your answer!
    – cat
    Jan 30, 2016 at 19:12
  • @cat, I'm going to predict that you'll find that doesn't work out as well as you think it will. I suspect your runner will end up more not less complicated as a result of what you've done. Jan 30, 2016 at 19:14
  • i beg to differ
    – cat
    Jan 30, 2016 at 19:25
  • @cat, your design is somewhat different, because you've got multiple stacks and are planning to do overloading in the runner rather then the stack. Those are the things which I think are going to contribute to complexity. Jan 30, 2016 at 19:50
  • 1
    But don't let me stop you. I'm just offering my opinion. Jan 30, 2016 at 19:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.