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]);
+	}
+}