예제 #1
0
 private void OutputOperatorInvoke(InvocationInfo ii, SyntaxNode node)
 {
     if (SymbolTable.Instance.IsCs2LuaSymbol(ii.MethodSymbol))
     {
         CodeBuilder.AppendFormat("{0}.", ii.ClassKey);
         string manglingName = NameMangling(ii.MethodSymbol);
         CodeBuilder.Append(manglingName);
         CodeBuilder.Append("(");
         OutputArgumentList(ii.Args, ii.DefaultValueArgs, ii.GenericTypeArgs, ii.ArrayToParams, false, node, ii.ArgConversions.ToArray());
         CodeBuilder.Append(")");
     }
     else
     {
         string method = ii.MethodSymbol.Name;
         string luaOp  = string.Empty;
         if (SymbolTable.ForSlua)
         {
             //slua导出时把重载操作符导出成lua实例方法了,然后利用lua实例上支持的操作符元方法在运行时绑定到重载实现
             //这里把lua支持的操作符方法转成lua操作(可能比invokeexternoperator要快一些)
             if (method == "op_Addition")
             {
                 luaOp = "+";
             }
             else if (method == "op_Subtraction")
             {
                 luaOp = "-";
             }
             else if (method == "op_Multiply")
             {
                 luaOp = "*";
             }
             else if (method == "op_Division")
             {
                 luaOp = "/";
             }
             else if (method == "op_UnaryNegation")
             {
                 luaOp = "-";
             }
             else if (method == "op_UnaryPlus")
             {
                 luaOp = "+";
             }
             else if (method == "op_LessThan")
             {
                 luaOp = "<";
             }
             else if (method == "op_GreaterThan")
             {
                 luaOp = ">";
             }
             else if (method == "op_LessThanOrEqual")
             {
                 luaOp = "<=";
             }
             else if (method == "op_GreaterThanOrEqual")
             {
                 luaOp = ">= ";
             }
         }
         if (string.IsNullOrEmpty(luaOp))
         {
             CodeBuilder.AppendFormat("invokeexternoperator({0}, ", ii.GenericClassKey);
             CodeBuilder.AppendFormat("\"{0}\"", method);
             CodeBuilder.Append(", ");
             OutputArgumentList(ii.Args, ii.DefaultValueArgs, ii.GenericTypeArgs, ii.ArrayToParams, false, node, ii.ArgConversions.ToArray());
             CodeBuilder.Append(")");
         }
         else
         {
             if (ii.Args.Count == 1)
             {
                 if (luaOp == "-")
                 {
                     CodeBuilder.Append("(");
                     CodeBuilder.Append(luaOp);
                     CodeBuilder.Append(" ");
                     OutputExpressionSyntax(ii.Args[0], ii.ArgConversions[0]);
                     CodeBuilder.Append(")");
                 }
             }
             else if (ii.Args.Count == 2)
             {
                 CodeBuilder.Append("(");
                 OutputExpressionSyntax(ii.Args[0], ii.ArgConversions[0]);
                 CodeBuilder.Append(" ");
                 CodeBuilder.Append(luaOp);
                 CodeBuilder.Append(" ");
                 OutputExpressionSyntax(ii.Args[1], ii.ArgConversions[1]);
                 CodeBuilder.Append(")");
             }
         }
     }
 }
