示例#1
0
 internal void ConvertArrayBase(ArgList args)
 {
     if (!Options.ArrayZero)
     {
         for (int i = 0; i < args.Args.Count; i++)
         {
             args.Args[i].Expr = BinaryExpr.Bound(args.Args[i].Expr, args.Args[i].Expr.Token, LiteralExpr.Bound(Constant.Create(1)), BinaryOperatorKind.Subtraction, Options.Binding);
             var expr = args.Args[i].Expr;
             Binder.Convert(ref expr, Compilation.Get(NativeType.Int32), BindOptions.Default);
             args.Args[i].Expr = expr;
         }
     }
 }
示例#2
0
        internal static MemberSymbol TryBindCall(Expr expr, Symbol symbol, ArgList args, out Expr self, ref OverloadResult ovRes, BindOptions options)
        {
            self = (expr as MemberAccessExpr)?.Expr;

            bool isStatic = self == null;

            if ((symbol as MethodSymbol)?.Method.IsStatic == isStatic || symbol is ConstructorSymbol)
            {
                CheckArguments(symbol as MemberSymbol, ((MethodBaseSymbol)symbol).Parameters, args, ref ovRes, options);
            }
            else if ((symbol as SymbolList)?.HasMethodBase == true)
            {
                var methods = symbol as SymbolList;
                for (int i = 0; i < methods.Symbols.Count; i++)
                {
                    var m = methods.Symbols[i];
                    if ((m as MethodSymbol)?.Method.IsStatic == isStatic || m is ConstructorSymbol)
                    {
                        CheckArguments(m as MemberSymbol, ((MethodBaseSymbol)m).Parameters, args, ref ovRes, options);
                        if (ovRes?.Exact == true)
                        {
                            break;
                        }
                    }
                }
            }

            if (ovRes?.Unique == true)
            {
                ApplyConversions(args, ovRes);
                return(ovRes.Symbol);
            }

            if (options.HasFlag(BindOptions.AllowDynamic) && expr != null && ovRes?.Valid != true)
            {
                if (symbol is DynamicExprSymbol symbolExpr)
                {
                    expr = self;
                    self = null;
                    Convert(ref expr, Compilation.Get(NativeType.Usual), options);
                    var obj       = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null)));
                    var name      = new Arg(symbolExpr.Name);
                    var arguments = new Arg(LiteralArray.Bound(args.Args));
                    args.Args.Clear();
                    args.Args.Add(obj);
                    args.Args.Add(name);
                    args.Args.Add(arguments);
                    return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend));
                }
                else if (symbol is DynamicSymbol symbolDynamic)
                {
                    expr = self;
                    self = null;
                    Convert(ref expr, Compilation.Get(NativeType.Usual), options);
                    var obj       = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null)));
                    var name      = new Arg(LiteralExpr.Bound(Constant.Create(symbolDynamic.Name)));
                    var arguments = new Arg(LiteralArray.Bound(args.Args));
                    args.Args.Clear();
                    args.Args.Add(obj);
                    args.Args.Add(name);
                    args.Args.Add(arguments);
                    return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend));
                }
                else if (symbol.Type()?.IsUsualOrObject() == true)
                {
                    self = null;
                    Convert(ref expr, Compilation.Get(NativeType.Usual), options);
                    var obj       = new Arg(expr);
                    var name      = new Arg(LiteralExpr.Bound(Constant.Create(SystemNames.DelegateInvokeName)));
                    var arguments = new Arg(LiteralArray.Bound(args.Args));
                    args.Args.Clear();
                    args.Args.Add(obj);
                    args.Args.Add(name);
                    args.Args.Add(arguments);
                    return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend));
                }
            }

            return(null);
        }
