Skip to content

Commit f5e0deb

Browse files
committed
feat: implement getter/setter expressions
1 parent 871a228 commit f5e0deb

4 files changed

Lines changed: 59 additions & 1 deletion

File tree

src/chunk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ typedef enum
1818
OP_SET_GLOBAL,
1919
OP_GET_UPVALUE,
2020
OP_SET_UPVALUE,
21+
OP_GET_PROPERTY,
22+
OP_SET_PROPERTY,
2123
OP_EQUAL,
2224
OP_GREATER,
2325
OP_LESS,

src/compiler.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,22 @@ static void call(bool can_assign)
499499
emit_bytes(OP_CALL, arg_count);
500500
}
501501

502+
static void dot(bool can_assign)
503+
{
504+
consume(TOKEN_DOT, "Expected property name after '.'.");
505+
u8 name = identifier_constant(&parser.previous);
506+
507+
if (can_assign && match(TOKEN_EQUAL))
508+
{
509+
expression();
510+
emit_bytes(OP_SET_PROPERTY, name);
511+
}
512+
else
513+
{
514+
emit_bytes(OP_GET_PROPERTY, name);
515+
}
516+
}
517+
502518
static void literal(bool can_assign)
503519
{
504520
switch (parser.previous.type)
@@ -626,7 +642,7 @@ ParseRule rules[] = {
626642
[TOKEN_LEFT_BRACE] = { NULL, NULL, PREC_NONE },
627643
[TOKEN_RIGHT_BRACE] = { NULL, NULL, PREC_NONE },
628644
[TOKEN_COMMA] = { NULL, NULL, PREC_NONE },
629-
[TOKEN_DOT] = { NULL, NULL, PREC_NONE },
645+
[TOKEN_DOT] = { NULL, dot, PREC_NONE },
630646
[TOKEN_MINUS] = { unary, binary, PREC_TERM },
631647
[TOKEN_PLUS] = { NULL, binary, PREC_TERM },
632648
[TOKEN_SEMICOLON] = { NULL, NULL, PREC_NONE },

src/debug.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ int disassemble_instruction(Chunk* chunk, int offset)
5757
return byte_instruction("OP_GET_UPVALUE", chunk, offset);
5858
case OP_SET_UPVALUE:
5959
return byte_instruction("OP_SET_UPVALUE", chunk, offset);
60+
case OP_GET_PROPERTY:
61+
return constant_instruction("OP_GET_PROPERTY", chunk, offset);
62+
case OP_SET_PROPERTY:
63+
return constant_instruction("OP_SET_PROPERTY", chunk, offset);
6064
case OP_EQUAL:
6165
return simple_instruction("OP_EQUAL", offset);
6266
case OP_GREATER:

src/vm.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,42 @@ static InterpretResult run()
318318
*frame->closure->upvalues[slot]->location = peek(0);
319319
break;
320320
}
321+
case OP_GET_PROPERTY:
322+
{
323+
if (!IS_INSTANCE(peek(0)))
324+
{
325+
runtime_error("Only instances can have properties.");
326+
return INTERPRET_RUNTIME_ERROR;
327+
}
328+
ObjInstance* instance = AS_INSTANCE(peek(0));
329+
ObjString* name = READ_STRING();
330+
331+
Value value;
332+
if (table_get(&instance->fields, name, &value))
333+
{
334+
pop();
335+
push(value);
336+
break;
337+
}
338+
runtime_error("Undefined property %s", name->chars);
339+
return INTERPRET_RUNTIME_ERROR;
340+
}
341+
case OP_SET_PROPERTY:
342+
{
343+
if (!IS_INSTANCE(peek(1)))
344+
{
345+
runtime_error("Only instances have fields.");
346+
return INTERPRET_RUNTIME_ERROR;
347+
}
348+
349+
ObjInstance* instance = AS_INSTANCE(peek(1));
350+
table_set(&instance->fields, READ_STRING(), peek(0));
351+
352+
Value value = pop();
353+
pop();
354+
push(value);
355+
break;
356+
}
321357
case OP_EQUAL:
322358
{
323359
Value v2 = pop();

0 commit comments

Comments
 (0)