new -> operator
This commit is contained in:
@@ -99,6 +99,7 @@ static const InstrInfo instr_table[] = {
|
||||
INSTR(CHECKTYPE, OPTP_INT, OPTP_STRING)
|
||||
INSTR(CALL, OPTP_INT, OPTP_INT)
|
||||
INSTR(SELECT)
|
||||
INSTR(SELECT2)
|
||||
INSTR(INSERT)
|
||||
INSTR(INSERT2)
|
||||
INSTR(PUSHINT, OPTP_INT)
|
||||
@@ -520,6 +521,13 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
|
||||
|
||||
const InstrInfo *info = Executable_GetInstrByOpcode(opcode);
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (info == NULL) {
|
||||
Error_Report(error, 1, "Missing instruction table entry for opcode");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(opc != info->opcount)
|
||||
{
|
||||
// ERROR: Too many operands were provided.
|
||||
|
||||
@@ -74,6 +74,7 @@ typedef enum {
|
||||
OPCODE_POP,
|
||||
OPCODE_CALL,
|
||||
OPCODE_SELECT,
|
||||
OPCODE_SELECT2,
|
||||
OPCODE_INSERT,
|
||||
OPCODE_INSERT2,
|
||||
OPCODE_PUSHINT,
|
||||
|
||||
@@ -65,6 +65,7 @@ typedef enum {
|
||||
EXPR_OR,
|
||||
EXPR_NOT,
|
||||
|
||||
EXPR_ARW,
|
||||
EXPR_ASS,
|
||||
EXPR_INT,
|
||||
EXPR_MAP,
|
||||
|
||||
@@ -198,19 +198,34 @@ static void emitInstrForFuncCallNode(CodegenContext *ctx, CallExprNode *expr,
|
||||
Label *label_break, int returns)
|
||||
{
|
||||
Node *arg = expr->argv;
|
||||
|
||||
while(arg)
|
||||
{
|
||||
emitInstrForNode(ctx, arg, label_break);
|
||||
arg = arg->next;
|
||||
}
|
||||
|
||||
emitInstrForNode(ctx, expr->func, label_break);
|
||||
int argc;
|
||||
if (expr->func->kind == NODE_EXPR && ((ExprNode*) expr->func)->kind == EXPR_ARW) {
|
||||
IndexSelectionExprNode *selection = (IndexSelectionExprNode*) expr->func;
|
||||
Node *idx = selection->idx;
|
||||
Node *set = selection->set;
|
||||
emitInstrForNode(ctx, set, label_break);
|
||||
emitInstrForNode(ctx, idx, label_break);
|
||||
CodegenContext_EmitInstr(ctx, OPCODE_SELECT2, NULL, 0,
|
||||
expr->func->offset,
|
||||
expr->func->length);
|
||||
argc = expr->argc+1;
|
||||
} else {
|
||||
emitInstrForNode(ctx, expr->func, label_break);
|
||||
argc = expr->argc;
|
||||
}
|
||||
|
||||
Operand ops[2];
|
||||
ops[0] = (Operand) { .type = OPTP_INT, .as_int = expr->argc };
|
||||
ops[0] = (Operand) { .type = OPTP_INT, .as_int = argc };
|
||||
ops[1] = (Operand) { .type = OPTP_INT, .as_int = returns };
|
||||
CodegenContext_EmitInstr(ctx, OPCODE_CALL, ops, 2, expr->base.base.offset, expr->base.base.length);
|
||||
CodegenContext_EmitInstr(ctx, OPCODE_CALL, ops, 2,
|
||||
expr->base.base.offset,
|
||||
expr->base.base.length);
|
||||
}
|
||||
|
||||
static void emitInstrForExprNode(CodegenContext *ctx, ExprNode *expr,
|
||||
@@ -394,6 +409,11 @@ static void emitInstrForExprNode(CodegenContext *ctx, ExprNode *expr,
|
||||
return;
|
||||
}
|
||||
|
||||
case EXPR_ARW:
|
||||
CodegenContext_ReportErrorAndJump(ctx, 0, "Operator -> out of a function call");
|
||||
UNREACHABLE;
|
||||
return;
|
||||
|
||||
case EXPR_AND:
|
||||
{
|
||||
OperExprNode *oper = (OperExprNode*) expr;
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
** +--------------------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
@@ -112,6 +113,7 @@ typedef enum {
|
||||
TNQL,
|
||||
TLEQ,
|
||||
TGEQ,
|
||||
TARW,
|
||||
|
||||
} TokenKind;
|
||||
|
||||
@@ -331,6 +333,7 @@ static Token *tokenize(Source *src, BPAlloc *alloc, Error *error)
|
||||
{ TCOMMA, 1, "," },
|
||||
{ TSMT, 1, "|" },
|
||||
{ TMOD, 1, "%" },
|
||||
{ TARW, 2, "->" },
|
||||
};
|
||||
|
||||
_Bool found = 0;
|
||||
@@ -1364,7 +1367,7 @@ static Node *parse_primary_expresion(Context *ctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Node *makeIndexSelectionExprNode(Context *ctx, Node *set, Node *idx)
|
||||
static Node *makeIndexOrArrowSelectionExprNode(Context *ctx, bool arrow, Node *set, Node *idx)
|
||||
{
|
||||
IndexSelectionExprNode *sel = BPAlloc_Malloc(ctx->alloc, sizeof(IndexSelectionExprNode));
|
||||
|
||||
@@ -1378,7 +1381,7 @@ static Node *makeIndexSelectionExprNode(Context *ctx, Node *set, Node *idx)
|
||||
sel->base.base.next = NULL;
|
||||
sel->base.base.offset = -1;
|
||||
sel->base.base.length = -1;
|
||||
sel->base.kind = EXPR_SELECT;
|
||||
sel->base.kind = arrow ? EXPR_ARW : EXPR_SELECT;
|
||||
sel->set = set;
|
||||
sel->idx = idx;
|
||||
return (Node*) sel;
|
||||
@@ -1398,20 +1401,23 @@ static Node *parse_postfix_expression(Context *ctx)
|
||||
switch(current(ctx))
|
||||
{
|
||||
case '.':
|
||||
case TARW:
|
||||
{
|
||||
bool arrow = (current(ctx) == TARW);
|
||||
|
||||
next(ctx);
|
||||
|
||||
// We expect an identifier after the dot.
|
||||
// We expect an identifier after the dot or arrow
|
||||
|
||||
if(done(ctx))
|
||||
{
|
||||
Error_Report(ctx->error, 0, "Source ended after dot of dot selection expression");
|
||||
Error_Report(ctx->error, 0, "Source ended after dot or arrow");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(current(ctx) != TIDENT)
|
||||
{
|
||||
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" after fot of dot selection expression where an identifier was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||
Error_Report(ctx->error, 0, "Got unexpected token \"%.*s\" after dot or arrow, where an identifier was expected", ctx->token->length, ctx->src + ctx->token->offset);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1419,7 +1425,7 @@ static Node *parse_postfix_expression(Context *ctx)
|
||||
if(idx == NULL)
|
||||
return NULL;
|
||||
|
||||
Node *sel = makeIndexSelectionExprNode(ctx, node, idx);
|
||||
Node *sel = makeIndexOrArrowSelectionExprNode(ctx, arrow, node, idx);
|
||||
if(sel == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1446,7 +1452,7 @@ static Node *parse_postfix_expression(Context *ctx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node *sel = makeIndexSelectionExprNode(ctx, node, ls->itemc == 1 ? ls->items : (Node*) ls);
|
||||
Node *sel = makeIndexOrArrowSelectionExprNode(ctx, false, node, ls->itemc == 1 ? ls->items : (Node*) ls);
|
||||
if(sel == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -1653,7 +1659,7 @@ static inline int precedenceof(Token *tok)
|
||||
|
||||
case ',':
|
||||
return 7;
|
||||
|
||||
|
||||
default:
|
||||
return -100000000;
|
||||
}
|
||||
@@ -1723,7 +1729,6 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bo
|
||||
case '=': temp->base.kind = EXPR_ASS; break;
|
||||
case '|': temp->base.kind = EXPR_SUMTYPE; break;
|
||||
case ',': temp->base.kind = EXPR_PAIR; break;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
break;
|
||||
|
||||
@@ -978,12 +978,18 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
}
|
||||
|
||||
case OPCODE_SELECT:
|
||||
case OPCODE_SELECT2:
|
||||
{
|
||||
ASSERT(opc == 0);
|
||||
|
||||
if(runtime->frame->used < 2)
|
||||
int to_be_popped = (opcode == OPCODE_SELECT) ? 2 : 1;
|
||||
|
||||
if(runtime->frame->used < to_be_popped)
|
||||
{
|
||||
Error_Report(error, 1, "Frame has not enough values on the stack to run SELECT instruction");
|
||||
const char *name = "SELECT";
|
||||
if (opcode == OPCODE_SELECT2)
|
||||
name = "SELECT2";
|
||||
Error_Report(error, 1, "Frame has not enough values on the stack to run %s instruction", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -992,7 +998,7 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
|
||||
ASSERT(col != NULL && key != NULL);
|
||||
|
||||
if(!Runtime_Pop(runtime, error, 2))
|
||||
if(!Runtime_Pop(runtime, error, to_be_popped))
|
||||
return 0;
|
||||
|
||||
ASSERT(error->occurred == 0);
|
||||
@@ -1007,7 +1013,6 @@ static _Bool step(Runtime *runtime, Error *error)
|
||||
Error_Free(&dummy);
|
||||
|
||||
val = Object_NewNone(runtime->heap, error);
|
||||
|
||||
if(val == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user