Ejemplo n.º 1
0
        protected AssociativeNode CreateOutputAST(
            AssociativeNode codeInputNode, List<AssociativeNode> inputAstNodes,
            List<Tuple<string, AssociativeNode>> additionalBindings)
        {
            var names =
                additionalBindings.Select(
                    x => AstFactory.BuildStringNode(x.Item1) as AssociativeNode).ToList();
            names.Add(AstFactory.BuildStringNode("IN"));

            var vals = additionalBindings.Select(x => x.Item2).ToList();
            vals.Add(AstFactory.BuildExprList(inputAstNodes));

            Func<string, IList, IList, object> backendMethod =
                IronPythonEvaluator.EvaluateIronPythonScript;

            return AstFactory.BuildAssignment(
                GetAstIdentifierForOutputIndex(0),
                AstFactory.BuildFunctionCall(
                    backendMethod,
                    new List<AssociativeNode>
                    {
                        codeInputNode,
                        AstFactory.BuildExprList(names),
                        AstFactory.BuildExprList(vals)
                    }));
        }
Ejemplo n.º 2
0
        private static BinaryExpressionNode CreateAssignmentNode(AssociativeNode rhsNode)
        {

            IdentifierNode lhs = new IdentifierNode(string.Format("tVar_{0}", staticVariableIndex++));
            BinaryExpressionNode bNode = new BinaryExpressionNode(lhs, rhsNode, ProtoCore.DSASM.Operator.assign);
            return bNode;
        }
Ejemplo n.º 3
0
        public static AssociativeNode GenerateBridgeDataAst(string id, AssociativeNode input)
        {
            Action<string, object> bridgeData = BridgeData;

            return AstFactory.BuildFunctionCall(
                bridgeData,
                new List<AssociativeNode> { AstFactory.BuildStringNode(id), input });
        }
Ejemplo n.º 4
0
        private string summary = null; // Indicating that it is not initialized.

        public TypedParameter(string parameter, ProtoCore.Type type, AssociativeNode defaultValue = null)
        {
            if (parameter == null)
                throw new ArgumentNullException("parameter");

            Name = parameter;
            Type = type;
            DefaultValue = defaultValue;
        }
 public static ProtoCore.AST.AssociativeAST.ExprListNode BuildArrayExprList(ProtoCore.AST.AssociativeAST.AssociativeNode arrayNode)
 {
     ProtoCore.AST.AssociativeAST.ExprListNode exprlist = new ProtoCore.AST.AssociativeAST.ExprListNode();
     while (arrayNode is ProtoCore.AST.AssociativeAST.ArrayNode)
     {
         ProtoCore.AST.AssociativeAST.ArrayNode array = arrayNode as ProtoCore.AST.AssociativeAST.ArrayNode;
         exprlist.list.Add(array.Expr);
         arrayNode = array.Type;
     }
     return(exprlist);
 }
Ejemplo n.º 6
0
		private void TopologicalSortVisit(AssociativeNode n, List<AssociativeNode> visited, List<AssociativeNode> topologicalSort)
		{
			if (visited.Contains(n))
				return;
			
			visited.Add(n);
			foreach (AssociativeNode node in tracker.DirectContingents[n])
				TopologicalSortVisit(node, visited, topologicalSort);
			
			topologicalSort.Add(n);
		}
Ejemplo n.º 7
0
        public void AddNode(AssociativeNode node)
        {
            if (AllNodes.Contains(node))
                return;

            AllNodes.Add(node);

            if (!DirectContingents.ContainsKey(node))
                DirectContingents.Add(node, new List<AssociativeNode>());

            if (!DirectDependents.ContainsKey(node))
                DirectDependents.Add(node, new List<AssociativeNode>());
        }
Ejemplo n.º 8
0
 protected override void AssignIdentifiersForFunctionCall(
     NodeModel model, AssociativeNode rhs, List<AssociativeNode> resultAst)
 {
     if (model.OutPortData.Count == 1)
     {
         resultAst.Add(AstFactory.BuildAssignment(model.AstIdentifierForPreview, rhs));
         resultAst.Add(
             AstFactory.BuildAssignment(
                 model.GetAstIdentifierForOutputIndex(0),
                 model.AstIdentifierForPreview));
     }
     else
         base.AssignIdentifiersForFunctionCall(model, rhs, resultAst);
 }
Ejemplo n.º 9
0
        /// <summary>
        /// This function creates TypedParameter
        /// </summary>
        /// <param name="parameter">parameter name</param>
        /// <param name="type">parameter type</param>
        /// <param name="defaultValue">parameter default value</param>
        /// <param name="shortArgumentName">short name is used as tooltip</param>
        /// <param name="summary">parameter description</param>
        public TypedParameter(string parameter, ProtoCore.Type type, AssociativeNode defaultValue = null, string shortArgumentName = null, string summary = null)
        {
            if (parameter == null)
                throw new ArgumentNullException("parameter");

            Name = parameter;
            Type = type;
            DefaultValue = defaultValue;

            if (defaultValue != null)
                defaultValueString = defaultValue.ToString();
            else
                defaultValueString = shortArgumentName;

            this.summary = summary;
        }
Ejemplo n.º 10
0
        protected override void BuildAstForPartialMultiOutput(
            NodeModel model, AssociativeNode rhs, List<AssociativeNode> resultAst)
        {
            base.BuildAstForPartialMultiOutput(model, rhs, resultAst);

            var emptyList = AstFactory.BuildExprList(new List<AssociativeNode>());
            var previewIdInit = AstFactory.BuildAssignment(model.AstIdentifierForPreview, emptyList);

            resultAst.Add(previewIdInit);
            resultAst.AddRange(
                Definition.ReturnKeys.Select(
                    (rtnKey, idx) =>
                        AstFactory.BuildAssignment(
                            AstFactory.BuildIdentifier(
                                model.AstIdentifierForPreview.Name,
                                AstFactory.BuildStringNode(rtnKey)),
                            model.GetAstIdentifierForOutputIndex(idx))));
        }
Ejemplo n.º 11
0
        public static bool IsReturnExpressionNode(ProtoCore.AST.AssociativeAST.AssociativeNode node)
        {
            ProtoCore.AST.AssociativeAST.BinaryExpressionNode binaryNode =
                node as ProtoCore.AST.AssociativeAST.BinaryExpressionNode;

            if (null == binaryNode)
            {
                return(false);
            }

            ProtoCore.AST.AssociativeAST.IdentifierNode retNode = binaryNode.LeftNode as ProtoCore.AST.AssociativeAST.IdentifierNode;
            if (null == retNode)
            {
                return(false);
            }

            return(retNode.Value == ProtoCore.DSDefinitions.Keyword.Return);
        }
        public static string GenerateIdentListNameString(ProtoCore.AST.AssociativeAST.AssociativeNode node)
        {
            ProtoCore.AST.AssociativeAST.IdentifierListNode iNode;
            ProtoCore.AST.AssociativeAST.AssociativeNode    leftNode = node;
            List <string> stringList = new List <string>();

            while (leftNode is ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                iNode    = leftNode as ProtoCore.AST.AssociativeAST.IdentifierListNode;
                leftNode = iNode.LeftNode;
                if (iNode.RightNode is ProtoCore.AST.AssociativeAST.IdentifierNode)
                {
                    ProtoCore.AST.AssociativeAST.IdentifierNode currentNode = (iNode.RightNode as ProtoCore.AST.AssociativeAST.IdentifierNode);
                    stringList.Add(currentNode.ToString());
                }
                else if (iNode.RightNode is ProtoCore.AST.AssociativeAST.FunctionCallNode)
                {
                    ProtoCore.AST.AssociativeAST.FunctionCallNode fCall = iNode.RightNode as ProtoCore.AST.AssociativeAST.FunctionCallNode;
                    stringList.Add(fCall.Function.Name);
                }
                else
                {
                    return(string.Empty);
                }
            }
            stringList.Add(leftNode.ToString());

            stringList.Reverse();

            string retString = string.Empty;

            foreach (string s in stringList)
            {
                retString += s;
                retString += '.';
            }

            // Remove the last dot
            retString = retString.Remove(retString.Length - 1);

            return(retString);
        }
Ejemplo n.º 13
0
 /// <summary>
 ///     Produces AST for a partial function application of a multi-output function.
 /// </summary>
 /// <param name="model">NodeModel to produce AST for.</param>
 /// <param name="rhs">AST representing the partial application. This will need to be used to assign all output port identifiers.</param>
 /// <param name="resultAst">Result accumulator: add all new output AST to this list.</param>
 protected virtual void BuildAstForPartialMultiOutput(
     NodeModel model, AssociativeNode rhs, List<AssociativeNode> resultAst)
 {
     var missingAmt =
         Enumerable.Range(0, model.InPortData.Count).Count(x => !model.HasInput(x));
     var tmp =
         AstFactory.BuildIdentifier("__partial_" + model.GUID.ToString().Replace('-', '_'));
     resultAst.Add(AstFactory.BuildAssignment(tmp, rhs));
     resultAst.AddRange(
         (Definition.ReturnKeys ?? Enumerable.Empty<string>()).Select(
             AstFactory.BuildStringNode)
             .Select(
                 (rtnKey, index) =>
                     AstFactory.BuildAssignment(
                         model.GetAstIdentifierForOutputIndex(index),
                         AstFactory.BuildFunctionObject(
                             "__ComposeBuffered",
                             3,
                             new[] { 0, 1 },
                             new List<AssociativeNode>
                             {
                                 AstFactory.BuildExprList(
                                     new List<AssociativeNode>
                                     {
                                         AstFactory.BuildFunctionObject(
                                             "__GetOutput",
                                             2,
                                             new[] { 1 },
                                             new List<AssociativeNode>
                                             {
                                                 AstFactory.BuildNullNode(),
                                                 rtnKey
                                             }),
                                         tmp
                                     }),
                                 AstFactory.BuildIntNode(missingAmt),
                                 AstFactory.BuildNullNode()
                             }))));
 }
Ejemplo n.º 14
0
        private void EmitFunctionCallNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, 
            ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, ProtoCore.AST.AssociativeAST.BinaryExpressionNode parentNode = null)
        {
            FunctionCallNode fnode = node as FunctionCallNode;
           
            bool dependentState = false;
            if (null != graphNode)
            {
                dependentState = graphNode.allowDependents;
                if (fnode != null && !ProtoCore.Utils.CoreUtils.IsSetter(fnode.Function.Name))
                {
                    graphNode.allowDependents = true;
                }
            }

            bool emitReplicationGuideFlag = emitReplicationGuide;
            bool lhsIndexing = false;
            if (graphNode != null)
            {
                lhsIndexing = graphNode.isIndexingLHS;
                graphNode.isIndexingLHS = false;
            }
            bool arrayIndexing = IsAssociativeArrayIndexing;
            IsAssociativeArrayIndexing = false;


            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
            {
                // Handle static calls to reflect the original call
                BuildRealDependencyForIdentList(graphNode);
                FunctionDotCallNode fcall = node as FunctionDotCallNode;
                if (fcall != null)
                {
                    if (fcall.isLastSSAIdentListFactor)
                    {
                        Validity.Assert(null != ssaPointerStack);
                        ssaPointerStack.Pop();
                    }
                }
            }

            ProtoCore.DSASM.ProcedureNode procNode = TraverseFunctionCall(node, null, ProtoCore.DSASM.Constants.kInvalidIndex, 0, ref inferedType, graphNode, subPass, parentNode);

            emitReplicationGuide = emitReplicationGuideFlag;
            if (graphNode != null)
            {
                graphNode.isIndexingLHS = lhsIndexing;
            }

            if (null != procNode && !procNode.IsConstructor)
            {
                functionCallStack.Add(procNode);
                if (null != graphNode)
                {
                    graphNode.firstProc = procNode;
                    graphNode.firstProcRefIndex = graphNode.dependentList.Count - 1;

                    // Memoize the graphnode that contains a user-defined function call in the global scope
                    bool inGlobalScope = ProtoCore.DSASM.Constants.kGlobalScope == globalProcIndex && ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex;
                    if (!procNode.IsExternal && inGlobalScope)
                    {
                        core.GraphNodeCallList.Add(graphNode);
                    }
                }
            }
            IsAssociativeArrayIndexing = arrayIndexing;

            inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID;

            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
            {
                if (fnode != null && fnode.ArrayDimensions != null)
                {
                    emitReplicationGuideFlag = emitReplicationGuide;
                    emitReplicationGuide = false;
                    int dimensions = DfsEmitArrayIndexHeap(fnode.ArrayDimensions, graphNode);
                    EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]");
                    EmitPushArrayIndex(dimensions);
                    fnode.ArrayDimensions = null;
                    emitReplicationGuide = emitReplicationGuideFlag;
                }

                List<AssociativeNode> replicationGuides = null;
                AtLevelNode atLevel = null;
                bool isRangeExpression = false;

                if (fnode != null)
                {
                    atLevel = fnode.AtLevel;
                    replicationGuides = fnode.ReplicationGuides;
                    isRangeExpression = fnode.Function.Name.Equals(Constants.kFunctionRangeExpression);
                }
                else if (node is FunctionDotCallNode)
                {
                    FunctionCallNode funcNode = (node as FunctionDotCallNode).FunctionCall;
                    var function = funcNode.Function as IdentifierNode;
                    replicationGuides = function.ReplicationGuides;
                    atLevel = function.AtLevel;
                }

                // YuKe: The replication guide for range expression will be 
                // generated in EmitRangeExprNode(). 
                // 
                // TODO: Revisit this piece of code to see how to handle array
                // index.
                if (!isRangeExpression && emitReplicationGuide)
                {
                    EmitAtLevel(atLevel);
                    EmitReplicationGuides(replicationGuides);
                }
            }

            if (null != graphNode)
            {
                graphNode.allowDependents = dependentState;
            }
        }
