From add9917ae89d0041621c34f09eeb1c918c3349a0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:56:39 +0000 Subject: [PATCH 1/9] Plan refactor InterpreterVisitor into focused handlers Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/047028e4-d3b7-4a83-9cf4-14625a476131 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- source_.jar | Bin 344170 -> 344170 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/source_.jar b/source_.jar index 745351b716d9a68cfc5eb09507e40def976156f4..a28d6f110f627a5dfa440a56f5834f17ade803a6 100644 GIT binary patch delta 12800 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 K1%{`q9sUm}6p2j$ delta 12798 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 C3y_8Y From abd2691dc860728c11073193d0f173dd211a1371 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 23:02:30 +0000 Subject: [PATCH 2/9] Extract loop lambda array context handlers Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/047028e4-d3b7-4a83-9cf4-14625a476131 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- .../cod/interpreter/InterpreterVisitor.java | 368 +------- .../java/cod/interpreter/TailCallSignal.java | 27 + .../handler/ArrayOperationHandler.java | 583 ++++++++++++ .../interpreter/handler/ContextHelper.java | 89 ++ .../interpreter/handler/LambdaInvoker.java | 506 ++++++++++ .../interpreter/handler/LoopOptimizer.java | 877 ++++++++++++++++++ .../interpreter/handler/PatternApplier.java | 288 ++++++ 7 files changed, 2397 insertions(+), 341 deletions(-) create mode 100644 src/main/java/cod/interpreter/TailCallSignal.java create mode 100644 src/main/java/cod/interpreter/handler/ArrayOperationHandler.java create mode 100644 src/main/java/cod/interpreter/handler/ContextHelper.java create mode 100644 src/main/java/cod/interpreter/handler/LambdaInvoker.java create mode 100644 src/main/java/cod/interpreter/handler/LoopOptimizer.java create mode 100644 src/main/java/cod/interpreter/handler/PatternApplier.java diff --git a/src/main/java/cod/interpreter/InterpreterVisitor.java b/src/main/java/cod/interpreter/InterpreterVisitor.java index f38ce8c0..e4fdbebf 100644 --- a/src/main/java/cod/interpreter/InterpreterVisitor.java +++ b/src/main/java/cod/interpreter/InterpreterVisitor.java @@ -24,26 +24,6 @@ public class InterpreterVisitor extends ASTVisitor implements Evaluator private static final String SELF_CALL_LAMBDA_OWNER = "self-call lambda"; private static final double SELF_CALL_LEVEL_FLOAT_EPSILON = 1e-12d; - private static final class TailCallSignal extends RuntimeException { - public final String methodName; - public final LambdaClosure lambdaClosure; - public final List arguments; - - private TailCallSignal(String methodName, LambdaClosure lambdaClosure, List arguments) { - this.methodName = methodName; - this.lambdaClosure = lambdaClosure; - this.arguments = - arguments != null ? new ArrayList(arguments) : Collections.emptyList(); - } - - static TailCallSignal forMethod(String methodName, List arguments) { - return new TailCallSignal(methodName, null, arguments); - } - - static TailCallSignal forLambda(LambdaClosure lambdaClosure, List arguments) { - return new TailCallSignal(null, lambdaClosure, arguments); - } - } // Tail-call trampolining intentionally uses this internal signal to unwind Java frames // without allocating wrapper result objects through every visitor return path. // This favors lower allocation overhead over exception cost in non-tail paths. @@ -102,11 +82,12 @@ private static class LinearRecurrencePattern { private final Stack contextStack = new Stack(); private final ExpressionHandler expressionHandler; private final AssignmentHandler assignmentHandler; - // Lazily resolved internal.range type references used for runtime range index objects. - private Type internalRangeSpecType; - private Type internalMultiRangeSpecType; - private final LiteralRegistry literalRegistry; + private final ContextHelper contextHelper; + private final LambdaInvoker lambdaInvoker; + private final ArrayOperationHandler arrayOperationHandler; + private final PatternApplier patternApplier; + private final LoopOptimizer loopOptimizer; // ========== SIMPLE LOOP OPTIMIZATION CONSTANTS ========== private static final int LAZY_THRESHOLD = 10; // From your data: 10+ iterations = worth it @@ -127,8 +108,16 @@ public InterpreterVisitor(Interpreter interpreter, TypeHandler typeSystem, this.interpreter = interpreter; this.typeSystem = typeSystem; this.literalRegistry = literalRegistry; + this.contextHelper = new ContextHelper(interpreter); this.expressionHandler = new ExpressionHandler(typeSystem, this); this.assignmentHandler = new AssignmentHandler(typeSystem, interpreter, expressionHandler, this); + this.arrayOperationHandler = + new ArrayOperationHandler(this, interpreter, typeSystem, expressionHandler, contextHelper); + this.patternApplier = + new PatternApplier(this, typeSystem, expressionHandler, arrayOperationHandler); + this.loopOptimizer = + new LoopOptimizer(this, typeSystem, expressionHandler, arrayOperationHandler, patternApplier); + this.lambdaInvoker = new LambdaInvoker(typeSystem, this); } // Implement Evaluator interface @@ -171,7 +160,7 @@ public Object invokeLambda(Object callback, List arguments, ExecutionCon if (ctx == null) { throw new InternalError("invokeLambda called with null context"); } - return invokeLambdaCallback(callback, arguments, ctx, ownerMethod); + return lambdaInvoker.invokeLambdaCallback(callback, arguments, ctx, ownerMethod); } public void pushContext(ExecutionContext context) { @@ -206,7 +195,7 @@ public boolean isContextStackEmpty() { } private Object createNoneValue() { - return new NoneLiteral(); + return contextHelper.createNoneValue(); } @Override @@ -350,7 +339,7 @@ public Object visit(Var node) { if (node.value == null) { throw new ProgramError("Constant '" + node.name + "' must have an initial value"); } - if (isVariableDeclaredInAnyScope(ctx, node.name)) { + if (contextHelper.isVariableDeclaredInAnyScope(ctx, node.name)) { throw new ProgramError("Cannot reassign constant '" + node.name + "'"); } } @@ -368,7 +357,7 @@ public Object visit(Var node) { // If expected is [text] but actual is not text, create a converting wrapper if (expectedElementType.equals("text") && !actualElementType.equals("text")) { // Create a new NaturalArray with conversion enabled - Range range = getRangeFromArray(arr); + Range range = contextHelper.getRangeFromArray(arr); if (range != null) { val = new NaturalArray(range, this, ctx, node.explicitType); } @@ -428,62 +417,19 @@ public Object visit(Var node) { // Helper method to extract Range from NaturalArray private Range getRangeFromArray(NaturalArray arr) { - try { - java.lang.reflect.Field rangeField = NaturalArray.class.getDeclaredField("baseRange"); - rangeField.setAccessible(true); - return (Range) rangeField.get(arr); - } catch (Exception e) { - return null; - } + return contextHelper.getRangeFromArray(arr); } private Type resolveInternalRangeSpecType() { - if (internalRangeSpecType != null) { - return internalRangeSpecType; - } - try { - Type type = interpreter.getImportResolver().resolveImport("internal.range.RangeSpec"); - if (type == null) { - throw new ProgramError("Unable to load internal.range.RangeSpec"); - } - internalRangeSpecType = type; - return type; - } catch (ProgramError e) { - throw e; - } catch (Exception e) { - throw new InternalError("Failed loading internal.range.RangeSpec", e); - } + return contextHelper.resolveInternalRangeSpecType(); } private Type resolveInternalMultiRangeSpecType() { - if (internalMultiRangeSpecType != null) { - return internalMultiRangeSpecType; - } - try { - Type type = interpreter.getImportResolver().resolveImport("internal.range.MultiRangeSpec"); - if (type == null) { - throw new ProgramError("Unable to load internal.range.MultiRangeSpec"); - } - internalMultiRangeSpecType = type; - return type; - } catch (ProgramError e) { - throw e; - } catch (Exception e) { - throw new InternalError("Failed loading internal.range.MultiRangeSpec", e); - } + return contextHelper.resolveInternalMultiRangeSpecType(); } private boolean isVariableDeclaredInAnyScope(ExecutionContext ctx, String name) { - if (ctx == null || name == null) return false; - List> localsStack = ctx.getLocalsStack(); - if (localsStack == null) return false; - for (int i = localsStack.size() - 1; i >= 0; i--) { - Map scope = localsStack.get(i); - if (scope != null && scope.containsKey(name)) { - return true; - } - } - return false; + return contextHelper.isVariableDeclaredInAnyScope(ctx, name); } @Override @@ -550,71 +496,7 @@ public Object visit(ExprIf node) { // ========== UPDATED FOR NODE WITH SIMPLE LOOP DECISION ========== @Override public Object visit(For node) { - if (node == null) { - throw new InternalError("visit(For) called with null node"); - } - - ExecutionContext ctx = getCurrentContext(); - int originalDepth = ctx.getScopeDepth(); - - // Estimate loop size before execution - long loopSize = estimateLoopSize(node, ctx); - boolean hasSideEffects = hasSideEffects(node.body); - - // Simple decision: should we try lazy execution? - boolean useLazyExecution = shouldUseLazyExecution(loopSize, hasSideEffects); - - // Start tracking this loop - int loopId = ArrayTracker.beginLoop(node); - - // Store estimated size in tracker - ArrayTracker.setLoopSize(loopId, loopSize); - ArrayTracker.setSideEffects(loopId, hasSideEffects); - - try { - ctx.pushScope(); - - // Try lazy execution if beneficial - if (useLazyExecution) { - Object result = tryOptimizedExecution(node, loopId); - if (result != null) { - return result; - } - } else { - DebugSystem.debug("LOOP", - String.format("Skipping optimization: size=%d, sideEffects=%s", - loopSize, hasSideEffects)); - } - - // Normal eager execution - ArrayTracker.incrementIteration(); - - if (node.range != null) { - return executeRangeLoop(ctx, node, node.iterator); - } else if (node.arraySource != null) { - Object arrayObj = dispatch(node.arraySource); - arrayObj = typeSystem.unwrap(arrayObj); - return executeArrayLoop(ctx, node, node.iterator, arrayObj); - } - throw new ProgramError("Invalid for loop: neither range nor array source specified"); - - } catch (ProgramError e) { - throw e; - } catch (TailCallSignal e) { - throw e; - } catch (Exception e) { - throw new InternalError("For loop execution failed", e); - } finally { - // End tracking - simple log - ArrayTracker.LoopStats stats = ArrayTracker.endLoop(); - if (stats != null) { - DebugSystem.debug("LOOP", stats.toString()); - } - - while (ctx.getScopeDepth() > originalDepth) { - ctx.popScope(); - } - } + return loopOptimizer.executeForLoop(node); } // ========== SIMPLE LOOP DECISION METHODS ========== @@ -2400,130 +2282,17 @@ private Object buildDimensionArray(List ranges, int dimension) { @SuppressWarnings("unchecked") @Override public Object visit(IndexAccess node) { - if (node == null) { - throw new InternalError("visit(IndexAccess) called with null node"); - } - - try { - Object arrayObj = dispatch(node.array); - arrayObj = typeSystem.unwrap(arrayObj); - - // Force materialization BEFORE index access - if (arrayObj instanceof NaturalArray) { - NaturalArray natural = (NaturalArray) arrayObj; - if (natural.hasPendingUpdates()) { - natural.commitUpdates(); - } - } - - Object indexObj = dispatch(node.index); - indexObj = typeSystem.unwrap(indexObj); - - if (indexObj instanceof List) { - return applyTupleIndices(arrayObj, (List) indexObj); - } - - if (RangeObjects.isRangeSpec(indexObj)) { - if (arrayObj instanceof String) { - return applyStringRangeIndex((String) arrayObj, indexObj); - } - return applyRangeIndex(arrayObj, indexObj); - } - - if (RangeObjects.isMultiRangeSpec(indexObj)) { - return applyMultiRangeIndex(arrayObj, indexObj); - } - - if (arrayObj instanceof String) { - String text = (String) arrayObj; - int index = expressionHandler.toIntIndex(indexObj); - index = normalizeTextIndex(index, text.length()); - if (index < 0 || index >= text.length()) { - throw new ProgramError( - "Index out of bounds: " + index + " for text of length " + text.length()); - } - return String.valueOf(text.charAt(index)); - } - - if (arrayObj instanceof NaturalArray) { - NaturalArray natural = (NaturalArray) arrayObj; - long index = expressionHandler.toLongIndex(indexObj); - - if (natural.needsConversion()) { - return natural.get(index, true); - } - return natural.get(index); - } - - if (arrayObj instanceof List) { - List list = (List) arrayObj; - if (indexObj instanceof AutoStackingNumber) { - int index = (int) ((AutoStackingNumber) indexObj).longValue(); - if (index < 0 || index >= list.size()) { - throw new ProgramError( - "Index out of bounds: " + index + " for array of size " + list.size()); - } - return list.get(index); - } else { - int index = expressionHandler.toIntIndex(indexObj); - if (index < 0 || index >= list.size()) { - throw new ProgramError( - "Index out of bounds: " + index + " for array of size " + list.size()); - } - return list.get(index); - } - } - - throw new ProgramError( - "Invalid array access: expected NaturalArray or List, got " - + (arrayObj != null ? arrayObj.getClass().getSimpleName() : "null")); - } catch (ProgramError e) { - throw e; - } catch (Exception e) { - throw new InternalError("Index access failed", e); - } + return arrayOperationHandler.visitIndexAccess(node); } @Override public Object visit(RangeIndex node) { - if (node == null) { - throw new InternalError("visit(RangeIndex) called with null node"); - } - - try { - Object step = node.step != null ? dispatch(node.step) : null; - Object start = dispatch(node.start); - Object end = dispatch(node.end); - - return RangeObjects.createRangeSpec(resolveInternalRangeSpecType(), step, start, end); - } catch (ProgramError e) { - throw e; - } catch (Exception e) { - throw new InternalError("Range index creation failed", e); - } + return arrayOperationHandler.visitRangeIndex(node); } @Override public Object visit(MultiRangeIndex node) { - if (node == null) { - throw new InternalError("visit(MultiRangeIndex) called with null node"); - } - - try { - List ranges = new ArrayList(); - for (RangeIndex rangeNode : node.ranges) { - Object range = visit(rangeNode); - if (!RangeObjects.isRangeSpec(range)) { - throw new InternalError("Multi-range index contains non-range value"); - } - ranges.add(range); - } - return RangeObjects.createMultiRangeSpec(resolveInternalMultiRangeSpecType(), ranges); - } catch (ProgramError e) { - throw e; - } catch (Exception e) { - throw new InternalError("Multi-range index creation failed", e); - } + return arrayOperationHandler.visitMultiRangeIndex(node); } @Override @@ -2578,26 +2347,7 @@ public Object visit(Slot n) { @Override public Object visit(Lambda node) { - if (node == null) { - throw new InternalError("visit(Lambda) called with null node"); - } - - ExecutionContext ctx = getCurrentContext(); - Map captured = new HashMap(); - for (int i = 0; i < ctx.getScopeDepth(); i++) { - Map scope = ctx.getScope(i); - if (scope != null) { - captured.putAll(scope); - } - } - - return new LambdaClosure( - node, - captured, - ctx.objectInstance, - ctx.currentClass, - ctx.currentLambdaClosure, - Collections.emptyList()); + return lambdaInvoker.createLambdaClosure(node, getCurrentContext()); } private Object invokeLambdaCallback( @@ -2605,71 +2355,7 @@ private Object invokeLambdaCallback( List args, ExecutionContext parentCtx, String ownerMethod) { - - Object callback = typeSystem.unwrap(callbackObj); - LambdaClosure closure; - if (callback instanceof LambdaClosure) { - closure = (LambdaClosure) callback; - } else if (callback instanceof Lambda) { - closure = - new LambdaClosure( - (Lambda) callback, - parentCtx.locals(), - parentCtx.objectInstance, - parentCtx.currentClass, - parentCtx.currentLambdaClosure, - Collections.emptyList()); - } else { - String actualType = callback == null ? "null" : callback.getClass().getSimpleName(); - throw new ProgramError(ownerMethod + " expects a lambda callback, got: " + actualType); - } - - LambdaClosure activeClosure = closure; - List activeIncomingValues = args != null ? args : Collections.emptyList(); - - while (true) { - Lambda lambda = activeClosure.lambda; - List params = resolveLambdaParameters(lambda); - List combinedValues = - mergeBoundAndIncomingLambdaArgs(activeClosure.boundArguments, activeIncomingValues); - - if (shouldAutoCurry(params, combinedValues)) { - return createCurriedLambdaClosure(activeClosure, combinedValues); - } - - int parameterBindCount = Math.min(params.size(), combinedValues.size()); - List values = new ArrayList(combinedValues.subList(0, parameterBindCount)); - List leftoverValues = - new ArrayList(combinedValues.subList(parameterBindCount, combinedValues.size())); - - Map lambdaLocals = - bindLambdaArguments(params, values, activeClosure, ownerMethod); - if (lambda.inferParameters && params.isEmpty()) { - bindPositionalInferredPlaceholderAliases(lambdaLocals, values); - } - - Object result; - try { - if (lambda.expressionBody != null) { - result = evaluateLambdaExpressionBody(lambda, activeClosure, lambdaLocals); - } else { - result = evaluateLambdaBlockBody(lambda, activeClosure, lambdaLocals); - } - } catch (TailCallSignal tailCallSignal) { - if (tailCallSignal.lambdaClosure != null - && tailCallSignal.lambdaClosure == activeClosure) { - activeClosure = tailCallSignal.lambdaClosure; - activeIncomingValues = tailCallSignal.arguments; - continue; - } - throw tailCallSignal; - } - - if (!leftoverValues.isEmpty() && (result instanceof LambdaClosure || result instanceof Lambda)) { - return invokeLambdaCallback(result, leftoverValues, parentCtx, ownerMethod); - } - return result; - } + return lambdaInvoker.invokeLambdaCallback(callbackObj, args, parentCtx, ownerMethod); } private List resolveLambdaParameters(Lambda lambda) { diff --git a/src/main/java/cod/interpreter/TailCallSignal.java b/src/main/java/cod/interpreter/TailCallSignal.java new file mode 100644 index 00000000..9c602b1b --- /dev/null +++ b/src/main/java/cod/interpreter/TailCallSignal.java @@ -0,0 +1,27 @@ +package cod.interpreter; + +import cod.interpreter.context.LambdaClosure; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class TailCallSignal extends RuntimeException { + public final String methodName; + public final LambdaClosure lambdaClosure; + public final List arguments; + + private TailCallSignal(String methodName, LambdaClosure lambdaClosure, List arguments) { + this.methodName = methodName; + this.lambdaClosure = lambdaClosure; + this.arguments = arguments != null ? new ArrayList(arguments) : Collections.emptyList(); + } + + public static TailCallSignal forMethod(String methodName, List arguments) { + return new TailCallSignal(methodName, null, arguments); + } + + public static TailCallSignal forLambda(LambdaClosure lambdaClosure, List arguments) { + return new TailCallSignal(null, lambdaClosure, arguments); + } +} diff --git a/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java b/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java new file mode 100644 index 00000000..6fe0fc33 --- /dev/null +++ b/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java @@ -0,0 +1,583 @@ +package cod.interpreter.handler; + +import cod.ast.node.*; +import cod.error.InternalError; +import cod.error.ProgramError; +import cod.interpreter.Interpreter; +import cod.interpreter.InterpreterVisitor; +import cod.interpreter.exception.BreakLoopException; +import cod.interpreter.exception.SkipIterationException; +import cod.math.AutoStackingNumber; +import cod.range.NaturalArray; +import cod.range.Range; +import cod.range.RangeObjects; + +import java.util.ArrayList; +import java.util.List; + +public class ArrayOperationHandler { + private final InterpreterVisitor dispatcher; + private final Interpreter interpreter; + private final TypeHandler typeSystem; + private final ExpressionHandler expressionHandler; + private final ContextHelper contextHelper; + + public ArrayOperationHandler( + InterpreterVisitor dispatcher, + Interpreter interpreter, + TypeHandler typeSystem, + ExpressionHandler expressionHandler, + ContextHelper contextHelper) { + if (dispatcher == null) throw new InternalError("ArrayOperationHandler dispatcher is null"); + if (interpreter == null) throw new InternalError("ArrayOperationHandler interpreter is null"); + if (typeSystem == null) throw new InternalError("ArrayOperationHandler typeSystem is null"); + if (expressionHandler == null) throw new InternalError("ArrayOperationHandler expressionHandler is null"); + if (contextHelper == null) throw new InternalError("ArrayOperationHandler contextHelper is null"); + this.dispatcher = dispatcher; + this.interpreter = interpreter; + this.typeSystem = typeSystem; + this.expressionHandler = expressionHandler; + this.contextHelper = contextHelper; + } + + public Object executeForLoopNormally(For node) { + if (node == null) { + throw new InternalError("executeForLoopNormally called with null node"); + } + + cod.interpreter.context.ExecutionContext ctx = dispatcher.getCurrentContext(); + String iter = node.iterator; + + try { + if (node.range != null) { + return executeRangeLoop(ctx, node, iter); + } else if (node.arraySource != null) { + Object arrayObj = dispatcher.dispatch(node.arraySource); + arrayObj = typeSystem.unwrap(arrayObj); + return executeArrayLoop(ctx, node, iter, arrayObj); + } + throw new ProgramError("Invalid for loop"); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Normal loop execution failed", e); + } + } + + @SuppressWarnings("unchecked") + public Object executeArrayLoop( + cod.interpreter.context.ExecutionContext ctx, For node, String iter, Object arrayObj) { + try { + if (arrayObj instanceof NaturalArray) { + NaturalArray natural = (NaturalArray) arrayObj; + long size = natural.size(); + for (long i = 0; i < size; i++) { + Object currentValue = natural.get(i); + ctx.setVariable(iter, currentValue); + try { + executeLoopBody(ctx, node); + } catch (BreakLoopException e) { + break; + } + } + } else if (arrayObj instanceof List) { + List list = (List) arrayObj; + for (Object currentValue : list) { + ctx.setVariable(iter, currentValue); + try { + executeLoopBody(ctx, node); + } catch (BreakLoopException e) { + break; + } + } + } else { + throw new ProgramError("Cannot iterate over: " + + (arrayObj != null ? arrayObj.getClass().getSimpleName() : "null")); + } + return null; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Array loop execution failed", e); + } + } + + public Object executeRangeLoop(cod.interpreter.context.ExecutionContext ctx, For node, String iter) { + try { + Object startObj = dispatcher.dispatch(node.range.start); + Object endObj = dispatcher.dispatch(node.range.end); + startObj = typeSystem.unwrap(startObj); + endObj = typeSystem.unwrap(endObj); + + if (node.range.step != null && node.range.step instanceof BinaryOp) { + BinaryOp binOp = (BinaryOp) node.range.step; + if (binOp.left instanceof Identifier + && ((Identifier) binOp.left).name.equals(iter) + && (binOp.op.equals("*") || binOp.op.equals("/"))) { + Object rightObj = dispatcher.dispatch(binOp.right); + rightObj = typeSystem.unwrap(rightObj); + AutoStackingNumber factor = typeSystem.toAutoStackingNumber(rightObj); + validateFactor(factor, binOp.op); + return executeMultiplicativeLoop(ctx, node, startObj, endObj, factor, binOp.op); + } + } + + AutoStackingNumber step; + if (node.range.step != null) { + Object stepObj = dispatcher.dispatch(node.range.step); + step = typeSystem.toAutoStackingNumber(typeSystem.unwrap(stepObj)); + } else { + AutoStackingNumber start = typeSystem.toAutoStackingNumber(startObj); + AutoStackingNumber end = typeSystem.toAutoStackingNumber(endObj); + step = (start.compareTo(end) > 0) ? AutoStackingNumber.minusOne(1) : AutoStackingNumber.one(1); + } + + if (step.isZero()) { + throw new ProgramError("Loop step cannot be zero."); + } + + return executeAdditiveLoop(ctx, node, startObj, endObj, step); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Range loop execution failed", e); + } + } + + public Object executeAdditiveLoop( + cod.interpreter.context.ExecutionContext ctx, For node, Object startObj, Object endObj, AutoStackingNumber step) { + try { + AutoStackingNumber start = typeSystem.toAutoStackingNumber(startObj); + AutoStackingNumber end = typeSystem.toAutoStackingNumber(endObj); + AutoStackingNumber current = start; + boolean increasing = step.isPositive(); + + while (shouldContinueAdditive(current, end, step, increasing)) { + try { + executeIteration(ctx, node, current, startObj); + } catch (BreakLoopException e) { + break; + } + current = current.add(step); + } + return null; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Additive loop execution failed", e); + } + } + + public Object executeMultiplicativeLoop( + cod.interpreter.context.ExecutionContext ctx, + For node, + Object startObj, + Object endObj, + AutoStackingNumber factor, + String operation) { + try { + AutoStackingNumber start = typeSystem.toAutoStackingNumber(startObj); + AutoStackingNumber end = typeSystem.toAutoStackingNumber(endObj); + AutoStackingNumber current = start; + + while (shouldContinueMultiplicative(current, start, end, factor, operation)) { + try { + executeIteration(ctx, node, current, startObj); + } catch (BreakLoopException e) { + break; + } + if (operation.equals("*")) { + current = current.multiply(factor); + } else { + current = current.divide(factor); + } + } + return null; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Multiplicative loop execution failed", e); + } + } + + public void executeIteration( + cod.interpreter.context.ExecutionContext ctx, For node, AutoStackingNumber current, Object startObj) { + try { + String iter = node.iterator; + Object currentValue = convertToAppropriateType(current, startObj); + ctx.setVariable(iter, currentValue); + if (ctx.getVariableType(iter) == null) { + String inferredType = (current.fitsInStacks(1) && + (current.getWords()[0] & 0x7FFFFFFFFFFFFFFFL) < Long.MAX_VALUE) + ? cod.syntax.Keyword.INT.toString() : cod.syntax.Keyword.FLOAT.toString(); + ctx.setVariableType(iter, inferredType); + } + executeLoopBody(ctx, node); + } catch (BreakLoopException e) { + throw e; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Loop iteration failed", e); + } + } + + public void executeLoopBody(cod.interpreter.context.ExecutionContext ctx, For node) { + try { + for (Stmt s : node.body.statements) { + try { + dispatcher.dispatch(s); + } catch (SkipIterationException e) { + break; + } catch (BreakLoopException e) { + throw e; + } + + if (!ctx.slotsInCurrentPath.isEmpty() + && interpreter.shouldReturnEarly(ctx.getSlotValues(), ctx.slotsInCurrentPath)) return; + } + } catch (BreakLoopException e) { + throw e; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Loop body execution failed", e); + } + } + + @SuppressWarnings("unchecked") + public Object visitIndexAccess(IndexAccess node) { + if (node == null) { + throw new InternalError("visit(IndexAccess) called with null node"); + } + + try { + Object arrayObj = dispatcher.dispatch(node.array); + arrayObj = typeSystem.unwrap(arrayObj); + + if (arrayObj instanceof NaturalArray) { + NaturalArray natural = (NaturalArray) arrayObj; + if (natural.hasPendingUpdates()) { + natural.commitUpdates(); + } + } + + Object indexObj = dispatcher.dispatch(node.index); + indexObj = typeSystem.unwrap(indexObj); + + if (indexObj instanceof List) { + return applyTupleIndices(arrayObj, (List) indexObj); + } + + if (RangeObjects.isRangeSpec(indexObj)) { + if (arrayObj instanceof String) { + return applyStringRangeIndex((String) arrayObj, indexObj); + } + return applyRangeIndex(arrayObj, indexObj); + } + + if (RangeObjects.isMultiRangeSpec(indexObj)) { + return applyMultiRangeIndex(arrayObj, indexObj); + } + + if (arrayObj instanceof String) { + String text = (String) arrayObj; + int index = expressionHandler.toIntIndex(indexObj); + index = normalizeTextIndex(index, text.length()); + if (index < 0 || index >= text.length()) { + throw new ProgramError( + "Index out of bounds: " + index + " for text of length " + text.length()); + } + return String.valueOf(text.charAt(index)); + } + + if (arrayObj instanceof NaturalArray) { + NaturalArray natural = (NaturalArray) arrayObj; + long index = expressionHandler.toLongIndex(indexObj); + + if (natural.needsConversion()) { + return natural.get(index, true); + } + return natural.get(index); + } + + if (arrayObj instanceof List) { + List list = (List) arrayObj; + if (indexObj instanceof AutoStackingNumber) { + int index = (int) ((AutoStackingNumber) indexObj).longValue(); + if (index < 0 || index >= list.size()) { + throw new ProgramError( + "Index out of bounds: " + index + " for array of size " + list.size()); + } + return list.get(index); + } else { + int index = expressionHandler.toIntIndex(indexObj); + if (index < 0 || index >= list.size()) { + throw new ProgramError( + "Index out of bounds: " + index + " for array of size " + list.size()); + } + return list.get(index); + } + } + + throw new ProgramError( + "Invalid array access: expected NaturalArray or List, got " + + (arrayObj != null ? arrayObj.getClass().getSimpleName() : "null")); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Index access failed", e); + } + } + + public Object visitRangeIndex(RangeIndex node) { + if (node == null) { + throw new InternalError("visit(RangeIndex) called with null node"); + } + + try { + Object step = node.step != null ? dispatcher.dispatch(node.step) : null; + Object start = dispatcher.dispatch(node.start); + Object end = dispatcher.dispatch(node.end); + + return RangeObjects.createRangeSpec(contextHelper.resolveInternalRangeSpecType(), step, start, end); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Range index creation failed", e); + } + } + + public Object visitMultiRangeIndex(MultiRangeIndex node) { + if (node == null) { + throw new InternalError("visit(MultiRangeIndex) called with null node"); + } + + try { + List ranges = new ArrayList(); + for (RangeIndex rangeNode : node.ranges) { + Object range = visitRangeIndex(rangeNode); + if (!RangeObjects.isRangeSpec(range)) { + throw new InternalError("Multi-range index contains non-range value"); + } + ranges.add(range); + } + return RangeObjects.createMultiRangeSpec(contextHelper.resolveInternalMultiRangeSpecType(), ranges); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Multi-range index creation failed", e); + } + } + + @SuppressWarnings("unchecked") + public Object applyRangeIndex(Object array, Object range) { + if (array instanceof NaturalArray) { + NaturalArray natural = (NaturalArray) array; + return natural.getRange(range); + } else if (array instanceof List) { + List list = (List) array; + return getListRange(list, range); + } + throw new ProgramError("Cannot apply range index to " + + (array != null ? array.getClass().getSimpleName() : "null")); + } + + @SuppressWarnings("unchecked") + public Object applyMultiRangeIndex(Object array, Object multiRange) { + if (array instanceof NaturalArray) { + NaturalArray natural = (NaturalArray) array; + return natural.getMultiRange(multiRange); + } else if (array instanceof List) { + List list = (List) array; + return getListMultiRange(list, multiRange); + } + throw new ProgramError("Cannot apply multi-range index to " + + (array != null ? array.getClass().getSimpleName() : "null")); + } + + @SuppressWarnings("unchecked") + public Object applyTupleIndices(Object array, List indices) { + Object current = array; + for (Object rawIndex : indices) { + Object indexObj = typeSystem.unwrap(rawIndex); + if (RangeObjects.isRangeSpec(indexObj)) { + current = applyRangeIndex(current, indexObj); + continue; + } + if (RangeObjects.isMultiRangeSpec(indexObj)) { + current = applyMultiRangeIndex(current, indexObj); + continue; + } + if (current instanceof NaturalArray) { + NaturalArray natural = (NaturalArray) current; + long idx = expressionHandler.toLongIndex(indexObj); + current = natural.needsConversion() ? natural.get(idx, true) : natural.get(idx); + continue; + } + if (current instanceof List) { + List list = (List) current; + int idx = expressionHandler.toIntIndex(indexObj); + if (idx < 0 || idx >= list.size()) { + throw new ProgramError("Index out of bounds: " + idx + " for array of size " + list.size()); + } + current = list.get(idx); + continue; + } + throw new ProgramError("Invalid array access during multidimensional indexing: expected NaturalArray or List, got " + + (current != null ? current.getClass().getSimpleName() : "null")); + } + return current; + } + + public List getListRange(List list, Object range) { + try { + long start, end; + + start = expressionHandler.toLongIndex(RangeObjects.getStart(range)); + if (start < 0) start = list.size() + start; + + end = expressionHandler.toLongIndex(RangeObjects.getEnd(range)); + if (end < 0) end = list.size() + end; + + long step = expressionHandler.calculateStep(range); + + List result = new ArrayList(); + if (step > 0) { + for (long i = start; i <= end && i < list.size(); i += step) { + result.add(list.get((int) i)); + } + } else if (step < 0) { + for (long i = start; i >= end && i >= 0; i += step) { + result.add(list.get((int) i)); + } + } else { + throw new InternalError("Step cannot be zero - should have been caught earlier"); + } + return result; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("List range extraction failed", e); + } + } + + public List getListMultiRange(List list, Object multiRange) { + try { + List result = new ArrayList(); + for (Object range : RangeObjects.getRanges(multiRange)) { + result.addAll(getListRange(list, range)); + } + return result; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("List multi-range extraction failed", e); + } + } + + public String applyStringRangeIndex(String text, Object range) { + try { + long start = expressionHandler.toLongIndex(RangeObjects.getStart(range)); + long end = expressionHandler.toLongIndex(RangeObjects.getEnd(range)); + long step = expressionHandler.calculateStep(range); + + int length = text.length(); + start = normalizeTextIndex(start, length); + end = normalizeTextIndex(end, length); + + if (start < 0 || start >= length) { + throw new ProgramError("Range start index out of bounds: " + start + " for text of length " + length); + } + if (end < 0 || end >= length) { + throw new ProgramError("Range end index out of bounds: " + end + " for text of length " + length); + } + if (step == 0) { + throw new ProgramError("Range step cannot be zero"); + } + + StringBuilder result = new StringBuilder(); + if (step > 0) { + for (long i = start; i <= end; i += step) { + result.append(text.charAt((int) i)); + } + } else { + for (long i = start; i >= end; i += step) { + result.append(text.charAt((int) i)); + } + } + return result.toString(); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("String range extraction failed", e); + } + } + + public int normalizeTextIndex(int index, int length) { + return (int) normalizeTextIndex((long) index, length); + } + + public long normalizeTextIndex(long index, int length) { + if (index < 0) { + return length + index; + } + return index; + } + + public long calculateRangeStep(Range range) { + if (range == null) { + return 1L; + } + + if (range.step != null) { + Object stepObj = dispatcher.dispatch(range.step); + return expressionHandler.toLong(stepObj); + } + + Object startObj = dispatcher.dispatch(range.start); + Object endObj = dispatcher.dispatch(range.end); + long start = expressionHandler.toLong(startObj); + long end = expressionHandler.toLong(endObj); + + return (start < end) ? 1L : -1L; + } + + private boolean shouldContinueAdditive( + AutoStackingNumber current, AutoStackingNumber end, AutoStackingNumber step, boolean increasing) { + return increasing ? current.compareTo(end) <= 0 : current.compareTo(end) >= 0; + } + + private void validateFactor(AutoStackingNumber factor, String operation) { + if (factor.compareTo(AutoStackingNumber.zero(1)) <= 0) { + throw new ProgramError("Factor must be positive"); + } + } + + private boolean shouldContinueMultiplicative( + AutoStackingNumber current, AutoStackingNumber start, AutoStackingNumber end, + AutoStackingNumber factor, String operation) { + int startEndComparison = start.compareTo(end); + if (operation.equals("*")) { + return factor.compareTo(AutoStackingNumber.one(1)) > 0 + ? (startEndComparison < 0 ? current.compareTo(end) <= 0 : current.compareTo(end) >= 0) + : (startEndComparison > 0 ? current.compareTo(end) >= 0 : current.compareTo(end) <= 0); + } else { + return factor.compareTo(AutoStackingNumber.one(1)) > 0 + ? (startEndComparison > 0 ? current.compareTo(end) >= 0 : current.compareTo(end) <= 0) + : (startEndComparison < 0 ? current.compareTo(end) <= 0 : current.compareTo(end) >= 0); + } + } + + private Object convertToAppropriateType(AutoStackingNumber value, Object original) { + if ((original instanceof Integer || original instanceof Long || + original instanceof IntLiteral) && value.fitsInStacks(1)) { + try { + return (int) value.longValue(); + } catch (ArithmeticException e) { + return value.longValue(); + } + } + return value; + } +} diff --git a/src/main/java/cod/interpreter/handler/ContextHelper.java b/src/main/java/cod/interpreter/handler/ContextHelper.java new file mode 100644 index 00000000..40177fb7 --- /dev/null +++ b/src/main/java/cod/interpreter/handler/ContextHelper.java @@ -0,0 +1,89 @@ +package cod.interpreter.handler; + +import cod.ast.node.NoneLiteral; +import cod.ast.node.Type; +import cod.error.InternalError; +import cod.error.ProgramError; +import cod.interpreter.Interpreter; +import cod.interpreter.context.ExecutionContext; +import cod.range.NaturalArray; +import cod.range.Range; + +import java.util.List; +import java.util.Map; + +public class ContextHelper { + private final Interpreter interpreter; + private Type internalRangeSpecType; + private Type internalMultiRangeSpecType; + + public ContextHelper(Interpreter interpreter) { + if (interpreter == null) { + throw new InternalError("ContextHelper constructed with null interpreter"); + } + this.interpreter = interpreter; + } + + public Object createNoneValue() { + return new NoneLiteral(); + } + + public Range getRangeFromArray(NaturalArray arr) { + try { + java.lang.reflect.Field rangeField = NaturalArray.class.getDeclaredField("baseRange"); + rangeField.setAccessible(true); + return (Range) rangeField.get(arr); + } catch (Exception e) { + return null; + } + } + + public Type resolveInternalRangeSpecType() { + if (internalRangeSpecType != null) { + return internalRangeSpecType; + } + try { + Type type = interpreter.getImportResolver().resolveImport("internal.range.RangeSpec"); + if (type == null) { + throw new ProgramError("Unable to load internal.range.RangeSpec"); + } + internalRangeSpecType = type; + return type; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Failed loading internal.range.RangeSpec", e); + } + } + + public Type resolveInternalMultiRangeSpecType() { + if (internalMultiRangeSpecType != null) { + return internalMultiRangeSpecType; + } + try { + Type type = interpreter.getImportResolver().resolveImport("internal.range.MultiRangeSpec"); + if (type == null) { + throw new ProgramError("Unable to load internal.range.MultiRangeSpec"); + } + internalMultiRangeSpecType = type; + return type; + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Failed loading internal.range.MultiRangeSpec", e); + } + } + + public boolean isVariableDeclaredInAnyScope(ExecutionContext ctx, String name) { + if (ctx == null || name == null) return false; + List> localsStack = ctx.getLocalsStack(); + if (localsStack == null) return false; + for (int i = localsStack.size() - 1; i >= 0; i--) { + Map scope = localsStack.get(i); + if (scope != null && scope.containsKey(name)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/cod/interpreter/handler/LambdaInvoker.java b/src/main/java/cod/interpreter/handler/LambdaInvoker.java new file mode 100644 index 00000000..42477b3b --- /dev/null +++ b/src/main/java/cod/interpreter/handler/LambdaInvoker.java @@ -0,0 +1,506 @@ +package cod.interpreter.handler; + +import cod.ast.node.*; +import cod.error.InternalError; +import cod.error.ProgramError; +import cod.interpreter.InterpreterVisitor; +import cod.interpreter.TailCallSignal; +import cod.interpreter.context.ExecutionContext; +import cod.interpreter.context.LambdaClosure; + +import java.util.*; + +public class LambdaInvoker { + private final TypeHandler typeSystem; + private final InterpreterVisitor dispatcher; + + public LambdaInvoker(TypeHandler typeSystem, InterpreterVisitor dispatcher) { + if (typeSystem == null) { + throw new InternalError("LambdaInvoker constructed with null typeSystem"); + } + if (dispatcher == null) { + throw new InternalError("LambdaInvoker constructed with null dispatcher"); + } + this.typeSystem = typeSystem; + this.dispatcher = dispatcher; + } + + public LambdaClosure createLambdaClosure(Lambda node, ExecutionContext ctx) { + if (node == null) { + throw new InternalError("createLambdaClosure called with null node"); + } + if (ctx == null) { + throw new InternalError("createLambdaClosure called with null context"); + } + + Map captured = new HashMap(); + for (int i = 0; i < ctx.getScopeDepth(); i++) { + Map scope = ctx.getScope(i); + if (scope != null) { + captured.putAll(scope); + } + } + + return new LambdaClosure( + node, + captured, + ctx.objectInstance, + ctx.currentClass, + ctx.currentLambdaClosure, + Collections.emptyList()); + } + + public Object invokeLambdaCallback( + Object callbackObj, + List args, + ExecutionContext parentCtx, + String ownerMethod) { + + Object callback = typeSystem.unwrap(callbackObj); + LambdaClosure closure; + if (callback instanceof LambdaClosure) { + closure = (LambdaClosure) callback; + } else if (callback instanceof Lambda) { + closure = + new LambdaClosure( + (Lambda) callback, + parentCtx.locals(), + parentCtx.objectInstance, + parentCtx.currentClass, + parentCtx.currentLambdaClosure, + Collections.emptyList()); + } else { + String actualType = callback == null ? "null" : callback.getClass().getSimpleName(); + throw new ProgramError(ownerMethod + " expects a lambda callback, got: " + actualType); + } + + LambdaClosure activeClosure = closure; + List activeIncomingValues = args != null ? args : Collections.emptyList(); + + while (true) { + Lambda lambda = activeClosure.lambda; + List params = resolveLambdaParameters(lambda); + List combinedValues = + mergeBoundAndIncomingLambdaArgs(activeClosure.boundArguments, activeIncomingValues); + + if (shouldAutoCurry(params, combinedValues)) { + return createCurriedLambdaClosure(activeClosure, combinedValues); + } + + int parameterBindCount = Math.min(params.size(), combinedValues.size()); + List values = new ArrayList(combinedValues.subList(0, parameterBindCount)); + List leftoverValues = + new ArrayList(combinedValues.subList(parameterBindCount, combinedValues.size())); + + Map lambdaLocals = + bindLambdaArguments(params, values, activeClosure, ownerMethod); + if (lambda.inferParameters && params.isEmpty()) { + bindPositionalInferredPlaceholderAliases(lambdaLocals, values); + } + + Object result; + try { + if (lambda.expressionBody != null) { + result = evaluateLambdaExpressionBody(lambda, activeClosure, lambdaLocals); + } else { + result = evaluateLambdaBlockBody(lambda, activeClosure, lambdaLocals); + } + } catch (TailCallSignal tailCallSignal) { + if (tailCallSignal.lambdaClosure != null + && tailCallSignal.lambdaClosure == activeClosure) { + activeClosure = tailCallSignal.lambdaClosure; + activeIncomingValues = tailCallSignal.arguments; + continue; + } + throw tailCallSignal; + } + + if (!leftoverValues.isEmpty() && (result instanceof LambdaClosure || result instanceof Lambda)) { + return invokeLambdaCallback(result, leftoverValues, parentCtx, ownerMethod); + } + return result; + } + } + + private List resolveLambdaParameters(Lambda lambda) { + if (lambda == null) { + return new ArrayList(); + } + List params = + lambda.parameters != null ? lambda.parameters : new ArrayList(); + if (!params.isEmpty()) { + return params; + } + if (!lambda.inferParameters) { + return params; + } + + List inferred = inferLambdaParamsFromPlaceholders(lambda); + return inferred; + } + + private List mergeBoundAndIncomingLambdaArgs(List boundArgs, List incomingArgs) { + if ((boundArgs == null || boundArgs.isEmpty()) && (incomingArgs == null || incomingArgs.isEmpty())) { + return Collections.emptyList(); + } + List combined = new ArrayList(); + if (boundArgs != null && !boundArgs.isEmpty()) { + combined.addAll(boundArgs); + } + if (incomingArgs != null && !incomingArgs.isEmpty()) { + combined.addAll(incomingArgs); + } + return combined; + } + + private boolean shouldAutoCurry(List params, List values) { + if (params == null || params.isEmpty()) return false; + int requiredCount = 0; + for (Param param : params) { + if (param == null) continue; + if (!param.hasDefaultValue) { + requiredCount++; + } + } + return values.size() < requiredCount; + } + + private LambdaClosure createCurriedLambdaClosure( + LambdaClosure closure, + List boundArgs) { + + return new LambdaClosure( + closure.lambda, + closure.capturedLocals, + closure.objectInstance, + closure.currentClass, + closure.parentClosure, + boundArgs); + } + + private Map bindLambdaArguments( + List params, + List values, + LambdaClosure closure, + String ownerMethod) { + + Map lambdaLocals = new HashMap(closure.capturedLocals); + for (int i = 0; i < params.size(); i++) { + Param param = params.get(i); + if (param == null || param.name == null) continue; + + Object boundValue = resolveLambdaArgumentValue(i, param, values, closure, lambdaLocals, ownerMethod); + validateLambdaArgumentType(param, boundValue); + lambdaLocals.put(param.name, boundValue); + } + return lambdaLocals; + } + + private Object resolveLambdaArgumentValue( + int index, + Param param, + List values, + LambdaClosure closure, + Map lambdaLocals, + String ownerMethod) { + + if (index < values.size()) { + return values.get(index); + } + if (param.hasDefaultValue && param.defaultValue != null) { + return evaluateLambdaDefaultValue(param, closure, lambdaLocals); + } + throw new ProgramError( + "Missing value for lambda parameter '" + param.name + "' in " + ownerMethod + " callback"); + } + + private Object evaluateLambdaDefaultValue( + Param param, + LambdaClosure closure, + Map lambdaLocals) { + + ExecutionContext defaultCtx = + new ExecutionContext(closure.objectInstance, lambdaLocals, null, null, typeSystem); + defaultCtx.currentClass = closure.currentClass; + defaultCtx.currentLambdaClosure = closure; + dispatcher.pushContext(defaultCtx); + try { + return dispatcher.visit((Base) param.defaultValue); + } finally { + dispatcher.popContext(); + } + } + + private void validateLambdaArgumentType(Param param, Object boundValue) { + if (param.type != null && !typeSystem.validateType(param.type, boundValue)) { + throw new ProgramError( + "Lambda parameter type mismatch for '" + param.name + "'. Expected " + + param.type + ", got: " + typeSystem.getConcreteType(boundValue)); + } + } + + private Object evaluateLambdaExpressionBody( + Lambda lambda, + LambdaClosure closure, + Map lambdaLocals) { + + ExecutionContext exprCtx = + new ExecutionContext(closure.objectInstance, lambdaLocals, null, null, typeSystem); + exprCtx.currentClass = closure.currentClass; + exprCtx.currentLambdaClosure = closure; + dispatcher.pushContext(exprCtx); + try { + return dispatcher.dispatch(lambda.expressionBody); + } finally { + dispatcher.popContext(); + } + } + + private void bindPositionalInferredPlaceholderAliases( + Map lambdaLocals, + List values) { + + if (values == null || values.isEmpty()) return; + Object first = values.get(0); + putIfAbsent(lambdaLocals, "$item", first); + putIfAbsent(lambdaLocals, "$left", first); + putIfAbsent(lambdaLocals, "$acc", first); + putIfAbsent(lambdaLocals, "$value", first); + + if (values.size() > 1) { + Object second = values.get(1); + putIfAbsent(lambdaLocals, "$index", second); + putIfAbsent(lambdaLocals, "$right", second); + putIfAbsent(lambdaLocals, "$next", second); + } + + if (values.size() > 2) { + Object third = values.get(2); + putIfAbsent(lambdaLocals, "$index", third); + putIfAbsent(lambdaLocals, "$position", third); + } + } + + private void putIfAbsent(Map lambdaLocals, String name, Object value) { + if (!lambdaLocals.containsKey(name)) { + lambdaLocals.put(name, value); + } + } + + private Object evaluateLambdaBlockBody( + Lambda lambda, + LambdaClosure closure, + Map lambdaLocals) { + + List lambdaSlots = + lambda.returnSlots != null ? lambda.returnSlots : new ArrayList(); + if (lambdaSlots.isEmpty()) { + throw new ProgramError( + "Lambda with explicit body requires a return contract (::). " + + "Use expression body syntax for implicit return values."); + } + + Map slotValues = new LinkedHashMap(); + Map slotTypes = new LinkedHashMap(); + for (Slot slot : lambdaSlots) { + slotValues.put(slot.name, null); + slotTypes.put(slot.name, slot.type); + } + + ExecutionContext lambdaCtx = + new ExecutionContext(closure.objectInstance, lambdaLocals, slotValues, slotTypes, typeSystem); + lambdaCtx.currentClass = closure.currentClass; + lambdaCtx.currentLambdaClosure = closure; + dispatcher.pushContext(lambdaCtx); + try { + if (lambda.body != null) { + dispatcher.visit((Base) lambda.body); + } + } catch (cod.interpreter.exception.EarlyExitException e) { + // normal lambda early exit + } finally { + dispatcher.popContext(); + } + + if (lambdaSlots.size() == 1) { + return slotValues.get(lambdaSlots.get(0).name); + } + return slotValues; + } + + private List inferLambdaParamsFromPlaceholders(Lambda lambda) { + if (lambda == null) { + return new ArrayList(); + } + LinkedHashSet names = new LinkedHashSet(); + + if (lambda.expressionBody != null) { + collectPlaceholderNames(lambda.expressionBody, names); + } else if (lambda.body != null) { + collectPlaceholderNames(lambda.body, names); + } + + List params = new ArrayList(); + for (String name : names) { + Param param = new Param(); + param.name = name; + param.type = null; + param.typeInferred = true; + param.isLambdaParameter = true; + params.add(param); + } + return params; + } + + private void collectPlaceholderNames(Base node, LinkedHashSet names) { + if (node == null) return; + + if (node instanceof Identifier) { + String name = ((Identifier) node).name; + if (name != null && name.startsWith("$") && name.length() > 1) { + names.add(name); + } + return; + } + + if (node instanceof BinaryOp) { + BinaryOp n = (BinaryOp) node; + collectPlaceholderNames(n.left, names); + collectPlaceholderNames(n.right, names); + return; + } + if (node instanceof Unary) { + collectPlaceholderNames(((Unary) node).operand, names); + return; + } + if (node instanceof TypeCast) { + collectPlaceholderNames(((TypeCast) node).expression, names); + return; + } + if (node instanceof MethodCall) { + MethodCall n = (MethodCall) node; + if (n.arguments != null) { + for (Expr arg : n.arguments) { + collectPlaceholderNames(arg, names); + } + } + if (n.target != null) { + collectPlaceholderNames(n.target, names); + } + return; + } + if (node instanceof PropertyAccess) { + PropertyAccess n = (PropertyAccess) node; + collectPlaceholderNames(n.left, names); + collectPlaceholderNames(n.right, names); + return; + } + if (node instanceof IndexAccess) { + IndexAccess n = (IndexAccess) node; + collectPlaceholderNames(n.array, names); + collectPlaceholderNames(n.index, names); + return; + } + if (node instanceof Array) { + Array n = (Array) node; + if (n.elements != null) { + for (Expr elem : n.elements) { + collectPlaceholderNames(elem, names); + } + } + return; + } + if (node instanceof Tuple) { + Tuple n = (Tuple) node; + if (n.elements != null) { + for (Expr elem : n.elements) { + collectPlaceholderNames(elem, names); + } + } + return; + } + if (node instanceof ExprIf) { + ExprIf n = (ExprIf) node; + collectPlaceholderNames(n.condition, names); + collectPlaceholderNames(n.thenExpr, names); + collectPlaceholderNames(n.elseExpr, names); + return; + } + if (node instanceof BooleanChain) { + BooleanChain n = (BooleanChain) node; + if (n.expressions != null) { + for (Expr expr : n.expressions) { + collectPlaceholderNames(expr, names); + } + } + return; + } + if (node instanceof EqualityChain) { + EqualityChain n = (EqualityChain) node; + collectPlaceholderNames(n.left, names); + if (n.chainArguments != null) { + for (Expr expr : n.chainArguments) { + collectPlaceholderNames(expr, names); + } + } + return; + } + if (node instanceof ChainedComparison) { + ChainedComparison n = (ChainedComparison) node; + if (n.expressions != null) { + for (Expr expr : n.expressions) { + collectPlaceholderNames(expr, names); + } + } + return; + } + if (node instanceof ValueExpr) { + Object value = ((ValueExpr) node).getValue(); + if (value instanceof Base) { + collectPlaceholderNames((Base) value, names); + } + return; + } + if (node instanceof Lambda) { + return; + } + + if (node instanceof Block) { + Block n = (Block) node; + if (n.statements != null) { + for (Stmt stmt : n.statements) { + collectPlaceholderNames(stmt, names); + } + } + return; + } + if (node instanceof SlotAssignment) { + collectPlaceholderNames(((SlotAssignment) node).value, names); + return; + } + if (node instanceof MultipleSlotAssignment) { + MultipleSlotAssignment n = (MultipleSlotAssignment) node; + if (n.assignments != null) { + for (SlotAssignment asg : n.assignments) { + collectPlaceholderNames(asg, names); + } + } + return; + } + if (node instanceof Assignment) { + Assignment n = (Assignment) node; + collectPlaceholderNames(n.left, names); + collectPlaceholderNames(n.right, names); + return; + } + if (node instanceof Var) { + collectPlaceholderNames(((Var) node).value, names); + return; + } + if (node instanceof ReturnSlotAssignment) { + ReturnSlotAssignment n = (ReturnSlotAssignment) node; + collectPlaceholderNames(n.methodCall, names); + collectPlaceholderNames(n.lambda, names); + } + } +} diff --git a/src/main/java/cod/interpreter/handler/LoopOptimizer.java b/src/main/java/cod/interpreter/handler/LoopOptimizer.java new file mode 100644 index 00000000..f41ebe1c --- /dev/null +++ b/src/main/java/cod/interpreter/handler/LoopOptimizer.java @@ -0,0 +1,877 @@ +package cod.interpreter.handler; + +import cod.ast.ASTFactory; +import cod.ast.node.*; +import cod.debug.DebugSystem; +import cod.error.InternalError; +import cod.error.ProgramError; +import cod.interpreter.InterpreterVisitor; +import cod.interpreter.TailCallSignal; +import cod.interpreter.context.ExecutionContext; +import cod.interpreter.exception.BreakLoopException; +import cod.math.AutoStackingNumber; +import cod.range.NaturalArray; +import cod.range.Range; +import cod.range.pattern.ArrayTracker; +import cod.range.pattern.ConditionalPattern; +import cod.range.pattern.OutputAwarePattern; +import cod.range.pattern.SequencePattern; +import cod.range.formula.ConditionalFormula; +import cod.range.formula.SequenceFormula; + +import java.util.*; + +public class LoopOptimizer { + private static final int LAZY_THRESHOLD = 10; + private static final int MAX_SUPPORTED_LAG = 64; + + private final InterpreterVisitor dispatcher; + private final TypeHandler typeSystem; + private final ExpressionHandler expressionHandler; + private final ArrayOperationHandler arrayOperationHandler; + private final PatternApplier patternApplier; + + public LoopOptimizer( + InterpreterVisitor dispatcher, + TypeHandler typeSystem, + ExpressionHandler expressionHandler, + ArrayOperationHandler arrayOperationHandler, + PatternApplier patternApplier) { + if (dispatcher == null) throw new InternalError("LoopOptimizer dispatcher is null"); + if (typeSystem == null) throw new InternalError("LoopOptimizer typeSystem is null"); + if (expressionHandler == null) throw new InternalError("LoopOptimizer expressionHandler is null"); + if (arrayOperationHandler == null) throw new InternalError("LoopOptimizer arrayOperationHandler is null"); + if (patternApplier == null) throw new InternalError("LoopOptimizer patternApplier is null"); + this.dispatcher = dispatcher; + this.typeSystem = typeSystem; + this.expressionHandler = expressionHandler; + this.arrayOperationHandler = arrayOperationHandler; + this.patternApplier = patternApplier; + } + + public Object executeForLoop(For node) { + if (node == null) { + throw new InternalError("visit(For) called with null node"); + } + + ExecutionContext ctx = dispatcher.getCurrentContext(); + int originalDepth = ctx.getScopeDepth(); + + long loopSize = estimateLoopSize(node, ctx); + boolean hasSideEffects = hasSideEffects(node.body); + + boolean useLazyExecution = shouldUseLazyExecution(loopSize, hasSideEffects); + + int loopId = ArrayTracker.beginLoop(node); + + ArrayTracker.setLoopSize(loopId, loopSize); + ArrayTracker.setSideEffects(loopId, hasSideEffects); + + try { + ctx.pushScope(); + + if (useLazyExecution) { + Object result = tryOptimizedExecution(node, loopId); + if (result != null) { + return result; + } + } else { + DebugSystem.debug("LOOP", + String.format("Skipping optimization: size=%d, sideEffects=%s", + loopSize, hasSideEffects)); + } + + ArrayTracker.incrementIteration(); + + if (node.range != null) { + return arrayOperationHandler.executeRangeLoop(ctx, node, node.iterator); + } else if (node.arraySource != null) { + Object arrayObj = dispatcher.dispatch(node.arraySource); + arrayObj = typeSystem.unwrap(arrayObj); + return arrayOperationHandler.executeArrayLoop(ctx, node, node.iterator, arrayObj); + } + throw new ProgramError("Invalid for loop: neither range nor array source specified"); + + } catch (ProgramError e) { + throw e; + } catch (TailCallSignal e) { + throw e; + } catch (Exception e) { + throw new InternalError("For loop execution failed", e); + } finally { + ArrayTracker.LoopStats stats = ArrayTracker.endLoop(); + if (stats != null) { + DebugSystem.debug("LOOP", stats.toString()); + } + + while (ctx.getScopeDepth() > originalDepth) { + ctx.popScope(); + } + } + } + + public boolean shouldUseLazyExecution(long loopSize, boolean hasSideEffects) { + if (loopSize < 0) { + return false; + } + + if (loopSize < LAZY_THRESHOLD) { + return !hasSideEffects; + } + + return true; + } + + public long estimateLoopSize(For node, ExecutionContext ctx) { + try { + if (node.range != null) { + Object startObj = dispatcher.dispatch(node.range.start); + Object endObj = dispatcher.dispatch(node.range.end); + + startObj = typeSystem.unwrap(startObj); + endObj = typeSystem.unwrap(endObj); + + AutoStackingNumber start = typeSystem.toAutoStackingNumber(startObj); + AutoStackingNumber end = typeSystem.toAutoStackingNumber(endObj); + + AutoStackingNumber step; + if (node.range.step != null) { + Object stepObj = dispatcher.dispatch(node.range.step); + step = typeSystem.toAutoStackingNumber(typeSystem.unwrap(stepObj)); + } else { + step = (start.compareTo(end) > 0) ? + AutoStackingNumber.minusOne(1) : AutoStackingNumber.one(1); + } + + if (step.isZero()) return 0; + + AutoStackingNumber diff = end.subtract(start); + AutoStackingNumber steps = diff.divide(step); + AutoStackingNumber size = steps.add(AutoStackingNumber.one(1)); + + return size.longValue(); + + } else if (node.arraySource != null) { + Object arrayObj = dispatcher.dispatch(node.arraySource); + arrayObj = typeSystem.unwrap(arrayObj); + + if (arrayObj instanceof NaturalArray) { + NaturalArray arr = (NaturalArray) arrayObj; + if (arr.hasPendingUpdates()) { + arr.commitUpdates(); + } + return arr.size(); + } else if (arrayObj instanceof List) { + return ((List) arrayObj).size(); + } + } + } catch (Exception e) { + DebugSystem.debug("LOOP", "Failed to estimate size: " + e.getMessage()); + } + + return -1; + } + + public boolean hasSideEffects(Block body) { + if (body == null || body.statements == null) return false; + + for (Stmt stmt : body.statements) { + if (stmt instanceof MethodCall) { + MethodCall call = (MethodCall) stmt; + if ("out".equals(call.name) || "outs".equals(call.name) || "in".equals(call.name)) { + return true; + } + return true; + } + + if (stmt instanceof StmtIf) { + StmtIf ifStmt = (StmtIf) stmt; + if (hasSideEffects(ifStmt.thenBlock) || hasSideEffects(ifStmt.elseBlock)) { + return true; + } + } + + if (stmt instanceof For) { + return true; + } + + if (stmt instanceof Assignment) { + Assignment assign = (Assignment) stmt; + if (assign.left instanceof PropertyAccess) { + return true; + } + } + } + + return false; + } + + public Object tryOptimizedExecution(For node, int loopId) { + OutputAwarePattern.OutputPattern outputPattern = + OutputAwarePattern.extract(node, node.iterator); + + if (outputPattern.isOptimizable) { + try { + Object result = executeOutputAwareLoop(node, outputPattern); + ArrayTracker.markLoopOptimized(loopId); + return result; + } catch (Exception e) { + DebugSystem.debug("OPTIMIZER", "Output pattern failed: " + e.getMessage()); + } + } + + List multiArrayPatterns = extractMultiArraySequencePatterns(node); + if (!multiArrayPatterns.isEmpty()) { + try { + Object result = patternApplier.applyPatterns(node, multiArrayPatterns); + ArrayTracker.markLoopOptimized(loopId); + return result; + } catch (Exception e) { + DebugSystem.debug("OPTIMIZER", "Multi-array pattern failed: " + e.getMessage()); + } + } + + PatternApplier.LinearRecurrencePattern recurrencePattern = extractLinearRecurrencePattern(node); + if (recurrencePattern != null) { + try { + List patterns = new ArrayList(); + patterns.add(new PatternApplier.PatternResult(PatternApplier.PatternType.LINEAR_RECURRENCE, recurrencePattern, recurrencePattern.targetArray)); + Object result = patternApplier.applyPatterns(node, patterns); + ArrayTracker.markLoopOptimized(loopId); + return result; + } catch (Exception e) { + DebugSystem.debug("OPTIMIZER", "Linear recurrence pattern failed: " + e.getMessage()); + } + } + + SequencePattern.Pattern seqPattern = + SequencePattern.extract(node.body.statements, node.iterator); + if (seqPattern != null && seqPattern.isOptimizable()) { + try { + List patterns = new ArrayList(); + patterns.add(new PatternApplier.PatternResult(PatternApplier.PatternType.SEQUENCE, seqPattern, seqPattern.targetArray)); + Object result = patternApplier.applyPatterns(node, patterns); + ArrayTracker.markLoopOptimized(loopId); + return result; + } catch (Exception e) { + DebugSystem.debug("OPTIMIZER", "Sequence pattern failed: " + e.getMessage()); + } + } + + List allPatterns = new ArrayList(); + for (Stmt stmt : node.body.statements) { + if (stmt instanceof StmtIf) { + StmtIf ifStmt = (StmtIf) stmt; + List patterns = extractConditionalPatterns(ifStmt, node.iterator); + for (ConditionalPattern pattern : patterns) { + if (pattern != null && pattern.isOptimizable()) { + allPatterns.add(new PatternApplier.PatternResult(PatternApplier.PatternType.CONDITIONAL, pattern, pattern.array)); + } + } + } + } + + if (!allPatterns.isEmpty()) { + try { + Object result = patternApplier.applyPatterns(node, allPatterns); + ArrayTracker.markLoopOptimized(loopId); + return result; + } catch (Exception e) { + DebugSystem.debug("OPTIMIZER", "Conditional pattern failed: " + e.getMessage()); + } + } + + return null; + } + + public PatternApplier.LinearRecurrencePattern extractLinearRecurrencePattern(For node) { + if (node == null || node.body == null || node.body.statements == null) { + return null; + } + if (node.body.statements.size() != 1) { + return null; + } + if (!(node.body.statements.get(0) instanceof Assignment)) { + return null; + } + Assignment assign = (Assignment) node.body.statements.get(0); + if (!(assign.left instanceof IndexAccess)) { + return null; + } + IndexAccess leftAccess = (IndexAccess) assign.left; + if (!(leftAccess.array instanceof Identifier) || !(leftAccess.index instanceof Identifier)) { + return null; + } + String iter = node.iterator; + Identifier idx = (Identifier) leftAccess.index; + if (!iter.equals(idx.name)) { + return null; + } + + Object resolved = dispatcher.dispatch(leftAccess.array); + resolved = typeSystem.unwrap(resolved); + if (!(resolved instanceof NaturalArray)) { + return null; + } + NaturalArray targetArray = (NaturalArray) resolved; + + Set deps = new HashSet(); + collectIndexedArrayRefs(assign.right, iter, deps); + String targetName = ((Identifier) leftAccess.array).name; + if (!deps.contains(targetName)) { + return null; + } + for (String dep : deps) { + if (!targetName.equals(dep)) { + return null; + } + } + + AutoStackingNumber[] coeff = new AutoStackingNumber[MAX_SUPPORTED_LAG + 1]; + for (int i = 0; i < coeff.length; i++) coeff[i] = AutoStackingNumber.fromLong(0L); + AutoStackingNumber[] constant = new AutoStackingNumber[]{AutoStackingNumber.fromLong(0L)}; + if (!collectLinearTerms(assign.right, targetName, iter, coeff, constant, AutoStackingNumber.fromLong(1L))) { + return null; + } + + int maxLag = 0; + boolean hasAnyLag = false; + for (int lag = 1; lag < coeff.length; lag++) { + if (!coeff[lag].isZero()) { + hasAnyLag = true; + if (lag > maxLag) maxLag = lag; + } + } + if (!hasAnyLag || maxLag <= 0) { + return null; + } + + int order = maxLag; + AutoStackingNumber[] coeffByLag = new AutoStackingNumber[order]; + for (int lag = 1; lag <= order; lag++) { + coeffByLag[lag - 1] = coeff[lag]; + } + + long[] bounds = resolveLoopBounds(node); + if (bounds == null) { + return null; + } + long min = bounds[0]; + long max = bounds[1]; + long recurrenceStart = min; + if (recurrenceStart < order) { + recurrenceStart = order; + } + if (recurrenceStart > max) { + return null; + } + + AutoStackingNumber[] seed = new AutoStackingNumber[order]; + long seedStart = recurrenceStart - order; + for (int i = 0; i < order; i++) { + long idxSeed = seedStart + i; + Object vObj = targetArray.get(idxSeed); + AutoStackingNumber v = typeSystem.toAutoStackingNumber(vObj); + if (v == null) { + return null; + } + seed[i] = v; + } + + return new PatternApplier.LinearRecurrencePattern( + leftAccess.array, + order, + coeffByLag, + constant[0], + recurrenceStart, + seedStart, + seed + ); + } + + private boolean collectLinearTerms( + Expr expr, + String targetArrayName, + String iterator, + AutoStackingNumber[] coeffByLag, + AutoStackingNumber[] constant, + AutoStackingNumber sign + ) { + if (expr == null) return false; + + if (expr instanceof BinaryOp) { + BinaryOp bin = (BinaryOp) expr; + if ("+".equals(bin.op)) { + return collectLinearTerms(bin.left, targetArrayName, iterator, coeffByLag, constant, sign) && + collectLinearTerms(bin.right, targetArrayName, iterator, coeffByLag, constant, sign); + } + if ("-".equals(bin.op)) { + return collectLinearTerms(bin.left, targetArrayName, iterator, coeffByLag, constant, sign) && + collectLinearTerms(bin.right, targetArrayName, iterator, coeffByLag, constant, sign.multiply(AutoStackingNumber.fromLong(-1L))); + } + if ("*".equals(bin.op)) { + TermRef ref = extractIndexedTargetTerm(bin.left, targetArrayName, iterator); + AutoStackingNumber scalar = toNumericLiteral(bin.right); + if (ref == null || scalar == null) { + ref = extractIndexedTargetTerm(bin.right, targetArrayName, iterator); + scalar = toNumericLiteral(bin.left); + } + if (ref != null && scalar != null) { + AutoStackingNumber c = sign.multiply(scalar); + coeffByLag[ref.lag] = coeffByLag[ref.lag].add(c); + return true; + } + return false; + } + return false; + } + + TermRef ref = extractIndexedTargetTerm(expr, targetArrayName, iterator); + if (ref != null) { + coeffByLag[ref.lag] = coeffByLag[ref.lag].add(sign); + return true; + } + + AutoStackingNumber literal = toNumericLiteral(expr); + if (literal != null) { + constant[0] = constant[0].add(sign.multiply(literal)); + return true; + } + + return false; + } + + private static class TermRef { + final int lag; + TermRef(int lag) { this.lag = lag; } + } + + private TermRef extractIndexedTargetTerm(Expr expr, String targetArrayName, String iterator) { + if (!(expr instanceof IndexAccess)) { + return null; + } + IndexAccess access = (IndexAccess) expr; + if (!(access.array instanceof Identifier)) { + return null; + } + String arrayName = ((Identifier) access.array).name; + if (!targetArrayName.equals(arrayName)) { + return null; + } + int lag = extractLag(access.index, iterator); + if (lag <= 0 || lag > MAX_SUPPORTED_LAG) { + return null; + } + return new TermRef(lag); + } + + private int extractLag(Expr indexExpr, String iterator) { + if (indexExpr instanceof BinaryOp) { + BinaryOp bin = (BinaryOp) indexExpr; + if ("-".equals(bin.op) && bin.left instanceof Identifier && + iterator.equals(((Identifier) bin.left).name)) { + AutoStackingNumber n = toNumericLiteral(bin.right); + if (n == null) return -1; + long lag = n.longValue(); + if (lag <= 0 || lag > Integer.MAX_VALUE) return -1; + return (int) lag; + } + } + return -1; + } + + private AutoStackingNumber toNumericLiteral(Expr expr) { + if (expr instanceof IntLiteral) { + return ((IntLiteral) expr).value; + } + if (expr instanceof FloatLiteral) { + return ((FloatLiteral) expr).value; + } + if (expr instanceof Unary) { + Unary unary = (Unary) expr; + if ("-".equals(unary.op)) { + AutoStackingNumber inner = toNumericLiteral(unary.operand); + if (inner == null) return null; + return AutoStackingNumber.fromLong(0L).subtract(inner); + } + if ("+".equals(unary.op)) { + return toNumericLiteral(unary.operand); + } + } + return null; + } + + private long[] resolveLoopBounds(For node) { + if (node == null) return null; + if (node.range != null) { + Object startObj = dispatcher.dispatch(node.range.start); + Object endObj = dispatcher.dispatch(node.range.end); + long start = expressionHandler.toLong(startObj); + long end = expressionHandler.toLong(endObj); + return new long[]{Math.min(start, end), Math.max(start, end)}; + } + if (node.arraySource != null) { + Object sourceObj = dispatcher.dispatch(node.arraySource); + sourceObj = typeSystem.unwrap(sourceObj); + if (sourceObj instanceof NaturalArray) { + NaturalArray sourceArr = (NaturalArray) sourceObj; + if (sourceArr.size() > 0) { + return new long[]{0L, sourceArr.size() - 1L}; + } + } else if (sourceObj instanceof List) { + List list = (List) sourceObj; + if (!list.isEmpty()) { + return new long[]{0L, list.size() - 1L}; + } + } + } + return null; + } + + public List extractMultiArraySequencePatterns(For node) { + List results = new ArrayList(); + if (node == null || node.body == null || node.body.statements == null) { + return results; + } + + List statements = node.body.statements; + if (statements.size() < 2) { + return results; + } + + List orderedTargets = new ArrayList(); + List orderedAssignments = new ArrayList(); + + for (Stmt stmt : statements) { + if (!(stmt instanceof Assignment)) { + return new ArrayList(); + } + + Assignment assign = (Assignment) stmt; + if (assign.isDeclaration || !(assign.left instanceof IndexAccess)) { + return new ArrayList(); + } + + IndexAccess indexAccess = (IndexAccess) assign.left; + if (!(indexAccess.array instanceof Identifier) || !(indexAccess.index instanceof Identifier)) { + return new ArrayList(); + } + + Identifier index = (Identifier) indexAccess.index; + if (!node.iterator.equals(index.name)) { + return new ArrayList(); + } + + String targetName = ((Identifier) indexAccess.array).name; + if (orderedTargets.contains(targetName)) { + return new ArrayList(); + } + + orderedTargets.add(targetName); + orderedAssignments.add(assign); + } + + for (int i = 0; i < orderedAssignments.size(); i++) { + Assignment assign = orderedAssignments.get(i); + IndexAccess indexAccess = (IndexAccess) assign.left; + Identifier targetArray = (Identifier) indexAccess.array; + + Set refs = new HashSet(); + collectIndexedArrayRefs(assign.right, node.iterator, refs); + + for (String ref : refs) { + int refIndex = orderedTargets.indexOf(ref); + if (refIndex == -1 || refIndex > i) { + return new ArrayList(); + } + } + + List steps = new ArrayList(); + steps.add(new SequencePattern.Step(null, assign.right)); + SequencePattern.Pattern pattern = new SequencePattern.Pattern(steps, targetArray, node.iterator); + results.add(new PatternApplier.PatternResult(PatternApplier.PatternType.SEQUENCE, pattern, targetArray)); + } + + return results; + } + + private void collectIndexedArrayRefs(Expr expr, String iterator, Set refs) { + if (expr == null || refs == null) { + return; + } + + if (expr instanceof IndexAccess) { + IndexAccess access = (IndexAccess) expr; + if (access.array instanceof Identifier && access.index instanceof Identifier) { + Identifier idx = (Identifier) access.index; + if (iterator.equals(idx.name)) { + refs.add(((Identifier) access.array).name); + } + } + collectIndexedArrayRefs(access.array, iterator, refs); + collectIndexedArrayRefs(access.index, iterator, refs); + return; + } + + if (expr instanceof BinaryOp) { + BinaryOp bin = (BinaryOp) expr; + collectIndexedArrayRefs(bin.left, iterator, refs); + collectIndexedArrayRefs(bin.right, iterator, refs); + return; + } + + if (expr instanceof Unary) { + collectIndexedArrayRefs(((Unary) expr).operand, iterator, refs); + return; + } + + if (expr instanceof MethodCall) { + MethodCall call = (MethodCall) expr; + if (call.arguments != null) { + for (Expr arg : call.arguments) { + collectIndexedArrayRefs(arg, iterator, refs); + } + } + return; + } + + if (expr instanceof TypeCast) { + collectIndexedArrayRefs(((TypeCast) expr).expression, iterator, refs); + return; + } + + if (expr instanceof PropertyAccess) { + PropertyAccess prop = (PropertyAccess) expr; + collectIndexedArrayRefs(prop.left, iterator, refs); + collectIndexedArrayRefs(prop.right, iterator, refs); + return; + } + + if (expr instanceof Tuple) { + Tuple tuple = (Tuple) expr; + if (tuple.elements != null) { + for (Expr elem : tuple.elements) { + collectIndexedArrayRefs(elem, iterator, refs); + } + } + return; + } + + if (expr instanceof Array) { + Array array = (Array) expr; + if (array.elements != null) { + for (Expr elem : array.elements) { + collectIndexedArrayRefs(elem, iterator, refs); + } + } + } + } + + public Object executeOutputAwareLoop(For node, OutputAwarePattern.OutputPattern pattern) { + ExecutionContext ctx = dispatcher.getCurrentContext(); + + try { + NaturalArray arr = createArrayFromOutputPattern(node, pattern.computation, ctx); + + ctx.enterOptimizedLoop(); + + if (node.range != null) { + executeOutputRangeLoop(ctx, node, arr, pattern.outputCalls); + } else if (node.arraySource != null) { + executeOutputArrayLoop(ctx, node, arr, pattern.outputCalls); + } + return arr; + } finally { + ctx.exitOptimizedLoop(); + } + } + + public NaturalArray createArrayFromOutputPattern(For node, Object computation, ExecutionContext ctx) { + if (computation instanceof SequencePattern.Pattern) { + SequencePattern.Pattern seqPattern = (SequencePattern.Pattern) computation; + + Range range = node.range; + if (range == null && node.arraySource != null) { + Object sourceObj = dispatcher.dispatch(node.arraySource); + sourceObj = typeSystem.unwrap(sourceObj); + + if (sourceObj instanceof NaturalArray) { + NaturalArray sourceArr = (NaturalArray) sourceObj; + long size = sourceArr.size(); + + Expr start = ASTFactory.createIntLiteral(0, null); + Expr end = ASTFactory.createIntLiteral((int)(size - 1), null); + range = ASTFactory.createRange(null, start, end, null, null); + } + } + + if (range == null) { + throw new ProgramError("Cannot create array from pattern: no range specified"); + } + + NaturalArray arr = new NaturalArray(range, dispatcher, ctx); + + if (seqPattern.isSimple()) { + SequenceFormula formula = SequenceFormula.createSimple( + 0, arr.size() - 1, + seqPattern.getFinalExpression(), + node.iterator + ); + arr.addSequenceFormula(formula); + } else { + SequenceFormula formula = SequenceFormula.createFromSequence( + 0, arr.size() - 1, node.iterator, + seqPattern.getTempVarNames(), + seqPattern.getTempExpressions(), + seqPattern.getFinalExpression() + ); + arr.addSequenceFormula(formula); + } + + return arr; + + } else if (computation instanceof ConditionalPattern) { + ConditionalPattern condPattern = (ConditionalPattern) computation; + + Range range = node.range; + if (range == null && node.arraySource != null) { + Object sourceObj = dispatcher.dispatch(node.arraySource); + sourceObj = typeSystem.unwrap(sourceObj); + + if (sourceObj instanceof NaturalArray) { + NaturalArray sourceArr = (NaturalArray) sourceObj; + long size = sourceArr.size(); + + Expr start = ASTFactory.createIntLiteral(0, null); + Expr end = ASTFactory.createIntLiteral((int)(size - 1), null); + range = ASTFactory.createRange(null, start, end, null, null); + } + } + + if (range == null) { + throw new ProgramError("Cannot create array from pattern: no range specified"); + } + + NaturalArray arr = new NaturalArray(range, dispatcher, ctx); + + List conditions = new ArrayList(); + List> branchStatements = new ArrayList>(); + + for (ConditionalPattern.Branch branch : condPattern.branches) { + conditions.add(branch.condition); + branchStatements.add(branch.statements); + } + + ConditionalFormula formula = new ConditionalFormula( + 0, arr.size() - 1, node.iterator, + conditions, + branchStatements, + condPattern.elseStatements + ); + arr.addConditionalFormula(formula); + + return arr; + } + + throw new ProgramError("Unknown computation pattern type"); + } + + public void executeOutputRangeLoop(ExecutionContext ctx, For node, + NaturalArray arr, List outputCalls) { + try { + Object startObj = dispatcher.dispatch(node.range.start); + Object endObj = dispatcher.dispatch(node.range.end); + startObj = typeSystem.unwrap(startObj); + endObj = typeSystem.unwrap(endObj); + + long start = expressionHandler.toLong(startObj); + long end = expressionHandler.toLong(endObj); + long step = arrayOperationHandler.calculateRangeStep(node.range); + + for (long i = start; i <= end; i += step) { + Object value = arr.get(i); + + arr.recordOutput(i, value); + + ctx.setVariable(node.iterator, value); + + for (MethodCall outputCall : outputCalls) { + MethodCall evalCall = new MethodCall(); + evalCall.name = outputCall.name; + evalCall.arguments = new ArrayList(); + + for (Expr arg : outputCall.arguments) { + if (arg instanceof Identifier && + "_".equals(((Identifier) arg).name)) { + evalCall.arguments.add(new ValueExpr(value)); + } else { + evalCall.arguments.add(arg); + } + } + + dispatcher.dispatch(evalCall); + } + } + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Output range loop execution failed", e); + } + } + + public void executeOutputArrayLoop(ExecutionContext ctx, For node, + NaturalArray arr, List outputCalls) { + try { + Object sourceObj = dispatcher.dispatch(node.arraySource); + sourceObj = typeSystem.unwrap(sourceObj); + + long size = 0; + if (sourceObj instanceof NaturalArray) { + size = ((NaturalArray) sourceObj).size(); + } else if (sourceObj instanceof List) { + size = ((List) sourceObj).size(); + } else { + throw new ProgramError("Cannot iterate over: " + + (sourceObj != null ? sourceObj.getClass().getSimpleName() : "null")); + } + + for (long i = 0; i < size; i++) { + Object value = arr.get(i); + + arr.recordOutput(i, value); + + ctx.setVariable(node.iterator, value); + + for (MethodCall outputCall : outputCalls) { + MethodCall evalCall = new MethodCall(); + evalCall.name = outputCall.name; + evalCall.arguments = new ArrayList(); + + for (Expr arg : outputCall.arguments) { + if (arg instanceof Identifier && + "_".equals(((Identifier) arg).name)) { + evalCall.arguments.add(new ValueExpr(value)); + } else { + evalCall.arguments.add(arg); + } + } + + dispatcher.dispatch(evalCall); + } + } + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Output array loop execution failed", e); + } + } + + public List extractConditionalPatterns(StmtIf ifStmt, String iterator) { + try { + return ConditionalPattern.extractAll(ifStmt, iterator); + } catch (Exception e) { + DebugSystem.debug("OPTIMIZER", "Failed to extract conditional pattern: " + e.getMessage()); + return new ArrayList(); + } + } +} diff --git a/src/main/java/cod/interpreter/handler/PatternApplier.java b/src/main/java/cod/interpreter/handler/PatternApplier.java new file mode 100644 index 00000000..23f24bc5 --- /dev/null +++ b/src/main/java/cod/interpreter/handler/PatternApplier.java @@ -0,0 +1,288 @@ +package cod.interpreter.handler; + +import cod.ast.node.*; +import cod.debug.DebugSystem; +import cod.error.InternalError; +import cod.error.ProgramError; +import cod.interpreter.InterpreterVisitor; +import cod.math.AutoStackingNumber; +import cod.range.NaturalArray; +import cod.range.formula.ConditionalFormula; +import cod.range.formula.LinearRecurrenceFormula; +import cod.range.formula.SequenceFormula; +import cod.range.pattern.ConditionalPattern; +import cod.range.pattern.SequencePattern; + +import java.util.*; + +public class PatternApplier { + public enum PatternType { + CONDITIONAL, + SEQUENCE, + LINEAR_RECURRENCE + } + + public static class PatternResult { + public final PatternType type; + public final Object pattern; + public final Expr targetArray; + + public PatternResult(PatternType type, Object pattern, Expr targetArray) { + if (type == null) { + throw new InternalError("PatternResult constructed with null type"); + } + this.type = type; + this.pattern = pattern; + this.targetArray = targetArray; + } + } + + public static class LinearRecurrencePattern { + public final Expr targetArray; + public final int order; + public final AutoStackingNumber[] coefficientsByLag; + public final AutoStackingNumber constantTerm; + public final long recurrenceStart; + public final long seedStart; + public final AutoStackingNumber[] seedValues; + + public LinearRecurrencePattern( + Expr targetArray, + int order, + AutoStackingNumber[] coefficientsByLag, + AutoStackingNumber constantTerm, + long recurrenceStart, + long seedStart, + AutoStackingNumber[] seedValues + ) { + this.targetArray = targetArray; + this.order = order; + this.coefficientsByLag = coefficientsByLag; + this.constantTerm = constantTerm; + this.recurrenceStart = recurrenceStart; + this.seedStart = seedStart; + this.seedValues = seedValues; + } + } + + private final InterpreterVisitor dispatcher; + private final TypeHandler typeSystem; + private final ExpressionHandler expressionHandler; + private final ArrayOperationHandler arrayOperationHandler; + + public PatternApplier( + InterpreterVisitor dispatcher, + TypeHandler typeSystem, + ExpressionHandler expressionHandler, + ArrayOperationHandler arrayOperationHandler + ) { + if (dispatcher == null) throw new InternalError("PatternApplier dispatcher is null"); + if (typeSystem == null) throw new InternalError("PatternApplier typeSystem is null"); + if (expressionHandler == null) throw new InternalError("PatternApplier expressionHandler is null"); + if (arrayOperationHandler == null) throw new InternalError("PatternApplier arrayOperationHandler is null"); + this.dispatcher = dispatcher; + this.typeSystem = typeSystem; + this.expressionHandler = expressionHandler; + this.arrayOperationHandler = arrayOperationHandler; + } + + public Object applyPatterns(For node, List patterns) { + if (node == null) { + throw new InternalError("applyPatterns called with null node"); + } + if (patterns == null) { + throw new InternalError("applyPatterns called with null patterns"); + } + + try { + List targetArrays = new ArrayList(); + List> groupedPatterns = new ArrayList>(); + Map arrayIdToGroupIndex = new HashMap(); + + for (PatternResult result : patterns) { + if (result == null || result.targetArray == null) { + continue; + } + + Object resolvedArray = dispatcher.dispatch(result.targetArray); + resolvedArray = typeSystem.unwrap(resolvedArray); + + if (!(resolvedArray instanceof NaturalArray)) { + DebugSystem.debug("OPTIMIZER", "Array not optimizable, falling back to normal execution"); + return arrayOperationHandler.executeForLoopNormally(node); + } + + NaturalArray naturalArray = (NaturalArray) resolvedArray; + int arrayId = naturalArray.getArrayId(); + Integer existingGroup = arrayIdToGroupIndex.get(arrayId); + int groupIndex = existingGroup != null ? existingGroup.intValue() : -1; + + if (groupIndex == -1) { + targetArrays.add(naturalArray); + List newGroup = new ArrayList(); + newGroup.add(result); + groupedPatterns.add(newGroup); + arrayIdToGroupIndex.put(arrayId, targetArrays.size() - 1); + } else { + groupedPatterns.get(groupIndex).add(result); + } + } + + if (targetArrays.isEmpty()) { + DebugSystem.debug("OPTIMIZER", "No target arrays found, falling back to normal execution"); + return arrayOperationHandler.executeForLoopNormally(node); + } + + long start = 0, end = 0; + boolean boundsFound = false; + + if (node.range != null) { + Object startObj = dispatcher.dispatch(node.range.start); + Object endObj = dispatcher.dispatch(node.range.end); + start = expressionHandler.toLong(startObj); + end = expressionHandler.toLong(endObj); + boundsFound = true; + } else if (node.arraySource != null) { + Object sourceObj = dispatcher.dispatch(node.arraySource); + if (sourceObj instanceof NaturalArray) { + NaturalArray sourceArr = (NaturalArray) sourceObj; + if (sourceArr.size() > 0) { + start = 0; + end = sourceArr.size() - 1; + boundsFound = true; + } + } + } + + if (!boundsFound) { + DebugSystem.debug("OPTIMIZER", "Could not determine bounds, falling back to normal execution"); + return arrayOperationHandler.executeForLoopNormally(node); + } + + long min = Math.min(start, end); + long max = Math.max(start, end); + + for (int arrayIndex = 0; arrayIndex < targetArrays.size(); arrayIndex++) { + NaturalArray arr = targetArrays.get(arrayIndex); + List arrayPatterns = groupedPatterns.get(arrayIndex); + + for (PatternResult result : arrayPatterns) { + if (result.type == PatternType.SEQUENCE) { + applySequencePattern(arr, (SequencePattern.Pattern) result.pattern, min, max, node.iterator); + } else if (result.type == PatternType.CONDITIONAL) { + applyConditionalPattern(arr, (ConditionalPattern) result.pattern, min, max, node.iterator); + } else if (result.type == PatternType.LINEAR_RECURRENCE) { + applyLinearRecurrencePattern(arr, (LinearRecurrencePattern) result.pattern, min, max, node.iterator); + } + } + } + + return targetArrays.get(targetArrays.size() - 1); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Pattern application failed, falling back to normal execution", e); + } + } + + public void applyConditionalPattern(NaturalArray arr, ConditionalPattern pattern, + long min, long max, String iterator) { + if (pattern == null) { + throw new InternalError("applyConditionalPattern called with null pattern"); + } + if (arr == null) { + throw new InternalError("applyConditionalPattern called with null array"); + } + + try { + List conditions = new ArrayList(); + List> branchStatements = new ArrayList>(); + + for (ConditionalPattern.Branch branch : pattern.branches) { + conditions.add(branch.condition); + branchStatements.add(branch.statements); + } + + ConditionalFormula formula = new ConditionalFormula( + min, max, iterator, + conditions, + branchStatements, + pattern.elseStatements + ); + arr.addConditionalFormula(formula); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Failed to apply conditional pattern", e); + } + } + + public void applySequencePattern(NaturalArray arr, + SequencePattern.Pattern pattern, + long min, long max, String iterator) { + if (pattern == null) { + throw new InternalError("applySequencePattern called with null pattern"); + } + if (arr == null) { + throw new InternalError("applySequencePattern called with null array"); + } + + try { + SequenceFormula formula; + + if (pattern.isSimple()) { + formula = SequenceFormula.createSimple(min, max, pattern.getFinalExpression(), iterator); + } else { + formula = SequenceFormula.createFromSequence( + min, max, iterator, + pattern.getTempVarNames(), + pattern.getTempExpressions(), + pattern.getFinalExpression() + ); + } + + arr.addSequenceFormula(formula); + + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Failed to apply sequence pattern", e); + } + } + + public void applyLinearRecurrencePattern( + NaturalArray arr, + LinearRecurrencePattern pattern, + long min, + long max, + String iterator + ) { + if (arr == null) { + throw new InternalError("applyLinearRecurrencePattern called with null array"); + } + if (pattern == null) { + throw new InternalError("applyLinearRecurrencePattern called with null pattern"); + } + try { + long start = Math.max(min, pattern.seedStart); + long end = max; + if (end < start) { + return; + } + LinearRecurrenceFormula formula = new LinearRecurrenceFormula( + start, + end, + pattern.recurrenceStart, + pattern.coefficientsByLag, + pattern.constantTerm, + pattern.seedValues, + pattern.seedStart + ); + arr.addLinearRecurrenceFormula(formula); + } catch (ProgramError e) { + throw e; + } catch (Exception e) { + throw new InternalError("Failed to apply linear recurrence pattern", e); + } + } +} From 9adae4b3155f931184198c50a1bb1f603ef61c78 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 23:04:45 +0000 Subject: [PATCH 3/9] Fix handler integration and compile after refactor Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/047028e4-d3b7-4a83-9cf4-14625a476131 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- source_.jar | Bin 344170 -> 359462 bytes .../cod/interpreter/InterpreterVisitor.java | 4 ++++ .../handler/ArrayOperationHandler.java | 3 +-- .../interpreter/handler/ContextHelper.java | 2 +- .../interpreter/handler/LoopOptimizer.java | 4 +--- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source_.jar b/source_.jar index a28d6f110f627a5dfa440a56f5834f17ade803a6..fc8e95b01bb279dec2b1e6d3048d7ac51d5b0fb8 100644 GIT binary patch delta 39378 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�RFs_}T?` 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 Wz-WI}=SJa1iE#n|!tuZl*8c%j4!mCg delta 24455 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 VNP_(u@iiioGXlb!CBWZ{{|~Wl3ikj2 diff --git a/src/main/java/cod/interpreter/InterpreterVisitor.java b/src/main/java/cod/interpreter/InterpreterVisitor.java index e4fdbebf..5bdb5715 100644 --- a/src/main/java/cod/interpreter/InterpreterVisitor.java +++ b/src/main/java/cod/interpreter/InterpreterVisitor.java @@ -194,6 +194,10 @@ public boolean isContextStackEmpty() { return contextStack.isEmpty(); } + public boolean shouldReturnEarly(Map slotValues, Set slotsInCurrentPath) { + return interpreter.shouldReturnEarly(slotValues, slotsInCurrentPath); + } + private Object createNoneValue() { return contextHelper.createNoneValue(); } diff --git a/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java b/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java index 6fe0fc33..78d28e27 100644 --- a/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java +++ b/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java @@ -9,7 +9,6 @@ import cod.interpreter.exception.SkipIterationException; import cod.math.AutoStackingNumber; import cod.range.NaturalArray; -import cod.range.Range; import cod.range.RangeObjects; import java.util.ArrayList; @@ -234,7 +233,7 @@ public void executeLoopBody(cod.interpreter.context.ExecutionContext ctx, For no } if (!ctx.slotsInCurrentPath.isEmpty() - && interpreter.shouldReturnEarly(ctx.getSlotValues(), ctx.slotsInCurrentPath)) return; + && dispatcher.shouldReturnEarly(ctx.getSlotValues(), ctx.slotsInCurrentPath)) return; } } catch (BreakLoopException e) { throw e; diff --git a/src/main/java/cod/interpreter/handler/ContextHelper.java b/src/main/java/cod/interpreter/handler/ContextHelper.java index 40177fb7..387e1453 100644 --- a/src/main/java/cod/interpreter/handler/ContextHelper.java +++ b/src/main/java/cod/interpreter/handler/ContextHelper.java @@ -7,7 +7,7 @@ import cod.interpreter.Interpreter; import cod.interpreter.context.ExecutionContext; import cod.range.NaturalArray; -import cod.range.Range; +import cod.ast.node.Range; import java.util.List; import java.util.Map; diff --git a/src/main/java/cod/interpreter/handler/LoopOptimizer.java b/src/main/java/cod/interpreter/handler/LoopOptimizer.java index f41ebe1c..14ef0552 100644 --- a/src/main/java/cod/interpreter/handler/LoopOptimizer.java +++ b/src/main/java/cod/interpreter/handler/LoopOptimizer.java @@ -8,11 +8,9 @@ import cod.interpreter.InterpreterVisitor; import cod.interpreter.TailCallSignal; import cod.interpreter.context.ExecutionContext; -import cod.interpreter.exception.BreakLoopException; import cod.math.AutoStackingNumber; +import cod.range.ArrayTracker; import cod.range.NaturalArray; -import cod.range.Range; -import cod.range.pattern.ArrayTracker; import cod.range.pattern.ConditionalPattern; import cod.range.pattern.OutputAwarePattern; import cod.range.pattern.SequencePattern; From a8b84699770351d1cf4d6dc97a294a7143d0d762 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 10 Apr 2026 23:08:59 +0000 Subject: [PATCH 4/9] Plan handler renames requested Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/8959a632-fdda-4ee2-aeef-8fde6373ac04 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- source_.jar | Bin 359462 -> 359462 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/source_.jar b/source_.jar index fc8e95b01bb279dec2b1e6d3048d7ac51d5b0fb8..789676cba0c8b247f74db8a6e1b3e955fd2e9f1f 100644 GIT binary patch delta 5967 zcmZWtcR-a_mVe)O-=&4F^o|H9c0{mIEPymYK%__&r75DIphU1tjK+yFFLE^+ESVU~ znvh}iOQOOUjT$AQ*+i3AB2J8=(O?wUnC!auob%k-b^qb_opMjT_uTu~^VDI_QwPiB zc&4||>CDV@&Yv_{2B`9HNId*q<*QnK(zGW4{&oe)zlIO{+zi)LbAz{H3FI(kG(eOZ zXxO0G!e@)Ji#TBt#Kkqt&9JH3%3vF6ZumE~zvQ)jri!7Ul06~<$n7KIOn{8550qMN zz#1BQ$`M#Q_5;gYyxE_d8ipo;$F}iF4Ap&_L8doUq~VfvX(`sQ04 zV}a{d7B1mMG)|(+iJMw8-M{jdI=jnSKy^}i0vOm-?x6sFSW$%7e?b&tM&(?@j)mTU zhVH7F0Am+@53s#ul(^x>Enl+TRQUz{=V^0E6n*0qod6%J5U2J$yc^L&5H4(UNMryDS$C#MMs*a$~)fD)EI!C&Psm z{b13p6~BY{X2V3#Zu40=9x-=SJ>u2X7KnG&%my_0G>;NH{kZwd32l09qYcSp0Lq#l z0py7&YpYMz=ZMIFhqrV(-4n&|@N7Sk?9bf|*TgSIgMZoT0AEg9@1pX0ubp=uO65w` z(0bDUFI&yq!r$(PL8NXQ1o-ZX?MODh_D=!f zt^FO4zM<#nC^2{lw|F`J-h-1~$PKNn7KVkbxSdzDK897*AEkhi(;t0;j#stqLdPRc zk1{muvoIVxWdD*q!^%U~U}65@X|V9X;Y?g;@^J`wX`A?IJQ`Sk1bfqU#2Lw+qp=_j zKGw-$v2r2}AmhXz0O=5;mb?5hO$mPWwo7QSlk`^y~K?$ z?qaxm3HeViea67d(eIKmLz3Ymps;gG?)pQ8u87|4390K#JO5QL*$&r2p&;qjH8KP)E&Hrd!}HZhAlKEfZCz`@uxyuU34t#$v?}GSl|VQ+~t% zHdH7$)wHzLN~sx$I^Ix{VW?_$nsN;}y&cNKSHR~#&ndwmaqd(mS;0rncgi)WkT(8` zvJUN?`ax;HTw{8aqqv&?Di?vyxW|eQ)Cbz?CnCdC)6K7|z&O;b){(~{>KSx&B~*ne zthtA&#kh9$ICTKp-y5!0qgl@w^+(KBAFr0fFWJN)kNlu zzO>3p^(wARtW{m1sIrlM!Zv}MymV}|T`Sasm|pS*)dq`Q(4<1owXIF6IYSq}e;0bb zQO<|GI*~F=x>(SxnuzmnsW2SHyv=GiU|h3$4$w)cA+S72s9UjIJzLaS@F6C@t-^>F zUfa}XfNtB>H$Zdmc6B2vjBQajgFv<$?hNgf9jYs&Edq9{?ZCLbTg|}|O?^+jgdZMz z)eHFX%YHRV#c0o)JCDBy(JCS@N=6&8U9}XirgAG$c~I>GGjl&s_h4w&t!fYSK>O{8 zIuy)^z;^WrFmAQ0`_XRGarH6uSgbuqd9|NY_jpPMR$QR_=WlBXB$m!jJR`Mo#fW)*p>74`4l0;r)T0}yXq_;TrGbRTaFg5O=fne-#dlD~VxK zQ00SIhL@Fgb{cz4!3;)EzVeSFGJ{Bw^tS4PCPhO$yNE)Ywm*C?Nnx`XnJLq2NMH{! zkZsHFpPncK`G7%te6$^jYz8%V=jd-AeFFti#Ko!1M|e-CidZDG|Ad&#Q!V7_Vhpz8;qe{p2P4^oiAqi9uvKD*%Jum&OGYvHzh0ujRcml zZv1$qLfXeDFHJv}?j(!rp^A}Nvbd4+$-J1qfL(^-L|3v-8bXC<%dc0M>vTVcz!37% zA{Mh%=4d3drzqu?G~#Fi9dg(1)wAaq8qQwZ1_sYAZD0e#VWLH?V)&30YgV%fSj&?S zzU};6R-+1P=^_@s!z@KWCAV%~gIgP3a8tpA^PkvNoW4&4OM}y=CA`Bf!*r039ybyB zK7;E`D}SF^;8a=qH->krHu>)i->}-=LkvgV3w;OSy@Z>+Jd+zVwg^x8qfglnc<#SG z!Tj(HKl_T!w8E@At78+tcF^haSBsSQ==_3Pm2to5$be`yCF9ozJ4edULUZP!NwZfe)x2CVDQcLV19Lw^%c zRyI_kR(D+gn`*Y!1c%e36nUxDX{w)~O) zL!50xp6N^QozSf3zgx(kJR;ndyNZK0+zp7cHars0(w4)61cV`gHMSh?2+?ZG@rOmP zEuRE*mmPN($##4&5cPH(o{_-Bbhi0OVX!@i*hPgsUk=z~&*7aX!uoM|(us@SQmM5c zxw+ks&jn`pV96}+&*5ei@Al_8fQkc82b|@=ivW)q(bthT0R2m(T-4#ngMfHAK@w(8 zlm!Md(}@Dv=)`A(#sen`AkLZ31G>$bmjZga5Uz9KWkC12@Djj0S3U>ub60W~?Z#&T zz0-}>qmzN|3{?LsRg*Q*`Jgy`coLO0en6vX#rFa??B>jN5 z9S2dt77il$cY}B(@Z$#a&44oZ8Gs={l=k!?GQ1ChI6ULU-5`oxGT{)3_lFQ|Ig}!t zKa{Tk{{5kR6=2mc>e`iId@ay(hEw5>4X2<+kKk2kX9NX-+i>(q+J@yLIsEt#7{Sev z6oKa`^0;~wRrU5L>c*U43io(0r9WacrMGo7Uu=xTT?`K42|(0_@M^#ZAv_5%d<<j80{R>u@qzZ zSP~vHBDx70M{ZKb@i@HdYqdG~mVefR__gq#8HV(kR(3rZ<7 zC2@KJ4+KIUI?OU+BF_hU*F-9rNjPD7I3@C#5nUpP#>2WHf(~nY1a&Sjk{10rl8njY z9Ro(gqNv`Rqi8HVGSbPDNdM3z+7XVENpJCFs$!QBgQgJw^(j0G?46rJ1IcwNwWMq+ z?e!y5DLDIRTE8Hgppd?a|76HDjugb{tG@m%1q znnscSa~eey8Asc0TO1jAXhf`WQ9RZ7&+!!A^>|W3VR8ZqmnBduyAo(Z_$Jb6S(Zq- zTukJX!LwtM@hB#d{7e$9^O#PjWXW_g-f5%3Snj|u4FW<``dDJX&vSk+O{W^=}(U~O2gYj`D9gG{9RK4IVLd<%1 z7G>R)MJoqnlW>U3>&1{GdW=U1K3-{(T{>A67*2#vqssp>k492z3Gok< zkRP*B>gb$OisMiz#cy3k_Dae~ezJ`GIF*zA(sHtMyqwnASCG88g5;W!wwO=++4Ct6 zd2HczDV`en@e4@*odq=QdKQphyw39~={nz1Ni$tpNLaS;f4x&4ETp09Uq!-=RdfLQ zs^~h-Swx+|34M7HDcdY2rJBX0bagSWfUx4KiQj5O#~LbkZ4FJun>AF%=p{tAE}?6? z-%@H<=~60}d^5OnKdiWn`()h#xPbdFQyC N8dGV+Gs}7Ie*;I(w=)0$ delta 5967 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 Date: Fri, 10 Apr 2026 23:09:21 +0000 Subject: [PATCH 5/9] Rename extracted handler classes and references Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/8959a632-fdda-4ee2-aeef-8fde6373ac04 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- .../cod/interpreter/InterpreterVisitor.java | 44 ++++++------- .../handler/ArrayOperationHandler.java | 12 ++-- ...ContextHelper.java => ContextHandler.java} | 6 +- ...nvoker.java => LambdaInvokingHandler.java} | 8 +-- ...izer.java => LoopOptimizationHandler.java} | 66 +++++++++---------- ...atternApplier.java => PattrrnHandler.java} | 12 ++-- 6 files changed, 74 insertions(+), 74 deletions(-) rename src/main/java/cod/interpreter/handler/{ContextHelper.java => ContextHandler.java} (94%) rename src/main/java/cod/interpreter/handler/{LambdaInvoker.java => LambdaInvokingHandler.java} (98%) rename src/main/java/cod/interpreter/handler/{LoopOptimizer.java => LoopOptimizationHandler.java} (92%) rename src/main/java/cod/interpreter/handler/{PatternApplier.java => PattrrnHandler.java} (96%) diff --git a/src/main/java/cod/interpreter/InterpreterVisitor.java b/src/main/java/cod/interpreter/InterpreterVisitor.java index 5bdb5715..0379ff8e 100644 --- a/src/main/java/cod/interpreter/InterpreterVisitor.java +++ b/src/main/java/cod/interpreter/InterpreterVisitor.java @@ -83,11 +83,11 @@ private static class LinearRecurrencePattern { private final ExpressionHandler expressionHandler; private final AssignmentHandler assignmentHandler; private final LiteralRegistry literalRegistry; - private final ContextHelper contextHelper; - private final LambdaInvoker lambdaInvoker; + private final ContextHandler contextHandler; + private final LambdaInvokingHandler lambdaInvokingHandler; private final ArrayOperationHandler arrayOperationHandler; - private final PatternApplier patternApplier; - private final LoopOptimizer loopOptimizer; + private final PattrrnHandler pattrrnHandler; + private final LoopOptimizationHandler loopOptimizationHandler; // ========== SIMPLE LOOP OPTIMIZATION CONSTANTS ========== private static final int LAZY_THRESHOLD = 10; // From your data: 10+ iterations = worth it @@ -108,16 +108,16 @@ public InterpreterVisitor(Interpreter interpreter, TypeHandler typeSystem, this.interpreter = interpreter; this.typeSystem = typeSystem; this.literalRegistry = literalRegistry; - this.contextHelper = new ContextHelper(interpreter); + this.contextHandler = new ContextHandler(interpreter); this.expressionHandler = new ExpressionHandler(typeSystem, this); this.assignmentHandler = new AssignmentHandler(typeSystem, interpreter, expressionHandler, this); this.arrayOperationHandler = - new ArrayOperationHandler(this, interpreter, typeSystem, expressionHandler, contextHelper); - this.patternApplier = - new PatternApplier(this, typeSystem, expressionHandler, arrayOperationHandler); - this.loopOptimizer = - new LoopOptimizer(this, typeSystem, expressionHandler, arrayOperationHandler, patternApplier); - this.lambdaInvoker = new LambdaInvoker(typeSystem, this); + new ArrayOperationHandler(this, interpreter, typeSystem, expressionHandler, contextHandler); + this.pattrrnHandler = + new PattrrnHandler(this, typeSystem, expressionHandler, arrayOperationHandler); + this.loopOptimizationHandler = + new LoopOptimizationHandler(this, typeSystem, expressionHandler, arrayOperationHandler, pattrrnHandler); + this.lambdaInvokingHandler = new LambdaInvokingHandler(typeSystem, this); } // Implement Evaluator interface @@ -160,7 +160,7 @@ public Object invokeLambda(Object callback, List arguments, ExecutionCon if (ctx == null) { throw new InternalError("invokeLambda called with null context"); } - return lambdaInvoker.invokeLambdaCallback(callback, arguments, ctx, ownerMethod); + return lambdaInvokingHandler.invokeLambdaCallback(callback, arguments, ctx, ownerMethod); } public void pushContext(ExecutionContext context) { @@ -199,7 +199,7 @@ public boolean shouldReturnEarly(Map slotValues, Set slo } private Object createNoneValue() { - return contextHelper.createNoneValue(); + return contextHandler.createNoneValue(); } @Override @@ -343,7 +343,7 @@ public Object visit(Var node) { if (node.value == null) { throw new ProgramError("Constant '" + node.name + "' must have an initial value"); } - if (contextHelper.isVariableDeclaredInAnyScope(ctx, node.name)) { + if (contextHandler.isVariableDeclaredInAnyScope(ctx, node.name)) { throw new ProgramError("Cannot reassign constant '" + node.name + "'"); } } @@ -361,7 +361,7 @@ public Object visit(Var node) { // If expected is [text] but actual is not text, create a converting wrapper if (expectedElementType.equals("text") && !actualElementType.equals("text")) { // Create a new NaturalArray with conversion enabled - Range range = contextHelper.getRangeFromArray(arr); + Range range = contextHandler.getRangeFromArray(arr); if (range != null) { val = new NaturalArray(range, this, ctx, node.explicitType); } @@ -421,19 +421,19 @@ public Object visit(Var node) { // Helper method to extract Range from NaturalArray private Range getRangeFromArray(NaturalArray arr) { - return contextHelper.getRangeFromArray(arr); + return contextHandler.getRangeFromArray(arr); } private Type resolveInternalRangeSpecType() { - return contextHelper.resolveInternalRangeSpecType(); + return contextHandler.resolveInternalRangeSpecType(); } private Type resolveInternalMultiRangeSpecType() { - return contextHelper.resolveInternalMultiRangeSpecType(); + return contextHandler.resolveInternalMultiRangeSpecType(); } private boolean isVariableDeclaredInAnyScope(ExecutionContext ctx, String name) { - return contextHelper.isVariableDeclaredInAnyScope(ctx, name); + return contextHandler.isVariableDeclaredInAnyScope(ctx, name); } @Override @@ -500,7 +500,7 @@ public Object visit(ExprIf node) { // ========== UPDATED FOR NODE WITH SIMPLE LOOP DECISION ========== @Override public Object visit(For node) { - return loopOptimizer.executeForLoop(node); + return loopOptimizationHandler.executeForLoop(node); } // ========== SIMPLE LOOP DECISION METHODS ========== @@ -2351,7 +2351,7 @@ public Object visit(Slot n) { @Override public Object visit(Lambda node) { - return lambdaInvoker.createLambdaClosure(node, getCurrentContext()); + return lambdaInvokingHandler.createLambdaClosure(node, getCurrentContext()); } private Object invokeLambdaCallback( @@ -2359,7 +2359,7 @@ private Object invokeLambdaCallback( List args, ExecutionContext parentCtx, String ownerMethod) { - return lambdaInvoker.invokeLambdaCallback(callbackObj, args, parentCtx, ownerMethod); + return lambdaInvokingHandler.invokeLambdaCallback(callbackObj, args, parentCtx, ownerMethod); } private List resolveLambdaParameters(Lambda lambda) { diff --git a/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java b/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java index 78d28e27..f3422763 100644 --- a/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java +++ b/src/main/java/cod/interpreter/handler/ArrayOperationHandler.java @@ -19,24 +19,24 @@ public class ArrayOperationHandler { private final Interpreter interpreter; private final TypeHandler typeSystem; private final ExpressionHandler expressionHandler; - private final ContextHelper contextHelper; + private final ContextHandler contextHandler; public ArrayOperationHandler( InterpreterVisitor dispatcher, Interpreter interpreter, TypeHandler typeSystem, ExpressionHandler expressionHandler, - ContextHelper contextHelper) { + ContextHandler contextHandler) { if (dispatcher == null) throw new InternalError("ArrayOperationHandler dispatcher is null"); if (interpreter == null) throw new InternalError("ArrayOperationHandler interpreter is null"); if (typeSystem == null) throw new InternalError("ArrayOperationHandler typeSystem is null"); if (expressionHandler == null) throw new InternalError("ArrayOperationHandler expressionHandler is null"); - if (contextHelper == null) throw new InternalError("ArrayOperationHandler contextHelper is null"); + if (contextHandler == null) throw new InternalError("ArrayOperationHandler contextHandler is null"); this.dispatcher = dispatcher; this.interpreter = interpreter; this.typeSystem = typeSystem; this.expressionHandler = expressionHandler; - this.contextHelper = contextHelper; + this.contextHandler = contextHandler; } public Object executeForLoopNormally(For node) { @@ -339,7 +339,7 @@ public Object visitRangeIndex(RangeIndex node) { Object start = dispatcher.dispatch(node.start); Object end = dispatcher.dispatch(node.end); - return RangeObjects.createRangeSpec(contextHelper.resolveInternalRangeSpecType(), step, start, end); + return RangeObjects.createRangeSpec(contextHandler.resolveInternalRangeSpecType(), step, start, end); } catch (ProgramError e) { throw e; } catch (Exception e) { @@ -361,7 +361,7 @@ public Object visitMultiRangeIndex(MultiRangeIndex node) { } ranges.add(range); } - return RangeObjects.createMultiRangeSpec(contextHelper.resolveInternalMultiRangeSpecType(), ranges); + return RangeObjects.createMultiRangeSpec(contextHandler.resolveInternalMultiRangeSpecType(), ranges); } catch (ProgramError e) { throw e; } catch (Exception e) { diff --git a/src/main/java/cod/interpreter/handler/ContextHelper.java b/src/main/java/cod/interpreter/handler/ContextHandler.java similarity index 94% rename from src/main/java/cod/interpreter/handler/ContextHelper.java rename to src/main/java/cod/interpreter/handler/ContextHandler.java index 387e1453..6b26f96d 100644 --- a/src/main/java/cod/interpreter/handler/ContextHelper.java +++ b/src/main/java/cod/interpreter/handler/ContextHandler.java @@ -12,14 +12,14 @@ import java.util.List; import java.util.Map; -public class ContextHelper { +public class ContextHandler { private final Interpreter interpreter; private Type internalRangeSpecType; private Type internalMultiRangeSpecType; - public ContextHelper(Interpreter interpreter) { + public ContextHandler(Interpreter interpreter) { if (interpreter == null) { - throw new InternalError("ContextHelper constructed with null interpreter"); + throw new InternalError("ContextHandler constructed with null interpreter"); } this.interpreter = interpreter; } diff --git a/src/main/java/cod/interpreter/handler/LambdaInvoker.java b/src/main/java/cod/interpreter/handler/LambdaInvokingHandler.java similarity index 98% rename from src/main/java/cod/interpreter/handler/LambdaInvoker.java rename to src/main/java/cod/interpreter/handler/LambdaInvokingHandler.java index 42477b3b..15935280 100644 --- a/src/main/java/cod/interpreter/handler/LambdaInvoker.java +++ b/src/main/java/cod/interpreter/handler/LambdaInvokingHandler.java @@ -10,16 +10,16 @@ import java.util.*; -public class LambdaInvoker { +public class LambdaInvokingHandler { private final TypeHandler typeSystem; private final InterpreterVisitor dispatcher; - public LambdaInvoker(TypeHandler typeSystem, InterpreterVisitor dispatcher) { + public LambdaInvokingHandler(TypeHandler typeSystem, InterpreterVisitor dispatcher) { if (typeSystem == null) { - throw new InternalError("LambdaInvoker constructed with null typeSystem"); + throw new InternalError("LambdaInvokingHandler constructed with null typeSystem"); } if (dispatcher == null) { - throw new InternalError("LambdaInvoker constructed with null dispatcher"); + throw new InternalError("LambdaInvokingHandler constructed with null dispatcher"); } this.typeSystem = typeSystem; this.dispatcher = dispatcher; diff --git a/src/main/java/cod/interpreter/handler/LoopOptimizer.java b/src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java similarity index 92% rename from src/main/java/cod/interpreter/handler/LoopOptimizer.java rename to src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java index 14ef0552..a5be8de7 100644 --- a/src/main/java/cod/interpreter/handler/LoopOptimizer.java +++ b/src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java @@ -19,7 +19,7 @@ import java.util.*; -public class LoopOptimizer { +public class LoopOptimizationHandler { private static final int LAZY_THRESHOLD = 10; private static final int MAX_SUPPORTED_LAG = 64; @@ -27,24 +27,24 @@ public class LoopOptimizer { private final TypeHandler typeSystem; private final ExpressionHandler expressionHandler; private final ArrayOperationHandler arrayOperationHandler; - private final PatternApplier patternApplier; + private final PattrrnHandler pattrrnHandler; - public LoopOptimizer( + public LoopOptimizationHandler( InterpreterVisitor dispatcher, TypeHandler typeSystem, ExpressionHandler expressionHandler, ArrayOperationHandler arrayOperationHandler, - PatternApplier patternApplier) { - if (dispatcher == null) throw new InternalError("LoopOptimizer dispatcher is null"); - if (typeSystem == null) throw new InternalError("LoopOptimizer typeSystem is null"); - if (expressionHandler == null) throw new InternalError("LoopOptimizer expressionHandler is null"); - if (arrayOperationHandler == null) throw new InternalError("LoopOptimizer arrayOperationHandler is null"); - if (patternApplier == null) throw new InternalError("LoopOptimizer patternApplier is null"); + PattrrnHandler pattrrnHandler) { + if (dispatcher == null) throw new InternalError("LoopOptimizationHandler dispatcher is null"); + if (typeSystem == null) throw new InternalError("LoopOptimizationHandler typeSystem is null"); + if (expressionHandler == null) throw new InternalError("LoopOptimizationHandler expressionHandler is null"); + if (arrayOperationHandler == null) throw new InternalError("LoopOptimizationHandler arrayOperationHandler is null"); + if (pattrrnHandler == null) throw new InternalError("LoopOptimizationHandler pattrrnHandler is null"); this.dispatcher = dispatcher; this.typeSystem = typeSystem; this.expressionHandler = expressionHandler; this.arrayOperationHandler = arrayOperationHandler; - this.patternApplier = patternApplier; + this.pattrrnHandler = pattrrnHandler; } public Object executeForLoop(For node) { @@ -218,10 +218,10 @@ public Object tryOptimizedExecution(For node, int loopId) { } } - List multiArrayPatterns = extractMultiArraySequencePatterns(node); + List multiArrayPatterns = extractMultiArraySequencePatterns(node); if (!multiArrayPatterns.isEmpty()) { try { - Object result = patternApplier.applyPatterns(node, multiArrayPatterns); + Object result = pattrrnHandler.applyPatterns(node, multiArrayPatterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -229,12 +229,12 @@ public Object tryOptimizedExecution(For node, int loopId) { } } - PatternApplier.LinearRecurrencePattern recurrencePattern = extractLinearRecurrencePattern(node); + PattrrnHandler.LinearRecurrencePattern recurrencePattern = extractLinearRecurrencePattern(node); if (recurrencePattern != null) { try { - List patterns = new ArrayList(); - patterns.add(new PatternApplier.PatternResult(PatternApplier.PatternType.LINEAR_RECURRENCE, recurrencePattern, recurrencePattern.targetArray)); - Object result = patternApplier.applyPatterns(node, patterns); + List patterns = new ArrayList(); + patterns.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.LINEAR_RECURRENCE, recurrencePattern, recurrencePattern.targetArray)); + Object result = pattrrnHandler.applyPatterns(node, patterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -246,9 +246,9 @@ public Object tryOptimizedExecution(For node, int loopId) { SequencePattern.extract(node.body.statements, node.iterator); if (seqPattern != null && seqPattern.isOptimizable()) { try { - List patterns = new ArrayList(); - patterns.add(new PatternApplier.PatternResult(PatternApplier.PatternType.SEQUENCE, seqPattern, seqPattern.targetArray)); - Object result = patternApplier.applyPatterns(node, patterns); + List patterns = new ArrayList(); + patterns.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.SEQUENCE, seqPattern, seqPattern.targetArray)); + Object result = pattrrnHandler.applyPatterns(node, patterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -256,14 +256,14 @@ public Object tryOptimizedExecution(For node, int loopId) { } } - List allPatterns = new ArrayList(); + List allPatterns = new ArrayList(); for (Stmt stmt : node.body.statements) { if (stmt instanceof StmtIf) { StmtIf ifStmt = (StmtIf) stmt; List patterns = extractConditionalPatterns(ifStmt, node.iterator); for (ConditionalPattern pattern : patterns) { if (pattern != null && pattern.isOptimizable()) { - allPatterns.add(new PatternApplier.PatternResult(PatternApplier.PatternType.CONDITIONAL, pattern, pattern.array)); + allPatterns.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.CONDITIONAL, pattern, pattern.array)); } } } @@ -271,7 +271,7 @@ public Object tryOptimizedExecution(For node, int loopId) { if (!allPatterns.isEmpty()) { try { - Object result = patternApplier.applyPatterns(node, allPatterns); + Object result = pattrrnHandler.applyPatterns(node, allPatterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -282,7 +282,7 @@ public Object tryOptimizedExecution(For node, int loopId) { return null; } - public PatternApplier.LinearRecurrencePattern extractLinearRecurrencePattern(For node) { + public PattrrnHandler.LinearRecurrencePattern extractLinearRecurrencePattern(For node) { if (node == null || node.body == null || node.body.statements == null) { return null; } @@ -376,7 +376,7 @@ public PatternApplier.LinearRecurrencePattern extractLinearRecurrencePattern(For seed[i] = v; } - return new PatternApplier.LinearRecurrencePattern( + return new PattrrnHandler.LinearRecurrencePattern( leftAccess.array, order, coeffByLag, @@ -526,8 +526,8 @@ private long[] resolveLoopBounds(For node) { return null; } - public List extractMultiArraySequencePatterns(For node) { - List results = new ArrayList(); + public List extractMultiArraySequencePatterns(For node) { + List results = new ArrayList(); if (node == null || node.body == null || node.body.statements == null) { return results; } @@ -542,27 +542,27 @@ public List extractMultiArraySequencePatterns(For for (Stmt stmt : statements) { if (!(stmt instanceof Assignment)) { - return new ArrayList(); + return new ArrayList(); } Assignment assign = (Assignment) stmt; if (assign.isDeclaration || !(assign.left instanceof IndexAccess)) { - return new ArrayList(); + return new ArrayList(); } IndexAccess indexAccess = (IndexAccess) assign.left; if (!(indexAccess.array instanceof Identifier) || !(indexAccess.index instanceof Identifier)) { - return new ArrayList(); + return new ArrayList(); } Identifier index = (Identifier) indexAccess.index; if (!node.iterator.equals(index.name)) { - return new ArrayList(); + return new ArrayList(); } String targetName = ((Identifier) indexAccess.array).name; if (orderedTargets.contains(targetName)) { - return new ArrayList(); + return new ArrayList(); } orderedTargets.add(targetName); @@ -580,14 +580,14 @@ public List extractMultiArraySequencePatterns(For for (String ref : refs) { int refIndex = orderedTargets.indexOf(ref); if (refIndex == -1 || refIndex > i) { - return new ArrayList(); + return new ArrayList(); } } List steps = new ArrayList(); steps.add(new SequencePattern.Step(null, assign.right)); SequencePattern.Pattern pattern = new SequencePattern.Pattern(steps, targetArray, node.iterator); - results.add(new PatternApplier.PatternResult(PatternApplier.PatternType.SEQUENCE, pattern, targetArray)); + results.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.SEQUENCE, pattern, targetArray)); } return results; diff --git a/src/main/java/cod/interpreter/handler/PatternApplier.java b/src/main/java/cod/interpreter/handler/PattrrnHandler.java similarity index 96% rename from src/main/java/cod/interpreter/handler/PatternApplier.java rename to src/main/java/cod/interpreter/handler/PattrrnHandler.java index 23f24bc5..dedc97c1 100644 --- a/src/main/java/cod/interpreter/handler/PatternApplier.java +++ b/src/main/java/cod/interpreter/handler/PattrrnHandler.java @@ -15,7 +15,7 @@ import java.util.*; -public class PatternApplier { +public class PattrrnHandler { public enum PatternType { CONDITIONAL, SEQUENCE, @@ -70,16 +70,16 @@ public LinearRecurrencePattern( private final ExpressionHandler expressionHandler; private final ArrayOperationHandler arrayOperationHandler; - public PatternApplier( + public PattrrnHandler( InterpreterVisitor dispatcher, TypeHandler typeSystem, ExpressionHandler expressionHandler, ArrayOperationHandler arrayOperationHandler ) { - if (dispatcher == null) throw new InternalError("PatternApplier dispatcher is null"); - if (typeSystem == null) throw new InternalError("PatternApplier typeSystem is null"); - if (expressionHandler == null) throw new InternalError("PatternApplier expressionHandler is null"); - if (arrayOperationHandler == null) throw new InternalError("PatternApplier arrayOperationHandler is null"); + if (dispatcher == null) throw new InternalError("PattrrnHandler dispatcher is null"); + if (typeSystem == null) throw new InternalError("PattrrnHandler typeSystem is null"); + if (expressionHandler == null) throw new InternalError("PattrrnHandler expressionHandler is null"); + if (arrayOperationHandler == null) throw new InternalError("PattrrnHandler arrayOperationHandler is null"); this.dispatcher = dispatcher; this.typeSystem = typeSystem; this.expressionHandler = expressionHandler; From 1771c32c7c5d94599bb7482ec58442c0fe37860b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 03:36:06 +0000 Subject: [PATCH 6/9] Plan naming cleanup for handler and PTAC/opt classes Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/829383f3-ec5d-4b89-883f-26c87e912a21 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- source_.jar | Bin 359462 -> 359503 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/source_.jar b/source_.jar index 789676cba0c8b247f74db8a6e1b3e955fd2e9f1f..e33189fa3a14e85bb58b52a3d9338475f851fe30 100644 GIT binary patch delta 44743 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 delta 44873 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 Date: Sat, 11 Apr 2026 03:36:42 +0000 Subject: [PATCH 7/9] Apply naming cleanup for Pattern/PTAC/opt classes Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/829383f3-ec5d-4b89-883f-26c87e912a21 Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- .../cod/interpreter/InterpreterVisitor.java | 8 +- .../handler/LoopOptimizationHandler.java | 54 ++-- ...attrrnHandler.java => PatternHandler.java} | 12 +- src/main/java/cod/ir/IRArtifactCodec.java | 98 +++---- src/main/java/cod/ir/IRManager.java | 38 +-- src/main/java/cod/ir/IRReader.java | 6 +- src/main/java/cod/ir/IRWriter.java | 6 +- .../{CodPTACArtifact.java => Artifact.java} | 4 +- src/main/java/cod/ptac/CodPTACCompiler.java | 27 -- .../java/cod/ptac/CodPTACInstruction.java | 34 --- src/main/java/cod/ptac/CodPTACOpcode.java | 78 ------ src/main/java/cod/ptac/CodPTACOperand.java | 36 --- src/main/java/cod/ptac/CodPTACOptimizer.java | 31 --- src/main/java/cod/ptac/Compiler.java | 27 ++ .../{CodPTACExecutor.java => Executor.java} | 192 ++++++------- .../cod/ptac/{CodPTACFlag.java => Flag.java} | 2 +- .../{CodPTACFunction.java => Function.java} | 4 +- src/main/java/cod/ptac/Instruction.java | 34 +++ .../ptac/{CodPTACLayer.java => Layer.java} | 2 +- .../{CodPTACLowerer.java => Lowerer.java} | 258 +++++++++--------- src/main/java/cod/ptac/Opcode.java | 78 ++++++ src/main/java/cod/ptac/Operand.java | 36 +++ ...dPTACOperandKind.java => OperandKind.java} | 2 +- src/main/java/cod/ptac/Optimizer.java | 31 +++ .../{CodPTACOptions.java => Options.java} | 12 +- .../cod/ptac/{CodPTACUnit.java => Unit.java} | 4 +- .../ptac/opt/CodPTACConstantFoldingPass.java | 59 ---- .../opt/CodPTACDeadTempEliminationPass.java | 54 ---- .../opt/CodPTACLazyRangePropagationPass.java | 41 --- .../cod/ptac/opt/CodPTACOptimizationPass.java | 7 - .../CodPTACOptionalPatternLoweringPass.java | 43 --- .../java/cod/ptac/opt/ConstantFolding.java | 59 ++++ .../cod/ptac/opt/DeadTempElimination.java | 54 ++++ src/main/java/cod/ptac/opt/Optimization.java | 7 + ...ternFusionPass.java => PatternFusion.java} | 26 +- .../java/cod/ptac/opt/PatternLowering.java | 43 +++ .../java/cod/ptac/opt/RangePropagation.java | 41 +++ src/main/java/cod/runner/CommandRunner.java | 14 +- .../java/cod/runner/IRValidationRunner.java | 10 +- ...TACParityRunner.java => ParityRunner.java} | 18 +- src/main/java/cod/runner/TestRunner.java | 14 +- .../java/cod/semantic/ImportResolver.java | 6 +- 42 files changed, 805 insertions(+), 805 deletions(-) rename src/main/java/cod/interpreter/handler/{PattrrnHandler.java => PatternHandler.java} (97%) rename src/main/java/cod/ptac/{CodPTACArtifact.java => Artifact.java} (84%) delete mode 100644 src/main/java/cod/ptac/CodPTACCompiler.java delete mode 100644 src/main/java/cod/ptac/CodPTACInstruction.java delete mode 100644 src/main/java/cod/ptac/CodPTACOpcode.java delete mode 100644 src/main/java/cod/ptac/CodPTACOperand.java delete mode 100644 src/main/java/cod/ptac/CodPTACOptimizer.java create mode 100644 src/main/java/cod/ptac/Compiler.java rename src/main/java/cod/ptac/{CodPTACExecutor.java => Executor.java} (58%) rename src/main/java/cod/ptac/{CodPTACFlag.java => Flag.java} (72%) rename src/main/java/cod/ptac/{CodPTACFunction.java => Function.java} (63%) create mode 100644 src/main/java/cod/ptac/Instruction.java rename src/main/java/cod/ptac/{CodPTACLayer.java => Layer.java} (64%) rename src/main/java/cod/ptac/{CodPTACLowerer.java => Lowerer.java} (57%) create mode 100644 src/main/java/cod/ptac/Opcode.java create mode 100644 src/main/java/cod/ptac/Operand.java rename src/main/java/cod/ptac/{CodPTACOperandKind.java => OperandKind.java} (75%) create mode 100644 src/main/java/cod/ptac/Optimizer.java rename src/main/java/cod/ptac/{CodPTACOptions.java => Options.java} (83%) rename src/main/java/cod/ptac/{CodPTACUnit.java => Unit.java} (59%) delete mode 100644 src/main/java/cod/ptac/opt/CodPTACConstantFoldingPass.java delete mode 100644 src/main/java/cod/ptac/opt/CodPTACDeadTempEliminationPass.java delete mode 100644 src/main/java/cod/ptac/opt/CodPTACLazyRangePropagationPass.java delete mode 100644 src/main/java/cod/ptac/opt/CodPTACOptimizationPass.java delete mode 100644 src/main/java/cod/ptac/opt/CodPTACOptionalPatternLoweringPass.java create mode 100644 src/main/java/cod/ptac/opt/ConstantFolding.java create mode 100644 src/main/java/cod/ptac/opt/DeadTempElimination.java create mode 100644 src/main/java/cod/ptac/opt/Optimization.java rename src/main/java/cod/ptac/opt/{CodPTACPatternFusionPass.java => PatternFusion.java} (50%) create mode 100644 src/main/java/cod/ptac/opt/PatternLowering.java create mode 100644 src/main/java/cod/ptac/opt/RangePropagation.java rename src/main/java/cod/runner/{CodPTACParityRunner.java => ParityRunner.java} (96%) diff --git a/src/main/java/cod/interpreter/InterpreterVisitor.java b/src/main/java/cod/interpreter/InterpreterVisitor.java index 0379ff8e..65043697 100644 --- a/src/main/java/cod/interpreter/InterpreterVisitor.java +++ b/src/main/java/cod/interpreter/InterpreterVisitor.java @@ -86,7 +86,7 @@ private static class LinearRecurrencePattern { private final ContextHandler contextHandler; private final LambdaInvokingHandler lambdaInvokingHandler; private final ArrayOperationHandler arrayOperationHandler; - private final PattrrnHandler pattrrnHandler; + private final PatternHandler patternHandler; private final LoopOptimizationHandler loopOptimizationHandler; // ========== SIMPLE LOOP OPTIMIZATION CONSTANTS ========== @@ -113,10 +113,10 @@ public InterpreterVisitor(Interpreter interpreter, TypeHandler typeSystem, this.assignmentHandler = new AssignmentHandler(typeSystem, interpreter, expressionHandler, this); this.arrayOperationHandler = new ArrayOperationHandler(this, interpreter, typeSystem, expressionHandler, contextHandler); - this.pattrrnHandler = - new PattrrnHandler(this, typeSystem, expressionHandler, arrayOperationHandler); + this.patternHandler = + new PatternHandler(this, typeSystem, expressionHandler, arrayOperationHandler); this.loopOptimizationHandler = - new LoopOptimizationHandler(this, typeSystem, expressionHandler, arrayOperationHandler, pattrrnHandler); + new LoopOptimizationHandler(this, typeSystem, expressionHandler, arrayOperationHandler, patternHandler); this.lambdaInvokingHandler = new LambdaInvokingHandler(typeSystem, this); } diff --git a/src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java b/src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java index a5be8de7..06916039 100644 --- a/src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java +++ b/src/main/java/cod/interpreter/handler/LoopOptimizationHandler.java @@ -27,24 +27,24 @@ public class LoopOptimizationHandler { private final TypeHandler typeSystem; private final ExpressionHandler expressionHandler; private final ArrayOperationHandler arrayOperationHandler; - private final PattrrnHandler pattrrnHandler; + private final PatternHandler patternHandler; public LoopOptimizationHandler( InterpreterVisitor dispatcher, TypeHandler typeSystem, ExpressionHandler expressionHandler, ArrayOperationHandler arrayOperationHandler, - PattrrnHandler pattrrnHandler) { + PatternHandler patternHandler) { if (dispatcher == null) throw new InternalError("LoopOptimizationHandler dispatcher is null"); if (typeSystem == null) throw new InternalError("LoopOptimizationHandler typeSystem is null"); if (expressionHandler == null) throw new InternalError("LoopOptimizationHandler expressionHandler is null"); if (arrayOperationHandler == null) throw new InternalError("LoopOptimizationHandler arrayOperationHandler is null"); - if (pattrrnHandler == null) throw new InternalError("LoopOptimizationHandler pattrrnHandler is null"); + if (patternHandler == null) throw new InternalError("LoopOptimizationHandler patternHandler is null"); this.dispatcher = dispatcher; this.typeSystem = typeSystem; this.expressionHandler = expressionHandler; this.arrayOperationHandler = arrayOperationHandler; - this.pattrrnHandler = pattrrnHandler; + this.patternHandler = patternHandler; } public Object executeForLoop(For node) { @@ -218,10 +218,10 @@ public Object tryOptimizedExecution(For node, int loopId) { } } - List multiArrayPatterns = extractMultiArraySequencePatterns(node); + List multiArrayPatterns = extractMultiArraySequencePatterns(node); if (!multiArrayPatterns.isEmpty()) { try { - Object result = pattrrnHandler.applyPatterns(node, multiArrayPatterns); + Object result = patternHandler.applyPatterns(node, multiArrayPatterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -229,12 +229,12 @@ public Object tryOptimizedExecution(For node, int loopId) { } } - PattrrnHandler.LinearRecurrencePattern recurrencePattern = extractLinearRecurrencePattern(node); + PatternHandler.LinearRecurrencePattern recurrencePattern = extractLinearRecurrencePattern(node); if (recurrencePattern != null) { try { - List patterns = new ArrayList(); - patterns.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.LINEAR_RECURRENCE, recurrencePattern, recurrencePattern.targetArray)); - Object result = pattrrnHandler.applyPatterns(node, patterns); + List patterns = new ArrayList(); + patterns.add(new PatternHandler.PatternResult(PatternHandler.PatternType.LINEAR_RECURRENCE, recurrencePattern, recurrencePattern.targetArray)); + Object result = patternHandler.applyPatterns(node, patterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -246,9 +246,9 @@ public Object tryOptimizedExecution(For node, int loopId) { SequencePattern.extract(node.body.statements, node.iterator); if (seqPattern != null && seqPattern.isOptimizable()) { try { - List patterns = new ArrayList(); - patterns.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.SEQUENCE, seqPattern, seqPattern.targetArray)); - Object result = pattrrnHandler.applyPatterns(node, patterns); + List patterns = new ArrayList(); + patterns.add(new PatternHandler.PatternResult(PatternHandler.PatternType.SEQUENCE, seqPattern, seqPattern.targetArray)); + Object result = patternHandler.applyPatterns(node, patterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -256,14 +256,14 @@ public Object tryOptimizedExecution(For node, int loopId) { } } - List allPatterns = new ArrayList(); + List allPatterns = new ArrayList(); for (Stmt stmt : node.body.statements) { if (stmt instanceof StmtIf) { StmtIf ifStmt = (StmtIf) stmt; List patterns = extractConditionalPatterns(ifStmt, node.iterator); for (ConditionalPattern pattern : patterns) { if (pattern != null && pattern.isOptimizable()) { - allPatterns.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.CONDITIONAL, pattern, pattern.array)); + allPatterns.add(new PatternHandler.PatternResult(PatternHandler.PatternType.CONDITIONAL, pattern, pattern.array)); } } } @@ -271,7 +271,7 @@ public Object tryOptimizedExecution(For node, int loopId) { if (!allPatterns.isEmpty()) { try { - Object result = pattrrnHandler.applyPatterns(node, allPatterns); + Object result = patternHandler.applyPatterns(node, allPatterns); ArrayTracker.markLoopOptimized(loopId); return result; } catch (Exception e) { @@ -282,7 +282,7 @@ public Object tryOptimizedExecution(For node, int loopId) { return null; } - public PattrrnHandler.LinearRecurrencePattern extractLinearRecurrencePattern(For node) { + public PatternHandler.LinearRecurrencePattern extractLinearRecurrencePattern(For node) { if (node == null || node.body == null || node.body.statements == null) { return null; } @@ -376,7 +376,7 @@ public PattrrnHandler.LinearRecurrencePattern extractLinearRecurrencePattern(For seed[i] = v; } - return new PattrrnHandler.LinearRecurrencePattern( + return new PatternHandler.LinearRecurrencePattern( leftAccess.array, order, coeffByLag, @@ -526,8 +526,8 @@ private long[] resolveLoopBounds(For node) { return null; } - public List extractMultiArraySequencePatterns(For node) { - List results = new ArrayList(); + public List extractMultiArraySequencePatterns(For node) { + List results = new ArrayList(); if (node == null || node.body == null || node.body.statements == null) { return results; } @@ -542,27 +542,27 @@ public List extractMultiArraySequencePatterns(For for (Stmt stmt : statements) { if (!(stmt instanceof Assignment)) { - return new ArrayList(); + return new ArrayList(); } Assignment assign = (Assignment) stmt; if (assign.isDeclaration || !(assign.left instanceof IndexAccess)) { - return new ArrayList(); + return new ArrayList(); } IndexAccess indexAccess = (IndexAccess) assign.left; if (!(indexAccess.array instanceof Identifier) || !(indexAccess.index instanceof Identifier)) { - return new ArrayList(); + return new ArrayList(); } Identifier index = (Identifier) indexAccess.index; if (!node.iterator.equals(index.name)) { - return new ArrayList(); + return new ArrayList(); } String targetName = ((Identifier) indexAccess.array).name; if (orderedTargets.contains(targetName)) { - return new ArrayList(); + return new ArrayList(); } orderedTargets.add(targetName); @@ -580,14 +580,14 @@ public List extractMultiArraySequencePatterns(For for (String ref : refs) { int refIndex = orderedTargets.indexOf(ref); if (refIndex == -1 || refIndex > i) { - return new ArrayList(); + return new ArrayList(); } } List steps = new ArrayList(); steps.add(new SequencePattern.Step(null, assign.right)); SequencePattern.Pattern pattern = new SequencePattern.Pattern(steps, targetArray, node.iterator); - results.add(new PattrrnHandler.PatternResult(PattrrnHandler.PatternType.SEQUENCE, pattern, targetArray)); + results.add(new PatternHandler.PatternResult(PatternHandler.PatternType.SEQUENCE, pattern, targetArray)); } return results; diff --git a/src/main/java/cod/interpreter/handler/PattrrnHandler.java b/src/main/java/cod/interpreter/handler/PatternHandler.java similarity index 97% rename from src/main/java/cod/interpreter/handler/PattrrnHandler.java rename to src/main/java/cod/interpreter/handler/PatternHandler.java index dedc97c1..1d2c6a24 100644 --- a/src/main/java/cod/interpreter/handler/PattrrnHandler.java +++ b/src/main/java/cod/interpreter/handler/PatternHandler.java @@ -15,7 +15,7 @@ import java.util.*; -public class PattrrnHandler { +public class PatternHandler { public enum PatternType { CONDITIONAL, SEQUENCE, @@ -70,16 +70,16 @@ public LinearRecurrencePattern( private final ExpressionHandler expressionHandler; private final ArrayOperationHandler arrayOperationHandler; - public PattrrnHandler( + public PatternHandler( InterpreterVisitor dispatcher, TypeHandler typeSystem, ExpressionHandler expressionHandler, ArrayOperationHandler arrayOperationHandler ) { - if (dispatcher == null) throw new InternalError("PattrrnHandler dispatcher is null"); - if (typeSystem == null) throw new InternalError("PattrrnHandler typeSystem is null"); - if (expressionHandler == null) throw new InternalError("PattrrnHandler expressionHandler is null"); - if (arrayOperationHandler == null) throw new InternalError("PattrrnHandler arrayOperationHandler is null"); + if (dispatcher == null) throw new InternalError("PatternHandler dispatcher is null"); + if (typeSystem == null) throw new InternalError("PatternHandler typeSystem is null"); + if (expressionHandler == null) throw new InternalError("PatternHandler expressionHandler is null"); + if (arrayOperationHandler == null) throw new InternalError("PatternHandler arrayOperationHandler is null"); this.dispatcher = dispatcher; this.typeSystem = typeSystem; this.expressionHandler = expressionHandler; diff --git a/src/main/java/cod/ir/IRArtifactCodec.java b/src/main/java/cod/ir/IRArtifactCodec.java index 32fd874b..ed3162e6 100644 --- a/src/main/java/cod/ir/IRArtifactCodec.java +++ b/src/main/java/cod/ir/IRArtifactCodec.java @@ -1,14 +1,14 @@ package cod.ir; import cod.ast.node.Type; -import cod.ptac.CodPTACArtifact; -import cod.ptac.CodPTACFlag; -import cod.ptac.CodPTACFunction; -import cod.ptac.CodPTACInstruction; -import cod.ptac.CodPTACOperand; -import cod.ptac.CodPTACOperandKind; -import cod.ptac.CodPTACOpcode; -import cod.ptac.CodPTACUnit; +import cod.ptac.Artifact; +import cod.ptac.Flag; +import cod.ptac.Function; +import cod.ptac.Instruction; +import cod.ptac.Operand; +import cod.ptac.OperandKind; +import cod.ptac.Opcode; +import cod.ptac.Unit; import java.io.DataInput; import java.io.DataOutput; @@ -24,12 +24,12 @@ final class IRArtifactCodec { private IRArtifactCodec() {} - static void writeArtifact(DataOutput out, CodPTACArtifact artifact) throws IOException { + static void writeArtifact(DataOutput out, Artifact artifact) throws IOException { IRCodec.writeHeader(out); IRCodec.writeValue(out, encodeArtifact(artifact), 0); } - static CodPTACArtifact readArtifact(DataInput in) throws IOException { + static Artifact readArtifact(DataInput in) throws IOException { IRCodec.readHeader(in); Object value = IRCodec.readValue(in, 0); if (!(value instanceof Map)) { @@ -38,7 +38,7 @@ static CodPTACArtifact readArtifact(DataInput in) throws IOException { return decodeArtifact(castMap(value, "artifact")); } - private static Map encodeArtifact(CodPTACArtifact artifact) { + private static Map encodeArtifact(Artifact artifact) { Map out = new LinkedHashMap(); out.put("schemaVersion", Integer.valueOf(ARTIFACT_SCHEMA_VERSION)); out.put("version", Integer.valueOf(artifact.version)); @@ -49,7 +49,7 @@ private static Map encodeArtifact(CodPTACArtifact artifact) { return out; } - private static Map encodeUnit(CodPTACUnit unit) { + private static Map encodeUnit(Unit unit) { if (unit == null) return null; Map out = new LinkedHashMap(); out.put("unitName", unit.unitName); @@ -59,10 +59,10 @@ private static Map encodeUnit(CodPTACUnit unit) { return out; } - private static List encodeFunctions(List functions) { + private static List encodeFunctions(List functions) { if (functions == null) return null; List out = new ArrayList(functions.size()); - for (CodPTACFunction fn : functions) { + for (Function fn : functions) { Map value = new LinkedHashMap(); value.put("name", fn == null ? null : fn.name); value.put("parameters", fn == null ? null : new ArrayList(safeStringList(fn.parameters))); @@ -74,10 +74,10 @@ private static List encodeFunctions(List functions) { return out; } - private static List encodeInstructions(List instructions) { + private static List encodeInstructions(List instructions) { if (instructions == null) return null; List out = new ArrayList(instructions.size()); - for (CodPTACInstruction instruction : instructions) { + for (Instruction instruction : instructions) { Map value = new LinkedHashMap(); value.put("opcode", instruction == null || instruction.opcode == null ? null : instruction.opcode.name()); value.put("dest", instruction == null ? null : instruction.dest); @@ -88,10 +88,10 @@ private static List encodeInstructions(List instruct return out; } - private static List encodeOperands(List operands) { + private static List encodeOperands(List operands) { if (operands == null) return null; List out = new ArrayList(operands.size()); - for (CodPTACOperand operand : operands) { + for (Operand operand : operands) { Map value = new LinkedHashMap(); value.put("kind", operand == null || operand.kind == null ? null : operand.kind.name()); value.put("value", operand == null ? null : operand.value); @@ -100,22 +100,22 @@ private static List encodeOperands(List operands) { return out; } - private static List encodeFlags(EnumSet flags) { + private static List encodeFlags(EnumSet flags) { if (flags == null) return null; List out = new ArrayList(flags.size()); - for (CodPTACFlag flag : flags) { + for (Flag flag : flags) { out.add(flag == null ? null : flag.name()); } return out; } - private static CodPTACArtifact decodeArtifact(Map map) throws IOException { + private static Artifact decodeArtifact(Map map) throws IOException { int schemaVersion = readInt(map.get("schemaVersion"), "schemaVersion"); if (schemaVersion != ARTIFACT_SCHEMA_VERSION) { throw new IOException("Unsupported artifact schema version: " + schemaVersion); } - CodPTACArtifact artifact = new CodPTACArtifact(); + Artifact artifact = new Artifact(); artifact.version = readInt(map.get("version"), "version"); artifact.unitName = asString(map.get("unitName"), "unitName"); artifact.className = asString(map.get("className"), "className"); @@ -124,10 +124,10 @@ private static CodPTACArtifact decodeArtifact(Map map) throws IO return artifact; } - private static CodPTACUnit decodeUnit(Object value) throws IOException { + private static Unit decodeUnit(Object value) throws IOException { if (value == null) return null; Map map = castMap(value, "unit"); - CodPTACUnit unit = new CodPTACUnit(); + Unit unit = new Unit(); unit.unitName = asString(map.get("unitName"), "unit.unitName"); unit.className = asString(map.get("className"), "unit.className"); unit.entryFunction = asString(map.get("entryFunction"), "unit.entryFunction"); @@ -135,13 +135,13 @@ private static CodPTACUnit decodeUnit(Object value) throws IOException { return unit; } - private static List decodeFunctions(Object value) throws IOException { - if (value == null) return new ArrayList(); + private static List decodeFunctions(Object value) throws IOException { + if (value == null) return new ArrayList(); List list = castList(value, "unit.functions"); - List out = new ArrayList(list.size()); + List out = new ArrayList(list.size()); for (Object item : list) { Map map = castMap(item, "function"); - CodPTACFunction function = new CodPTACFunction(); + Function function = new Function(); function.name = asString(map.get("name"), "function.name"); function.parameters = asStringList(map.get("parameters"), "function.parameters"); function.instructions = decodeInstructions(map.get("instructions")); @@ -152,65 +152,65 @@ private static List decodeFunctions(Object value) throws IOExce return out; } - private static List decodeInstructions(Object value) throws IOException { - if (value == null) return new ArrayList(); + private static List decodeInstructions(Object value) throws IOException { + if (value == null) return new ArrayList(); List list = castList(value, "function.instructions"); - List out = new ArrayList(list.size()); + List out = new ArrayList(list.size()); for (Object item : list) { Map map = castMap(item, "instruction"); String opcodeName = asString(map.get("opcode"), "instruction.opcode"); - CodPTACOpcode opcode = parseEnum(CodPTACOpcode.class, opcodeName, "instruction.opcode"); + Opcode opcode = parseEnum(Opcode.class, opcodeName, "instruction.opcode"); String dest = asString(map.get("dest"), "instruction.dest"); - List operands = decodeOperands(map.get("operands")); - EnumSet flags = decodeFlags(map.get("flags")); - out.add(new CodPTACInstruction(opcode, dest, operands, flags)); + List operands = decodeOperands(map.get("operands")); + EnumSet flags = decodeFlags(map.get("flags")); + out.add(new Instruction(opcode, dest, operands, flags)); } return out; } - private static List decodeOperands(Object value) throws IOException { - if (value == null) return new ArrayList(); + private static List decodeOperands(Object value) throws IOException { + if (value == null) return new ArrayList(); List list = castList(value, "instruction.operands"); - List out = new ArrayList(list.size()); + List out = new ArrayList(list.size()); for (Object item : list) { Map map = castMap(item, "operand"); String kindName = asString(map.get("kind"), "operand.kind"); - CodPTACOperandKind kind = parseEnum(CodPTACOperandKind.class, kindName, "operand.kind"); + OperandKind kind = parseEnum(OperandKind.class, kindName, "operand.kind"); Object operandValue = map.get("value"); out.add(createOperand(kind, operandValue)); } return out; } - private static EnumSet decodeFlags(Object value) throws IOException { - EnumSet out = EnumSet.noneOf(CodPTACFlag.class); + private static EnumSet decodeFlags(Object value) throws IOException { + EnumSet out = EnumSet.noneOf(Flag.class); if (value == null) return out; List list = castList(value, "instruction.flags"); for (Object item : list) { String flagName = asString(item, "instruction.flag"); - CodPTACFlag flag = parseEnum(CodPTACFlag.class, flagName, "instruction.flag"); + Flag flag = parseEnum(Flag.class, flagName, "instruction.flag"); out.add(flag); } return out; } - private static CodPTACOperand createOperand(CodPTACOperandKind kind, Object value) throws IOException { + private static Operand createOperand(OperandKind kind, Object value) throws IOException { if (kind == null) { throw new IOException("operand.kind is null"); } switch (kind) { case REGISTER: - return CodPTACOperand.register(asString(value, "operand.value")); + return Operand.register(asString(value, "operand.value")); case IMMEDIATE: - return CodPTACOperand.immediate(value); + return Operand.immediate(value); case LABEL: - return CodPTACOperand.label(asString(value, "operand.value")); + return Operand.label(asString(value, "operand.value")); case FUNCTION: - return CodPTACOperand.function(asString(value, "operand.value")); + return Operand.function(asString(value, "operand.value")); case SLOT: - return CodPTACOperand.slot(asString(value, "operand.value")); + return Operand.slot(asString(value, "operand.value")); case IDENTIFIER: - return CodPTACOperand.identifier(asString(value, "operand.value")); + return Operand.identifier(asString(value, "operand.value")); default: throw new IOException("Unsupported operand kind: " + kind); } diff --git a/src/main/java/cod/ir/IRManager.java b/src/main/java/cod/ir/IRManager.java index 9bfe5f72..943988ed 100644 --- a/src/main/java/cod/ir/IRManager.java +++ b/src/main/java/cod/ir/IRManager.java @@ -1,9 +1,9 @@ package cod.ir; import cod.ast.node.Type; -import cod.ptac.CodPTACArtifact; -import cod.ptac.CodPTACCompiler; -import cod.ptac.CodPTACUnit; +import cod.ptac.Artifact; +import cod.ptac.Compiler; +import cod.ptac.Unit; import java.io.File; import java.io.IOException; @@ -18,16 +18,16 @@ public class IRManager { private final IRWriter writer; private final IRReader reader; private final Map> cache; - private final Map> artifactCache; - private final CodPTACCompiler compiler; + private final Map> artifactCache; + private final Compiler compiler; public IRManager(String projectRoot) { this.projectRoot = projectRoot; this.writer = new IRWriter(); this.reader = new IRReader(); this.cache = new HashMap>(); - this.artifactCache = new HashMap>(); - this.compiler = new CodPTACCompiler(); + this.artifactCache = new HashMap>(); + this.compiler = new Compiler(); } public Type load(String unit, String className) { @@ -49,7 +49,7 @@ public Type load(String unit, String className) { } try { - CodPTACArtifact artifact = reader.readArtifact(file); + Artifact artifact = reader.readArtifact(file); if (artifact != null) { putArtifactCache(unit, className, artifact); Type type = artifact.typeSnapshot; @@ -70,19 +70,19 @@ public void save(String unit, Type type) { } File file = getIRFile(unit, type.name); try { - CodPTACArtifact artifact = compiler.compile(unit, type); + Artifact artifact = compiler.compile(unit, type); writer.writeArtifact(file, artifact); putCache(unit, type.name, type); putArtifactCache(unit, type.name, artifact); } catch (IOException ignored) {} } - public CodPTACArtifact loadArtifact(String unit, String className) { + public Artifact loadArtifact(String unit, String className) { if (unit == null || className == null) { return null; } - Map unitCache = artifactCache.get(unit); + Map unitCache = artifactCache.get(unit); if (unitCache != null && unitCache.containsKey(className)) { return unitCache.get(className); } @@ -93,7 +93,7 @@ public CodPTACArtifact loadArtifact(String unit, String className) { } try { - CodPTACArtifact artifact = reader.readArtifact(file); + Artifact artifact = reader.readArtifact(file); if (artifact != null) { putArtifactCache(unit, className, artifact); if (artifact.typeSnapshot != null) { @@ -106,12 +106,12 @@ public CodPTACArtifact loadArtifact(String unit, String className) { } } - public CodPTACUnit loadCodPTACUnit(String unit, String className) { - CodPTACArtifact artifact = loadArtifact(unit, className); + public Unit loadCodPTACUnit(String unit, String className) { + Artifact artifact = loadArtifact(unit, className); return artifact != null ? artifact.unit : null; } - public void saveArtifact(String unit, CodPTACArtifact artifact) { + public void saveArtifact(String unit, Artifact artifact) { if (artifact == null || unit == null || artifact.className == null) return; File file = getIRFile(unit, artifact.className); try { @@ -137,7 +137,7 @@ public Map getCacheStats() { stats.put("units", cache.size()); stats.put("classes", total); int artifacts = 0; - for (Map unitArtifacts : artifactCache.values()) { + for (Map unitArtifacts : artifactCache.values()) { artifacts += unitArtifacts.size(); } stats.put("artifacts", artifacts); @@ -153,10 +153,10 @@ private void putCache(String unit, String className, Type type) { unitCache.put(className, type); } - private void putArtifactCache(String unit, String className, CodPTACArtifact artifact) { - Map unitCache = artifactCache.get(unit); + private void putArtifactCache(String unit, String className, Artifact artifact) { + Map unitCache = artifactCache.get(unit); if (unitCache == null) { - unitCache = new HashMap(); + unitCache = new HashMap(); artifactCache.put(unit, unitCache); } unitCache.put(className, artifact); diff --git a/src/main/java/cod/ir/IRReader.java b/src/main/java/cod/ir/IRReader.java index b3df4457..ad41d07e 100644 --- a/src/main/java/cod/ir/IRReader.java +++ b/src/main/java/cod/ir/IRReader.java @@ -1,7 +1,7 @@ package cod.ir; import cod.ast.node.Type; -import cod.ptac.CodPTACArtifact; +import cod.ptac.Artifact; import java.io.BufferedInputStream; import java.io.DataInputStream; @@ -11,14 +11,14 @@ public final class IRReader { public Type read(File file) throws IOException { - CodPTACArtifact artifact = readArtifact(file); + Artifact artifact = readArtifact(file); if (artifact == null) { return null; } return artifact.typeSnapshot; } - public CodPTACArtifact readArtifact(File file) throws IOException { + public Artifact readArtifact(File file) throws IOException { if (file == null) { throw new IOException("IR source file is null"); } diff --git a/src/main/java/cod/ir/IRWriter.java b/src/main/java/cod/ir/IRWriter.java index 689e6bef..9d1a2996 100644 --- a/src/main/java/cod/ir/IRWriter.java +++ b/src/main/java/cod/ir/IRWriter.java @@ -1,7 +1,7 @@ package cod.ir; import cod.ast.node.Type; -import cod.ptac.CodPTACArtifact; +import cod.ptac.Artifact; import java.io.BufferedOutputStream; import java.io.DataOutputStream; @@ -11,13 +11,13 @@ public final class IRWriter { public void write(File file, Type type) throws IOException { - CodPTACArtifact artifact = new CodPTACArtifact(); + Artifact artifact = new Artifact(); artifact.className = type != null ? type.name : null; artifact.typeSnapshot = type; writeArtifact(file, artifact); } - public void writeArtifact(File file, CodPTACArtifact artifact) throws IOException { + public void writeArtifact(File file, Artifact artifact) throws IOException { if (file == null) { throw new IOException("IR target file is null"); } diff --git a/src/main/java/cod/ptac/CodPTACArtifact.java b/src/main/java/cod/ptac/Artifact.java similarity index 84% rename from src/main/java/cod/ptac/CodPTACArtifact.java rename to src/main/java/cod/ptac/Artifact.java index 165f2f48..dda56721 100644 --- a/src/main/java/cod/ptac/CodPTACArtifact.java +++ b/src/main/java/cod/ptac/Artifact.java @@ -3,13 +3,13 @@ import cod.ast.node.Type; -public final class CodPTACArtifact { +public final class Artifact { public static final int FORMAT_VERSION = 1; public int version = FORMAT_VERSION; public String unitName; public String className; - public CodPTACUnit unit; + public Unit unit; public Type typeSnapshot; public boolean hasExecutableUnit() { diff --git a/src/main/java/cod/ptac/CodPTACCompiler.java b/src/main/java/cod/ptac/CodPTACCompiler.java deleted file mode 100644 index ae8b67b8..00000000 --- a/src/main/java/cod/ptac/CodPTACCompiler.java +++ /dev/null @@ -1,27 +0,0 @@ -package cod.ptac; - -import cod.ast.node.Type; - -public final class CodPTACCompiler { - private final CodPTACLowerer lowerer; - private final CodPTACOptimizer optimizer; - - public CodPTACCompiler() { - this(false); - } - - public CodPTACCompiler(boolean enableOptionalLowering) { - this.lowerer = new CodPTACLowerer(); - this.optimizer = new CodPTACOptimizer(enableOptionalLowering); - } - - public CodPTACArtifact compile(String unitName, Type type) { - CodPTACArtifact artifact = new CodPTACArtifact(); - artifact.version = CodPTACArtifact.FORMAT_VERSION; - artifact.unitName = unitName; - artifact.className = type != null ? type.name : null; - artifact.typeSnapshot = type; - artifact.unit = optimizer.optimize(lowerer.lower(unitName, type)); - return artifact; - } -} diff --git a/src/main/java/cod/ptac/CodPTACInstruction.java b/src/main/java/cod/ptac/CodPTACInstruction.java deleted file mode 100644 index eeef6ffc..00000000 --- a/src/main/java/cod/ptac/CodPTACInstruction.java +++ /dev/null @@ -1,34 +0,0 @@ -package cod.ptac; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -public final class CodPTACInstruction { - public final CodPTACOpcode opcode; - public final String dest; - public final List operands; - public final EnumSet flags; - - public CodPTACInstruction( - CodPTACOpcode opcode, - String dest, - List operands, - EnumSet flags - ) { - this.opcode = opcode; - this.dest = dest; - this.operands = operands != null ? operands : new ArrayList(); - this.flags = flags != null ? flags : EnumSet.noneOf(CodPTACFlag.class); - } - - public CodPTACInstruction(CodPTACOpcode opcode, String dest, List operands) { - this(opcode, dest, operands, null); - } - - public CodPTACInstruction withFlag(CodPTACFlag flag) { - EnumSet copy = EnumSet.copyOf(this.flags); - copy.add(flag); - return new CodPTACInstruction(this.opcode, this.dest, this.operands, copy); - } -} diff --git a/src/main/java/cod/ptac/CodPTACOpcode.java b/src/main/java/cod/ptac/CodPTACOpcode.java deleted file mode 100644 index aeb2caa2..00000000 --- a/src/main/java/cod/ptac/CodPTACOpcode.java +++ /dev/null @@ -1,78 +0,0 @@ -package cod.ptac; - - -public enum CodPTACOpcode { - // Core TAC - NOP(CodPTACLayer.CORE_TAC), - ASSIGN(CodPTACLayer.CORE_TAC), - ADD(CodPTACLayer.CORE_TAC), - SUB(CodPTACLayer.CORE_TAC), - MUL(CodPTACLayer.CORE_TAC), - DIV(CodPTACLayer.CORE_TAC), - MOD(CodPTACLayer.CORE_TAC), - EQ(CodPTACLayer.CORE_TAC), - NE(CodPTACLayer.CORE_TAC), - GT(CodPTACLayer.CORE_TAC), - LT(CodPTACLayer.CORE_TAC), - GTE(CodPTACLayer.CORE_TAC), - LTE(CodPTACLayer.CORE_TAC), - BRANCH(CodPTACLayer.CORE_TAC), - BRANCH_IF(CodPTACLayer.CORE_TAC), - CALL(CodPTACLayer.CORE_TAC), - RETURN(CodPTACLayer.CORE_TAC), - LOAD(CodPTACLayer.CORE_TAC), - STORE(CodPTACLayer.CORE_TAC), - - // Coderive pattern ops - RANGE(CodPTACLayer.PATTERN), - RANGE_Q(CodPTACLayer.PATTERN), - RANGE_S(CodPTACLayer.PATTERN), - RANGE_L(CodPTACLayer.PATTERN), - RANGE_LS(CodPTACLayer.PATTERN), - MAP(CodPTACLayer.PATTERN), - FILTER(CodPTACLayer.PATTERN), - REDUCE(CodPTACLayer.PATTERN), - WHERE(CodPTACLayer.PATTERN), - SCAN(CodPTACLayer.PATTERN), - ZIP(CodPTACLayer.PATTERN), - TAKE(CodPTACLayer.PATTERN), - FILTER_MAP(CodPTACLayer.PATTERN), - FILTER_MAP_REDUCE(CodPTACLayer.PATTERN), - - // Lambda / recursion / closures - LAMBDA(CodPTACLayer.PATTERN), - CLOSURE(CodPTACLayer.PATTERN), - ANCESTOR(CodPTACLayer.PATTERN), - SELF(CodPTACLayer.PATTERN), - TAIL_CALL(CodPTACLayer.PATTERN), - - // Slot ops - SLOT_GET(CodPTACLayer.PATTERN), - SLOT_SET(CodPTACLayer.PATTERN), - SLOT_RET(CodPTACLayer.PATTERN), - SLOT_UNPACK(CodPTACLayer.PATTERN), - SLOT_DIV(CodPTACLayer.PATTERN), - - // Lazy ops - LAZY_GET(CodPTACLayer.PATTERN), - LAZY_SET(CodPTACLayer.PATTERN), - LAZY_COMMIT(CodPTACLayer.PATTERN), - LAZY_SIZE(CodPTACLayer.PATTERN), - LAZY_SLICE(CodPTACLayer.PATTERN), - - // Formula ops - FORMULA_SEQ(CodPTACLayer.PATTERN), - FORMULA_COND(CodPTACLayer.PATTERN), - FORMULA_RECUR(CodPTACLayer.PATTERN), - FORMULA_FUSE(CodPTACLayer.PATTERN); - - private final CodPTACLayer layer; - - CodPTACOpcode(CodPTACLayer layer) { - this.layer = layer; - } - - public CodPTACLayer getLayer() { - return layer; - } -} diff --git a/src/main/java/cod/ptac/CodPTACOperand.java b/src/main/java/cod/ptac/CodPTACOperand.java deleted file mode 100644 index b777fafd..00000000 --- a/src/main/java/cod/ptac/CodPTACOperand.java +++ /dev/null @@ -1,36 +0,0 @@ -package cod.ptac; - - -public final class CodPTACOperand { - public final CodPTACOperandKind kind; - public final Object value; - - private CodPTACOperand(CodPTACOperandKind kind, Object value) { - this.kind = kind; - this.value = value; - } - - public static CodPTACOperand register(String name) { - return new CodPTACOperand(CodPTACOperandKind.REGISTER, name); - } - - public static CodPTACOperand immediate(Object value) { - return new CodPTACOperand(CodPTACOperandKind.IMMEDIATE, value); - } - - public static CodPTACOperand label(String name) { - return new CodPTACOperand(CodPTACOperandKind.LABEL, name); - } - - public static CodPTACOperand function(String name) { - return new CodPTACOperand(CodPTACOperandKind.FUNCTION, name); - } - - public static CodPTACOperand slot(String name) { - return new CodPTACOperand(CodPTACOperandKind.SLOT, name); - } - - public static CodPTACOperand identifier(String name) { - return new CodPTACOperand(CodPTACOperandKind.IDENTIFIER, name); - } -} diff --git a/src/main/java/cod/ptac/CodPTACOptimizer.java b/src/main/java/cod/ptac/CodPTACOptimizer.java deleted file mode 100644 index 5142344f..00000000 --- a/src/main/java/cod/ptac/CodPTACOptimizer.java +++ /dev/null @@ -1,31 +0,0 @@ -package cod.ptac; - -import cod.ptac.opt.*; - -import java.util.ArrayList; -import java.util.List; - -public final class CodPTACOptimizer { - private final List passes; - - public CodPTACOptimizer() { - this(false); - } - - public CodPTACOptimizer(boolean enableOptionalLowering) { - this.passes = new ArrayList(); - this.passes.add(new CodPTACPatternFusionPass()); - this.passes.add(new CodPTACLazyRangePropagationPass()); - this.passes.add(new CodPTACConstantFoldingPass()); - this.passes.add(new CodPTACDeadTempEliminationPass()); - this.passes.add(new CodPTACOptionalPatternLoweringPass(enableOptionalLowering)); - } - - public CodPTACUnit optimize(CodPTACUnit unit) { - if (unit == null) return null; - for (CodPTACOptimizationPass pass : passes) { - pass.apply(unit); - } - return unit; - } -} diff --git a/src/main/java/cod/ptac/Compiler.java b/src/main/java/cod/ptac/Compiler.java new file mode 100644 index 00000000..226ccd6a --- /dev/null +++ b/src/main/java/cod/ptac/Compiler.java @@ -0,0 +1,27 @@ +package cod.ptac; + +import cod.ast.node.Type; + +public final class Compiler { + private final Lowerer lowerer; + private final Optimizer optimizer; + + public Compiler() { + this(false); + } + + public Compiler(boolean enableOptionalLowering) { + this.lowerer = new Lowerer(); + this.optimizer = new Optimizer(enableOptionalLowering); + } + + public Artifact compile(String unitName, Type type) { + Artifact artifact = new Artifact(); + artifact.version = Artifact.FORMAT_VERSION; + artifact.unitName = unitName; + artifact.className = type != null ? type.name : null; + artifact.typeSnapshot = type; + artifact.unit = optimizer.optimize(lowerer.lower(unitName, type)); + return artifact; + } +} diff --git a/src/main/java/cod/ptac/CodPTACExecutor.java b/src/main/java/cod/ptac/Executor.java similarity index 58% rename from src/main/java/cod/ptac/CodPTACExecutor.java rename to src/main/java/cod/ptac/Executor.java index 0ad9d9df..4bbd28af 100644 --- a/src/main/java/cod/ptac/CodPTACExecutor.java +++ b/src/main/java/cod/ptac/Executor.java @@ -10,27 +10,27 @@ import java.util.List; import java.util.Map; -public final class CodPTACExecutor { - private final CodPTACOptions options; +public final class Executor { + private final Options options; private static final Object FALLBACK_SENTINEL = new Object(); - private static final class CodPTACRange { + private static final class Range { final BigInteger start; final BigInteger end; final BigInteger step; - CodPTACRange(BigInteger start, BigInteger end, BigInteger step) { + Range(BigInteger start, BigInteger end, BigInteger step) { this.start = start; this.end = end; this.step = step; } } - public CodPTACExecutor(CodPTACOptions options) { - this.options = options != null ? options : CodPTACOptions.current(); + public Executor(Options options) { + this.options = options != null ? options : Options.current(); } - public Object execute(CodPTACArtifact artifact, Interpreter fallbackInterpreter) { + public Object execute(Artifact artifact, Interpreter fallbackInterpreter) { if (artifact == null) { throw new ProgramError("Cannot execute null CodP-TAC artifact"); } @@ -39,7 +39,7 @@ public Object execute(CodPTACArtifact artifact, Interpreter fallbackInterpreter) return fallback(artifact, fallbackInterpreter, "No executable CodP-TAC unit in artifact"); } - CodPTACFunction entry = findEntry(artifact.unit); + Function entry = findEntry(artifact.unit); if (entry == null) { return fallback(artifact, fallbackInterpreter, "No entry function found in CodP-TAC unit"); } @@ -48,11 +48,11 @@ public Object execute(CodPTACArtifact artifact, Interpreter fallbackInterpreter) } private Object executeFunction( - CodPTACUnit unit, - CodPTACFunction function, + Unit unit, + Function function, List args, Interpreter fallbackInterpreter, - CodPTACArtifact artifact + Artifact artifact ) { Map registers = new HashMap(); if (function.parameters != null) { @@ -64,13 +64,13 @@ private Object executeFunction( if (function.instructions == null) return null; - for (CodPTACInstruction inst : function.instructions) { + for (Instruction inst : function.instructions) { if (inst == null) continue; Object result = runInstruction(unit, inst, registers, fallbackInterpreter, artifact); if (result == FALLBACK_SENTINEL) { return FALLBACK_SENTINEL; } - if (inst.opcode == CodPTACOpcode.RETURN) { + if (inst.opcode == Opcode.RETURN) { return result; } } @@ -78,13 +78,13 @@ private Object executeFunction( } private Object runInstruction( - CodPTACUnit unit, - CodPTACInstruction inst, + Unit unit, + Instruction inst, Map registers, Interpreter fallbackInterpreter, - CodPTACArtifact artifact + Artifact artifact ) { - if (inst.opcode == CodPTACOpcode.ASSIGN) { + if (inst.opcode == Opcode.ASSIGN) { Object value = operandValue(inst.operands, 0, registers); registers.put(inst.dest, value); return value; @@ -106,65 +106,65 @@ private Object runInstruction( return out; } - if (inst.opcode == CodPTACOpcode.RANGE - || inst.opcode == CodPTACOpcode.RANGE_Q - || inst.opcode == CodPTACOpcode.RANGE_S - || inst.opcode == CodPTACOpcode.RANGE_L - || inst.opcode == CodPTACOpcode.RANGE_LS) { + if (inst.opcode == Opcode.RANGE + || inst.opcode == Opcode.RANGE_Q + || inst.opcode == Opcode.RANGE_S + || inst.opcode == Opcode.RANGE_L + || inst.opcode == Opcode.RANGE_LS) { Object start = operandValue(inst.operands, 0, registers); Object end = operandValue(inst.operands, 1, registers); Object stepVal = inst.operands != null && inst.operands.size() > 2 ? operandValue(inst.operands, 2, registers) : 1; - CodPTACRange range = new CodPTACRange(toBigInt(start), toBigInt(end), toBigInt(stepVal)); + Range range = new Range(toBigInt(start), toBigInt(end), toBigInt(stepVal)); if (inst.dest != null) registers.put(inst.dest, range); return range; } - if (inst.opcode == CodPTACOpcode.TAKE) { - CodPTACRange source = asRange(operandValue(inst.operands, 0, registers)); + if (inst.opcode == Opcode.TAKE) { + Range source = asRange(operandValue(inst.operands, 0, registers)); BigInteger n = toBigInt(operandValue(inst.operands, 1, registers)); List out = take(source, n); if (inst.dest != null) registers.put(inst.dest, out); return out; } - if (inst.opcode == CodPTACOpcode.FILTER - || inst.opcode == CodPTACOpcode.MAP - || inst.opcode == CodPTACOpcode.FILTER_MAP - || inst.opcode == CodPTACOpcode.REDUCE - || inst.opcode == CodPTACOpcode.SCAN - || inst.opcode == CodPTACOpcode.ZIP - || inst.opcode == CodPTACOpcode.WHERE - || inst.opcode == CodPTACOpcode.FILTER_MAP_REDUCE - || inst.opcode == CodPTACOpcode.LAZY_GET - || inst.opcode == CodPTACOpcode.LAZY_SET - || inst.opcode == CodPTACOpcode.LAZY_COMMIT - || inst.opcode == CodPTACOpcode.LAZY_SIZE - || inst.opcode == CodPTACOpcode.LAZY_SLICE - || inst.opcode == CodPTACOpcode.SLOT_GET - || inst.opcode == CodPTACOpcode.SLOT_SET - || inst.opcode == CodPTACOpcode.SLOT_RET - || inst.opcode == CodPTACOpcode.SLOT_UNPACK - || inst.opcode == CodPTACOpcode.SLOT_DIV - || inst.opcode == CodPTACOpcode.ANCESTOR - || inst.opcode == CodPTACOpcode.SELF - || inst.opcode == CodPTACOpcode.TAIL_CALL - || inst.opcode == CodPTACOpcode.CLOSURE - || inst.opcode == CodPTACOpcode.FORMULA_SEQ - || inst.opcode == CodPTACOpcode.FORMULA_COND - || inst.opcode == CodPTACOpcode.FORMULA_RECUR - || inst.opcode == CodPTACOpcode.FORMULA_FUSE - || inst.opcode == CodPTACOpcode.STORE - || inst.opcode == CodPTACOpcode.LOAD - || inst.opcode == CodPTACOpcode.BRANCH - || inst.opcode == CodPTACOpcode.BRANCH_IF) { + if (inst.opcode == Opcode.FILTER + || inst.opcode == Opcode.MAP + || inst.opcode == Opcode.FILTER_MAP + || inst.opcode == Opcode.REDUCE + || inst.opcode == Opcode.SCAN + || inst.opcode == Opcode.ZIP + || inst.opcode == Opcode.WHERE + || inst.opcode == Opcode.FILTER_MAP_REDUCE + || inst.opcode == Opcode.LAZY_GET + || inst.opcode == Opcode.LAZY_SET + || inst.opcode == Opcode.LAZY_COMMIT + || inst.opcode == Opcode.LAZY_SIZE + || inst.opcode == Opcode.LAZY_SLICE + || inst.opcode == Opcode.SLOT_GET + || inst.opcode == Opcode.SLOT_SET + || inst.opcode == Opcode.SLOT_RET + || inst.opcode == Opcode.SLOT_UNPACK + || inst.opcode == Opcode.SLOT_DIV + || inst.opcode == Opcode.ANCESTOR + || inst.opcode == Opcode.SELF + || inst.opcode == Opcode.TAIL_CALL + || inst.opcode == Opcode.CLOSURE + || inst.opcode == Opcode.FORMULA_SEQ + || inst.opcode == Opcode.FORMULA_COND + || inst.opcode == Opcode.FORMULA_RECUR + || inst.opcode == Opcode.FORMULA_FUSE + || inst.opcode == Opcode.STORE + || inst.opcode == Opcode.LOAD + || inst.opcode == Opcode.BRANCH + || inst.opcode == Opcode.BRANCH_IF) { return fallback(artifact, fallbackInterpreter, "Opcode not yet natively executed: " + inst.opcode); } - if (inst.opcode == CodPTACOpcode.CALL) { + if (inst.opcode == Opcode.CALL) { String functionName = String.valueOf(operandValue(inst.operands, 0, registers)); - CodPTACFunction target = findFunction(unit, functionName); + Function target = findFunction(unit, functionName); if (target == null) { return fallback(artifact, fallbackInterpreter, "Unknown function: " + functionName); } @@ -180,14 +180,14 @@ private Object runInstruction( return result; } - if (inst.opcode == CodPTACOpcode.RETURN) { + if (inst.opcode == Opcode.RETURN) { return operandValue(inst.operands, 0, registers); } return null; } - private Object fallback(CodPTACArtifact artifact, Interpreter fallbackInterpreter, String reason) { + private Object fallback(Artifact artifact, Interpreter fallbackInterpreter, String reason) { if (!options.isFallbackEnabled()) { throw new ProgramError("CodP-TAC execution failed without fallback: " + reason); } @@ -205,62 +205,62 @@ private Object fallback(CodPTACArtifact artifact, Interpreter fallbackInterprete throw new ProgramError("CodP-TAC fallback unavailable: " + reason); } - private CodPTACFunction findEntry(CodPTACUnit unit) { + private Function findEntry(Unit unit) { if (unit.entryFunction != null) { - CodPTACFunction explicit = findFunction(unit, unit.entryFunction); + Function explicit = findFunction(unit, unit.entryFunction); if (explicit != null) return explicit; } return findFunction(unit, "main"); } - private CodPTACFunction findFunction(CodPTACUnit unit, String name) { + private Function findFunction(Unit unit, String name) { if (unit == null || unit.functions == null || name == null) return null; - for (CodPTACFunction fn : unit.functions) { + for (Function fn : unit.functions) { if (fn != null && name.equals(fn.name)) return fn; } return null; } - private Object operandValue(List operands, int index, Map registers) { + private Object operandValue(List operands, int index, Map registers) { if (operands == null || index >= operands.size()) return null; - CodPTACOperand operand = operands.get(index); + Operand operand = operands.get(index); if (operand == null) return null; - if (operand.kind == CodPTACOperandKind.REGISTER && operand.value instanceof String) { + if (operand.kind == OperandKind.REGISTER && operand.value instanceof String) { return registers.get(operand.value); } return operand.value; } - private boolean isMath(CodPTACOpcode opcode) { - return opcode == CodPTACOpcode.ADD - || opcode == CodPTACOpcode.SUB - || opcode == CodPTACOpcode.MUL - || opcode == CodPTACOpcode.DIV - || opcode == CodPTACOpcode.MOD; + private boolean isMath(Opcode opcode) { + return opcode == Opcode.ADD + || opcode == Opcode.SUB + || opcode == Opcode.MUL + || opcode == Opcode.DIV + || opcode == Opcode.MOD; } - private boolean isCompare(CodPTACOpcode opcode) { - return opcode == CodPTACOpcode.EQ - || opcode == CodPTACOpcode.NE - || opcode == CodPTACOpcode.GT - || opcode == CodPTACOpcode.LT - || opcode == CodPTACOpcode.GTE - || opcode == CodPTACOpcode.LTE; + private boolean isCompare(Opcode opcode) { + return opcode == Opcode.EQ + || opcode == Opcode.NE + || opcode == Opcode.GT + || opcode == Opcode.LT + || opcode == Opcode.GTE + || opcode == Opcode.LTE; } - private Object evaluateMath(CodPTACOpcode opcode, Object a, Object b) { + private Object evaluateMath(Opcode opcode, Object a, Object b) { BigInteger left = toBigInt(a); BigInteger right = toBigInt(b); - if (opcode == CodPTACOpcode.ADD) return left.add(right); - if (opcode == CodPTACOpcode.SUB) return left.subtract(right); - if (opcode == CodPTACOpcode.MUL) return left.multiply(right); - if (opcode == CodPTACOpcode.DIV) { + if (opcode == Opcode.ADD) return left.add(right); + if (opcode == Opcode.SUB) return left.subtract(right); + if (opcode == Opcode.MUL) return left.multiply(right); + if (opcode == Opcode.DIV) { if (right.equals(BigInteger.ZERO)) { throw new ProgramError("CodP-TAC division by zero"); } return left.divide(right); } - if (opcode == CodPTACOpcode.MOD) { + if (opcode == Opcode.MOD) { if (right.equals(BigInteger.ZERO)) { throw new ProgramError("CodP-TAC modulo by zero"); } @@ -269,25 +269,25 @@ private Object evaluateMath(CodPTACOpcode opcode, Object a, Object b) { return BigInteger.ZERO; } - private Boolean evaluateCompare(CodPTACOpcode opcode, Object a, Object b) { + private Boolean evaluateCompare(Opcode opcode, Object a, Object b) { BigInteger left = toBigInt(a); BigInteger right = toBigInt(b); int cmp = left.compareTo(right); - if (opcode == CodPTACOpcode.EQ) return cmp == 0; - if (opcode == CodPTACOpcode.NE) return cmp != 0; - if (opcode == CodPTACOpcode.GT) return cmp > 0; - if (opcode == CodPTACOpcode.LT) return cmp < 0; - if (opcode == CodPTACOpcode.GTE) return cmp >= 0; - if (opcode == CodPTACOpcode.LTE) return cmp <= 0; + if (opcode == Opcode.EQ) return cmp == 0; + if (opcode == Opcode.NE) return cmp != 0; + if (opcode == Opcode.GT) return cmp > 0; + if (opcode == Opcode.LT) return cmp < 0; + if (opcode == Opcode.GTE) return cmp >= 0; + if (opcode == Opcode.LTE) return cmp <= 0; return false; } - private CodPTACRange asRange(Object value) { - if (value instanceof CodPTACRange) return (CodPTACRange) value; - return new CodPTACRange(BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE); + private Range asRange(Object value) { + if (value instanceof Range) return (Range) value; + return new Range(BigInteger.ZERO, BigInteger.ZERO, BigInteger.ONE); } - private List take(CodPTACRange range, BigInteger n) { + private List take(Range range, BigInteger n) { List out = new ArrayList(); if (range == null || n == null || n.compareTo(BigInteger.ZERO) <= 0) return out; diff --git a/src/main/java/cod/ptac/CodPTACFlag.java b/src/main/java/cod/ptac/Flag.java similarity index 72% rename from src/main/java/cod/ptac/CodPTACFlag.java rename to src/main/java/cod/ptac/Flag.java index 5ff2f640..1f7cb675 100644 --- a/src/main/java/cod/ptac/CodPTACFlag.java +++ b/src/main/java/cod/ptac/Flag.java @@ -1,7 +1,7 @@ package cod.ptac; -public enum CodPTACFlag { +public enum Flag { LAZY, TAIL, PURE, diff --git a/src/main/java/cod/ptac/CodPTACFunction.java b/src/main/java/cod/ptac/Function.java similarity index 63% rename from src/main/java/cod/ptac/CodPTACFunction.java rename to src/main/java/cod/ptac/Function.java index f95a572e..a32de63b 100644 --- a/src/main/java/cod/ptac/CodPTACFunction.java +++ b/src/main/java/cod/ptac/Function.java @@ -3,10 +3,10 @@ import java.util.ArrayList; import java.util.List; -public final class CodPTACFunction { +public final class Function { public String name; public List parameters = new ArrayList(); - public List instructions = new ArrayList(); + public List instructions = new ArrayList(); public boolean lambdaBlock; public int closureLevel; } diff --git a/src/main/java/cod/ptac/Instruction.java b/src/main/java/cod/ptac/Instruction.java new file mode 100644 index 00000000..5aa8fedc --- /dev/null +++ b/src/main/java/cod/ptac/Instruction.java @@ -0,0 +1,34 @@ +package cod.ptac; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +public final class Instruction { + public final Opcode opcode; + public final String dest; + public final List operands; + public final EnumSet flags; + + public Instruction( + Opcode opcode, + String dest, + List operands, + EnumSet flags + ) { + this.opcode = opcode; + this.dest = dest; + this.operands = operands != null ? operands : new ArrayList(); + this.flags = flags != null ? flags : EnumSet.noneOf(Flag.class); + } + + public Instruction(Opcode opcode, String dest, List operands) { + this(opcode, dest, operands, null); + } + + public Instruction withFlag(Flag flag) { + EnumSet copy = EnumSet.copyOf(this.flags); + copy.add(flag); + return new Instruction(this.opcode, this.dest, this.operands, copy); + } +} diff --git a/src/main/java/cod/ptac/CodPTACLayer.java b/src/main/java/cod/ptac/Layer.java similarity index 64% rename from src/main/java/cod/ptac/CodPTACLayer.java rename to src/main/java/cod/ptac/Layer.java index 737906e9..5b18c15a 100644 --- a/src/main/java/cod/ptac/CodPTACLayer.java +++ b/src/main/java/cod/ptac/Layer.java @@ -1,7 +1,7 @@ package cod.ptac; -public enum CodPTACLayer { +public enum Layer { CORE_TAC, PATTERN } diff --git a/src/main/java/cod/ptac/CodPTACLowerer.java b/src/main/java/cod/ptac/Lowerer.java similarity index 57% rename from src/main/java/cod/ptac/CodPTACLowerer.java rename to src/main/java/cod/ptac/Lowerer.java index 2465a17e..bac3a95d 100644 --- a/src/main/java/cod/ptac/CodPTACLowerer.java +++ b/src/main/java/cod/ptac/Lowerer.java @@ -8,13 +8,13 @@ import java.util.Arrays; import java.util.List; -public final class CodPTACLowerer { +public final class Lowerer { private int tempCounter = 0; private int patternCounter = 0; private int lambdaCounter = 0; - public CodPTACUnit lower(String unitName, Type type) { - CodPTACUnit unit = new CodPTACUnit(); + public Unit lower(String unitName, Type type) { + Unit unit = new Unit(); unit.unitName = unitName; unit.className = type != null ? type.name : null; @@ -34,8 +34,8 @@ public CodPTACUnit lower(String unitName, Type type) { return unit; } - private CodPTACFunction lowerMethod(Method method, CodPTACUnit unit) { - CodPTACFunction fn = new CodPTACFunction(); + private Function lowerMethod(Method method, Unit unit) { + Function fn = new Function(); fn.name = method != null ? method.methodName : "anonymous"; if (method != null && method.parameters != null) { for (Param param : method.parameters) { @@ -49,22 +49,22 @@ private CodPTACFunction lowerMethod(Method method, CodPTACUnit unit) { for (Stmt stmt : method.body) { lowerStmt(stmt, fn, unit); } - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + fn.instructions.add(new Instruction( + Opcode.RETURN, null, - Arrays.asList(CodPTACOperand.immediate(null)) + Arrays.asList(Operand.immediate(null)) )); return fn; } - private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { + private void lowerStmt(Stmt stmt, Function fn, Unit unit) { if (stmt == null) return; if (stmt instanceof Var) { Var var = (Var) stmt; - CodPTACOperand value = lowerExpr(var.value, fn, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.ASSIGN, + Operand value = lowerExpr(var.value, fn, unit); + fn.instructions.add(new Instruction( + Opcode.ASSIGN, var.name, Arrays.asList(value) )); @@ -73,19 +73,19 @@ private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { if (stmt instanceof Assignment) { Assignment assign = (Assignment) stmt; - CodPTACOperand rhs = lowerExpr(assign.right, fn, unit); + Operand rhs = lowerExpr(assign.right, fn, unit); if (assign.left instanceof Identifier) { - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.ASSIGN, + fn.instructions.add(new Instruction( + Opcode.ASSIGN, ((Identifier) assign.left).name, Arrays.asList(rhs) )); } else if (assign.left instanceof IndexAccess) { IndexAccess access = (IndexAccess) assign.left; - CodPTACOperand arr = lowerExpr(access.array, fn, unit); - CodPTACOperand idx = lowerExpr(access.index, fn, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.LAZY_SET, + Operand arr = lowerExpr(access.array, fn, unit); + Operand idx = lowerExpr(access.index, fn, unit); + fn.instructions.add(new Instruction( + Opcode.LAZY_SET, null, Arrays.asList(arr, idx, rhs) )); @@ -95,11 +95,11 @@ private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { if (stmt instanceof SlotAssignment) { SlotAssignment slot = (SlotAssignment) stmt; - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.SLOT_SET, + fn.instructions.add(new Instruction( + Opcode.SLOT_SET, null, Arrays.asList( - CodPTACOperand.slot(slot.slotName), + Operand.slot(slot.slotName), lowerExpr(slot.value, fn, unit) ) )); @@ -119,16 +119,16 @@ private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { if (stmt instanceof ReturnSlotAssignment) { ReturnSlotAssignment ret = (ReturnSlotAssignment) stmt; if (ret.methodCall != null) { - CodPTACOperand result = lowerExpr(ret.methodCall, fn, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.SLOT_UNPACK, + Operand result = lowerExpr(ret.methodCall, fn, unit); + fn.instructions.add(new Instruction( + Opcode.SLOT_UNPACK, null, Arrays.asList(result) )); } else if (ret.lambda != null) { - CodPTACOperand lambdaReg = lowerExpr(ret.lambda, fn, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.SLOT_UNPACK, + Operand lambdaReg = lowerExpr(ret.lambda, fn, unit); + fn.instructions.add(new Instruction( + Opcode.SLOT_UNPACK, null, Arrays.asList(lambdaReg) )); @@ -145,36 +145,36 @@ private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { StmtIf ifStmt = (StmtIf) stmt; String thenLabel = "L_then_" + nextTemp(); String endLabel = "L_end_" + nextTemp(); - CodPTACOperand cond = lowerExpr(ifStmt.condition, fn, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.BRANCH_IF, + Operand cond = lowerExpr(ifStmt.condition, fn, unit); + fn.instructions.add(new Instruction( + Opcode.BRANCH_IF, null, - Arrays.asList(cond, CodPTACOperand.label(thenLabel)) + Arrays.asList(cond, Operand.label(thenLabel)) )); if (ifStmt.elseBlock != null && ifStmt.elseBlock.statements != null) { for (Stmt elseStmt : ifStmt.elseBlock.statements) { lowerStmt(elseStmt, fn, unit); } } - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.BRANCH, + fn.instructions.add(new Instruction( + Opcode.BRANCH, null, - Arrays.asList(CodPTACOperand.label(endLabel)) + Arrays.asList(Operand.label(endLabel)) )); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.NOP, + fn.instructions.add(new Instruction( + Opcode.NOP, thenLabel, - new ArrayList() + new ArrayList() )); if (ifStmt.thenBlock != null && ifStmt.thenBlock.statements != null) { for (Stmt thenStmt : ifStmt.thenBlock.statements) { lowerStmt(thenStmt, fn, unit); } } - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.NOP, + fn.instructions.add(new Instruction( + Opcode.NOP, endLabel, - new ArrayList() + new ArrayList() )); return; } @@ -190,10 +190,10 @@ private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { } if (stmt instanceof Exit) { - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + fn.instructions.add(new Instruction( + Opcode.RETURN, null, - Arrays.asList(CodPTACOperand.immediate(null)) + Arrays.asList(Operand.immediate(null)) )); return; } @@ -203,21 +203,21 @@ private void lowerStmt(Stmt stmt, CodPTACFunction fn, CodPTACUnit unit) { return; } - fn.instructions.add(new CodPTACInstruction(CodPTACOpcode.NOP, null, new ArrayList())); + fn.instructions.add(new Instruction(Opcode.NOP, null, new ArrayList())); } - private void lowerFor(For node, CodPTACFunction fn, CodPTACUnit unit) { + private void lowerFor(For node, Function fn, Unit unit) { if (node == null || node.range == null) return; String rangeReg = nextPattern(); - CodPTACOpcode rangeOpcode = selectRangeOpcode(node.range); - List rangeOps = new ArrayList(); + Opcode rangeOpcode = selectRangeOpcode(node.range); + List rangeOps = new ArrayList(); rangeOps.add(lowerExpr(node.range.start, fn, unit)); rangeOps.add(lowerExpr(node.range.end, fn, unit)); if (node.range.step != null) { rangeOps.add(lowerExpr(node.range.step, fn, unit)); } - fn.instructions.add(new CodPTACInstruction(rangeOpcode, rangeReg, rangeOps)); + fn.instructions.add(new Instruction(rangeOpcode, rangeReg, rangeOps)); List body = node.body != null ? node.body.statements : null; if (body == null || body.isEmpty()) return; @@ -231,13 +231,13 @@ private void lowerFor(For node, CodPTACFunction fn, CodPTACUnit unit) { if (seq != null && seq.isOptimizable() && cond != null && cond.isOptimizable()) { String condLambda = lowerConditionLambda(cond, unit); String mapLambda = lowerSequenceLambda(seq, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.FILTER_MAP, + fn.instructions.add(new Instruction( + Opcode.FILTER_MAP, nextPattern(), Arrays.asList( - CodPTACOperand.register(rangeReg), - CodPTACOperand.function(condLambda), - CodPTACOperand.function(mapLambda) + Operand.register(rangeReg), + Operand.function(condLambda), + Operand.function(mapLambda) ) )); return; @@ -245,20 +245,20 @@ private void lowerFor(For node, CodPTACFunction fn, CodPTACUnit unit) { if (cond != null && cond.isOptimizable()) { String condLambda = lowerConditionLambda(cond, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.FILTER, + fn.instructions.add(new Instruction( + Opcode.FILTER, nextPattern(), - Arrays.asList(CodPTACOperand.register(rangeReg), CodPTACOperand.function(condLambda)) + Arrays.asList(Operand.register(rangeReg), Operand.function(condLambda)) )); return; } if (seq != null && seq.isOptimizable()) { String lambdaName = lowerSequenceLambda(seq, unit); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.MAP, + fn.instructions.add(new Instruction( + Opcode.MAP, nextPattern(), - Arrays.asList(CodPTACOperand.register(rangeReg), CodPTACOperand.function(lambdaName)) + Arrays.asList(Operand.register(rangeReg), Operand.function(lambdaName)) )); return; } @@ -268,9 +268,9 @@ private void lowerFor(For node, CodPTACFunction fn, CodPTACUnit unit) { } } - private String lowerConditionLambda(ConditionalPattern pattern, CodPTACUnit unit) { + private String lowerConditionLambda(ConditionalPattern pattern, Unit unit) { String lambdaName = nextLambdaName("cond"); - CodPTACFunction lambda = new CodPTACFunction(); + Function lambda = new Function(); lambda.name = lambdaName; lambda.lambdaBlock = true; lambda.parameters.add(pattern.indexVar != null ? pattern.indexVar : "p0"); @@ -278,28 +278,28 @@ private String lowerConditionLambda(ConditionalPattern pattern, CodPTACUnit unit if (pattern.branches != null && !pattern.branches.isEmpty()) { ConditionalPattern.Branch first = pattern.branches.get(0); if (first != null && first.condition != null) { - CodPTACOperand condition = lowerExpr(first.condition, lambda, unit); - lambda.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + Operand condition = lowerExpr(first.condition, lambda, unit); + lambda.instructions.add(new Instruction( + Opcode.RETURN, null, Arrays.asList(condition) )); } } if (lambda.instructions.isEmpty()) { - lambda.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + lambda.instructions.add(new Instruction( + Opcode.RETURN, null, - Arrays.asList(CodPTACOperand.immediate(Boolean.TRUE)) + Arrays.asList(Operand.immediate(Boolean.TRUE)) )); } unit.functions.add(lambda); return lambdaName; } - private String lowerSequenceLambda(SequencePattern.Pattern pattern, CodPTACUnit unit) { + private String lowerSequenceLambda(SequencePattern.Pattern pattern, Unit unit) { String lambdaName = nextLambdaName("seq"); - CodPTACFunction lambda = new CodPTACFunction(); + Function lambda = new Function(); lambda.name = lambdaName; lambda.lambdaBlock = true; lambda.parameters.add(pattern.indexVar != null ? pattern.indexVar : "p0"); @@ -309,16 +309,16 @@ private String lowerSequenceLambda(SequencePattern.Pattern pattern, CodPTACUnit if (step == null) { continue; } - CodPTACOperand value = lowerExpr(step.expression, lambda, unit); + Operand value = lowerExpr(step.expression, lambda, unit); if (step.tempVar != null) { - lambda.instructions.add(new CodPTACInstruction( - CodPTACOpcode.ASSIGN, + lambda.instructions.add(new Instruction( + Opcode.ASSIGN, step.tempVar, Arrays.asList(value) )); } else { - lambda.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + lambda.instructions.add(new Instruction( + Opcode.RETURN, null, Arrays.asList(value) )); @@ -326,92 +326,92 @@ private String lowerSequenceLambda(SequencePattern.Pattern pattern, CodPTACUnit } } if (lambda.instructions.isEmpty()) { - lambda.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + lambda.instructions.add(new Instruction( + Opcode.RETURN, null, - Arrays.asList(CodPTACOperand.immediate(null)) + Arrays.asList(Operand.immediate(null)) )); } unit.functions.add(lambda); return lambdaName; } - private CodPTACOperand lowerExpr(Expr expr, CodPTACFunction fn, CodPTACUnit unit) { - if (expr == null) return CodPTACOperand.immediate(null); + private Operand lowerExpr(Expr expr, Function fn, Unit unit) { + if (expr == null) return Operand.immediate(null); - if (expr instanceof IntLiteral) return CodPTACOperand.immediate(((IntLiteral) expr).value); - if (expr instanceof FloatLiteral) return CodPTACOperand.immediate(((FloatLiteral) expr).value); - if (expr instanceof BoolLiteral) return CodPTACOperand.immediate(((BoolLiteral) expr).value); - if (expr instanceof TextLiteral) return CodPTACOperand.immediate(((TextLiteral) expr).value); - if (expr instanceof NoneLiteral) return CodPTACOperand.immediate(null); - if (expr instanceof Identifier) return CodPTACOperand.register(((Identifier) expr).name); + if (expr instanceof IntLiteral) return Operand.immediate(((IntLiteral) expr).value); + if (expr instanceof FloatLiteral) return Operand.immediate(((FloatLiteral) expr).value); + if (expr instanceof BoolLiteral) return Operand.immediate(((BoolLiteral) expr).value); + if (expr instanceof TextLiteral) return Operand.immediate(((TextLiteral) expr).value); + if (expr instanceof NoneLiteral) return Operand.immediate(null); + if (expr instanceof Identifier) return Operand.register(((Identifier) expr).name); if (expr instanceof Range) { Range range = (Range) expr; String dest = nextPattern(); - CodPTACOpcode op = selectRangeOpcode(range); - List ops = new ArrayList(); + Opcode op = selectRangeOpcode(range); + List ops = new ArrayList(); ops.add(lowerExpr(range.start, fn, unit)); ops.add(lowerExpr(range.end, fn, unit)); if (range.step != null) ops.add(lowerExpr(range.step, fn, unit)); - fn.instructions.add(new CodPTACInstruction(op, dest, ops)); - return CodPTACOperand.register(dest); + fn.instructions.add(new Instruction(op, dest, ops)); + return Operand.register(dest); } if (expr instanceof IndexAccess) { IndexAccess access = (IndexAccess) expr; String dest = nextTemp(); - fn.instructions.add(new CodPTACInstruction( - CodPTACOpcode.LAZY_GET, + fn.instructions.add(new Instruction( + Opcode.LAZY_GET, dest, Arrays.asList( lowerExpr(access.array, fn, unit), lowerExpr(access.index, fn, unit) ) )); - return CodPTACOperand.register(dest); + return Operand.register(dest); } if (expr instanceof BinaryOp) { BinaryOp binary = (BinaryOp) expr; - CodPTACOperand left = lowerExpr(binary.left, fn, unit); - CodPTACOperand right = lowerExpr(binary.right, fn, unit); + Operand left = lowerExpr(binary.left, fn, unit); + Operand right = lowerExpr(binary.right, fn, unit); String dest = nextTemp(); - fn.instructions.add(new CodPTACInstruction( + fn.instructions.add(new Instruction( mapBinary(binary.op), dest, Arrays.asList(left, right) )); - return CodPTACOperand.register(dest); + return Operand.register(dest); } if (expr instanceof MethodCall) { MethodCall call = (MethodCall) expr; - List ops = new ArrayList(); + List ops = new ArrayList(); if (call.isSelfCall) { for (Expr arg : call.arguments) { ops.add(lowerExpr(arg, fn, unit)); } String dest = nextTemp(); - fn.instructions.add(new CodPTACInstruction(CodPTACOpcode.SELF, dest, ops)); - return CodPTACOperand.register(dest); + fn.instructions.add(new Instruction(Opcode.SELF, dest, ops)); + return Operand.register(dest); } - ops.add(CodPTACOperand.function(call.name)); + ops.add(Operand.function(call.name)); if (call.arguments != null) { for (Expr arg : call.arguments) { ops.add(lowerExpr(arg, fn, unit)); } } String dest = nextTemp(); - fn.instructions.add(new CodPTACInstruction(CodPTACOpcode.CALL, dest, ops)); - return CodPTACOperand.register(dest); + fn.instructions.add(new Instruction(Opcode.CALL, dest, ops)); + return Operand.register(dest); } if (expr instanceof Lambda) { Lambda lambdaNode = (Lambda) expr; String lambdaName = nextLambdaName("inline"); - CodPTACFunction lambda = new CodPTACFunction(); + Function lambda = new Function(); lambda.name = lambdaName; lambda.lambdaBlock = true; if (lambdaNode.parameters != null) { @@ -420,45 +420,45 @@ private CodPTACOperand lowerExpr(Expr expr, CodPTACFunction fn, CodPTACUnit unit } } if (lambdaNode.expressionBody != null) { - CodPTACOperand val = lowerExpr(lambdaNode.expressionBody, lambda, unit); - lambda.instructions.add(new CodPTACInstruction(CodPTACOpcode.RETURN, null, Arrays.asList(val))); + Operand val = lowerExpr(lambdaNode.expressionBody, lambda, unit); + lambda.instructions.add(new Instruction(Opcode.RETURN, null, Arrays.asList(val))); } else if (lambdaNode.body != null) { lowerStmt(lambdaNode.body, lambda, unit); } if (lambda.instructions.isEmpty()) { - lambda.instructions.add(new CodPTACInstruction( - CodPTACOpcode.RETURN, + lambda.instructions.add(new Instruction( + Opcode.RETURN, null, - Arrays.asList(CodPTACOperand.immediate(null)) + Arrays.asList(Operand.immediate(null)) )); } unit.functions.add(lambda); - return CodPTACOperand.function(lambdaName); + return Operand.function(lambdaName); } - return CodPTACOperand.identifier(String.valueOf(expr)); + return Operand.identifier(String.valueOf(expr)); } - private CodPTACOpcode selectRangeOpcode(Range range) { + private Opcode selectRangeOpcode(Range range) { if (range != null && (range.start instanceof TextLiteral || range.end instanceof TextLiteral)) { - return range.step == null ? CodPTACOpcode.RANGE_L : CodPTACOpcode.RANGE_LS; + return range.step == null ? Opcode.RANGE_L : Opcode.RANGE_LS; } - return range != null && range.step != null ? CodPTACOpcode.RANGE_S : CodPTACOpcode.RANGE; + return range != null && range.step != null ? Opcode.RANGE_S : Opcode.RANGE; } - private CodPTACOpcode mapBinary(String op) { - if ("+".equals(op)) return CodPTACOpcode.ADD; - if ("-".equals(op)) return CodPTACOpcode.SUB; - if ("*".equals(op)) return CodPTACOpcode.MUL; - if ("/".equals(op)) return CodPTACOpcode.DIV; - if ("%".equals(op)) return CodPTACOpcode.MOD; - if ("==".equals(op)) return CodPTACOpcode.EQ; - if ("!=".equals(op)) return CodPTACOpcode.NE; - if (">".equals(op)) return CodPTACOpcode.GT; - if ("<".equals(op)) return CodPTACOpcode.LT; - if (">=".equals(op)) return CodPTACOpcode.GTE; - if ("<=".equals(op)) return CodPTACOpcode.LTE; - return CodPTACOpcode.NOP; + private Opcode mapBinary(String op) { + if ("+".equals(op)) return Opcode.ADD; + if ("-".equals(op)) return Opcode.SUB; + if ("*".equals(op)) return Opcode.MUL; + if ("/".equals(op)) return Opcode.DIV; + if ("%".equals(op)) return Opcode.MOD; + if ("==".equals(op)) return Opcode.EQ; + if ("!=".equals(op)) return Opcode.NE; + if (">".equals(op)) return Opcode.GT; + if ("<".equals(op)) return Opcode.LT; + if (">=".equals(op)) return Opcode.GTE; + if ("<=".equals(op)) return Opcode.LTE; + return Opcode.NOP; } private String nextTemp() { @@ -473,9 +473,9 @@ private String nextLambdaName(String prefix) { return "lambda$" + prefix + "$" + (lambdaCounter++); } - private CodPTACFunction findFunction(CodPTACUnit unit, String name) { + private Function findFunction(Unit unit, String name) { if (unit == null || unit.functions == null) return null; - for (CodPTACFunction fn : unit.functions) { + for (Function fn : unit.functions) { if (fn != null && name.equals(fn.name)) return fn; } return null; diff --git a/src/main/java/cod/ptac/Opcode.java b/src/main/java/cod/ptac/Opcode.java new file mode 100644 index 00000000..b44e9d9b --- /dev/null +++ b/src/main/java/cod/ptac/Opcode.java @@ -0,0 +1,78 @@ +package cod.ptac; + + +public enum Opcode { + // Core TAC + NOP(Layer.CORE_TAC), + ASSIGN(Layer.CORE_TAC), + ADD(Layer.CORE_TAC), + SUB(Layer.CORE_TAC), + MUL(Layer.CORE_TAC), + DIV(Layer.CORE_TAC), + MOD(Layer.CORE_TAC), + EQ(Layer.CORE_TAC), + NE(Layer.CORE_TAC), + GT(Layer.CORE_TAC), + LT(Layer.CORE_TAC), + GTE(Layer.CORE_TAC), + LTE(Layer.CORE_TAC), + BRANCH(Layer.CORE_TAC), + BRANCH_IF(Layer.CORE_TAC), + CALL(Layer.CORE_TAC), + RETURN(Layer.CORE_TAC), + LOAD(Layer.CORE_TAC), + STORE(Layer.CORE_TAC), + + // Coderive pattern ops + RANGE(Layer.PATTERN), + RANGE_Q(Layer.PATTERN), + RANGE_S(Layer.PATTERN), + RANGE_L(Layer.PATTERN), + RANGE_LS(Layer.PATTERN), + MAP(Layer.PATTERN), + FILTER(Layer.PATTERN), + REDUCE(Layer.PATTERN), + WHERE(Layer.PATTERN), + SCAN(Layer.PATTERN), + ZIP(Layer.PATTERN), + TAKE(Layer.PATTERN), + FILTER_MAP(Layer.PATTERN), + FILTER_MAP_REDUCE(Layer.PATTERN), + + // Lambda / recursion / closures + LAMBDA(Layer.PATTERN), + CLOSURE(Layer.PATTERN), + ANCESTOR(Layer.PATTERN), + SELF(Layer.PATTERN), + TAIL_CALL(Layer.PATTERN), + + // Slot ops + SLOT_GET(Layer.PATTERN), + SLOT_SET(Layer.PATTERN), + SLOT_RET(Layer.PATTERN), + SLOT_UNPACK(Layer.PATTERN), + SLOT_DIV(Layer.PATTERN), + + // Lazy ops + LAZY_GET(Layer.PATTERN), + LAZY_SET(Layer.PATTERN), + LAZY_COMMIT(Layer.PATTERN), + LAZY_SIZE(Layer.PATTERN), + LAZY_SLICE(Layer.PATTERN), + + // Formula ops + FORMULA_SEQ(Layer.PATTERN), + FORMULA_COND(Layer.PATTERN), + FORMULA_RECUR(Layer.PATTERN), + FORMULA_FUSE(Layer.PATTERN); + + private final Layer layer; + + Opcode(Layer layer) { + this.layer = layer; + } + + public Layer getLayer() { + return layer; + } +} diff --git a/src/main/java/cod/ptac/Operand.java b/src/main/java/cod/ptac/Operand.java new file mode 100644 index 00000000..414c6e85 --- /dev/null +++ b/src/main/java/cod/ptac/Operand.java @@ -0,0 +1,36 @@ +package cod.ptac; + + +public final class Operand { + public final OperandKind kind; + public final Object value; + + private Operand(OperandKind kind, Object value) { + this.kind = kind; + this.value = value; + } + + public static Operand register(String name) { + return new Operand(OperandKind.REGISTER, name); + } + + public static Operand immediate(Object value) { + return new Operand(OperandKind.IMMEDIATE, value); + } + + public static Operand label(String name) { + return new Operand(OperandKind.LABEL, name); + } + + public static Operand function(String name) { + return new Operand(OperandKind.FUNCTION, name); + } + + public static Operand slot(String name) { + return new Operand(OperandKind.SLOT, name); + } + + public static Operand identifier(String name) { + return new Operand(OperandKind.IDENTIFIER, name); + } +} diff --git a/src/main/java/cod/ptac/CodPTACOperandKind.java b/src/main/java/cod/ptac/OperandKind.java similarity index 75% rename from src/main/java/cod/ptac/CodPTACOperandKind.java rename to src/main/java/cod/ptac/OperandKind.java index 08d09c3a..d5f4f972 100644 --- a/src/main/java/cod/ptac/CodPTACOperandKind.java +++ b/src/main/java/cod/ptac/OperandKind.java @@ -1,7 +1,7 @@ package cod.ptac; -public enum CodPTACOperandKind { +public enum OperandKind { REGISTER, IMMEDIATE, LABEL, diff --git a/src/main/java/cod/ptac/Optimizer.java b/src/main/java/cod/ptac/Optimizer.java new file mode 100644 index 00000000..4ca314bb --- /dev/null +++ b/src/main/java/cod/ptac/Optimizer.java @@ -0,0 +1,31 @@ +package cod.ptac; + +import cod.ptac.opt.*; + +import java.util.ArrayList; +import java.util.List; + +public final class Optimizer { + private final List passes; + + public Optimizer() { + this(false); + } + + public Optimizer(boolean enableOptionalLowering) { + this.passes = new ArrayList(); + this.passes.add(new PatternFusion()); + this.passes.add(new RangePropagation()); + this.passes.add(new ConstantFolding()); + this.passes.add(new DeadTempElimination()); + this.passes.add(new PatternLowering(enableOptionalLowering)); + } + + public Unit optimize(Unit unit) { + if (unit == null) return null; + for (Optimization pass : passes) { + pass.apply(unit); + } + return unit; + } +} diff --git a/src/main/java/cod/ptac/CodPTACOptions.java b/src/main/java/cod/ptac/Options.java similarity index 83% rename from src/main/java/cod/ptac/CodPTACOptions.java rename to src/main/java/cod/ptac/Options.java index d46c99fc..1f479bbb 100644 --- a/src/main/java/cod/ptac/CodPTACOptions.java +++ b/src/main/java/cod/ptac/Options.java @@ -1,6 +1,6 @@ package cod.ptac; -public final class CodPTACOptions { +public final class Options { public enum Mode { INTERPRETER, COMPILE_ONLY, @@ -10,12 +10,12 @@ public enum Mode { private final Mode mode; private final boolean fallbackEnabled; - private CodPTACOptions(Mode mode, boolean fallbackEnabled) { + private Options(Mode mode, boolean fallbackEnabled) { this.mode = mode; this.fallbackEnabled = fallbackEnabled; } - public static CodPTACOptions current() { + public static Options current() { String rawMode = firstNonEmpty( System.getProperty("cod.ptac.mode"), System.getenv("COD_PTAC_MODE") @@ -27,11 +27,11 @@ public static CodPTACOptions current() { Mode mode = parseMode(rawMode); boolean fallback = rawFallback == null || !"false".equalsIgnoreCase(rawFallback.trim()); - return new CodPTACOptions(mode, fallback); + return new Options(mode, fallback); } - public static CodPTACOptions compileExecuteWithFallback(boolean fallback) { - return new CodPTACOptions(Mode.COMPILE_EXECUTE, fallback); + public static Options compileExecuteWithFallback(boolean fallback) { + return new Options(Mode.COMPILE_EXECUTE, fallback); } public Mode getMode() { diff --git a/src/main/java/cod/ptac/CodPTACUnit.java b/src/main/java/cod/ptac/Unit.java similarity index 59% rename from src/main/java/cod/ptac/CodPTACUnit.java rename to src/main/java/cod/ptac/Unit.java index dcd9f72f..fb105e54 100644 --- a/src/main/java/cod/ptac/CodPTACUnit.java +++ b/src/main/java/cod/ptac/Unit.java @@ -3,9 +3,9 @@ import java.util.ArrayList; import java.util.List; -public final class CodPTACUnit { +public final class Unit { public String unitName; public String className; public String entryFunction; - public List functions = new ArrayList(); + public List functions = new ArrayList(); } diff --git a/src/main/java/cod/ptac/opt/CodPTACConstantFoldingPass.java b/src/main/java/cod/ptac/opt/CodPTACConstantFoldingPass.java deleted file mode 100644 index be398b36..00000000 --- a/src/main/java/cod/ptac/opt/CodPTACConstantFoldingPass.java +++ /dev/null @@ -1,59 +0,0 @@ -package cod.ptac.opt; - -import cod.ptac.*; - -import java.util.ArrayList; -import java.util.List; - -public final class CodPTACConstantFoldingPass implements CodPTACOptimizationPass { - @Override - public void apply(CodPTACUnit unit) { - if (unit == null || unit.functions == null) return; - - for (CodPTACFunction function : unit.functions) { - if (function == null || function.instructions == null) continue; - List rewritten = new ArrayList(); - - for (CodPTACInstruction inst : function.instructions) { - rewritten.add(fold(inst)); - } - function.instructions = rewritten; - } - } - - private CodPTACInstruction fold(CodPTACInstruction inst) { - if (inst == null || inst.operands == null || inst.operands.size() != 2) return inst; - - if (!isFoldable(inst.opcode)) return inst; - CodPTACOperand left = inst.operands.get(0); - CodPTACOperand right = inst.operands.get(1); - if (left.kind != CodPTACOperandKind.IMMEDIATE || right.kind != CodPTACOperandKind.IMMEDIATE) return inst; - if (!(left.value instanceof Number) || !(right.value instanceof Number)) return inst; - - double a = ((Number) left.value).doubleValue(); - double b = ((Number) right.value).doubleValue(); - Object folded = compute(inst.opcode, a, b); - if (folded == null) return inst; - - List operands = new ArrayList(); - operands.add(CodPTACOperand.immediate(folded)); - return new CodPTACInstruction(CodPTACOpcode.ASSIGN, inst.dest, operands, inst.flags); - } - - private boolean isFoldable(CodPTACOpcode opcode) { - return opcode == CodPTACOpcode.ADD - || opcode == CodPTACOpcode.SUB - || opcode == CodPTACOpcode.MUL - || opcode == CodPTACOpcode.DIV - || opcode == CodPTACOpcode.MOD; - } - - private Object compute(CodPTACOpcode opcode, double a, double b) { - if (opcode == CodPTACOpcode.ADD) return a + b; - if (opcode == CodPTACOpcode.SUB) return a - b; - if (opcode == CodPTACOpcode.MUL) return a * b; - if (opcode == CodPTACOpcode.DIV) return b == 0.0d ? null : a / b; - if (opcode == CodPTACOpcode.MOD) return b == 0.0d ? null : a % b; - return null; - } -} diff --git a/src/main/java/cod/ptac/opt/CodPTACDeadTempEliminationPass.java b/src/main/java/cod/ptac/opt/CodPTACDeadTempEliminationPass.java deleted file mode 100644 index f9c8a713..00000000 --- a/src/main/java/cod/ptac/opt/CodPTACDeadTempEliminationPass.java +++ /dev/null @@ -1,54 +0,0 @@ -package cod.ptac.opt; - -import cod.ptac.*; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public final class CodPTACDeadTempEliminationPass implements CodPTACOptimizationPass { - @Override - public void apply(CodPTACUnit unit) { - if (unit == null || unit.functions == null) return; - - for (CodPTACFunction function : unit.functions) { - if (function == null || function.instructions == null) continue; - Set used = collectUsedRegisters(function.instructions); - List rewritten = new ArrayList(); - for (CodPTACInstruction inst : function.instructions) { - if (canDrop(inst, used)) continue; - rewritten.add(inst); - } - function.instructions = rewritten; - } - } - - private Set collectUsedRegisters(List instructions) { - Set used = new HashSet(); - for (CodPTACInstruction inst : instructions) { - if (inst == null || inst.operands == null) continue; - for (CodPTACOperand operand : inst.operands) { - if (operand != null && operand.kind == CodPTACOperandKind.REGISTER && operand.value instanceof String) { - used.add((String) operand.value); - } - } - } - return used; - } - - private boolean canDrop(CodPTACInstruction inst, Set used) { - if (inst == null || inst.dest == null) return false; - if (!inst.dest.startsWith("t")) return false; - if (hasSideEffect(inst.opcode)) return false; - return !used.contains(inst.dest); - } - - private boolean hasSideEffect(CodPTACOpcode opcode) { - return opcode == CodPTACOpcode.STORE - || opcode == CodPTACOpcode.CALL - || opcode == CodPTACOpcode.SLOT_SET - || opcode == CodPTACOpcode.LAZY_SET - || opcode == CodPTACOpcode.LAZY_COMMIT; - } -} diff --git a/src/main/java/cod/ptac/opt/CodPTACLazyRangePropagationPass.java b/src/main/java/cod/ptac/opt/CodPTACLazyRangePropagationPass.java deleted file mode 100644 index 8a6ebfea..00000000 --- a/src/main/java/cod/ptac/opt/CodPTACLazyRangePropagationPass.java +++ /dev/null @@ -1,41 +0,0 @@ -package cod.ptac.opt; - -import cod.ptac.*; - -import java.util.ArrayList; -import java.util.EnumSet; -import java.util.List; - -public final class CodPTACLazyRangePropagationPass implements CodPTACOptimizationPass { - @Override - public void apply(CodPTACUnit unit) { - if (unit == null || unit.functions == null) return; - - for (CodPTACFunction function : unit.functions) { - if (function == null || function.instructions == null) continue; - List rewritten = new ArrayList(); - - for (CodPTACInstruction inst : function.instructions) { - rewritten.add(markLazyIfNeeded(inst)); - } - - function.instructions = rewritten; - } - } - - private CodPTACInstruction markLazyIfNeeded(CodPTACInstruction inst) { - if (inst == null) return null; - if (inst.opcode != CodPTACOpcode.RANGE - && inst.opcode != CodPTACOpcode.RANGE_Q - && inst.opcode != CodPTACOpcode.RANGE_S - && inst.opcode != CodPTACOpcode.RANGE_L - && inst.opcode != CodPTACOpcode.RANGE_LS) { - return inst; - } - EnumSet flags = inst.flags != null - ? EnumSet.copyOf(inst.flags) - : EnumSet.noneOf(CodPTACFlag.class); - flags.add(CodPTACFlag.LAZY); - return new CodPTACInstruction(inst.opcode, inst.dest, inst.operands, flags); - } -} diff --git a/src/main/java/cod/ptac/opt/CodPTACOptimizationPass.java b/src/main/java/cod/ptac/opt/CodPTACOptimizationPass.java deleted file mode 100644 index f5e7a148..00000000 --- a/src/main/java/cod/ptac/opt/CodPTACOptimizationPass.java +++ /dev/null @@ -1,7 +0,0 @@ -package cod.ptac.opt; - -import cod.ptac.CodPTACUnit; - -public interface CodPTACOptimizationPass { - void apply(CodPTACUnit unit); -} diff --git a/src/main/java/cod/ptac/opt/CodPTACOptionalPatternLoweringPass.java b/src/main/java/cod/ptac/opt/CodPTACOptionalPatternLoweringPass.java deleted file mode 100644 index 619fdf3d..00000000 --- a/src/main/java/cod/ptac/opt/CodPTACOptionalPatternLoweringPass.java +++ /dev/null @@ -1,43 +0,0 @@ -package cod.ptac.opt; - -import cod.ptac.*; - -import java.util.ArrayList; -import java.util.List; - -public final class CodPTACOptionalPatternLoweringPass implements CodPTACOptimizationPass { - private final boolean enabled; - - public CodPTACOptionalPatternLoweringPass(boolean enabled) { - this.enabled = enabled; - } - - @Override - public void apply(CodPTACUnit unit) { - if (!enabled || unit == null || unit.functions == null) return; - - for (CodPTACFunction function : unit.functions) { - if (function == null || function.instructions == null) continue; - - List rewritten = new ArrayList(); - for (CodPTACInstruction inst : function.instructions) { - if (inst == null) continue; - if (isUnsupportedPattern(inst.opcode)) { - List operands = new ArrayList(); - operands.add(CodPTACOperand.function(inst.opcode.name())); - rewritten.add(new CodPTACInstruction(CodPTACOpcode.CALL, inst.dest, operands, inst.flags)); - } else { - rewritten.add(inst); - } - } - function.instructions = rewritten; - } - } - - private boolean isUnsupportedPattern(CodPTACOpcode opcode) { - return opcode == CodPTACOpcode.ZIP - || opcode == CodPTACOpcode.SCAN - || opcode == CodPTACOpcode.FORMULA_RECUR - || opcode == CodPTACOpcode.FORMULA_FUSE; - } -} diff --git a/src/main/java/cod/ptac/opt/ConstantFolding.java b/src/main/java/cod/ptac/opt/ConstantFolding.java new file mode 100644 index 00000000..a80a5232 --- /dev/null +++ b/src/main/java/cod/ptac/opt/ConstantFolding.java @@ -0,0 +1,59 @@ +package cod.ptac.opt; + +import cod.ptac.*; + +import java.util.ArrayList; +import java.util.List; + +public final class ConstantFolding implements Optimization { + @Override + public void apply(Unit unit) { + if (unit == null || unit.functions == null) return; + + for (Function function : unit.functions) { + if (function == null || function.instructions == null) continue; + List rewritten = new ArrayList(); + + for (Instruction inst : function.instructions) { + rewritten.add(fold(inst)); + } + function.instructions = rewritten; + } + } + + private Instruction fold(Instruction inst) { + if (inst == null || inst.operands == null || inst.operands.size() != 2) return inst; + + if (!isFoldable(inst.opcode)) return inst; + Operand left = inst.operands.get(0); + Operand right = inst.operands.get(1); + if (left.kind != OperandKind.IMMEDIATE || right.kind != OperandKind.IMMEDIATE) return inst; + if (!(left.value instanceof Number) || !(right.value instanceof Number)) return inst; + + double a = ((Number) left.value).doubleValue(); + double b = ((Number) right.value).doubleValue(); + Object folded = compute(inst.opcode, a, b); + if (folded == null) return inst; + + List operands = new ArrayList(); + operands.add(Operand.immediate(folded)); + return new Instruction(Opcode.ASSIGN, inst.dest, operands, inst.flags); + } + + private boolean isFoldable(Opcode opcode) { + return opcode == Opcode.ADD + || opcode == Opcode.SUB + || opcode == Opcode.MUL + || opcode == Opcode.DIV + || opcode == Opcode.MOD; + } + + private Object compute(Opcode opcode, double a, double b) { + if (opcode == Opcode.ADD) return a + b; + if (opcode == Opcode.SUB) return a - b; + if (opcode == Opcode.MUL) return a * b; + if (opcode == Opcode.DIV) return b == 0.0d ? null : a / b; + if (opcode == Opcode.MOD) return b == 0.0d ? null : a % b; + return null; + } +} diff --git a/src/main/java/cod/ptac/opt/DeadTempElimination.java b/src/main/java/cod/ptac/opt/DeadTempElimination.java new file mode 100644 index 00000000..49272333 --- /dev/null +++ b/src/main/java/cod/ptac/opt/DeadTempElimination.java @@ -0,0 +1,54 @@ +package cod.ptac.opt; + +import cod.ptac.*; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public final class DeadTempElimination implements Optimization { + @Override + public void apply(Unit unit) { + if (unit == null || unit.functions == null) return; + + for (Function function : unit.functions) { + if (function == null || function.instructions == null) continue; + Set used = collectUsedRegisters(function.instructions); + List rewritten = new ArrayList(); + for (Instruction inst : function.instructions) { + if (canDrop(inst, used)) continue; + rewritten.add(inst); + } + function.instructions = rewritten; + } + } + + private Set collectUsedRegisters(List instructions) { + Set used = new HashSet(); + for (Instruction inst : instructions) { + if (inst == null || inst.operands == null) continue; + for (Operand operand : inst.operands) { + if (operand != null && operand.kind == OperandKind.REGISTER && operand.value instanceof String) { + used.add((String) operand.value); + } + } + } + return used; + } + + private boolean canDrop(Instruction inst, Set used) { + if (inst == null || inst.dest == null) return false; + if (!inst.dest.startsWith("t")) return false; + if (hasSideEffect(inst.opcode)) return false; + return !used.contains(inst.dest); + } + + private boolean hasSideEffect(Opcode opcode) { + return opcode == Opcode.STORE + || opcode == Opcode.CALL + || opcode == Opcode.SLOT_SET + || opcode == Opcode.LAZY_SET + || opcode == Opcode.LAZY_COMMIT; + } +} diff --git a/src/main/java/cod/ptac/opt/Optimization.java b/src/main/java/cod/ptac/opt/Optimization.java new file mode 100644 index 00000000..7a164d08 --- /dev/null +++ b/src/main/java/cod/ptac/opt/Optimization.java @@ -0,0 +1,7 @@ +package cod.ptac.opt; + +import cod.ptac.Unit; + +public interface Optimization { + void apply(Unit unit); +} diff --git a/src/main/java/cod/ptac/opt/CodPTACPatternFusionPass.java b/src/main/java/cod/ptac/opt/PatternFusion.java similarity index 50% rename from src/main/java/cod/ptac/opt/CodPTACPatternFusionPass.java rename to src/main/java/cod/ptac/opt/PatternFusion.java index 3da52459..a038bd0d 100644 --- a/src/main/java/cod/ptac/opt/CodPTACPatternFusionPass.java +++ b/src/main/java/cod/ptac/opt/PatternFusion.java @@ -5,26 +5,26 @@ import java.util.ArrayList; import java.util.List; -public final class CodPTACPatternFusionPass implements CodPTACOptimizationPass { +public final class PatternFusion implements Optimization { @Override - public void apply(CodPTACUnit unit) { + public void apply(Unit unit) { if (unit == null || unit.functions == null) return; - for (CodPTACFunction function : unit.functions) { + for (Function function : unit.functions) { if (function == null || function.instructions == null) continue; - List rewritten = new ArrayList(); + List rewritten = new ArrayList(); for (int i = 0; i < function.instructions.size(); i++) { - CodPTACInstruction current = function.instructions.get(i); - CodPTACInstruction next = i + 1 < function.instructions.size() + Instruction current = function.instructions.get(i); + Instruction next = i + 1 < function.instructions.size() ? function.instructions.get(i + 1) : null; if (canFuseFilterMap(current, next)) { - List fusedOps = new ArrayList(); + List fusedOps = new ArrayList(); fusedOps.add(current.operands.get(0)); // source fusedOps.add(current.operands.get(1)); // filter lambda fusedOps.add(next.operands.get(1)); // map lambda - rewritten.add(new CodPTACInstruction(CodPTACOpcode.FILTER_MAP, next.dest, fusedOps, next.flags)); + rewritten.add(new Instruction(Opcode.FILTER_MAP, next.dest, fusedOps, next.flags)); i++; continue; } @@ -35,13 +35,13 @@ public void apply(CodPTACUnit unit) { } } - private boolean canFuseFilterMap(CodPTACInstruction filter, CodPTACInstruction map) { + private boolean canFuseFilterMap(Instruction filter, Instruction map) { if (filter == null || map == null) return false; - if (filter.opcode != CodPTACOpcode.FILTER) return false; - if (map.opcode != CodPTACOpcode.MAP) return false; + if (filter.opcode != Opcode.FILTER) return false; + if (map.opcode != Opcode.MAP) return false; if (filter.dest == null) return false; if (map.operands == null || map.operands.isEmpty()) return false; - CodPTACOperand mapSource = map.operands.get(0); - return mapSource.kind == CodPTACOperandKind.REGISTER && filter.dest.equals(mapSource.value); + Operand mapSource = map.operands.get(0); + return mapSource.kind == OperandKind.REGISTER && filter.dest.equals(mapSource.value); } } diff --git a/src/main/java/cod/ptac/opt/PatternLowering.java b/src/main/java/cod/ptac/opt/PatternLowering.java new file mode 100644 index 00000000..7f9f5cf9 --- /dev/null +++ b/src/main/java/cod/ptac/opt/PatternLowering.java @@ -0,0 +1,43 @@ +package cod.ptac.opt; + +import cod.ptac.*; + +import java.util.ArrayList; +import java.util.List; + +public final class PatternLowering implements Optimization { + private final boolean enabled; + + public PatternLowering(boolean enabled) { + this.enabled = enabled; + } + + @Override + public void apply(Unit unit) { + if (!enabled || unit == null || unit.functions == null) return; + + for (Function function : unit.functions) { + if (function == null || function.instructions == null) continue; + + List rewritten = new ArrayList(); + for (Instruction inst : function.instructions) { + if (inst == null) continue; + if (isUnsupportedPattern(inst.opcode)) { + List operands = new ArrayList(); + operands.add(Operand.function(inst.opcode.name())); + rewritten.add(new Instruction(Opcode.CALL, inst.dest, operands, inst.flags)); + } else { + rewritten.add(inst); + } + } + function.instructions = rewritten; + } + } + + private boolean isUnsupportedPattern(Opcode opcode) { + return opcode == Opcode.ZIP + || opcode == Opcode.SCAN + || opcode == Opcode.FORMULA_RECUR + || opcode == Opcode.FORMULA_FUSE; + } +} diff --git a/src/main/java/cod/ptac/opt/RangePropagation.java b/src/main/java/cod/ptac/opt/RangePropagation.java new file mode 100644 index 00000000..d88d388b --- /dev/null +++ b/src/main/java/cod/ptac/opt/RangePropagation.java @@ -0,0 +1,41 @@ +package cod.ptac.opt; + +import cod.ptac.*; + +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; + +public final class RangePropagation implements Optimization { + @Override + public void apply(Unit unit) { + if (unit == null || unit.functions == null) return; + + for (Function function : unit.functions) { + if (function == null || function.instructions == null) continue; + List rewritten = new ArrayList(); + + for (Instruction inst : function.instructions) { + rewritten.add(markLazyIfNeeded(inst)); + } + + function.instructions = rewritten; + } + } + + private Instruction markLazyIfNeeded(Instruction inst) { + if (inst == null) return null; + if (inst.opcode != Opcode.RANGE + && inst.opcode != Opcode.RANGE_Q + && inst.opcode != Opcode.RANGE_S + && inst.opcode != Opcode.RANGE_L + && inst.opcode != Opcode.RANGE_LS) { + return inst; + } + EnumSet flags = inst.flags != null + ? EnumSet.copyOf(inst.flags) + : EnumSet.noneOf(Flag.class); + flags.add(Flag.LAZY); + return new Instruction(inst.opcode, inst.dest, inst.operands, flags); + } +} diff --git a/src/main/java/cod/runner/CommandRunner.java b/src/main/java/cod/runner/CommandRunner.java index ba07469d..d6e89ed3 100644 --- a/src/main/java/cod/runner/CommandRunner.java +++ b/src/main/java/cod/runner/CommandRunner.java @@ -6,21 +6,21 @@ import cod.interpreter.Interpreter; import cod.interpreter.Index; import cod.ir.IRManager; -import cod.ptac.CodPTACArtifact; -import cod.ptac.CodPTACExecutor; -import cod.ptac.CodPTACOptions; +import cod.ptac.Artifact; +import cod.ptac.Executor; +import cod.ptac.Options; public class CommandRunner extends BaseRunner { private final Interpreter interpreter; private IRManager irManager; - private final CodPTACOptions ptacOptions; + private final Options ptacOptions; private static final String NAME = "COMMAND"; public CommandRunner() { this.interpreter = new Interpreter(); - this.ptacOptions = CodPTACOptions.current(); + this.ptacOptions = Options.current(); } @Override @@ -191,14 +191,14 @@ private void executeInterpretation(Program ast) { if (ptacOptions.isCompileExecuteEnabled() && irManager != null && ast != null && ast.unit != null) { Type entryType = findMainType(ast); if (entryType != null) { - CodPTACArtifact artifact = irManager.loadArtifact(ast.unit.name, entryType.name); + Artifact artifact = irManager.loadArtifact(ast.unit.name, entryType.name); if (artifact == null) { irManager.save(ast.unit.name, entryType); artifact = irManager.loadArtifact(ast.unit.name, entryType.name); } if (artifact != null) { DebugSystem.info(NAME + LOG_TAG, "Executing using CodP-TAC executor"); - new CodPTACExecutor(ptacOptions).execute(artifact, interpreter); + new Executor(ptacOptions).execute(artifact, interpreter); DebugSystem.info(NAME + LOG_TAG, "Program interpretation completed"); return; } diff --git a/src/main/java/cod/runner/IRValidationRunner.java b/src/main/java/cod/runner/IRValidationRunner.java index 106e9d1f..79deedb6 100644 --- a/src/main/java/cod/runner/IRValidationRunner.java +++ b/src/main/java/cod/runner/IRValidationRunner.java @@ -5,7 +5,7 @@ import cod.ir.IRReader; import cod.ir.IRWriter; import cod.interpreter.Interpreter; -import cod.ptac.CodPTACArtifact; +import cod.ptac.Artifact; import cod.semantic.ImportResolver; import java.io.File; @@ -40,7 +40,7 @@ public void run(String[] args) throws Exception { IRWriter writer = new IRWriter(); IRReader reader = new IRReader(); writer.write(tmp, original); - CodPTACArtifact artifact = reader.readArtifact(tmp); + Artifact artifact = reader.readArtifact(tmp); Type loaded = artifact != null ? artifact.typeSnapshot : null; assertTrue(loaded != null, "Loaded type is null"); @@ -65,7 +65,7 @@ public void run(String[] args) throws Exception { Type managerLoaded = manager.load(program.unit.name, original.name); assertTrue(managerLoaded != null, "IRManager failed to load saved class"); assertTrue(equalsSafe(original.name, managerLoaded.name), "IRManager loaded wrong class"); - CodPTACArtifact managerArtifact = manager.loadArtifact(program.unit.name, original.name); + Artifact managerArtifact = manager.loadArtifact(program.unit.name, original.name); assertTrue(managerArtifact != null, "IRManager failed to load saved CodP-TAC artifact"); assertTrue(managerArtifact.unit != null, "CodP-TAC unit missing from artifact"); } @@ -94,7 +94,7 @@ private void validateInternalImportIRPath() throws Exception { IRManager manager = new IRManager(codProjectRoot); Type internalType = internalProgram.unit.types.get(0); manager.save(internalProgram.unit.name, internalType); - CodPTACArtifact artifact = manager.loadArtifact(internalProgram.unit.name, internalType.name); + Artifact artifact = manager.loadArtifact(internalProgram.unit.name, internalType.name); assertTrue(artifact != null, "Failed to save/load internal CodP-TAC artifact"); Interpreter internalMultiRangeInterpreter = new Interpreter(); @@ -107,7 +107,7 @@ private void validateInternalImportIRPath() throws Exception { Type internalMultiRangeType = internalMultiRangeProgram.unit.types.get(0); manager.save(internalMultiRangeProgram.unit.name, internalMultiRangeType); - CodPTACArtifact multiArtifact = manager.loadArtifact(internalMultiRangeProgram.unit.name, internalMultiRangeType.name); + Artifact multiArtifact = manager.loadArtifact(internalMultiRangeProgram.unit.name, internalMultiRangeType.name); assertTrue(multiArtifact != null, "Failed to save/load internal multi-range CodP-TAC artifact"); ImportResolver resolver = new ImportResolver(); diff --git a/src/main/java/cod/runner/CodPTACParityRunner.java b/src/main/java/cod/runner/ParityRunner.java similarity index 96% rename from src/main/java/cod/runner/CodPTACParityRunner.java rename to src/main/java/cod/runner/ParityRunner.java index a6fd8eb1..b83146a6 100644 --- a/src/main/java/cod/runner/CodPTACParityRunner.java +++ b/src/main/java/cod/runner/ParityRunner.java @@ -6,9 +6,9 @@ import cod.interpreter.Index; import cod.interpreter.Interpreter; import cod.ir.IRManager; -import cod.ptac.CodPTACArtifact; -import cod.ptac.CodPTACExecutor; -import cod.ptac.CodPTACOptions; +import cod.ptac.Artifact; +import cod.ptac.Executor; +import cod.ptac.Options; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FilterInputStream; @@ -21,7 +21,7 @@ import java.util.List; import java.util.Scanner; -public final class CodPTACParityRunner extends BaseRunner { +public final class ParityRunner extends BaseRunner { private static final String NUMBER_REGEX_PATTERN = "[-+]?\\d+(?:\\.\\d+)?(?:[eE][-+]?\\d+)?"; private static final int DEFAULT_INPUT_LINE_COUNT = 10; private static final String DEFAULT_INPUT = buildDefaultInput(DEFAULT_INPUT_LINE_COUNT); @@ -99,7 +99,7 @@ public void run(String[] args) throws Exception { if (files.isEmpty()) { System.out.println("No .cod files found."); - System.out.println("Usage: CodPTACParityRunner or "); + System.out.println("Usage: ParityRunner or "); return; } @@ -224,7 +224,7 @@ private String runCodPTACPath(String file) throws Exception { } manager.save(unitName, entryType); - CodPTACArtifact artifact = manager.loadArtifact(unitName, entryType.name); + Artifact artifact = manager.loadArtifact(unitName, entryType.name); if (artifact == null) { throw new Exception("Failed to load CodP-TAC artifact for: " + file); @@ -282,7 +282,7 @@ private String captureOutput(Interpreter interpreter, Program ast) { } } - private String captureOutputPTAC(CodPTACArtifact artifact, Interpreter interpreter) { + private String captureOutputPTAC(Artifact artifact, Interpreter interpreter) { PrintStream oldOut = System.out; PrintStream oldErr = System.err; java.io.InputStream oldIn = System.in; @@ -295,7 +295,7 @@ private String captureOutputPTAC(CodPTACArtifact artifact, Interpreter interpret System.setOut(outReplacement); System.setErr(errReplacement); System.setIn(new ByteArrayInputStream(DEFAULT_INPUT.getBytes(StandardCharsets.UTF_8))); - new CodPTACExecutor(CodPTACOptions.compileExecuteWithFallback(true)) + new Executor(Options.compileExecuteWithFallback(true)) .execute(artifact, interpreter); outReplacement.flush(); errReplacement.flush(); @@ -375,7 +375,7 @@ private static final class PathResult { } public static void main(String[] args) { - CodPTACParityRunner runner = new CodPTACParityRunner(); + ParityRunner runner = new ParityRunner(); try { runner.run(args); } catch (Exception e) { diff --git a/src/main/java/cod/runner/TestRunner.java b/src/main/java/cod/runner/TestRunner.java index 3347c821..f46a57ff 100644 --- a/src/main/java/cod/runner/TestRunner.java +++ b/src/main/java/cod/runner/TestRunner.java @@ -6,9 +6,9 @@ import cod.debug.Linter; import cod.interpreter.Index; import cod.ir.IRManager; -import cod.ptac.CodPTACArtifact; -import cod.ptac.CodPTACExecutor; -import cod.ptac.CodPTACOptions; +import cod.ptac.Artifact; +import cod.ptac.Executor; +import cod.ptac.Options; import java.io.File; import java.io.FilterInputStream; @@ -36,11 +36,11 @@ public class TestRunner extends BaseRunner { private final Interpreter interpreter; private IRManager irManager; - private final CodPTACOptions ptacOptions; + private final Options ptacOptions; public TestRunner() { this.interpreter = new Interpreter(); - this.ptacOptions = CodPTACOptions.current(); + this.ptacOptions = Options.current(); } @Override @@ -273,14 +273,14 @@ private void executeWithManualInterpreter(Program ast) { if (ptacOptions.isCompileExecuteEnabled() && irManager != null && ast != null && ast.unit != null) { Type entryType = findMainType(ast); if (entryType != null) { - CodPTACArtifact artifact = irManager.loadArtifact(ast.unit.name, entryType.name); + Artifact artifact = irManager.loadArtifact(ast.unit.name, entryType.name); if (artifact == null) { irManager.save(ast.unit.name, entryType); artifact = irManager.loadArtifact(ast.unit.name, entryType.name); } if (artifact != null) { DebugSystem.info(NAME + LOG_TAG, "Executing using CodP-TAC executor"); - new CodPTACExecutor(ptacOptions).execute(artifact, interpreter); + new Executor(ptacOptions).execute(artifact, interpreter); double duration = DebugSystem.stopTimer("interpretation"); DebugSystem.info(NAME + LOG_TAG, String.format("Interpretation completed in %.3f ms", duration)); return; diff --git a/src/main/java/cod/semantic/ImportResolver.java b/src/main/java/cod/semantic/ImportResolver.java index a8c9dde7..b298bdca 100644 --- a/src/main/java/cod/semantic/ImportResolver.java +++ b/src/main/java/cod/semantic/ImportResolver.java @@ -9,7 +9,7 @@ import cod.debug.DebugSystem; import cod.interpreter.Index; import cod.ir.IRManager; -import cod.ptac.CodPTACArtifact; +import cod.ptac.Artifact; import java.util.*; import java.io.*; @@ -61,7 +61,7 @@ public class ImportResolver { // Cache for loaded TypeNodes (bytecode or parsed) private Map loadedTypes = createBoundedMap(LOADED_TYPES_CACHE_LIMIT); - private Map loadedArtifacts = createBoundedMap(LOADED_TYPES_CACHE_LIMIT); + private Map loadedArtifacts = createBoundedMap(LOADED_TYPES_CACHE_LIMIT); // Filesystem result cache private Map fileCache = createBoundedMap(FILE_CACHE_LIMIT); @@ -733,7 +733,7 @@ public Type resolveImport(String importName) throws Exception { // ========== TRY CODE-P-TAC ARTIFACT FIRST (FAST PATH) ========== if (irManager != null) { - CodPTACArtifact artifact = irManager.loadArtifact(unitName, className); + Artifact artifact = irManager.loadArtifact(unitName, className); if (artifact != null) { bytecodeCacheHits++; DebugSystem.debug("IR", "Loaded " + className + " CodP-TAC artifact from .codb (cache hit)"); From 0b57609b14fe71fe3ca3fa6c82f0cc9ef48bc3d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 04:11:53 +0000 Subject: [PATCH 8/9] Plan restore CodPTACParityRunner naming Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/a3f306c2-e83d-4743-925f-966729ea845c Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- source_.jar | Bin 359503 -> 358740 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/source_.jar b/source_.jar index e33189fa3a14e85bb58b52a3d9338475f851fe30..d45e76f3cabb3d59b157003837e82225b921ae58 100644 GIT binary patch delta 77163 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