示例#3
0
        internal Constant CreateLiteral(LiteralExpr expr, string Value)
        {
            switch (expr.Kind)
            {
            case TokenType.TRUE_CONST:
                return(Constant.Create(true));

            case TokenType.FALSE_CONST:
                return(Constant.Create(false));

            case TokenType.CHAR_CONST:
                return(Constant.Create(Literals.CharValue(Value)));

            case TokenType.STRING_CONST:
                return(Constant.Create(Literals.StringValue(Value)));

            case TokenType.ESCAPED_STRING_CONST:
                return(Constant.Create(Literals.EscapedStringValue(Value)));

            case TokenType.INTERPOLATED_STRING_CONST:
                return(Constant.Create(Literals.StringValue(Value)));

            case TokenType.SYMBOL_CONST:
                return(Constant.CreateSymbol(Value.StartsWith("#") ? Value.Substring(1).ToUpperInvariant() : Value.ToUpperInvariant()));

            case TokenType.BINARY_CONST:
                return(Constant.CreateBinary(Literals.BinaryValue(Value)));

            case TokenType.HEX_CONST:
                switch (Value.Last())
                {
                case 'U':
                case 'u':
                    if (Value.Length > 8 + 3)
                    {
                        return(Constant.Create(unchecked ((ulong)Literals.HexValue(Value.Substring(2)))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((uint)Literals.HexValue(Value.Substring(2)))));
                    }

                case 'L':
                case 'l':
                    if (Value.Length > 8 + 3)
                    {
                        return(Constant.Create(Literals.HexValue(Value.Substring(2))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)Literals.HexValue(Value.Substring(2)))));
                    }

                default:
                {
                    long l = Literals.HexValue(Value.Substring(2));
                    if (l < 0)
                    {
                        return(Constant.Create(unchecked ((ulong)l)));
                    }
                    else if (l > uint.MaxValue)
                    {
                        return(Constant.Create(l));
                    }
                    else if (l > int.MaxValue)
                    {
                        return(Constant.Create(unchecked ((uint)l)));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)l)));
                    }
                }
                }

            case TokenType.BIN_CONST:
                switch (Value.Last())
                {
                case 'U':
                case 'u':
                    if (Value.Length > 32 + 3)
                    {
                        return(Constant.Create(unchecked ((ulong)Literals.BinValue(Value.Substring(2)))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((uint)Literals.BinValue(Value.Substring(2)))));
                    }

                case 'L':
                case 'l':
                    if (Value.Length > 32 + 3)
                    {
                        return(Constant.Create(Literals.BinValue(Value.Substring(2))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)Literals.BinValue(Value.Substring(2)))));
                    }

                default:
                {
                    long l = Literals.BinValue(Value.Substring(2));
                    if (l < 0)
                    {
                        return(Constant.Create(unchecked ((ulong)l)));
                    }
                    else if (l > uint.MaxValue)
                    {
                        return(Constant.Create(l));
                    }
                    else if (l > int.MaxValue)
                    {
                        return(Constant.Create(unchecked ((uint)l)));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)l)));
                    }
                }
                }

            case TokenType.REAL_CONST:
                char spec = Value.First() == '$' ? '$' : Value.Last();
                switch (spec)
                {
                case 'M':
                case 'm':
                    try
                    {
                        return(Constant.Create(decimal.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                case 'S':
                case 's':
                    try
                    {
                        return(Constant.Create(float.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                case 'D':
                case 'd':
                    try
                    {
                        return(Constant.Create(double.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                case '$':
                    try
                    {
                        return(Constant.CreateCurrency(decimal.Parse(Value.Substring(1, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                default:
                    try
                    {
                        if (Options.VOFloatConstants)
                        {
                            var args = Value.Split('.');
                            if (args.Length == 2)
                            {
                                int dec = 0;
                                while (args[1].Length > dec && Char.IsDigit(args[1][dec]))
                                {
                                    dec++;
                                }
                                return(Constant.Create(double.Parse(Value, System.Globalization.CultureInfo.InvariantCulture), 0, dec));
                            }
                            return(Constant.Create(double.Parse(Value, System.Globalization.CultureInfo.InvariantCulture)));
                        }
                        else
                        {
                            return(Constant.Create(double.Parse(Value, System.Globalization.CultureInfo.InvariantCulture)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }
                }

            case TokenType.INT_CONST:
                switch (Value.Last())
                {
                case 'U':
                case 'u':
                    try
                    {
                        ulong ul = ulong.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture);
                        if (ul > uint.MaxValue)
                        {
                            return(Constant.Create(ul));
                        }
                        else
                        {
                            return(Constant.Create(unchecked ((uint)ul)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralIntegerOverflow);
                    }

                case 'L':
                case 'l':
                    try
                    {
                        long l = long.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture);
                        if (l > int.MaxValue)
                        {
                            return(Constant.Create(l));
                        }
                        else
                        {
                            return(Constant.Create(unchecked ((int)l)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralIntegerOverflow);
                    }

                default:
                    try
                    {
                        ulong un = 0;
                        long  n  = 0;
                        if (Value.First() != '-')
                        {
                            un = ulong.Parse(Value, System.Globalization.CultureInfo.InvariantCulture);
                            if (un <= long.MaxValue)
                            {
                                n = unchecked ((long)un);
                            }
                        }
                        else
                        {
                            n = long.Parse(Value, System.Globalization.CultureInfo.InvariantCulture);
                        }
                        if (un > long.MaxValue)
                        {
                            return(Constant.Create(un));
                        }
                        else if (n > uint.MaxValue)
                        {
                            return(Constant.Create(n));
                        }
                        else if (n > int.MaxValue)
                        {
                            return(Constant.Create(unchecked ((uint)n)));
                        }
                        else
                        {
                            return(Constant.Create(unchecked ((int)n)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralIntegerOverflow);
                    }
                }

            case TokenType.NULL:
                return(Constant.Create((object)null));

            case TokenType.NIL:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Usual)));

            case TokenType.DATE_CONST:
            {
                var args = Value.Split('.');
                if (args.Length == 3)
                {
                    int year, month, day;
                    if (Int32.TryParse(args[0], out year) &&
                        Int32.TryParse(args[1], out month) &&
                        Int32.TryParse(args[2], out day))
                    {
                        if (year == 0 || month == 0 || day == 0)
                        {
                            return(Constant.CreateDefault(Compilation.Get(NativeType.VODate)));
                        }
                        if (Options.VODateConstants)
                        {
                            return(Constant.CreateVODate(year, month, day));
                        }
                        else
                        {
                            return(Constant.Create(new DateTime(year, month, day)));
                        }
                    }
                }
                throw new InternalError();
            }

            case TokenType.DATETIME_CONST:
            {
                // when we get here then the value is "{^.....}"
                Value = Value.Trim();
                if (Value.Length < 6)
                {
                    throw new InternalError();
                }
                Value = Value.Substring(2, Value.Length - 3).Trim();
                // replace possible duplicate spaces inside the string
                var  numbers = new int[6];
                int  current = 0;
                int  value   = 0;
                bool hasAmPm = false;
                bool isPm    = false;
                bool valid   = true;
                char last    = '\0';
                numbers[0] = numbers[1] = numbers[2] = numbers[3] = numbers[4] = numbers[5] = 0;
                foreach (var c in Value)
                {
                    switch (c)
                    {
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                    case '0':
                        if (hasAmPm)             // no numbers after Am or Pm
                        {
                            valid = false;
                        }
                        else
                        {
                            value            = value * 10 + (c - '0');
                            numbers[current] = value;
                        }
                        break;

                    case ':':
                    case '.':
                    case ' ':
                    case '-':
                        // separators
                        if (char.IsNumber(last))
                        {
                            // prevent duplicate spaces or other separators from confusing us
                            if (current < 5)
                            {
                                current += 1;
                                value    = 0;
                            }
                        }
                        break;

                    case 'a':
                    case 'A':
                    case 'p':
                    case 'P':
                        if (current == 5)
                        {
                            hasAmPm = true;
                            isPm    = (c == 'P' || c == 'p');
                        }
                        else
                        {
                            valid = false;
                        }
                        break;

                    case 'm':
                    case 'M':
                        if (!hasAmPm)
                        {
                            valid = false;
                        }
                        break;

                    default:
                        valid = false;
                        break;
                    }
                    last = c;
                    if (!valid)
                    {
                        throw new InternalError();
                    }
                }
                var year   = numbers[0];
                var month  = numbers[1];
                var day    = numbers[2];
                var hour   = numbers[3];
                var minute = numbers[4];
                var second = numbers[5];
                if (isPm)
                {
                    hour += 12;
                }
                return(Constant.CreateDateTime(year, month, day, hour, minute, second));
            }

            case TokenType.NULL_ARRAY:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Array)));

            case TokenType.NULL_CODEBLOCK:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Codeblock)));

            case TokenType.NULL_DATE:
                return(Constant.CreateDefault(Compilation.Get(NativeType.VODate)));

            case TokenType.NULL_OBJECT:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Object)));

            case TokenType.NULL_PSZ:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Psz)));

            case TokenType.NULL_PTR:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Ptr)));

            case TokenType.NULL_STRING:
                return(Constant.CreateDefault(Compilation.Get(NativeType.String)));

            case TokenType.NULL_SYMBOL:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Symbol)));

            default:
                throw new InternalError();
            }
        }
