private void executeInvoke(Datastructures.Dag<ProgramRepresentation.DagElementData> dag, InterpretationState state) { Datastructures.Variadic invokeResult; EnumInvokeDispatcherCallResult callResult; int currentDagElementIndex; Datastructures.Dag<ProgramRepresentation.DagElementData>.Element currentDagElement; InterpretationState.ScopeLevel topScope; currentDagElementIndex = state.scopeLevels[state.scopeLevels.Count-1].dagElementIndex; currentDagElement = dag.elements[currentDagElementIndex]; topScope = state.scopeLevels[state.currentScopeLevel]; if( topScope.invokeState == InterpretationState.ScopeLevel.EnumInvokeState.INITIAL ) { topScope.invokeState = InterpretationState.ScopeLevel.EnumInvokeState.RESOLVEPARAMETERS; topScope.invokeResolvedParameters = new List<Datastructures.Variadic>(); return; } else if( topScope.invokeState == InterpretationState.ScopeLevel.EnumInvokeState.RESOLVEPARAMETERS ) { int dagIndexOfArrayWithParameters; List<int> dagIndicesOfArrayContentForParameters; // retrieve and try to resolve remaining parameters dagIndexOfArrayWithParameters = currentDagElement.childIndices[1]; dagIndicesOfArrayContentForParameters = dag.elements[dagIndexOfArrayWithParameters].childIndices; for(;;) { int dagIndexOfParameter; // check if we are done with the resolving System.Diagnostics.Debug.Assert(topScope.invokeResolveParametersIndex <= dagIndicesOfArrayContentForParameters.Count); if( topScope.invokeResolveParametersIndex == dagIndicesOfArrayContentForParameters.Count ) { topScope.invokeState = InterpretationState.ScopeLevel.EnumInvokeState.INVOKE; return; } // check if the current parameter is a scope // if it is the case, we open the scope and transfer control // if its not the case we can try to resolve the parameter as usual and continue dagIndexOfParameter = dagIndicesOfArrayContentForParameters[topScope.invokeResolveParametersIndex]; if( dag.elements[dagIndexOfParameter].content.type == DagElementData.EnumType.FSCOPE ) { InterpretationState.ScopeLevel createdScopeLevel; topScope.invokeResolveParametersIndex++; topScope.invokeState = InterpretationState.ScopeLevel.EnumInvokeState.SCOPEFORPARAMETERWASINVOKED; // build new scope createdScopeLevel = new InterpretationState.ScopeLevel(); state.scopeLevels.Add(createdScopeLevel); createdScopeLevel.dagElementIndex = dagIndexOfParameter; // do this so the next step executes the scope state.currentScopeLevel++; return; } else { Datastructures.Variadic currentResolvedParameter; currentResolvedParameter = resolveVariableAndConstant(dag, dagIndexOfParameter, state); topScope.invokeResolvedParameters.Add(currentResolvedParameter); topScope.invokeResolveParametersIndex++; } } } else if( topScope.invokeState == InterpretationState.ScopeLevel.EnumInvokeState.SCOPEFORPARAMETERWASINVOKED ) { Datastructures.Variadic parameterFromScope; // the scope for an parameter was invoked and the result is on the stack // * get the result from the stack // * add it to the parameters // * go back in the state // NOTE< we just move the reference > parameterFromScope = topScope.calleeResult; topScope.invokeResolvedParameters.Add(parameterFromScope); topScope.invokeState = InterpretationState.ScopeLevel.EnumInvokeState.RESOLVEPARAMETERS; return; } else if( topScope.invokeState == InterpretationState.ScopeLevel.EnumInvokeState.INVOKE ) { int dagIndexOfArrayWithPath; List<int> dagIndicesOfArrayContentForPath; List<string> pathOfInvokedProgram; bool isInterpretableInvoke; int dagIndexOfInvokedScope; List<string> invokeVariableNames; // build the path of the invoked program dagIndexOfArrayWithPath = currentDagElement.childIndices[0]; if (dag.elements[dagIndexOfArrayWithPath].content.type != DagElementData.EnumType.FARRAY) { throw new Exception("Invoke parameter [0] was not an Array as expected!"); } // grab the indices of the array dagIndicesOfArrayContentForPath = dag.elements[dagIndexOfArrayWithPath].childIndices; // and put them into the function which executes building stuff for the path for the invoke pathOfInvokedProgram = getPathOfInvokeScopeInstruction(dag, dagIndicesOfArrayContentForPath, state); // try to lookup the path inside the list with all interpretable programs (which can be invoked) invokeVariableNames = new List<string>(); lookupInvokePath(state, pathOfInvokedProgram, out isInterpretableInvoke, out dagIndexOfInvokedScope, invokeVariableNames); if (isInterpretableInvoke) { InterpretationState.ScopeLevel createdScopeLevel; int variableI; // set state topScope.invokeState = InterpretationState.ScopeLevel.EnumInvokeState.PROGRAMINVOKED; // check if number of parameter is correct if (topScope.invokeResolvedParameters.Count != invokeVariableNames.Count) { throw new Exception("invoke parameter count is invalid!"); } // build new scope createdScopeLevel = new InterpretationState.ScopeLevel(); state.scopeLevels.Add(createdScopeLevel); createdScopeLevel.dagElementIndex = dagIndexOfInvokedScope; // set variables for (variableI = 0; variableI < invokeVariableNames.Count; variableI++) { InterpretationState.ScopeLevel.Variable createdVariable; createdVariable = new InterpretationState.ScopeLevel.Variable(); createdVariable.name = invokeVariableNames[variableI]; createdVariable.value = topScope.invokeResolvedParameters[variableI]; createdScopeLevel.variables.Add(createdVariable); } // do this so the next step executes the scope state.currentScopeLevel++; return; } else { // dispatch invoke invokeDispatcher.dispatchInvokeStart(pathOfInvokedProgram, topScope.invokeResolvedParameters, state.scopeLevels, out invokeResult, out callResult); // TODO< maybe logic for searching of callee > System.Diagnostics.Debug.Assert(state.currentScopeLevel > 0); // if we are done // return result to caller (in state stack) // if the call failed we return false if (callResult == EnumInvokeDispatcherCallResult.DONE) { state.scopeLevels[state.currentScopeLevel - 1].calleeResult = invokeResult; // remove scope of call state.scopeLevels.RemoveAt(state.scopeLevels.Count - 1); state.currentScopeLevel--; return; } else if (callResult == EnumInvokeDispatcherCallResult.PATHINVALID) { state.scopeLevels[state.currentScopeLevel - 1].calleeResult = new Datastructures.Variadic(Datastructures.Variadic.EnumType.BOOL); state.scopeLevels[state.currentScopeLevel - 1].calleeResult.valueBool = false; // remove scope of call state.scopeLevels.RemoveAt(state.scopeLevels.Count - 1); state.currentScopeLevel--; return; } else if (callResult == EnumInvokeDispatcherCallResult.SUCCEEDINGINTERNAL) { System.Diagnostics.Debug.Assert(false, "SUCCEEDINGINTERNAL not supported!"); throw new Exception("Internal Error!"); } return; } } else if( topScope.invokeState == InterpretationState.ScopeLevel.EnumInvokeState.PROGRAMINVOKED ) { // TODO< maybe logic for searching of callee > System.Diagnostics.Debug.Assert(state.currentScopeLevel > 0); state.scopeLevels[state.currentScopeLevel - 1].calleeResult = state.scopeLevels[state.currentScopeLevel].calleeResult; // remove scope of call state.scopeLevels.RemoveAt(state.scopeLevels.Count - 1); state.currentScopeLevel--; return; } else { throw new Exception("Internal Error!"); } throw new Exception("unreachable!"); }
private static void setVariableInScope( string variablename, EnumOverwriteExistingVariable overwriteExistingVariable, Datastructures.Variadic value, InterpretationState.ScopeLevel topScope ) { int foundVariableIndex; int i; foundVariableIndex = -1; for( i = 0; i < topScope.variables.Count; i++ ) { if( topScope.variables[i].name == variablename ) { foundVariableIndex = i; break; } } if( foundVariableIndex != -1 ) { if( overwriteExistingVariable == EnumOverwriteExistingVariable.NO ) { // variable allready existed, but can't be overwritten throw new Exception("variable " + variablename + " exists in scope but can't be overwritten!"); } topScope.variables[foundVariableIndex].value = value; } else { InterpretationState.ScopeLevel.Variable newVariable; newVariable = new InterpretationState.ScopeLevel.Variable(); newVariable.name = variablename; newVariable.value = value; topScope.variables.Add(newVariable); } }