Пример #1
0
 public void TestMethodHasNullCheck()
 {
     AssociativeNode foo = new IdentifierNode("foo");
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildAssignment(foo, null));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildAssignment(null, foo));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildBinaryExpression(foo, null, ProtoCore.DSASM.Operator.assign));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildBinaryExpression(null, foo, ProtoCore.DSASM.Operator.assign));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildConditionalNode(null, foo, foo));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildConditionalNode(foo, null, foo));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildConditionalNode(foo, foo, null));
     List<AssociativeNode> nullList = null;
     List<AssociativeNode> fooList = new List<AssociativeNode>();
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildExprList(nullList));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildFunctionCall(() => {}, null));
     string nullIdent = null;
     AssociativeNode nullNode = null;
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildFunctionObject(nullNode, 0, new List<int> {}, fooList));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildFunctionObject(foo, 0, null, fooList));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildFunctionObject(nullNode, 0, new List<int> {}, null));
     Assert.Throws<ArgumentException>(() => AstFactory.BuildFunctionObject(nullIdent, 0, new List<int> { } , fooList));
     Assert.Throws<ArgumentException>(() => AstFactory.BuildFunctionObject(string.Empty, 0, new List<int> { } , fooList));
     Assert.Throws<ArgumentException>(() => AstFactory.BuildIdentifier(null));
     Assert.Throws<ArgumentException>(() => AstFactory.BuildIdentifier(String.Empty));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildStringNode(null));
     Assert.Throws<ArgumentException>(() => AstFactory.BuildParamNode(null));
     Assert.Throws<ArgumentException>(() => AstFactory.BuildParamNode(string.Empty));
     Assert.Throws<ArgumentNullException>(() => AstFactory.BuildReturnStatement(null));
     Assert.Throws<ArgumentNullException>(() => AstFactory.AddReplicationGuide(null, null, false));
 }
Пример #2
0
 public static ProtoCore.AST.AssociativeAST.IdentifierNode BuildAssocIdentifier(Core core, string name, ProtoCore.PrimitiveType type = ProtoCore.PrimitiveType.kTypeVar)
 {
     var ident = new ProtoCore.AST.AssociativeAST.IdentifierNode();
     ident.Name = ident.Value = name;
     ident.datatype = TypeSystem.BuildPrimitiveTypeObject(type, 0);
     return ident;
 }
Пример #3
0
        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {
            AssociativeNode rhs = null;

            if (IsPartiallyApplied)
            {
                var connectedInputs = new List<AssociativeNode>();
                var functionNode = new IdentifierNode(functionName);
                var paramNumNode = new IntNode(1);
                var positionNode = AstFactory.BuildExprList(connectedInputs);
                var arguments = AstFactory.BuildExprList(inputAstNodes);
                var inputParams = new List<AssociativeNode>
                {
                    functionNode,
                    paramNumNode,
                    positionNode,
                    arguments,
                    AstFactory.BuildBooleanNode(true)
                };

                rhs = AstFactory.BuildFunctionCall("_SingleFunctionObject", inputParams);
            }
            else
            {
                rhs = AstFactory.BuildFunctionCall(functionName, inputAstNodes);
            }

            return new[]
            {
               AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), rhs)
            };
        }
Пример #4
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;
        }
Пример #5
0
        private ProtoCore.AST.AssociativeAST.VarDeclNode ParseArgumentDeclaration(string parameterName, Type parameterType)
        {
            ProtoCore.AST.AssociativeAST.VarDeclNode varDeclNode = new ProtoCore.AST.AssociativeAST.VarDeclNode();
            varDeclNode.memregion = ProtoCore.DSASM.MemoryRegion.kMemStack;
            varDeclNode.access    = ProtoCore.DSASM.AccessSpecifier.kPublic;

            ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode = new ProtoCore.AST.AssociativeAST.IdentifierNode
            {
                Value    = parameterName,
                Name     = parameterName,
                datatype = new ProtoCore.Type()
                {
                    Name        = "var",
                    IsIndexable = false,
                    rank        = 0,
                    UID         = (int)ProtoCore.PrimitiveType.kTypeVar
                }
            };
            //Lets emit native DS type object
            ProtoCore.Type argtype = CLRModuleType.GetProtoCoreType(parameterType, Module);

            varDeclNode.NameNode     = identifierNode;
            varDeclNode.ArgumentType = argtype;
            return(varDeclNode);
        }
        public static ProtoCore.AST.AssociativeAST.IdentifierNode BuildAssocIdentifier(Core core, string name, ProtoCore.PrimitiveType type = ProtoCore.PrimitiveType.kTypeVar)
        {
            var ident = new ProtoCore.AST.AssociativeAST.IdentifierNode();

            ident.Name     = ident.Value = name;
            ident.datatype = TypeSystem.BuildPrimitiveTypeObject(type, 0);
            return(ident);
        }
Пример #7
0
        private VariableSlotInfo GetVariableSlotInfo(ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode)
        {
            string var  = identifierNode.Value;
            int    line = identifierNode.line;
            uint   slot = uint.MaxValue;

            return(new VariableSlotInfo(var, line, slot));
        }
Пример #8
0
        private static FunctionDotCallNode CreateFunctionCallNode(string className, string methodName, List<AssociativeNode> args, Core core)
        {
            FunctionCallNode fNode = new FunctionCallNode();
            fNode.Function = new IdentifierNode(methodName);
            fNode.FormalArguments = args;

            IdentifierNode inode = new IdentifierNode(className);
            return CoreUtils.GenerateCallDotNode(inode, fNode, core);
        }
        private static void InsertInlineConditionOperationMethod(Core core, ProtoCore.AST.Node root, PrimitiveType condition, PrimitiveType r)
        {
            ProtoCore.AST.AssociativeAST.FunctionDefinitionNode funcDefNode = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode();
            funcDefNode.access     = ProtoCore.Compiler.AccessSpecifier.kPublic;
            funcDefNode.Name       = ProtoCore.DSASM.Constants.kInlineCondition;
            funcDefNode.ReturnType = new ProtoCore.Type()
            {
                Name = core.TypeSystem.GetType((int)r), UID = (int)r
            };
            ProtoCore.AST.AssociativeAST.ArgumentSignatureNode args = new ProtoCore.AST.AssociativeAST.ArgumentSignatureNode();
            args.AddArgument(new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion    = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access       = ProtoCore.Compiler.AccessSpecifier.kPublic,
                NameNode     = BuildAssocIdentifier(core, "%condition"),
                ArgumentType = new ProtoCore.Type {
                    Name = core.TypeSystem.GetType((int)condition), UID = (int)condition
                }
            });
            args.AddArgument(new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion    = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access       = ProtoCore.Compiler.AccessSpecifier.kPublic,
                NameNode     = BuildAssocIdentifier(core, "%trueExp"),
                ArgumentType = new ProtoCore.Type {
                    Name = core.TypeSystem.GetType((int)r), UID = (int)r
                }
            });
            args.AddArgument(new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion    = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access       = ProtoCore.Compiler.AccessSpecifier.kPublic,
                NameNode     = BuildAssocIdentifier(core, "%falseExp"),
                ArgumentType = new ProtoCore.Type {
                    Name = core.TypeSystem.GetType((int)r), UID = (int)r
                }
            });
            funcDefNode.Signature = args;

            ProtoCore.AST.AssociativeAST.CodeBlockNode  body    = new ProtoCore.AST.AssociativeAST.CodeBlockNode();
            ProtoCore.AST.AssociativeAST.IdentifierNode _return = BuildAssocIdentifier(core, ProtoCore.DSDefinitions.Keyword.Return, ProtoCore.PrimitiveType.kTypeReturn);
            ProtoCore.AST.AssociativeAST.IdentifierNode con     = BuildAssocIdentifier(core, "%condition");
            ProtoCore.AST.AssociativeAST.IdentifierNode t       = BuildAssocIdentifier(core, "%trueExp");
            ProtoCore.AST.AssociativeAST.IdentifierNode f       = BuildAssocIdentifier(core, "%falseExp");

            body.Body.Add(new ProtoCore.AST.AssociativeAST.BinaryExpressionNode()
            {
                LeftNode = _return, Optr = Operator.assign, RightNode = new ProtoCore.AST.AssociativeAST.InlineConditionalNode()
                {
                    ConditionExpression = con, TrueExpression = t, FalseExpression = f
                }
            });
            funcDefNode.FunctionBody = body;
            (root as ProtoCore.AST.AssociativeAST.CodeBlockNode).Body.Add(funcDefNode);
        }
