Show HN: A minimal stack based VM in C
github.com
github.com
> The core loop uses computed goto, which means that new instructions must be added in identical order
> Values are represented as tagged unions.
> Fundamental types are global (as in not tied to a specific VM instance)
What exactly is a global fundamental type? Is there a local counterpart?
The data type structure contains pointers to functions that implement operations such as addition, subtraction, copying and cloning. An integer type instance is initialized with addition and subtraction functions. The integer value representation is part of the value data structure though. So how could a user of the library define new data types? It seems like it would be necessary to modify the library's source code in order to add new members to the tagged union.
Also, perhaps the virtual machine could be optimized further by using tagged pointers to make integer values immediate, avoiding the need to dereference the pointer.
I'll add a void *as_any to the union eventually which means you're just one level of indirection from supporting any representation without touching the union.
One approach would be designing the input language for performance. In particular, having statically typed operations. A specialized iadd instruction for values that you are sure you want to treat as integers would save you a lot of indirecting through function pointers. A disadvantage of static typing is that you need to implement type checks if you want to guarantee well typedness.
Another (orthogonal) approach would be to consider a JIT backend. Not one you write yourself, that could definitely be considered "making a mess". But in the past I've had success using LibJIT (https://www.gnu.org/software/libjit/) for speeding up a stack interpreter. In that case, it was a subset of Python bytecode (see https://github.com/gergo-/pylibjit, the code has very probably bitrotted).
For example:
struct lg_buf *lg_buf_init(struct lg_buf *_) {
_->data = NULL;
_->len = _->cap = 0;
return _;
}http://www.tutorialspoint.com/perl/perl_special_variables.ht...
(The $ sigil denotes that the variable is a scalar; all Perl variables have a sigil like that.)
So this reads naturally to me: _ is the lg_buf, it doesn't need a real name like "buf", because it's just "the thing" or "it".
One such instance is the abbreviated scala lambda syntax, where (x:Int) => x + 2 can be abbreviated to _ + 2 in the same way that kotlin would allow abbreviating it as { it + 2 } with its equivalent default lambda parameter name, "it".
In the example you quoted, the identifier denotes the sole parameter, so in a sense its name does not matter, and as such people from certain programming circles might be inclined to use an underscore instead of taking the time to come up with an appropriate name. It's not like a more descriptive name would help in that example, the type name and function name already give sufficient context for it to be perfectly clear what the parameter is for, and it's not like parameter names have any semantic significance in C.
I agree, and I’ve been thinking about this today. There is also a minimalistic quality to this style, the _ pointer is more prominent simply by not having a real name. I like it!
The ISO C standard in section 7.1.3 states that global functions and variables in compiler/system libraries should be prefixed with an underscore to avoid the risk of conflict with names in user programs.
I checked and indeed... lg_buf is a global variable.
But I've never seen anyone use just the underscore prefix without a name before.
libriscv: fib(20) median 317ns lowest: 310ns highest: 356ns
luajit: fib(20) median 146ns lowest: 145ns highest: 170ns
lua5.4: fib(20) median 631ns lowest: 598ns highest: 694ns
Running your emulator:
$ ./fibrec
567usModern compilers used with emulated machines can beat even v8 at times. Cool project! I divided your number by 100, is that correct? Is there some additional overhead in setting up / tearing down something?
There is no additional overhead that I'm aware of except calling a function in a loop, which is intentional.