示例#4
0
        void ApplyConversions(ArgList args, OverloadResult ovRes, out Expr writeBack)
        {
            writeBack = null;
            var parameters = ovRes.Parameters.Parameters;

            for (int i = 0; i < ovRes.FixedArgs; i++)
            {
                var conv = ovRes.Conversions[i];
                var e    = args.Args[i].Expr;
                if (conv.Kind != ConversionKind.Identity)
                {
                    Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), conv);
                }
                if (conv is ConversionSymbolToConstant)
                {
                    Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), BindOptions.Default);
                }
                HandleArgWriteBack(conv, e, ref writeBack);
            }
            if (ovRes.MissingArgs > 0)
            {
                for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.MissingArgs; i++)
                {
                    var conv = ovRes.Conversions[i];
                    var a    = new Arg(LiteralExpr.Bound(((ConversionSymbolToConstant)conv).Constant));
                    Convert(ref a.Expr, FindType(parameters[i].ParameterType), BindOptions.Default);
                    args.Args.Add(a);
                }
            }
            else if (ovRes.Parameters.HasParamArray)
            {
                var  varArgs    = new List <Expr>(ovRes.VarArgs);
                var  varArgType = FindType(parameters[ovRes.FixedArgs].ParameterType.GetElementType());
                bool hasRefArgs = false;
                for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++)
                {
                    var conv = ovRes.Conversions[i];
                    var e    = args.Args[i].Expr;
                    Convert(ref e, varArgType, conv);
                    varArgs.Add(e);
                    if (args.Args[i].RefKind != RefKind.None)
                    {
                        hasRefArgs = true;
                    }
                }
                var varArg = new Arg(LiteralArray.Bound(varArgs, varArgType));
                if (hasRefArgs)
                {
                    var conv = ConversionSymbol.Create(ConversionSymbol.Create(ConversionKind.Identity), new ConversionToTemp(varArg.Expr.Datatype));
                    Convert(ref varArg.Expr, varArg.Expr.Datatype, conv);
                    for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++)
                    {
                        if (args.Args[i].RefKind != RefKind.None)
                        {
                            HandleVarArgWriteBack(conv, args.Args[i].Expr, i - ovRes.FixedArgs, ref writeBack);
                        }
                    }
                }
                while (args.Args.Count > ovRes.FixedArgs)
                {
                    args.Args.RemoveAt(args.Args.Count - 1);
                }
                args.Args.Add(varArg);
            }

            void HandleArgWriteBack(ConversionSymbol conv, Expr e, ref Expr wb)
            {
                if (conv.IsIndirectRefConversion())
                {
                    if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr)
                    {
                        // Handle writeBack
                        Expr t  = IdExpr.Bound(conv.IndirectRefConversionTempLocal());
                        var  wc = Conversion(t, e.Datatype, BindOptions.Default);
                        if (wc.Exists)
                        {
                            Convert(ref t, e.Datatype, wc);
                            SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default));
                        }
                    }
                }
            }

            void HandleVarArgWriteBack(ConversionSymbol conv, Expr e, int i, ref Expr wb)
            {
                if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr)
                {
                    // Handle writeBack
                    Expr t = IdExpr.Bound(conv.IndirectRefConversionTempLocal());
                    t = ArrayAccessExpr.Bound(t, ArgList.Bound(LiteralExpr.Bound(Constant.Create(i + 1))), this);
                    var wc = Conversion(t, e.Datatype, BindOptions.Default);
                    if (wc.Exists)
                    {
                        Convert(ref t, e.Datatype, wc);
                        SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default));
                    }
                }
            }
        }