Пример #10
0
        private static FunctionDotCallNode CreateEntityNode(long hostInstancePtr, Core core)
        {
            FunctionCallNode fNode = new FunctionCallNode();
            fNode.Function = new IdentifierNode("FromObject");
            List<ProtoCore.AST.AssociativeAST.AssociativeNode> listArgs = new List<ProtoCore.AST.AssociativeAST.AssociativeNode>();
            listArgs.Add(new ProtoCore.AST.AssociativeAST.IntNode(hostInstancePtr));
            fNode.FormalArguments = listArgs;

            string className = "Geometry";
            IdentifierNode inode = new ProtoCore.AST.AssociativeAST.IdentifierNode(className);
            return ProtoCore.Utils.CoreUtils.GenerateCallDotNode(inode, fNode, core);            
        }
Пример #11
0
        private static FunctionDotCallNode CreateEntityNode(long hostInstancePtr, Core core)
        {
            FunctionCallNode fNode = new FunctionCallNode();

            fNode.Function = new IdentifierNode("FromObject");
            List <ProtoCore.AST.AssociativeAST.AssociativeNode> listArgs = new List <ProtoCore.AST.AssociativeAST.AssociativeNode>();

            listArgs.Add(new ProtoCore.AST.AssociativeAST.IntNode(hostInstancePtr));
            fNode.FormalArguments = listArgs;

            string         className = "Geometry";
            IdentifierNode inode     = new ProtoCore.AST.AssociativeAST.IdentifierNode(className);

            return(ProtoCore.Utils.CoreUtils.GenerateCallDotNode(inode, fNode, core));
        }
Пример #12
0
        private VariableSlotInfo GetVariableSlotInfo(FunctionDotCallNode functionDotCallNode)
        {
            // @TODO(done): No hard-casting.
            ProtoCore.AST.AssociativeAST.IdentifierNode idenNode = functionDotCallNode.DotCall.FormalArguments[0] as ProtoCore.AST.AssociativeAST.IdentifierNode;

            if (idenNode == null)
            {
                throw new InvalidOperationException("Unsupported AST Node Type");
            }

            string var  = idenNode.Value;
            int    line = functionDotCallNode.line;
            uint   slot = uint.MaxValue;

            return(new VariableSlotInfo(var, line, slot));
        }
        private static void InsertBinaryOperationMethod(Core core, ProtoCore.AST.Node root, Operator op, PrimitiveType r, PrimitiveType op1, PrimitiveType op2, int retRank = 0, int op1rank = 0, int op2rank = 0)
        {
            ProtoCore.AST.AssociativeAST.FunctionDefinitionNode funcDefNode = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode();
            funcDefNode.access          = ProtoCore.Compiler.AccessSpecifier.kPublic;
            funcDefNode.IsAssocOperator = true;
            funcDefNode.IsBuiltIn       = true;
            funcDefNode.Name            = Op.GetOpFunction(op);
            funcDefNode.ReturnType      = new ProtoCore.Type()
            {
                Name = core.TypeSystem.GetType((int)r), UID = (int)r, rank = retRank
            };
            ProtoCore.AST.AssociativeAST.ArgumentSignatureNode args = new ProtoCore.AST.AssociativeAST.ArgumentSignatureNode();
            args.AddArgument(new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion    = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access       = ProtoCore.Compiler.AccessSpecifier.kPublic,
                NameNode     = BuildAssocIdentifier(core, ProtoCore.DSASM.Constants.kLHS),
                ArgumentType = new ProtoCore.Type {
                    Name = core.TypeSystem.GetType((int)op1), UID = (int)op1, rank = op1rank
                }
            });
            args.AddArgument(new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion    = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access       = ProtoCore.Compiler.AccessSpecifier.kPublic,
                NameNode     = BuildAssocIdentifier(core, ProtoCore.DSASM.Constants.kRHS),
                ArgumentType = new ProtoCore.Type {
                    Name = core.TypeSystem.GetType((int)op2), UID = (int)op2, rank = op2rank
                }
            });
            funcDefNode.Signature = args;

            ProtoCore.AST.AssociativeAST.CodeBlockNode  body    = new ProtoCore.AST.AssociativeAST.CodeBlockNode();
            ProtoCore.AST.AssociativeAST.IdentifierNode _return = BuildAssocIdentifier(core, ProtoCore.DSDefinitions.Keyword.Return, ProtoCore.PrimitiveType.kTypeReturn);

            ProtoCore.AST.AssociativeAST.IdentifierNode lhs = BuildAssocIdentifier(core, ProtoCore.DSASM.Constants.kLHS);
            ProtoCore.AST.AssociativeAST.IdentifierNode rhs = BuildAssocIdentifier(core, ProtoCore.DSASM.Constants.kRHS);
            body.Body.Add(new ProtoCore.AST.AssociativeAST.BinaryExpressionNode()
            {
                LeftNode = _return, Optr = ProtoCore.DSASM.Operator.assign, RightNode = new ProtoCore.AST.AssociativeAST.BinaryExpressionNode()
                {
                    LeftNode = lhs, RightNode = rhs, Optr = op
                }
            });
            funcDefNode.FunctionBody = body;
            (root as ProtoCore.AST.AssociativeAST.CodeBlockNode).Body.Add(funcDefNode);
        }
Пример #14
0
 private string GetTopLevelVariable(AssociativeNode astNode)
 {
     if (astNode is ProtoCore.AST.AssociativeAST.IdentifierNode)
     {
         ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode = (ProtoCore.AST.AssociativeAST.IdentifierNode)astNode;
         return(((ProtoCore.AST.AssociativeAST.IdentifierNode)astNode).Value);
     }
     else if (astNode is IdentifierListNode)
     {
         IdentifierListNode identListNode = (IdentifierListNode)astNode;
         return(GetTopLevelVariable(identListNode.LeftNode));
     }
     else
     {
         throw new InvalidOperationException("Input is not IdentifierNode or IdentifierListNode");
     }
 }
Пример #15
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);
        }
Пример #16
0
        private ProtoCore.AST.AssociativeAST.VarDeclNode ParseArgumentDeclaration(string parameterName, Type parameterType)
        {
            ProtoCore.AST.AssociativeAST.VarDeclNode varDeclNode = new ProtoCore.AST.AssociativeAST.VarDeclNode();
            varDeclNode.memregion = ProtoCore.DSASM.MemoryRegion.kMemStack;
            varDeclNode.access    = ProtoCore.Compiler.AccessSpecifier.kPublic;

            ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode = new ProtoCore.AST.AssociativeAST.IdentifierNode
            {
                Value    = parameterName,
                Name     = parameterName,
                datatype = ProtoCore.TypeSystem.BuildPrimitiveTypeObject(ProtoCore.PrimitiveType.kTypeVar, 0)
            };
            //Lets emit native DS type object
            ProtoCore.Type argtype = CLRModuleType.GetProtoCoreType(parameterType, Module);

            varDeclNode.NameNode     = identifierNode;
            varDeclNode.ArgumentType = argtype;
            return(varDeclNode);
        }
        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);
        }
Пример #18
0
        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {
            var lhs = GetAstIdentifierForOutputIndex(0);
            AssociativeNode rhs;

            if (IsPartiallyApplied)
            {
                var connectedInputs = Enumerable.Range(0, InPorts.Count)
                                            .Where(index=>InPorts[index].IsConnected)
                                            .Select(x => new IntNode(x) as AssociativeNode)
                                            .ToList();
                var functionNode = new IdentifierNode(Constants.kInlineConditionalMethodName);
                var paramNumNode = new IntNode(3);
                var positionNode = AstFactory.BuildExprList(connectedInputs);
                var arguments = AstFactory.BuildExprList(inputAstNodes);
                var inputParams = new List<AssociativeNode>
                {
                    functionNode,
                    paramNumNode,
                    positionNode,
                    arguments,
                    AstFactory.BuildBooleanNode(true)
                };

                rhs = AstFactory.BuildFunctionCall("__CreateFunctionObject", inputParams);
            }
            else
            {
                rhs = new InlineConditionalNode
                {
                    ConditionExpression = inputAstNodes[0],
                    TrueExpression = inputAstNodes[1],
                    FalseExpression = inputAstNodes[2]
                };
            }

            return new[]
            {
                AstFactory.BuildAssignment(lhs, rhs)
            };
        }
Пример #19
0
        private static List<ProtoCore.AST.AssociativeAST.AssociativeNode> CreateArgs(string formatString, List<string> primitiveArgs, List<AssociativeNode> argNodes)
        {
            List<AssociativeNode> args = new List<AssociativeNode>();

            for (int i = 0; i < formatString.Length; i++)
            {
                // TODO: Add a switch-case to create primitive nodes depending on the format string
                if (formatString[i] == 'd')
                {
                    double value;
                    if (Double.TryParse(primitiveArgs[i], out value))
                    {
                        args.Add(new DoubleNode(value));
                    }
                }
                else if (formatString[i].Equals('i'))
                {
                    Int64 value;
                    if (Int64.TryParse(primitiveArgs[i], out value))
                    {
                        args.Add(new IntNode(value));
                    }
                }
                else if (formatString[i].Equals('b'))
                {
                    Boolean value;
                    if (Boolean.TryParse(primitiveArgs[i], out value))
                    {
                        args.Add(new BooleanNode(value));
                    }
                }
                else if (formatString[i].Equals('s'))
                {
                    IdentifierNode iNode = new IdentifierNode(primitiveArgs[i]);

                    args.Add(iNode);
                }
            }

            return args;
        }
