view src/ploki/compile.c @ 12292:d51f2100210c draft

<kspalaiologos> `` cat <<<"asmbf && bfi output.b" > /hackenv/ibin/asmbf
author HackEso <hackeso@esolangs.org>
date Thu, 02 Jan 2020 15:38:21 +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]);
	}
}