Skip to content

Commit a29402b

Browse files
committed
Modify the CSEC machine to be able to run the break statement. Fix switch statements fallthrough logic and evaluation in the CSEC machine
1 parent 06b2683 commit a29402b

File tree

3 files changed

+42
-23
lines changed

3 files changed

+42
-23
lines changed

src/ec-evaluator/instrCreator.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { Expression, SwitchCase } from '../ast/types/blocks-and-statements'
33
import { EnvNode } from "./components";
44
import {
55
AssmtInstr,
6-
BinOpInstr,
7-
Class, CondInstr,
6+
BinOpInstr, BranchInstr,
7+
Class,
88
DerefInstr,
99
EnvInstr,
1010
EvalVarInstr,
@@ -155,12 +155,12 @@ export const resConOverloadInstr = (
155155
arity,
156156
});
157157

158-
export const condInstr = (
158+
export const branchInstr = (
159159
trueExpr: Expression,
160160
falseExpr: Expression,
161161
srcNode: Node,
162-
): CondInstr => ({
163-
instrType: InstrType.COND,
162+
): BranchInstr => ({
163+
instrType: InstrType.BRANCH,
164164
trueExpr,
165165
falseExpr,
166166
srcNode

src/ec-evaluator/interpreter.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { cloneDeep } from "lodash";
33
import {
44
Assignment,
55
BinaryExpression,
6-
Block,
6+
Block, BreakStatement,
77
ClassInstanceCreationExpression,
88
ExplicitConstructorInvocation,
99
Expression,
@@ -58,7 +58,7 @@ import {
5858
ResConOverloadInstr,
5959
ResOverrideInstr,
6060
ResTypeContInstr,
61-
StructType, CondInstr, SwitchInstr
61+
StructType, BranchInstr, SwitchInstr
6262
} from './types'
6363
import {
6464
defaultValues,
@@ -419,7 +419,7 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
419419
control: Control,
420420
_stash: Stash,
421421
) => {
422-
control.push(instr.condInstr(command.consequent, command.alternate, command));
422+
control.push(instr.branchInstr(command.consequent, command.alternate, command));
423423
control.push(command.condition);
424424
},
425425

@@ -429,10 +429,23 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
429429
control: Control,
430430
_stash: Stash,
431431
) => {
432+
control.push(instr.markerInstr(command));
432433
control.push(instr.switchInstr(command.cases, command.expression, command));
433434
control.push(command.expression);
434435
},
435436

437+
BreakStatement: (
438+
_command: BreakStatement,
439+
_environment: Environment,
440+
control: Control,
441+
_stash: Stash,
442+
) => {
443+
while ((control.peek() as Instr).instrType != InstrType.MARKER) {
444+
control.pop();
445+
}
446+
447+
control.pop(); // pop the marker
448+
},
436449

437450
[InstrType.POP]: (
438451
_command: Instr,
@@ -863,8 +876,8 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
863876
// No post-processing required for constructor.
864877
},
865878

866-
[InstrType.COND]: (
867-
command: CondInstr,
879+
[InstrType.BRANCH]: (
880+
command: BranchInstr,
868881
_environment: Environment,
869882
control: Control,
870883
stash: Stash,
@@ -895,34 +908,40 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = {
895908
const discValue = stash.pop() as Literal;
896909

897910
let matchedCase: SwitchCase | null = null;
911+
let matchedIndex = -1;
898912

899913
// Iterate over each switch case.
900-
for (const swCase of command.cases) {
914+
for (let i = 0; i < command.cases.length; i++) {
915+
const swCase = command.cases[i];
901916
// Check all labels for this case.
902917
for (const label of swCase.labels) {
903918
if (label.kind === "CaseLabel") {
904919
// Assume the case label's expression is a literal.
905920
const caseLiteral = label.expression as Literal;
906921
if (discValue.literalType.value === caseLiteral.literalType.value) {
907922
matchedCase = swCase;
923+
matchedIndex = i;
908924
break;
909925
}
910-
} else if (label.kind === "DefaultLabel") {
926+
} else if (label.kind === "DefaultLabel" && !matchedCase) {
911927
// Save default case (only one default should exist).
912928
matchedCase = swCase;
929+
matchedIndex = i;
913930
}
914931
}
915-
if (matchedCase) break;
916932
}
917933

918-
// Determine which case to use.
919-
if (matchedCase) {
920-
if (matchedCase && matchedCase.statements && matchedCase.statements.length > 0) {
934+
if (!matchedCase) {
935+
return // do nothing if no matching case found.
936+
}
937+
938+
for (let i = command.cases.length; i >= matchedIndex; i--) {
939+
const swCase = command.cases[i];
940+
941+
if (swCase && swCase.statements && swCase.statements.length > 0) {
921942
// Push the statements in reverse order to the control stack.
922-
for (let i = matchedCase.statements.length - 1; i >= 0; i--) {
923-
if (matchedCase.statements[i].kind == "BreakStatement")
924-
continue
925-
control.push(matchedCase.statements[i]);
943+
for (let j = swCase.statements.length - 1; j >= 0; j--) {
944+
control.push(swCase.statements[j]);
926945
}
927946
}
928947
}

src/ec-evaluator/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export enum InstrType {
4040
RES_OVERLOAD = 'ResOverload',
4141
RES_OVERRIDE = 'ResOverride',
4242
RES_CON_OVERLOAD = 'ResConOverload',
43-
COND = 'Cond',
43+
BRANCH = 'Branch',
4444
SWITCH = 'Switch',
4545
}
4646

@@ -100,7 +100,7 @@ export interface ResInstr extends BaseInstr {
100100
name: string;
101101
}
102102

103-
export interface CondInstr extends BaseInstr {
103+
export interface BranchInstr extends BaseInstr {
104104
trueExpr: Expression;
105105
falseExpr: Expression;
106106
}
@@ -128,7 +128,7 @@ export type Instr =
128128
| ResTypeContInstr
129129
| ResOverloadInstr
130130
| ResConOverloadInstr
131-
| CondInstr
131+
| BranchInstr
132132
| SwitchInstr;
133133

134134
/**

0 commit comments

Comments
 (0)