示例#5
0
        internal MemberSymbol TryBindCall(Expr expr, Symbol symbol, ArgList args, out Expr self, out Expr writeBack, ref OverloadResult ovRes, BindOptions options)
        {
            self      = (expr as MemberAccessExpr)?.Expr;
            writeBack = null;

            bool isStatic = self == null;
            var  matching = new List <OverloadResult>();

            if ((symbol as MethodSymbol)?.Method.IsStatic == isStatic || symbol is ConstructorSymbol)
            {
                CheckArguments(symbol as MemberSymbol, ((MethodBaseSymbol)symbol).Parameters, args, ref ovRes, options);
            }
            else if ((symbol as SymbolList)?.HasMethodBase == true)
            {
                var methods = symbol as SymbolList;

                for (int i = 0; i < methods.Symbols.Count; i++)
                {
                    var m = methods.Symbols[i];
                    if ((m as MethodSymbol)?.Method.IsStatic == isStatic || m is ConstructorSymbol)
                    {
                        CheckArguments(m as MemberSymbol, ((MethodBaseSymbol)m).Parameters, args, ref ovRes, options);
                        if (ovRes?.Exact == true)
                        {
                            break;
                        }
                        if (ovRes != null)
                        {
                            if (!matching.Contains(ovRes))
                            {
                                matching.Add(ovRes);
                            }
                            if (ovRes.Equivalent != null && !matching.Contains(ovRes.Equivalent))
                            {
                                matching.Add(ovRes.Equivalent);
                            }
                        }
                    }
                }
            }

            if (ovRes?.Unique == true)
            {
                ApplyConversions(args, ovRes, out writeBack);
                return(ovRes.Symbol);
            }
            // Add automatic overload resolution
            if (ovRes != null && !ovRes.Unique && ovRes.Equivalent != null)
            {
                var ov1   = ovRes.Symbol;
                var ov2   = ovRes.Equivalent.Symbol;
                var func1 = ov1.DeclaringType.FullName;
                var func2 = ov2.DeclaringType.FullName;

                if (func1 != func2 && func1.StartsWith("XSharp") && func2.StartsWith("XSharp"))
                {
                    switch (func1)
                    {
                    case XSharpSpecialNames.XSharpVOFunctionsClass:
                    case XSharpSpecialNames.XSharpDataFunctionsClass:
                    case XSharpSpecialNames.XSharpVFPFunctionsClass:
                    case XSharpSpecialNames.XSharpXPPFunctionsClass:
                        // functions in specific runtime files override generic files
                        return(ovRes.Symbol);

                    case XSharpSpecialNames.XSharpRTFunctionsClass:
                        if (func2 == XSharpSpecialNames.XSharpCoreFunctionsClass)
                        {
                            // functions in specific runtime files override generic files
                            return(ovRes.Symbol);
                        }
                        break;
                    }
                    switch (func2)
                    {
                    case XSharpSpecialNames.XSharpVOFunctionsClass:
                    case XSharpSpecialNames.XSharpDataFunctionsClass:
                    case XSharpSpecialNames.XSharpVFPFunctionsClass:
                    case XSharpSpecialNames.XSharpXPPFunctionsClass:
                        // functions in specific runtime files override generic files
                        return(ovRes.Equivalent.Symbol);

                    case XSharpSpecialNames.XSharpRTFunctionsClass:
                        if (func1 == XSharpSpecialNames.XSharpCoreFunctionsClass)
                        {
                            // functions in specific runtime files override generic files
                            return(ovRes.Equivalent.Symbol);
                        }
                        break;
                    }
                }
            }
            if (matching.Count > 1 && ovRes.Valid && Options.Resolver != null)
            {
                var res = AskUserForCorrectOverload(matching, args);
                if (res != null)
                {
                    ovRes = res;
                    ApplyConversions(args, ovRes, out writeBack);
                    return(ovRes.Symbol);
                }
            }
            if (options.HasFlag(BindOptions.AllowDynamic) && expr != null && ovRes?.Valid != true)
            {
                if (symbol is DynamicExprSymbol symbolExpr)
                {
                    expr = self;
                    self = null;
                    Convert(ref expr, Compilation.Get(NativeType.Usual), options);
                    ApplyUsualConversions(args, out writeBack);
                    var obj       = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null)));
                    var name      = new Arg(symbolExpr.Name);
                    var arguments = ApplyUsualConversions(args, out writeBack);
                    args.Args.Clear();
                    args.Args.Add(obj);
                    args.Args.Add(name);
                    args.Args.Add(arguments);
                    // todo: Check for ref arguments and handle writeback from arguments array
                    return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend));
                }
                else if (symbol is DynamicSymbol symbolDynamic)
                {
                    expr = self;
                    self = null;
                    Convert(ref expr, Compilation.Get(NativeType.Usual), options);
                    var obj       = new Arg(expr ?? LiteralExpr.Bound(Constant.Create(null)));
                    var name      = new Arg(LiteralExpr.Bound(Constant.Create(symbolDynamic.Name)));
                    var arguments = ApplyUsualConversions(args, out writeBack);
                    args.Args.Clear();
                    args.Args.Add(obj);
                    args.Args.Add(name);
                    args.Args.Add(arguments);
                    // todo: Check for ref arguments and handle writeback from arguments array
                    return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend));
                }
                else if (symbol.Type()?.IsUsualOrObject() == true)
                {
                    self = null;
                    Convert(ref expr, Compilation.Get(NativeType.Usual), options);
                    ApplyUsualConversions(args, out writeBack);
                    var obj       = new Arg(expr);
                    var name      = new Arg(LiteralExpr.Bound(Constant.Create(SystemNames.DelegateInvokeName)));
                    var arguments = ApplyUsualConversions(args, out writeBack);
                    args.Args.Clear();
                    args.Args.Add(obj);
                    args.Args.Add(name);
                    args.Args.Add(arguments);
                    // todo: Check for ref arguments and handle writeback from arguments array
                    return(Compilation.Get(WellKnownMembers.XSharp_RT_Functions___InternalSend));
                }
            }

            return(null);
        }