예제 #2
0
        public override void VisitConditionalAccessExpression(ConditionalAccessExpressionSyntax node)
        {
            CodeBuilder.Append("condaccess(");
            VisitExpressionSyntax(node.Expression);
            CodeBuilder.Append(", ");
            var elementBinding = node.WhenNotNull as ElementBindingExpressionSyntax;

            if (null != elementBinding)
            {
                var oper    = m_Model.GetOperation(node.WhenNotNull);
                var symInfo = m_Model.GetSymbolInfo(node.WhenNotNull);
                var sym     = symInfo.Symbol;
                var psym    = sym as IPropertySymbol;
                if (null != sym && sym.IsStatic)
                {
                    var ci = m_ClassInfoStack.Peek();
                    AddReferenceAndTryDeriveGenericTypeInstance(ci, sym);
                }
                if (null != psym && psym.IsIndexer)
                {
                    CodeBuilder.Append("(function() return ");
                    CodeBuilder.AppendFormat("get{0}{1}indexer(", psym.ContainingAssembly == m_SymbolTable.AssemblySymbol ? string.Empty : "extern", psym.IsStatic ? "static" : "instance");
                    if (psym.IsStatic)
                    {
                        string fullName = ClassInfo.GetFullName(psym.ContainingType);
                        CodeBuilder.Append(fullName);
                    }
                    else
                    {
                        VisitExpressionSyntax(node.Expression);
                    }
                    CodeBuilder.Append(", ");
                    if (!psym.IsStatic)
                    {
                        string fnOfIntf = "nil";
                        CheckExplicitInterfaceAccess(psym.GetMethod, ref fnOfIntf);
                        CodeBuilder.AppendFormat("{0}, ", fnOfIntf);
                    }
                    string manglingName = NameMangling(psym.GetMethod);
                    CodeBuilder.AppendFormat("\"{0}\", ", manglingName);
                    InvocationInfo          ii   = new InvocationInfo();
                    List <ExpressionSyntax> args = new List <ExpressionSyntax> {
                        node.WhenNotNull
                    };
                    ii.Init(psym.GetMethod, args, m_Model);
                    OutputArgumentList(ii.Args, ii.DefaultValueArgs, ii.GenericTypeArgs, ii.ArrayToParams, false, elementBinding);
                    CodeBuilder.Append(")");
                    CodeBuilder.Append("; end)");
                }
                else if (oper.Kind == OperationKind.ArrayElementReferenceExpression)
                {
                    CodeBuilder.Append("(function() return ");
                    VisitExpressionSyntax(node.Expression);
                    CodeBuilder.Append("[");
                    VisitExpressionSyntax(node.WhenNotNull);
                    CodeBuilder.Append(" + 1]");
                    CodeBuilder.Append("; end)");
                }
                else if (null != sym)
                {
                    CodeBuilder.Append("(function() return ");
                    CodeBuilder.AppendFormat("get{0}{1}element(", sym.ContainingAssembly == m_SymbolTable.AssemblySymbol ? string.Empty : "extern", sym.IsStatic ? "static" : "instance");
                    if (sym.IsStatic)
                    {
                        string fullName = ClassInfo.GetFullName(sym.ContainingType);
                        CodeBuilder.Append(fullName);
                    }
                    else
                    {
                        VisitExpressionSyntax(node.Expression);
                    }
                    CodeBuilder.Append(", ");
                    CodeBuilder.AppendFormat("\"{0}\", ", sym.Name);
                    VisitExpressionSyntax(node.WhenNotNull);
                    CodeBuilder.Append(")");
                    CodeBuilder.Append("; end)");
                }
                else
                {
                    ReportIllegalSymbol(node, symInfo);
                }
            }
            else
            {
                CodeBuilder.Append("(function() return ");
                VisitExpressionSyntax(node.Expression);
                VisitExpressionSyntax(node.WhenNotNull);
                CodeBuilder.Append("; end)");
            }
            CodeBuilder.Append(")");
        }
