Mercurial > repo
diff src/ploki/compile.c @ 4223:ac0403686959
<oerjan> rm -rf src/ploki; mv ploki src
author | HackBot |
---|---|
date | Fri, 20 Dec 2013 22:18:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ploki/compile.c Fri Dec 20 22:18:50 2013 +0000 @@ -0,0 +1,171 @@ +#include "config.h" +#include "Str.h" +#include "compile.h" +#include "expr.h" +#include "main_var.h" +#include "op.h" +#include "text.h" +#include "zz.h" + +#include <assert.h> + +static struct op *end_if(struct text *code, size_t *n) { + for (; *n < code->length; ++*n) { + struct op *const p = code->start[*n]; + switch (p->type) { + case OP_IF: + ++*n; + p->arh.op = code->start[*n]; + p->next = end_if(code, n); + break; + + case OP_ELSE: { + size_t tmp; + tmp = ++*n; + p->next = end_if(code, n); + p->type = OP_NOP; + if (tmp < code->length) { + return code->start[tmp]; + } + return p; + } + + case OP_FI: + p->type = OP_NOP; + return p; + + default: + break; + } + } + + return code->start[0]; +} + +static void resolve(struct expr *e) { + if (!e) { + return; + } + + switch (e->type) { + case literE: + break; + + case varE: + e->v.val = vr_data(Var_plain, e->v.tent); + assert(e->v.val != NULL); + break; + + case varhashE: + e->v.hash = vr_data(Var_hash, e->v.tent); + resolve(e->right); + break; + + case symbolE: + if (e->op == S_ARGV) { + resolve(e->right); + } + break; + + case unopE: + resolve(e->right); + break; + + case binopE: + resolve(e->left.expr); + resolve(e->right); + break; + + case listE: + resolve(e->right); + resolve(e->left.expr); + break; + } +} + +static void op_resolve(struct op *o) { + switch (o->type) { + case OP_NOP: + case OP_GOBACK: + case OP_GOTO: + case OP_HANG: + break; + + case OP_ASSIGN: + case OP_CALL_BACK: + case OP_MODIFY: + case OP_PRINT: + case OP_PUTC: + case OP_TEMP: + resolve(o->arh.expr); + resolve(o->arg); + break; + + case OP_CALL: + case OP_CALL_DYN: + case OP_CLOSE: + case OP_EXIT: + case OP_IF: + case OP_RETURN: + case OP_SYSTEM: + case OP_THROW: + resolve(o->arg); + break; + + default: + NOTREACHED; + break; + } +} + +void compile(struct text *code) { + size_t i; + + for (i = 0; i < code->length; ++i) { + struct op *const p = code->start[i]; + + op_getop(p); + + if (!p->next && p->type != OP_EXIT && i + 1 < code->length) { + p->next = code->start[i + 1]; + } + } + + if (!i) { + struct op tmp; + op_init(&tmp); + text_push(code, &tmp); + } + + vr_freeze(Var_plain); + vr_freeze(Var_hash); + + for (i = 0; i < code->length; ++i) { + struct op *const p = code->start[i]; + + switch (p->type) { + case OP_IF: + ++i; + p->arh.op = code->start[i]; + p->next = end_if(code, &i); + break; + + case OP_ELSE: + ++i; + p->next = end_if(code, &i); + p->type = OP_NOP; + break; + + case OP_FI: + p->type = OP_NOP; + break; + + default: + break; + } + } + + for (i = 0; i < code->length; ++i) { + op_resolve(code->start[i]); + } +}