diff --git a/src/ast/utils/astToString.ts b/src/ast/utils/astToString.ts index bf4f38d0..9c6e1cb7 100644 --- a/src/ast/utils/astToString.ts +++ b/src/ast/utils/astToString.ts @@ -9,7 +9,7 @@ import { ExpressionStatement, Literal, LocalVariableDeclarationStatement, - MethodInvocation, + MethodInvocation, PostfixExpression,PrefixExpression, ReturnStatement, } from '../types/blocks-and-statements'; import { @@ -125,6 +125,13 @@ export const astToString = (node: Node, indent: number = 0): string => { case "Void": return "void"; + case "PostfixExpression": + const postfix = node as PostfixExpression; + return `${astToString(postfix.expression)}${postfix.operator}`; + case "PrefixExpression": + const prefix = node as PrefixExpression; + return `${prefix.operator}${astToString(prefix.expression)}`; + default: return node.kind; } diff --git a/src/ec-evaluator/__tests__/arithmetic.test.ts b/src/ec-evaluator/__tests__/arithmetic.test.ts index 62f8828d..0a9159e3 100644 --- a/src/ec-evaluator/__tests__/arithmetic.test.ts +++ b/src/ec-evaluator/__tests__/arithmetic.test.ts @@ -208,6 +208,7 @@ it("evaluate LocalVariableDeclarationStatement to a complex arithmetic operation // TODO test env }); + it("evaluate FieldDeclaration to a basic arithmetic expression without brackets to enforce precedence correctly", () => { const programStr = ` public class Test { @@ -302,6 +303,7 @@ it("evaluate FieldDeclaration to a basic arithmetic expression without brackets // TODO test env }); + it("evaluate FieldDeclaration to a complex arithmetic expression without brackets to enforce precedence correctly", () => { const programStr = ` public class Test { @@ -408,6 +410,7 @@ it("evaluate FieldDeclaration to a complex arithmetic expression without bracket "Void", // Void ]; + expect(result).toEqual(undefined); expect((context.control as ControlStub).getTrace().map(i => getControlItemStr(i))).toEqual(expectedControlTrace); expect((context.stash as StashStub).getTrace().map(i => getStashItemStr(i))).toEqual(expectedStashTrace); diff --git a/src/ec-evaluator/interpreter.ts b/src/ec-evaluator/interpreter.ts index 0eeb08e4..d1e32b7e 100644 --- a/src/ec-evaluator/interpreter.ts +++ b/src/ec-evaluator/interpreter.ts @@ -1,5 +1,6 @@ import { cloneDeep } from "lodash"; + import { Assignment, BinaryExpression, @@ -16,6 +17,8 @@ import { ReturnStatement, VariableDeclarator, Void, + PrefixExpression, + PostfixExpression, } from "../ast/types/blocks-and-statements"; import { ConstructorDeclaration, @@ -413,6 +416,48 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = { control.push(command.left); }, + PrefixExpression: ( + command:PrefixExpression, + environment: Environment, + control: Control, + stash: Stash, + ) => { + const operator = command.operator; // Prefix operator (e.g., "++" or "--") + const operand = command.expression; // The variable being operated on (e.g., x) + + if (operand.kind !== "ExpressionName") { + throw new errors.RuntimeError( + `Postfix operator ${operator} can only be applied to variables` + ); + } + const binExpr = { + kind: "BinaryExpression", + operator: operator === "++" ? "+" : "-", + left: operand, + right: { + kind: "Literal", + literalType: { + kind: "DecimalIntegerLiteral", + value: "1" // This is the increment/decrement value + }, + location: command.location + }, + location: command.location + } as BinaryExpression + + // Push the assignment to update the variable: + control.push({ + kind: "Assignment", + left: operand, + operator: "=", + right: binExpr, // Use the result of the binary operation + location: command.location + }); + + }, + + + [InstrType.POP]: ( _command: Instr, _environment: Environment, @@ -421,6 +466,52 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = { ) => { stash.pop(); }, + + PostfixExpression: ( + command: PostfixExpression, + _environment: Environment, + control: Control, + _stash: Stash, + ) => { + const operator = command.operator; // Postfix operator (e.g., "++" or "--") + const operand = command.expression; // The variable being operated on (e.g., x) + if (operand.kind !== "ExpressionName") { + throw new errors.RuntimeError( + `Postfix operator ${operator} can only be applied to variables` + ); + } + + control.push(instr.popInstr(operand)); + + const binExpr = { + kind: "BinaryExpression", + operator: operator === "++" ? "+" : "-", + left: operand, + right: { + kind: "Literal", + literalType: { + kind: "DecimalIntegerLiteral", + value: "1" // This is the increment/decrement value + }, + location: command.location + }, + location: command.location + } as BinaryExpression + + // Push the assignment to update the variable: + control.push({ + kind: "Assignment", + left: operand, + operator: "=", + right: binExpr, // Use the result of the binary operation + location: command.location + }); + + control.push(operand); + + // Apply the postfix operation (after using the value) + + }, [InstrType.ASSIGNMENT]: ( _command: AssmtInstr, @@ -842,3 +933,4 @@ const cmdEvaluators: { [type: string]: CmdEvaluator } = { // No post-processing required for constructor. }, }; +