<story><title>Show HN: A small virtual machine written in C</title><url>https://github.com/tekknolagi/carp</url></story><parent_chain></parent_chain><comment><author>axman6</author><text>Seems like [1] could benefit from use of the X macro [2], should make adding new instructions much easier and you can avoid the hassle of having to keep two separate tables in sync. There&amp;#x27;s probably quite a few places where the code could be made clearer by using it. Also in the implementation of your functions, there&amp;#x27;s a hell of a lot of repetition in all the binary operations, another macro which you pass in the operation and the function name would make life earier:&lt;p&gt;&lt;pre&gt;&lt;code&gt;    #define binop(NAME, OP) definstr (NAME) { \
        long long b, a; \
        if (carp_stack_pop(&amp;amp;m-&amp;gt;stack, &amp;amp;b) == -1)\
            carp_vm_err(m, CARP_STACK_EMPTY);\
        if (carp_stack_pop(&amp;amp;m-&amp;gt;stack, &amp;amp;a) == -1)\
            carp_vm_err(m, CARP_STACK_EMPTY);\
        carp_stack_push(&amp;amp;m-&amp;gt;stack, a OP b);}
    
    binop(ADD,+)
    binop(MUL,*)
    ...
&lt;/code&gt;&lt;/pre&gt;
The repetition of&lt;p&gt;&lt;pre&gt;&lt;code&gt;    if (carp_stack_pop(&amp;amp;m-&amp;gt;stack, &amp;amp;a) == -1)
        carp_vm_err(m, CARP_STACK_EMPTY);
&lt;/code&gt;&lt;/pre&gt;
seems like a good place to just use a function to encapsulate all the error checking and handling.&lt;p&gt;[1] &lt;a href=&quot;https://github.com/tekknolagi/carp/blob/master/src/carp_instructions.h&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;tekknolagi&amp;#x2F;carp&amp;#x2F;blob&amp;#x2F;master&amp;#x2F;src&amp;#x2F;carp_inst...&lt;/a&gt;&lt;p&gt;[2] &lt;a href=&quot;http://www.embedded.com/design/programming-languages-and-tools/4403953/C-language-coding-errors-with-X-macros-Part-1&quot; rel=&quot;nofollow&quot;&gt;http:&amp;#x2F;&amp;#x2F;www.embedded.com&amp;#x2F;design&amp;#x2F;programming-languages-and-too...&lt;/a&gt; and the following parts</text></comment>
<story><title>Show HN: A small virtual machine written in C</title><url>https://github.com/tekknolagi/carp</url></story><parent_chain></parent_chain><comment><author>panic</author><text>The implementation is really clean!   The mixing of general-purpose registers, special-purpose registers and the stack makes the instruction set a bit weird, though.&lt;p&gt;For example, instead of using registers, why not have OR pick values off the stack like ADD, or vice versa?  Why use EAX for the conditional jump instructions when you could look at the top of the stack?  Why have REM when you can just MOV from ERX?</text></comment>