Ejemplo n.º 15
0
        private void EmitFunctionDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, GraphNode graphNode = null)
        {
            bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalFuncBody == compilePass;
            bool parseMemberFunctionBody = ProtoCore.DSASM.Constants.kGlobalScope != globalClassIndex && ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncBody == compilePass;

            FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;
            localFunctionDefNode = funcDef;

            if (funcDef.IsAssocOperator)
            {
                isAssocOperator = true;
            }
            else
            {
                isAssocOperator = false;
            }

            bool hasReturnStatement = false;
            ProtoCore.DSASM.CodeBlockType origCodeBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;
            if (IsParsingGlobalFunctionSig() || IsParsingMemberFunctionSig())
            {
                Validity.Assert(null == localProcedure);
                localProcedure = new ProtoCore.DSASM.ProcedureNode();

                localProcedure.Name = funcDef.Name;
                localProcedure.PC = ProtoCore.DSASM.Constants.kInvalidIndex;
                localProcedure.LocalCount = 0; // Defer till all locals are allocated
                var uid = core.TypeSystem.GetType(funcDef.ReturnType.Name);
                var rank = funcDef.ReturnType.rank;
                var returnType = core.TypeSystem.BuildTypeObject(uid, rank); 
                if (returnType.UID == (int)PrimitiveType.kInvalidType)
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kReturnTypeUndefined, funcDef.ReturnType.Name, funcDef.Name);
                    buildStatus.LogWarning(WarningID.kTypeUndefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    returnType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, rank);
                }
                localProcedure.ReturnType = returnType;
                localProcedure.IsConstructor = false;
                localProcedure.IsStatic = funcDef.IsStatic;
                localProcedure.RuntimeIndex = codeBlock.codeBlockId;
                localProcedure.AccessModifier = funcDef.Access;
                localProcedure.IsExternal = funcDef.IsExternLib;
                localProcedure.IsAutoGenerated = funcDef.IsAutoGenerated;
                localProcedure.ClassID = globalClassIndex;
                localProcedure.IsAssocOperator = funcDef.IsAssocOperator;
                localProcedure.IsAutoGeneratedThisProc = funcDef.IsAutoGeneratedThisProc;

                localProcedure.MethodAttribute = funcDef.MethodAttributes;

                int peekFunctionindex = ProtoCore.DSASM.Constants.kInvalidIndex;

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    peekFunctionindex = codeBlock.procedureTable.Procedures.Count;
                }
                else
                {
                    peekFunctionindex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures.Count;
                }

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                string functionDescription = localProcedure.Name;
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        var argInfo = BuildArgumentInfoFromVarDeclNode(argNode);
                        localProcedure.ArgumentInfos.Add(argInfo);

                        var argType = BuildArgumentTypeFromVarDeclNode(argNode, graphNode);
                        localProcedure.ArgumentTypes.Add(argType);

                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(argInfo.Name, argType));

                        functionDescription += argNode.ArgumentType.ToString();
                    }
                    localProcedure.HashID = functionDescription.GetHashCode();
                    localProcedure.IsVarArg = funcDef.Signature.IsVarArg;
                }

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    globalProcIndex = codeBlock.procedureTable.Append(localProcedure);
                }
                else
                {
                    globalProcIndex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Append(localProcedure);
                }

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalProcIndex)
                {
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, globalProcIndex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("B2CB2093");
                        }
                    });                   
                }
                else
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kMethodAlreadyDefined, localProcedure.Name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionAlreadyDefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    funcDef.skipMe = true;
                }
            }
            else if (parseGlobalFunctionBody || parseMemberFunctionBody)
            {
                if (CoreUtils.IsDisposeMethod(node.Name))
                {
                    core.Options.EmitBreakpoints = false;
                }

                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode, graphNode);
                        argList.Add(argType);
                    }
                }

                // Get the exisitng procedure that was added on the previous pass
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    var procNode = codeBlock.procedureTable.GetFunctionBySignature(funcDef.Name, argList);
                    globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;
                    localProcedure = codeBlock.procedureTable.Procedures[globalProcIndex];
                }
                else
                {
                    var procNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.GetFunctionBySignature(funcDef.Name, argList);
                    globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;
                    localProcedure = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                }

                Validity.Assert(null != localProcedure);

                // code gen the attribute 
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc);
                localProcedure.PC = pc;

                // Copy the active function to the core so nested language blocks can refer to it
                core.ProcNode = localProcedure;

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    //Traverse default argument
                    emitDebugInfo = false;
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.ArgumentInfos)
                    {
                        if (!argNode.IsDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.DefaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        var iNodeTemp = AstFactory.BuildIdentifier(core.GenerateTempVar());
                        var bNodeTemp = AstFactory.BuildAssignment(iNodeTemp, bNode.LeftNode);
                        bNodeTemp.IsProcedureOwned = true;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        icNode.IsAutoGenerated = true;
                        BinaryExpressionNode cExprNode = new BinaryExpressionNode();
                        cExprNode.Optr = ProtoCore.DSASM.Operator.eq;
                        cExprNode.LeftNode = iNodeTemp;
                        cExprNode.RightNode = new DefaultArgNode();
                        icNode.ConditionExpression = cExprNode;
                        icNode.TrueExpression = bNode.RightNode;
                        icNode.FalseExpression = iNodeTemp;
                        bNodeTemp.LeftNode = bNode.LeftNode;
                        bNodeTemp.RightNode = icNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                    }
                    emitDebugInfo = true;

                    EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature));

                    ProtoCore.Type itype = new ProtoCore.Type();

                    hasReturnStatement = EmitCodeBlock(funcDef.FunctionBody.Body, ref itype, subPass, true);

                    // Build dependency within the function
                    ProtoCore.AssociativeEngine.Utils.BuildGraphNodeDependencies(
                        codeBlock.instrStream.dependencyGraph.GetGraphNodesAtScope(globalClassIndex, globalProcIndex));


                    EmitCompileLogFunctionEnd();

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.LocalCount = core.BaseOffset;

                    if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                    {
                        localProcedure.LocalCount = core.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in codeBlock.symbolTable.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.ID && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.LocalCount;
                            }
                        }
                    }
                    else
                    {
                        core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[localProcedure.ID].LocalCount = core.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.ID && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.LocalCount;
                            }
                        }
                    }

                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.PC;
                    record.locals = localProcedure.LocalCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = localProcedure.ID;
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                else if (funcDef.BuiltInMethodId != ProtoCore.Lang.BuiltInMethods.MethodID.kInvalidMethodID)
                {
                    fep = new ProtoCore.Lang.BuiltInFunctionEndPoint(funcDef.BuiltInMethodId);
                }
                else
                {
                    ProtoCore.Lang.JILActivationRecord jRecord = new ProtoCore.Lang.JILActivationRecord();
                    jRecord.pc = localProcedure.PC;
                    jRecord.locals = localProcedure.LocalCount;
                    jRecord.classIndex = globalClassIndex;
                    jRecord.funcIndex = localProcedure.ID;

                    ProtoCore.Lang.FFIActivationRecord record = new ProtoCore.Lang.FFIActivationRecord();
                    record.JILRecord = jRecord;
                    record.FunctionName = funcDef.Name;
                    record.ModuleName = funcDef.ExternLibName;
                    record.ModuleType = "dll";
                    record.IsDNI = funcDef.IsDNI;
                    record.ReturnType = funcDef.ReturnType;
                    record.ParameterTypes = localProcedure.ArgumentTypes;
                    fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                }

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.ArgumentTypes.Count];
                fep.BlockScope = codeBlock.codeBlockId;
                fep.ClassOwnerIndex = localProcedure.ClassID;
                fep.procedureNode = localProcedure;
                localProcedure.ArgumentTypes.CopyTo(fep.FormalParams, 0);

                // 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.InitGlobalFunctionEntry(classIndexAtCallsite);

                // Get the function group of the current class and see if the current function exists
                Dictionary<string, FunctionGroup> fgroup = core.FunctionTable.GlobalFuncTable[classIndexAtCallsite];
                if (!fgroup.ContainsKey(funcDef.Name))
                {
                    // If any functions in the base class have the same name, append them here
                    int ci = classIndexAtCallsite - 1;
                    if (ProtoCore.DSASM.Constants.kInvalidIndex != ci)
                    {
                        ProtoCore.DSASM.ClassNode cnode = core.ClassTable.ClassNodes[ci];
                        if (cnode.Bases.Count > 0)
                        {
                            Validity.Assert(1 == cnode.Bases.Count, "We don't support multiple inheritance yet");

                            ci = cnode.Bases[0];

                            Dictionary<string, FunctionGroup> tgroup = new Dictionary<string, FunctionGroup>();
                            int callsiteCI = ci + 1;
                            bool bSucceed = core.FunctionTable.GlobalFuncTable.TryGetValue(callsiteCI, out tgroup);
                            if (bSucceed)
                            {
                                if (tgroup.ContainsKey(funcDef.Name))
                                {
                                    // Get that base group - the group of function from the baseclass
                                    FunctionGroup basegroup = new FunctionGroup();
                                    bSucceed = tgroup.TryGetValue(funcDef.Name, out basegroup);
                                    if (bSucceed)
                                    {
                                        // Copy all non-private feps from the basegroup into this the new group
                                        FunctionGroup newGroup = new FunctionGroup();
                                        newGroup.CopyVisible(basegroup.FunctionEndPoints);

                                        // Append the new fep 
                                        newGroup.FunctionEndPoints.Add(fep);

                                        // Copy the new group to this class table
                                        core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, newGroup);
                                    }
                                }
                                else
                                {
                                    // Create a new function group in this class
                                    ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                                    funcGroup.FunctionEndPoints.Add(fep);

                                    // Add this group to the class function tables
                                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                                }
                            }
                            else
                            {
                                // Create a new function group in this class
                                ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                                funcGroup.FunctionEndPoints.Add(fep);

                                // Add this group to the class function tables
                                core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                            }
                            cnode = core.ClassTable.ClassNodes[ci];
                        }
                        else
                        {
                            // Create a new function group in this class
                            ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                            funcGroup.FunctionEndPoints.Add(fep);

                            // Add this group to the class function tables
                            core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                        }
                    }
                    else
                    {
                        // Create a new function group in this class
                        ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                        funcGroup.FunctionEndPoints.Add(fep);

                        // Add this group to the class function tables
                        core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                    }
                }
                else
                {
                    // Add this fep into the exisitng function group
                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite][funcDef.Name].FunctionEndPoints.Add(fep);
                }

                if (!hasReturnStatement && !funcDef.IsExternLib)
                {
                    if (!core.Options.SuppressFunctionResolutionWarning)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kFunctionNotReturnAtAllCodePaths, localProcedure.Name);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kMissingReturnStatement, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    }
                    EmitReturnNull();
                }

                if (CoreUtils.IsDisposeMethod(node.Name))
                {
                    core.Options.EmitBreakpoints = true;
                }
            }

            core.ProcNode = localProcedure = null;
            codeBlock.blockType = origCodeBlockType;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            localFunctionDefNode = null;
            core.BaseOffset = 0;
            argOffset = 0;
            isAssocOperator = false;
        }
Ejemplo n.º 16
0
        private int AllocateArg(
            string ident,
            int funcIndex,
            ProtoCore.Type datatype,
            int size = 1,
            int datasize = ProtoCore.DSASM.Constants.kPrimitiveSize,
            AssociativeNode nodeArray = null,
            ProtoCore.DSASM.MemoryRegion region = ProtoCore.DSASM.MemoryRegion.kMemStack)
        {
            ProtoCore.DSASM.SymbolNode node = new ProtoCore.DSASM.SymbolNode(
                ident,
                ProtoCore.DSASM.Constants.kInvalidIndex,
                ProtoCore.DSASM.Constants.kInvalidIndex,
                funcIndex,
                datatype,
                datatype,
                size,
                datasize,
                true,
                codeBlock.symbolTable.RuntimeIndex,
                region,
                false,
                null,
                globalClassIndex);

            node.name = ident;
            node.isTemp = ident.StartsWith("%");
            node.size = datasize;
            node.functionIndex = funcIndex;
            node.absoluteFunctionIndex = funcIndex;
            node.datatype = datatype;
            node.isArgument = true;
            node.memregion = ProtoCore.DSASM.MemoryRegion.kMemStack;
            node.classScope = globalClassIndex;
            node.absoluteClassScope = globalClassIndex;
            node.codeBlockId = codeBlock.codeBlockId;
            if (this.isEmittingImportNode)
                node.ExternLib = core.CurrentDSFileName;

            // Comment Jun: The local count will be adjusted and all dependent symbol offsets after the function body has been traversed
            int locOffset = 0;

            // This will be offseted by the local count after locals have been allocated
            node.index = -1 - ProtoCore.DSASM.StackFrame.kStackFrameSize - (locOffset + argOffset);
            ++argOffset;

            int symbolindex = ProtoCore.DSASM.Constants.kInvalidIndex;
            if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
            {
                symbolindex = core.ClassTable.ClassNodes[globalClassIndex].Symbols.Append(node);
            }
            else
            {
                symbolindex = codeBlock.symbolTable.Append(node);
            }
            return symbolindex;
        }
Ejemplo n.º 17
0
        private ProtoCore.AssociativeGraph.UpdateNodeRef GetUpdatedNodeRef(AssociativeNode node)
        {
            if (null == localProcedure)
            {
                return null;
            }

            // Get the lhs symbol list
            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = globalClassIndex;
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
            DFSGetSymbolList(node, ref type, leftNodeRef);

     
            return leftNodeRef;
        }
