view src/ploki/op.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 "IO.h"
#include "Str.h"
#include "expr.h"
#include "main_label.h"
#include "mars.h"
#include "op.h"

#include <ctype.h>
#include <stddef.h>
#include <string.h>

void op_init(struct op *op) {
	St_init(&op->txt);
	op->type = OP_NOP;
	op->arg = NULL;
	op->arh.expr = NULL;
	op->next = NULL;
	op->line = 0;
}

void op_end(struct op *op) {
	St_clear(&op->txt);
	free_expr(op->arg);
	switch (op->type) {
		case OP_ASSIGN:
		case OP_CALL_BACK:
		case OP_MODIFY:
		case OP_PRINT:
		case OP_PUTC:
		case OP_SET_VAL:
		case OP_TEMP:
			free_expr(op->arh.expr);
			break;

		default:
			break;
	}
}

void op_getop(struct op *p) {
	p->next = NULL;

	switch (ST_FIRSTCHAR(&p->txt)) {
		case '#':
			if (ST_INDEX(&p->txt, 1) == '!') {
				p->type = OP_NOP;
				break;
			}
			p->type = OP_SYSTEM;
			St_shift(&p->txt);
			p->arg = get_expr(p);
			break;

		case 'A':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'B':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "ABRUF", 5)) {
						goto defualt;
					}
					p->type = OP_CALL_BACK;
					St_del(&p->txt, 0, 5);
					p->arh.expr = get_iobj(p);
					p->arg = get_expr(p);
					break;

				case 'N':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "ANRUF", 5)) {
						goto defualt;
					}
					p->type = OP_CALL_DYN;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'C':
			if (St_len(&p->txt) < 6 || St_ncmp_m(&p->txt, "CLAUDS", 6)) {
				goto defualt;
			}
			p->type = OP_CLOSE;
			St_del(&p->txt, 0, 6);
			p->arg = get_expr(p);
			break;

		case 'E':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'L':
					if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "ELSE", 4)) {
						goto defualt;
					}
					p->type = OP_ELSE;
					St_del(&p->txt, 0, 4);
					break;

				case 'N':
					if (St_len(&p->txt) >= 6 && St_ncmp_m(&p->txt, "END IF", 6) == 0) {
						p->type = OP_FI;
						break;
					}
					if (St_len(&p->txt) < 3 || St_ncmp_m(&p->txt, "END", 3)) {
						goto defualt;
					}
					p->type = OP_EXIT;
					St_del(&p->txt, 0, 3);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'F':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'I':
					p->type = OP_FI;
					break;

				case 'L':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "FLUSH", 5)) {
						goto defualt;
					}
					p->type = OP_FLUSH;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'G':
			if (ST_INDEX(&p->txt, 1) != 'O') {
				goto defualt;
			}
			switch (ST_INDEX(&p->txt, 2)) {
				case 'F':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "GOFOR", 5)) {
						goto defualt;
					}
					p->type = OP_GOBACK;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				case 'T':
					if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "GOTO", 4)) {
						goto defualt;
					}
					p->type = OP_GOTO;
					St_del(&p->txt, 0, 4);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'I':
			switch (ST_INDEX(&p->txt, 1)) {
				case 'A':
					if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "IACS", 4)) {
						goto defualt;
					}
					p->type = OP_THROW;
					St_del(&p->txt, 0, 4);
					p->arg = get_expr(p);
					break;

				case 'F':
					p->type = OP_IF;
					St_del(&p->txt, 0, 2);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'K':
			if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "KTHX", 4)) {
				goto defualt;
			}
			p->type = OP_RETURN;
			St_del(&p->txt, 0, 4);
			p->arg = get_expr(p);
			break;

		case 'L':
			if (ST_INDEX(&p->txt, 1) != 'E') {
				goto defualt;
			}
			switch (ST_INDEX(&p->txt, 2)) {
				case 'E':
					if (ST_INDEX(&p->txt, 3) != 'T') {
						goto defualt;
					}
					p->type = OP_TEMP;
					St_del(&p->txt, 0, 4);
					p->arh.expr = get_lval(p);
					p->arg = get_expr(p);
					break;

				case 'T':
					p->type = OP_ASSIGN;
					St_del(&p->txt, 0, 3);
					p->arh.expr = get_lval(p);
					St_shiftws(&p->txt);
					if (p->arh.expr && ST_INDEX(&p->txt, 1) == '=' && OPERATOR_P(ST_FIRSTCHAR(&p->txt))) {
						p->arh.expr->op = expr_binop(ST_FIRSTCHAR(&p->txt));
						St_del(&p->txt, 0, 2);
						p->type = OP_MODIFY;
					}
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'N':
			if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "NEXT", 4)) {
				goto defualt;
			} else {
				size_t tmp;
				p->type = OP_NOP;
				St_del(&p->txt, 0, 4);
				tmp = St_shiftws(&p->txt);
				if (!(p->next = ma_find(&Mars, &p->txt))) {
					St_tac_m(&p->txt, "NEXT ", 4 + !!tmp);
					p->arg = get_expr(p);
					p->arh.expr = NULL;
					p->type = OP_PRINT;
				}
			}
			break;

		case 'R':
			if (ST_INDEX(&p->txt, 1) != 'E') {
				goto defualt;
			}
			switch (ST_INDEX(&p->txt, 2)) {
				case 'M':
					p->type = OP_NOP;
					break;

				case 'S':
					if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "RESET", 5)) {
						goto defualt;
					}
					p->type = OP_RESET;
					St_del(&p->txt, 0, 5);
					p->arg = get_expr(p);
					break;

				default:
					goto defualt;
			}
			break;

		case 'S':
			if (St_len(&p->txt) < 3 || St_ncmp_m(&p->txt, "SET", 3)) {
				goto defualt;
			}
			p->type = OP_PUTC;
			St_del(&p->txt, 0, 3);
			p->arg = get_iobj(p);
			p->arh.expr = NULL;
			St_shiftws(&p->txt);
			if (ST_FIRSTCHAR(&p->txt) == ',') {
				St_shift(&p->txt);
				p->arh.expr = p->arg;
				p->arg = get_expr(p);
			}
			break;

		case 'W':
			if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "WUNT", 4)) {
				goto defualt;
			}
			p->type = OP_PRINT;
			St_del(&p->txt, 0, 4);
			p->arg = get_iobj(p);
			p->arh.expr = NULL;
			St_shiftws(&p->txt);
			if (ST_FIRSTCHAR(&p->txt) != EOF) {
				p->arh.expr = p->arg;
				p->arg = get_expr(p);
			}
			break;

defualt:
		default:
			if ((p->arh.op = ma_find(&Mars, &p->txt))) {
				p->type = OP_CALL;
				p->arg = get_expr(p);
			} else {
				p->type = OP_PRINT;
				p->arg = get_expr(p);
				p->arh.expr = NULL;
			}
			break;
	}

	St_clear(&p->txt);
}