view src/ploki/compile.c @ 8427:1fc808cd5b1f

<b_jonas> learn can\'t is the most frequent word whose pronunciation varies between /\xc9\x91\xcb\x90/ and /\xc3\xa6/ depending on dialect. The list is: advance after answer ask aunt brass can\'t cast castle chance class command dance demand draft enhance example fast father glass graph grass half last laugh mask master nasty pass past path plant rather sample shan\'t staff task vast
author HackBot
date Thu, 09 Jun 2016 21:28:47 +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]);
	}
}