Ejemplo n.º 18
0
        private void TraverseAndAppendThisPtrArg(AssociativeNode node, ref AssociativeNode newIdentList)
        {
            if (node is BinaryExpressionNode)
            {
                TraverseAndAppendThisPtrArg((node as BinaryExpressionNode).LeftNode, ref newIdentList);
                TraverseAndAppendThisPtrArg((node as BinaryExpressionNode).RightNode, ref newIdentList);
            }
            else if (node is IdentifierListNode)
            {
                // Travere until the left most identifier
                IdentifierListNode binaryNode = node as IdentifierListNode;
                while ((binaryNode as IdentifierListNode).LeftNode is IdentifierListNode)
                {
                    binaryNode = (binaryNode as IdentifierListNode).LeftNode as IdentifierListNode;
                }
                
                IdentifierNode identNode = null;
                if ((binaryNode as IdentifierListNode).LeftNode is IdentifierNode)
                {
                    identNode = (binaryNode as IdentifierListNode).LeftNode as IdentifierNode;
                }

                Validity.Assert(identNode is IdentifierNode);

                string leftMostSymbolName = identNode.Name;

                // Is it a this pointer?
                if (leftMostSymbolName.Equals(ProtoCore.DSDefinitions.Keyword.This))
                {
                    // Then just replace it
                    identNode.Name = identNode.Value = ProtoCore.DSASM.Constants.kThisPointerArgName;

                    newIdentList = node;
                    return;
                }



                // Is the left most symbol a member?
                SymbolNode symbolnode;
                bool isAccessible = false;
                bool isAllocated = VerifyAllocation(leftMostSymbolName, globalClassIndex, ProtoCore.DSASM.Constants.kGlobalScope, out symbolnode, out isAccessible);
                if (!isAllocated)
                {
                    newIdentList = node;
                    return;
                }

                IdentifierListNode identList = new IdentifierListNode();

                IdentifierNode lhsThisArg = new IdentifierNode();
                lhsThisArg.Name = ProtoCore.DSASM.Constants.kThisPointerArgName;
                lhsThisArg.Value = ProtoCore.DSASM.Constants.kThisPointerArgName;

                identList.LeftNode = lhsThisArg;
                identList.Optr = Operator.dot;
                identList.RightNode = identNode;

                // Update the last binary dot node with the new dot node
                binaryNode.LeftNode = identList;

                newIdentList = binaryNode;
            }

            else if (node is FunctionCallNode)
            {
                FunctionCallNode fCall = node as FunctionCallNode;

                for(int n = 0; n < fCall.FormalArguments.Count; ++n)
                {
                    AssociativeNode argNode = fCall.FormalArguments[n];
                    TraverseAndAppendThisPtrArg(argNode, ref argNode);
                    fCall.FormalArguments[n] = argNode;
                }
                newIdentList = fCall;
            }
            else if (node is FunctionDotCallNode)
            {
                FunctionDotCallNode dotCall = node as FunctionDotCallNode;
                string name = dotCall.DotCall.FormalArguments[0].Name;

                // TODO Jun: If its a constructor, leave it as it is. 
                // After the first version of global instance functioni s implemented, 2nd phase would be to remove dotarg methods completely
                bool isConstructorCall = false;
                if (null != name)
                {
                    isConstructorCall = ProtoCore.DSASM.Constants.kInvalidIndex != core.ClassTable.IndexOf(name);
                }

                FunctionCallNode fCall = (node as FunctionDotCallNode).FunctionCall;


                if (isConstructorCall)
                {
                    newIdentList = node;
                }
                else
                {
                    for (int n = 0; n < fCall.FormalArguments.Count; ++n)
                    {
                        AssociativeNode argNode = fCall.FormalArguments[n];
                        TraverseAndAppendThisPtrArg(argNode, ref argNode);
                        fCall.FormalArguments[n] = argNode;
                    }
                    newIdentList = node;
                }
            }
            else if (node is IdentifierNode)
            {
                string identName = (node as IdentifierNode).Name;
                if (identName.Equals(ProtoCore.DSDefinitions.Keyword.Return))
                {
                    newIdentList = node;
                    return;
                }

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    newIdentList = node;
                    return;
                }

                // Temp are not member vars
                if (ProtoCore.Utils.CoreUtils.IsAutoGeneratedVar(identName))
                {
                    newIdentList = node;
                    return;
                }

                // Is it a member
                SymbolNode symbolnode;
                bool isAccessible = false;

                bool isAllocated = VerifyAllocation(identName, globalClassIndex, ProtoCore.DSASM.Constants.kGlobalScope, out symbolnode, out isAccessible);
                if (!isAllocated)
                {
                    newIdentList = node;
                    return;
                }

                IdentifierListNode identList = new IdentifierListNode();

                IdentifierNode lhsThisArg = new IdentifierNode();
                lhsThisArg.Name = ProtoCore.DSASM.Constants.kThisPointerArgName;
                lhsThisArg.Value = ProtoCore.DSASM.Constants.kThisPointerArgName;

                identList.LeftNode = lhsThisArg;
                identList.Optr = Operator.dot;
                identList.RightNode = node;

                newIdentList = identList;
            }
            else
            {
                newIdentList = node;
            }
        }
Ejemplo n.º 19
0
        private void EmitInlineConditionalNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, ProtoCore.AST.AssociativeAST.BinaryExpressionNode parentNode = null)
        {
            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            bool isInlineConditionalFlag = false;
            int startPC = pc;
            bool isReturn = false;
            if (graphNode != null)
            {
                isInlineConditionalFlag = graphNode.isInlineConditional;
                graphNode.isInlineConditional = true;
                startPC = graphNode.updateBlock.startpc;
                isReturn = graphNode.isReturn;
            }

            InlineConditionalNode inlineConditionalNode = node as InlineConditionalNode;
            // TODO: Jun, this 'if' condition needs to be removed as it was the old implementation - pratapa
            if (inlineConditionalNode.IsAutoGenerated)
            {
                // Normal inline conditional

                IfStatementNode ifNode = new IfStatementNode();
                ifNode.ifExprNode = inlineConditionalNode.ConditionExpression;
                List<AssociativeNode> ifBody = new List<AssociativeNode>();
                List<AssociativeNode> elseBody = new List<AssociativeNode>();
                ifBody.Add(inlineConditionalNode.TrueExpression);
                elseBody.Add(inlineConditionalNode.FalseExpression);
                ifNode.IfBody = ifBody;
                ifNode.ElseBody = elseBody;

                EmitIfStatementNode(ifNode, ref inferedType, graphNode);
            }
            else
            {
                // CPS inline conditional
                
                FunctionCallNode inlineCall = new FunctionCallNode();
                IdentifierNode identNode = new IdentifierNode();
                identNode.Name = ProtoCore.DSASM.Constants.kInlineConditionalMethodName;
                inlineCall.Function = identNode;

                DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions;
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint;
                core.DebuggerProperties.breakOptions = newOptions;

                core.DebuggerProperties.highlightRange = new ProtoCore.CodeModel.CodeRange
                {
                    StartInclusive = new ProtoCore.CodeModel.CodePoint
                    {
                        LineNo = parentNode.line,
                        CharNo = parentNode.col
                    },

                    EndExclusive = new ProtoCore.CodeModel.CodePoint
                    {
                        LineNo = parentNode.endLine,
                        CharNo = parentNode.endCol
                    }
                };

                // As SSA conversion is enabled, we have got the values of
                // true and false branch, so it isn't necessary to create 
                // language blocks.
                if (core.Options.GenerateSSA)
                {
                    inlineCall.FormalArguments.Add(inlineConditionalNode.ConditionExpression);
                    inlineCall.FormalArguments.Add(inlineConditionalNode.TrueExpression);
                    inlineCall.FormalArguments.Add(inlineConditionalNode.FalseExpression);
                }
                else
                {
                    // True condition language block
                    BinaryExpressionNode bExprTrue = AstFactory.BuildReturnStatement(inlineConditionalNode.TrueExpression);

                    LanguageBlockNode langblockT = new LanguageBlockNode();
                    int trueBlockId = Constants.kInvalidIndex;
                    langblockT.codeblock.Language = ProtoCore.Language.Associative;
                    core.AssocNode = bExprTrue;
                    core.InlineConditionalBodyGraphNodes.Push(new List<GraphNode>());
                    EmitDynamicLanguageBlockNode(langblockT, bExprTrue, ref inferedType, ref trueBlockId, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone);
                    List<GraphNode> trueBodyNodes = core.InlineConditionalBodyGraphNodes.Pop();

                    // Append dependent nodes of the inline conditional 
                    foreach (GraphNode gnode in trueBodyNodes)
                        foreach (GraphNode dNode in gnode.dependentList)
                            graphNode.PushDependent(dNode);

                    core.AssocNode = null;
                    DynamicBlockNode dynBlockT = new DynamicBlockNode(trueBlockId);

                    // False condition language block
                    BinaryExpressionNode bExprFalse = AstFactory.BuildReturnStatement(inlineConditionalNode.FalseExpression);

                    LanguageBlockNode langblockF = new LanguageBlockNode();
                    int falseBlockId = Constants.kInvalidIndex;
                    langblockF.codeblock.Language = ProtoCore.Language.Associative;
                    core.AssocNode = bExprFalse;
                    core.InlineConditionalBodyGraphNodes.Push(new List<GraphNode>());
                    EmitDynamicLanguageBlockNode(langblockF, bExprFalse, ref inferedType, ref falseBlockId, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone);
                    List<GraphNode> falseBodyNodes = core.InlineConditionalBodyGraphNodes.Pop();

                    // Append dependent nodes of the inline conditional 
                    foreach (GraphNode gnode in falseBodyNodes)
                        foreach (GraphNode dNode in gnode.dependentList)
                            graphNode.PushDependent(dNode);

                    core.AssocNode = null;
                    DynamicBlockNode dynBlockF = new DynamicBlockNode(falseBlockId);

                    inlineCall.FormalArguments.Add(inlineConditionalNode.ConditionExpression);
                    inlineCall.FormalArguments.Add(dynBlockT);
                    inlineCall.FormalArguments.Add(dynBlockF);
                }

                core.DebuggerProperties.breakOptions = oldOptions;
                core.DebuggerProperties.highlightRange = new ProtoCore.CodeModel.CodeRange
                {
                    StartInclusive = new ProtoCore.CodeModel.CodePoint
                    {
                        LineNo = Constants.kInvalidIndex,
                        CharNo = Constants.kInvalidIndex
                    },

                    EndExclusive = new ProtoCore.CodeModel.CodePoint
                    {
                        LineNo = Constants.kInvalidIndex,
                        CharNo = Constants.kInvalidIndex
                    }
                };

                // Save the pc and store it after the call
                EmitFunctionCallNode(inlineCall, ref inferedType, false, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                EmitFunctionCallNode(inlineCall, ref inferedType, false, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, parentNode);

                // Need to restore those settings.
                if (graphNode != null)
                {
                    graphNode.isInlineConditional = isInlineConditionalFlag;
                    graphNode.updateBlock.startpc = startPC;
                    graphNode.isReturn = isReturn;
                }
            }
        }
Ejemplo n.º 20
0
        private void EmitLHSIdentifierListForBinaryExpr(AssociativeNode bnode, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode binaryExpr = bnode as BinaryExpressionNode;
            if (binaryExpr == null || !(binaryExpr.LeftNode is IdentifierListNode))
            {
                return;
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == graphNode.updateBlock.startpc)
            {
                graphNode.updateBlock.startpc = pc;
            }

            // This is a setter, so disable dependents
            graphNode.allowDependents = false;
            IdentifierListNode theLeftNode = binaryExpr.LeftNode as IdentifierListNode;
            bool isThisPtr = null != theLeftNode.LeftNode.Name && theLeftNode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This);
            if (isThisPtr)
            {
                graphNode.allowDependents = true;
            }

            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = AutoGenerateUpdateReference(binaryExpr.LeftNode, graphNode);
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeArgRef = __To__Deprecate__AutoGenerateUpdateArgumentReference(binaryExpr.LeftNode, graphNode);

            ProtoCore.AST.Node lnode = binaryExpr.LeftNode;
            NodeUtils.CopyNodeLocation(lnode, binaryExpr);

            ProtoCore.AST.Node rnode = binaryExpr.RightNode;
            bool isCollapsed = false;
            EmitGetterSetterForIdentList(lnode, ref inferedType, graphNode, subPass, out isCollapsed, rnode);

            graphNode.allowDependents = true;

            // Dependency
            if (!isTempExpression)
            {
                // Dependency graph top level symbol 
                graphNode.updateNodeRefList.Add(leftNodeRef);
                graphNode.updateNodeRefList[0].nodeList[0].dimensionNodeList = graphNode.dimensionNodeList;

                // @keyu: foo.id = 42; will generate same leftNodeRef and leftNodeArgRef
                if (!isThisPtr && !leftNodeRef.Equals(leftNodeArgRef))
                {
                    graphNode.updateNodeRefList.Add(leftNodeArgRef);
                }

                //
                // If the lhs of the expression is an identifier list, it could have been modified. 
                // It must then be a dependent of its own graphnode
                //
                //      class C
                //      {
                //          x : int;
                //          constructor C(i:int)
                //          {
                //              x = i;
                //          }
                //      }
                //
                //      i = 10;
                //      a = C.C(i);
                //      a.x = 15; -> re-execute this line ... as 'a' was redefined and its members now changed
                //      val = a.x;
                //      i = 7;
                //

                //
                // If inside a member function, and the lhs is a property, make sure it is not just:
                //      x = y (this.x = y)
                //

                if (core.Options.LHSGraphNodeUpdate)
                {
                    if (!isThisPtr || graphNode.updateNodeRefList[0].nodeList.Count > 1)
                    {
                        ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                        dependentNode.isLHSNode = true;
                        dependentNode.updateNodeRefList.Add(graphNode.updateNodeRefList[0]);
                        graphNode.dependentList.Add(dependentNode);
                    }
                }


                ProtoCore.DSASM.SymbolNode firstSymbol = leftNodeRef.nodeList[0].symbol;
                if (null != firstSymbol)
                {
                    EmitDependency(binaryExpr.ExpressionUID, binaryExpr.modBlkUID, false);
                }

                if (core.Options.GenerateSSA)
                {
                    if (!graphNode.IsSSANode() && !ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(graphNode))
                    {
                        // This is the last expression in the SSA'd expression
                        // Backtrack and assign the this last final assignment graphnode to its associated SSA graphnodes
                        for (int n = codeBlock.instrStream.dependencyGraph.GraphList.Count - 1; n >= 0; --n)
                        {
                            GraphNode currentNode = codeBlock.instrStream.dependencyGraph.GraphList[n];
                            bool isWithinSameScope = currentNode.classIndex == graphNode.classIndex
                                && currentNode.procIndex == graphNode.procIndex;
                            bool isWithinSameExpressionID = currentNode.exprUID == graphNode.exprUID;
                            if (isWithinSameScope && isWithinSameExpressionID)
                            {
                                graphNode.IsLastNodeInSSA = true;
                                codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode = graphNode;
                            }
                        }
                    }
                }


                // Assign the end pc to this graph node's update block
                // Dependency graph construction is complete for this expression
                graphNode.updateBlock.endpc = pc - 1;
                PushGraphNode(graphNode);
                functionCallStack.Clear();
            }
        }
