Пример #1
0
        // ===================================================================
        // CODE GENERATION FUNCTIONS
        // -------------------------------------------------------------------
        /// Generate the enable block header code.
        ///
        /// @param indentSize The indentation needed for the class definition.
        /// @return The formatted header code for the if-statement.
        ///
        public override string GenerateHeader(int indentSize)
        {
            var indent = ToIndent(indentSize);
            var result = new StringBuilder(indent, 1024);

            result.Append("if(");
            var len = myEnablePorts.Length;

            for (int i = 0; i < len; ++i)
            {
                if (myEnableCode[i] != null)
                {
                    result.Append(myEnableCode[i].GenerateBody(0));
                }
                else
                {
                    result.Append(GetNameFor(GraphInfo.GetProducerPort(myEnablePorts[i])));
                }
                if (i < len - 1)
                {
                    result.Append(" || ");
                }
            }
            result.Append(") {\n");
            return(result.ToString());
        }
Пример #2
0
        // -------------------------------------------------------------------------
        /// Returns list of nodes required for code generation
        ///
        /// @param node Root node from which the code will be generated.
        ///
        CodeBase[] GetFunctionBodyParts(iCS_EditorObject node)
        {
            var code = new List <CodeBase>();

            node.ForEachChildRecursiveDepthFirst(
                vsObj => {
                if (Context.IsInError(vsObj.InstanceId))
                {
                    Debug.LogWarning("iCanScript: Code not generated for node in Error: " + VSObject.FullName);
                    return;
                }
                if (IsFieldOrPropertyGet(vsObj))
                {
                    code.Add(new GetPropertyCallDefinition(vsObj, this));
                }
                else if (IsFieldOrPropertySet(vsObj))
                {
                    code.Add(new SetPropertyCallDefinition(vsObj, this));
                }
                else if (vsObj.IsKindOfFunction && !vsObj.IsConstructor)
                {
                    code.Add(new FunctionCallDefinition(vsObj, this));
                }
                else if (vsObj.IsConstructor && !AreAllInputsConstant(vsObj))
                {
                    code.Add(new ConstructorDefinition(vsObj, this));
                }
                else if (vsObj.IsInlineCode)
                {
                    code.Add(new InlineCodeDefinition(vsObj, this));
                }
                else if (vsObj.IsTriggerPort)
                {
                    if (ShouldGenerateTriggerCode(vsObj))
                    {
                        var triggerSet      = new TriggerSetDefinition(vsObj, this);
                        var triggerVariable = new TriggerVariableDefinition(vsObj, this, triggerSet);
                        code.Add(triggerVariable);
                        code.Add(triggerSet);
                    }
                }
                else if (vsObj.IsOutDataPort && vsObj.ParentNode == node)
                {
                    var portVariable = Context.GetCodeFor(vsObj);
                    if (portVariable != null)
                    {
                        var producerPort = GraphInfo.GetProducerPort(vsObj);
                        if (producerPort != null)
                        {
                            var consumerCode = new VariableReferenceDefinition(vsObj, this);
                            var producerCode = new VariableReferenceDefinition(producerPort, this);
                            code.Add(new AssignmentDefinition(this, consumerCode, producerCode));
                        }
                    }
                }
            }
                );
            return(code.ToArray());
        }
        // ===================================================================
        // COMMON INTERFACE FUNCTIONS
        // -------------------------------------------------------------------
        /// Resolves any dependencies that this code has.
        public override void ResolveDependencies()
        {
            // Optimize input parameters to fields/properties
            for (int i = 0; i < myParameters.Length; ++i)
            {
                var code         = myParameters[i];
                var producerCode = OptimizeInputParameter(code, myParent);
                if (producerCode != null)
                {
                    myParameters[i]     = producerCode;
                    producerCode.Parent = myParent;
                }
                myParameters[i].ResolveDependencies();
            }
            // -- Optimize target port from get fields/properties. --
            if (!IsStatic())
            {
                var targetPort = GraphInfo.GetTargetPort(VSObject);
                if (targetPort != null)
                {
                    var producerPort = GraphInfo.GetProducerPort(targetPort);
                    var producerCode = Context.GetCodeFor(producerPort.ParentNode);
                    if (producerCode is GetPropertyCallDefinition)
                    {
                        if (producerPort.ConsumerPorts.Length == 1)
                        {
                            myTargetCode = producerCode;
                            producerCode.Parent.Remove(producerCode);
                            producerCode.Parent = myParent;
                        }
                    }
                }
            }
            // Ask output objects to resolve their own child dependencies.
            foreach (var v in myOutputVariables)
            {
                v.ResolveDependencies();
            }
            if (myReturnVariable != null)
            {
                myReturnVariable.ResolveDependencies();

                // Return variable relocation
                var returnParent = GetProperParentForProducerPort(myReturnVariable);
                if (returnParent != null && returnParent != myParent)
                {
                    var returnPort = myReturnVariable.VSObject;
                    if (returnParent is ClassDefinition)
                    {
                        var v = new VariableDefinition(returnPort, returnParent, AccessSpecifier.Private, ScopeSpecifier.NonStatic);
                        returnParent.AddVariable(v);
                        myReturnVariable = null;
                        v.ResolveDependencies();
                    }
                }
            }
        }
        // -------------------------------------------------------------------
        /// Build information for parameters.
        void BuildParameterInformation()
        {
            var parameters = GetParameters(VSObject);
            var pLen       = parameters.Length;

            myParameters = new CodeBase[pLen];
            foreach (var p in parameters)
            {
                int idx = p.PortIndex;
                if (idx >= parameters.Length)
                {
                    VSObject.ForEachChildPort(
                        dp => {
                        Debug.Log("Index: " + dp.PortIndex + " => " + dp.FullName);
                    }
                        );
                }
                if (p.IsInputPort)
                {
                    var producerPort = GraphInfo.GetProducerPort(p);
                    if (producerPort != null && producerPort != p)
                    {
                        myParameters[idx] = new FunctionCallParameterDefinition(p, this, p.RuntimeType);
                    }
                    else
                    {
                        // Generate class variable for UnityEngine.Objects
                        var portType = p.RuntimeType;
                        if (iCS_Types.IsA <UnityEngine.Object>(portType))
                        {
                            myParameters[idx] = new FunctionCallParameterDefinition(p, this, p.RuntimeType);
                            var typeDef = GetClassDefinition();
                            var v       = new VariableDefinition(p, typeDef, AccessSpecifier.Public, ScopeSpecifier.NonStatic);
                            typeDef.AddVariable(v);
                        }
                        else
                        {
                            myParameters[idx] = new ConstantDefinition(p, this);
                        }
                    }
                }
                else
                {
                    myParameters[idx] = new FunctionCallOutParameterDefinition(p, this);
                }
            }
        }
        // ===================================================================
        // CODE GENERATION FUNCTIONS
        // -------------------------------------------------------------------
        /// Generate the parameter code.
        ///
        /// @param indentSize The indentation needed for the class definition.
        /// @return The formatted body code for the parameter.
        ///
        public override string GenerateBody(int indentSize)
        {
            var producerPort = GraphInfo.GetProducerPort(VSObject);
            var result       = new StringBuilder(GetNameFor(producerPort), 64);

            if (myType != null)
            {
                var desiredTypeName = ToTypeName(myType);
                var producerType    = Context.GetRuntimeTypeFor(producerPort);
                if (!iCS_Types.IsA(myType, producerType))
                {
                    result.Append(" as ");
                    result.Append(desiredTypeName);
                }
            }
            return(result.ToString());
        }
        // -------------------------------------------------------------------------
        /// Generates the function call prefix code fragment.
        ///
        /// @param memberInfo The member information of the function to call.
        /// @param node Visual script function call node.
        /// @return The code fragment to prepend to the function call.
        ///
        protected string FunctionCallPrefix(iCS_EditorObject node)
        {
            var result = new StringBuilder(32);

            if (IsStatic())
            {
                if (!GraphInfo.IsLocalType(VSObject))
                {
                    result.Append(ToTypeName(node.RuntimeType));
                    result.Append(".");
                }
            }
            else
            {
                var thisPort = GraphInfo.GetTargetPort(node);
                if (thisPort != null)
                {
//					result.Append(GetExpressionFor(thisPort));
//					result.Append(".");
                    // -- Prepend target code producer if optimized. --
                    if (myTargetCode != null)
                    {
                        result.Append(myTargetCode.GenerateBody(0));
                        result.Append(".");
                        return(result.ToString());
                    }
                    var producerPort = GraphInfo.GetProducerPort(thisPort);
                    var producerType = Context.GetRuntimeTypeFor(producerPort);
                    var producerCode = Context.GetCodeFor(producerPort);
                    if (producerCode is FunctionDefinitionParameter)
                    {
                        var producerPortName = GetNameFor(producerPort);
                        if (producerPortName == null || producerPortName == "null")
                        {
                            Debug.LogWarning("producer port is null: " + producerPort.CodeName);
                        }
                        result.Append(GetNameFor(producerPort));
                        result.Append(".");
                    }
                    else if (producerCode is LocalVariableDefinition)
                    {
                        var producerPortName = Parent.GetLocalVariableName(producerPort);
                        if (producerPortName == null || producerPortName == "null")
                        {
                            Debug.LogWarning("producer port is null: " + producerPort.CodeName);
                        }
                        result.Append(producerPortName);
                        result.Append(".");
                    }
                    else if (producerPort.IsOwner)
                    {
                        if (producerType == typeof(Transform))
                        {
                            result.Append("transform.");
                        }
                        else if (producerType == typeof(GameObject))
                        {
                            result.Append("gameObject.");
                        }
                    }
                    else if (producerPort != thisPort)
                    {
                        var desiredType     = VSObject.RuntimeType;
                        var desiredTypeName = ToTypeName(desiredType);
                        var isUpcastNeeded  = producerType != desiredType && iCS_Types.IsA(producerType, desiredType);
                        if (isUpcastNeeded)
                        {
                            result.Append("(");
                        }
                        var producerNode = producerPort.ParentNode;
                        if (producerNode.IsConstructor)
                        {
                            result.Append(GetNameFor(producerNode));
                        }
                        else
                        {
                            result.Append(GetNameFor(producerPort));
                        }
                        if (isUpcastNeeded)
                        {
                            result.Append(" as ");
                            result.Append(desiredTypeName);
                            result.Append(")");
                        }
                        result.Append(".");
                    }
                }
            }
            return(result.ToString());
        }