Пример #20
0
        private AssociativeNode ContextDataMethodCallNode(IContextData data)
        {
            string appname          = data.ContextProvider.Name;
            string connectionstring = data.Name;
            string varname          = data.Name;
            //
            //Build a functioncall node for expression varname = ImportData(appname, connectionstring);

            var func = new ProtoCore.AST.AssociativeAST.IdentifierNode();

            func.Value = func.Name = ProtoCore.DSASM.Constants.kImportData;

            var paramAppName = new ProtoCore.AST.AssociativeAST.StringNode();

            paramAppName.Value = appname;

            var paramConnectionString = new ProtoCore.AST.AssociativeAST.StringNode();

            paramConnectionString.Value = connectionstring;

            var funcCall = new ProtoCore.AST.AssociativeAST.FunctionCallNode();

            funcCall.Function = func;
            funcCall.Name     = ProtoCore.DSASM.Constants.kImportData;
            funcCall.FormalArguments.Add(paramAppName);
            funcCall.FormalArguments.Add(paramConnectionString);

            var var = new ProtoCore.AST.AssociativeAST.IdentifierNode();

            var.Name = var.Value = varname;

            var assignExpr = new ProtoCore.AST.AssociativeAST.BinaryExpressionNode();

            assignExpr.LeftNode  = var;
            assignExpr.Optr      = ProtoCore.DSASM.Operator.assign;
            assignExpr.RightNode = funcCall;

            return(assignExpr);
        }
Пример #21
0
        private void AddReferencesFromAst(AssociativeNode astNode)
        {
            if (IsPrimitiveType(astNode))
            {
                return;
            }

            ProtoCore.AST.AssociativeAST.IdentifierNode identNode = astNode as ProtoCore.AST.AssociativeAST.IdentifierNode;
            if (identNode != null)
            {
                this.references.Add(GetVariableSlotInfo(identNode));
                return;
            }

            FunctionDotCallNode funcDotCallNode = astNode as FunctionDotCallNode;

            if (funcDotCallNode != null)
            {
                // @TODO(done): Avoid hard casting.
                this.references.Add(GetVariableSlotInfo(funcDotCallNode));
                return;
            }

            FunctionCallNode functionCallNode = (FunctionCallNode)astNode;

            if (funcDotCallNode != null)
            {
                // @TODO(done): Avoid hard casting.
                foreach (AssociativeNode node in functionCallNode.FormalArguments)
                {
                    AddReferencesFromAst(node);
                }
                return;
            }

            // @TODO(Sean): Print out type info to help yourself.
            throw new ArgumentException("Unsupported node type  (79CCBEA9F50E)", "astNode");
        }
Пример #22
0
        // The following methods are used to insert methods to the bottom of the AST and convert operator to these method calls
        // to support replication on operators
        private static void InsertUnaryOperationMethod(Core core, ProtoCore.AST.Node root, UnaryOperator op, PrimitiveType r, PrimitiveType operand)
        {
            ProtoCore.AST.AssociativeAST.FunctionDefinitionNode funcDefNode = new ProtoCore.AST.AssociativeAST.FunctionDefinitionNode();
            funcDefNode.access          = ProtoCore.CompilerDefinitions.AccessModifier.kPublic;
            funcDefNode.IsAssocOperator = true;
            funcDefNode.IsBuiltIn       = true;
            funcDefNode.Name            = Op.GetUnaryOpFunction(op);
            funcDefNode.ReturnType      = new ProtoCore.Type()
            {
                Name = core.TypeSystem.GetType((int)r), UID = (int)r
            };
            ProtoCore.AST.AssociativeAST.ArgumentSignatureNode args = new ProtoCore.AST.AssociativeAST.ArgumentSignatureNode();
            args.AddArgument(new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion    = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access       = ProtoCore.CompilerDefinitions.AccessModifier.kPublic,
                NameNode     = BuildAssocIdentifier(core, "%param"),
                ArgumentType = new ProtoCore.Type {
                    Name = core.TypeSystem.GetType((int)operand), UID = (int)operand
                }
            });
            funcDefNode.Signature = args;

            ProtoCore.AST.AssociativeAST.CodeBlockNode  body    = new ProtoCore.AST.AssociativeAST.CodeBlockNode();
            ProtoCore.AST.AssociativeAST.IdentifierNode _return = BuildAssocIdentifier(core, ProtoCore.DSDefinitions.Keyword.Return, ProtoCore.PrimitiveType.kTypeReturn);
            ProtoCore.AST.AssociativeAST.IdentifierNode param   = BuildAssocIdentifier(core, "%param");
            body.Body.Add(new ProtoCore.AST.AssociativeAST.BinaryExpressionNode()
            {
                LeftNode = _return, Optr = ProtoCore.DSASM.Operator.assign, RightNode = new ProtoCore.AST.AssociativeAST.UnaryExpressionNode()
                {
                    Expression = param, Operator = op
                }
            });
            funcDefNode.FunctionBody = body;
            (root as ProtoCore.AST.AssociativeAST.CodeBlockNode).Body.Add(funcDefNode);
        }
Пример #23
0
        public AssociativeNode BuildIdentfier(string name, PrimitiveType type = PrimitiveType.kTypeVar)
        {
            var ident = new ProtoCore.AST.AssociativeAST.IdentifierNode();
            ident.Name = ident.Value = name;
            ident.datatype = compileState.TypeSystem.BuildTypeObject(type, false);

            return ident;
        }
Пример #24
0
        private AssociativeNode ContextDataMethodCallNode(IContextData data)
        {
            string appname = data.ContextProvider.Name;
            string connectionstring = data.Name;
            string varname = data.Name;
            //
            //Build a functioncall node for expression varname = ImportData(appname, connectionstring);

            var func = new ProtoCore.AST.AssociativeAST.IdentifierNode();
            func.Value = func.Name = ProtoCore.DSASM.Constants.kImportData;

            var paramAppName = new ProtoCore.AST.AssociativeAST.StringNode();
            paramAppName.value = appname;

            var paramConnectionString = new ProtoCore.AST.AssociativeAST.StringNode();
            paramConnectionString.value = connectionstring;

            var funcCall = new ProtoCore.AST.AssociativeAST.FunctionCallNode();
            funcCall.Function = func;
            funcCall.Name = ProtoCore.DSASM.Constants.kImportData;
            funcCall.FormalArguments.Add(paramAppName);
            funcCall.FormalArguments.Add(paramConnectionString);

            var var = new ProtoCore.AST.AssociativeAST.IdentifierNode();
            var.Name = var.Value = varname;

            var assignExpr = new ProtoCore.AST.AssociativeAST.BinaryExpressionNode();
            assignExpr.LeftNode = var;
            assignExpr.Optr = ProtoCore.DSASM.Operator.assign;
            assignExpr.RightNode = funcCall;

            return assignExpr;
        }
Пример #25
0
        private ProtoCore.AST.AssociativeAST.VarDeclNode ParseArgumentDeclaration(string parameterName, Type parameterType)
        {
            ProtoCore.AST.AssociativeAST.VarDeclNode varDeclNode = new ProtoCore.AST.AssociativeAST.VarDeclNode();
            varDeclNode.memregion = ProtoCore.DSASM.MemoryRegion.kMemStack;
            varDeclNode.access = ProtoCore.Compiler.AccessSpecifier.kPublic;

            ProtoCore.AST.AssociativeAST.IdentifierNode identifierNode = new ProtoCore.AST.AssociativeAST.IdentifierNode
                                                                             {
                Value = parameterName,
                Name = parameterName,
                datatype = ProtoCore.TypeSystem.BuildPrimitiveTypeObject(ProtoCore.PrimitiveType.kTypeVar, 0)
            };
            //Lets emit native DS type object
            ProtoCore.Type argtype = CLRModuleType.GetProtoCoreType(parameterType, Module);

            varDeclNode.NameNode = identifierNode;
            varDeclNode.ArgumentType = argtype;
            return varDeclNode;
        }
Пример #26
0
        public void GetStatementVariables01()
        {
            // Create a statement of "Value = 1234".
            var leftNode = new IdentifierNode("Value");
            var rightNode = new IntNode(1234);
            var binExprNode = new BinaryExpressionNode(
                leftNode, rightNode, Operator.assign);

            var statements = new List<Statement>
            {
                Statement.CreateInstance(binExprNode)
            };

            var vars = CodeBlockUtils.GetStatementVariables(statements, true);
            Assert.IsNotNull(vars);
            Assert.AreEqual(1, vars.Count());

            var variables = vars.ElementAt(0);
            Assert.IsNotNull(variables);
            Assert.AreEqual(1, variables.Count());
            Assert.AreEqual("Value", variables.ElementAt(0));
        }
