Skip to content

Commit f698924

Browse files
committed
Fix stepEval to correctly move through times statements.
1 parent 9828551 commit f698924

2 files changed

Lines changed: 56 additions & 10 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "c4c-lib",
3-
"version": "0.2.5",
3+
"version": "0.2.51",
44
"description": "Code4Community's tools for programming games.",
55
"main": "src/index.js",
66
"scripts": {

src/interpreter/stepEval.js

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,46 @@
11
/**
2-
|--------------------------------------------------
32
| This traverses the AST step by step. Each step only evaluates one "atomic"
43
| statement, like an assignment statement or a function call statement. The
54
| stepping follows the semantics of the program. The order of statements
65
| executed with stepEval is the same as the order of statements executed with
76
| normal eval. To use it, you pass in the AST and an index / location into
8-
| the AST. It evaluates the first atomic element following that index and
9-
| returns the result along with the index for the next atomic element in the
10-
| AST.
7+
| the AST. It evaluates the first atomic element AT that index and returns
8+
| the result along with the index of the NEXT atomic element in the AST to
9+
| evaluate.
10+
11+
| A tree location is a a list of integers. The absolute index of the root
12+
| node is [] or [0]. They are equivalent. The absolute index of the root
13+
| node's first child is [0, 0], the second child is [0, 1], etc. Sometimes an
14+
| index is expressed relative to a position in the tree. Assume the current
15+
| position is a block. The index of the block's first statement is [x, 0]
16+
| where x is the position of the block relative to its parent. If the current
17+
| context is a block that is the second child of its parent, the index for
18+
| the block's third child is [1, 2]. In keeping with the equivalence of []
19+
| and [0] for the root node, the index for the block's first child can be
20+
| expressed as [x, 0] or just [x]. Based on these rules, its also the case
21+
| that the first (bottom-left most statement) of the entire tree is []. This
22+
| is useful for pointing to the start of the program without knowing the
23+
| structure of the tree. The "real" index of the start will eventually be
24+
| unfolded as [0, 0, ..., 0] as stepEval runs.
25+
26+
| Why do we need to pass the index relative to the parent to every stepEval
27+
| method? It's true that it is not necessary at all to step through that
28+
| function, but it is a compact way for a stepEval method to communicate when
29+
| done with its done with a segment of the tree. For instance, if a stepEval
30+
| is passed [4, 3] as a location and returns [5], its easy to see that we've
31+
| finished with the subtree rooted at [4] and have moved on to the sibling of
32+
| our tree (located at [5]). It could also work for each function to return a
33+
| separate boolean to say "I'm done", but they are not significantly
34+
| different.
35+
36+
| stepEvalBlock(block, [], ns) evaluates the first item of the block and
37+
| returns the result of that expression along with the index of the next
38+
| expression to evaluate. So does stepEvalBlock(block, [x], ns), and
39+
| stepEvalBlock(block, [x, 0], ns). The next index can be either [x, 1] or
40+
| [x+1] depending on the length of the block. If the block has zero length,
41+
| any location argument will evaluate nothing, step out of the block, and
42+
| return [x+1].
43+
1144
|--------------------------------------------------
1245
*/
1346

@@ -57,8 +90,18 @@ function stepEvalTimes(args, loc, env) {
5790
throw new Error('Invalid "times" statement.');
5891
}
5992

93+
if (loc.length == 0) {
94+
console.log("First stepEvalTimes call");
95+
console.log("args", args);
96+
}
97+
6098
let result, childPath;
99+
61100
let index = loc[0] || 0;
101+
102+
// upon entry, the loc is [] or [0]. The loc for the items in the times
103+
// statement's block is [1, x] where 1 indicates that the block is this time
104+
// statement's second child. x is the index into the block.
62105
if (loc.slice(1).length != 0) {
63106
childPath = loc.slice(1);
64107
} else {
@@ -76,16 +119,19 @@ function stepEvalTimes(args, loc, env) {
76119

77120
[result, newLoc] = stepEvalAST(body, childPath, env);
78121

122+
console.log("FROM", childPath);
123+
console.log("TO", newLoc);
124+
79125
// if reached end of block
80-
if (newLoc[0] >= index + 1) {
126+
if (newLoc[0] > 1) {
81127
iter += 1;
82128

83-
if (iter > times) {
129+
if (iter >= times) {
84130
// if passed through loop enough times, move outside of loop
85131
newLoc = [index + 1];
86132
} else {
87133
// otherwise, move to the beginning of loop
88-
newLoc = [index, 0];
134+
newLoc = [index, 1, 0];
89135
}
90136
} else {
91137
newLoc.unshift(index);
@@ -96,9 +142,9 @@ function stepEvalTimes(args, loc, env) {
96142
[result, newLoc] = stepEvalAST(body, childPath, env);
97143

98144
// if reached end of block
99-
if (newLoc[0] >= index + 1) {
145+
if (newLoc[0] > 1) {
100146
// move to beginning of loop
101-
newLoc = [index, 0];
147+
newLoc = [index, 1, 0];
102148
} else {
103149
newLoc.unshift(index);
104150
}

0 commit comments

Comments
 (0)