示例#6
0
        internal static ConversionSymbol ArgumentConversion(Arg arg, ParameterInfo param, BindOptions options)
        {
            if (arg == null || arg.Expr is EmptyExpr)
            {
                var type = FindType(param.ParameterType);
                if (param.HasDefaultValue && type.NativeType != NativeType.Unknown)
                {
                    return(ConversionSymbol.Create(Constant.Create(param.DefaultValue, type.NativeType)));
                }
                else if (param.HasDefaultValue || param.IsOptional)
                {
                    return(ConversionSymbol.Create(Constant.CreateDefault(type)));
                }
                else
                {
                    var defValAttr = Compilation.Get(WellKnownTypes.DefaultParameterValueAttribute);
                    foreach (var attr in param.CustomAttributes)
                    {
                        if (attr.AttributeType == defValAttr.Type)
                        {
                            int desc = attr.ConstructorArguments[1].Value as int? ?? -1;

                            var val = attr.ConstructorArguments[0];
                            switch (desc)
                            {
                            case 0:
                                // normal .Net Object
                                // return value  or null
                                if (val.ArgumentType != null && val.Value != null)
                                {
                                    var valType = FindType(val.ArgumentType);
                                    if (valType.NativeType == NativeType.Unknown)
                                    {
                                        // Enum type? can be casted to Int32
                                        return(ConversionSymbol.Create(Constant.Create(val.Value, NativeType.Int32)));
                                    }
                                    else
                                    {
                                        return(ConversionSymbol.Create(Constant.Create(val.Value, valType.NativeType)));
                                    }
                                }
                                else
                                {
                                    return(ConversionSymbol.Create(Constant.Null));
                                }

                            case 1:
                                // NIL
                                return(ConversionSymbol.Create(Constant.Nil));

                            case 2:
                                // Date, value should be long of ticks. Return DateTime
                                DateTime dt = new DateTime((long)val.Value);
                                return(ConversionSymbol.Create(Constant.Create(dt)));

                            case 3:
                                // Symbol, value should be a string literal or null
                                if (val.Value == null)
                                {
                                    return(ConversionSymbol.Create(Constant.Null));
                                }
                                else
                                {
                                    return(ConversionSymbol.Create(Constant.Create((string)val.Value)));
                                }

                            case 4:
                                // Psz, value should be a string or null
                                if (val.Value == null)
                                {
                                    return(ConversionSymbol.Create(Constant.Null));
                                }
                                else
                                {
                                    return(ConversionSymbol.Create(Constant.Create((string)val.Value)));
                                }

                            case 5:
                                // IntPtr, return value as IntPtr
                                if (val.Value == null)
                                {
                                    return(ConversionSymbol.Create(Constant.Null));
                                }
                                else
                                {
                                    int    i = val.Value as int? ?? 0;
                                    IntPtr p = new IntPtr(i);
                                    return(ConversionSymbol.Create(Constant.Create(p)));
                                }

                            default:
                                return(ConversionSymbol.Create(Constant.Null));
                            }
                        }
                    }
                }
                return(ConversionSymbol.Create(ConversionKind.NoConversion));
            }
            if (arg.RefKind == RefKind.Ref && !param.ParameterType.IsByRef)
            {
                return(ConversionSymbol.Create(ConversionKind.NoConversion));
            }
            if (arg.RefKind == RefKind.Out && !param.ParameterType.IsByRef)
            {
                return(ConversionSymbol.Create(ConversionKind.NoConversion));
            }
            var conv = Conversion(arg.Expr, FindType(param.ParameterType), options);

            return(conv);
        }