Пример #27
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;
                }
            }
        }
Пример #28
0
        public Variable(IdentifierNode identNode)
        {
            if (identNode == null)
                throw new ArgumentNullException();

            Name = identNode.ToString();
            Row = identNode.line;
            StartColumn = identNode.col;
        }
Пример #29
0
        private bool EmitReplicationGuideForIdentifier(IdentifierNode t)
        {
            bool isReplicationGuideEmitted = false;
            if (emitReplicationGuide)
            {
                int replicationGuides = 0;
                if (null != t.ReplicationGuides)
                {
                    isReplicationGuideEmitted = true;

                    replicationGuides = t.ReplicationGuides.Count;
                    for (int n = 0; n < replicationGuides; ++n)
                    {
                        ProtoCore.DSASM.StackValue opguide = new ProtoCore.DSASM.StackValue();
                        Debug.Assert(t.ReplicationGuides[n] is IdentifierNode);
                        IdentifierNode nodeGuide = t.ReplicationGuides[n] as IdentifierNode;

                        EmitInstrConsole(ProtoCore.DSASM.kw.push, nodeGuide.Value);
                        opguide.optype = ProtoCore.DSASM.AddressType.Int;
                        opguide.opdata = System.Convert.ToInt64(nodeGuide.Value);
                        EmitPush(opguide);
                    }
                }
            }

            return isReplicationGuideEmitted;
        }
Пример #30
0
        protected override AssociativeNode GetFunctionApplication(NodeModel model, List<AssociativeNode> inputAstNodes)
        {
            AssociativeNode rhs;

            string function = Definition.Name;

            switch (Definition.Type)
            {
                case FunctionType.Constructor:
                case FunctionType.StaticMethod:
                    if (model.IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(model, functionNode, inputAstNodes);
                    }
                    else
                    {
                        model.AppendReplicationGuides(inputAstNodes);
                        rhs = AstFactory.BuildFunctionCall(
                            Definition.ClassName,
                            Definition.Name,
                            inputAstNodes);
                    }
                    break;

                case FunctionType.StaticProperty:

                    var staticProp = new IdentifierListNode
                    {
                        LeftNode = new IdentifierNode(Definition.ClassName),
                        RightNode = new IdentifierNode(Definition.Name)
                    };
                    rhs = staticProp;
                    break;

                case FunctionType.InstanceProperty:

                    // Only handle getter here. Setter could be handled in CBN.
                    if (model.IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(model, functionNode, inputAstNodes);
                    }
                    else
                    {
                        rhs = new NullNode();
                        if (inputAstNodes != null && inputAstNodes.Count >= 1)
                        {
                            var thisNode = inputAstNodes[0];
                            if (thisNode != null && !(thisNode is NullNode))
                            {
                                var insProp = new IdentifierListNode
                                {
                                    LeftNode = inputAstNodes[0],
                                    RightNode = new IdentifierNode(Definition.Name)
                                };
                                rhs = insProp;
                            }
                        }
                    }

                    break;

                case FunctionType.InstanceMethod:
                    if (model.IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierListNode
                        {
                            LeftNode = new IdentifierNode(Definition.ClassName),
                            RightNode = new IdentifierNode(Definition.Name)
                        };
                        rhs = CreateFunctionObject(model, functionNode, inputAstNodes);
                    }
                    else
                    {
                        rhs = new NullNode();
                        model.AppendReplicationGuides(inputAstNodes);

                        if (inputAstNodes != null && inputAstNodes.Count >= 1)
                        {
                            var thisNode = inputAstNodes[0];
                            inputAstNodes.RemoveAt(0); // remove this pointer

                            if (thisNode != null && !(thisNode is NullNode))
                            {
                                var memberFunc = new IdentifierListNode
                                {
                                    LeftNode = thisNode,
                                    RightNode =
                                        AstFactory.BuildFunctionCall(function, inputAstNodes)
                                };
                                rhs = memberFunc;
                            }
                        }
                    }

                    break;

                default:
                    if (model.IsPartiallyApplied)
                    {
                        var functionNode = new IdentifierNode(function);
                        rhs = CreateFunctionObject(model, functionNode, inputAstNodes);
                    }
                    else
                    {
                        model.AppendReplicationGuides(inputAstNodes);
                        rhs = AstFactory.BuildFunctionCall(function, inputAstNodes);
                    }
                    break;
            }

            return rhs;
        }
Пример #31
0
        private void BuildThisFunctionBody(ThisPointerProcOverload procOverload)
        {
            BinaryExpressionNode thisFunctionBody = new BinaryExpressionNode();
            IdentifierNode leftNode = new IdentifierNode();
            leftNode.Name = leftNode.Value = ProtoCore.DSDefinitions.Keyword.Return;
            thisFunctionBody.LeftNode = leftNode;

            thisFunctionBody.Optr = Operator.assign;


            // Build the function call and pass it the arguments including the this pointer
            FunctionCallNode fcall = new FunctionCallNode();
            IdentifierNode identNode = new IdentifierNode();
            identNode.Name = procOverload.procNode.Name;
            fcall.Function = identNode;

            // Set the arguments passed into the function excluding the 'this' argument
            List<AssociativeNode> args = new List<AssociativeNode>();
            for (int n = 1; n < procOverload.procNode.Signature.Arguments.Count; ++n)
            {
                VarDeclNode varDecl = procOverload.procNode.Signature.Arguments[n];
                args.Add(varDecl.NameNode);
            }
            fcall.FormalArguments = args;


            // Build the dotcall node
            procOverload.procNode.FunctionBody.Body = new List<AssociativeNode>();
            procOverload.procNode.FunctionBody.Body.Add(thisFunctionBody);

            thisFunctionBody.RightNode = CoreUtils.GenerateCallDotNode(procOverload.procNode.Signature.Arguments[0].NameNode, fcall, core);
        }
Пример #32
0
        private void EmitInlineConditionalNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone, ProtoCore.AST.AssociativeAST.BinaryExpressionNode parentNode = null)
        {
            if (subPass == AssociativeSubCompilePass.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 = compileStateTracker.DebugProps.breakOptions;
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint;
                compileStateTracker.DebugProps.breakOptions = newOptions;

                compileStateTracker.DebugProps.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
                    }
                };

                // True condition language block
                BinaryExpressionNode bExprTrue = new BinaryExpressionNode();
                bExprTrue.LeftNode = nodeBuilder.BuildReturn();
                bExprTrue.Optr = Operator.assign;
                bExprTrue.RightNode = inlineConditionalNode.TrueExpression;

                LanguageBlockNode langblockT = new LanguageBlockNode();
                int trueBlockId = ProtoCore.DSASM.Constants.kInvalidIndex;
                langblockT.codeblock.language = ProtoCore.Language.kAssociative;
                langblockT.codeblock.fingerprint = "";
                langblockT.codeblock.version = "";
                compileStateTracker.AssocNode = bExprTrue;
                EmitDynamicLanguageBlockNode(langblockT, bExprTrue, ref inferedType, ref trueBlockId, graphNode, AssociativeSubCompilePass.kNone);
                compileStateTracker.AssocNode = null;
                ProtoCore.AST.AssociativeAST.DynamicBlockNode dynBlockT = new ProtoCore.AST.AssociativeAST.DynamicBlockNode(trueBlockId);

                // False condition language block
                BinaryExpressionNode bExprFalse = new BinaryExpressionNode();
                bExprFalse.LeftNode = nodeBuilder.BuildReturn();
                bExprFalse.Optr = Operator.assign;
                bExprFalse.RightNode = inlineConditionalNode.FalseExpression;

                LanguageBlockNode langblockF = new LanguageBlockNode();
                int falseBlockId = ProtoCore.DSASM.Constants.kInvalidIndex;
                langblockF.codeblock.language = ProtoCore.Language.kAssociative;
                langblockF.codeblock.fingerprint = "";
                langblockF.codeblock.version = "";
                compileStateTracker.AssocNode = bExprFalse;
                EmitDynamicLanguageBlockNode(langblockF, bExprFalse, ref inferedType, ref falseBlockId, graphNode, AssociativeSubCompilePass.kNone);
                compileStateTracker.AssocNode = null;
                ProtoCore.AST.AssociativeAST.DynamicBlockNode dynBlockF = new ProtoCore.AST.AssociativeAST.DynamicBlockNode(falseBlockId);

                compileStateTracker.DebugProps.breakOptions = oldOptions;
                compileStateTracker.DebugProps.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
                    }
                };

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

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

                // Need to restore those settings.
                if (graphNode != null)
                {
                    graphNode.isInlineConditional = isInlineConditionalFlag;
                    graphNode.updateBlock.startpc = startPC;
                    graphNode.isReturn = isReturn;
                }
            }
        }
