-
Notifications
You must be signed in to change notification settings - Fork 0
/
commands_flow.c
145 lines (123 loc) · 3.18 KB
/
commands_flow.c
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "commands.h"
// Variables defined in cwhitespace.c
extern int pc;
extern int errcode;
extern num stack[STACK_MAX];
extern int sp;
extern int pcstack[PCSTACK_MAX];
extern int pcsp;
extern num labels[LABEL_MAX];
extern int labelvals[LABEL_MAX];
extern num heap[HEAP_MAX];
extern num heapvals[HEAP_MAX];
extern struct stmt* cache;
extern int cache_size;
extern int cp;
int cmd_flow_mark(num arg)
{
int i, j = (arg % LABEL_MAX);
while (j < 0) j = j + LABEL_MAX;
// Attempt to create new label
// 1. Must be at least 1 open slot
// 2. Must not already exist
for (i = 0; i <= LABEL_MAX; i++, j++)
{
if (j > LABEL_MAX) j = j % LABEL_MAX;
// If we made full loop, no open spots
if (i == LABEL_MAX)
{
errcode = ERROR_LABEL_FULL; // TOO MANY LABELS DECLARED
return -1;
}
// If we find duplicate, throw error
if (labels[j] == arg && labelvals[j] != -1)
{
errcode = ERROR_LABEL_DUP; // LABEL ALREADY DECLARED
return -1;
}
// Check for clear spot. If found, take it!
if (labels[j] == -1 && labelvals[j] == -1)
{
labels[j] = arg;
labelvals[j] = cp;
return 0;
}
}
// We shouldn't ever get here. If we do, something's wrong.
return -1;
}
int cmd_flow_subroutine(num arg)
{
// Make sure we don't overflow our PC stack
if (pcsp >= PCSTACK_MAX)
{
errcode = ERROR_STACK_FULL; // STACK OVERFLOW!
return -1;
}
// Push program counter onto pc stack and goto label
pcstack[pcsp] = pc;
pcsp = pcsp + 1;
return cmd_flow_goto(arg);
}
int cmd_flow_goto(num arg)
{
int i, j = (arg % LABEL_MAX);
while (j < 0) j = j + LABEL_MAX;
// Find matching label
for (i = 0; i <= LABEL_MAX; i++, j++)
{
if (j > LABEL_MAX) j = j % LABEL_MAX;
// If we made a full loop, label not found
if (i == LABEL_MAX)
{
errcode = ERROR_LABEL_NOT_DEC;// NO SUCH LABEL
return -1;
}
// Match found; move program counter
if (labels[j] == arg && labelvals[j] != -1)
{
pc = labelvals[j];
return 0;
}
}
return 0;
}
int cmd_flow_goto_zero(num arg)
{
// Make sure we even have something on the stack
if (sp < 1)
{
errcode = ERROR_STACK_EMPTY; // ILLEGAL ACCESS
return -1;
}
if (stack[sp-1] == 0)
return cmd_flow_goto(arg);
else
return 0;
}
int cmd_flow_goto_negative(num arg)
{
// Make sure we even have something on the stack
if (sp < 1)
{
errcode = ERROR_OUT_OF_BOUNDS; // ILLEGAL ACCESS EXCEPTION
return -1;
}
if (stack[sp-1] < 0)
return cmd_flow_goto(arg);
else
return 0;
}
int cmd_flow_return()
{
// Make sure we have something to pop from
if (pcsp < 1)
{
errcode = ERROR_RETURN_NOWHERE; // RETURNING FROM NOWHERE!
return -1;
}
// Pop program counter off top of pc stack
pcsp = pcsp - 1;
pc = pcstack[pcsp];
return 0;
}