added index selection

This commit is contained in:
Francesco Cozzuto
2021-11-25 11:25:23 +01:00
parent fdaebdaecc
commit ba9c01f261
7 changed files with 89 additions and 3 deletions
+1
View File
@@ -59,6 +59,7 @@ static const InstrInfo instr_table[] = {
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_CALL] = {"CALL", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_INSERT] = {"INSERT", 0, NULL},
[OPCODE_SELECT] = {"SELECT", 0, NULL},
[OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}},
[OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}},
+1
View File
@@ -38,6 +38,7 @@ typedef enum {
OPCODE_POP,
OPCODE_CALL,
OPCODE_INSERT,
OPCODE_SELECT,
OPCODE_PUSHINT,
OPCODE_PUSHFLT,
OPCODE_PUSHSTR,
+7
View File
@@ -40,6 +40,7 @@ typedef enum {
EXPR_FLOAT,
EXPR_STRING,
EXPR_IDENT,
EXPR_SELECT,
} ExprKind;
typedef struct Node Node;
@@ -104,6 +105,12 @@ typedef struct {
int argc;
} CallExprNode;
typedef struct {
ExprNode base;
Node *idx;
Node *set;
} IndexSelectionExprNode;
typedef struct {
Node base;
Node *condition;
+13
View File
@@ -188,6 +188,19 @@ static _Bool emit_instr_for_node(ExeBuilder *exeb, Node *node, Error *error)
return ExeBuilder_Append(exeb, error, OPCODE_CALL, &op, 1, node->offset, node->length);
}
case EXPR_SELECT:
{
IndexSelectionExprNode *sel = (IndexSelectionExprNode*) expr;
if(!emit_instr_for_node(exeb, sel->set, error))
return 0;
if(!emit_instr_for_node(exeb, sel->idx, error))
return 0;
return ExeBuilder_Append(exeb, error, OPCODE_SELECT, NULL, 0, node->offset, node->length);
}
case EXPR_NONE:
return ExeBuilder_Append(exeb, error, OPCODE_PUSHNNE, NULL, 0, node->offset, node->length);
+38
View File
@@ -1160,6 +1160,44 @@ static Node *parse_postfix_expression(Context *ctx)
{
switch(current(ctx))
{
case '[':
{
Node *idx = parse_list_primary_expression(ctx);
if(idx == NULL)
return NULL;
ListExprNode *ls = (ListExprNode*) idx;
if(ls->itemc == 0)
{
Error_Report(ctx->error, 0, "Missing index in index selection expression");
return NULL;
}
IndexSelectionExprNode *sel;
{
sel = BPAlloc_Malloc(ctx->alloc, sizeof(IndexSelectionExprNode));
if(sel == NULL)
{
Error_Report(ctx->error, 1, "No memory");
return NULL;
}
sel->base.base.kind = NODE_EXPR;
sel->base.base.next = NULL;
sel->base.base.offset = node->offset;
sel->base.base.length = idx->offset + idx->length - node->offset;
sel->base.kind = EXPR_SELECT;
sel->set = node;
sel->idx = ls->itemc == 1 ? ls->items : (Node*) ls;
}
node = (Node*) sel;
break;
}
case '(':
{
int offset = current_token(ctx)->offset;
+28
View File
@@ -665,6 +665,34 @@ static _Bool step(Runtime *runtime, Error *error)
return 1;
}
case OPCODE_SELECT:
{
assert(opc == 0);
if(runtime->frame->used < 2)
{
Error_Report(error, 1, "Frame has not enough values on the stack to run SELECT instruction");
return NULL;
}
Object *col = Stack_Top(runtime->stack, -1);
Object *key = Stack_Top(runtime->stack, 0);
assert(col != NULL && key != NULL);
if(!Runtime_Pop(runtime, error, 2))
return 0;
Object *val = Object_Select(col, key, runtime->heap, error);
if(val == NULL)
return 0;
if(!Runtime_Push(runtime, error, val))
return 0;
return 1;
}
case OPCODE_PUSHINT:
{
assert(opc == 1);