Пример #33
0
        private void EmitFunctionDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncBody == compilePass;
            bool parseMemberFunctionBody = ProtoCore.DSASM.Constants.kGlobalScope != globalClassIndex && ProtoCore.DSASM.AssociativeCompilePass.kClassMemFuncBody == compilePass;

            FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;
            bool hasReturnStatement = false;

            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;
            if (IsParsingGlobalFunctionSig() || IsParsingMemberFunctionSig())
            {
                Debug.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
                localProcedure.returntype.Name = funcDef.ReturnType.Name;
                localProcedure.returntype.UID = core.TypeSystem.GetType(funcDef.ReturnType.Name);
                if (localProcedure.returntype.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                    localProcedure.returntype.UID = (int)PrimitiveType.kTypeVar;
                localProcedure.returntype.Name = core.TypeSystem.GetType(localProcedure.returntype.UID);
                localProcedure.returntype.IsIndexable = funcDef.ReturnType.IsIndexable;
                localProcedure.returntype.rank = funcDef.ReturnType.rank;
                localProcedure.isConstructor = false;
                localProcedure.isStatic = funcDef.IsStatic;
                localProcedure.runtimeIndex = codeBlock.codeBlockId;
                localProcedure.access = funcDef.access;
                localProcedure.isExternal = funcDef.IsExternLib;
                localProcedure.isAutoGenerated = funcDef.IsAutoGenerated;
                localProcedure.classScope = globalClassIndex;
                localProcedure.isAssocOperator = funcDef.IsAssocOperator;

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

                if (IsParsingMemberFunctionSig() && !funcDef.IsExternLib)
                    CodeRangeTable.AddClassBlockFunctionEntry(globalClassIndex,
                        peekFunctionindex,
                        funcDef.FunctionBody.line,
                        funcDef.FunctionBody.col,
                        funcDef.FunctionBody.endLine,
                        funcDef.FunctionBody.endCol,
                        core.CurrentDSFileName);
                else if (!funcDef.IsExternLib)
                    CodeRangeTable.AddCodeBlockFunctionEntry(codeBlock.codeBlockId,
                        peekFunctionindex,
                        funcDef.FunctionBody.line,
                        funcDef.FunctionBody.col,
                        funcDef.FunctionBody.endLine,
                        funcDef.FunctionBody.endCol,
                        core.CurrentDSFileName);

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                if (null != funcDef.Singnature)
                {
                    int argNumber = 0;
                    foreach (VarDeclNode argNode in funcDef.Singnature.Arguments)
                    {
                        ++argNumber;

                        IdentifierNode paramNode = null;
                        bool aIsDefault = false;
                        ProtoCore.AST.Node aDefaultExpression = null;
                        if (argNode.NameNode is IdentifierNode)
                        {
                            paramNode = argNode.NameNode as IdentifierNode;
                        }
                        else if (argNode.NameNode is BinaryExpressionNode)
                        {
                            BinaryExpressionNode bNode = argNode.NameNode as BinaryExpressionNode;
                            paramNode = bNode.LeftNode as IdentifierNode;
                            aIsDefault = true;
                            aDefaultExpression = bNode;
                            //buildStatus.LogSemanticError("Defualt parameters are not supported");
                            //throw new BuildHaltException();
                        }
                        else
                        {
                            Debug.Assert(false, "Check generated AST");
                        }

                        ProtoCore.Type argType = new ProtoCore.Type();
                        argType.UID = core.TypeSystem.GetType(argNode.ArgumentType.Name);
                        if (argType.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                            argType.UID = (int)PrimitiveType.kTypeVar;
                        argType.Name = core.TypeSystem.GetType(argType.UID);
                        argType.IsIndexable = argNode.ArgumentType.IsIndexable;
                        argType.rank = argNode.ArgumentType.rank;
                        // We dont directly allocate arguments now
                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(paramNode.Value, argType));

                        localProcedure.argTypeList.Add(argType);
                        ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { isDefault = aIsDefault, defaultExpression = aDefaultExpression, Name = paramNode.Name };
                        localProcedure.argInfoList.Add(argInfo);
                    }
                }

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

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalProcIndex)
                {
                    Debug.Assert(peekFunctionindex == localProcedure.procId);

                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, globalProcIndex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException();
                        }
                    });

                    ExceptionRegistration registration = core.ExceptionHandlingManager.ExceptionTable.GetExceptionRegistration(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
                    if (registration == null)
                    {
                        registration = core.ExceptionHandlingManager.ExceptionTable.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
                        Debug.Assert(registration != null);
                    }
                }
            }
            else if (parseGlobalFunctionBody || parseMemberFunctionBody)
            {
                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Singnature)
                {
                    foreach (VarDeclNode argNode in funcDef.Singnature.Arguments)
                    {
                        int argType = core.TypeSystem.GetType(argNode.ArgumentType.Name);
                        bool isArray = argNode.ArgumentType.IsIndexable;
                        int rank = argNode.ArgumentType.rank;
                        argList.Add(core.TypeSystem.BuildTypeObject(argType, isArray, rank));
                    }
                }

                // Get the exisitng procedure that was added on the previous pass
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    globalProcIndex = codeBlock.procedureTable.IndexOfExact(funcDef.Name, argList);
                    localProcedure = codeBlock.procedureTable.procList[globalProcIndex];
                }
                else
                {
                    globalProcIndex = core.ClassTable.ClassNodes[globalClassIndex].vtable.IndexOfExact(funcDef.Name, argList);
                    localProcedure = core.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex];
                }

                Debug.Assert(null != localProcedure);

                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.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)
                {
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.argInfoList)
                    {
                        if (!argNode.isDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.defaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        IdentifierNode iNodeTemp = new IdentifierNode()
                        {
                            Value = ProtoCore.DSASM.Constants.kTempDefaultArg,
                            Name = ProtoCore.DSASM.Constants.kTempDefaultArg,
                            datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false)
                        };
                        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();
                        //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);
                    }

                    // Traverse definition
                    foreach (AssociativeNode bnode in funcDef.FunctionBody.Body)
                    {

                        //
                        // TODO Jun:    Handle stand alone language blocks
                        //              Integrate the subPass into a proper pass
                        //

                        ProtoCore.Type itype = new ProtoCore.Type();
                        itype.UID = (int)PrimitiveType.kTypeVar;

                        if (bnode is LanguageBlockNode)
                        {
                            // Build a binaryn node with a temporary lhs for every stand-alone language block
                            IdentifierNode iNode = new IdentifierNode()
                            {
                                Value = ProtoCore.DSASM.Constants.kTempLangBlock,
                                Name = ProtoCore.DSASM.Constants.kTempLangBlock,
                                datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false)
                            };
                            BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                            langBlockNode.LeftNode = iNode;
                            langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                            langBlockNode.RightNode = bnode;

                            //DfsTraverse(bnode, ref itype, false, null, ProtoCore.DSASM.AssociativeSubCompilePass.kNone);
                            DfsTraverse(langBlockNode, ref itype, false, null, subPass);
                        }
                        else
                        {
                            DfsTraverse(bnode, ref itype, false, null, subPass);
                        }

                        BinaryExpressionNode binaryNode = bnode as BinaryExpressionNode;
                        hasReturnStatement = hasReturnStatement || ((binaryNode != null) && (binaryNode.LeftNode.Name == ProtoCore.DSDefinitions.Kw.kw_return));
                    }

                    // 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.procId && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.localCount;
                            }
                        }
                    }
                    else
                    {
                        core.ClassTable.ClassNodes[globalClassIndex].vtable.procList[localProcedure.procId].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.procId && 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.procId;
                    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.procId;

                    // TODO Jun/Luke: Wrap this into Core.Options and extend if needed
                    /*bool isCSFFI = false;
                    if (isCSFFI)
                    {
                        ProtoCore.Lang.CSFFIActivationRecord record = new ProtoCore.Lang.CSFFIActivationRecord();
                        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.argTypeList;
                        fep = new ProtoCore.Lang.CSFFIFunctionEndPoint(record);
                    }
                    else
                    {*/
                        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.argTypeList;
                        fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                    //}
                }

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

                // TODO Jun: 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                // Determine whether this still needs to be aligned to the actual 'classIndex' variable
                // The factors that will affect this is whether the 2 function tables (compiler and callsite) need to be merged
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep);
            }

            core.ProcNode = localProcedure = null;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            core.BaseOffset = 0;
            argOffset = 0;
        }