Пример #7
0
        // -------------------------------------------------------------------
        /// Resolves code dependencies.
        public override void ResolveDependencies()
        {
            // -- Ask our children to resolve their dependencies. --
            base.ResolveDependencies();

            // -- Don't generate code if all enables are false. --
            if (ControlFlow.IsAllEnablesAlwaysFalse(myEnablePorts))
            {
                Parent.Remove(this);
                return;
            }
            // -- Merge with parent if one of the enables is always true. --
            if (ControlFlow.IsAtLeastOneEnableAlwaysTrue(myEnablePorts))
            {
                (Parent as ExecutionBlockDefinition).Replace(this, myExecutionList);
                return;
            }

            // -- Determine if enable producers where optimized out. --
            var  enableLen   = myEnablePorts.Length;
            bool hasProducer = false;

            for (int i = 0; i < enableLen; ++i)
            {
                var enable       = myEnablePorts[i];
                var producerPort = GraphInfo.GetProducerPort(enable);
                if (FindCodeBase(producerPort) != null || producerPort.ParentNode.IsConstructor)
                {
                    hasProducer = true;
                    break;
                }
            }
            if (!hasProducer)
            {
                (Parent as ExecutionBlockDefinition).Replace(this, myExecutionList);
                return;
            }

            // -- Reposition code for simple trigger->enable --
            CodeBase commonParent = null;

            if (AreAllInSameExecutionContext(out commonParent))
            {
                var parentAsExecBlock = commonParent as ExecutionBlockDefinition;
                if (AreAllProducersTriggers())
                {
                    if (parentAsExecBlock != null)
                    {
                        Debug.Log("Removing enable for=> " + myEnablePorts[0].FullName);
                        parentAsExecBlock.Replace(this, myExecutionList);
                        return;
                    }
                }
                else if (parentAsExecBlock != null)
                {
                    if (Parent != parentAsExecBlock)
                    {
                        Parent.Remove(this);
                        parentAsExecBlock.AddExecutable(this);
                    }
                }
            }

            // -- Determine best enable order for code optimization. --
            if (enableLen > 1)
            {
                for (int i = 0; i < enableLen; ++i)
                {
                    var enable = myEnablePorts[i];
                    if (enable.IsTheOnlyConsumer && !enable.SegmentProducerPort.IsTriggerPort)
                    {
                        if (i != 0)
                        {
                            var t = myEnablePorts[0];
                            myEnablePorts[0] = enable;
                            myEnablePorts[i] = t;
                        }
                        break;
                    }
                }
            }

            // -- Verify if we can optimize parameter ports. --
            myEnableCode[0] = Context.GetCodeFor(GraphInfo.GetProducerPort(myEnablePorts[0]));
            if (myEnableCode[0] != null)
            {
                myEnableCode[0] = OptimizeInputParameter(myEnableCode[0], myParent);
                if (myEnableCode[0] != null)
                {
                    myEnableCode[0].Parent = this;
                }
            }
        }