///////////////////////////////////////////////////////////////////////////////// private Expression GenerateArrayIndex(ExprCall pExpr) { // We have two possibilities here - we're either a single index array, in which // case we'll be PM_EXPRESSION_ARRAYINDEX, or we have multiple dimensions, // in which case we are PM_EXPRESSION_ARRAYINDEX2. // // Our arguments then, are: object, index or object, indices. ExprList list = (ExprList)pExpr.OptionalArguments; Debug.Assert(list != null); Expression obj = GetExpression(list.OptionalElement); Expression[] indices; if (pExpr.PredefinedMethod == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX) { indices = new[] { GetExpression(list.OptionalNextListNode) }; } else { Debug.Assert(pExpr.PredefinedMethod == PREDEFMETH.PM_EXPRESSION_ARRAYINDEX2); indices = GetArgumentsFromArrayInit((ExprArrayInit)list.OptionalNextListNode); } return(Expression.ArrayAccess(obj, indices)); }
private Stmt Call(Instruction inst, bool isVirtualCallInst) { var callingRef = ((MethodReference)inst.Operand).FullResolve(this.ctx); bool isVirtualCall = isVirtualCallInst && callingRef.Resolve().IsVirtual; var numArgs = callingRef.Parameters.Count; var argExprs = new Expr[numArgs]; for (int i = numArgs - 1; i >= 0; i--) { argExprs[i] = this.stack.Pop(); } for (int i = 0; i < numArgs; i++) { var argType = callingRef.Parameters[i].ParameterType.FullResolve(callingRef); if (argType.IsGenericParameter) { throw new InvalidOperationException(); } argExprs[i] = this.InsertConvIfRequired(argExprs[i], argType); } var obj = callingRef.HasThis ? this.stack.Pop() : null; var exprCall = new ExprCall(this.ctx, callingRef, obj, argExprs, isVirtualCall, this.ConstrainedType); if (callingRef.ReturnType.IsVoid()) { return(new StmtWrapExpr(this.ctx, exprCall)); } else { return(this.SsaLocalAssignment(exprCall)); } }
protected override ICode VisitUnboxAny(ExprUnboxAny e) { if (!e.Type.IsValueType) { // On ref-type, unbox-any becomes a castclass var expr = (Expr)this.Visit(e.Expr); var cast = new ExprCast(e.Ctx, expr, e.Type); return(cast); } var ctx = e.Ctx; if (e.Type.IsNullable()) { // If obj==null create Nullable with hasValue=false // If obj.Type not assignable to e.InnerType throw InvalidCastEx var innerType = e.Type.GetNullableInnerType(); var unboxMethod = ((Func <object, int?>)InternalFunctions.UnboxAnyNullable <int>).Method.GetGenericMethodDefinition(); var mUnbox = ctx.Module.Import(unboxMethod).MakeGeneric(innerType); var unboxAnyCall = new ExprCall(ctx, mUnbox, null, e.Expr); return(unboxAnyCall); } else { // If obj==null throw NullRefEx // If obj.Type not assignable to e.Type throw InvalidCastEx // otherwise unbox var unboxMethod = ((Func <object, int>)InternalFunctions.UnboxAnyNonNullable <int>).Method.GetGenericMethodDefinition(); var mUnbox = ctx.Module.Import(unboxMethod).MakeGeneric(e.Type); var unboxAnyCall = new ExprCall(ctx, mUnbox, null, e.Expr); return(unboxAnyCall); } }
///////////////////////////////////////////////////////////////////////////////// private Expression GenerateProperty(ExprCall pExpr) { ExprList list = (ExprList)pExpr.OptionalArguments; Expr instance = list.OptionalElement; Expr nextNode = list.OptionalNextListNode; ExprPropertyInfo propinfo; ExprArrayInit arguments; if (nextNode is ExprList nextList) { propinfo = nextList.OptionalElement as ExprPropertyInfo; arguments = nextList.OptionalNextListNode as ExprArrayInit; } else { propinfo = nextNode as ExprPropertyInfo; arguments = null; } PropertyInfo p = propinfo.PropertyInfo; if (p == null) { Debug.Fail("How did we get a prop that doesn't have a propinfo?"); throw Error.InternalCompilerError(); } if (arguments == null) { return(Expression.Property(GetExpression(instance), p)); } return(Expression.Property(GetExpression(instance), p, GetArgumentsFromArrayInit(arguments))); }
///////////////////////////////////////////////////////////////////////////////// private Expression GenerateField(ExprCall pExpr) { ExprList list = (ExprList)pExpr.OptionalArguments; ExprFieldInfo fieldInfo = (ExprFieldInfo)list.OptionalNextListNode; Debug.Assert(fieldInfo != null); Type t = fieldInfo.FieldType.AssociatedSystemType; FieldInfo f = fieldInfo.Field.AssociatedFieldInfo; // This is to ensure that for embedded nopia types, we have the // appropriate local type from the member itself; this is possible // because nopia types are not generic or nested. if (!t.IsGenericType && !t.IsNested) { t = f.DeclaringType; } // Now find the generic'ed one if we're generic. if (t.IsGenericType) { f = t.GetField(f.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); } return(Expression.Field(GetExpression(list.OptionalElement), f)); }
// TODO: Make these methods share most of the code... protected override ICode VisitCall(ExprCall e) { var ctx = e.Ctx; var byRefs = new List <Tuple <Expr, Expr> >(); var args = e.CallMethod.Parameters.Zip(e.Args, (p, a) => new { p, a }) .Select(x => { if (x.p.ParameterType.IsByReference) { var wrapper = ctx.Local(ctx.IntPtr); byRefs.Add(Tuple.Create(x.a, (Expr)wrapper)); return(wrapper); } else { return(x.a); } }) .ToArray(); if (!args.SequenceEqual(e.Args)) { var call = new ExprCall(ctx, e.CallMethod, e.Obj, args, e.IsVirtualCall, e.ConstrainedType, e.Type); var resultTemp = ctx.Local(e.Type); return(new ExprJsByRefWrapper(e.Ctx, call, resultTemp, byRefs)); } return(base.VisitCall(e)); }
///////////////////////////////////////////////////////////////////////////////// private static Expression GenerateConstantType(ExprCall pExpr) { ExprList list = (ExprList)pExpr.OptionalArguments; return(Expression.Constant( list.OptionalElement.Object, ((ExprTypeOf)list.OptionalNextListNode).SourceType.AssociatedSystemType)); }
public Stmt GetImpl(Ctx ctx) { var obj = ctx.MethodParameter(0, "obj"); var toType = ctx.MethodParameter(1, "toType"); var canCastTo = new ExprVarLocal(ctx, ctx.Type.MakeArray()).Named("canCastTo"); var mGetType = ctx.Module.Import(typeof(object).GetMethod("GetType")); var getTypeCall = new ExprCall(ctx, mGetType, obj.Expr).Named("getTypeCall"); var assignableTo = new ExprJsTypeData(ctx, TypeData.AssignableTo).Named("assignableTo"); var i = new ExprVarLocal(ctx, ctx.Int32).Named("i"); var t = new ExprVarLocal(ctx, ctx.Type).Named("temp"); var js = @" if (obj == null) return true; temp = getTypeCall; if (!temp) return false; // Required because C# objects received via JSON may have null type when type is never refered to in JS if (temp === toType) return true; canCastTo = temp.assignableTo; for (i = canCastTo.length - 1; i >= 0; i--) if (canCastTo[i] === toType) return true; return false; "; var stmt = new StmtJsExplicit(ctx, js, obj, toType, canCastTo, getTypeCall, assignableTo, i, t); return(stmt); }
public Stmt GetImpl(Ctx ctx) { var a = ctx.MethodParameter(0, "a"); var b = ctx.MethodParameter(1, "b"); var neg = ctx.Local(ctx.Boolean, "neg"); var aNegate = new ExprUnary(ctx, UnaryOp.Negate, ctx.Int64, a.Expr).Named("aNegate"); var bNegate = new ExprUnary(ctx, UnaryOp.Negate, ctx.Int64, b.Expr).Named("bNegate"); var divMod = new ExprCall(ctx, (Func <UInt64, UInt64, object>)_Int64UInt64.UInt64DivRem, null, a.Expr, b.Expr).Named("divMod"); var r = ctx.Local(ctx.Int64, "r"); var rNegate = new ExprUnary(ctx, UnaryOp.Negate, ctx.Int64, r.Expr).Named("rNegate"); // TODO: Throw ArithmeticException if a == Int64.MinValue and b == -1 // TODO: Handle a or b being Int64.MinValue var js = @" neg = false; if (a[0] >>> 31) { a = aNegate; neg = true; } if (b[0] >>> 31) b = bNegate; r = divMod[1]; return neg ? rNegate : r; "; var stmt = new StmtJsExplicit(ctx, js, a, b, neg, r, aNegate, bNegate, divMod, rNegate); return(stmt); }
public Stmt GetImpl(Ctx ctx) { var obj = ctx.MethodParameter(0, "obj"); var toType = ctx.MethodParameter(1); var callCanAssignTo = new ExprCall(ctx, (Func <object, Type, bool>)CanAssignTo, null, obj.Expr, toType).Named("callCanAssignTo"); var mCtorEx = ctx.Module.Import(typeof(InvalidCastException).GetConstructor(new[] { typeof(string) })); var mGetType = ctx.Module.Import(typeof(object).GetMethod("GetType")); var getTypeCall = new ExprCall(ctx, mGetType, obj.Expr); var msgParts = new Expr[] { new ExprLiteral(ctx, "Unable to cast object of type '", ctx.String), new ExprCall(ctx, typeof(Type).GetProperty("FullName").GetMethod, getTypeCall), new ExprLiteral(ctx, "' to type '", ctx.String), new ExprCall(ctx, typeof(Type).GetProperty("FullName").GetMethod, toType), new ExprLiteral(ctx, "'.", ctx.String) }; var msg = msgParts.Aggregate((a, b) => new ExprBinary(ctx, BinaryOp.Add, ctx.String, a, b)); var ctorEx = new ExprNewObj(ctx, mCtorEx, msg).Named("callCtorEx"); var js = @" if (callCanAssignTo) return obj; throw callCtorEx "; var stmt = new StmtJsExplicit(ctx, js, callCanAssignTo, obj, ctorEx); return(stmt); }
///////////////////////////////////////////////////////////////////////////////// private Expression GenerateUserDefinedUnaryOperator(ExprCall pExpr) { PREDEFMETH pm = pExpr.PredefinedMethod; ExprList list = (ExprList)pExpr.OptionalArguments; Expression arg = GetExpression(list.OptionalElement); MethodInfo methodInfo = ((ExprMethodInfo)list.OptionalNextListNode).MethodInfo; switch (pm) { case PREDEFMETH.PM_EXPRESSION_NOT_USER_DEFINED: return(Expression.Not(arg, methodInfo)); case PREDEFMETH.PM_EXPRESSION_NEGATE_USER_DEFINED: return(Expression.Negate(arg, methodInfo)); case PREDEFMETH.PM_EXPRESSION_UNARYPLUS_USER_DEFINED: return(Expression.UnaryPlus(arg, methodInfo)); case PREDEFMETH.PM_EXPRESSION_NEGATECHECKED_USER_DEFINED: return(Expression.NegateChecked(arg, methodInfo)); default: Debug.Fail("Invalid Predefined Method in GenerateUserDefinedUnaryOperator"); throw Error.InternalCompilerError(); } }
protected override ICode VisitUnary(ExprUnary e) { if (e.Expr.Type.IsInt64() || e.Expr.Type.IsUInt64()) { var ctx = e.Ctx; var signed = e.Expr.Type.IsInt64(); Delegate d; switch (e.Op) { case UnaryOp.Negate: var zero = ctx.Literal(0L, ctx.Int64); var subCall = new ExprBinary(ctx, BinaryOp.Sub, ctx.Int64, zero, e.Expr); return(subCall); case UnaryOp.BitwiseNot: d = signed ? (Delegate)(Func <Int64, Int64>)_Int64.BitwiseNot : (Func <UInt64, UInt64>)_UInt64.BitwiseNot; break; default: throw new NotImplementedException("Cannot handle: " + e.Op); } var m = ctx.Module.Import(d.Method); var expr = (Expr)this.Visit(e.Expr); var call = new ExprCall(ctx, m, null, expr); return(call); } return(base.VisitUnary(e)); }
protected override ICode VisitCall(ExprCall e) { var obj = this.Convert(e.Obj, e.CallMethod.DeclaringType); var args = e.Args.Select((x, i) => this.Convert(x, e.CallMethod.Parameters[i].ParameterType.FullResolve(e.CallMethod))).ToArray(); return(new ExprCall(e.Ctx, e.CallMethod, obj, args, e.IsVirtualCall, e.ConstrainedType, e.Type)); }
public static Stmt GetHashCode(Ctx ctx) { var toString = new ExprJsResolvedMethod(ctx, ctx.String, ctx.This, "toExponential"); var getHashCode = new ExprCall(ctx, typeof(string).GetMethod("GetHashCode"), toString); var stmt = new StmtReturn(ctx, getHashCode); return(stmt); }
///////////////////////////////////////////////////////////////////////////////// private Expression GenerateInvoke(ExprCall pExpr) { ExprList list = (ExprList)pExpr.OptionalArguments; return(Expression.Invoke( GetExpression(list.OptionalElement), GetArgumentsFromArrayInit(list.OptionalNextListNode as ExprArrayInit))); }
///////////////////////////////////////////////////////////////////////////////// private Expression GenerateAssignment(ExprCall pExpr) { ExprList list = (ExprList)pExpr.OptionalArguments; return(Expression.Assign( GetExpression(list.OptionalElement), GetExpression(list.OptionalNextListNode))); }
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 VisitIsInst(ExprIsInst e) { var ctx = e.Ctx; var mIsInst = ctx.Module.Import(((Func <object, Type, object>)InternalFunctions.IsInst).Method); var eType = new ExprJsTypeVarName(ctx, e.Type); var expr = new ExprCall(ctx, e.Type, mIsInst, null, e.Expr, eType); return(expr); }
///////////////////////////////////////////////////////////////////////////////// private Expression GenerateNew(ExprCall pExpr) { ExprList list = (ExprList)pExpr.OptionalArguments; ConstructorInfo constructor = ((ExprMethodInfo)list.OptionalElement).ConstructorInfo; Expression[] arguments = GetArgumentsFromArrayInit(list.OptionalNextListNode as ExprArrayInit); return(Expression.New(constructor, arguments)); }
public Stmt GetImpl(Ctx ctx) { var obj = ctx.MethodParameter(0, "obj"); var toType = ctx.MethodParameter(1); var callCanAssignTo = new ExprCall(ctx, (Func <object, Type, bool>)CanAssignTo, null, obj.Expr, toType).Named("callCanAssignTo"); var js = "return callCanAssignTo ? obj : null;"; var stmt = new StmtJsExplicit(ctx, js, callCanAssignTo, obj); return(stmt); }
public Stmt GetImpl(Ctx ctx) { var a = ctx.MethodParameter(0); var b = ctx.MethodParameter(1); var divMod = new ExprCall(ctx, (Func <UInt64, UInt64, object>)_Int64UInt64.UInt64DivRem, null, a, b).Named("divMod"); var js = "return divMod[1];"; var stmt = new StmtJsExplicit(ctx, js, divMod); return(stmt); }
public static Stmt ToString(Ctx ctx) { var value = ctx.This; var format = ctx.MethodParameter(0); var provider = ctx.MethodParameter(1); var nfi = ctx.Literal(null, ctx.Module.Import(typeof(NumberFormatInfo))); var expr = new ExprCall(ctx, (Func <double, string, NumberFormatInfo, string>)JsResolvers.Classes.Helpers.Number.FormatDouble, null, value, format, nfi); return(new StmtReturn(ctx, expr)); }
protected override Expr VisitCall(ExprCall e) { foreach (var param in e.Parameters) { this.Visit(param); } var instCall = this.il.Create(OpCodes.Call, e.Method); this.Emit(e, instCall); return(e); }
private Expr ProcessRequires2(ExprCall e) { MethodDefinition mRequires = this.contractsRuntime.GetRequires(); Expr conditionExpr = e.Parameters.First(); Expr msgExpr = e.Parameters.ElementAt(1); string conditionText = this.GetConditionString(e); Expr conditionStringExpr = new ExprLoadConstant(this.methodInfo, conditionText); var call = new ExprCall(this.methodInfo, mRequires, new Expr [] { conditionExpr, msgExpr, conditionStringExpr }); this.contractRequiresInfo.Add(new ContractRequiresInfo(e, call)); return(call); }
///////////////////////////////////////////////////////////////////////////////// protected override Expr VisitSAVE(ExprBinOp pExpr) { // Saves should have a LHS that is a CALL to PM_EXPRESSION_PARAMETER // and a RHS that is a WRAP of that call. ExprCall call = (ExprCall)pExpr.OptionalLeftChild; Debug.Assert(call?.PredefinedMethod == PREDEFMETH.PM_EXPRESSION_PARAMETER); Debug.Assert(pExpr.OptionalRightChild is ExprWrap); Expression parameter = _ListOfParameters[_currentParameterIndex++]; _DictionaryOfParameters.Add(call, parameter); return(null); }
public static Expr SortComparer(ICall call) { var ctx = call.Ctx; var t = call.CallMethod.DeclaringType.GetGenericArgument(0); var tComparer = call.CallMethod.Parameters.First().ParameterType.FullResolve(call.CallMethod); var mGenSort = ((Action <T[], IComparer <T> >)Array.Sort <T>).Method.GetGenericMethodDefinition(); var mSort = ctx.Module.Import(mGenSort).MakeGeneric(t); var comparer = call.Arg(0, "comparer"); var mDefaultComparerNet = typeof(Comparer <T>).GetProperty("Default").GetMethod; var mDefaultComparer = ctx.Module.Import(mDefaultComparerNet); var defaultComparerCall = new ExprCall(ctx, mDefaultComparer, null).Named("defaultComparerCall"); var ensureComparer = new ExprJsExplicit(ctx, "(comparer || defaultComparerCall)", tComparer, comparer, defaultComparerCall); return(new ExprCall(ctx, mSort, null, GetNamedArrayField(call).Expr, ensureComparer)); }
public static Expr SortArrayComparer(ICall call) { var ctx = call.Ctx; var genType = call.CallMethod.GetGenericArgument(0); var array = call.Arg(0, "array"); var comparer = call.Arg(1); var comparerType = call.CallMethod.Parameters.ElementAt(1).ParameterType.FullResolve(call.CallMethod); var mCompare = comparerType.EnumResolvedMethods().First(x => x.Name == "Compare"); var a = ctx.Local(genType, "a"); var b = ctx.Local(genType, "b"); var comparerCall = new ExprCall(ctx, mCompare, comparer, new[] { a.Expr, b.Expr }, true).Named("comparerCall"); var js = "array.sort(function(a, b) { return comparerCall; })"; return(new ExprJsExplicit(ctx, js, ctx.Void, array, comparerCall, a, b)); }
public static Stmt GetValue(Ctx ctx) { var value = ctx.Local(ctx.Object, "value"); var index = ctx.MethodParameter(0, "index"); var thisType = ctx.Local(ctx.Type, "thisType"); var thisGetTypeCall = new ExprCall(ctx, (Func <Type>)(new object().GetType), ctx.This).Named("thisGetTypeCall"); var eElementType = new ExprJsTypeData(ctx, TypeData.ElementType).Named("eElementType"); var eIsValueType = new ExprJsTypeData(ctx, TypeData.IsValueType).Named("eIsValueType"); var js = @" value = this[index]; thisType = thisGetTypeCall; return thisType.eElementType.eIsValueType ? {v:value, _:thisType.eElementType} : value; "; var stmt = new StmtJsExplicit(ctx, js, ctx.ThisNamed, value, index, thisType, thisGetTypeCall, eElementType, eIsValueType); return(stmt); }
protected override ICode VisitNewArray(ExprNewArray e) { var ctx = e.Ctx; MethodInfo caGenDef; if (e.ElementType.IsValueType) { caGenDef = ((Func <int, int[]>)InternalFunctions.CreateArrayValueType <int>).Method.GetGenericMethodDefinition(); } else { caGenDef = ((Func <int, object[]>)InternalFunctions.CreateArrayRefType <object>).Method.GetGenericMethodDefinition(); } var mCreateArray = ctx.Module.Import(caGenDef).MakeGeneric(e.ElementType); var expr = new ExprCall(ctx, mCreateArray, null, e.ExprNumElements); return(expr); }
///////////////////////////////////////////////////////////////////////////////// private Expr GenerateLambda(ExprCall pExpr) { // We always call Lambda(body, arrayinit) where the arrayinit // is the initialization of the parameters. return(Visit(((ExprList)pExpr.OptionalArguments).OptionalElement)); /* * // Do we need to do this? * Expression e = (body as ExpressionExpr).Expression; * if (e.Type.IsValueType) * { * // If we have a value type, convert it to object so that boxing * // can happen. * * e = Expression.Convert(body.Expression, typeof(object)); * } * */ }