예제 #3
0
        public override void VisitObjectCreationExpression(ObjectCreationExpressionSyntax node)
        {
            var ci           = m_ClassInfoStack.Peek();
            var oper         = m_Model.GetOperation(node);
            var objectCreate = oper as IObjectCreationExpression;

            if (null != objectCreate)
            {
                var typeSymInfo = objectCreate.Type;
                var sym         = objectCreate.Constructor;

                m_ObjectCreateStack.Push(typeSymInfo);

                string fullTypeName = ClassInfo.GetFullName(typeSymInfo);

                //处理ref/out参数
                InvocationInfo ii = new InvocationInfo();
                ii.Init(sym, node.ArgumentList, m_Model);
                AddReferenceAndTryDeriveGenericTypeInstance(ci, sym);

                bool isCollection = IsImplementationOfSys(typeSymInfo, "ICollection");
                bool isExternal   = typeSymInfo.ContainingAssembly != m_SymbolTable.AssemblySymbol;

                string ctor      = NameMangling(sym);
                string localName = string.Format("__compiler_newobject_{0}", node.GetLocation().GetLineSpan().StartLinePosition.Line);
                if (ii.ReturnArgs.Count > 0)
                {
                    CodeBuilder.Append("(function() ");
                    CodeBuilder.AppendFormat("local {0}; {1}", localName, localName);
                    CodeBuilder.Append(", ");
                    OutputExpressionList(ii.ReturnArgs);
                    CodeBuilder.Append(" = ");
                }
                if (isCollection)
                {
                    bool isDictionary = IsImplementationOfSys(typeSymInfo, "IDictionary");
                    bool isList       = IsImplementationOfSys(typeSymInfo, "IList");
                    if (isDictionary)
                    {
                        //字典对象的处理
                        CodeBuilder.AppendFormat("new{0}dictionary({1}, ", isExternal ? "extern" : string.Empty, fullTypeName);
                        if (isExternal)
                        {
                            CodeBuilder.AppendFormat("\"{0}\", ", fullTypeName);
                        }
                    }
                    else if (isList)
                    {
                        //列表对象的处理
                        CodeBuilder.AppendFormat("new{0}list({1}, ", isExternal ? "extern" : string.Empty, fullTypeName);
                        if (isExternal)
                        {
                            CodeBuilder.AppendFormat("\"{0}\", ", fullTypeName);
                        }
                    }
                    else
                    {
                        //集合对象的处理
                        CodeBuilder.AppendFormat("new{0}collection({1}, ", isExternal ? "extern" : string.Empty, fullTypeName);
                        if (isExternal)
                        {
                            CodeBuilder.AppendFormat("\"{0}\", ", fullTypeName);
                        }
                    }
                }
                else
                {
                    CodeBuilder.AppendFormat("new{0}object({1}, ", isExternal ? "extern" : string.Empty, fullTypeName);
                    if (isExternal)
                    {
                        CodeBuilder.AppendFormat("\"{0}\", ", fullTypeName);
                    }
                }
                if (string.IsNullOrEmpty(ctor))
                {
                    CodeBuilder.Append("nil");
                }
                else
                {
                    CodeBuilder.AppendFormat("\"{0}\"", ctor);
                }
                if (isExternal)
                {
                    ClassSymbolInfo csi;
                    if (m_SymbolTable.ClassSymbols.TryGetValue(fullTypeName, out csi))
                    {
                        if (csi.ExtensionClasses.Count > 0)
                        {
                            CodeBuilder.Append(", (function(obj)");
                            foreach (var pair in csi.ExtensionClasses)
                            {
                                string refname = pair.Key;
                                CodeBuilder.AppendFormat(" {0}.__install_{1}(obj);", fullTypeName, refname.Replace(".", "_"));
                            }
                            CodeBuilder.Append(" end)");
                        }
                        else
                        {
                            CodeBuilder.Append(", nil");
                        }
                    }
                    else
                    {
                        CodeBuilder.Append(", nil");
                    }
                }
                if (null != node.Initializer)
                {
                    CodeBuilder.Append(", ");
                    if (!isCollection)
                    {
                        CodeBuilder.Append("{");
                    }
                    VisitInitializerExpression(node.Initializer);
                    if (!isCollection)
                    {
                        CodeBuilder.Append("}");
                    }
                }
                else
                {
                    CodeBuilder.Append(", {}");
                }
                if (ii.Args.Count + ii.DefaultValueArgs.Count + ii.GenericTypeArgs.Count > 0)
                {
                    CodeBuilder.Append(", ");
                }
                OutputArgumentList(ii.Args, ii.DefaultValueArgs, ii.GenericTypeArgs, ii.ArrayToParams, false, node);
                CodeBuilder.Append(")");
                if (ii.ReturnArgs.Count > 0)
                {
                    CodeBuilder.Append("; ");
                    CodeBuilder.AppendFormat("return {0}; end)()", localName);
                }

                m_ObjectCreateStack.Pop();
            }
            else
            {
                var methodBinding = oper as IMethodBindingExpression;
                if (null != methodBinding)
                {
                    var typeSymInfo = methodBinding.Type;
                    var msym        = methodBinding.Method;
                    if (null != msym)
                    {
                        string manglingName = NameMangling(msym);
                        var    mi           = new MethodInfo();
                        mi.Init(msym, node);

                        CodeBuilder.Append("(function(");
                        string paramsString = string.Join(", ", mi.ParamNames.ToArray());
                        CodeBuilder.Append(paramsString);
                        CodeBuilder.Append(") ");
                        if (!msym.ReturnsVoid)
                        {
                            CodeBuilder.Append("return ");
                        }
                        if (msym.IsStatic)
                        {
                            AddReferenceAndTryDeriveGenericTypeInstance(ci, msym);

                            string className = ClassInfo.GetFullName(msym.ContainingType);
                            CodeBuilder.Append(className);
                            CodeBuilder.Append(".");
                        }
                        else
                        {
                            CodeBuilder.Append("this:");
                        }
                        CodeBuilder.Append(manglingName);
                        CodeBuilder.AppendFormat("({0}) end)", paramsString);
                    }
                    else
                    {
                        VisitArgumentList(node.ArgumentList);
                    }
                }
                else
                {
                    var typeParamObjCreate = oper as ITypeParameterObjectCreationExpression;
                    if (null != typeParamObjCreate)
                    {
                        CodeBuilder.Append("newtypeparamobject(");
                        OutputType(typeParamObjCreate.Type, node, ci, "new");
                        CodeBuilder.Append(")");
                    }
                    else
                    {
                        Log(node, "Unknown ObjectCreationExpressionSyntax !");
                    }
                }
            }
        }
