added index selection
This commit is contained in:
+1
-3
@@ -23,6 +23,4 @@ do
|
||||
while i < 3;
|
||||
|
||||
# ------------------------------------- #
|
||||
# ------------------------------------- #
|
||||
|
||||
print(count(1, 2));
|
||||
# ------------------------------------- #
|
||||
@@ -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}},
|
||||
|
||||
@@ -38,6 +38,7 @@ typedef enum {
|
||||
OPCODE_POP,
|
||||
OPCODE_CALL,
|
||||
OPCODE_INSERT,
|
||||
OPCODE_SELECT,
|
||||
OPCODE_PUSHINT,
|
||||
OPCODE_PUSHFLT,
|
||||
OPCODE_PUSHSTR,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user