Пример #34
0
        /*
            1 Copy user-defined function definitions (excluding constructors) into a temp

            2 Modify its signature to include an additional this pointer as the first argument.
              The 'this' argument should take the type of the current class being traversed and be the first argument in the function.
              The function name must be name mangled in order to stay unique

            3 Append this temp to the current vtable
        */
        private void InsertThisPointerArg(ThisPointerProcOverload procOverload)
        {
            // Modify its signature to include an additional this pointer as the first argument.
            // The 'this' argument should take the type of the current class being traversed and be the first argument in the function.
            // The function name must be name mangled in order to stay unique

            ProtoCore.AST.AssociativeAST.FunctionDefinitionNode procNode = procOverload.procNode;

            string className = compileStateTracker.ClassTable.ClassNodes[procOverload.classIndex].name;
            string thisPtrArgName = ProtoCore.DSASM.Constants.kThisPointerArgName;

            ProtoCore.AST.AssociativeAST.IdentifierNode ident = new ProtoCore.AST.AssociativeAST.IdentifierNode();
            ident.Name = ident.Value = thisPtrArgName;

            VarDeclNode thisPtrArg = new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access = ProtoCore.DSASM.AccessSpecifier.kPublic,
                NameNode = ident,
                ArgumentType = new ProtoCore.Type { Name = className, UID = procOverload.classIndex, IsIndexable = false, rank = 0 }
            };

            procNode.Singnature.Arguments.Insert(0, thisPtrArg);

            ProtoCore.Type type = new ProtoCore.Type();
        }
Пример #35
0
        protected FunctionCallNode EmitGetterSetterForIdent(IdentifierNode inode, bool isSetter = false)
        {
            if (isSetter)
            {
                FunctionCallNode setter = new FunctionCallNode();
                setter.Function = inode;

                IdentifierNode tmpArg = new IdentifierNode();
                tmpArg.Name = tmpArg.Value = ProtoCore.DSASM.Constants.kTempArg;
                tmpArg.datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false);
                setter.FormalArguments.Add(tmpArg);

                return setter;
            }
            else
            {
                FunctionCallNode getter = new FunctionCallNode();
                getter.Function = inode;
                return getter;
            }
        }
Пример #36
0
        private void SetPreviewVariable(IEnumerable<Node> parsedNodes)
        {
            previewVariable = null;
            if (parsedNodes == null || (!parsedNodes.Any()))
                return;

            IdentifierNode identifierNode = null;
            foreach (var statement in parsedNodes.Reverse().OfType<BinaryExpressionNode>())
            {
                identifierNode = statement.LeftNode as IdentifierNode;
                if (identifierNode != null) // Found the identifier...
                {
                    // ... that is not a temporary variable, take it!
                    if (!tempVariables.Contains(identifierNode.Value))
                        break;
                }
            }

            if (identifierNode == null)
                return;

            var duplicatedNode = new IdentifierNode(identifierNode);
            MapIdentifiers(duplicatedNode);

            // Of course, if we just needed "duplicatedNode.Value" we would not 
            // have to clone the original "IdentifierNode". In addition to 
            // renaming the variable, we also need to keep the array indexer 
            // (e.g. the "previewVariable" should be "arr[2][3]" instead of just
            // "arr") to obtain the correct value for that particular array 
            // element. The best way to keep these array indexers, naturally, is
            // to use "IdentifierNode.ToString" method, as in:
            // 
            //      previewVariable = duplicatedNode.ToString();
            // 
            // But the problem now is, "ILiveRunner.InspectNodeValue" method can 
            // only return a valid RuntimeMirror if "previewVariable" contains 
            // variable name (i.e. "arr") and nothing else (e.g. "arr[2][3]").
            // For now, simply set the "previewVariable" to just the array name,
            // instead of the full expression with array indexers.
            // 
            previewVariable = duplicatedNode.Value;
        }
        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);
        }
Пример #38
0
        /// <summary>
        /// Converts lhs ident lists to a function call
        /// a.x = 10 
        ///     -> t = a.%set_x(10)
        ///     
        /// a.x.y = b + c 
        ///     -> a.x.%set_y(b + c)
        ///     
        /// a.x[0] = 10
        ///     ->  tval = a.%get_x()
        ///         tval[0] = 10         
        ///         tmp = a.%set_x(tval)
        /// </summary>
        /// <param name="astList"></param>
        /// <returns></returns>
        private List<AssociativeNode> TransformLHSIdentList(List<AssociativeNode> astList)
        {
            List<AssociativeNode> newAstList = new List<AssociativeNode>();
            foreach (AssociativeNode node in astList)
            {
                BinaryExpressionNode bNode = node as BinaryExpressionNode;
                if (bNode == null)
                {
                    newAstList.Add(node);
                }
                else
                {
                    bool isLHSIdentList = bNode.LeftNode is IdentifierListNode;
                    if (!isLHSIdentList)
                    {
                        newAstList.Add(node);
                    }
                    else
                    {
                        IdentifierNode lhsTemp = new IdentifierNode(Constants.kTempVar);

                        IdentifierListNode identList = bNode.LeftNode as IdentifierListNode;
                        Validity.Assert(identList != null);

                        AssociativeNode argument = bNode.RightNode;

                        IdentifierNode identFunctionCall = identList.RightNode as IdentifierNode;
                        string setterName = ProtoCore.DSASM.Constants.kSetterPrefix + identList.RightNode.Name;
                        bool isArrayIndexed = identFunctionCall.ArrayDimensions != null;
                        if (isArrayIndexed)
                        {
                            // a.x[0] = 10
                            //      tval = a.%get_x()
                            string getterName = ProtoCore.DSASM.Constants.kGetterPrefix + identList.RightNode.Name;
                            ProtoCore.AST.AssociativeAST.FunctionCallNode fcall = new ProtoCore.AST.AssociativeAST.FunctionCallNode();
                            fcall.Function = new IdentifierNode(identList.RightNode.Name);
                            fcall.Function.Name = getterName;

                            IdentifierListNode identList1 = new IdentifierListNode();
                            identList1.LeftNode = identList.LeftNode;
                            identList1.RightNode = fcall;
                            BinaryExpressionNode bnodeGet = new BinaryExpressionNode(
                                lhsTemp,
                                identList1, 
                                Operator.assign
                                );
                            newAstList.Add(bnodeGet);

                            //      tval[0] = 10     
                            IdentifierNode lhsTempIndexed = new IdentifierNode(Constants.kTempVar);
                            lhsTempIndexed.ArrayDimensions = identFunctionCall.ArrayDimensions;
                            BinaryExpressionNode bnodeAssign = new BinaryExpressionNode(
                                lhsTempIndexed,
                                argument,
                                Operator.assign
                                );
                            newAstList.Add(bnodeAssign);

                            //      tmp = a.%set_x(tval)
                            ProtoCore.AST.AssociativeAST.FunctionCallNode fcallSet = new ProtoCore.AST.AssociativeAST.FunctionCallNode();
                            fcallSet.Function = identFunctionCall;
                            fcallSet.Function.Name = setterName;
                            List<AssociativeNode> args = new List<AssociativeNode>();
                            IdentifierNode lhsTempAssignBack = new IdentifierNode(Constants.kTempVar);
                            args.Add(lhsTempAssignBack);
                            fcallSet.FormalArguments = args;

                            IdentifierListNode identList2 = new IdentifierListNode();
                            identList2.LeftNode = identList.LeftNode;
                            identList2.RightNode = fcallSet;

                            IdentifierNode lhsTempAssign = new IdentifierNode(Constants.kTempPropertyVar);

                            BinaryExpressionNode bnodeSet = new BinaryExpressionNode(
                                lhsTempAssign,
                                identList2,
                                Operator.assign
                                );
                            newAstList.Add(bnodeSet);
                        }
                        else
                        {
                            List<AssociativeNode> args = new List<AssociativeNode>();
                            args.Add(argument);

                            ProtoCore.AST.AssociativeAST.FunctionCallNode fcall = new ProtoCore.AST.AssociativeAST.FunctionCallNode();
                            fcall.Function = identFunctionCall;
                            fcall.Function.Name = setterName;
                            fcall.FormalArguments = args;

                            identList.RightNode = fcall;
                            BinaryExpressionNode convertedAssignNode = new BinaryExpressionNode(lhsTemp, identList, Operator.assign);

                            NodeUtils.CopyNodeLocation(convertedAssignNode, bNode);
                            newAstList.Add(convertedAssignNode);
                        }
                    }
                }
            }
            return newAstList;
        }