Ejemplo n.º 21
0
        public static ProtoCore.AST.AssociativeAST.AssociativeNode Clone(ProtoCore.AST.AssociativeAST.AssociativeNode rhsNode)
        {
            if (rhsNode is ProtoCore.AST.AssociativeAST.IdentifierNode)
            {
                if (rhsNode is TypedIdentifierNode)
                {
                    return(new ProtoCore.AST.AssociativeAST.TypedIdentifierNode(rhsNode as ProtoCore.AST.AssociativeAST.IdentifierNode));
                }

                return(new ProtoCore.AST.AssociativeAST.IdentifierNode(rhsNode as ProtoCore.AST.AssociativeAST.IdentifierNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                return(new ProtoCore.AST.AssociativeAST.IdentifierListNode(rhsNode as ProtoCore.AST.AssociativeAST.IdentifierListNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.BinaryExpressionNode)
            {
                return(new ProtoCore.AST.AssociativeAST.BinaryExpressionNode(rhsNode as ProtoCore.AST.AssociativeAST.BinaryExpressionNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.FunctionCallNode)
            {
                return(new ProtoCore.AST.AssociativeAST.FunctionCallNode(rhsNode as ProtoCore.AST.AssociativeAST.FunctionCallNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.CodeBlockNode)
            {
                return(new ProtoCore.AST.AssociativeAST.CodeBlockNode(rhsNode as ProtoCore.AST.AssociativeAST.CodeBlockNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ArrayNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ArrayNode(rhsNode as ProtoCore.AST.AssociativeAST.ArrayNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.FunctionDotCallNode)
            {
                return(new ProtoCore.AST.AssociativeAST.FunctionDotCallNode(rhsNode as ProtoCore.AST.AssociativeAST.FunctionDotCallNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ConstructorDefinitionNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ConstructorDefinitionNode(rhsNode as ProtoCore.AST.AssociativeAST.ConstructorDefinitionNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ArgumentSignatureNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ArgumentSignatureNode(rhsNode as ProtoCore.AST.AssociativeAST.ArgumentSignatureNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ExprListNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ExprListNode(rhsNode as ProtoCore.AST.AssociativeAST.ExprListNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.LanguageBlockNode)
            {
                return(new ProtoCore.AST.AssociativeAST.LanguageBlockNode(rhsNode as ProtoCore.AST.AssociativeAST.LanguageBlockNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ThisPointerNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ThisPointerNode(rhsNode as ProtoCore.AST.AssociativeAST.ThisPointerNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.InlineConditionalNode)
            {
                return(new ProtoCore.AST.AssociativeAST.InlineConditionalNode(rhsNode as ProtoCore.AST.AssociativeAST.InlineConditionalNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.RangeExprNode)
            {
                return(new ProtoCore.AST.AssociativeAST.RangeExprNode(rhsNode as ProtoCore.AST.AssociativeAST.RangeExprNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.GroupExpressionNode)
            {
                return(new ProtoCore.AST.AssociativeAST.GroupExpressionNode(rhsNode as ProtoCore.AST.AssociativeAST.GroupExpressionNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ClassDeclNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ClassDeclNode(rhsNode as ProtoCore.AST.AssociativeAST.ClassDeclNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ImportNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ImportNode(rhsNode as ProtoCore.AST.AssociativeAST.ImportNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.VarDeclNode)
            {
                return(new ProtoCore.AST.AssociativeAST.VarDeclNode(rhsNode as ProtoCore.AST.AssociativeAST.VarDeclNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.FunctionDefinitionNode)
            {
                return(new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode(rhsNode as ProtoCore.AST.AssociativeAST.FunctionDefinitionNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.ReplicationGuideNode)
            {
                return(new ProtoCore.AST.AssociativeAST.ReplicationGuideNode(rhsNode as ProtoCore.AST.AssociativeAST.ReplicationGuideNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.IntNode)
            {
                return(new ProtoCore.AST.AssociativeAST.IntNode(rhsNode as ProtoCore.AST.AssociativeAST.IntNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.DoubleNode)
            {
                return(new ProtoCore.AST.AssociativeAST.DoubleNode(rhsNode as ProtoCore.AST.AssociativeAST.DoubleNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.BooleanNode)
            {
                return(new ProtoCore.AST.AssociativeAST.BooleanNode(rhsNode as ProtoCore.AST.AssociativeAST.BooleanNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.CharNode)
            {
                return(new ProtoCore.AST.AssociativeAST.CharNode(rhsNode as ProtoCore.AST.AssociativeAST.CharNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.StringNode)
            {
                return(new ProtoCore.AST.AssociativeAST.StringNode(rhsNode as ProtoCore.AST.AssociativeAST.StringNode));
            }
            else if (rhsNode is ProtoCore.AST.AssociativeAST.NullNode)
            {
                return(new ProtoCore.AST.AssociativeAST.NullNode());
            }
            else if (rhsNode is AtLevelNode)
            {
                return(new AtLevelNode(rhsNode as AtLevelNode));
            }

            // Comment Jun: Leaving this as an assert to can catch unhandled nodes
            Validity.Assert(false);
            return(null);
        }
Ejemplo n.º 22
0
        private static IEnumerable <AST.Node> ParseUserCodeCore(Core core, string expression, string postfixGuid, ref bool parseSuccess)
        {
            List <ProtoCore.AST.Node> astNodes = new List <ProtoCore.AST.Node>();

            core.ResetForPrecompilation();
            core.IsParsingCodeBlockNode = true;
            core.ParsingMode            = ParseMode.AllowNonAssignment;

            ProtoCore.AST.Node codeBlockNode = ProtoCore.Utils.ParserUtils.ParseWithCore(expression, core);
            parseSuccess = true;
            List <ProtoCore.AST.Node> nodes = ParserUtils.GetAstNodes(codeBlockNode);

            Validity.Assert(nodes != null);

            int index = 0;

            foreach (var node in nodes)
            {
                ProtoCore.AST.AssociativeAST.AssociativeNode n = node as ProtoCore.AST.AssociativeAST.AssociativeNode;
                ProtoCore.Utils.Validity.Assert(n != null);

                // Append the temporaries only if it is not a function def or class decl
                bool isFunctionOrClassDef = n is FunctionDefinitionNode || n is ClassDeclNode;

                // Handle non Binary expression nodes separately
                if (n is ProtoCore.AST.AssociativeAST.ModifierStackNode)
                {
                    core.BuildStatus.LogSemanticError("Modifier Blocks are not supported currently.");
                }
                else if (n is ProtoCore.AST.AssociativeAST.ImportNode)
                {
                    core.BuildStatus.LogSemanticError("Import statements are not supported in CodeBlock Nodes.");
                }
                else if (isFunctionOrClassDef)
                {
                    // Add node as it is
                    astNodes.Add(node);
                }
                else
                {
                    // Handle temporary naming for temporary Binary exp. nodes and non-assignment nodes
                    BinaryExpressionNode ben = node as BinaryExpressionNode;
                    if (ben != null && ben.Optr == ProtoCore.DSASM.Operator.assign)
                    {
                        ModifierStackNode mNode = ben.RightNode as ModifierStackNode;
                        if (mNode != null)
                        {
                            core.BuildStatus.LogSemanticError("Modifier Blocks are not supported currently.");
                        }
                        IdentifierNode lNode = ben.LeftNode as IdentifierNode;
                        if (lNode != null && lNode.Value == ProtoCore.DSASM.Constants.kTempProcLeftVar)
                        {
                            string name = string.Format("temp_{0}_{1}", index++, postfixGuid);
                            BinaryExpressionNode newNode = new BinaryExpressionNode(new IdentifierNode(name), ben.RightNode);
                            astNodes.Add(newNode);
                        }
                        else
                        {
                            // Add node as it is
                            astNodes.Add(node);
                        }
                    }
                    else
                    {
                        // These nodes are non-assignment nodes
                        string name = string.Format("temp_{0}_{1}", index++, postfixGuid);
                        BinaryExpressionNode newNode = new BinaryExpressionNode(new IdentifierNode(name), n);
                        astNodes.Add(newNode);
                    }
                }
            }
            return(astNodes);
        }
Ejemplo n.º 23
0
        private void EmitModifierStackNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
        {
            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody() && !IsParsingMemberFunctionBody())
            {
                return;
            }

            AssociativeNode prevElement = null;

            //core.Options.EmitBreakpoints = false;
            ModifierStackNode m = node as ModifierStackNode;

            int ci = Constants.kInvalidIndex;
            for(int i = 0; i < m.ElementNodes.Count; ++i)
            {
                bool emitBreakpointForPop = false;
                AssociativeNode modifierNode = m.ElementNodes[i];
                
                // Convert Function call nodes into function dot call nodes 
                if (modifierNode is BinaryExpressionNode)
                {
                    BinaryExpressionNode bnode = modifierNode as BinaryExpressionNode;
                    if (bnode.LeftNode.Name.StartsWith(ProtoCore.DSASM.Constants.kTempModifierStateNamePrefix))
                    {
                        emitBreakpointForPop = true;
                    }

                    if (!ProtoCore.Utils.CoreUtils.IsSSATemp(bnode.LeftNode.Name))
                    {
                        prevElement = bnode;
                    }

                    // Get class index from function call node if it is constructor call
                    if (bnode.RightNode is FunctionDotCallNode)
                    {
                        FunctionDotCallNode fnode = bnode.RightNode as FunctionDotCallNode;
                        IdentifierNode ident = fnode.DotCall.FormalArguments[0] as IdentifierNode;
                        string name = "";
                        if (ident != null)
                        {
                            name = ident.Value;
                        }

                        ci = core.ClassTable.IndexOf(name);
                        NodeUtils.SetNodeStartLocation(bnode, fnode.DotCall);
                    }
                    // Check if the right node of the modifierNode is a FunctionCall node
                    else if (bnode.RightNode is FunctionCallNode && ci != Constants.kInvalidIndex)
                    {
                        FunctionCallNode rnode = bnode.RightNode as FunctionCallNode;

                        if (i >= 1)
                        {
                            // Use class index to search for function call node and return procedure node
                            ProcedureNode procCallNode = core.ClassTable.ClassNodes[ci].GetFirstMemberFunctionBy(rnode.Function.Name, rnode.FormalArguments.Count);

                            // Only if procedure node is non-null do we know its a member function and prefix it with an instance pointer
                            if (procCallNode != null)
                            {
                                ////////////////////////////////      
                                BinaryExpressionNode previousElementNode = null;
                                if (core.Options.GenerateSSA)
                                {
                                    Validity.Assert(null != prevElement && prevElement is BinaryExpressionNode);
                                    previousElementNode = prevElement as BinaryExpressionNode; 
                                }
                                else
                                {
                                    previousElementNode = m.ElementNodes[i - 1] as BinaryExpressionNode;
                                }
                                Validity.Assert(null != previousElementNode);
                                AssociativeNode lhs = previousElementNode.LeftNode;
                                bnode.RightNode = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(lhs, rnode, core);

                                FunctionDotCallNode fdcNode = bnode.RightNode as FunctionDotCallNode;
                                if (fdcNode != null)
                                {
                                    NodeUtils.SetNodeStartLocation(fdcNode.DotCall, rnode);
                                }
                            }
                        }
                    }
                }
                else
                {
                    // We should never get here. Fix it!
                    Validity.Assert(null != "Unknown node type!");
                }

                DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions;

                if (emitBreakpointForPop)
                {
                    DebugProperties.BreakpointOptions newOptions = oldOptions;
                    newOptions |= DebugProperties.BreakpointOptions.EmitPopForTempBreakpoint;
                    core.DebuggerProperties.breakOptions = newOptions;
                }

                DfsTraverse(modifierNode, ref inferedType, isBooleanOp, graphNode, subPass);
                core.DebuggerProperties.breakOptions = oldOptions;
            }
            //core.Options.EmitBreakpoints = true;
        }
Ejemplo n.º 24
0
        private void EmitIfStatementNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex;
            int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex;

            // If-expr
            IfStatementNode ifnode = node as IfStatementNode;
            DfsTraverse(ifnode.ifExprNode, ref inferedType, false, graphNode);
            L1 = ProtoCore.DSASM.Constants.kInvalidIndex;
            bp = pc;
            EmitCJmp(L1);


            // Create a new codeblock for this block
            // Set the current codeblock as the parent of the new codeblock
            // Set the new codeblock as a new child of the current codeblock
            // Set the new codeblock as the current codeblock
            ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock(
                context.guid,
                ProtoCore.DSASM.CodeBlockType.kConstruct,
                Language.NotSpecified,
                core.CodeBlockIndex++,
                new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("if"), core.RuntimeTableIndex++),
                null,
                false,
                core);


            localCodeBlock.instrStream = codeBlock.instrStream;
            localCodeBlock.parent = codeBlock;
            codeBlock.children.Add(localCodeBlock);
            codeBlock = localCodeBlock;

            // If-body
            foreach (AssociativeNode ifBody in ifnode.IfBody)
            {
                inferedType = new ProtoCore.Type();
                inferedType.UID = (int)PrimitiveType.kTypeVar;
                DfsTraverse(ifBody, ref inferedType, false, graphNode);
            }

            // Restore - Set the local codeblock parent to be the current codeblock
            codeBlock = localCodeBlock.parent;


            L1 = ProtoCore.DSASM.Constants.kInvalidIndex;

            BackpatchTable backpatchTable = new BackpatchTable();
            backpatchTable.Append(pc, L1);
            EmitJmp(L1);

            // Backpatch the L2 destination of the if block
            Backpatch(bp, pc);


            /*		
            else if(E)	->	traverse E
                            L1 = pc + 1
                            L2 = null 
                            bp = pc
                            emit(jmp, _cx, L1, L2) 
            {				
                S		->	traverse S
                            L1 = null
                            bpTable.append(pc)
                            emit(jmp,labelEnd) 
                            backpatch(bp,pc)
            }
             * */

            // Elseif-expr


            /*
            else 			
            {				
                S		->	traverse S
                            L1 = null
                            bpTable.append(pc)
                            emit(jmp,labelEnd) 
                            backpatch(bp,pc)
            }		
             * */
            // Else-body     

            Validity.Assert(null != ifnode.ElseBody);
            if (0 != ifnode.ElseBody.Count)
            {
                // Create a new symboltable for this block
                // Set the current table as the parent of the new table
                // Set the new table as a new child of the current table
                // Set the new table as the current table
                // Create a new codeblock for this block
                // Set the current codeblock as the parent of the new codeblock
                // Set the new codeblock as a new child of the current codeblock
                // Set the new codeblock as the current codeblock
                localCodeBlock = new ProtoCore.DSASM.CodeBlock(
                    context.guid,
                    ProtoCore.DSASM.CodeBlockType.kConstruct,
                    Language.NotSpecified,
                    core.CodeBlockIndex++,
                    new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("else"), core.RuntimeTableIndex++),
                    null,
                    false,
                    core);

                localCodeBlock.instrStream = codeBlock.instrStream;
                localCodeBlock.parent = codeBlock;
                codeBlock.children.Add(localCodeBlock);
                codeBlock = localCodeBlock;
                foreach (AssociativeNode elseBody in ifnode.ElseBody)
                {
                    inferedType = new ProtoCore.Type();
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                    DfsTraverse(elseBody, ref inferedType, false, graphNode);
                }

                // Restore - Set the local codeblock parent to be the current codeblock
                codeBlock = localCodeBlock.parent;

                L1 = ProtoCore.DSASM.Constants.kInvalidIndex;
                backpatchTable.Append(pc, L1);
                EmitJmp(L1);
            }

            /*
             * 
                      ->	backpatch(bpTable, pc) 
             */
            // ifstmt-exit
            // Backpatch all the previous unconditional jumps
            Backpatch(backpatchTable.backpatchList, pc);
        }
Ejemplo n.º 25
0
        private void EmitBinaryExpressionNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode bnode = null;

            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody() && !IsParsingMemberFunctionBody())
                return;

            bool isBooleanOperation = false;
            bnode = node as BinaryExpressionNode;
            ProtoCore.Type leftType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);
            ProtoCore.Type rightType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

            DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions;
            
            // If this is an assignment statement, setup the top level graph node
            bool isGraphInScope = false;
            if (ProtoCore.DSASM.Operator.assign == bnode.Optr)
            {
                if (null == graphNode)
                {
                    isGraphInScope = true;
                    EmitCompileLog("==============Start Node==============\n");
                    graphNode = new ProtoCore.AssociativeGraph.GraphNode();
                    graphNode.AstID = bnode.ID;
                    graphNode.OriginalAstID = bnode.OriginalAstID; 
                    graphNode.exprUID = bnode.ExpressionUID;
                    graphNode.ssaSubExpressionID = bnode.SSASubExpressionID;
                    graphNode.ssaExpressionUID = bnode.SSAExpressionUID;
                    graphNode.IsModifier = bnode.IsModifier;
                    graphNode.guid = bnode.guid;
                    graphNode.procIndex = globalProcIndex;
                    graphNode.classIndex = globalClassIndex;
                    graphNode.languageBlockId = codeBlock.codeBlockId;
                    graphNode.ProcedureOwned = bnode.IsProcedureOwned;


                    //
                    // Comment Jun: 
                    //      If the expression ID of the assignment node in the context execDirtyFlag list is false,
                    //      it means that it was already executed. This needs to be marked as not dirty
                    if (core.Options.IsDeltaExecution)
                    {
                        if (context.exprExecutionFlags.ContainsKey(bnode.ExpressionUID))
                        {
                            graphNode.isDirty = context.exprExecutionFlags[bnode.ExpressionUID];
                        }
                    }
                }

                if (bnode.isSSAFirstAssignment)
                {
                    firstSSAGraphNode = graphNode;
                }
                HandlePointerList(bnode);
                        

                if (bnode.LeftNode is IdentifierListNode)
                {
                    // If the lhs is an identifierlist then emit the entire expression here
                    // This also handles the dependencies of expressions where the lhs is a member variable (this.x = y)
                    EmitLHSIdentifierListForBinaryExpr(bnode, ref inferedType, isBooleanOp, graphNode, subPass);
                    if (isGraphInScope)
                    {
                        EmitCompileLog("==============End Node==============\n");
                    }
                    return;
                }
                else if (bnode.LeftNode is IdentifierNode)
                {
                    if (bnode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This))
                    {
                        string errorMessage = ProtoCore.Properties.Resources.kInvalidThis;
                        if (localProcedure != null)
                        {
                            if (localProcedure.IsStatic)
                            {
                                errorMessage = ProtoCore.Properties.Resources.kUsingThisInStaticFunction;
                            }
                            else if (localProcedure.ClassID == Constants.kGlobalScope)
                            {
                                errorMessage = ProtoCore.Properties.Resources.kInvalidThis;
                            }
                            else
                            {
                                errorMessage = ProtoCore.Properties.Resources.kAssingToThis;
                            }
                        }
                        core.BuildStatus.LogWarning(WarningID.kInvalidThis, errorMessage, core.CurrentDSFileName, bnode.line, bnode.col, graphNode);

                        if (isGraphInScope)
                        {
                            EmitCompileLog("==============End Node==============\n");
                        }

                        return;
                    }

                    if (EmitLHSThisDotProperyForBinaryExpr(bnode, ref inferedType, isBooleanOp, graphNode, subPass))
                    {
                        if (isGraphInScope)
                        {
                            EmitCompileLog("==============End Node==============\n");
                        }
                        return;
                    }
                }
            }
            else //(ProtoCore.DSASM.Operator.assign != b.Optr)
            {
                // Traversing the left node if this binary expression is not an assignment
                //
                isBooleanOperation = ProtoCore.DSASM.Operator.lt == bnode.Optr
                     || ProtoCore.DSASM.Operator.gt == bnode.Optr
                     || ProtoCore.DSASM.Operator.le == bnode.Optr
                     || ProtoCore.DSASM.Operator.ge == bnode.Optr
                     || ProtoCore.DSASM.Operator.eq == bnode.Optr
                     || ProtoCore.DSASM.Operator.nq == bnode.Optr
                     || ProtoCore.DSASM.Operator.and == bnode.Optr
                     || ProtoCore.DSASM.Operator.or == bnode.Optr;

                DfsTraverse(bnode.LeftNode, ref inferedType, isBooleanOperation, graphNode, subPass);

                if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier && emitDebugInfo)
                {
                    buildStatus.LogSemanticError(Resources.FunctionPointerNotAllowedAtBinaryExpression, core.CurrentDSFileName, bnode.LeftNode.line, bnode.LeftNode.col);
                }

                leftType.UID = inferedType.UID;
                leftType.rank = inferedType.rank;
            }

            int startpc = ProtoCore.DSASM.Constants.kInvalidIndex;
            if ((ProtoCore.DSASM.Operator.assign == bnode.Optr) && (bnode.RightNode is LanguageBlockNode))
            {
                inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);
            }

            if (null != localProcedure && localProcedure.IsConstructor && setConstructorStartPC)
            {
                startpc -= 1;
                setConstructorStartPC = false;
            }

            if (bnode.RightNode == null && bnode.Optr == Operator.assign && bnode.LeftNode is IdentifierNode)
            {
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.SuppressNullVarDeclarationBreakpoint;
                core.DebuggerProperties.breakOptions = newOptions;

                IdentifierNode t = bnode.LeftNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAccessible = false;
                bool hasAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                if (hasAllocated)
                {
                    bool allowDependent = graphNode.allowDependents;
                    graphNode.allowDependents = false;
                    bnode.RightNode =AstFactory.BuildIdentifier(t.Value);
                    graphNode.allowDependents = false;
                }
                else
                {
                    bnode.RightNode = new NullNode();
                }
            }

            // Keep track of current pc, because when travese right node it
            // may generate null assignment ( x = null; if x hasn't been defined
            // yet - Yu Ke
            startpc = pc;

            DfsTraverse(bnode.RightNode, ref inferedType, isBooleanOperation, graphNode, subPass, node);

            rightType.UID = inferedType.UID;
            rightType.rank = inferedType.rank;

            BinaryExpressionNode rightNode = bnode.RightNode as BinaryExpressionNode;
            if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr))
            {
                DfsTraverse(rightNode.LeftNode, ref inferedType, false, graphNode);
            }

            if (bnode.Optr != ProtoCore.DSASM.Operator.assign)
            {
                if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                {
                    return;
                }

                if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo)
                {
                    buildStatus.LogSemanticError(Resources.FunctionPointerNotAllowedAtBinaryExpression, core.CurrentDSFileName, bnode.RightNode.line, bnode.RightNode.col);
                }
                EmitBinaryOperation(leftType, rightType, bnode.Optr);
                isBooleanOp = false;

                return;
            }

            Validity.Assert(null != graphNode);
            if (!isTempExpression)
            {
                graphNode.updateBlock.startpc = pc;
            }

            currentBinaryExprUID = bnode.ExpressionUID;

            // These have been integrated into "EmitGetterSetterForIdentList" so 
            // that stepping through class properties can be supported. Setting 
            // these values here will cause issues with statements like this to 
            // be highlighted in its entirety (all the way up to closing bracket 
            // without highlighting the semi-colon).
            // 
            //      x = foo(a, b);
            // 
            // bnode.RightNode.line = bnode.line;
            // bnode.RightNode.col = bnode.col;
            // bnode.RightNode.endLine = bnode.endLine;
            // bnode.RightNode.endCol = bnode.endCol;

            // Traverse the entire RHS expression
            DfsTraverse(bnode.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bnode);
            subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier;

            if (bnode.LeftNode is IdentifierNode)
            {
                // TODO Jun: Cleansify this block where the lhs is being handled.
                // For one, make the return as a return node
                IdentifierNode t = bnode.LeftNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symbolnode = null;


                ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeGlobalRef = null; 

                string s = t.Value;
                if (s == ProtoCore.DSDefinitions.Keyword.Return)
                {
                    Validity.Assert(null == symbolnode);
                    symbolnode = new ProtoCore.DSASM.SymbolNode();
                    symbolnode.name = s;
                    symbolnode.isTemp = s.StartsWith("%");
                    symbolnode.functionIndex = globalProcIndex;
                    symbolnode.classScope = globalClassIndex;

                    EmitReturnStatement(node, inferedType);


                    // Comment Jun: The inline conditional holds a graphnode and traversing its body will set isReturn = true
                    // Resolve that here as an inline conditional is obviosuly not a return graphnode
                    if (!graphNode.isInlineConditional)
                    {
                        graphNode.isReturn = true;
                    }
                }
                else
                {
                    leftNodeGlobalRef = GetUpdatedNodeRef(bnode.LeftNode);

                    // check whether the variable name is a function name
                    if (globalClassIndex != ProtoCore.DSASM.Constants.kGlobalScope)
                    {
                        bool isAccessibleFp;
                        int realType;
                        var procNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(t.Name, null, globalClassIndex, out isAccessibleFp, out realType);
                        if (procNode != null && procNode.ID != Constants.kInvalidIndex && emitDebugInfo)
                        {
                            buildStatus.LogSemanticError(String.Format(Resources.FunctionAsVariableError, t.Name), core.CurrentDSFileName, t.line, t.col);
                        }
                    }

                    //int type = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    bool isLocalDeclaration = t.IsLocal;
                    bool isAccessible = false;
                    bool isAllocated = false;

                    if (isLocalDeclaration)
                    {
                        isAllocated = VerifyAllocationInScope(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                    }
                    else
                    {
                        isAllocated = VerifyAllocation(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                    }

                    int runtimeIndex = (!isAllocated || !isAccessible) ? codeBlock.symbolTable.RuntimeIndex : symbolnode.runtimeTableIndex;
                    if (isAllocated && !isAccessible)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kPropertyIsInaccessible, t.Name);
                        buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, t.line, t.col, graphNode);
                    }

                    int dimensions = 0;
                    if (null != t.ArrayDimensions)   
                    {
                        graphNode.isIndexingLHS = true;
                        dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, bnode);
                    }


                    // Comment Jun: Attempt to get the modified argument arrays in the current method
                    // Comment Jun: As of R1 - arrays are copy constructed and cannot propagate update unless explicitly returned
                    ProtoCore.Type castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, Constants.kArbitraryRank);
                    var tident = bnode.LeftNode as TypedIdentifierNode;
                    if (tident != null)
                    {
                        int castUID = core.ClassTable.IndexOf(tident.datatype.Name);
                        if ((int)PrimitiveType.kInvalidType == castUID)
                        {
                            castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kInvalidType, 0);
                            castType.Name = tident.datatype.Name;
                            castType.rank = tident.datatype.rank;
                        }
                        else
                        {
                            castType = core.TypeSystem.BuildTypeObject(castUID, tident.datatype.rank);
                        }
                    }

                    if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
                    {
                        // In a class
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == globalProcIndex)
                        {
                            string message = "A binary assignment inside a class must be inside a function (AB5E3EC1)";
                            buildStatus.LogSemanticError(message, core.CurrentDSFileName, bnode.line, bnode.col);
                            throw new BuildHaltException(message);
                        }

                        // TODO Jun: refactor this by having symbol table functions for retrieval of node index
                        int symbol = ProtoCore.DSASM.Constants.kInvalidIndex;
                        bool isMemVar = false;
                        if (symbolnode != null)
                        {
                            if (symbolnode.classScope != ProtoCore.DSASM.Constants.kInvalidIndex 
                                && symbolnode.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                            {
                                isMemVar = true;
                            }
                            symbol = symbolnode.symbolTableIndex;
                        }

                        if (!isMemVar)
                        {
                            // This is local variable
                            // TODO Jun: If this local var exists globally, should it allocate a local copy?
                            if (!isAllocated || !isAccessible)
                            {
                                symbolnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Name, inferedType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                                    false, ProtoCore.CompilerDefinitions.AccessModifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, bnode.line, bnode.col);

                                // Add the symbols during watching process to the watch symbol list.
                                if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                                {
                                    core.watchSymbolList.Add(symbolnode);
                                }

                                Validity.Assert(symbolnode != null);
                            }
                            else
                            {
                                symbolnode.datatype = inferedType;
                            }

                            if (bnode.LeftNode is TypedIdentifierNode)
                            {
                                symbolnode.SetStaticType(castType);
                            }
                            castType = symbolnode.staticType;
                            EmitPushVarData(dimensions, castType.UID, castType.rank);

                            symbol = symbolnode.symbolTableIndex;
                            if (t.Name == ProtoCore.DSASM.Constants.kTempArg)
                            {
                                EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Name);
                                EmitPopForSymbol(symbolnode, runtimeIndex);
                            }
                            else
                            {
                                if (core.Options.RunMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                                {
                                    EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Name);
                                    EmitPopForSymbol(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                                }
                                else
                                {
                                    EmitInstrConsole(ProtoCore.DSASM.kw.popw, t.Name);
                                    EmitPopForSymbolW(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                                }
                            }
                        }
                        else
                        {
                            if (bnode.LeftNode is TypedIdentifierNode)
                            {
                                symbolnode.SetStaticType(castType);
                            }
                            castType = symbolnode.staticType;
                            EmitPushVarData(dimensions, castType.UID, castType.rank);

                            EmitInstrConsole(ProtoCore.DSASM.kw.popm, t.Name);

                            if (symbolnode.isStatic)
                            {
                                var op = StackValue.BuildStaticMemVarIndex(symbol);
                                EmitPopm(op, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                            }
                            else
                            {
                                var op = StackValue.BuildMemVarIndex(symbol);
                                EmitPopm(op, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                            }
                        }

                        //if (t.Name[0] != '%')
                        {
                            AutoGenerateUpdateReference(bnode.LeftNode, graphNode);
                        }

                        // Dependency
                        if (!isTempExpression)
                        {
                            // Dependency graph top level symbol 
                            graphNode.PushSymbolReference(symbolnode);
                            EmitDependency(bnode.ExpressionUID, bnode.modBlkUID, bnode.isSSAAssignment);
                            functionCallStack.Clear();
                        }
                    }
                    else
                    {
                        if (!isAllocated)
                        {
                            symbolnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Name, inferedType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                                    false, ProtoCore.CompilerDefinitions.AccessModifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, bnode.line, bnode.col);

                            if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                            {
                                core.watchSymbolList.Add(symbolnode);
                            }

                            if (dimensions > 0)
                            {
                                symbolnode.datatype.rank = dimensions;
                            }
                        }
                        else if (dimensions == 0)
                        {
                            symbolnode.datatype = inferedType;
                        }

                        //
                        // Jun Comment: 
                        //      Update system uses the following registers:  
                        //      _ex stores prev value of ident 't'  - VM assigned
                        //      _fx stores new value                - VM assigned
                        //

                        if (bnode.LeftNode is TypedIdentifierNode)
                        {
                            symbolnode.SetStaticType(castType);
                        }
                        castType = symbolnode.staticType;


                        if (bnode.IsInputExpression)
                        {
                            StackValue regLX = StackValue.BuildRegister(Registers.LX);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regLX);
                            EmitPop(regLX, globalClassIndex);

                            graphNode.updateBlock.updateRegisterStartPC = pc;

                            EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regLX);
                            EmitPush(regLX);
                        }

                        EmitPushVarData(dimensions, castType.UID, castType.rank);

                        if (core.Options.RunMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                        {
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, symbolnode.name);
                            EmitPopForSymbol(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                        }
                        else
                        {
                            EmitInstrConsole(ProtoCore.DSASM.kw.popw, symbolnode.name);
                            EmitPopForSymbolW(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);                            
                        }

                        AutoGenerateUpdateReference(bnode.LeftNode, graphNode);

                        // Dependency
                        if (!isTempExpression)
                        {
                            // Dependency graph top level symbol 
                            graphNode.PushSymbolReference(symbolnode);
                            EmitDependency(bnode.ExpressionUID, bnode.modBlkUID, bnode.isSSAAssignment);
                            functionCallStack.Clear();
                        }
                    }
                }

                // Dependency graph top level symbol 
                //graphNode.symbol = symbolnode;

                // Assign the end pc to this graph node's update block
                // Dependency graph construction is complete for this expression
                if (!isTempExpression)
                {
                    if (null != leftNodeGlobalRef)
                    {
                        if (null != localProcedure)
                        {
                            // Track for updated globals only in user defined functions
                            if (!localProcedure.IsAssocOperator && !localProcedure.IsAutoGenerated)
                            {
                                localProcedure.UpdatedGlobalVariables.Push(leftNodeGlobalRef);
                            }
                        }
                    }

                    {
                        if (!graphNode.IsSSANode() && !ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(graphNode))
                        {
                            // This is the last expression in the SSA'd expression
                            // Backtrack and assign the this last final assignment graphnode to its associated SSA graphnodes
                            for (int n = codeBlock.instrStream.dependencyGraph.GraphList.Count - 1; n >= 0; --n)
                            {
                                GraphNode currentNode = codeBlock.instrStream.dependencyGraph.GraphList[n];
                                bool isWithinSameScope = currentNode.classIndex == graphNode.classIndex
                                    && currentNode.procIndex == graphNode.procIndex;
                                bool isWithinSameExpressionID = currentNode.exprUID == graphNode.exprUID;
                                if (isWithinSameScope && isWithinSameExpressionID)
                                {
                                    graphNode.IsLastNodeInSSA = true;
                                    if (null == codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode)
                                    {
                                        codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode = graphNode;
                                    }
                                }
                            }
                        }
                    }

                    graphNode.ResolveLHSArrayIndex();
                    graphNode.updateBlock.endpc = pc - 1;

                    PushGraphNode(graphNode);
                    if (core.InlineConditionalBodyGraphNodes.Count > 0)
                    {
                        core.InlineConditionalBodyGraphNodes.Last().Add(graphNode);
                    }

                    SymbolNode cyclicSymbol1 = null;
                    SymbolNode cyclicSymbol2 = null;
                    if (core.Options.staticCycleCheck)
                    {
                        if (!CyclicDependencyTest(graphNode, ref cyclicSymbol1, ref cyclicSymbol2))
                        {
                            Validity.Assert(null != cyclicSymbol1);
                            Validity.Assert(null != cyclicSymbol2);

                            //
                            // Set the first symbol that triggers the cycle to null
                            ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode1 = new ProtoCore.AssociativeGraph.GraphNode();
                            nullAssignGraphNode1.updateBlock.startpc = pc;

                            EmitPushNull();
                            EmitPushVarData(0);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, cyclicSymbol1.name);
                            EmitPopForSymbol(cyclicSymbol1, cyclicSymbol1.runtimeTableIndex, node.line, node.col, node.endLine, node.endCol);

                            nullAssignGraphNode1.PushSymbolReference(cyclicSymbol1);
                            nullAssignGraphNode1.procIndex = globalProcIndex;
                            nullAssignGraphNode1.classIndex = globalClassIndex;
                            nullAssignGraphNode1.updateBlock.endpc = pc - 1;

                            PushGraphNode(nullAssignGraphNode1);
                            EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);


                            //
                            // Set the second symbol that triggers the cycle to null
                            ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode2 = new ProtoCore.AssociativeGraph.GraphNode();
                            nullAssignGraphNode2.updateBlock.startpc = pc;

                            EmitPushNull();
                            EmitPushVarData(0);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, cyclicSymbol2.name);
                            EmitPopForSymbol(cyclicSymbol2, cyclicSymbol2.runtimeTableIndex, node.line, node.col, node.endLine, node.endCol);

                            nullAssignGraphNode2.PushSymbolReference(cyclicSymbol2);
                            nullAssignGraphNode2.procIndex = globalProcIndex;
                            nullAssignGraphNode2.classIndex = globalClassIndex;
                            nullAssignGraphNode2.updateBlock.endpc = pc - 1;

                            PushGraphNode(nullAssignGraphNode2);
                            EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);
                        }
                    }
                    if (isGraphInScope)
                    {
                        EmitCompileLog("==============End Node==============\n");
                    }
                }

                // Jun Comment: If it just so happens that the inline conditional is in the return statement
                if (graphNode.isInlineConditional)
                {
                    graphNode.isReturn = false;
                    if (0 == graphNode.updateNodeRefList.Count)
                    {
                        graphNode.isReturn = true;
                    }
                }
            }
            else
            {
                string message = "Illegal assignment (90787393)";
                buildStatus.LogSemanticError(message, core.CurrentDSFileName, bnode.line, bnode.col);
                throw new BuildHaltException(message);
            }
            core.DebuggerProperties.breakOptions = oldOptions;
        }
Ejemplo n.º 26
0
        private void EmitUnaryExpressionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
        {
            UnaryExpressionNode u = node as UnaryExpressionNode;
            bool isPrefixOperation = ProtoCore.DSASM.UnaryOperator.Increment == u.Operator || ProtoCore.DSASM.UnaryOperator.Decrement == u.Operator;

            //(Ayush) In case of prefix, apply prefix operation first
            if (isPrefixOperation)
            {
                if (u.Expression is IdentifierListNode || u.Expression is IdentifierNode)
                {
                    BinaryExpressionNode binRight = new BinaryExpressionNode();
                    BinaryExpressionNode bin = new BinaryExpressionNode();
                    binRight.LeftNode = u.Expression;
                    binRight.RightNode = new IntNode(1);
                    binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == u.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub;
                    bin.LeftNode = u.Expression; bin.RightNode = binRight; bin.Optr = ProtoCore.DSASM.Operator.assign;
                    EmitBinaryExpressionNode(bin, ref inferedType, false, graphNode, subPass);
                }
                else
                    throw new BuildHaltException("Invalid use of prefix operation (DCDDEEF1).");
            }

            DfsTraverse(u.Expression, ref inferedType, false, graphNode, subPass);

            if (!isPrefixOperation && subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
            {
                string op = Op.GetUnaryOpName(u.Operator);
                EmitInstrConsole(op);
                EmitUnary(Op.GetUnaryOpCode(u.Operator));
            }
        }
Ejemplo n.º 27
0
        private void EmitImportNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
        {
            ImportNode importNode = node as ImportNode;
            CodeBlockNode codeBlockNode = importNode.CodeNode;
            string origSourceLocation = core.CurrentDSFileName;

            core.CurrentDSFileName = importNode.ModulePathFileName;
            this.isEmittingImportNode = true;

            // TODO Jun: Merge all the DeltaCompile routines in codegen into one place
            bool firstImportInDeltaExecution = false;
            int startPC = pc;

            if (core.Options.IsDeltaExecution)
            {
                //ModuleName can be full path as well 
                if (core.LoadedDLLs.Contains(importNode.ModulePathFileName))
                {
                    return;
                }

                if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalFuncBody == compilePass)
                {
                    core.LoadedDLLs.Add(importNode.ModulePathFileName);
                    firstImportInDeltaExecution = true;
                }
            }

            if (codeBlockNode != null)
            {
                // Only build SSA for the first time
                // Transform after class name compile pass
                if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassName > compilePass)
                {
                    codeBlockNode.Body = ApplyTransform(codeBlockNode.Body);
                    codeBlockNode.Body = BuildSSA(codeBlockNode.Body, context);
                }

                foreach (AssociativeNode assocNode in codeBlockNode.Body)
                {
                    inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); 

                    if (assocNode is LanguageBlockNode)
                    {
                        // Build a binaryn node with a temporary lhs for every stand-alone language block
                        var iNode = AstFactory.BuildIdentifier(core.GenerateTempLangageVar());
                        var langBlockNode = AstFactory.BuildAssignment(iNode, assocNode);

                        DfsTraverse(langBlockNode, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                    }
                    else
                    {
                        DfsTraverse(assocNode, ref inferedType, false, null, subPass);
                    }
                }
            }

            core.CurrentDSFileName = origSourceLocation;
            this.isEmittingImportNode = false;

            // If in delta execution (a.k.a. LiveRunner) we import an external 
            // library and at the same time this library generates some 
            // instructions, we need to keep those instructions to avoid they
            // are overwritten in the next run.
            if (firstImportInDeltaExecution && pc > startPC)
            {
                core.deltaCompileStartPC = pc;
            }
        }
Ejemplo n.º 28
0
        // 
        //  proc TraverseFunctionDef(node)
        //      ...
        //      def argList
        //      foreach arg in node.argdefinition
        //          ; Store not just the argument types, but also the argument identifier
        //          def argtype = buildtype(arg)
        //          argtype.name = arg.identname
        //          argList.push(argtype)
        //      end
        //      ...
        //  end
        //  

        private ProtoCore.AssociativeGraph.UpdateNodeRef __To__Deprecate__AutoGenerateUpdateArgumentReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode)
        {
            // Get the lhs symbol list
            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = globalClassIndex;
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
            DFSGetSymbolList(node, ref type, leftNodeRef);

            ProtoCore.DSASM.SymbolNode firstSymbol = null;


            // Check if we are inside a procedure
            if (null != localProcedure)
            {
                // Check if there are at least 2 symbols in the list
                if (leftNodeRef.nodeList.Count >= 2)
                {
                    firstSymbol = leftNodeRef.nodeList[0].symbol;
                    if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod)
                    {
                        // Now check if the first element of the identifier list is an argument
                        foreach (ProtoCore.DSASM.ArgumentInfo argInfo in localProcedure.ArgumentInfos)
                        {
                            if (argInfo.Name == firstSymbol.name)
                            {
                                leftNodeRef.nodeList.RemoveAt(0);

                                List<ProtoCore.AssociativeGraph.UpdateNodeRef> refList = null;
                                bool found = localProcedure.UpdatedArgumentProperties.TryGetValue(argInfo.Name, out refList);
                                if (found)
                                {
                                    refList.Add(leftNodeRef);
                                }
                                else
                                {
                                    refList = new List<ProtoCore.AssociativeGraph.UpdateNodeRef>();
                                    refList.Add(leftNodeRef);
                                    localProcedure.UpdatedArgumentProperties.Add(argInfo.Name, refList);
                                }
                            }
                        }
                    }
                }
            }
            return leftNodeRef;
        }
Ejemplo n.º 29
0
        private void EmitConstructorDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, GraphNode gNode = null)
        {
            ConstructorDefinitionNode funcDef = node as ConstructorDefinitionNode;
            ProtoCore.DSASM.CodeBlockType originalBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;

            if (IsParsingMemberFunctionSig())
            {
                Validity.Assert(null == localProcedure);
                localProcedure = new ProtoCore.DSASM.ProcedureNode();

                localProcedure.Name = funcDef.Name;
                localProcedure.PC = ProtoCore.DSASM.Constants.kInvalidIndex;
                localProcedure.LocalCount = 0;// Defer till all locals are allocated
                ProtoCore.Type returnType = localProcedure.ReturnType; 
                if (globalClassIndex != -1)
                    returnType.Name = core.ClassTable.ClassNodes[globalClassIndex].Name;
                returnType.UID = globalClassIndex;
                returnType.rank = 0;
                localProcedure.ReturnType = returnType;
                localProcedure.IsConstructor = true;
                localProcedure.RuntimeIndex = 0;
                localProcedure.IsExternal = funcDef.IsExternLib;
                Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex, "A constructor node must be associated with class");
                localProcedure.LocalCount = 0;
                localProcedure.ClassID = globalClassIndex;

                localProcedure.MethodAttribute = funcDef.MethodAttributes;

                int peekFunctionindex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures.Count;

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        var argInfo = BuildArgumentInfoFromVarDeclNode(argNode); 
                        localProcedure.ArgumentInfos.Add(argInfo);

                        var argType = BuildArgumentTypeFromVarDeclNode(argNode, gNode);
                        localProcedure.ArgumentTypes.Add(argType);

                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(argInfo.Name, argType));
                    }

                    localProcedure.IsVarArg = funcDef.Signature.IsVarArg;
                }

                int findex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Append(localProcedure);

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != findex)
                {
                    Validity.Assert(peekFunctionindex == localProcedure.ID);
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, findex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("44B557F1");
                        }
                    });
                }
                else
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kMethodAlreadyDefined, localProcedure.Name);
                    buildStatus.LogWarning(WarningID.kFunctionAlreadyDefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, gNode);
                    funcDef.skipMe = true;
                }
            }
            else if (IsParsingMemberFunctionBody())
            {
                EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature, true));
                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode, gNode);
                        argList.Add(argType);
                    }
                }

                var procNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.GetFunctionBySignature(funcDef.Name, argList);
                globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;

                Validity.Assert(null == localProcedure);
                localProcedure = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];

                Validity.Assert(null != localProcedure);
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc);
                localProcedure.PC = pc;

                EmitInstrConsole(ProtoCore.DSASM.kw.allocc, localProcedure.Name);
                EmitAllocc(globalClassIndex);
                setConstructorStartPC = true;

                EmitCallingForBaseConstructor(globalClassIndex, funcDef.BaseConstructor);

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    // Traverse default assignment for the class
                    emitDebugInfo = false;

                    List<AssociativeNode> defaultArgList = core.ClassTable.ClassNodes[globalClassIndex].DefaultArgExprList;
                    defaultArgList = BuildSSA(defaultArgList, context);
                    foreach (BinaryExpressionNode bNode in defaultArgList)
                    {
                        ProtoCore.AssociativeGraph.GraphNode graphNode = new ProtoCore.AssociativeGraph.GraphNode();
                        graphNode.exprUID = bNode.ExpressionUID;
                        graphNode.ssaExpressionUID = bNode.SSAExpressionUID;
                        graphNode.procIndex = globalProcIndex;
                        graphNode.classIndex = globalClassIndex;
                        graphNode.languageBlockId = codeBlock.codeBlockId;
                        graphNode.isAutoGenerated = true;
                        bNode.IsProcedureOwned = graphNode.ProcedureOwned = true;

                        EmitBinaryExpressionNode(bNode, ref inferedType, false, graphNode, subPass);
                    }

                    //Traverse default argument for the constructor
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.ArgumentInfos)
                    {
                        if (!argNode.IsDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.DefaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        var iNodeTemp =AstFactory.BuildIdentifier(Constants.kTempDefaultArg);
                        BinaryExpressionNode bNodeTemp = new BinaryExpressionNode();
                        bNodeTemp.LeftNode = iNodeTemp;
                        bNodeTemp.Optr = ProtoCore.DSASM.Operator.assign;
                        bNodeTemp.RightNode = bNode.LeftNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        icNode.IsAutoGenerated = true;
                        BinaryExpressionNode cExprNode = new BinaryExpressionNode();
                        cExprNode.Optr = ProtoCore.DSASM.Operator.eq;
                        cExprNode.LeftNode = iNodeTemp;
                        cExprNode.RightNode = new DefaultArgNode();
                        icNode.ConditionExpression = cExprNode;
                        icNode.TrueExpression = bNode.RightNode;
                        icNode.FalseExpression = iNodeTemp;
                        bNodeTemp.LeftNode = bNode.LeftNode;
                        bNodeTemp.RightNode = icNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType);
                    }
                    emitDebugInfo = true;

                    EmitCodeBlock(funcDef.FunctionBody.Body, ref inferedType, subPass, true);

                    // Build dependency within the function
                    ProtoCore.AssociativeEngine.Utils.BuildGraphNodeDependencies(
                        codeBlock.instrStream.dependencyGraph.GetGraphNodesAtScope(globalClassIndex, globalProcIndex));

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.LocalCount = core.BaseOffset;
                    core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex].LocalCount = core.BaseOffset;

                    // Update the param stack indices of this function
                    foreach (ProtoCore.DSASM.SymbolNode symnode in core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList.Values)
                    {
                        if (symnode.functionIndex == globalProcIndex && symnode.isArgument)
                        {
                            symnode.index -= localProcedure.LocalCount;
                        }
                    }

                    // JIL FEP
                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.PC;
                    record.locals = localProcedure.LocalCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = globalProcIndex;

                    // Construct the fep arguments
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                else
                {
                    ProtoCore.Lang.JILActivationRecord jRecord = new ProtoCore.Lang.JILActivationRecord();
                    jRecord.pc = localProcedure.PC;
                    jRecord.locals = localProcedure.LocalCount;
                    jRecord.classIndex = globalClassIndex;
                    jRecord.funcIndex = localProcedure.ID;

                    ProtoCore.Lang.FFIActivationRecord record = new ProtoCore.Lang.FFIActivationRecord();
                    record.JILRecord = jRecord;
                    record.FunctionName = funcDef.Name;
                    record.ModuleName = funcDef.ExternLibName;
                    record.ModuleType = "dll";
                    record.IsDNI = false;
                    record.ReturnType = funcDef.ReturnType;
                    record.ParameterTypes = localProcedure.ArgumentTypes;
                    fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                }

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.ArgumentTypes.Count];
                fep.procedureNode = localProcedure;
                localProcedure.ArgumentTypes.CopyTo(fep.FormalParams, 0);

                // 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.InitGlobalFunctionEntry(classIndexAtCallsite);

                Dictionary<string, FunctionGroup> fgroup = core.FunctionTable.GlobalFuncTable[classIndexAtCallsite];
                if (!fgroup.ContainsKey(funcDef.Name))
                {
                    // Create a new function group in this class
                    ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                    funcGroup.FunctionEndPoints.Add(fep);

                    // Add this group to the class function tables
                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                }
                else
                {
                    // Add this fep into the exisitng function group
                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite][funcDef.Name].FunctionEndPoints.Add(fep);
                }

                int startpc = pc;

                // Constructors auto return
                EmitInstrConsole(ProtoCore.DSASM.kw.retc);

                // Stepping out of a constructor body will have the execution cursor 
                // placed right at the closing curly bracket of the constructor definition.
                // 
                int closeCurlyBracketLine = 0, closeCurlyBracketColumn = -1;
                if (null != funcDef.FunctionBody)
                {
                    closeCurlyBracketLine = funcDef.FunctionBody.endLine;
                    closeCurlyBracketColumn = funcDef.FunctionBody.endCol;
                }

                // The execution cursor covers exactly one character -- the closing 
                // curly bracket. Note that we decrement the start-column by one here 
                // because end-column of "FunctionBody" here is *after* the closing 
                // curly bracket, so we want one before that.
                // 
                EmitRetc(closeCurlyBracketLine, closeCurlyBracketColumn - 1,
                    closeCurlyBracketLine, closeCurlyBracketColumn);

                // Build and append a graphnode for this return statememt
                ProtoCore.DSASM.SymbolNode returnNode = new ProtoCore.DSASM.SymbolNode();
                returnNode.name = ProtoCore.DSDefinitions.Keyword.Return;

                ProtoCore.AssociativeGraph.GraphNode retNode = new ProtoCore.AssociativeGraph.GraphNode();
                //retNode.symbol = returnNode;
                retNode.PushSymbolReference(returnNode);
                retNode.procIndex = globalProcIndex;
                retNode.classIndex = globalClassIndex;
                retNode.updateBlock.startpc = startpc;
                retNode.updateBlock.endpc = pc - 1;

                PushGraphNode(retNode);
                EmitCompileLogFunctionEnd();
            }

            // Constructors have no return statemetns, reset variables here
            core.ProcNode = localProcedure = null;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            core.BaseOffset = 0;
            argOffset = 0;
            classOffset = 0;
            codeBlock.blockType = originalBlockType;
        }