N4qz!UQ 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

i%-lY9zUBu=r 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 TBFY<(#q4EKB+`B!1S0%D@Z-}N From 571711d41f35fd75dc9e8a38f0c1088ced1983ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Apr 2026 04:12:04 +0000 Subject: [PATCH 9/9] Restore CodPTACParityRunner class name Agent-Logs-Url: https://github.com/DanexCodr/Coderive/sessions/a3f306c2-e83d-4743-925f-966729ea845c Co-authored-by: DanexCodr <216312766+DanexCodr@users.noreply.github.com> --- .../runner/{ParityRunner.java => CodPTACParityRunner.java} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/main/java/cod/runner/{ParityRunner.java => CodPTACParityRunner.java} (98%) diff --git a/src/main/java/cod/runner/ParityRunner.java b/src/main/java/cod/runner/CodPTACParityRunner.java similarity index 98% rename from src/main/java/cod/runner/ParityRunner.java rename to src/main/java/cod/runner/CodPTACParityRunner.java index b83146a6..8ac91370 100644 --- a/src/main/java/cod/runner/ParityRunner.java +++ b/src/main/java/cod/runner/CodPTACParityRunner.java @@ -21,7 +21,7 @@ import java.util.List; import java.util.Scanner; -public final class ParityRunner extends BaseRunner { +public final class CodPTACParityRunner extends BaseRunner { private static final String NUMBER_REGEX_PATTERN = "[-+]?\\d+(?:\\.\\d+)?(?:[eE][-+]?\\d+)?"; private static final int DEFAULT_INPUT_LINE_COUNT = 10; private static final String DEFAULT_INPUT = buildDefaultInput(DEFAULT_INPUT_LINE_COUNT); @@ -99,7 +99,7 @@ public void run(String[] args) throws Exception { if (files.isEmpty()) { System.out.println("No .cod files found."); - System.out.println("Usage: ParityRunner or "); + System.out.println("Usage: CodPTACParityRunner or "); return; } @@ -375,7 +375,7 @@ private static final class PathResult { } public static void main(String[] args) { - ParityRunner runner = new ParityRunner(); + CodPTACParityRunner runner = new CodPTACParityRunner(); try { runner.run(args); } catch (Exception e) {