Пример #39
0
        private static void ParseUserCodeCore(Core core, string expression, out List<AssociativeNode> astNodes, out List<AssociativeNode> commentNodes)
        {
            astNodes = new List<AssociativeNode>();

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

            ParseResult parseResult = ParserUtils.ParseWithCore(expression, core);

            commentNodes = ParserUtils.GetAstNodes(parseResult.CommentBlockNode);
            var nodes = ParserUtils.GetAstNodes(parseResult.CodeBlockNode);
            Validity.Assert(nodes != null);

            int index = 0;
            int typedIdentIndex = 0;
            foreach (var node in nodes)
            {
                var n = node as AssociativeNode;
                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 ModifierStackNode)
                {
                    core.BuildStatus.LogSemanticError(Resources.ModifierBlockNotSupported);
                }
                else if (n is ImportNode)
                {
                    core.BuildStatus.LogSemanticError(Resources.ImportStatementNotSupported);
                }
                else if (isFunctionOrClassDef)
                {
                    // Add node as it is
                    astNodes.Add(node);
                }
                else
                {
                    // Handle temporary naming for temporary Binary exp. nodes and non-assignment nodes
                    var ben = node as BinaryExpressionNode;
                    if (ben != null && ben.Optr == Operator.assign)
                    {
                        var mNode = ben.RightNode as ModifierStackNode;
                        if (mNode != null)
                        {
                            core.BuildStatus.LogSemanticError(Resources.ModifierBlockNotSupported);
                        }
                        var lNode = ben.LeftNode as IdentifierNode;
                        if (lNode != null && lNode.Value == Constants.kTempProcLeftVar)
                        {
                            string name = Constants.kTempVarForNonAssignment + index;
                            var newNode = new BinaryExpressionNode(new IdentifierNode(name), ben.RightNode);
                            astNodes.Add(newNode);
                            index++;
                        }
                        else
                        {
                            // Add node as it is
                            astNodes.Add(node);
                            index++;
                        }
                    }
                    else
                    {
                        if (node is TypedIdentifierNode)
                        {
                            // e.g. a : int = %tTypedIdent_<Index>;
                            var ident = new IdentifierNode(Constants.kTempVarForTypedIdentifier + typedIdentIndex);
                            NodeUtils.CopyNodeLocation(ident, node);
                            var typedNode = new BinaryExpressionNode(node as TypedIdentifierNode, ident, Operator.assign);
                            NodeUtils.CopyNodeLocation(typedNode, node);
                            astNodes.Add(typedNode);
                            typedIdentIndex++;
                        }
                        else
                        {
                            string name = Constants.kTempVarForNonAssignment + index;
                            var newNode = new BinaryExpressionNode(new IdentifierNode(name), n);
                            astNodes.Add(newNode);
                            index++;
                        }
                        
                    }
                }
            }
        }
Пример #40
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;
            }
        }
Пример #41
0
        public int Emit(CodeBlockNode codeblocknode)
        {
            bool isTopBlock = null == codeBlock.parent;
            if (!isTopBlock)
            {
                // If this is an inner block where there can be no classes, we can start at parsing at the global function state
                compilePass = ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncSig;
            }

            if (codeBlock.parent != null)
                CodeRangeTable.AddCodeBlockRangeEntry(codeBlock.codeBlockId,
                    codeblocknode.line,
                    codeblocknode.col,
                    codeblocknode.endLine,
                    codeblocknode.endCol,
                    core.CurrentDSFileName);
            else
                CodeRangeTable.AddCodeBlockRangeEntry(codeBlock.codeBlockId,
                    0, 0, int.MaxValue, int.MaxValue, core.CurrentDSFileName);

            ProtoCore.Type inferedType = new ProtoCore.Type();
            while (ProtoCore.DSASM.AssociativeCompilePass.kDone != compilePass)
            {
                foreach (AssociativeNode node in codeblocknode.Body)
                {
                    inferedType = new ProtoCore.Type();
                    inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                    inferedType.IsIndexable = false;

                    //
                    // TODO Jun:    Handle stand alone language blocks
                    //              Integrate the subPass into a proper pass
                    //
                    if (node is LanguageBlockNode)
                    {
                        // Build a binaryn node with a temporary lhs for every stand-alone language block
                        IdentifierNode iNode = new IdentifierNode()
                        {
                            Value = ProtoCore.DSASM.Constants.kTempLangBlock,
                            Name = ProtoCore.DSASM.Constants.kTempLangBlock,
                            datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false)
                        };
                        BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                        langBlockNode.LeftNode = iNode;
                        langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                        langBlockNode.RightNode = node;

                        DfsTraverse(langBlockNode, ref inferedType, false, null, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier);
                        //DfsTraverse(node, ref inferedType, false, null, ProtoCore.DSASM.AssociativeSubCompilePass.kNone);
                    }
                    else
                    {
                        DfsTraverse(node, ref inferedType, false, null, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier);
                    }
                }
                compilePass++;

                // We have compiled all classes
                if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && isTopBlock)
                {
                    EmitFunctionCallToInitStaticProperty(codeblocknode.Body);
                }
            }
            core.InferedType = inferedType;

            return codeBlock.codeBlockId;
        }
Пример #42
0
 public Variable(IdentifierNode identNode)
 {
     if (identNode == null)
         throw new ArgumentNullException();
     Name = identNode.Value;
     if (identNode.ArrayDimensions != null)
         ; //  Implement!
     Row = identNode.line;
     StartColumn = identNode.col;
 }
Пример #43
0
        private void EmitConstructorDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            ConstructorDefinitionNode funcDef = node as ConstructorDefinitionNode;
            ProtoCore.DSASM.CodeBlockType originalBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;

            if (IsParsingMemberFunctionSig())
            {
                Debug.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
                localProcedure.returntype.UID = core.TypeSystem.GetType(funcDef.ReturnType.Name);
                if (localProcedure.returntype.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                    localProcedure.returntype.UID = (int)PrimitiveType.kTypeVar;
                localProcedure.returntype.Name = core.TypeSystem.GetType(localProcedure.returntype.UID);
                localProcedure.returntype.IsIndexable = false;
                localProcedure.isConstructor = true;
                localProcedure.runtimeIndex = 0;

                Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex, "A constructor node must be associated with class");
                localProcedure.localCount = 0;

                int peekFunctionindex = core.ClassTable.ClassNodes[globalClassIndex].vtable.procList.Count;

                if (!funcDef.IsExternLib)
                    CodeRangeTable.AddClassBlockFunctionEntry(globalClassIndex,
                        peekFunctionindex,
                        funcDef.FunctionBody.line,
                        funcDef.FunctionBody.col,
                        funcDef.FunctionBody.endLine,
                        funcDef.FunctionBody.endCol,
                        core.CurrentDSFileName);

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                if (null != funcDef.Signature)
                {
                    int argNumber = 0;
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        ++argNumber;

                        IdentifierNode paramNode = null;
                        bool aIsDefault = false;
                        ProtoCore.AST.Node aDefaultExpression = null;
                        if (argNode.NameNode is IdentifierNode)
                        {
                            paramNode = argNode.NameNode as IdentifierNode;
                        }
                        else if (argNode.NameNode is BinaryExpressionNode)
                        {
                            BinaryExpressionNode bNode = argNode.NameNode as BinaryExpressionNode;
                            paramNode = bNode.LeftNode as IdentifierNode;
                            aIsDefault = true;
                            aDefaultExpression = bNode;
                            //buildStatus.LogSemanticError("Default parameters are not supported");
                            //throw new BuildHaltException();
                        }
                        else
                        {
                            Debug.Assert(false, "Check generated AST");
                        }

                        ProtoCore.Type argType = new ProtoCore.Type();
                        argType.UID = core.TypeSystem.GetType(argNode.ArgumentType.Name);
                        if (argType.UID == ProtoCore.DSASM.Constants.kInvalidIndex)
                            argType.UID = (int)PrimitiveType.kTypeVar;
                        argType.Name = core.TypeSystem.GetType(argType.UID);
                        argType.IsIndexable = argNode.ArgumentType.IsIndexable;
                        argType.rank = argNode.ArgumentType.rank;

                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(paramNode.Value, argType));
                        localProcedure.argTypeList.Add(argType);
                        ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { isDefault = aIsDefault, defaultExpression = aDefaultExpression, Name = paramNode.Name };
                        localProcedure.argInfoList.Add(argInfo);
                    }
                }

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

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != findex)
                {
                    Debug.Assert(peekFunctionindex == localProcedure.procId);
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, findex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException();
                        }
                    });
                }
            }
            else if (IsParsingMemberFunctionBody())
            {
                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        int argType = core.TypeSystem.GetType(argNode.ArgumentType.Name);
                        bool isArray = argNode.ArgumentType.IsIndexable;
                        int rank = argNode.ArgumentType.rank;
                        argList.Add(core.TypeSystem.BuildTypeObject(argType, isArray, rank));
                    }
                }

                globalProcIndex = core.ClassTable.ClassNodes[globalClassIndex].vtable.IndexOfExact(funcDef.Name, argList);

                Debug.Assert(null == localProcedure);
                localProcedure = core.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex];

                Debug.Assert(null != localProcedure);
                if (null == localProcedure)
                    return;

                if (-1 == localProcedure.classScope && (localProcedure.classScope != globalClassIndex))
                    localProcedure.classScope = globalClassIndex; // Assign class index if it's not done.

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    // Traverse default assignment for the class
                    foreach (BinaryExpressionNode bNode in core.ClassTable.ClassNodes[globalClassIndex].defaultArgExprList)
                    {
                        EmitBinaryExpressionNode(bNode, ref inferedType, false, null, subPass);
                        UpdateType(bNode.LeftNode.Name, ProtoCore.DSASM.Constants.kInvalidIndex, inferedType);
                    }

                    //Traverse default argument for the constructor
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.argInfoList)
                    {
                        if (!argNode.isDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.defaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        IdentifierNode iNodeTemp = new IdentifierNode()
                        {
                            Value = ProtoCore.DSASM.Constants.kTempDefaultArg,
                            Name = ProtoCore.DSASM.Constants.kTempDefaultArg,
                            datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false)
                        };
                        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();
                        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);
                    }

                    // Traverse definition
                    foreach (AssociativeNode bnode in funcDef.FunctionBody.Body)
                    {
                        inferedType.UID = (int)PrimitiveType.kTypeVoid;
                        inferedType.rank = 0;
                        DfsTraverse(bnode, ref inferedType, false, null, subPass);
                    }

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.localCount = core.BaseOffset;
                    core.ClassTable.ClassNodes[globalClassIndex].vtable.procList[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.procId;

                    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.argTypeList;
                    fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                }

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

                // TODO Jun: 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                // Determine whether this still needs to be aligned to the actual 'classIndex' variable
                // The factors that will affect this is whether the 2 function tables (compiler and callsite) need to be merged
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep);

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

            // 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;
        }