예제 #4
0
        public override void VisitBinaryExpression(BinaryExpressionSyntax node)
        {
            var ci   = m_ClassInfoStack.Peek();
            var oper = m_Model.GetOperation(node) as IHasOperatorMethodExpression;

            if (null != oper && oper.UsesOperatorMethod)
            {
                IMethodSymbol msym     = oper.OperatorMethod;
                var           castOper = oper as IConversionExpression;
                if (null != castOper)
                {
                    InvocationInfo ii      = new InvocationInfo();
                    var            arglist = new List <ExpressionSyntax>()
                    {
                        node.Left
                    };
                    ii.Init(msym, arglist, m_Model);
                    OutputOperatorInvoke(ii, node);
                }
                else
                {
                    InvocationInfo ii      = new InvocationInfo();
                    var            arglist = new List <ExpressionSyntax>()
                    {
                        node.Left, node.Right
                    };
                    ii.Init(msym, arglist, m_Model);
                    OutputOperatorInvoke(ii, node);
                }
            }
            else
            {
                string op = node.OperatorToken.Text;
                ProcessBinaryOperator(node, ref op);
                string functor;
                if (s_BinaryFunctor.TryGetValue(op, out functor))
                {
                    CodeBuilder.AppendFormat("{0}(", functor);
                    VisitExpressionSyntax(node.Left);
                    CodeBuilder.Append(", ");
                    if (op == "as" || op == "is")
                    {
                        var typeInfo = m_Model.GetTypeInfo(node.Right);
                        var type     = typeInfo.Type;
                        OutputType(type, node, ci, op);
                    }
                    else if (op == "??")
                    {
                        var  rightOper    = m_Model.GetOperation(node.Right);
                        bool rightIsConst = null != rightOper && rightOper.ConstantValue.HasValue;
                        if (rightIsConst)
                        {
                            CodeBuilder.Append("true, ");
                            VisitExpressionSyntax(node.Right);
                        }
                        else
                        {
                            CodeBuilder.Append("false, (function() return ");
                            VisitExpressionSyntax(node.Right);
                            CodeBuilder.Append("; end)");
                        }
                    }
                    else
                    {
                        VisitExpressionSyntax(node.Right);
                    }
                    CodeBuilder.Append(")");
                }
                else if (op == "+")
                {
                    ProcessAddOrStringConcat(node.Left, node.Right);
                }
                else if (op == "==" || op == "~=")
                {
                    ProcessEqualOrNotEqual(op, node.Left, node.Right);
                }
                else
                {
                    CodeBuilder.Append("(");
                    VisitExpressionSyntax(node.Left);
                    CodeBuilder.AppendFormat(" {0} ", op);
                    VisitExpressionSyntax(node.Right);
                    CodeBuilder.Append(")");
                }
            }
        }