aboutsummaryrefslogtreecommitdiffstats
path: root/creole.c
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2023-02-11 14:28:43 +0000
committerGravatar Peter McGoron 2023-02-11 14:28:43 +0000
commit582a0a2c9a476abe9dec3410ff4f555433ed9e0f (patch)
tree422878d94f091f440143348d7f52fcfa42b294dc /creole.c
parenttest pop (diff)
enable compiling and add compile test
Diffstat (limited to 'creole.c')
-rw-r--r--creole.c146
1 files changed, 109 insertions, 37 deletions
diff --git a/creole.c b/creole.c
index 78beaa0..b482d1e 100644
--- a/creole.c
+++ b/creole.c
@@ -346,14 +346,27 @@ creole_parse_line(struct creole_ins *ins, struct creole_reader *r)
* High level compiling interface
*************************************************************************/
-static int typecheck(enum creole_word_flag fl, enum creole_arg_type typ)
+static int valid_register(struct creole_env *env, int reg)
+{
+ return reg < env->reglen;
+}
+
+static int valid_label(struct creole_env *env, int reg)
+{
+ return reg < env->lablen;
+}
+
+static int typecheck(struct creole_env *env, int val,
+ enum creole_word_flag fl, enum creole_arg_type typ)
{
switch (typ) {
case TYPE_IMM: return fl == CREOLE_IMMEDIATE;
- case TYPE_REG: return fl == CREOLE_REGISTER;
+ case TYPE_REG: return fl == CREOLE_REGISTER
+ && valid_register(env, val);
case TYPE_VAL: return fl == CREOLE_IMMEDIATE
|| fl == CREOLE_REGISTER;
- case TYPE_LAB: return fl == CREOLE_IMMEDIATE;
+ case TYPE_LAB: return fl == CREOLE_IMMEDIATE
+ && valid_label(env, val);
default: return 0;
}
}
@@ -364,7 +377,7 @@ static enum creole_compiler_ret typecheck_ins(struct creole_env *env,
unsigned i;
for (i = 0; i < opcode_info[ins->opcode].arglen; i++) {
- if (!typecheck(ins->w_flags[i],
+ if (!typecheck(env, ins->w[i], ins->w_flags[i],
opcode_info[ins->opcode].argtype[i]))
return CREOLE_TYPE_ERROR;
}
@@ -373,11 +386,13 @@ static enum creole_compiler_ret typecheck_ins(struct creole_env *env,
static void clear_ins(struct creole_ins *i)
{
- i->opcode = 0;
- i->w[0] = i->w[1] = i->w[2] = i->w_flags[0] =
- i->w_flags[1] = i->w_flags[2] = 0;
+ const struct creole_ins blank = {0};
+ *i = blank;
}
+/****
+ * Get rid of instructions that can be written out at compile time.
+ ***/
static enum creole_compiler_ret
handle_compiletime_immediate(struct creole_env *env,
struct creole_ins *cur_ins)
@@ -433,61 +448,118 @@ creole_compile(struct creole_env *env, struct creole_reader *r)
return CREOLE_COMPILE_OK;
}
-#if 0
+enum creole_run_ret creole_reg_write(struct creole_env *env,
+ creole_word w, unsigned reg)
+{
+ if (!valid_register(env, reg))
+ return CREOLE_REGISTER_OVERFLOW;
+ env->reg[reg] = w;
+ return CREOLE_STEP_CONTINUE;
+}
+
+enum creole_run_ret creole_reg_read(struct creole_env *env, creole_word *w,
+ unsigned reg)
+{
+ if (!valid_register(env, reg))
+ return CREOLE_REGISTER_OVERFLOW;
+ *w = env->reg[reg];
+ return CREOLE_STEP_CONTINUE;
+}
+
+static enum creole_run_ret read_val(struct creole_env *env,
+ struct creole_ins *ins,
+ unsigned arg,
+ creole_word *w)
+{
+ if (ins->w_flags[arg] == CREOLE_REGISTER) {
+ return creole_reg_read(env, w, ins->w[arg]);
+ } else {
+ *w = ins->w[arg];
+ }
+
+ return CREOLE_STEP_CONTINUE;
+}
+
+enum creole_run_ret creole_push(struct creole_env *env, creole_word w)
+{
+ if (env->stkptr == env->stklen)
+ return CREOLE_STACK_OVERFLOW;
+ env->stk[env->stkptr++] = w;
+ return CREOLE_STEP_CONTINUE;
+}
+
+enum creole_run_ret creole_pop(struct creole_env *env, creole_word *w)
+{
+ if (env->stkptr == 0)
+ return CREOLE_STACK_UNDERFLOW;
+ *w = env->stk[--env->stkptr];
+ return CREOLE_STEP_CONTINUE;
+}
-static creole_word read_word(struct creole_ins *ins, int i)
+static enum creole_run_ret
+check_label(struct creole_env *env, creole_word label)
{
- if (env->w_flags[i] == CREOLE_REGISTER)
- return env->reg[env->w[i]];
- else
- return env->w[i];
+ return label < env->lablen
+ ? CREOLE_STEP_CONTINUE
+ : CREOLE_RUN_LABEL_OVERFLOW;
}
-int creole_step(struct creole_env *env)
+#define check(fun) do { \
+ rcode = fun; \
+ if (rcode != CREOLE_STEP_CONTINUE) \
+ return rcode; \
+} while(0)
+
+enum creole_run_ret creole_step(struct creole_env *env, creole_word *sc)
{
struct creole_ins *ins = env->prg + env->prgptr;
creole_word a1, a2;
+ int rcode = CREOLE_STEP_CONTINUE;
if (env->prgptr == env->prgend)
return CREOLE_STEP_STOP;
- env->prgptr++;
switch (ins->opcode) {
case CREOLE_PUSH:
- if (env->stkptr == env->stklen)
- return CREOLE_STACK_OVERFLOW;
- env->stk[env->stkptr++] = env->reg[env->w[0]];
+ check(read_val(env, ins, 0, &a1));
+ check(creole_push(env, a1));
break;
case CREOLE_POP:
- if (env->stkptr == 0)
- return CREOLE_STACK_OVERFLOW;
- env->reg[env->w[0]] = env->stk[--env->stkptr];
+ check(creole_pop(env, &a1));
+ check(creole_reg_write(env, a1, ins->w[0]));
break;
case CREOLE_ADD:
- a1 = read_word(ins, 1);
- a2 = read_word(ins, 2);
- env->reg[env->w[0]] = a1 + a2;
+ check(read_val(env, ins, 1, &a1));
+ check(read_val(env, ins, 2, &a2));
+ check(creole_reg_write(env, ins->w[0], a1 + a2));
break;
case CREOLE_MUL:
- a1 = read_word(ins, 1);
- a2 = read_word(ins, 2);
- env->reg[env->w[0]] = a1 * a2;
+ check(read_val(env, ins, 1, &a1));
+ check(read_val(env, ins, 2, &a2));
+ check(creole_reg_write(env, ins->w[0], a1 * a2));
break;
case CREOLE_DIV:
- a1 = read_word(ins, 1);
- a2 = read_word(ins, 2);
- env->reg[env->w[0]] = a1 / a2;
+ check(read_val(env, ins, 1, &a1));
+ check(read_val(env, ins, 2, &a2));
+ check(creole_reg_write(env, ins->w[0], a1 / a2));
break;
case CREOLE_JL:
- a1 = read_word(ins, 1);
- a2 = read_word(ins, 2);
+ check(read_val(env, ins, 1, &a1));
+ check(read_val(env, ins, 2, &a2));
+ check(check_label(env, ins->w[0]));
if (a1 < a2)
- env->prgptr = env->lab[env->w[0]];
+ env->prgptr = env->lab[ins->w[0]];
break;
- case SYS:
- a1 = read_word(ins, 1);
- /* do syscall */
+ case CREOLE_SYS:
+ check(read_val(env, ins, 0, sc));
+ rcode = CREOLE_STEP_SYSCALL;
break;
+ default:
+ rcode = CREOLE_STEP_UNKNOWN_OPCODE;
}
+
+ env->prgptr++;
+ return rcode;
}
-#endif
+
+#undef check