refactoring of the instruction table; removed unused instructions PUSHTYPTYP and ERROR; new modulo operator %; new examples fibonacci.noja and isprime.noja

This commit is contained in:
cozis
2022-12-07 18:31:35 +01:00
parent d483822538
commit 98374ee491
12 changed files with 194 additions and 11453 deletions
+80 -60
View File
@@ -37,6 +37,7 @@
#include "executable.h"
#define MAX_OPS 3
#define MAX_OPCODE_NAME_SIZE 127
typedef struct {
Opcode opcode;
@@ -62,84 +63,104 @@ struct xExeBuilder {
};
typedef struct {
Opcode opcode;
const char *name;
int opcount;
int opcount;
OperandType *optypes;
} InstrInfo;
#define INSTR(name, ...) \
{ \
OPCODE_##name, \
#name, \
sizeof((OperandType[]) { __VA_ARGS__ }) / sizeof(OperandType), \
(OperandType[]) { __VA_ARGS__ }, \
},
static const InstrInfo instr_table[] = {
[OPCODE_NOPE] = {"NOPE", 0, NULL},
[OPCODE_POS] = {"POS", 0, NULL},
[OPCODE_NEG] = {"NEG", 0, NULL},
[OPCODE_NOT] = {"NOT", 0, NULL},
[OPCODE_ADD] = {"ADD", 0, NULL},
[OPCODE_SUB] = {"SUB", 0, NULL},
[OPCODE_MUL] = {"MUL", 0, NULL},
[OPCODE_DIV] = {"DIV", 0, NULL},
[OPCODE_EQL] = {"EQL", 0, NULL},
[OPCODE_NQL] = {"NQL", 0, NULL},
[OPCODE_LSS] = {"LSS", 0, NULL},
[OPCODE_GRT] = {"GRT", 0, NULL},
[OPCODE_LEQ] = {"LEQ", 0, NULL},
[OPCODE_GEQ] = {"GEQ", 0, NULL},
[OPCODE_NLB] = {"NLB", 0, NULL},
[OPCODE_STP] = {"STP", 0, NULL},
[OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}},
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_CHECKTYPE] = {"CHECKTYPE", 2, (OperandType[]) {OPTP_INT, OPTP_STRING}},
[OPCODE_CALL] = {"CALL", 2, (OperandType[]) {OPTP_INT, OPTP_INT}},
[OPCODE_SELECT] = {"SELECT", 0, NULL},
[OPCODE_INSERT] = {"INSERT", 0, NULL},
[OPCODE_INSERT2] = {"INSERT2", 0, NULL},
[OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}},
[OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}},
[OPCODE_PUSHVAR] = {"PUSHVAR", 1, (OperandType[]) {OPTP_STRING}},
[OPCODE_PUSHTRU] = {"PUSHTRU", 0, NULL},
[OPCODE_PUSHFLS] = {"PUSHFLS", 0, NULL},
[OPCODE_PUSHNNE] = {"PUSHNNE", 0, NULL},
[OPCODE_PUSHFUN] = {"PUSHFUN", 2, (OperandType[]) {OPTP_IDX, OPTP_INT}},
[OPCODE_PUSHLST] = {"PUSHLST", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_PUSHMAP] = {"PUSHMAP", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_PUSHTYP] = {"PUSHTYP", 0, NULL},
[OPCODE_PUSHTYPTYP] = {"PUSHTYPTYP", 0, NULL},
[OPCODE_PUSHNNETYP] = {"PUSHNNETYP", 0, NULL},
[OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}},
[OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}},
[OPCODE_EXIT] = {"EXIT", 0, NULL},
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}},
[OPCODE_JUMPIFANDPOP] = {"JUMPIFANDPOP", 1, (OperandType[]) {OPTP_IDX}},
[OPCODE_JUMP] = {"JUMP", 1, (OperandType[]) {OPTP_IDX}},
INSTR(NOPE)
INSTR(POS)
INSTR(NEG)
INSTR(NOT)
INSTR(ADD)
INSTR(SUB)
INSTR(MUL)
INSTR(DIV)
INSTR(EQL)
INSTR(NQL)
INSTR(LSS)
INSTR(GRT)
INSTR(LEQ)
INSTR(GEQ)
INSTR(NLB)
INSTR(STP)
INSTR(ASS, OPTP_STRING)
INSTR(POP, OPTP_INT)
INSTR(CHECKTYPE, OPTP_INT, OPTP_STRING)
INSTR(CALL, OPTP_INT, OPTP_INT)
INSTR(SELECT)
INSTR(INSERT)
INSTR(INSERT2)
INSTR(PUSHINT, OPTP_INT)
INSTR(PUSHFLT, OPTP_FLOAT)
INSTR(PUSHSTR, OPTP_STRING)
INSTR(PUSHVAR, OPTP_STRING)
INSTR(PUSHTRU)
INSTR(PUSHFLS)
INSTR(PUSHNNE)
INSTR(PUSHFUN, OPTP_IDX, OPTP_INT)
INSTR(PUSHLST, OPTP_INT)
INSTR(PUSHMAP, OPTP_INT)
INSTR(PUSHTYP)
INSTR(PUSHNNETYP)
INSTR(RETURN, OPTP_INT)
INSTR(EXIT)
INSTR(JUMPIFNOTANDPOP, OPTP_IDX)
INSTR(JUMPIFANDPOP, OPTP_IDX)
INSTR(JUMP, OPTP_IDX)
};
_Bool Executable_GetOpcodeBinaryFromName(const char *name, size_t name_len, Opcode *opcode)
static const size_t instr_count = sizeof(instr_table)/sizeof(instr_table[0]);
_Bool Executable_GetOpcodeBinaryFromName(const char *name, size_t len, Opcode *opcode)
{
// The input name is assumed not zero-terminated,
// so to simplify things we duplicate it to add
// an extra null byte.
char buff[128]; // No opcode should have a name this big.
ASSERT(name_len < sizeof(buff)); // If this is triggered, [buff] should be made bigger.
memcpy(buff, name, name_len);
buff[name_len] = '\0';
char buff[MAX_OPCODE_NAME_SIZE+1]; // No opcode should have a name this big.
if (len >= sizeof(buff))
return false;
memcpy(buff, name, len);
buff[len] = '\0';
name = buff;
// Now name is zero terminated.
ASSERT(name[name_len] == '\0');
ASSERT(name[len] == '\0');
for(size_t i = 0; i < sizeof(instr_table)/sizeof(instr_table[0]); i += 1) {
for(size_t i = 0; i < instr_count; i += 1) {
if(!strcmp(name, instr_table[i].name)) {
*opcode = i; // Is this safe?
if (opcode != NULL)
*opcode = instr_table[i].opcode;
return 1;
}
}
return 0;
}
static const InstrInfo *Executable_GetInstrByOpcode(Opcode opcode)
{
for (size_t i = 0; i < instr_count; i++)
if (instr_table[i].opcode == opcode)
return instr_table + i;
return NULL;
}
const char *Executable_GetOpcodeName(Opcode opcode)
{
return instr_table[opcode].name;
const InstrInfo *instr = Executable_GetInstrByOpcode(opcode);
if (instr == NULL)
return NULL;
return instr->name;
}
Executable *Executable_Copy(Executable *exe)
@@ -172,8 +193,8 @@ void Executable_Dump(Executable *exe)
int opc = MAX_OPS;
(void) Executable_Fetch(exe, i, &opcode, ops, &opc);
const InstrInfo *info = instr_table + exe->body[i].opcode;
const InstrInfo *info = Executable_GetInstrByOpcode(opcode);
fprintf(stderr, "%d: %s ", i, info->name);
@@ -250,7 +271,7 @@ _Bool Executable_Fetch(Executable *exe, int index, Opcode *opcode, Operand *ops,
return 0;
const Instruction *instr = exe->body + index;
const InstrInfo *info = instr_table + instr->opcode;
const InstrInfo *info = Executable_GetInstrByOpcode(instr->opcode);
if(opcode)
*opcode = instr->opcode;
@@ -497,7 +518,7 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
[OPTP_STRING] = membersizeof(Operand, as_string),
};
const InstrInfo *info = instr_table + opcode;
const InstrInfo *info = Executable_GetInstrByOpcode(opcode);
if(opc != info->opcount)
{
@@ -633,5 +654,4 @@ int ExeBuilder_InstrCount(ExeBuilder *exeb)
ASSERT(raw_size % sizeof(Instruction) == 0);
return raw_size / sizeof(Instruction);
}
}
+1 -2
View File
@@ -61,6 +61,7 @@ typedef enum {
OPCODE_SUB,
OPCODE_MUL,
OPCODE_DIV,
OPCODE_MOD,
OPCODE_EQL,
OPCODE_NQL,
OPCODE_LSS,
@@ -86,10 +87,8 @@ typedef enum {
OPCODE_PUSHLST,
OPCODE_PUSHMAP,
OPCODE_PUSHTYP,
OPCODE_PUSHTYPTYP,
OPCODE_PUSHNNETYP,
OPCODE_RETURN,
OPCODE_ERROR,
OPCODE_EXIT,
OPCODE_JUMPIFANDPOP,
OPCODE_JUMPIFNOTANDPOP,
+1
View File
@@ -52,6 +52,7 @@ typedef enum {
EXPR_SUB,
EXPR_MUL,
EXPR_DIV,
EXPR_MOD,
EXPR_EQL,
EXPR_NQL,
+2 -14
View File
@@ -135,14 +135,6 @@ static void emitInstr_EQL(CodegenContext *ctx, int off, int len)
CodegenContext_EmitInstr(ctx, OPCODE_EQL, NULL, 0, off, len);
}
static void emitInstr_ERROR(CodegenContext *ctx, const char *msg, int off, int len)
{
Operand opv[1] = {
{ .type = OPTP_STRING, .as_string = msg },
};
CodegenContext_EmitInstr(ctx, OPCODE_ERROR, opv, 1, off, len);
}
static void emitInstr_CHECKTYPE(CodegenContext *ctx, int arg_index, const char *arg_name, int off, int len)
{
Operand opv[2] = {
@@ -167,11 +159,6 @@ static void emitInstr_PUSHTYP(CodegenContext *ctx, int off, int len)
CodegenContext_EmitInstr(ctx, OPCODE_PUSHTYP, NULL, 0, off, len);
}
static void emitInstr_PUSHTYPTYP(CodegenContext *ctx, int off, int len)
{
CodegenContext_EmitInstr(ctx, OPCODE_PUSHTYPTYP, NULL, 0, off, len);
}
static void emitInstr_PUSHNNETYP(CodegenContext *ctx, int off, int len)
{
CodegenContext_EmitInstr(ctx, OPCODE_PUSHNNETYP, NULL, 0, off, len);
@@ -192,6 +179,7 @@ static Opcode exprkind_to_opcode(ExprKind kind)
case EXPR_SUB: return OPCODE_SUB;
case EXPR_MUL: return OPCODE_MUL;
case EXPR_DIV: return OPCODE_DIV;
case EXPR_MOD: return OPCODE_MOD;
case EXPR_EQL: return OPCODE_EQL;
case EXPR_NQL: return OPCODE_NQL;
case EXPR_LSS: return OPCODE_LSS;
@@ -391,7 +379,7 @@ static void emitInstrForExprNode(CodegenContext *ctx, ExprNode *expr,
case EXPR_NULLABLETYPE:
case EXPR_SUMTYPE:
case EXPR_NOT:
case EXPR_NOT: case EXPR_MOD:
case EXPR_POS: case EXPR_NEG:
case EXPR_ADD: case EXPR_SUB:
case EXPR_MUL: case EXPR_DIV:
+7 -2
View File
@@ -71,6 +71,7 @@ typedef enum {
TSUB = '-',
TMUL = '*',
TDIV = '/',
TMOD = '%',
TLSS = '<',
TGRT = '>',
@@ -145,7 +146,8 @@ static inline _Bool isoper(char c)
c == '*' || c == '/' ||
c == '<' || c == '>' ||
c == '!' || c == '=' ||
c == ',' || c == '|';
c == ',' || c == '|' ||
c == '%';
}
/* Symbol: tokenize
@@ -328,6 +330,7 @@ static Token *tokenize(Source *src, BPAlloc *alloc, Error *error)
{ TASS, 1, "=" },
{ TCOMMA, 1, "," },
{ TSMT, 1, "|" },
{ TMOD, 1, "%" },
};
_Bool found = 0;
@@ -1603,7 +1606,7 @@ static inline _Bool isbinop(Token *tok)
tok->kind == TEQL || tok->kind == TNQL ||
tok->kind == TKWAND || tok->kind == TKWOR ||
tok->kind == '=' || tok->kind == ',' ||
tok->kind == '|';
tok->kind == '|' || tok->kind == '%';
}
static inline _Bool isrightassoc(Token *tok)
@@ -1645,6 +1648,7 @@ static inline int precedenceof(Token *tok)
case '*':
case '/':
case '%':
return 6;
case ',':
@@ -1707,6 +1711,7 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bo
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_MOD; break;
case '<': temp->base.kind = EXPR_LSS; break;
case '>': temp->base.kind = EXPR_GRT; break;
case TLEQ: temp->base.kind = EXPR_LEQ; break;
+34 -21
View File
@@ -739,6 +739,40 @@ static _Bool step(Runtime *runtime, Error *error)
return 1;
}
case OPCODE_MOD:
{
ASSERT(opc == 0);
Object *rop = Stack_Top(runtime->stack, 0);
Object *lop = Stack_Top(runtime->stack, -1);
if(!Runtime_Pop(runtime, error, 2))
return 0;
// We managed to pop rop and lop,
// so we know they're not NULL.
ASSERT(rop != NULL);
ASSERT(lop != NULL);
if (!Object_IsInt(rop) || !Object_IsInt(lop)) {
Error_Report(error, 0, "Arithmetic operation on a non-numeric object");
return 0;
}
long long int x, y, z;
y = Object_GetInt(rop);
x = Object_GetInt(lop);
z = x % y;
Object *res = Object_FromInt(z, runtime->heap, error);
if(res == NULL)
return 0;
if(!Runtime_Push(runtime, error, res))
return 0;
return 1;
}
case OPCODE_EQL:
case OPCODE_NQL:
{
@@ -1213,18 +1247,6 @@ static _Bool step(Runtime *runtime, Error *error)
return 1;
}
case OPCODE_PUSHTYPTYP:
{
ASSERT(opc == 0);
Object *obj = (Object*) Object_GetTypeType();
ASSERT(obj != NULL);
if(!Runtime_Push(runtime, error, obj))
return 0;
return 1;
}
case OPCODE_PUSHNNETYP:
{
ASSERT(opc == 0);
@@ -1282,15 +1304,6 @@ static _Bool step(Runtime *runtime, Error *error)
return 0;
}
case OPCODE_ERROR:
{
ASSERT(opc == 1);
ASSERT(ops[0].type == OPTP_STRING);
const char *msg = ops[0].as_string;
Error_Report(error, 0, "%s", msg);
return 0;
}
case OPCODE_JUMP:
ASSERT(opc == 1);
ASSERT(ops[0].type == OPTP_IDX);