From 5bf6a9f08530145ba0e218cebe4174952a402d78 Mon Sep 17 00:00:00 2001 From: cozis Date: Mon, 1 Nov 2021 15:55:59 +0000 Subject: [PATCH] added assignment operator --- build.sh | 2 +- samples/if-else.noja | 7 +++++-- src/common/executable.c | 2 +- src/common/executable.h | 1 + src/compiler/ASTi.h | 1 + src/compiler/compile.c | 23 +++++++++++++++++++++++ src/compiler/parse.c | 10 +++++++--- src/objects/heap.c | 17 +++++++++++++++++ src/objects/o_map.c | 8 ++++---- src/objects/o_string.c | 27 +++++++++++++++++++++++++++ src/objects/objects.c | 34 +++++++++++++++++++--------------- src/runtime/runtime.c | 28 ++++++++++++++++++++++++++-- 12 files changed, 132 insertions(+), 28 deletions(-) diff --git a/build.sh b/build.sh index 87cdbe2..fdac6b1 100755 --- a/build.sh +++ b/build.sh @@ -1,4 +1,4 @@ -USING_VALGRIND=0 +USING_VALGRIND=1 FLAGS="-L3p/libs/ -I3p/include/ -Wall -Wextra -g -DUSING_VALGRIND=$USING_VALGRIND -DTRACE_SOURCE_COPIES=$TRACE_SOURCE_COPIES" diff --git a/samples/if-else.noja b/samples/if-else.noja index 797966b..38f7d08 100644 --- a/samples/if-else.noja +++ b/samples/if-else.noja @@ -1,9 +1,12 @@ +p = 1; +return p; + if true { - return 3; + x = 7; 2; } else 4; -return 99; \ No newline at end of file +return x; \ No newline at end of file diff --git a/src/common/executable.c b/src/common/executable.c index 4f3ef82..602c59b 100644 --- a/src/common/executable.c +++ b/src/common/executable.c @@ -47,7 +47,7 @@ static const InstrInfo instr_table[] = { [OPCODE_SUB] = {"SUB", 0, NULL}, [OPCODE_MUL] = {"MUL", 0, NULL}, [OPCODE_DIV] = {"DIV", 0, NULL}, - + [OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}}, [OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}}, [OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}}, diff --git a/src/common/executable.h b/src/common/executable.h index d3769c1..31384be 100644 --- a/src/common/executable.h +++ b/src/common/executable.h @@ -28,6 +28,7 @@ typedef enum { OPCODE_SUB, OPCODE_MUL, OPCODE_DIV, + OPCODE_ASS, OPCODE_POP, OPCODE_PUSHINT, OPCODE_PUSHFLT, diff --git a/src/compiler/ASTi.h b/src/compiler/ASTi.h index 4a9c049..840c6bf 100644 --- a/src/compiler/ASTi.h +++ b/src/compiler/ASTi.h @@ -18,6 +18,7 @@ typedef enum { EXPR_SUB, EXPR_MUL, EXPR_DIV, + EXPR_ASS, EXPR_INT, EXPR_NONE, EXPR_TRUE, diff --git a/src/compiler/compile.c b/src/compiler/compile.c index e132cdb..004f049 100644 --- a/src/compiler/compile.c +++ b/src/compiler/compile.c @@ -50,6 +50,29 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error) NULL, 0, node->offset, node->length); } + case EXPR_ASS: + { + OperExprNode *oper = (OperExprNode*) expr; + + Node *lop, *rop; + lop = oper->head; + rop = lop->next; + + if(((ExprNode*) lop)->kind != EXPR_IDENT) + { + Error_Report(error, 0, "Assignment left operand must be an identifier"); + return 0; + } + + if(!emit_instr_for_node(exeb, rop, error)) + return 0; + + const char *name = ((IdentExprNode*) lop)->val; + + Operand op = { .type = OPTP_STRING, .as_string = name }; + return ExeBuilder_Append(exeb, error, OPCODE_ASS, &op, 1, node->offset, node->length); + } + case EXPR_INT: { IntExprNode *p = (IntExprNode*) expr; diff --git a/src/compiler/parse.c b/src/compiler/parse.c index b3827cb..7db497d 100644 --- a/src/compiler/parse.c +++ b/src/compiler/parse.c @@ -852,15 +852,15 @@ static inline _Bool isbinop(Token *tok) return tok->kind == '+' || tok->kind == '-' || tok->kind == '*' || - tok->kind == '/'; + tok->kind == '/' || + tok->kind == '='; } static inline _Bool isrightassoc(Token *tok) { assert(tok != NULL); - (void) tok; - return 0; + return tok->kind == '='; } static inline int precedenceof(Token *tok) @@ -869,6 +869,9 @@ static inline int precedenceof(Token *tok) switch(tok->kind) { + case '=': + return 0; + case '+': case '-': return 1; @@ -928,6 +931,7 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec) case '-': temp->base.kind = EXPR_SUB; break; case '*': temp->base.kind = EXPR_MUL; break; case '/': temp->base.kind = EXPR_DIV; break; + case '=': temp->base.kind = EXPR_ASS; break; default: UNREACHABLE; diff --git a/src/objects/heap.c b/src/objects/heap.c index 7288352..2c6f4d9 100644 --- a/src/objects/heap.c +++ b/src/objects/heap.c @@ -4,6 +4,10 @@ #include #include "objects.h" +#if USING_VALGRIND +#include +#endif + typedef struct OflowAlloc OflowAlloc; struct OflowAlloc { OflowAlloc *prev; @@ -38,11 +42,20 @@ Heap *Heap_New(int size) return NULL; } +#if USING_VALGRIND + VALGRIND_CREATE_MEMPOOL(heap, 0, 0); +#endif + return heap; } void Heap_Free(Heap *heap) { + +#if USING_VALGRIND + VALGRIND_DESTROY_MEMPOOL(heap); +#endif + while(heap->oflow) { OflowAlloc *prev = heap->oflow->prev; @@ -106,5 +119,9 @@ void *Heap_RawMalloc(Heap *heap, int size, Error *err) assert(((intptr_t) addr) % 8 == 0); +#if USING_VALGRIND + VALGRIND_MEMPOOL_ALLOC(heap, addr, size); +#endif + return addr; } \ No newline at end of file diff --git a/src/objects/o_map.c b/src/objects/o_map.c index d9307d2..6e67721 100644 --- a/src/objects/o_map.c +++ b/src/objects/o_map.c @@ -103,9 +103,9 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error) assert(k >= 0); - if(Object_Compare(key, map->keys[i], error)) + if(Object_Compare(key, map->keys[k], error)) // Found it! - return map->vals[i]; + return map->vals[k]; if(error->occurred) // Key doesn't implement compare. @@ -230,11 +230,11 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e { assert(k >= 0); - if(Object_Compare(key, map->keys[i], error)) + if(Object_Compare(key, map->keys[k], error)) { // Already inserted. // Overwrite the value. - map->vals[i] = val; + map->vals[k] = val; return 1; } diff --git a/src/objects/o_string.c b/src/objects/o_string.c index a96e761..74036fb 100644 --- a/src/objects/o_string.c +++ b/src/objects/o_string.c @@ -12,6 +12,8 @@ typedef struct { static int hash(Object *self); static int count(Object *self); +static Object *copy(Object *self, Heap *heap, Error *err); +static _Bool op_eql(Object *self, Object *other); static const Type t_string = { .base = (Object) { .type = &t_type, .flags = Object_STATIC }, @@ -19,6 +21,8 @@ static const Type t_string = { .size = sizeof (StringObject), .hash = hash, .count = count, + .copy = copy, + .op_eql = op_eql, }; Object *Object_FromString(const char *str, int len, Heap *heap, Error *error) @@ -66,4 +70,27 @@ static int hash(Object *self) StringObject *strobj = (StringObject*) self; return hashbytes((unsigned char*) strobj->body, strobj->size); +} + +static Object *copy(Object *self, Heap *heap, Error *err) +{ + assert(self != NULL); + assert(self->type == &t_string); + assert(heap != NULL); + assert(err != NULL); + + return self; +} + +static _Bool op_eql(Object *self, Object *other) +{ + assert(self != NULL); + assert(self->type == &t_string); + assert(other != NULL); + assert(other->type == &t_string); + + StringObject *s1 = (StringObject*) self; + StringObject *s2 = (StringObject*) other; + + return s1->size == s2->size && !strncmp(s1->body, s2->body, s1->size); } \ No newline at end of file diff --git a/src/objects/objects.c b/src/objects/objects.c index 7f58c65..a7485e7 100644 --- a/src/objects/objects.c +++ b/src/objects/objects.c @@ -49,7 +49,7 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err) if(type->deepsize == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return 0; } @@ -65,7 +65,7 @@ int Object_Hash(Object *obj, Error *err) if(type->hash == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return -1; } @@ -82,7 +82,7 @@ Object *Object_Copy(Object *obj, Heap *heap, Error *err) if(type->copy == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return NULL; } @@ -99,7 +99,7 @@ Object *Object_Call(Object *obj, Object **argv, unsigned int argc, Heap *heap, E if(type->call == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return NULL; } @@ -117,11 +117,11 @@ Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err) if(type->select == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); return NULL; } - return type->select(coll, key, heap, err); + return type->select(coll, key, heap, err); } Object *Object_Delete(Object *coll, Object *key, Heap *heap, Error *err) @@ -135,7 +135,7 @@ Object *Object_Delete(Object *coll, Object *key, Heap *heap, Error *err) if(type->delete == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); return NULL; } @@ -153,7 +153,7 @@ _Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *e if(type->insert == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); return 0; } @@ -170,7 +170,7 @@ int Object_Count(Object *coll, Error *err) if(type->count == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(coll), __func__); return -1; } @@ -187,7 +187,7 @@ Object *Object_Next(Object *iter, Heap *heap, Error *err) if(type->next == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(iter), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__); return NULL; } @@ -204,7 +204,7 @@ Object *Object_Prev(Object *iter, Heap *heap, Error *err) if(type->prev == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(iter), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(iter), __func__); return NULL; } @@ -248,7 +248,7 @@ long long int Object_ToInt(Object *obj, Error *err) if(type->to_int == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return 0; } @@ -271,7 +271,7 @@ _Bool Object_ToBool(Object *obj, Error *err) if(type->to_bool == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return 0; } @@ -294,7 +294,7 @@ double Object_ToFloat(Object *obj, Error *err) if(type->to_float == NULL) { - Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__); + Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__); return 0; } @@ -303,12 +303,16 @@ double Object_ToFloat(Object *obj, Error *err) _Bool Object_Compare(Object *obj1, Object *obj2, Error *error) { + assert(obj1 != NULL); + assert(obj2 != NULL); + assert(error != NULL); + if(obj1->type != obj2->type) return 0; if(obj1->type->op_eql == NULL) { - Error_Report(error, "Object %s doesn't implement %s", Object_GetName(obj1), __func__); + Error_Report(error, 0, "Object %s doesn't implement %s", Object_GetName(obj1), __func__); return 0; } diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c index d979461..f66d744 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -83,7 +83,7 @@ _Bool Runtime_Push(Runtime *runtime, Error *error, Object *obj) if(runtime->frame->used == MAX_FRAME_STACK) { - Error_Report(error, 0, "Frames stack limit of %d reached", MAX_FRAME_STACK); + Error_Report(error, 0, "Frame stack limit of %d reached", MAX_FRAME_STACK); return 0; } @@ -112,7 +112,7 @@ _Bool Runtime_Pop(Runtime *runtime, Error *error, unsigned int n) if((unsigned int) runtime->frame->used < n) { - Error_Report(error, 0, "Frames has not enough values on the stack"); + Error_Report(error, 0, "Frame has not enough values on the stack"); return 0; } @@ -365,6 +365,30 @@ static _Bool step(Runtime *runtime, Error *error) break; } + case OPCODE_ASS: + { + assert(opc == 1); + assert(ops[0].type == OPTP_STRING); + + if(runtime->frame->used == 0) + { + Error_Report(error, 0, "Frame has not enough values on the stack"); + return 0; + } + + Object *val = Stack_Top(runtime->stack, 0); + assert(val != NULL); + + Object *key = Object_FromString(ops[0].as_string, -1, runtime->heap, error); + + if(key == NULL) + return 0; + + if(!Object_Insert(runtime->frame->vars, key, val, runtime->heap, error)) + return 0; + return 1; + } + case OPCODE_POP: { assert(opc == 1);