debbuging failure to read from builtin map
This commit is contained in:
@@ -75,6 +75,7 @@ gcc src/main.c src/debug.c \
|
|||||||
temp/utils/bucketlist.o \
|
temp/utils/bucketlist.o \
|
||||||
temp/objects/o_map.o \
|
temp/objects/o_map.o \
|
||||||
temp/objects/o_none.o \
|
temp/objects/o_none.o \
|
||||||
|
temp/objects/o_list.o \
|
||||||
temp/objects/o_bool.o \
|
temp/objects/o_bool.o \
|
||||||
temp/objects/o_string.o \
|
temp/objects/o_string.o \
|
||||||
temp/runtime/runtime.o \
|
temp/runtime/runtime.o \
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
l = [1, 2, 3];
|
||||||
|
|
||||||
|
print(count);
|
||||||
|
print(count(l));
|
||||||
|
print(l, '\n');
|
||||||
@@ -58,6 +58,7 @@ static const InstrInfo instr_table[] = {
|
|||||||
[OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}},
|
[OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}},
|
||||||
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
|
||||||
[OPCODE_CALL] = {"CALL", 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_CALL] = {"CALL", 1, (OperandType[]) {OPTP_INT}},
|
||||||
|
[OPCODE_INSERT] = {"INSERT", 0, NULL},
|
||||||
[OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}},
|
||||||
[OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}},
|
[OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}},
|
||||||
[OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}},
|
[OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}},
|
||||||
@@ -66,6 +67,7 @@ static const InstrInfo instr_table[] = {
|
|||||||
[OPCODE_PUSHFLS] = {"PUSHFLS", 0, NULL},
|
[OPCODE_PUSHFLS] = {"PUSHFLS", 0, NULL},
|
||||||
[OPCODE_PUSHNNE] = {"PUSHNNE", 0, NULL},
|
[OPCODE_PUSHNNE] = {"PUSHNNE", 0, NULL},
|
||||||
[OPCODE_PUSHFUN] = {"PUSHFUN", 2, (OperandType[]) {OPTP_INT, OPTP_INT}},
|
[OPCODE_PUSHFUN] = {"PUSHFUN", 2, (OperandType[]) {OPTP_INT, OPTP_INT}},
|
||||||
|
[OPCODE_PUSHLST] = {"PUSHLST", 1, (OperandType[]) {OPTP_INT}},
|
||||||
|
|
||||||
[OPCODE_RETURN] = {"RETURN", 0, NULL},
|
[OPCODE_RETURN] = {"RETURN", 0, NULL},
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ typedef enum {
|
|||||||
OPCODE_ASS,
|
OPCODE_ASS,
|
||||||
OPCODE_POP,
|
OPCODE_POP,
|
||||||
OPCODE_CALL,
|
OPCODE_CALL,
|
||||||
|
OPCODE_INSERT,
|
||||||
OPCODE_PUSHINT,
|
OPCODE_PUSHINT,
|
||||||
OPCODE_PUSHFLT,
|
OPCODE_PUSHFLT,
|
||||||
OPCODE_PUSHSTR,
|
OPCODE_PUSHSTR,
|
||||||
@@ -45,6 +46,7 @@ typedef enum {
|
|||||||
OPCODE_PUSHFLS,
|
OPCODE_PUSHFLS,
|
||||||
OPCODE_PUSHNNE,
|
OPCODE_PUSHNNE,
|
||||||
OPCODE_PUSHFUN,
|
OPCODE_PUSHFUN,
|
||||||
|
OPCODE_PUSHLST,
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
OPCODE_JUMPIFANDPOP,
|
OPCODE_JUMPIFANDPOP,
|
||||||
OPCODE_JUMPIFNOTANDPOP,
|
OPCODE_JUMPIFNOTANDPOP,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ typedef enum {
|
|||||||
EXPR_ASS,
|
EXPR_ASS,
|
||||||
EXPR_INT,
|
EXPR_INT,
|
||||||
EXPR_CALL,
|
EXPR_CALL,
|
||||||
|
EXPR_LIST,
|
||||||
EXPR_NONE,
|
EXPR_NONE,
|
||||||
EXPR_TRUE,
|
EXPR_TRUE,
|
||||||
EXPR_FALSE,
|
EXPR_FALSE,
|
||||||
@@ -78,6 +79,12 @@ typedef struct {
|
|||||||
int len;
|
int len;
|
||||||
} StringExprNode;
|
} StringExprNode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ExprNode base;
|
||||||
|
Node *items;
|
||||||
|
int itemc;
|
||||||
|
} ListExprNode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ExprNode base;
|
ExprNode base;
|
||||||
char *val;
|
char *val;
|
||||||
|
|||||||
@@ -113,6 +113,42 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
|
|||||||
return ExeBuilder_Append(exeb, error, OPCODE_PUSHVAR, &op, 1, node->offset, node->length);
|
return ExeBuilder_Append(exeb, error, OPCODE_PUSHVAR, &op, 1, node->offset, node->length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case EXPR_LIST:
|
||||||
|
{
|
||||||
|
// PUSHLST
|
||||||
|
// PUSHINT
|
||||||
|
// <expr>
|
||||||
|
// INSERT
|
||||||
|
|
||||||
|
ListExprNode *l = (ListExprNode*) node;
|
||||||
|
|
||||||
|
Operand op;
|
||||||
|
|
||||||
|
op = (Operand) { .type = OPTP_INT, .as_int = l->itemc };
|
||||||
|
if(!ExeBuilder_Append(exeb, error, OPCODE_PUSHLST, &op, 1, node->offset, node->length))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Node *item = l->items;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while(item)
|
||||||
|
{
|
||||||
|
op = (Operand) { .type = OPTP_INT, .as_int = i };
|
||||||
|
if(!ExeBuilder_Append(exeb, error, OPCODE_PUSHINT, &op, 1, item->offset, item->length))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!emit_instr_for_node(exeb, item, error))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!ExeBuilder_Append(exeb, error, OPCODE_INSERT, NULL, 0, item->offset, item->length))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
item = item->next;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
case EXPR_CALL:
|
case EXPR_CALL:
|
||||||
{
|
{
|
||||||
CallExprNode *p = (CallExprNode*) expr;
|
CallExprNode *p = (CallExprNode*) expr;
|
||||||
|
|||||||
@@ -651,6 +651,96 @@ static Node *parse_string_primary_expression(Context *ctx)
|
|||||||
return (Node*) node;
|
return (Node*) node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Node *parse_list_primary_expression(Context *ctx)
|
||||||
|
{
|
||||||
|
assert(ctx != NULL);
|
||||||
|
|
||||||
|
if(done(ctx))
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 0, "Source ended where a list literal was expected");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(current(ctx) != '[')
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 0, "Got token \"%.*s\" where a list literal was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = current_token(ctx)->offset;
|
||||||
|
|
||||||
|
Node *items = NULL;
|
||||||
|
int itemc = 0;
|
||||||
|
|
||||||
|
next(ctx); // Skip the '['.
|
||||||
|
|
||||||
|
if(current(ctx) != ']')
|
||||||
|
{
|
||||||
|
Node *tail = NULL;
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
// Parse.
|
||||||
|
Node *item = parse_expression(ctx);
|
||||||
|
|
||||||
|
if(item == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Append.
|
||||||
|
if(tail)
|
||||||
|
tail->next = item;
|
||||||
|
else
|
||||||
|
items = item;
|
||||||
|
tail = item;
|
||||||
|
itemc += 1;
|
||||||
|
|
||||||
|
// Get ',' or ']'.
|
||||||
|
|
||||||
|
if(current(ctx) == ']')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(current(ctx) != ',')
|
||||||
|
{
|
||||||
|
if(current(ctx) == TDONE)
|
||||||
|
Error_Report(ctx->error, 0, "Source ended inside a list literal");
|
||||||
|
else
|
||||||
|
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" inside list literal, where ',' or ']' were expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
next(ctx); // Skip the ','.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int length = current_token(ctx)->offset
|
||||||
|
+ current_token(ctx)->length
|
||||||
|
- offset;
|
||||||
|
|
||||||
|
next(ctx); // Skip the ']'.
|
||||||
|
|
||||||
|
ListExprNode *list;
|
||||||
|
{
|
||||||
|
list = BPAlloc_Malloc(ctx->alloc, sizeof(ListExprNode));
|
||||||
|
|
||||||
|
if(list == NULL)
|
||||||
|
{
|
||||||
|
Error_Report(ctx->error, 1, "No memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->base.base.kind = NODE_EXPR;
|
||||||
|
list->base.base.next = NULL;
|
||||||
|
list->base.base.offset = offset;
|
||||||
|
list->base.base.length = length;
|
||||||
|
list->base.kind = EXPR_LIST;
|
||||||
|
list->items = items;
|
||||||
|
list->itemc = itemc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (Node*) list;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static char *copy_token_text(Context *ctx)
|
static char *copy_token_text(Context *ctx)
|
||||||
{
|
{
|
||||||
char *copy = BPAlloc_Malloc(ctx->alloc, ctx->token->length + 1);
|
char *copy = BPAlloc_Malloc(ctx->alloc, ctx->token->length + 1);
|
||||||
@@ -705,6 +795,9 @@ static Node *parse_primary_expresion(Context *ctx)
|
|||||||
return (Node*) temp;
|
return (Node*) temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case '[':
|
||||||
|
return parse_list_primary_expression(ctx);
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
{
|
{
|
||||||
next(ctx); // Consume the '('.
|
next(ctx); // Consume the '('.
|
||||||
|
|||||||
+1
-12
@@ -453,9 +453,6 @@ _Bool Debug_Callback(Runtime *runtime, void *userp)
|
|||||||
Stack *stack = Runtime_GetStack(runtime);
|
Stack *stack = Runtime_GetStack(runtime);
|
||||||
assert(stack != NULL);
|
assert(stack != NULL);
|
||||||
|
|
||||||
Error error;
|
|
||||||
Error_Init(&error);
|
|
||||||
|
|
||||||
if(Stack_Size(stack) == 0)
|
if(Stack_Size(stack) == 0)
|
||||||
fprintf(stderr, "The stack is empty.\n");
|
fprintf(stderr, "The stack is empty.\n");
|
||||||
|
|
||||||
@@ -465,15 +462,7 @@ _Bool Debug_Callback(Runtime *runtime, void *userp)
|
|||||||
assert(obj != NULL);
|
assert(obj != NULL);
|
||||||
|
|
||||||
fprintf(stderr, " %d | ", i);
|
fprintf(stderr, " %d | ", i);
|
||||||
Object_Print(obj, stderr, &error);
|
Object_Print(obj, stderr);
|
||||||
|
|
||||||
if(error.occurred)
|
|
||||||
{
|
|
||||||
Error_Free(&error);
|
|
||||||
Error_Init(&error);
|
|
||||||
fprintf(stderr, "(unprintable)");
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ typedef struct {
|
|||||||
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
|
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
|
||||||
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
|
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
|
||||||
static int count(Object *self);
|
static int count(Object *self);
|
||||||
|
static void print(Object *obj, FILE *fp);
|
||||||
|
|
||||||
static const Type t_list = {
|
static const Type t_list = {
|
||||||
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
|
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
|
||||||
@@ -19,6 +20,7 @@ static const Type t_list = {
|
|||||||
.select = select,
|
.select = select,
|
||||||
.insert = insert,
|
.insert = insert,
|
||||||
.count = count,
|
.count = count,
|
||||||
|
.print = print,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int calc_capacity(int mapper_size)
|
static inline int calc_capacity(int mapper_size)
|
||||||
@@ -152,3 +154,16 @@ static int count(Object *self)
|
|||||||
|
|
||||||
return list->count;
|
return list->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print(Object *self, FILE *fp)
|
||||||
|
{
|
||||||
|
ListObject *list = (ListObject*) self;
|
||||||
|
|
||||||
|
for(int i = 0; i < list->count; i += 1)
|
||||||
|
{
|
||||||
|
Object_Print(list->vals[i], fp);
|
||||||
|
|
||||||
|
if(i+1 < list->count)
|
||||||
|
fprintf(fp, ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ typedef struct {
|
|||||||
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
|
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
|
||||||
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
|
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
|
||||||
static int count(Object *self);
|
static int count(Object *self);
|
||||||
|
static void print(Object *self, FILE *fp);
|
||||||
|
|
||||||
static const Type t_map = {
|
static const Type t_map = {
|
||||||
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
|
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
|
||||||
@@ -21,6 +22,7 @@ static const Type t_map = {
|
|||||||
.select = select,
|
.select = select,
|
||||||
.insert = insert,
|
.insert = insert,
|
||||||
.count = count,
|
.count = count,
|
||||||
|
.print = print,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int calc_capacity(int mapper_size)
|
static inline int calc_capacity(int mapper_size)
|
||||||
@@ -74,6 +76,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
|||||||
assert(heap != NULL);
|
assert(heap != NULL);
|
||||||
assert(error != NULL);
|
assert(error != NULL);
|
||||||
|
|
||||||
|
fprintf(stderr, "Selecting from:\n\t");
|
||||||
|
Object_Print(self, stderr);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
MapObject *map = (MapObject*) self;
|
MapObject *map = (MapObject*) self;
|
||||||
|
|
||||||
int mask = map->mapper_size - 1;
|
int mask = map->mapper_size - 1;
|
||||||
@@ -86,10 +92,15 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
|||||||
|
|
||||||
int i = hash & mask;
|
int i = hash & mask;
|
||||||
|
|
||||||
|
#warning "TEMP"
|
||||||
|
fprintf(stderr, "-----------------\n");
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
int k = map->mapper[i];
|
int k = map->mapper[i];
|
||||||
|
|
||||||
|
fprintf(stderr, "map->mapper[%d] = %d\n", i, k);
|
||||||
|
|
||||||
if(k == -1)
|
if(k == -1)
|
||||||
{
|
{
|
||||||
// Empty slot.
|
// Empty slot.
|
||||||
@@ -102,6 +113,10 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
|||||||
// Is it the right one?
|
// Is it the right one?
|
||||||
|
|
||||||
assert(k >= 0);
|
assert(k >= 0);
|
||||||
|
#warning "TEMP"
|
||||||
|
fprintf(stderr, "map->keys[%d] = ", k);
|
||||||
|
Object_Print(map->keys[k], stderr);
|
||||||
|
fprintf(stderr, " (of type %s)\n", Object_GetName(map->keys[k]));
|
||||||
|
|
||||||
if(Object_Compare(key, map->keys[k], error))
|
if(Object_Compare(key, map->keys[k], error))
|
||||||
// Found it!
|
// Found it!
|
||||||
@@ -114,8 +129,12 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
|
|||||||
// Not the one we wanted.
|
// Not the one we wanted.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int old_i = i;
|
||||||
|
|
||||||
pert >>= 5;
|
pert >>= 5;
|
||||||
i = (i * 5 + pert + 1) & mask;
|
i = (i * 5 + pert + 1) & mask;
|
||||||
|
|
||||||
|
fprintf(stderr, "%d -> %d\n", old_i, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
UNREACHABLE;
|
UNREACHABLE;
|
||||||
@@ -259,3 +278,18 @@ static int count(Object *self)
|
|||||||
|
|
||||||
return map->count;
|
return map->count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print(Object *self, FILE *fp)
|
||||||
|
{
|
||||||
|
MapObject *map = (MapObject*) self;
|
||||||
|
|
||||||
|
for(int i = 0; i < map->count; i += 1)
|
||||||
|
{
|
||||||
|
Object_Print(map->keys[i], fp);
|
||||||
|
fprintf(fp, ": ");
|
||||||
|
Object_Print(map->vals[i], fp);
|
||||||
|
|
||||||
|
if(i+1 < map->count)
|
||||||
|
fprintf(fp, ", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -94,7 +94,12 @@ static _Bool op_eql(Object *self, Object *other)
|
|||||||
StringObject *s1 = (StringObject*) self;
|
StringObject *s1 = (StringObject*) self;
|
||||||
StringObject *s2 = (StringObject*) other;
|
StringObject *s2 = (StringObject*) other;
|
||||||
|
|
||||||
return s1->size == s2->size && !strncmp(s1->body, s2->body, s1->size);
|
_Bool match = s1->size == s2->size && !strncmp(s1->body, s2->body, s1->size);
|
||||||
|
|
||||||
|
#warning "TEMP"
|
||||||
|
fprintf(stderr, "%s == %s ? %s\n", s1->body, s2->body, match ? "yes" : "no");
|
||||||
|
|
||||||
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void print(Object *obj, FILE *fp)
|
static void print(Object *obj, FILE *fp)
|
||||||
|
|||||||
@@ -106,22 +106,17 @@ Object *Object_Call(Object *obj, Object **argv, unsigned int argc, Heap *heap, E
|
|||||||
return type->call(obj, argv, argc, heap, err);
|
return type->call(obj, argv, argc, heap, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Bool Object_Print(Object *obj, FILE *fp, Error *error)
|
void Object_Print(Object *obj, FILE *fp)
|
||||||
{
|
{
|
||||||
assert(error != NULL);
|
|
||||||
assert(obj != NULL);
|
assert(obj != NULL);
|
||||||
|
|
||||||
const Type *type = Object_GetType(obj);
|
const Type *type = Object_GetType(obj);
|
||||||
assert(type);
|
assert(type);
|
||||||
|
|
||||||
if(type->print == NULL)
|
if(type->print == NULL)
|
||||||
{
|
fprintf(fp, "<%s is unprintable>", Object_GetName(obj));
|
||||||
Error_Report(error, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
|
else
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
type->print(obj, fp);
|
type->print(obj, fp);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err)
|
Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err);
|
|||||||
int Object_Hash (Object *obj, Error *err);
|
int Object_Hash (Object *obj, Error *err);
|
||||||
Object* Object_Copy (Object *obj, Heap *heap, Error *err);
|
Object* Object_Copy (Object *obj, Heap *heap, Error *err);
|
||||||
Object* Object_Call (Object *obj, Object **argv, unsigned int argc, Heap *heap, Error *err);
|
Object* Object_Call (Object *obj, Object **argv, unsigned int argc, Heap *heap, Error *err);
|
||||||
_Bool Object_Print (Object *obj, FILE *fp, Error *error);
|
void Object_Print (Object *obj, FILE *fp);
|
||||||
Object* Object_Select(Object *coll, Object *key, Heap *heap, Error *err);
|
Object* Object_Select(Object *coll, Object *key, Heap *heap, Error *err);
|
||||||
Object* Object_Delete(Object *coll, Object *key, Heap *heap, Error *err);
|
Object* Object_Delete(Object *coll, Object *key, Heap *heap, Error *err);
|
||||||
_Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *err);
|
_Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *err);
|
||||||
|
|||||||
+13
-2
@@ -4,11 +4,21 @@
|
|||||||
static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
|
static Object *bin_print(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < (int) argc; i += 1)
|
for(int i = 0; i < (int) argc; i += 1)
|
||||||
Object_Print(argv[i], stdout, error);
|
Object_Print(argv[i], stdout);
|
||||||
|
|
||||||
return Object_NewNone(Runtime_GetHeap(runtime), error);
|
return Object_NewNone(Runtime_GetHeap(runtime), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Object *bin_count(Runtime *runtime, Object **argv, unsigned int argc, Error *error)
|
||||||
|
{
|
||||||
|
int n = Object_Count(argv[0], error);
|
||||||
|
|
||||||
|
if(error->occurred)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return Object_FromInt(n, Runtime_GetHeap(runtime), error);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
int argc;
|
int argc;
|
||||||
@@ -17,6 +27,7 @@ typedef struct {
|
|||||||
|
|
||||||
BuiltinNativeFunctions builtins[] = {
|
BuiltinNativeFunctions builtins[] = {
|
||||||
{"print", -1, bin_print},
|
{"print", -1, bin_print},
|
||||||
|
{"count", 1, bin_count},
|
||||||
};
|
};
|
||||||
|
|
||||||
_Bool add_builtins(Runtime *runtime, Error *error)
|
_Bool add_builtins(Runtime *runtime, Error *error)
|
||||||
@@ -29,7 +40,7 @@ _Bool add_builtins(Runtime *runtime, Error *error)
|
|||||||
if(dest == NULL)
|
if(dest == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for(int i = 0; i < (int) (sizeof(builtins) / sizeof(builtins[0])); i += 1)
|
for(int i = 0; (unsigned int) i < sizeof(builtins) / sizeof(builtins[0]); i += 1)
|
||||||
{
|
{
|
||||||
Object *name = Object_FromString(builtins[i].name, -1, heap, error);
|
Object *name = Object_FromString(builtins[i].name, -1, heap, error);
|
||||||
|
|
||||||
|
|||||||
+41
-1
@@ -641,6 +641,30 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OPCODE_INSERT:
|
||||||
|
{
|
||||||
|
assert(opc == 0);
|
||||||
|
|
||||||
|
if(runtime->frame->used < 3)
|
||||||
|
{
|
||||||
|
Error_Report(error, 1, "Frame has not enough values on the stack to run INSERT instruction");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object *col = Stack_Top(runtime->stack, -2);
|
||||||
|
Object *key = Stack_Top(runtime->stack, -1);
|
||||||
|
Object *val = Stack_Top(runtime->stack, 0);
|
||||||
|
|
||||||
|
assert(col != NULL && key != NULL && val != NULL);
|
||||||
|
|
||||||
|
if(!Runtime_Pop(runtime, error, 2))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!Object_Insert(col, key, val, runtime->heap, error))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
case OPCODE_PUSHINT:
|
case OPCODE_PUSHINT:
|
||||||
{
|
{
|
||||||
assert(opc == 1);
|
assert(opc == 1);
|
||||||
@@ -713,7 +737,8 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(obj == NULL)
|
else
|
||||||
|
if(obj == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if(!Runtime_Push(runtime, error, obj))
|
if(!Runtime_Push(runtime, error, obj))
|
||||||
@@ -780,6 +805,21 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OPCODE_PUSHLST:
|
||||||
|
{
|
||||||
|
assert(opc == 1);
|
||||||
|
assert(ops[0].type == OPTP_INT);
|
||||||
|
|
||||||
|
Object *obj = Object_NewList(ops[0].as_int, runtime->heap, error);
|
||||||
|
|
||||||
|
if(obj == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!Runtime_Push(runtime, error, obj))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
case OPCODE_RETURN:
|
case OPCODE_RETURN:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user