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:
+1
-1
@@ -11,4 +11,4 @@ vgcore.*
|
|||||||
*.gcov
|
*.gcov
|
||||||
lib*.a
|
lib*.a
|
||||||
|
|
||||||
*.noja
|
./*.noja
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
fun fibonacci(n: int) {
|
||||||
|
|
||||||
|
if n < 0:
|
||||||
|
error("Only non-negative integers allowed");
|
||||||
|
|
||||||
|
if n == 0 or n == 1:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if n == 2:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
return fibonacci(n-1)
|
||||||
|
+ fibonacci(n-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(fibonacci(10), "\n");
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
fun isPrime(n: int) {
|
||||||
|
prime = true; # First assumption
|
||||||
|
if n < 3: {
|
||||||
|
if n == 2:
|
||||||
|
prime = true;
|
||||||
|
else
|
||||||
|
prime = false;
|
||||||
|
} else {
|
||||||
|
i = 2;
|
||||||
|
sqrt = math.sqrt(n/1.0);
|
||||||
|
do {
|
||||||
|
if n % i == 0: {
|
||||||
|
prime = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = i+1;
|
||||||
|
} while i <= sqrt;
|
||||||
|
}
|
||||||
|
return prime;
|
||||||
|
}
|
||||||
|
|
||||||
|
numbers = [
|
||||||
|
[-1, false],
|
||||||
|
[ 0, false],
|
||||||
|
[ 1, false],
|
||||||
|
[ 2, true],
|
||||||
|
[ 3, true],
|
||||||
|
[ 4, false],
|
||||||
|
[ 5, true],
|
||||||
|
[ 6, false],
|
||||||
|
[ 7, true],
|
||||||
|
[ 9, false],
|
||||||
|
[10, false],
|
||||||
|
[11, true],
|
||||||
|
[12, false],
|
||||||
|
[13, true],
|
||||||
|
[14, false],
|
||||||
|
[15, false]
|
||||||
|
];
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while i < count(numbers): {
|
||||||
|
num = numbers[i][0];
|
||||||
|
exp = numbers[i][1];
|
||||||
|
res = isPrime(numbers[i][0]);
|
||||||
|
print("isPrime(", num, ") == ", res, "\n");
|
||||||
|
assert(res == exp);
|
||||||
|
i = i+1;
|
||||||
|
}
|
||||||
-11352
File diff suppressed because one or more lines are too long
+78
-58
@@ -37,6 +37,7 @@
|
|||||||
#include "executable.h"
|
#include "executable.h"
|
||||||
|
|
||||||
#define MAX_OPS 3
|
#define MAX_OPS 3
|
||||||
|
#define MAX_OPCODE_NAME_SIZE 127
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Opcode opcode;
|
Opcode opcode;
|
||||||
@@ -62,84 +63,104 @@ struct xExeBuilder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Opcode opcode;
|
||||||
const char *name;
|
const char *name;
|
||||||
int opcount;
|
int opcount;
|
||||||
OperandType *optypes;
|
OperandType *optypes;
|
||||||
} InstrInfo;
|
} InstrInfo;
|
||||||
|
|
||||||
|
#define INSTR(name, ...) \
|
||||||
|
{ \
|
||||||
|
OPCODE_##name, \
|
||||||
|
#name, \
|
||||||
|
sizeof((OperandType[]) { __VA_ARGS__ }) / sizeof(OperandType), \
|
||||||
|
(OperandType[]) { __VA_ARGS__ }, \
|
||||||
|
},
|
||||||
|
|
||||||
static const InstrInfo instr_table[] = {
|
static const InstrInfo instr_table[] = {
|
||||||
[OPCODE_NOPE] = {"NOPE", 0, NULL},
|
INSTR(NOPE)
|
||||||
[OPCODE_POS] = {"POS", 0, NULL},
|
INSTR(POS)
|
||||||
[OPCODE_NEG] = {"NEG", 0, NULL},
|
INSTR(NEG)
|
||||||
[OPCODE_NOT] = {"NOT", 0, NULL},
|
INSTR(NOT)
|
||||||
[OPCODE_ADD] = {"ADD", 0, NULL},
|
INSTR(ADD)
|
||||||
[OPCODE_SUB] = {"SUB", 0, NULL},
|
INSTR(SUB)
|
||||||
[OPCODE_MUL] = {"MUL", 0, NULL},
|
INSTR(MUL)
|
||||||
[OPCODE_DIV] = {"DIV", 0, NULL},
|
INSTR(DIV)
|
||||||
[OPCODE_EQL] = {"EQL", 0, NULL},
|
INSTR(EQL)
|
||||||
[OPCODE_NQL] = {"NQL", 0, NULL},
|
INSTR(NQL)
|
||||||
[OPCODE_LSS] = {"LSS", 0, NULL},
|
INSTR(LSS)
|
||||||
[OPCODE_GRT] = {"GRT", 0, NULL},
|
INSTR(GRT)
|
||||||
[OPCODE_LEQ] = {"LEQ", 0, NULL},
|
INSTR(LEQ)
|
||||||
[OPCODE_GEQ] = {"GEQ", 0, NULL},
|
INSTR(GEQ)
|
||||||
[OPCODE_NLB] = {"NLB", 0, NULL},
|
INSTR(NLB)
|
||||||
[OPCODE_STP] = {"STP", 0, NULL},
|
INSTR(STP)
|
||||||
[OPCODE_ASS] = {"ASS", 1, (OperandType[]) {OPTP_STRING}},
|
INSTR(ASS, OPTP_STRING)
|
||||||
[OPCODE_POP] = {"POP", 1, (OperandType[]) {OPTP_INT}},
|
INSTR(POP, OPTP_INT)
|
||||||
[OPCODE_CHECKTYPE] = {"CHECKTYPE", 2, (OperandType[]) {OPTP_INT, OPTP_STRING}},
|
INSTR(CHECKTYPE, OPTP_INT, OPTP_STRING)
|
||||||
[OPCODE_CALL] = {"CALL", 2, (OperandType[]) {OPTP_INT, OPTP_INT}},
|
INSTR(CALL, OPTP_INT, OPTP_INT)
|
||||||
[OPCODE_SELECT] = {"SELECT", 0, NULL},
|
INSTR(SELECT)
|
||||||
[OPCODE_INSERT] = {"INSERT", 0, NULL},
|
INSTR(INSERT)
|
||||||
[OPCODE_INSERT2] = {"INSERT2", 0, NULL},
|
INSTR(INSERT2)
|
||||||
[OPCODE_PUSHINT] = {"PUSHINT", 1, (OperandType[]) {OPTP_INT}},
|
INSTR(PUSHINT, OPTP_INT)
|
||||||
[OPCODE_PUSHFLT] = {"PUSHFLT", 1, (OperandType[]) {OPTP_FLOAT}},
|
INSTR(PUSHFLT, OPTP_FLOAT)
|
||||||
[OPCODE_PUSHSTR] = {"PUSHSTR", 1, (OperandType[]) {OPTP_STRING}},
|
INSTR(PUSHSTR, OPTP_STRING)
|
||||||
[OPCODE_PUSHVAR] = {"PUSHVAR", 1, (OperandType[]) {OPTP_STRING}},
|
INSTR(PUSHVAR, OPTP_STRING)
|
||||||
[OPCODE_PUSHTRU] = {"PUSHTRU", 0, NULL},
|
INSTR(PUSHTRU)
|
||||||
[OPCODE_PUSHFLS] = {"PUSHFLS", 0, NULL},
|
INSTR(PUSHFLS)
|
||||||
[OPCODE_PUSHNNE] = {"PUSHNNE", 0, NULL},
|
INSTR(PUSHNNE)
|
||||||
[OPCODE_PUSHFUN] = {"PUSHFUN", 2, (OperandType[]) {OPTP_IDX, OPTP_INT}},
|
INSTR(PUSHFUN, OPTP_IDX, OPTP_INT)
|
||||||
[OPCODE_PUSHLST] = {"PUSHLST", 1, (OperandType[]) {OPTP_INT}},
|
INSTR(PUSHLST, OPTP_INT)
|
||||||
[OPCODE_PUSHMAP] = {"PUSHMAP", 1, (OperandType[]) {OPTP_INT}},
|
INSTR(PUSHMAP, OPTP_INT)
|
||||||
[OPCODE_PUSHTYP] = {"PUSHTYP", 0, NULL},
|
INSTR(PUSHTYP)
|
||||||
[OPCODE_PUSHTYPTYP] = {"PUSHTYPTYP", 0, NULL},
|
INSTR(PUSHNNETYP)
|
||||||
[OPCODE_PUSHNNETYP] = {"PUSHNNETYP", 0, NULL},
|
INSTR(RETURN, OPTP_INT)
|
||||||
[OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}},
|
INSTR(EXIT)
|
||||||
[OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}},
|
INSTR(JUMPIFNOTANDPOP, OPTP_IDX)
|
||||||
[OPCODE_EXIT] = {"EXIT", 0, NULL},
|
INSTR(JUMPIFANDPOP, OPTP_IDX)
|
||||||
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
INSTR(JUMP, OPTP_IDX)
|
||||||
[OPCODE_JUMPIFANDPOP] = {"JUMPIFANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
|
||||||
[OPCODE_JUMP] = {"JUMP", 1, (OperandType[]) {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,
|
// The input name is assumed not zero-terminated,
|
||||||
// so to simplify things we duplicate it to add
|
// so to simplify things we duplicate it to add
|
||||||
// an extra null byte.
|
// an extra null byte.
|
||||||
char buff[128]; // No opcode should have a name this big.
|
char buff[MAX_OPCODE_NAME_SIZE+1]; // No opcode should have a name this big.
|
||||||
ASSERT(name_len < sizeof(buff)); // If this is triggered, [buff] should be made bigger.
|
if (len >= sizeof(buff))
|
||||||
|
return false;
|
||||||
memcpy(buff, name, name_len);
|
memcpy(buff, name, len);
|
||||||
buff[name_len] = '\0';
|
buff[len] = '\0';
|
||||||
|
|
||||||
name = buff;
|
name = buff;
|
||||||
|
|
||||||
// Now name is zero terminated.
|
// 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)) {
|
if(!strcmp(name, instr_table[i].name)) {
|
||||||
*opcode = i; // Is this safe?
|
if (opcode != NULL)
|
||||||
|
*opcode = instr_table[i].opcode;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
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)
|
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)
|
Executable *Executable_Copy(Executable *exe)
|
||||||
@@ -173,7 +194,7 @@ void Executable_Dump(Executable *exe)
|
|||||||
|
|
||||||
(void) Executable_Fetch(exe, i, &opcode, ops, &opc);
|
(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);
|
fprintf(stderr, "%d: %s ", i, info->name);
|
||||||
|
|
||||||
@@ -250,7 +271,7 @@ _Bool Executable_Fetch(Executable *exe, int index, Opcode *opcode, Operand *ops,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const Instruction *instr = exe->body + index;
|
const Instruction *instr = exe->body + index;
|
||||||
const InstrInfo *info = instr_table + instr->opcode;
|
const InstrInfo *info = Executable_GetInstrByOpcode(instr->opcode);
|
||||||
|
|
||||||
if(opcode)
|
if(opcode)
|
||||||
*opcode = instr->opcode;
|
*opcode = instr->opcode;
|
||||||
@@ -497,7 +518,7 @@ _Bool ExeBuilder_Append(ExeBuilder *exeb, Error *error, Opcode opcode, Operand *
|
|||||||
[OPTP_STRING] = membersizeof(Operand, as_string),
|
[OPTP_STRING] = membersizeof(Operand, as_string),
|
||||||
};
|
};
|
||||||
|
|
||||||
const InstrInfo *info = instr_table + opcode;
|
const InstrInfo *info = Executable_GetInstrByOpcode(opcode);
|
||||||
|
|
||||||
if(opc != info->opcount)
|
if(opc != info->opcount)
|
||||||
{
|
{
|
||||||
@@ -634,4 +655,3 @@ int ExeBuilder_InstrCount(ExeBuilder *exeb)
|
|||||||
|
|
||||||
return raw_size / sizeof(Instruction);
|
return raw_size / sizeof(Instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ typedef enum {
|
|||||||
OPCODE_SUB,
|
OPCODE_SUB,
|
||||||
OPCODE_MUL,
|
OPCODE_MUL,
|
||||||
OPCODE_DIV,
|
OPCODE_DIV,
|
||||||
|
OPCODE_MOD,
|
||||||
OPCODE_EQL,
|
OPCODE_EQL,
|
||||||
OPCODE_NQL,
|
OPCODE_NQL,
|
||||||
OPCODE_LSS,
|
OPCODE_LSS,
|
||||||
@@ -86,10 +87,8 @@ typedef enum {
|
|||||||
OPCODE_PUSHLST,
|
OPCODE_PUSHLST,
|
||||||
OPCODE_PUSHMAP,
|
OPCODE_PUSHMAP,
|
||||||
OPCODE_PUSHTYP,
|
OPCODE_PUSHTYP,
|
||||||
OPCODE_PUSHTYPTYP,
|
|
||||||
OPCODE_PUSHNNETYP,
|
OPCODE_PUSHNNETYP,
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
OPCODE_ERROR,
|
|
||||||
OPCODE_EXIT,
|
OPCODE_EXIT,
|
||||||
OPCODE_JUMPIFANDPOP,
|
OPCODE_JUMPIFANDPOP,
|
||||||
OPCODE_JUMPIFNOTANDPOP,
|
OPCODE_JUMPIFNOTANDPOP,
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ typedef enum {
|
|||||||
EXPR_SUB,
|
EXPR_SUB,
|
||||||
EXPR_MUL,
|
EXPR_MUL,
|
||||||
EXPR_DIV,
|
EXPR_DIV,
|
||||||
|
EXPR_MOD,
|
||||||
|
|
||||||
EXPR_EQL,
|
EXPR_EQL,
|
||||||
EXPR_NQL,
|
EXPR_NQL,
|
||||||
|
|||||||
@@ -135,14 +135,6 @@ static void emitInstr_EQL(CodegenContext *ctx, int off, int len)
|
|||||||
CodegenContext_EmitInstr(ctx, OPCODE_EQL, NULL, 0, off, 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)
|
static void emitInstr_CHECKTYPE(CodegenContext *ctx, int arg_index, const char *arg_name, int off, int len)
|
||||||
{
|
{
|
||||||
Operand opv[2] = {
|
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);
|
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)
|
static void emitInstr_PUSHNNETYP(CodegenContext *ctx, int off, int len)
|
||||||
{
|
{
|
||||||
CodegenContext_EmitInstr(ctx, OPCODE_PUSHNNETYP, NULL, 0, off, 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_SUB: return OPCODE_SUB;
|
||||||
case EXPR_MUL: return OPCODE_MUL;
|
case EXPR_MUL: return OPCODE_MUL;
|
||||||
case EXPR_DIV: return OPCODE_DIV;
|
case EXPR_DIV: return OPCODE_DIV;
|
||||||
|
case EXPR_MOD: return OPCODE_MOD;
|
||||||
case EXPR_EQL: return OPCODE_EQL;
|
case EXPR_EQL: return OPCODE_EQL;
|
||||||
case EXPR_NQL: return OPCODE_NQL;
|
case EXPR_NQL: return OPCODE_NQL;
|
||||||
case EXPR_LSS: return OPCODE_LSS;
|
case EXPR_LSS: return OPCODE_LSS;
|
||||||
@@ -391,7 +379,7 @@ static void emitInstrForExprNode(CodegenContext *ctx, ExprNode *expr,
|
|||||||
|
|
||||||
case EXPR_NULLABLETYPE:
|
case EXPR_NULLABLETYPE:
|
||||||
case EXPR_SUMTYPE:
|
case EXPR_SUMTYPE:
|
||||||
case EXPR_NOT:
|
case EXPR_NOT: case EXPR_MOD:
|
||||||
case EXPR_POS: case EXPR_NEG:
|
case EXPR_POS: case EXPR_NEG:
|
||||||
case EXPR_ADD: case EXPR_SUB:
|
case EXPR_ADD: case EXPR_SUB:
|
||||||
case EXPR_MUL: case EXPR_DIV:
|
case EXPR_MUL: case EXPR_DIV:
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ typedef enum {
|
|||||||
TSUB = '-',
|
TSUB = '-',
|
||||||
TMUL = '*',
|
TMUL = '*',
|
||||||
TDIV = '/',
|
TDIV = '/',
|
||||||
|
TMOD = '%',
|
||||||
|
|
||||||
TLSS = '<',
|
TLSS = '<',
|
||||||
TGRT = '>',
|
TGRT = '>',
|
||||||
@@ -145,7 +146,8 @@ static inline _Bool isoper(char c)
|
|||||||
c == '*' || c == '/' ||
|
c == '*' || c == '/' ||
|
||||||
c == '<' || c == '>' ||
|
c == '<' || c == '>' ||
|
||||||
c == '!' || c == '=' ||
|
c == '!' || c == '=' ||
|
||||||
c == ',' || c == '|';
|
c == ',' || c == '|' ||
|
||||||
|
c == '%';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Symbol: tokenize
|
/* Symbol: tokenize
|
||||||
@@ -328,6 +330,7 @@ static Token *tokenize(Source *src, BPAlloc *alloc, Error *error)
|
|||||||
{ TASS, 1, "=" },
|
{ TASS, 1, "=" },
|
||||||
{ TCOMMA, 1, "," },
|
{ TCOMMA, 1, "," },
|
||||||
{ TSMT, 1, "|" },
|
{ TSMT, 1, "|" },
|
||||||
|
{ TMOD, 1, "%" },
|
||||||
};
|
};
|
||||||
|
|
||||||
_Bool found = 0;
|
_Bool found = 0;
|
||||||
@@ -1603,7 +1606,7 @@ static inline _Bool isbinop(Token *tok)
|
|||||||
tok->kind == TEQL || tok->kind == TNQL ||
|
tok->kind == TEQL || tok->kind == TNQL ||
|
||||||
tok->kind == TKWAND || tok->kind == TKWOR ||
|
tok->kind == TKWAND || tok->kind == TKWOR ||
|
||||||
tok->kind == '=' || tok->kind == ',' ||
|
tok->kind == '=' || tok->kind == ',' ||
|
||||||
tok->kind == '|';
|
tok->kind == '|' || tok->kind == '%';
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline _Bool isrightassoc(Token *tok)
|
static inline _Bool isrightassoc(Token *tok)
|
||||||
@@ -1645,6 +1648,7 @@ static inline int precedenceof(Token *tok)
|
|||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
case '/':
|
case '/':
|
||||||
|
case '%':
|
||||||
return 6;
|
return 6;
|
||||||
|
|
||||||
case ',':
|
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_SUB; break;
|
||||||
case '*': temp->base.kind = EXPR_MUL; break;
|
case '*': temp->base.kind = EXPR_MUL; break;
|
||||||
case '/': temp->base.kind = EXPR_DIV; 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_LSS; break;
|
||||||
case '>': temp->base.kind = EXPR_GRT; break;
|
case '>': temp->base.kind = EXPR_GRT; break;
|
||||||
case TLEQ: temp->base.kind = EXPR_LEQ; break;
|
case TLEQ: temp->base.kind = EXPR_LEQ; break;
|
||||||
|
|||||||
+34
-21
@@ -739,6 +739,40 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
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_EQL:
|
||||||
case OPCODE_NQL:
|
case OPCODE_NQL:
|
||||||
{
|
{
|
||||||
@@ -1213,18 +1247,6 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
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:
|
case OPCODE_PUSHNNETYP:
|
||||||
{
|
{
|
||||||
ASSERT(opc == 0);
|
ASSERT(opc == 0);
|
||||||
@@ -1282,15 +1304,6 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 0;
|
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:
|
case OPCODE_JUMP:
|
||||||
ASSERT(opc == 1);
|
ASSERT(opc == 1);
|
||||||
ASSERT(ops[0].type == OPTP_IDX);
|
ASSERT(ops[0].type == OPTP_IDX);
|
||||||
|
|||||||
Binary file not shown.
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "keyword.operator.noja",
|
"name": "keyword.operator.noja",
|
||||||
"match": "(\\+|-|\\*|\\/|=|==|!=|\\>|\\<|\\>=|\\<=|\\|)"
|
"match": "(\\+|-|\\*|\\/|%|=|==|!=|\\>|\\<|\\>=|\\<=|\\|)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "keyword.operator.logical.noja",
|
"name": "keyword.operator.logical.noja",
|
||||||
|
|||||||
Reference in New Issue
Block a user