valkarias / Pa

A Small & Interesting Programming Language.
https://valkarias.github.io
MIT License
18 stars 1 forks source link

Implementation of postfilx increment and decrement operators #2

Closed SjVer closed 3 years ago

SjVer commented 3 years ago

Hey!

I've recently finished Crafting Interpreters and I've been building upon my implementation of clox ever since. When trying to implement the postfix ++ and -- operators however, I got stuck.
The problem I'm facing is how to let the compiler and/or vm know if, and how to store the incremented value.
I've just stumbled upon your language which seems to also be built upon clox so I wondered how you got it to work? (I assume you did after reading through your code a bit.)
The way I did it so far appears to be very similar to the way you did it but in my case the storing part doesn't work. I'd love to hear how you managed it!
Thanks in advance!

valkarias commented 3 years ago

Oh Hello & welcome! Sorry for the delayed reply im experiencing some burnout at the moment.

The way i increment the actual value is by emitting opcodes that do update the value to increment in a case-by-case situation, for example here i check for the '++' after a list subscript, i emit an opcode to get the value at the specified index in the list, then i increment it and finally store it using an opcode named 'OP_STORE_SUBSCR' which stores an item in the stack to a list (here).

its the same idea with variables, u check for the '++' then emit your increment opcode and to update it u emit the setOp variable which can be a different opcode at different situations (local variables, globals...etc)

and finally for attributes (here) we check for the '++' after the property, emit the increment opcode then to update it u emit the opcode 'OP_SET_PROPETY' which stores the the incremented item in the stack to property. I hope this helps, im sorry for my english. Feel free to ask any questions.

SjVer commented 3 years ago

Thanks for the explanation! I've thought of a number of possible solutions but checking for the operators in other functions instead of having a seperate postfix() function didn't even occur to me.

Again, thanks for the clearification and good luck with your burnout! (I'm not sure if that came out correctly but english isn't my first language so you'll just have to take my word for that it's meant nicely :) )

SjVer commented 3 years ago

Hey! I just successfully implemented both the ++ and -- operators and I thought u'd perhaps wanna know how I did it. Since I didn't have (and didn't want to implement) the NO_POP variants of some instructions I opted for using the OP_DUPLICATE instruction I already had (which copies and pushes a value off the stack at the given index) and did it like this:
in function index (my version of your subsript function i believe):

    else if (canAssign && match(TOKEN_PLUS_PLUS))
    {
        // stack: [array, index]
        emitBytes(OP_DUPLICATE, (uint8_t)1);
        emitBytes(OP_DUPLICATE, (uint8_t)1);
        // stack: [array, index, array, index]
        emitBytes(OP_GET_INDEX, OP_INCREMENT);
        // stack: [array, index, newvalue]
        emitByte(OP_SET_INDEX);
    }
    else if (canAssign && match(TOKEN_MINUS_MINUS))
    {
        emitBytes(OP_DUPLICATE, (uint8_t)1);
        emitBytes(OP_DUPLICATE, (uint8_t)1);
        emitBytes(OP_GET_INDEX, OP_DECREMENT);
        emitByte(OP_SET_INDEX);
    }

in function dot:

    else if (canAssign && match(TOKEN_PLUS_PLUS))
    {
        emitBytes(OP_DUPLICATE, 0);
        emitBytes(OP_GET_PROPERTY, name);
        emitByte(OP_INCREMENT);
        emitBytes(OP_SET_PROPERTY, name);
    }
    else if (canAssign && match(TOKEN_MINUS_MINUS))
    {
        emitBytes(OP_DUPLICATE, 0);
        emitBytes(OP_GET_PROPERTY, name);
        emitByte(OP_DECREMENT);
        emitBytes(OP_SET_PROPERTY, name);
    }

And the rest is pretty much the same.

valkarias commented 3 years ago

Oh Great! im glad for helping you, thanks for providing a solution to remove the NO_POP instructions, i think your method is useful in the future as well, the reason behind the NO_POP instruction is to minimize the size of the bytecode at the cost of the vm being big. If you have any questions feel free to ask!