Ejemplo n.º 30
0
        private ProtoCore.AssociativeGraph.UpdateNodeRef AutoGenerateUpdateReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode)
        {
            // Get the lhs symbol list
            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = globalClassIndex;
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
            DFSGetSymbolList(node, ref type, leftNodeRef);


            // Auto-generate the updateNodeRefs for this graphnode given the list 
            // stored in the first procedure found in the assignment expression
            if (functionCallStack.Count > 0)
            {
                ProtoCore.DSASM.ProcedureNode firstProc = functionCallStack[0];
                if (!firstProc.IsAutoGenerated)
                {
                    graphNode.firstProc = firstProc;
                }
            }
            ProtoCore.DSASM.SymbolNode firstSymbol = null;

            // See if the leftmost symbol(updateNodeRef) of the lhs expression is a property of the current class. 
            // If it is, then push the lhs updateNodeRef to the list of modified properties in the procedure node
            if (null != localProcedure && leftNodeRef.nodeList.Count > 0)
            {
                firstSymbol = leftNodeRef.nodeList[0].symbol;

                // Check if this symbol being modified in this function is allocated in the current scope.
                // If it is, then it means this symbol is not a member and is local to this function
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAccessible = false;
                bool isLocalVariable = VerifyAllocationInScope(firstSymbol.name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                if (!isLocalVariable)
                {
                    if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod)
                    {
                        if (firstSymbol.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                        {
                            // Does the symbol belong on the same class or class heirarchy as the function calling it
                            if (firstSymbol.classScope == localProcedure.ClassID)
                            {
                                localProcedure.UpdatedProperties.Push(leftNodeRef);
                            }
                            else
                            {
                                if (localProcedure.ClassID > 0)
                                {
                                    if (core.ClassTable.ClassNodes[localProcedure.ClassID].IsMyBase(firstSymbol.classScope))
                                    {
                                        localProcedure.UpdatedProperties.Push(leftNodeRef);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return leftNodeRef;
        }
        public static ProtoCore.AST.AssociativeAST.FunctionDotCallNode GenerateCallDotNode(ProtoCore.AST.AssociativeAST.AssociativeNode lhs,
                                                                                           ProtoCore.AST.AssociativeAST.FunctionCallNode rhsCall, Core core = null)
        {
            // The function name to call
            string rhsName = rhsCall.Function.Name;
            int    argNum  = rhsCall.FormalArguments.Count;

            ProtoCore.AST.AssociativeAST.ExprListNode argList = new ProtoCore.AST.AssociativeAST.ExprListNode();
            foreach (ProtoCore.AST.AssociativeAST.AssociativeNode arg in rhsCall.FormalArguments)
            {
                // The function arguments
                argList.list.Add(arg);
            }


            FunctionCallNode funCallNode = new FunctionCallNode();
            IdentifierNode   funcName    = new IdentifierNode {
                Value = Constants.kDotArgMethodName, Name = Constants.kDotArgMethodName
            };

            funCallNode.Function = funcName;
            funCallNode.Name     = Constants.kDotArgMethodName;

            NodeUtils.CopyNodeLocation(funCallNode, lhs);
            int    rhsIdx  = ProtoCore.DSASM.Constants.kInvalidIndex;
            string lhsName = string.Empty;

            if (lhs is ProtoCore.AST.AssociativeAST.IdentifierNode)
            {
                lhsName = (lhs as ProtoCore.AST.AssociativeAST.IdentifierNode).Name;
                if (lhsName == ProtoCore.DSDefinitions.Keyword.This)
                {
                    lhs = new ProtoCore.AST.AssociativeAST.ThisPointerNode();
                }
            }

            if (core != null)
            {
                DynamicFunction func;
                if (core.DynamicFunctionTable.TryGetFunction(rhsName, 0, Constants.kInvalidIndex, out func))
                {
                    rhsIdx = func.Index;
                }
                else
                {
                    func   = core.DynamicFunctionTable.AddNewFunction(rhsName, 0, Constants.kInvalidIndex);
                    rhsIdx = func.Index;
                }
            }

            // The first param to the dot arg (the pointer or the class name)
            funCallNode.FormalArguments.Add(lhs);

            // The second param which is the dynamic table index of the function to call
            var rhs = new IntNode(rhsIdx);

            funCallNode.FormalArguments.Add(rhs);

            // The array dimensions
            ProtoCore.AST.AssociativeAST.ExprListNode arrayDimExperList = new ProtoCore.AST.AssociativeAST.ExprListNode();
            int dimCount = 0;

            if (rhsCall.Function is ProtoCore.AST.AssociativeAST.IdentifierNode)
            {
                // Number of dimensions
                ProtoCore.AST.AssociativeAST.IdentifierNode fIdent = rhsCall.Function as ProtoCore.AST.AssociativeAST.IdentifierNode;
                if (fIdent.ArrayDimensions != null)
                {
                    arrayDimExperList = ProtoCore.Utils.CoreUtils.BuildArrayExprList(fIdent.ArrayDimensions);
                    dimCount          = arrayDimExperList.list.Count;
                }
                else if (rhsCall.ArrayDimensions != null)
                {
                    arrayDimExperList = ProtoCore.Utils.CoreUtils.BuildArrayExprList(rhsCall.ArrayDimensions);
                    dimCount          = arrayDimExperList.list.Count;
                }
                else
                {
                    arrayDimExperList = new ProtoCore.AST.AssociativeAST.ExprListNode();
                }
            }

            funCallNode.FormalArguments.Add(arrayDimExperList);

            // Number of dimensions
            var dimNode = new IntNode(dimCount);

            funCallNode.FormalArguments.Add(dimNode);

            if (argNum >= 0)
            {
                funCallNode.FormalArguments.Add(argList);
                funCallNode.FormalArguments.Add(new IntNode(argNum));
            }

            var funDotCallNode = new FunctionDotCallNode(rhsCall);

            funDotCallNode.DotCall = funCallNode;
            funDotCallNode.FunctionCall.Function = rhsCall.Function;

            // Consider the case of "myClass.Foo(a, b)", we will have "DotCall" being
            // equal to "myClass" (in terms of its starting line/column), and "rhsCall"
            // matching with the location of "Foo(a, b)". For execution cursor to cover
            // this whole statement, the final "DotCall" function call node should
            // range from "lhs.col" to "rhs.col".
            //
            NodeUtils.SetNodeEndLocation(funDotCallNode.DotCall, rhsCall);
            NodeUtils.CopyNodeLocation(funDotCallNode, funDotCallNode.DotCall);


            return(funDotCallNode);
        }
Ejemplo n.º 32
0
        private bool EmitLHSThisDotProperyForBinaryExpr(AssociativeNode bnode, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode binaryExpr = bnode as BinaryExpressionNode;
            if (binaryExpr == null || !(binaryExpr.LeftNode is IdentifierNode))
            {
                return false;
            }

            if (globalClassIndex != Constants.kGlobalScope && globalProcIndex != Constants.kGlobalScope)
            {
                ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];
                ProcedureNode procNode = thisClass.ProcTable.Procedures[globalProcIndex];

                IdentifierNode identNode = (binaryExpr.LeftNode as IdentifierNode);
                string identName = identNode.Value;

                // Local variables are not appended with 'this'
                if (!identNode.IsLocal)
                {
                    if (!procNode.Name.Equals(ProtoCore.DSASM.Constants.kSetterPrefix + identName))
                    {
                        SymbolNode symbolnode;
                        bool isAccessible = false;
                        VerifyAllocation(identName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);

                        if (symbolnode != null &&
                            symbolnode.classScope != Constants.kGlobalScope &&
                            symbolnode.functionIndex == Constants.kGlobalScope)
                        {
                            var thisNode =AstFactory.BuildIdentifier(ProtoCore.DSDefinitions.Keyword.This);
                            var thisIdentListNode = AstFactory.BuildIdentList(thisNode, binaryExpr.LeftNode);
                            var newAssignment = AstFactory.BuildAssignment(thisIdentListNode, binaryExpr.RightNode);
                            NodeUtils.CopyNodeLocation(newAssignment, bnode);

                            if (ProtoCore.DSASM.Constants.kInvalidIndex != binaryExpr.ExpressionUID)
                            {
                                (newAssignment as BinaryExpressionNode).ExpressionUID = binaryExpr.ExpressionUID;
                            }
                            EmitBinaryExpressionNode(newAssignment, ref inferedType, isBooleanOp, graphNode, subPass, isTempExpression);
                            return true;
                        }
                    }
                }
            }

            return false;
        }
Ejemplo n.º 33
0
        /// <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;
        }
Ejemplo n.º 34
0
 private void InferDFSTraverse(AssociativeNode node, ref ProtoCore.Type inferedType)
 {
     if (node is IdentifierNode)
     {
         IdentifierNode t = node as IdentifierNode;
         if (core.TypeSystem.IsHigherRank(t.datatype.UID, inferedType.UID))
         {
             ProtoCore.Type type = new ProtoCore.Type();
             type.UID = t.datatype.UID;
             inferedType = type;
         }
     }
     else if (node is BinaryExpressionNode)
     {
         BinaryExpressionNode b = node as BinaryExpressionNode;
         InferDFSTraverse(b.LeftNode, ref inferedType);
         InferDFSTraverse(b.RightNode, ref inferedType);
     }
 }
Ejemplo n.º 35
0
        private void EmitDynamicLanguageBlockNode(AssociativeNode node, AssociativeNode singleBody, ref ProtoCore.Type inferedType, ref int blockId, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
        {
            if (IsParsingGlobal() || IsParsingGlobalFunctionBody() || IsParsingMemberFunctionBody())
            {
                if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                {
                    return;
                }

                LanguageBlockNode langblock = node as LanguageBlockNode;

                //Validity.Assert(ProtoCore.Language.kInvalid != langblock.codeblock.language);
                if (ProtoCore.Language.NotSpecified == langblock.codeblock.Language)
                    throw new BuildHaltException("Invalid language block type (B1C57E37)");

                ProtoCore.CompileTime.Context context = new ProtoCore.CompileTime.Context();

                // Set the current class scope so the next language can refer to it
                core.ClassIndex = globalClassIndex;

                if (globalProcIndex != ProtoCore.DSASM.Constants.kInvalidIndex && core.ProcNode == null)
                {
                    if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                        core.ProcNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                    else
                        core.ProcNode = codeBlock.procedureTable.Procedures[globalProcIndex];
                }

                core.Compilers[langblock.codeblock.Language].Compile(
                    out blockId, codeBlock, langblock.codeblock, context, codeBlock.EventSink, langblock.CodeBlockNode, null);
                
            }
        }
Ejemplo n.º 36
0
        private void EmitGroupExpressionNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
        {
            GroupExpressionNode group = node as GroupExpressionNode;
            if (group == null)
            {
                return;
            }

            bool emitReplicationGuideFlag = emitReplicationGuide;
            emitReplicationGuide = false;
            DfsTraverse(group.Expression, ref inferedType, isBooleanOp, graphNode, subPass);
            emitReplicationGuide = emitReplicationGuideFlag;

            if (group.ArrayDimensions != null)
            {
                if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                {
                    int dimensions = DfsEmitArrayIndexHeap(group.ArrayDimensions, graphNode);
                    EmitPushArrayIndex(dimensions);
                }
            }

            if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier && emitReplicationGuide)
            {
                EmitAtLevel(group.AtLevel);
                EmitReplicationGuides(group.ReplicationGuides);
            }
        }
Ejemplo n.º 37
0
        private void EmitClassDeclNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone,
            GraphNode graphNode = null)
        {
            ClassDeclNode classDecl = node as ClassDeclNode;
            
            // Restrict classes 
            if (!IsClassAllowed(classDecl))
            {
                return;
            }
            // Handling n-pass on class declaration
            if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassName == compilePass)
            {
                // Class name pass
                // Populating the class tables with the class names
                if (null != codeBlock.parent)
                {
                    buildStatus.LogSemanticError(Resources.ClassCannotBeDefinedInsideLanguageBlock, core.CurrentDSFileName, classDecl.line, classDecl.col);
                }


                ProtoCore.DSASM.ClassNode thisClass = new ProtoCore.DSASM.ClassNode();
                thisClass.Name = classDecl.ClassName;
                thisClass.Size = classDecl.Variables.Count;
                thisClass.IsImportedClass = classDecl.IsImportedClass;
                thisClass.TypeSystem = core.TypeSystem;
                thisClass.ClassAttributes = classDecl.ClassAttributes;
                
                if (classDecl.ExternLibName != null)
                    thisClass.ExternLib = classDecl.ExternLibName;
                else
                    thisClass.ExternLib = Path.GetFileName(core.CurrentDSFileName);

                globalClassIndex = core.ClassTable.Append(thisClass);
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    string message = string.Format("Class redefinition '{0}' (BE1C3285).\n", classDecl.ClassName);
                    buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                    throw new BuildHaltException(message);
                }

                unPopulatedClasses.Add(globalClassIndex, classDecl);

                //Always allow us to convert a class to a bool
                thisClass.CoerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore);
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassBaseClass == compilePass)
            { 
                // Base class pass
                // Populating each class entry with their immediate baseclass
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];

                // Verify and store the list of classes it inherits from 
                if (null != classDecl.BaseClasses)
                {
                    for (int n = 0; n < classDecl.BaseClasses.Count; ++n)
                    {
                        int baseClass = core.ClassTable.GetClassId(classDecl.BaseClasses[n]);
                        if (baseClass == globalClassIndex)
                        {
                            string message = string.Format("Class '{0}' cannot derive from itself (DED0A61F).\n", classDecl.ClassName);
                            buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                            throw new BuildHaltException(message);
                        }

                        if (ProtoCore.DSASM.Constants.kInvalidIndex != baseClass)
                        {
                            if (core.ClassTable.ClassNodes[baseClass].IsImportedClass && !thisClass.IsImportedClass)
                            {
                                string message = string.Format("Cannot derive from FFI class {0} (DA87AC4D).\n",
                                    core.ClassTable.ClassNodes[baseClass].Name);

                                buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                                throw new BuildHaltException(message);
                            }

                            thisClass.Bases.Add(baseClass);
                            thisClass.CoerceTypes.Add(baseClass, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceBaseClass);
                        }
                        else
                        {
                            string message = string.Format("Unknown base class '{0}' (9E44FFB3).\n", classDecl.BaseClasses[n]);
                            buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                            throw new BuildHaltException(message);
                        }
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassHierarchy == compilePass)
            {
                // Class hierarchy pass
                // Populating each class entry with all sub classes in the hierarchy
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];

                // Verify and store the list of classes it inherits from 
                if (null != classDecl.BaseClasses)
                {
                    for (int n = 0; n < classDecl.BaseClasses.Count; ++n)
                    {
                        int baseClass = core.ClassTable.GetClassId(classDecl.BaseClasses[n]);

                        // baseClass is already resovled in the previous pass
                        Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != baseClass);

                            
                        // Iterate through all the base classes until the the root class
                        // For every base class, add the coercion score
                        ProtoCore.DSASM.ClassNode tmpCNode = core.ClassTable.ClassNodes[baseClass];
                        if (tmpCNode.Bases.Count > 0)
                        {
                            baseClass = tmpCNode.Bases[0];
                            while (ProtoCore.DSASM.Constants.kInvalidIndex != baseClass)
                            {
                                thisClass.CoerceTypes.Add(baseClass, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceBaseClass);
                                tmpCNode = core.ClassTable.ClassNodes[baseClass];

                                baseClass = ProtoCore.DSASM.Constants.kInvalidIndex;
                                if (tmpCNode.Bases.Count > 0)
                                {
                                    baseClass = tmpCNode.Bases[0];
                                }
                            }
                        }
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemVar == compilePass)
            {
                EmitMemberVariables(classDecl, graphNode);
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncSig == compilePass)
            {
                // Class member variable pass
                // Populating each class entry vtables with their respective
                // member variables signatures
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                List<AssociativeNode> thisPtrOverloadList = new List<AssociativeNode>();
                foreach (AssociativeNode funcdecl in classDecl.Procedures)
                {
                    DfsTraverse(funcdecl, ref inferedType);

                    var funcDef = funcdecl as FunctionDefinitionNode;
                    if (funcDef == null || funcDef.IsStatic || funcDef.Name == ProtoCore.DSDefinitions.Keyword.Dispose)
                        continue;

                    bool isGetterSetter = CoreUtils.IsGetterSetter(funcDef.Name);

                    var thisPtrArgName = Constants.kThisPointerArgName;
                    if (!isGetterSetter)
                    {
                        var classsShortName = classDecl.ClassName.Split('.').Last();
                        var typeDepName = classsShortName.ToLower();
                        if (typeDepName != classsShortName && funcDef.Signature.Arguments.All(a => a.NameNode.Name != typeDepName))
                            thisPtrArgName = typeDepName;
                    }

                    // This is a function, create its parameterized this pointer overload
                    ThisPointerProcOverload thisProc = new ThisPointerProcOverload();
                    thisProc.classIndex = globalClassIndex;
                    thisProc.procNode = new FunctionDefinitionNode(funcDef);
                    var thisPtrArg = new VarDeclNode()
                    {
                        Access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic,
                        NameNode = AstFactory.BuildIdentifier(thisPtrArgName),
                        ArgumentType = new ProtoCore.Type { Name = classDecl.ClassName, UID = globalClassIndex, rank = 0 }
                    };
                    thisProc.procNode.Signature.Arguments.Insert(0, thisPtrArg);
                    thisProc.procNode.IsAutoGeneratedThisProc = true;

                    if (CoreUtils.IsGetterSetter(funcDef.Name))
                    {
                        InsertThisPointerAtBody(thisProc);
                    }
                    else
                    {
                        // Generate a static function for member function f():
                        //     satic def f(a: A)
                        //     { 
                        //        return = a.f()
                        //     }
                        thisProc.procNode.IsStatic = true;
                        BuildThisFunctionBody(thisProc);
                    }

                    thisPtrOverloadList.Add(thisProc.procNode);
                }

                foreach (var overloadFunc in thisPtrOverloadList)
                {
                    // Emit the newly defined overloads
                    DfsTraverse(overloadFunc, ref inferedType);
                }

                classDecl.Procedures.AddRange(thisPtrOverloadList);

                if (!classDecl.IsExternLib)
                {
                    ProtoCore.DSASM.ProcedureTable vtable = core.ClassTable.ClassNodes[globalClassIndex].ProcTable;
                    if (vtable.GetFunctionBySignature(classDecl.ClassName, new List<ProtoCore.Type>()) == null)
                    {
                        ConstructorDefinitionNode defaultConstructor = new ConstructorDefinitionNode();
                        defaultConstructor.Name = classDecl.ClassName;
                        defaultConstructor.LocalVariableCount = 0;
                        defaultConstructor.Signature = new ArgumentSignatureNode();
                        defaultConstructor.ReturnType = new ProtoCore.Type { Name = "var", UID = 0 };
                        defaultConstructor.FunctionBody = new CodeBlockNode();
                        defaultConstructor.BaseConstructor = null;
                        defaultConstructor.Access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic;
                        defaultConstructor.IsExternLib = false;
                        defaultConstructor.ExternLibName = null;
                        DfsTraverse(defaultConstructor, ref inferedType);
                        classDecl.Procedures.Add(defaultConstructor);
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope == compilePass)
            {
                // before populate the attributes, we must know the attribute class constructor signatures
                // in order to check the parameter 
                // populate the attributes for the class and class member variable 
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);
                if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];
                    // class
                    if (classDecl.Attributes != null)
                    {
                        thisClass.Attributes = PopulateAttributes(classDecl.Attributes);
                    }

                    // member variable
                    int ix = -1;
                    int currentClassScope = -1;
                    foreach (ProtoCore.DSASM.SymbolNode sn in thisClass.Symbols.symbolList.Values)
                    {
                        // only populate the attributes for member variabls
                        if (sn.functionIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                            continue;
                        if (sn.classScope != globalClassIndex)
                        {
                            if (currentClassScope != sn.classScope)
                            {
                                currentClassScope = sn.classScope;
                                ix = 0;
                            }
                            // copy attribute information from base class
                            sn.Attributes = core.ClassTable.ClassNodes[currentClassScope].Symbols.symbolList[ix++].Attributes;
                        }
                        else
                        {
                            if (currentClassScope != globalClassIndex)
                            {
                                currentClassScope = globalClassIndex;
                                ix = 0;
                            }
                        }
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncBody == compilePass)
            {
                // Class member variable pass
                // Populating the function body of each member function defined in the class vtables

                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                // Initialize the global function table for this class
                // 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.InitGlobalFunctionEntry(classIndexAtCallsite);

                foreach (AssociativeNode funcdecl in classDecl.Procedures)
                {
                    // reset the inferedtype between functions
                    inferedType = new ProtoCore.Type();
                    DfsTraverse(funcdecl, ref inferedType, false, null, subPass);
                }
            }

            // Reset the class index
            core.ClassIndex = globalClassIndex = ProtoCore.DSASM.Constants.kGlobalScope;
        }