Пример #44
0
        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;
        }
Пример #45
0
        public override void TraverseFunctionCall(ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            FunctionCallNode funcCall = node as FunctionCallNode;
            string procName = funcCall.Function.Name;
            List<ProtoCore.Type> arglist = new List<ProtoCore.Type>();
            ProtoCore.Type dotCallType = new ProtoCore.Type();
            dotCallType.UID = (int)PrimitiveType.kTypeVar;
            dotCallType.IsIndexable = false;
            if (procName == "%dot")
            {
                if (funcCall.FormalArguments[0] is IdentifierNode)
                {
                    int ci = core.ClassTable.IndexOf((funcCall.FormalArguments[0] as IdentifierNode).Name);
                    if (ci != ProtoCore.DSASM.Constants.kInvalidIndex)
                    {
                        funcCall.FormalArguments[0] = new IntNode() { value = ci.ToString() };
                        dotCallType.UID = ci;
                    }

                    if (funcCall.FormalArguments.Count > 4)
                    {
                        int dynamicRhsIndex = int.Parse((funcCall.FormalArguments[1] as IntNode).value);
                        core.DynamicFunctionTable.functionTable[dynamicRhsIndex].classIndex = globalClassIndex;
                    }
                    else if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                    {
                        ProtoCore.DSASM.SymbolNode symbolnode = null;
                        bool isAccessible = false;
                        bool isAllocated = VerifyAllocation((funcCall.FormalArguments[0] as IdentifierNode).Name, globalClassIndex, out symbolnode, out isAccessible);
                        if (isAllocated && symbolnode.datatype.UID != (int)PrimitiveType.kTypeVar)
                        {
                            int rhsIndex = int.Parse((funcCall.FormalArguments[1] as IntNode).value);
                            string rhsName = core.DynamicVariableTable.variableTable[rhsIndex].variableName;
                            isAllocated = VerifyAllocation(rhsName, symbolnode.datatype.UID, out symbolnode, out isAccessible);
                            if (null == symbolnode)    //unbound identifier
                            {
                                if (isAllocated && !isAccessible)
                                {
                                    ProtoCore.Type leftType = new ProtoCore.Type();
                                    leftType.UID = (int)PrimitiveType.kInvalidType;
                                    leftType.IsIndexable = false;
                                    bool isFirstIdent = true;
                                    DfsEmitIdentList(funcCall.FormalArguments[0], null, globalClassIndex, ref leftType, ref depth, ref inferedType, false, ref isFirstIdent, graphNode, subPass);
                                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                                    return;
                                }
                            }
                        }
                    }
                }
                else if (funcCall.FormalArguments[0] is IntNode)
                {
                    dotCallType.UID = int.Parse((funcCall.FormalArguments[0] as IntNode).value);
                }
            }

            foreach (AssociativeNode paramNode in funcCall.FormalArguments)
            {
                ProtoCore.Type paramType = new ProtoCore.Type();
                paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                paramType.IsIndexable = false;

                //emitReplicationGuide = paramNode is IdentifierNode || paramNode is ExprListNode;

                // If it's a binary node then continue type check, otherwise disable type check and just take the type of paramNode itself
                // f(1+2.0) -> type check enabled - param is typed as double
                // f(2) -> type check disabled - param is typed as int
                enforceTypeCheck = !(paramNode is BinaryExpressionNode);

                DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                enforceTypeCheck = true;

                arglist.Add(paramType);
            }

            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            ProtoCore.DSASM.ProcedureNode procNode = null;
            int type = ProtoCore.DSASM.Constants.kInvalidIndex;
            bool isConstructor = false;
            bool isStatic = false;
            bool hasLogError = false;

            int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex;
            if (parentNode != null && parentNode is ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode)
                {
                    refClassIndex = core.ClassTable.IndexOf(leftnode.Name);
                }
            }

            // If lefttype is a valid class then check if calling a constructor
            if ((int)ProtoCore.PrimitiveType.kInvalidType != inferedType.UID && (int)ProtoCore.PrimitiveType.kTypeVoid != inferedType.UID)
            {
                bool isAccessible;
                int realType;
                if (inferedType.UID > (int)PrimitiveType.kMaxPrimitives)
                {
                    //check if it is function pointer
                    ProtoCore.DSASM.SymbolNode symbolnode = null;
                    bool isAllocated = VerifyAllocation(procName, inferedType.UID, out symbolnode, out isAccessible);
                    if (isAllocated)
                    {
                        procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                    }
                }
                if (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    procNode = core.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType);

                    if (procNode != null)
                    {
                        Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                        isConstructor = procNode.isConstructor;
                        isStatic = procNode.isStatic;
                        type = lefttype = realType;

                        if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor)
                        {
                            inferedType.UID = (int)PrimitiveType.kTypeNull;
                            return;
                        }

                        if (!isAccessible)
                        {
                            type = lefttype = realType;
                            procNode = null;
                            hasLogError = true;
                        }
                    }
                }
            }

            if (!isConstructor && !isStatic && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
            {
                //check if it is function pointer
                bool isAccessibleFp;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAllocated = VerifyAllocation(procName, globalClassIndex, out symbolnode, out isAccessibleFp);
                if (isAllocated) // not checking the type against function pointer, as the type could be var
                {
                    procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                }
                else
                {
                    procNode = core.GetFirstVisibleProcedure(procName, arglist, codeBlock);
                    if (null != procNode)
                    {
                        if ((int)ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                        {
                            // A global function
                            if (core.TypeSystem.IsHigherRank((int)procNode.returntype.UID, inferedType.UID))
                            {
                                inferedType = procNode.returntype;
                            }
                        }
                        else
                        {
                            procNode = null;
                        }
                    }
                    else
                    {
                        type = (lefttype != ProtoCore.DSASM.Constants.kInvalidIndex) ? lefttype : globalClassIndex;
                        if (type != ProtoCore.DSASM.Constants.kInvalidIndex)
                        {
                            int realType;
                            bool isAccessible;
                            ProtoCore.DSASM.ProcedureNode memProcNode = core.ClassTable.ClassNodes[type].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType);

                            if (memProcNode != null)
                            {
                                Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                                procNode = memProcNode;
                                inferedType = procNode.returntype;
                                type = realType;

                                if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor)
                                {
                                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                                    return;
                                }

                                if (!isAccessible)
                                {
                                    procNode = null;
                                    if (!hasLogError)
                                    {
                                        hasLogError = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            if (null != procNode)
            {
                //if call is replication call
                if (procNode.isThisCallReplication)
                {
                    inferedType.IsIndexable = true;
                    inferedType.rank++;
                }

                if ((int)ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                {
                    if (dotCallType.UID != (int)PrimitiveType.kTypeVar)
                    {
                        inferedType.UID = dotCallType.UID;
                    }
                }
            }
            else
            {
                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    // At compile time we only check if function name and the number of parameter are
                    // both matched, so if it is a global function call but we still can't get procNode,
                    // it is hopeless to resolve that at run-time. Then we should return null. -yu ke
                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                }
                else
                {
                    if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0)
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype);
                        core.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                        IdentifierNode iNode = new IdentifierNode()
                        {
                            Value = funcCall.Function.Name,
                            Name = funcCall.Function.Name,
                            datatype = core.TypeSystem.BuildTypeObject(PrimitiveType.kTypeVar, false)
                        };
                        EmitIdentifierNode(iNode, ref inferedType);
                    }
                    else
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype);
                        core.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                    }
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                }
            }
        }