view src/ploki/compile.c @ 5556:f2e89077ff1d

<oerjan> learn Turkey was the center of an empire that gobbled up much of Eastern Europe and the Middle East, something which brought them into conflict with Ostrich. In the 19th century the overstuffed empire started declining, and after the Great War it was cut up like so much Shish Kebab.
author HackBot
date Fri, 12 Jun 2015 06:39:15 +0000
parents ac0403686959
children
line wrap: on
line source

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