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); } }
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; } }