package com.sap.finex.interpreter; import structure.Field; import structure.FinexClass; import structure.Type; import behavior.expressions.Alias; import behavior.expressions.Expression; import behavior.functions.SignatureImplementation; import com.sap.runlet.abstractinterpreter.StackFrame; import com.sap.runlet.abstractinterpreter.objects.RunletObject; public class FinexStackFrame extends StackFrame<Field, Type, FinexClass, SignatureImplementation> { /** * The <tt>this</tt> pointer of the stack frame in element 0; the array is <tt>null</tt> * if this frame is not for a method call but, e.g., a function call, or if this frame is for a nested * block. This is different from a valid array holding the value <tt>null</tt> in element 0 * which encodes <tt>this==null</tt>. */ private RunletObject<Field, Type, FinexClass>[] implicitContext; /** * The set of alias values keyed by the expressions and their result objects for which the * alias value is in scope. */ private AliasValues aliasValues; /** * Creates a new stack frame for a method or function invocation with no parent stack * for name resolution. The frame initializes a new, clean {@link AliasValues} map. */ public FinexStackFrame() { super(); aliasValues = new AliasValues(); } /** * Create a stack frame that has <tt>parent</tt> as its parent stack frame. This constructor * is expected to be used when a nested block inside a method or function execution begins * to execute.<p> * * The parent's alias values map is used for the new frame as well. */ public FinexStackFrame(FinexStackFrame parent) { super(parent); this.aliasValues = parent.getAliasValues(); } @Override public FinexStackFrame getScopeParent() { return (FinexStackFrame) super.getScopeParent(); } public RunletObject<Field, Type, FinexClass> getImplicitContext() { RunletObject<Field, Type, FinexClass> result; if (implicitContext == null) { if (getScopeParent() != null) { result = getScopeParent().getImplicitContext(); } else { result = null; } } else { result = implicitContext[0]; } return result; } @SuppressWarnings("unchecked") public void setImplicitContext(RunletObject<Field, Type, FinexClass> implicitContext) { this.implicitContext = (RunletObject<Field, Type, FinexClass>[]) new RunletObject<?, ?, ?>[] { implicitContext }; } public AliasValues getAliasValues() { return aliasValues; } /** * Finds all aliases from the {@link #getAliasValues() alias values map} that have been computed by * the evaluation of the expression <tt>e</tt> and adds the values they had for the particular * result object <tt>o</tt> of expression <tt>e</tt> as entries to this stack frame. */ public void enterCurrentAliasValues(Expression e, RunletObject<Field, Type, FinexClass> resultOfE) { for (Alias a : getAliasValues().getAllAliasesDefinedFor(e, resultOfE)) { setOrEnterValue(a.getName(), getAliasValues().getAliasValue(e, resultOfE, a)); } } }