示例#7
0
 internal void ConvertArrayBase(ArgList args)
 {
     if (!Options.ArrayZero)
     {
         for (int i = 0; i < args.Args.Count; i++)
         {
             args.Args[i].Expr = BinaryExpr.Bound(args.Args[i].Expr, args.Args[i].Expr.Token, LiteralExpr.Bound(Constant.Create(1)), BinaryOperatorKind.Subtraction, false, Options.Binding);
         }
     }
 }
示例#8
0
        internal Constant CreateLiteral(LiteralExpr expr, string Value)
        {
            switch (expr.Kind)
            {
            case TokenType.TRUE_CONST:
                return(Constant.Create(true));

            case TokenType.FALSE_CONST:
                return(Constant.Create(false));

            case TokenType.CHAR_CONST:
                return(Constant.Create(Literals.CharValue(Value)));

            case TokenType.STRING_CONST:
                return(Constant.Create(Literals.StringValue(Value)));

            case TokenType.ESCAPED_STRING_CONST:
                return(Constant.Create(Literals.EscapedStringValue(Value)));

            case TokenType.INTERPOLATED_STRING_CONST:
                return(Constant.Create(Literals.StringValue(Value)));

            case TokenType.SYMBOL_CONST:
                return(Constant.CreateSymbol(Value.StartsWith("#") ? Value.Substring(1).ToUpperInvariant() : Value.ToUpperInvariant()));

            case TokenType.HEX_CONST:
                switch (Value.Last())
                {
                case 'U':
                case 'u':
                    if (Value.Length > 8 + 3)
                    {
                        return(Constant.Create(unchecked ((ulong)Literals.HexValue(Value.Substring(2)))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((uint)Literals.HexValue(Value.Substring(2)))));
                    }

                case 'L':
                case 'l':
                    if (Value.Length > 8 + 3)
                    {
                        return(Constant.Create(Literals.HexValue(Value.Substring(2))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)Literals.HexValue(Value.Substring(2)))));
                    }

                default:
                {
                    long l = Literals.HexValue(Value.Substring(2));
                    if (l < 0)
                    {
                        return(Constant.Create(unchecked ((ulong)l)));
                    }
                    else if (l > uint.MaxValue)
                    {
                        return(Constant.Create(l));
                    }
                    else if (l > int.MaxValue)
                    {
                        return(Constant.Create(unchecked ((uint)l)));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)l)));
                    }
                }
                }

            case TokenType.BIN_CONST:
                switch (Value.Last())
                {
                case 'U':
                case 'u':
                    if (Value.Length > 32 + 3)
                    {
                        return(Constant.Create(unchecked ((ulong)Literals.BinValue(Value.Substring(2)))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((uint)Literals.BinValue(Value.Substring(2)))));
                    }

                case 'L':
                case 'l':
                    if (Value.Length > 32 + 3)
                    {
                        return(Constant.Create(Literals.BinValue(Value.Substring(2))));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)Literals.BinValue(Value.Substring(2)))));
                    }

                default:
                {
                    long l = Literals.BinValue(Value.Substring(2));
                    if (l < 0)
                    {
                        return(Constant.Create(unchecked ((ulong)l)));
                    }
                    else if (l > uint.MaxValue)
                    {
                        return(Constant.Create(l));
                    }
                    else if (l > int.MaxValue)
                    {
                        return(Constant.Create(unchecked ((uint)l)));
                    }
                    else
                    {
                        return(Constant.Create(unchecked ((int)l)));
                    }
                }
                }

            case TokenType.REAL_CONST:
                switch (Value.Last())
                {
                case 'M':
                case 'm':
                    try
                    {
                        return(Constant.Create(decimal.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                case 'S':
                case 's':
                    try
                    {
                        return(Constant.Create(float.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                case 'D':
                case 'd':
                    try
                    {
                        return(Constant.Create(double.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture)));
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }

                default:
                    try
                    {
                        if (Options.VOFloatConstants)
                        {
                            var args = Value.Split('.');
                            if (args.Length == 2)
                            {
                                int dec = 0;
                                while (args[1].Length > dec && Char.IsDigit(args[1][dec]))
                                {
                                    dec++;
                                }
                                return(Constant.Create(double.Parse(Value, System.Globalization.CultureInfo.InvariantCulture), 0, dec));
                            }
                            return(Constant.Create(double.Parse(Value, System.Globalization.CultureInfo.InvariantCulture)));
                        }
                        else
                        {
                            return(Constant.Create(double.Parse(Value, System.Globalization.CultureInfo.InvariantCulture)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralFloatOverflow);
                    }
                }

            case TokenType.INT_CONST:
                switch (Value.Last())
                {
                case 'U':
                case 'u':
                    try
                    {
                        ulong ul = ulong.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture);
                        if (ul > uint.MaxValue)
                        {
                            return(Constant.Create(ul));
                        }
                        else
                        {
                            return(Constant.Create(unchecked ((uint)ul)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralIntegerOverflow);
                    }

                case 'L':
                case 'l':
                    try
                    {
                        long l = long.Parse(Value.Substring(0, Value.Length - 1), System.Globalization.CultureInfo.InvariantCulture);
                        if (l > int.MaxValue)
                        {
                            return(Constant.Create(l));
                        }
                        else
                        {
                            return(Constant.Create(unchecked ((int)l)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralIntegerOverflow);
                    }

                default:
                    try
                    {
                        ulong un = 0;
                        long  n  = 0;
                        if (Value.First() != '-')
                        {
                            un = ulong.Parse(Value, System.Globalization.CultureInfo.InvariantCulture);
                            if (un <= long.MaxValue)
                            {
                                n = unchecked ((long)un);
                            }
                        }
                        else
                        {
                            n = long.Parse(Value, System.Globalization.CultureInfo.InvariantCulture);
                        }
                        if (un > long.MaxValue)
                        {
                            return(Constant.Create(un));
                        }
                        else if (n > uint.MaxValue)
                        {
                            return(Constant.Create(n));
                        }
                        else if (n > int.MaxValue)
                        {
                            return(Constant.Create(unchecked ((uint)n)));
                        }
                        else
                        {
                            return(Constant.Create(unchecked ((int)n)));
                        }
                    }
                    catch (OverflowException)
                    {
                        throw expr.Error(ErrorCode.LiteralIntegerOverflow);
                    }
                }

            case TokenType.NULL:
                return(Constant.Create((object)null));

            case TokenType.NIL:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Usual)));

            case TokenType.DATE_CONST:
            {
                var args = Value.Split('.');
                if (args.Length == 3)
                {
                    int year, month, day;
                    if (Int32.TryParse(args[0], out year) &&
                        Int32.TryParse(args[1], out month) &&
                        Int32.TryParse(args[2], out day))
                    {
                        if (Options.VODateConstants)
                        {
                            return(Constant.CreateVODate(year, month, day));
                        }
                        else
                        {
                            return(Constant.Create(new DateTime(year, month, day)));
                        }
                    }
                }
                throw new InternalError();
            }

            case TokenType.NULL_ARRAY:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Array)));

            case TokenType.NULL_CODEBLOCK:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Codeblock)));

            case TokenType.NULL_DATE:
                return(Constant.CreateDefault(Compilation.Get(NativeType.VODate)));

            case TokenType.NULL_OBJECT:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Object)));

            case TokenType.NULL_PSZ:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Psz)));

            case TokenType.NULL_PTR:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Ptr)));

            case TokenType.NULL_STRING:
                return(Constant.CreateDefault(Compilation.Get(NativeType.String)));

            case TokenType.NULL_SYMBOL:
                return(Constant.CreateDefault(Compilation.Get(NativeType.Symbol)));

            default:
                throw new InternalError();
            }
        }