diff src/ploki/sub.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/sub.c	Fri Dec 20 22:18:50 2013 +0000
@@ -0,0 +1,134 @@
+#include "expr.h"
+#include "main_opt.h"
+#include "sub.h"
+#include "transmogrify.h"
+#include "xmalloc.h"
+
+#include <stddef.h>
+
+struct sub {
+	struct expr *expr;
+	size_t refs;
+	size_t id;
+};
+
+static struct expr *dup(const struct expr *e) {
+	struct expr *p;
+
+	if (!e) {
+		return NULL;
+	}
+
+	p = xmalloc(1, sizeof *p);
+	*p = *e;
+
+	switch (e->type) {
+		case literE:
+			p->v.val = v_undef();
+			v_set(p->v.val, e->v.val);
+			break;
+
+		case varE:
+			break;
+
+		case varhashE:
+			p->right = dup(e->right);
+			break;
+
+		case symbolE:
+			switch (e->op) {
+				case S_ARGV:
+					p->right = dup(e->right);
+					break;
+			}
+			break;
+
+		case unopE:
+			p->right = dup(e->right);
+			if (e->op == F_MATCH) {
+				p->left.rx = re_dup(e->left.rx);
+			}
+			break;
+
+		case binopE:
+		case listE:
+			p->right = dup(e->right);
+			p->left.expr = dup(e->left.expr);
+			break;
+	}
+
+	return p;
+}
+
+static void solid(struct expr *e) {
+	if (!e) {
+		return;
+	}
+
+	switch (e->type) {
+		case literE:
+			break;
+
+		case varE:
+			e->v.val = eval_expr(e);
+			e->type = literE;
+			break;
+
+		case varhashE:
+			break;
+
+		case symbolE:
+			switch (e->op) {
+				case S_ARGV:
+					solid(e->right);
+					break;
+			}
+			break;
+
+		case unopE:
+			solid(e->right);
+			break;
+
+		case binopE:
+		case listE:
+			solid(e->left.expr);
+			solid(e->right);
+			break;
+	}
+}
+
+struct sub *sub_new(const struct expr *e) {
+	static size_t idcount;
+	struct sub *p;
+	p = xmalloc(1, sizeof *p);
+	p->expr = dup(e);
+	solid(p->expr);
+	if (!Opt.unoptimize) {
+		trans_fold(&p->expr);
+	}
+	p->refs = 0;
+	p->id = idcount++;
+	return p;
+}
+
+struct sub *sub_incr(struct sub *p) {
+	++p->refs;
+	return p;
+}
+
+void sub_decr(struct sub *p) {
+	if (!p->refs) {
+		free_expr(p->expr);
+		xfree(p);
+		return;
+	}
+	--p->refs;
+}
+
+struct expr *sub_expr(const struct sub *p) {
+	return p->expr;
+}
+
+size_t sub_id(const struct sub *p) {
+	return p->id;
+}