protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e) {
     if (e.Call.CallMethod != null) {
         var ctx = e.Ctx;
         var mDef = e.Call.CallMethod.Resolve();
         if (mDef.IsSetter) {
             var tRef = e.Call.CallMethod.Parameters.Last().ParameterType;
             var tDef = tRef.Resolve();
             var attr = tDef.GetCustomAttribute<JsStringEnumAttribute>();
             if (attr != null) {
                 var prop = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type = new ExprJsTypeVarName(ctx, tRef).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var value = e.Call.Args.Last().Named("value");
                 var js =  "prop = type.enumStringMap[value]";
                 var expr = new ExprJsExplicit(ctx, js, e.Type, type, enumStringMap, value, prop);
                 return expr;
             }
         } else {
             var tDef = e.Type.Resolve();
             var attr = tDef.GetCustomAttribute<JsStringEnumAttribute>();
             if (attr != null) {
                 var prop = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type = new ExprJsTypeVarName(ctx, e.Type).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var js = "type.enumStringMap[prop]";
                 var expr = new ExprJsExplicit(ctx, js, e.Type, prop, type, enumStringMap);
                 return expr;
             }
         }
     }
     return base.VisitJsResolvedProperty(e);
 }
        protected override ICode VisitBox(ExprBox e)
        {
            var ctx  = e.Ctx;
            var expr = (Expr)this.Visit(e.Expr);

            if (e.Type.IsUnsignedInteger() && expr.Type.IsSignedInteger())
            {
                expr = new ExprConv(ctx, expr, e.Type, false);
            }
            if (!e.Type.IsValueType)
            {
                // For ref-types 'box' does nothing
                return(this.Visit(e.Expr));
            }
            var eType = new ExprJsTypeVarName(ctx, e.Type);

            if (e.Type.IsNullable())
            {
                var exprIsVar    = expr.IsVar();
                var innerType    = e.Type.GetNullableInnerType();
                var temp         = exprIsVar ? null : new ExprVarLocal(ctx, e.Type);
                var box          = new ExprBox(ctx, temp ?? expr, innerType).Named("box");
                var nullableJs   = exprIsVar ? "(expr !== null ? box : null)" : "((temp = expr) !== null ? box : null)";
                var nullableExpr = new ExprJsExplicit(ctx, nullableJs, innerType, temp.Named("temp"), expr.Named("expr"), box);
                return(nullableExpr);
            }
            else
            {
                var deepCopyExpr = InternalFunctions.ValueTypeDeepCopyIfRequired(e.Type, () => (Expr)this.Visit(expr));
                var int2bool     = e.Type.IsBoolean() && expr.Type.IsInteger() ? "!!" : "";
                var js           = "{v:" + int2bool + "expr,_:type}";
                var ret          = new ExprJsExplicit(ctx, js, e.Type, (deepCopyExpr ?? expr).Named("expr"), eType.Named("type"));
                return(ret);
            }
        }
        protected override ICode VisitConv(ExprConv e)
        {
            var fromType = e.Expr.Type;
            var toType   = e.Type;

            var fromTypeMetadataType = fromType.MetadataType;
            var toTypeMetadataType   = toType.MetadataType;

            if (e.ForceFromUnsigned)
            {
                switch (fromTypeMetadataType)
                {
                case MetadataType.SByte: fromTypeMetadataType = MetadataType.Byte; break;

                case MetadataType.Int16: fromTypeMetadataType = MetadataType.UInt16; break;

                case MetadataType.Int32: fromTypeMetadataType = MetadataType.UInt32; break;

                case MetadataType.Int64: fromTypeMetadataType = MetadataType.UInt64; break;

                case MetadataType.IntPtr: fromTypeMetadataType = MetadataType.UIntPtr; break;
                }
            }
            if (fromTypeMetadataType == MetadataType.Char)
            {
                fromTypeMetadataType = MetadataType.UInt16;
            }
            if (toTypeMetadataType == MetadataType.Char)
            {
                toTypeMetadataType = MetadataType.UInt16;
            }

            var fromIdx = indexMap.ValueOrDefault(fromTypeMetadataType, -1);
            var toIdx   = indexMap.ValueOrDefault(toTypeMetadataType, -1);

            if (fromIdx == -1 || toIdx == -1)
            {
                return(e.Expr);
            }

            var ctx = e.Ctx;
            var js  = jss[fromIdx, toIdx];

            if (js != null)
            {
                // In-place conversion
                var expr = new ExprJsExplicit(ctx, js, e.Type, e.Expr.Named("e"));
                return(expr);
            }
            else
            {
                // Call conversion function
                var convMi   = ((Func <int, int>)InternalFunctions.Conv <int, int>).Method.GetGenericMethodDefinition();
                var mConv    = ctx.Module.Import(convMi).MakeGeneric(e.Expr.Type, e.Type);
                var convCall = new ExprCall(ctx, mConv, null, e.Expr);
                return(convCall);
            }
        }
        protected override ICode VisitReturn(StmtReturn s)
        {
            var ctx  = s.Ctx;
            var expr = (Expr)this.Visit(s.Expr);

            if (expr != null && expr.Type.IsInteger() && ctx.MRef.ReturnType.FullResolve(ctx).IsBoolean())
            {
                expr = new ExprJsExplicit(ctx, "!!expr", ctx.Boolean, expr.Named("expr"));
            }
            if (expr != s.Expr)
            {
                return(new StmtReturn(ctx, expr));
            }
            else
            {
                return(s);
            }
        }
        protected virtual ICode VisitJsExplicit(ExprJsExplicit e)
        {
            this.ThrowOnNoOverride();
            var namedExprs = this.HandleList(e.NamedExprs, x => {
                if (x == null)
                {
                    return(null);
                }
                var expr = (Expr)this.Visit(x.Expr);
                return(expr == x.Expr ? x : expr.Named(x.Name));
            });

            if (namedExprs != null)
            {
                return(new ExprJsExplicit(e.Ctx, e.JavaScript, e.Type, namedExprs));
            }
            else
            {
                return(e);
            }
        }
