protected override void compile(Context ctx, bool mustReturn) { var gen = ctx.CurrentILGenerator; // find constructor var type = FunctionalHelper.CreateDelegateType(Body.GetExpressionType(ctx), _Method.ArgumentTypes); var ctor = ctx.ResolveConstructor(type, new[] {typeof (object), typeof (IntPtr)}); var closureInstance = ctx.CurrentScope.ClosureVariable; gen.EmitLoadLocal(closureInstance); gen.EmitLoadFunctionPointer(_Method.MethodBuilder); gen.EmitCreateObject(ctor.ConstructorInfo); }
protected override void compile(Context ctx, bool mustReturn) { var gen = ctx.CurrentILGenerator; var type = GetExpressionType(ctx); if(type.IsVoid()) Error(CompilerMessages.VoidTypeDefault); if(type.IsAbstract) Error(CompilerMessages.TypeAbstract, TypeSignature.FullSignature); if(Arguments.Count == 0) Error(CompilerMessages.ParameterlessConstructorParens); var isParameterless = Arguments.Count == 1 && Arguments[0].GetExpressionType(ctx) == typeof (Unit); var argTypes = isParameterless ? Type.EmptyTypes : Arguments.Select(a => a.GetExpressionType(ctx)).ToArray(); try { var ctor = ctx.ResolveConstructor(type, argTypes); if (!isParameterless) { var destTypes = ctor.ArgumentTypes; for (var idx = 0; idx < Arguments.Count; idx++) Expr.Cast(Arguments[idx], destTypes[idx]).Compile(ctx, true); } gen.EmitCreateObject(ctor.ConstructorInfo); } catch (AmbiguousMatchException) { Error(CompilerMessages.TypeConstructorAmbiguos, TypeSignature.FullSignature); } catch (KeyNotFoundException) { if (!isParameterless || !type.IsValueType) Error(CompilerMessages.TypeConstructorNotFound, TypeSignature.FullSignature); var castExpr = Expr.Default(TypeSignature); castExpr.Compile(ctx, true); } }
protected override void emitCode(Context ctx, bool mustReturn) { var resultType = Resolve(ctx); var gen = ctx.CurrentMethod.Generator; // local name is not cached because it can be closured. // if the identifier is actually a local constant, the 'compile' method is not invoked at all var local = Local ?? ctx.Scope.FindLocal(Identifier); if (local != null) { if(local.IsImmutable && RefArgumentRequired) error(CompilerMessages.ConstantByRef); if (local.IsClosured) { if (local.ClosureDistance == 0) emitGetClosuredLocal(ctx, local); else emitGetClosuredRemote(ctx, local); } else { emitGetLocal(ctx, local); } return; } // load pointer to global function if (_Method != null) { var ctor = ctx.ResolveConstructor(resultType, new[] {typeof (object), typeof (IntPtr)}); gen.EmitNull(); gen.EmitLoadFunctionPointer(_Method.MethodInfo); gen.EmitCreateObject(ctor.ConstructorInfo); return; } // get a property value if (_Property != null) { var id = _Property.PropertyId; if(!_Property.HasGetter) error(CompilerMessages.GlobalPropertyNoGetter, Identifier); var type = _Property.PropertyType; if (_Property.GetterMethod != null) { gen.EmitCall(_Property.GetterMethod.MethodInfo); } else { var method = typeof (GlobalPropertyHelper).GetMethod("Get").MakeGenericMethod(type); gen.EmitConstant(ctx.ContextId); gen.EmitConstant(id); gen.EmitCall(method); } return; } error(CompilerMessages.IdentifierNotFound, Identifier); }
private void castDelegate(Context ctx, Type from, Type to) { var gen = ctx.CurrentILGenerator; var toCtor = ctx.ResolveConstructor(to, new[] {typeof (object), typeof (IntPtr)}); var fromMethod = ctx.ResolveMethod(from, "Invoke"); var toMethod = ctx.ResolveMethod(to, "Invoke"); var fromArgs = fromMethod.ArgumentTypes; var toArgs = toMethod.ArgumentTypes; if(fromArgs.Length != toArgs.Length || toArgs.Select((ta, id) => !ta.IsExtendablyAssignableFrom(fromArgs[id], true)).Any(x => x)) Error(CompilerMessages.CastDelegateArgTypesMismatch, from, to); if(!toMethod.ReturnType.IsExtendablyAssignableFrom(fromMethod.ReturnType, true)) Error(CompilerMessages.CastDelegateReturnTypesMismatch, from, to); if (fromMethod.IsStatic) gen.EmitNull(); else Expression.Compile(ctx, true); if (from.IsGenericType && to.IsGenericType && from.GetGenericTypeDefinition() == to.GetGenericTypeDefinition()) return; gen.EmitLoadFunctionPointer(fromMethod.MethodInfo); gen.EmitCreateObject(toCtor.ConstructorInfo); }
protected override Type resolve(Context ctx, bool mustReturn) { base.resolve(ctx, true); var type = Type ?? ctx.ResolveType(TypeSignature); if (type.IsVoid()) error(CompilerMessages.VoidTypeDefault); if (type.IsAbstract) error(CompilerMessages.TypeAbstract, TypeSignature.FullSignature); if (type.IsInterface) error(CompilerMessages.TypeInterface, TypeSignature.FullSignature); if (Arguments.Count == 0) error(CompilerMessages.ParameterlessConstructorParens); try { _Constructor = ctx.ResolveConstructor(type, _ArgTypes); } catch (AmbiguousMatchException) { error(CompilerMessages.TypeConstructorAmbiguos, TypeSignature.FullSignature); } catch (KeyNotFoundException) { if (_ArgTypes.Length > 0 || !type.IsValueType) error(CompilerMessages.TypeConstructorNotFound, TypeSignature.FullSignature); _IsDefault = true; return type; } applyLambdaArgTypes(ctx); return resolvePartial(_Constructor, type, _ArgTypes); }
private void compileComposition(Context ctx) { var gen = ctx.CurrentILGenerator; // find constructor var type = FunctionalHelper.CreateDelegateType(_Method.ReturnType, _Method.ArgumentTypes); var ctor = ctx.ResolveConstructor(type, new[] { typeof(object), typeof(IntPtr) }); var closureInstance = ctx.CurrentScope.ClosureVariable; gen.EmitLoadLocal(closureInstance); gen.EmitLoadFunctionPointer(_Method.MethodBuilder); gen.EmitCreateObject(ctor.ConstructorInfo); }
/// <summary> /// Emits code for getting the method as a delegate instance. /// </summary> private void emitMethod(Context ctx, ILGenerator gen) { if (RefArgumentRequired) error(CompilerMessages.MethodRef); if (_IsStatic) gen.EmitNull(); var retType = _Method.ReturnType; var type = retType.IsVoid() ? FunctionalHelper.CreateActionType(_Method.ArgumentTypes) : FunctionalHelper.CreateFuncType(retType, _Method.ArgumentTypes); var ctor = ctx.ResolveConstructor(type, new [] { typeof(object), typeof(IntPtr) }); gen.EmitLoadFunctionPointer(_Method.MethodInfo); gen.EmitCreateObject(ctor.ConstructorInfo); }
private void castNumeric(Context ctx, Type from, Type to) { var gen = ctx.CurrentMethod.Generator; Expression.Emit(ctx, true); if (to == typeof (decimal)) { var ctor = ctx.ResolveConstructor(typeof (decimal), new[] { from }); if (ctor == null) { ctor = ctx.ResolveConstructor(typeof(decimal), new[] { typeof(int) }); gen.EmitConvert(typeof(int)); } gen.EmitCreateObject(ctor.ConstructorInfo); } else { gen.EmitConvert(to); } }