summaryrefslogtreecommitdiff
path: root/clformat/src/main/java/bjc/utils/ioutils/format/directives/GotoDirective.java
blob: aea107f5852e9b60de116fbd29c6f8895412d914 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package bjc.utils.ioutils.format.directives;

import bjc.esodata.*;
import bjc.utils.ioutils.format.*;

/**
 * Implement the * directive.
 *
 * @author student
 *
 */
public class GotoDirective implements Directive {
	@Override
	public Edict compile(CompileContext compCTX) {
		CLParameters params = compCTX.decr.parameters;
		CLModifiers mods = compCTX.decr.modifiers;

		CLValue numVal = CLValue.nil();
		GotoEdict.Mode mode;

		if (mods.colonMod) {
			mode = GotoEdict.Mode.BACKWARD;

			if (params.length() >= 1) {
				params.mapIndices("numargs");
				numVal = params.resolveKey("numargs");
			}
		} else if (mods.atMod) {
			mode = GotoEdict.Mode.INDEX;

			if (params.length() >= 1) {
				params.mapIndices("argidx");
				numVal = params.resolveKey("argidx");
			}
		} else {
			mode = GotoEdict.Mode.FORWARD;

			if (params.length() >= 1) {
				params.mapIndices("numargs");
				numVal = params.resolveKey("numargs");
			}
		}

		return new GotoEdict(mode, numVal);
	}
}

class GotoEdict implements Edict {
	public static enum Mode {
		FORWARD, BACKWARD, INDEX
	}

	private Mode mode;

	private CLValue numVal;

	public GotoEdict(Mode mode, CLValue numVal) {
		this.mode = mode;

		this.numVal = numVal;
	}

	@Override
	public void format(FormatContext formCTX) {
		Tape<Object> items = formCTX.items;

		int num;
		switch (mode) {
		case FORWARD:
			num = numVal.asInt(items, "number of arguments forward", "*", 1);
			items.right(num);
			break;
		case BACKWARD:
			num = numVal.asInt(items, "number of arguments backward", "*", 1);
			items.left(num);
			break;
		case INDEX:
			num = numVal.asInt(items, "argument index", "*", 0);
			items.seekTo(num);
			break;
		default:
			throw new IllegalArgumentException("Unsupported goto mode " + mode);
		}

	}
}