Exemple #6
0
 protected override ICode VisitJsResolvedProperty(ExprJsResolvedProperty e)
 {
     if (e.Call.CallMethod != null)
     {
         var ctx  = e.Ctx;
         var mDef = e.Call.CallMethod.Resolve();
         if (mDef.IsSetter)
         {
             var tRef = e.Call.CallMethod.Parameters.Last().ParameterType;
             var tDef = tRef.Resolve();
             var attr = tDef.GetCustomAttribute <JsStringEnumAttribute>();
             if (attr != null)
             {
                 var prop          = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type          = new ExprJsTypeVarName(ctx, tRef).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var value         = e.Call.Args.Last().Named("value");
                 var js            = "prop = type.enumStringMap[value]";
                 var expr          = new ExprJsExplicit(ctx, js, e.Type, type, enumStringMap, value, prop);
                 return(expr);
             }
         }
         else
         {
             var tDef = e.Type.Resolve();
             var attr = tDef.GetCustomAttribute <JsStringEnumAttribute>();
             if (attr != null)
             {
                 var prop          = new ExprJsResolvedProperty(ctx, new FakeCall(e.Call), e.PropertyName).Named("prop");
                 var type          = new ExprJsTypeVarName(ctx, e.Type).Named("type");
                 var enumStringMap = new ExprJsTypeData(ctx, TypeData.EnumStringMap).Named("enumStringMap");
                 var js            = "type.enumStringMap[prop]";
                 var expr          = new ExprJsExplicit(ctx, js, e.Type, prop, type, enumStringMap);
                 return(expr);
             }
         }
     }
     return(base.VisitJsResolvedProperty(e));
 }
        protected override ICode VisitAssignment(ExprAssignment e)
        {
            var ctx    = e.Ctx;
            var expr   = (Expr)this.Visit(e.Expr);
            var target = (ExprVar)this.Visit(e.Target);

            if (target.Type.IsBoolean() && expr.Type.IsInteger())
            {
                expr = new ExprJsExplicit(ctx, "!!expr", ctx.Boolean, expr.Named("expr"));
            }
            else if (target.Type.IsUnsignedInteger() && expr.Type.IsSignedInteger())
            {
                expr = new ExprConv(ctx, expr, expr.Type.UnsignedEquivilent(ctx.TypeSystem), false);
            }
            if (expr != e.Expr || target != e.Target)
            {
                return(new ExprAssignment(ctx, target, expr));
            }
            else
            {
                return(e);
            }
        }
 protected virtual ICode VisitJsExplicit(ExprJsExplicit e) {
     this.ThrowOnNoOverride();
     var namedExprs = this.HandleList(e.NamedExprs, x => {
         if (x == null) {
             return null;
         }
         var expr = (Expr)this.Visit(x.Expr);
         return expr == x.Expr ? x : expr.Named(x.Name);
     });
     if (namedExprs != null) {
         return new ExprJsExplicit(e.Ctx, e.JavaScript, e.Type, namedExprs);
     } else {
         return e;
     }
 }
 protected override ICode VisitReturn(StmtReturn s) {
     var ctx = s.Ctx;
     var expr = (Expr)this.Visit(s.Expr);
     if (expr != null && expr.Type.IsInteger() && ctx.MRef.ReturnType.FullResolve(ctx).IsBoolean()) {
         expr = new ExprJsExplicit(ctx, "!!expr", ctx.Boolean, expr.Named("expr"));
     }
     if (expr != s.Expr) {
         return new StmtReturn(ctx, expr);
     } else {
         return s;
     }
 }
 protected override ICode VisitAssignment(ExprAssignment e) {
     var ctx = e.Ctx;
     var expr = (Expr)this.Visit(e.Expr);
     var target = (ExprVar)this.Visit(e.Target);
     if (target.Type.IsBoolean() && expr.Type.IsInteger()) {
         expr = new ExprJsExplicit(ctx, "!!expr", ctx.Boolean, expr.Named("expr"));
     } else if (target.Type.IsUnsignedInteger() && expr.Type.IsSignedInteger()) {
         expr = new ExprConv(ctx, expr, expr.Type.UnsignedEquivilent(ctx.TypeSystem), false);
     }
     if (expr != e.Expr || target != e.Target) {
         return new ExprAssignment(ctx, target, expr);
     } else {
         return e;
     }
 }
 protected override ICode VisitBox(ExprBox e) {
     var ctx = e.Ctx;
     var expr = (Expr)this.Visit(e.Expr);
     if (e.Type.IsUnsignedInteger() && expr.Type.IsSignedInteger()) {
         expr = new ExprConv(ctx, expr, e.Type, false);
     }
     if (!e.Type.IsValueType) {
         // For ref-types 'box' does nothing
         return this.Visit(e.Expr);
     }
     var eType = new ExprJsTypeVarName(ctx, e.Type);
     if (e.Type.IsNullable()) {
         var exprIsVar = expr.IsVar();
         var innerType = e.Type.GetNullableInnerType();
         var temp = exprIsVar ? null : new ExprVarLocal(ctx, e.Type);
         var box = new ExprBox(ctx, temp ?? expr, innerType).Named("box");
         var nullableJs = exprIsVar ? "(expr !== null ? box : null)" : "((temp = expr) !== null ? box : null)";
         var nullableExpr = new ExprJsExplicit(ctx, nullableJs, innerType, temp.Named("temp"), expr.Named("expr"), box);
         return nullableExpr;
     } else {
         var deepCopyExpr = InternalFunctions.ValueTypeDeepCopyIfRequired(e.Type, () => (Expr)this.Visit(expr));
         var int2bool = e.Type.IsBoolean() && expr.Type.IsInteger() ? "!!" : "";
         var js = "{v:" + int2bool + "expr,_:type}";
         var ret = new ExprJsExplicit(ctx, js, e.Type, (deepCopyExpr ?? expr).Named("expr"), eType.Named("type"));
         return ret;
     }
 }
 protected override ICode VisitJsExplicit(ExprJsExplicit e)
 {
     this.HandleExplicitJs(e.JavaScript, e.NamedExprs);
     return(e);
 }
 protected override ICode VisitJsExplicit(ExprJsExplicit e) {
     this.HandleExplicitJs(e.JavaScript, e.NamedExprs);
     return e;
 }
 protected override ICode VisitJsExplicit(ExprJsExplicit e) {
     this.code.Append(e.JavaScript);
     return e;
 }
        protected override ICode VisitConv(ExprConv e) {
            var fromType = e.Expr.Type;
            var toType = e.Type;

            var fromTypeMetadataType = fromType.MetadataType;
            var toTypeMetadataType = toType.MetadataType;
            if (e.ForceFromUnsigned) {
                switch (fromTypeMetadataType) {
                case MetadataType.SByte: fromTypeMetadataType = MetadataType.Byte; break;
                case MetadataType.Int16: fromTypeMetadataType = MetadataType.UInt16; break;
                case MetadataType.Int32: fromTypeMetadataType = MetadataType.UInt32; break;
                case MetadataType.Int64: fromTypeMetadataType = MetadataType.UInt64; break;
                case MetadataType.IntPtr: fromTypeMetadataType = MetadataType.UIntPtr; break;
                }
            }
            if (fromTypeMetadataType == MetadataType.Char) {
                fromTypeMetadataType = MetadataType.UInt16;
            }
            if (toTypeMetadataType == MetadataType.Char) {
                toTypeMetadataType = MetadataType.UInt16;
            }

            var fromIdx = indexMap.ValueOrDefault(fromTypeMetadataType, -1);
            var toIdx = indexMap.ValueOrDefault(toTypeMetadataType, -1);

            if (fromIdx == -1 || toIdx == -1) {
                return e.Expr;
            }

            var ctx = e.Ctx;
            var js = jss[fromIdx, toIdx];
            if (js != null) {
                // In-place conversion
                var expr = new ExprJsExplicit(ctx, js, e.Type, e.Expr.Named("e"));
                return expr;
            } else {
                // Call conversion function
                var convMi = ((Func<int, int>)InternalFunctions.Conv<int, int>).Method.GetGenericMethodDefinition();
                var mConv = ctx.Module.Import(convMi).MakeGeneric(e.Expr.Type, e.Type);
                var convCall = new ExprCall(ctx, mConv, null, e.Expr);
                return convCall;
            }
        }