code: purgatorio

ref: a8083462e62459b2ae8a243dc4ba88416eba03b1
dir: /appl/spree/engines/debug.b/

View raw version
implement Engine;

include "sys.m";
	sys: Sys;
include "draw.m";
include "../spree.m";
	spree: Spree;
	Attributes, Range, Object, Clique, Member: import spree;

clique: ref Clique;

init(g: ref Clique, srvmod: Spree): string
{
	sys = load Sys Sys->PATH;
	clique = g;
	spree = srvmod;
	return nil;
}

join(nil: ref Member): string
{
	return nil;
}

leave(nil: ref Member)
{
}

number := 0;
currmember: ref Member;

obj(ext: int): ref Object
{
	o := currmember.obj(ext);
	if (o == nil)
		sys->raise("parse:bad object");
	return o;
}

Eusage: con "bad command usage";

assert(b: int, err: string)
{
	if (b == 0)
		sys->raise("parse:" + err);
}

command(member: ref Member, cmd: string): string
{
	e := ref Sys->Exception;
	if (sys->rescue("parse:*", e) == Sys->EXCEPTION) {
		sys->rescued(Sys->ONCE, nil);
		currmember = nil;
		return e.name[6:];
	}
	currmember = member;
	(nlines, lines) := sys->tokenize(cmd, "\n");
	assert(nlines > 0, "unknown command");
	(n, toks) := sys->tokenize(hd lines, " ");
	assert(n > 0, "unknown command");
	case hd toks {
	"new" =>			# new parent visibility\nvisibility attr val\nvisibility attr val...
		assert(n == 3, Eusage);
		setattrs(clique.newobject(obj(int hd tl toks), int hd tl tl toks), tl lines);
	"deck" =>
		stack := clique.newobject(nil, ~0);
		stack.setattr("type", "stack", ~0);
		for (i := 0; i < 6; i++) {
			o := clique.newobject(stack, ~0);
			o.setattr("face", "down", ~0);
			o.setattr("number", string number++, 0);
		}
	"flip" =>
		# flip objid start [end]
		assert(n == 2 || n == 3 || n == 4, Eusage);
		o := obj(int hd tl toks);
		if (n > 2) {
			start := int hd tl tl toks;
			end := start + 1;
			if (n == 4)
				end = int hd tl tl tl toks;
			assert(start >= 0 && start < len o.children &&
					end >= start && end >= 0 && end <= len o.children, "index out of range");
			for (; start < end; start++)
				flip(o.children[start]);
		} else
			flip(o);
		
	"set" =>			# set objid attr val
		assert(n == 4, Eusage);
		obj(int hd tl toks).setattr(hd tl tl toks, hd tl tl tl toks, ~0);
	"vis" =>			# vis objid flags
		assert(n == 3, Eusage);
		obj(int hd tl toks).setvisibility(int hd tl tl toks);
	"attrvis" =>		# attrvis objid attr flags
		assert(n == 4, Eusage);
		o := obj(int hd tl toks);
		name := hd tl tl toks;
		attr := o.attrs.get(name);
		assert(attr != nil, "attribute not found");
		o.setattrvisibility(name, int hd tl tl tl toks);
	"show" =>			# show [memberid]
		p: ref Member = nil;
		if (n == 2) {
			memberid := int hd tl toks;
			p = clique.member(memberid);
			assert(p != nil, "bad memberid");
		}
		clique.show(p);
	"del" or "delete" =>			# del obj
		assert(n == 2, Eusage);
		obj(int hd tl toks).delete();
	"tx" =>					# tx src from to dest [index]
		assert(n == 5 || n == 6, Eusage);
		src, dest: ref Object;
		r: Range;
		(src, toks) = (obj(int hd tl toks), tl tl toks);
		(r.start, toks) = (int hd toks, tl toks);
		(r.end, toks) = (int hd toks, tl toks);
		(dest, toks) = (obj(int hd toks), tl toks);
		index := len dest.children;
		if (n == 6)
			index = int hd toks;
		assert(r.start >= 0 && r.start < len src.children &&
				r.end >= 0 && r.end <= len src.children && r.end >= r.start,
				"bad range");
		src.transfer(r, dest, index);
	* =>
		assert(0, "bad command");
	}
	currmember = nil;
	return nil;
}


flip(o: ref Object)
{
	face := o.getattr("face");
	if (face == "down") {
		face = "up";
		o.setattrvisibility("number", ~0);
	} else {
		face = "down";
		o.setattrvisibility("number", 0);
	}
	o.setattr("face", face, ~0);
}

setattrs(o: ref Object, lines: list of string): string
{
	for (; lines != nil; lines = tl lines) {
		# attr val [visibility]
		(n, toks) := sys->tokenize(hd lines, " ");
		if (n != 2 && n != 3)
			return "bad attribute line";
		vis := 0;
		if (n == 3)
			vis = int hd tl tl toks;
		o.setattr(hd toks, hd tl toks, vis);
	}
	return nil;
}