/// <summary> /// Create BinaryExpressionNode /// </summary> /// <param name="node"></param> /// <param name="outnode"></param> private void EmitBlockNode(Block node, out AssociativeNode outnode) { Validity.Assert(node != null); // TODO: Confirm that these children are returned in the order that they // appear in the code Dictionary <int, Node> childNodes = node.GetChildrenWithIndices(); // Parse program statement in node.Name string code = node.Name + ";"; ProtoCore.AST.AssociativeAST.CodeBlockNode commentNode = null; ProtoCore.AST.AssociativeAST.CodeBlockNode codeBlockNode = (ProtoCore.AST.AssociativeAST.CodeBlockNode)GraphUtilities.Parse(code, out commentNode); Validity.Assert(codeBlockNode != null); List <ProtoCore.AST.AssociativeAST.AssociativeNode> astList = codeBlockNode.Body; Validity.Assert(astList.Count == 1); if (astList[0] is ProtoCore.AST.AssociativeAST.IdentifierNode) { ProtoCore.AST.AssociativeAST.BinaryExpressionNode ben = new ProtoCore.AST.AssociativeAST.BinaryExpressionNode(); ben.LeftNode = astList[0]; ben.Optr = ProtoCore.DSASM.Operator.assign; ProtoCore.AST.AssociativeAST.AssociativeNode statement = null; foreach (KeyValuePair <int, Node> kvp in childNodes) { DFSTraverse(kvp.Value, out statement); } ben.RightNode = statement; astList[0] = ben; } //I don't know what I am doing if (astList[0] is BinaryExpressionNode) { BinaryExpressionNode tempBen = astList[0] as BinaryExpressionNode; if (tempBen.LeftNode is IdentifierNode) { IdentifierNode identitiferNode = tempBen.LeftNode as IdentifierNode; if (identitiferNode.ArrayDimensions != null) { ArrayIndexerNode arrIndex = new ArrayIndexerNode(); arrIndex.ArrayDimensions = identitiferNode.ArrayDimensions; arrIndex.Array = identitiferNode; tempBen.LeftNode = arrIndex; } } if (tempBen.RightNode is IdentifierNode) { IdentifierNode identitiferNode = tempBen.RightNode as IdentifierNode; if (identitiferNode.ArrayDimensions != null) { ArrayIndexerNode arrIndex = new ArrayIndexerNode(); arrIndex.ArrayDimensions = identitiferNode.ArrayDimensions; arrIndex.Array = identitiferNode; tempBen.RightNode = arrIndex; } } astList[0] = tempBen; } //it should be correct, if not, debug? ProtoCore.AST.AssociativeAST.BinaryExpressionNode bNode = astList[0] as ProtoCore.AST.AssociativeAST.BinaryExpressionNode; Validity.Assert(bNode != null); bNode.Guid = node.Guid; //bNode.SplitFromUID = node.splitFomUint; // Child nodes are arguments to expression in bNode.RightNode. // Match child nodes with IdentifierNode's in bNode.RightNode - pratapa foreach (Node n in childNodes.Values) { AssociativeNode argNode = null; DFSTraverse(n, out argNode); // DFS traverse the bNode.RightNode and check for IdentifierNode's // and if their names match with the names of argNode, then replace // the IdentifierNode in bNode.RightNode with argNode BinaryExpressionNode ben = argNode as BinaryExpressionNode; Validity.Assert(ben != null); //ProtoCore.CodeGenDS codeGen = new ProtoCore.CodeGenDS(ben); AstCodeBlockTraverse sourceGen = new AstCodeBlockTraverse(ben); ProtoCore.AST.AssociativeAST.AssociativeNode right = bNode.RightNode; sourceGen.DFSTraverse(ref right); bNode.RightNode = right; } //(AstRootNode as CodeBlockNode).Body.Add(expressionNode); Validity.Assert(gc != null); gc.HandleNewNode(bNode); outnode = bNode; }
private void EmitFunctionNode(Func node, out AssociativeNode outnode) { Validity.Assert(node != null); AssociativeNode fNode = new NullNode(); string funcQualifier = node.Name; if (node.isRange) { EmitRangeExpNode(node, out fNode); } else if (!funcQualifier.Contains(".")) { if (node.isProperty) { Dictionary <int, Node> nodes = node.GetChildrenWithIndices(); Validity.Assert(nodes.Count == 1); for (int i = 0; i < nodes.Count; ++i) { AssociativeNode instanceNode = null; DFSTraverse(nodes[i], out instanceNode); EmitFunctionCallNode(node, out fNode); ((fNode as FunctionCallNode).Function as IdentifierNode).Value = ProtoCore.DSASM.Constants.kGetterPrefix + ((fNode as FunctionCallNode).Function as IdentifierNode).Value; //string className = (node.Name.Split('.'))[0]; //IdentifierNode inode = new IdentifierNode(className); fNode = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(instanceNode, fNode as FunctionCallNode); } } else if (node.isMemberFunction) { Dictionary <int, Node> nodes = node.GetChildrenWithIndices(); AssociativeNode instanceNode = null; DFSTraverse(nodes[0], out instanceNode); EmitFunctionCallNode(node, out fNode); //string className = (node.Name.Split('.'))[0]; //IdentifierNode inode = new IdentifierNode(className); fNode = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(instanceNode, fNode as FunctionCallNode); } else { // Create AssociativeAST.FunctionCallNode for global and built-in functions EmitFunctionCallNode(node, out fNode); } } else { // Create FunctionDotCallNode for ctors, static and instance methods EmitFunctionDotCallNode(node, out fNode); } BinaryExpressionNode assignmentNode = new BinaryExpressionNode(); assignmentNode.LeftNode = new IdentifierNode(node.tempName); assignmentNode.Optr = ProtoCore.DSASM.Operator.assign; assignmentNode.RightNode = fNode; assignmentNode.Guid = node.Guid; Validity.Assert(gc != null); gc.HandleNewNode(assignmentNode); outnode = assignmentNode; }
public override StackValue Execute(ProtoCore.Runtime.Context c, List <StackValue> formalParameters, ProtoCore.DSASM.StackFrame stackFrame, Core core) { // ensure there is no data race, function resolution and execution happens in parallel // but for FFI we want it to be serial cause the code we are calling into may not cope // with parallelism. // // we are always looking and putting our function pointers in handler with each lang // so better lock for FFIHandler (being static) it will be good object to lock // lock (FFIHandlers) { ProtoCore.DSASM.Interpreter interpreter = new ProtoCore.DSASM.Interpreter(core, true); StackValue svThisPtr = stackFrame.GetAt(StackFrame.AbsoluteIndex.kThisPtr); StackValue svBlockDecl = stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionBlock); // Setup the stack frame data //int thisPtr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kThisPtr).opdata; int ci = activation.JILRecord.classIndex; int fi = activation.JILRecord.funcIndex; int returnAddr = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kReturnAddress).opdata; int blockDecl = (int)svBlockDecl.opdata; int blockCaller = (int)stackFrame.GetAt(DSASM.StackFrame.AbsoluteIndex.kFunctionCallerBlock).opdata; int framePointer = core.Rmem.FramePointer; int locals = activation.JILRecord.locals; FFIHandler handler = FFIHandlers[activation.ModuleType]; FFIActivationRecord r = activation; string className = ""; if (activation.JILRecord.classIndex > 0) { className = core.DSExecutable.classTable.ClassNodes[activation.JILRecord.classIndex].name; } bool gcThisPtr = false; List <ProtoCore.Type> argTypes = new List <Type>(r.ParameterTypes); ProcedureNode fNode = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != ci) { fNode = interpreter.runtime.exe.classTable.ClassNodes[ci].vtable.procList[fi]; } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != fNode && fNode.isAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = AddressType.Pointer == svThisPtr.optype && ProtoCore.DSASM.Constants.kInvalidPointer == (int)svThisPtr.opdata; if (isStaticCall) { thisPtrIndex = formalParameters.Count - 1; } argTypes.RemoveAt(thisPtrIndex); // Comment Jun: Execute() can handle a null this pointer. // But since we dont even need to to reach there if we dont have a valid this pointer, then just return null if (AddressType.Null == formalParameters[thisPtrIndex].optype) { core.RuntimeStatus.LogWarning(ProtoCore.RuntimeData.WarningID.kDereferencingNonPointer, ProtoCore.RuntimeData.WarningMessage.kDeferencingNonPointer); return(StackUtils.BuildNull()); } // These are the op types allowed. Validity.Assert(AddressType.Pointer == formalParameters[thisPtrIndex].optype || AddressType.DefaultArg == formalParameters[thisPtrIndex].optype); svThisPtr = formalParameters[thisPtrIndex]; gcThisPtr = true; formalParameters.RemoveAt(thisPtrIndex); } FFIFunctionPointer functionPointer = handler.GetFunctionPointer(r.ModuleName, className, r.FunctionName, argTypes, r.ReturnType); mFunctionPointer = Validate(functionPointer) ? functionPointer : null; mFunctionPointer.IsDNI = activation.IsDNI; if (mFunctionPointer == null) { return(ProtoCore.DSASM.StackUtils.BuildNull()); } List <object> ps = new List <object>(); //obsolete { interpreter.runtime.executingBlock = core.RunningBlock; activation.JILRecord.globs = core.DSExecutable.runtimeSymbols[core.RunningBlock].GetGlobalSize(); // Params formalParameters.Reverse(); for (int i = 0; i < formalParameters.Count; i++) { interpreter.Push(formalParameters[i]); } List <ProtoCore.DSASM.StackValue> registers = new List <DSASM.StackValue>(); interpreter.runtime.SaveRegisters(registers); // Comment Jun: the depth is always 0 for a function call as we are reseting this for each function call // This is only incremented for every language block bounce int depth = 0; StackFrameType callerType = (StackFrameType)stackFrame.GetAt(StackFrame.AbsoluteIndex.kCallerStackFrameType).opdata; core.Rmem.PushStackFrame(svThisPtr, ci, fi, returnAddr, blockDecl, blockCaller, callerType, ProtoCore.DSASM.StackFrameType.kTypeFunction, depth, framePointer, registers, locals); //is there a way the current stack be passed across and back into the managed runtime by FFI calling back into the language? //e.g. DCEnv* carrying all the stack information? look at how vmkit does this. // = jilMain.Run(ActivationRecord.JILRecord.pc, null, true); //double[] tempArray = GetUnderlyingArray<double>(jilMain.runtime.rmem.stack); Object ret = mFunctionPointer.Execute(c, interpreter); StackValue op; if (ret == null) { op = StackUtils.BuildNull(); } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = new StackValue(); op.optype = AddressType.Int; op.opdata = (Int64)ret; } else if (ret is double) { op = new StackValue(); op.optype = AddressType.Double; op.opdata_d = (double)ret; } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } // gc the parameters if (gcThisPtr)// && core.Options.EnableThisPointerFunctionOverload) { // thisptr is sent as parameter, so need to gc it. // but when running in expression interpreter mode, do not GC because in DSASM.Executive.DecRefCounter() related GC functions, // the reference count will not be changed in expression interpreter mode. if (core.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { interpreter.runtime.Core.Rmem.Heap.GCRelease(new StackValue[] { svThisPtr }, interpreter.runtime); } } interpreter.runtime.Core.Rmem.Heap.GCRelease(formalParameters.ToArray(), interpreter.runtime); // increment the reference counter of the return value interpreter.runtime.GCRetain(op); // Clear the FFI stack frame // FFI stack frames have no local variables interpreter.runtime.rmem.FramePointer = (int)interpreter.runtime.rmem.GetAtRelative(ProtoCore.DSASM.StackFrame.kFrameIndexFramePointer).opdata; interpreter.runtime.rmem.PopFrame(ProtoCore.DSASM.StackFrame.kStackFrameSize + formalParameters.Count); return(op); //DSASM.Mirror.ExecutionMirror.Unpack(op, core.heap, core); } } }
private void EmitBinaryExpNode(Operator node, out AssociativeNode outnode) { Validity.Assert(node != null); Dictionary <int, Node> nodes = node.GetChildrenWithIndices(); Validity.Assert(nodes.Count <= 2); BinaryExpressionNode expressionNode = new BinaryExpressionNode(); // Create operator from input node switch (node.Name) { case "=": expressionNode.Optr = ProtoCore.DSASM.Operator.assign; break; case "+": expressionNode.Optr = ProtoCore.DSASM.Operator.add; break; case "-": expressionNode.Optr = ProtoCore.DSASM.Operator.sub; break; case "*": expressionNode.Optr = ProtoCore.DSASM.Operator.mul; break; case "/": expressionNode.Optr = ProtoCore.DSASM.Operator.div; break; case "%": expressionNode.Optr = ProtoCore.DSASM.Operator.mod; break; case "==": expressionNode.Optr = ProtoCore.DSASM.Operator.eq; break; case "!=": expressionNode.Optr = ProtoCore.DSASM.Operator.nq; break; case ">=": expressionNode.Optr = ProtoCore.DSASM.Operator.ge; break; case ">": expressionNode.Optr = ProtoCore.DSASM.Operator.gt; break; case "<=": expressionNode.Optr = ProtoCore.DSASM.Operator.le; break; case "<": expressionNode.Optr = ProtoCore.DSASM.Operator.lt; break; case "&&": expressionNode.Optr = ProtoCore.DSASM.Operator.and; break; case "||": expressionNode.Optr = ProtoCore.DSASM.Operator.or; break; case "&": expressionNode.Optr = ProtoCore.DSASM.Operator.bitwiseand; break; case "|": expressionNode.Optr = ProtoCore.DSASM.Operator.bitwiseor; break; case "^": expressionNode.Optr = ProtoCore.DSASM.Operator.bitwisexor; break; default: break; } AssociativeNode identNode1 = new NullNode(); AssociativeNode identNode2 = new NullNode(); if (nodes.Count == 2) { // Create BinaryExpressionNode from identNode1, identNode2 and operator DFSTraverse(nodes[0], out identNode1); DFSTraverse(nodes[1], out identNode2); } else if (nodes.Count == 1) { // Create BinaryExpressionNode from identNode1, null DFSTraverse(nodes[0], out identNode1); } expressionNode.LeftNode = identNode1; expressionNode.RightNode = identNode2; //(AstRootNode as CodeBlockNode).Body.Add(expressionNode); BinaryExpressionNode assignmentNode = new BinaryExpressionNode(); assignmentNode.LeftNode = new IdentifierNode(node.tempName); assignmentNode.Optr = ProtoCore.DSASM.Operator.assign; assignmentNode.RightNode = expressionNode; assignmentNode.Guid = node.Guid; Validity.Assert(gc != null); gc.HandleNewNode(assignmentNode); outnode = assignmentNode; }
public int GetType(string ident) { Validity.Assert(null != classTable); return(classTable.IndexOf(ident)); }
public static StackValue Coerce(StackValue sv, Type targetType, Core core) { //@TODO(Jun): FIX ME - abort coersion for default args if (sv.IsDefaultArgument) { return(sv); } if (!( sv.metaData.type == targetType.UID || (core.ClassTable.ClassNodes[sv.metaData.type].ConvertibleTo(targetType.UID)) || sv.IsArray)) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, ProtoCore.RuntimeData.WarningMessage.kConvertNonConvertibleTypes); return(StackValue.Null); } //if it's an array if (sv.IsArray && !targetType.IsIndexable) { //This is an array rank reduction //this may only be performed in recursion and is illegal here string errorMessage = String.Format(ProtoCore.RuntimeData.WarningMessage.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID)); core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, errorMessage); return(StackValue.Null); } if (sv.IsArray && targetType.IsIndexable) { Validity.Assert(sv.IsArray); //We're being asked to convert an array into an array //walk over the structure converting each othe elements if (targetType.UID == (int)PrimitiveType.kTypeVar && targetType.rank == DSASM.Constants.kArbitraryRank && core.Heap.IsTemporaryPointer(sv)) { return(sv); } //Validity.Assert(targetType.rank != -1, "Arbitrary rank array conversion not yet implemented {2EAF557F-62DE-48F0-9BFA-F750BBCDF2CB}"); //Decrease level of reductions by one Type newTargetType = new Type(); newTargetType.UID = targetType.UID; if (targetType.rank != Constants.kArbitraryRank) { newTargetType.rank = targetType.rank - 1; } else { if (ArrayUtils.GetMaxRankForArray(sv, core) == 1) { //Last unpacking newTargetType.rank = 0; } else { newTargetType.rank = Constants.kArbitraryRank; } } return(ArrayUtils.CopyArray(sv, newTargetType, core)); } if (!sv.IsArray && !sv.IsNull && targetType.IsIndexable && targetType.rank != DSASM.Constants.kArbitraryRank) { //We're being asked to promote the value into an array if (targetType.rank == 1) { Type newTargetType = new Type(); newTargetType.UID = targetType.UID; newTargetType.Name = targetType.Name; newTargetType.rank = 0; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null); return(newSv); } else { Validity.Assert(targetType.rank > 1, "Target rank should be greater than one for this clause"); Type newTargetType = new Type(); newTargetType.UID = targetType.UID; newTargetType.Name = targetType.Name; newTargetType.rank = targetType.rank - 1; //Upcast once StackValue coercedValue = Coerce(sv, newTargetType, core); GCUtils.GCRetain(coercedValue, core); StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null); return(newSv); } } if (sv.IsPointer) { StackValue ret = ClassCoerece(sv, targetType, core); return(ret); } //If it's anything other than array, just create a new copy switch (targetType.UID) { case (int)PrimitiveType.kInvalidType: Validity.Assert(false, "Can't convert invalid type"); break; case (int)PrimitiveType.kTypeBool: return(sv.ToBoolean(core)); case (int)PrimitiveType.kTypeChar: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeChar }; return(newSV); } case (int)PrimitiveType.kTypeDouble: return(sv.ToDouble()); case (int)PrimitiveType.kTypeFunctionPointer: if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToFunction); return(StackValue.Null); } return(sv); case (int)PrimitiveType.kTypeHostEntityID: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeHostEntityID }; return(newSV); } case (int)PrimitiveType.kTypeInt: { if (sv.metaData.type == (int)PrimitiveType.kTypeDouble) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, ProtoCore.RuntimeData.WarningMessage.kConvertDoubleToInt); } return(sv.ToInteger()); } case (int)PrimitiveType.kTypeNull: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToNull); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.kTypePointer: { if (sv.metaData.type != (int)PrimitiveType.kTypeNull) { core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToPointer); return(StackValue.Null); } return(sv); } case (int)PrimitiveType.kTypeString: { StackValue newSV = sv.ShallowClone(); newSV.metaData = new MetaData { type = (int)PrimitiveType.kTypeString }; if (sv.metaData.type == (int)PrimitiveType.kTypeChar) { char ch = EncodingUtils.ConvertInt64ToCharacter(newSV.opdata); newSV = StackValue.BuildString(ch.ToString(), core.Heap); } return(newSV); } case (int)PrimitiveType.kTypeVar: { return(sv); } case (int)PrimitiveType.kTypeArray: { return(ArrayUtils.CopyArray(sv, targetType, core)); } default: if (sv.IsNull) { return(StackValue.Null); } else { throw new NotImplementedException("Requested coercion not implemented"); } } throw new NotImplementedException("Requested coercion not implemented"); }
public string GetType(int UID) { Validity.Assert(null != classTable); return(classTable.GetTypeName(UID)); }
public static string GetMethodName(StackValue pointer, Interpreter dsi) { Validity.Assert(pointer.IsFunctionPointer); return(dsi.runtime.exe.procedureTable[0].procList[(int)pointer.opdata].name); }
public void SetUpCallrForDebug(RuntimeCore runtimeCore, DSASM.Executive exec, ProcedureNode fNode, int pc, bool isBaseCall = false, CallSite callsite = null, List <StackValue> arguments = null, List <List <ReplicationGuide> > replicationGuides = null, StackFrame stackFrame = null, List <StackValue> dotCallDimensions = null, bool hasDebugInfo = false, bool isMember = false, StackValue?thisPtr = null) { //ProtoCore.DSASM.Executive exec = core.CurrentExecutive.CurrentDSASMExec; DebugFrame debugFrame = new DebugFrame(); debugFrame.IsBaseCall = isBaseCall; debugFrame.Arguments = arguments; debugFrame.IsMemberFunction = isMember; debugFrame.ThisPtr = thisPtr; debugFrame.HasDebugInfo = hasDebugInfo; if (CoreUtils.IsDisposeMethod(fNode.name)) { debugFrame.IsDisposeCall = true; ReturnPCFromDispose = DebugEntryPC; } if (RunMode == Runmode.StepNext) { debugFrame.FunctionStepOver = true; } bool isReplicating = false; bool isExternalFunction = false; // callsite is set to null for a base class constructor call in CALL if (callsite == null) { isReplicating = false; isExternalFunction = false; SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); return; } // Comment Jun: A dot call does not replicate and must be handled immediately if (fNode.name == Constants.kDotMethodName) { isReplicating = false; isExternalFunction = false; debugFrame.IsDotCall = true; debugFrame.DotCallDimensions = dotCallDimensions; SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); return; } List <List <ReplicationInstruction> > replicationTrials; bool willReplicate = callsite.WillCallReplicate(new Context(), arguments, replicationGuides, stackFrame, runtimeCore, out replicationTrials); // the inline conditional built-in is handled separately as 'WillCallReplicate' is always true in this case if (fNode.name.Equals(Constants.kInlineConditionalMethodName)) { // The inline conditional built-in is created only for associative blocks and needs to be handled separately as below InstructionStream istream = runtimeCore.DSExecutable.instrStreamList[CurrentBlockId]; Validity.Assert(istream.language == Language.kAssociative); { runtimeCore.DebugProps.InlineConditionOptions.isInlineConditional = true; runtimeCore.DebugProps.InlineConditionOptions.startPc = pc; runtimeCore.DebugProps.InlineConditionOptions.endPc = FindEndPCForAssocGraphNode(pc, istream, fNode, exec.Properties.executingGraphNode, runtimeCore.Options.ExecuteSSA); runtimeCore.DebugProps.InlineConditionOptions.instructionStream = runtimeCore.RunningBlock; debugFrame.IsInlineConditional = true; } // no replication case if (willReplicate && replicationTrials.Count == 1) { runtimeCore.DebugProps.InlineConditionOptions.ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); /*if (core.DebugProps.RunMode == Runmode.StepNext) * { * core.Breakpoints.Clear(); * }*/ isReplicating = false; isExternalFunction = false; } else // an inline conditional call that replicates { #if !__DEBUG_REPLICATE // Clear all breakpoints for outermost replicated call if (!DebugStackFrameContains(StackFrameFlagOptions.IsReplicating)) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } #endif isExternalFunction = false; isReplicating = true; } SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec, 0); DebugStackFrame.Push(debugFrame); return; } // Prevent breaking inside a function that is external except for dot calls // by clearing all breakpoints from outermost external function call // This check takes precedence over the replication check else if (fNode.isExternal && fNode.name != Constants.kDotMethodName) { // Clear all breakpoints if (!DebugStackFrameContains(StackFrameFlagOptions.IsExternalFunction) && fNode.name != Constants.kFunctionRangeExpression) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } isExternalFunction = true; isReplicating = false; } // Find if function call will replicate or not and if so // prevent stepping in by removing all breakpoints from outermost replicated call else if (willReplicate) { #if !__DEBUG_REPLICATE // Clear all breakpoints for outermost replicated call if (!DebugStackFrameContains(StackFrameFlagOptions.IsReplicating)) { ActiveBreakPoints.AddRange(runtimeCore.Breakpoints); runtimeCore.Breakpoints.Clear(); } #endif isReplicating = true; isExternalFunction = false; } // For all other function calls else { isReplicating = false; isExternalFunction = false; } SetUpCallr(ref debugFrame, isReplicating, isExternalFunction, exec); DebugStackFrame.Push(debugFrame); }
public void SetTypeSystem() { Validity.Assert(null == classTable); if (null != classTable) { return; } classTable = new DSASM.ClassTable(); classTable.Reserve((int)PrimitiveType.kMaxPrimitives); ClassNode cnode; cnode = new ClassNode { name = DSDefinitions.Keyword.Array, size = 0, rank = 5, symbols = null, vtable = null, typeSystem = this }; /*cnode.coerceTypes.Add((int)PrimitiveType.kTypeDouble, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeChar, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeString, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); */ cnode.classId = (int)PrimitiveType.kTypeArray; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeArray); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Double, size = 0, rank = 4, symbols = null, vtable = null, typeSystem = this }; cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceDoubleToIntScore); cnode.classId = (int)PrimitiveType.kTypeDouble; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeDouble); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Int, size = 0, rank = 3, symbols = null, vtable = null, typeSystem = this }; cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeDouble, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceIntToDoubleScore); cnode.classId = (int)PrimitiveType.kTypeInt; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeInt); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Bool, size = 0, rank = 2, symbols = null, vtable = null, typeSystem = this }; // if convert operator to method call, without the following statement // a = true + 1 will fail, because _add expects two integers //cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.classId = (int)PrimitiveType.kTypeBool; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeBool); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Char, size = 0, rank = 1, symbols = null, vtable = null, typeSystem = this }; cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeString, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.classId = (int)PrimitiveType.kTypeChar; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeChar); // // cnode = new ClassNode { name = DSDefinitions.Keyword.String, size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.classId = (int)PrimitiveType.kTypeString; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeString); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Var, size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; /*cnode.coerceTypes.Add((int)PrimitiveType.kTypeDouble, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeChar, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); * cnode.coerceTypes.Add((int)PrimitiveType.kTypeString, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore);*/ cnode.classId = (int)PrimitiveType.kTypeVar; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeVar); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Null, size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; cnode.coerceTypes.Add((int)PrimitiveType.kTypeDouble, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeChar, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.coerceTypes.Add((int)PrimitiveType.kTypeString, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.classId = (int)PrimitiveType.kTypeNull; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeNull); // // cnode = new ClassNode { name = DSDefinitions.Keyword.Void, size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; cnode.classId = (int)PrimitiveType.kTypeVoid; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeVoid); // // cnode = new ClassNode { name = "hostentityid", size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; cnode.classId = (int)PrimitiveType.kTypeHostEntityID; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeHostEntityID); // // cnode = new ClassNode { name = "pointer_reserved", size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; // if convert operator to method call, without the following statement, // a = b.c + d.e will fail, b.c and d.e are resolved as pointer and _add method requires two integer cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.classId = (int)PrimitiveType.kTypePointer; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypePointer); // // cnode = new ClassNode { name = DSDefinitions.Keyword.FunctionPointer, size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; cnode.coerceTypes.Add((int)PrimitiveType.kTypeInt, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore); cnode.classId = (int)PrimitiveType.kTypeFunctionPointer; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeFunctionPointer); // // cnode = new ClassNode { name = "return_reserved", size = 0, rank = 0, symbols = null, vtable = null, typeSystem = this }; cnode.classId = (int)PrimitiveType.kTypeReturn; classTable.SetClassNodeAt(cnode, (int)PrimitiveType.kTypeReturn); }
public void ResetModifedSymbols() { Validity.Assert(null != mapModifiedSymbols); mapModifiedSymbols.Clear(); }
public void SetGlobalStackData(int globalOffset, StackValue svData) { Validity.Assert(globalOffset >= 0); Validity.Assert(Stack.Count > 0); Stack[globalOffset] = svData; }
public StackValue Evaluate(List <StackValue> args, StackFrame stackFrame) { // Build the stackframe var core = interpreter.runtime.Core; int classScopeCaller = stackFrame.ClassScope; int returnAddr = stackFrame.ReturnPC; int blockDecl = procNode.runtimeIndex; int blockCaller = stackFrame.FunctionCallerBlock; int framePointer = core.Rmem.FramePointer; StackValue thisPtr = StackValue.BuildPointer(Constants.kInvalidIndex); // Functoion has variable input parameter. This case only happen // for FFI functions whose last parameter's type is (params T[]). // In this case, we need to convert argument list from // // {a1, a2, ..., am, v1, v2, ..., vn} // // to // // {a1, a2, ..., am, {v1, v2, ..., vn}} if (procNode.isVarArg) { int paramCount = procNode.argInfoList.Count; Validity.Assert(paramCount >= 1); int varParamCount = args.Count - (paramCount - 1); var varParams = args.GetRange(paramCount - 1, varParamCount).ToArray(); args.RemoveRange(paramCount - 1, varParamCount); var packedParams = interpreter.runtime.Core.Heap.AllocateArray(varParams, null); args.Add(packedParams); } bool isCallingMemberFunciton = procNode.classScope != Constants.kInvalidIndex && !procNode.isConstructor && !procNode.isStatic; bool isValidThisPointer = true; if (isCallingMemberFunciton) { Validity.Assert(args.Count >= 1); thisPtr = args[0]; if (thisPtr.IsArray) { isValidThisPointer = ArrayUtils.GetFirstNonArrayStackValue(thisPtr, ref thisPtr, core); } else { args.RemoveAt(0); } } if (!isValidThisPointer || (!thisPtr.IsPointer && !thisPtr.IsArray)) { core.RuntimeStatus.LogWarning(WarningID.kDereferencingNonPointer, Resources.kDeferencingNonPointer); return(StackValue.Null); } var callerType = stackFrame.StackFrameType; interpreter.runtime.TX = StackValue.BuildCallingConversion((int)ProtoCore.DSASM.CallingConvention.BounceType.kImplicit); StackValue svBlockDecl = StackValue.BuildBlockIndex(blockDecl); interpreter.runtime.SX = svBlockDecl; var repGuides = new List <List <ProtoCore.ReplicationGuide> >(); List <StackValue> registers = new List <StackValue>(); interpreter.runtime.SaveRegisters(registers); var newStackFrame = new StackFrame(thisPtr, classScopeCaller, 1, returnAddr, blockDecl, blockCaller, callerType, StackFrameType.kTypeFunction, 0, // depth framePointer, registers, null); bool isInDebugMode = core.Options.IDEDebugMode && core.ExecMode != InterpreterMode.kExpressionInterpreter; if (isInDebugMode) { core.DebugProps.SetUpCallrForDebug(core, interpreter.runtime, procNode, returnAddr - 1, false, callsite, args, repGuides, newStackFrame); } StackValue rx = callsite.JILDispatchViaNewInterpreter( new Runtime.Context(), args, repGuides, newStackFrame, core); if (isInDebugMode) { core.DebugProps.RestoreCallrForNoBreak(core, procNode); } return(rx); }
public override StackValue Execute(Runtime.Context c, List <StackValue> formalParameters, StackFrame stackFrame, RuntimeCore runtimeCore) { StackValue svThisPtr = stackFrame.ThisPtr; if (mInterpreter == null) { Init(runtimeCore); } if (mFunctionPointer == null) { return(StackValue.Null); } // Check if this is a 'this' pointer function overload that was generated by the compiler if (null != mFNode && mFNode.IsAutoGeneratedThisProc) { int thisPtrIndex = 0; bool isStaticCall = svThisPtr.IsPointer && Constants.kInvalidPointer == svThisPtr.Pointer; if (isStaticCall) { stackFrame.ThisPtr = formalParameters[thisPtrIndex]; } // Comment Jun: Execute() can handle a null this pointer. // But since we don't even need to to reach there if we don't have a valid this pointer, then just return null if (formalParameters[thisPtrIndex].IsNull) { runtimeCore.RuntimeStatus.LogWarning( Runtime.WarningID.DereferencingNonPointer, Resources.kDeferencingNonPointer); return(StackValue.Null); } // These are the op types allowed. Validity.Assert(formalParameters[thisPtrIndex].IsPointer || formalParameters[thisPtrIndex].IsDefaultArgument); // Make sure we to pass a pointer to unmarshal. if (formalParameters[thisPtrIndex].IsPointer) { svThisPtr = formalParameters[thisPtrIndex]; } formalParameters.RemoveAt(thisPtrIndex); } formalParameters.Add(svThisPtr); Object ret = mFunctionPointer.Execute(c, mInterpreter, formalParameters); StackValue op; if (ret == null) { op = StackValue.Null; } else if (ret is StackValue) { op = (StackValue)ret; } else if (ret is Int64 || ret is int) { op = StackValue.BuildInt((Int64)ret); } else if (ret is double) { op = StackValue.BuildDouble((double)ret); } else { throw new ArgumentException(string.Format("FFI: incorrect return type {0} from external function {1}:{2}", activation.ReturnType.Name, activation.ModuleName, activation.FunctionName)); } return(op); }
public string GetType(Type type) { Validity.Assert(null != classTable); return(classTable.GetTypeName(type.UID)); }
public void RunExpression(HomeWorkspaceModel workspaceModel, int?executionInterval = null) { if (workspaceModel == null) { return; } var dynamoModel = workspaceModel.DynamoModel; execInternval = executionInterval; lock (RunControlMutex) { if (Running) { //We're already running, so we might need an additional run NeedsAdditionalRun = true; return; } //We're new so if we needed an additional run, this one counts NeedsAdditionalRun = false; // If there is preloaded trace data, send that along to the current // LiveRunner instance. Here we make sure it is done exactly once // by resetting WorkspaceModel.PreloadedTraceData property after it // is obtained. // IEnumerable <KeyValuePair <Guid, List <string> > > traceData = workspaceModel.PreloadedTraceData; workspaceModel.PreloadedTraceData = null; // Reset. if (dynamoModel == null || dynamoModel.EngineController == null) { return; } dynamoModel.EngineController.LiveRunnerCore.SetTraceDataForNodes(traceData); //We are now considered running Running = true; } if (!DynamoModel.IsTestMode) { //Setup background worker dynamoModel.RunEnabled = false; //As we are the only place that is allowed to activate this, it is a trap door, so this is safe lock (RunControlMutex) { Validity.Assert(Running); } RunAsync(workspaceModel); } else { //for testing, we do not want to run asynchronously, as it will finish the //test before the evaluation (and the run) is complete //RunThread(evaluationWorker, new DoWorkEventArgs(executionInterval)); RunSync(workspaceModel); } }
private void CompileToAstNodes(NodeModel node, List <AssociativeNode> resultList, CompilationContext context, bool verboseLogging) { var inputAstNodes = new List <AssociativeNode>(); foreach (int index in Enumerable.Range(0, node.InPortData.Count)) { Tuple <int, NodeModel> inputTuple; if (node.TryGetInput(index, out inputTuple)) { int outputIndexOfInput = inputTuple.Item1; NodeModel inputModel = inputTuple.Item2; AssociativeNode inputNode = inputModel.GetAstIdentifierForOutputIndex(outputIndexOfInput); #if DEBUG Validity.Assert(inputNode != null, "Shouldn't have null nodes in the AST list"); #endif inputAstNodes.Add(inputNode); } else { PortData port = node.InPortData[index]; inputAstNodes.Add(port.DefaultValue ?? new NullNode()); } } //TODO: This should do something more than just log a generic message. --SJE if (node.State == ElementState.Error) { Log("Error in Node. Not sent for building and compiling"); } if (context == CompilationContext.DeltaExecution || context == CompilationContext.PreviewGraph) { OnAstNodeBuilding(node.GUID); } #if DEBUG Validity.Assert(inputAstNodes.All(n => n != null), "Shouldn't have null nodes in the AST list"); #endif var scopedNode = node as ScopedNodeModel; IEnumerable <AssociativeNode> astNodes = scopedNode != null ? scopedNode.BuildAstInScope(inputAstNodes, verboseLogging, this) : node.BuildAst(inputAstNodes, context); if (verboseLogging) { foreach (var n in astNodes) { Log(n.ToString()); } } if (null == astNodes) { resultList.AddRange(new AssociativeNode[0]); } else if (context == CompilationContext.DeltaExecution || context == CompilationContext.PreviewGraph) { OnAstNodeBuilt(node.GUID, astNodes); resultList.AddRange(astNodes); } else if (context == CompilationContext.NodeToCode) { resultList.AddRange(astNodes); } else //Inside custom node compilation. { bool notified = false; foreach (var item in astNodes) { if (item is FunctionDefinitionNode) { if (!notified) { OnAstNodeBuilding(node.GUID); } notified = true; //Register the function node in global scope with Graph Sync data, //so that we don't have a function definition inside the function def //of custom node. OnAstNodeBuilt(node.GUID, new[] { item }); } else { resultList.Add(item); } } } }