public static TypeCompilerEnvironment EnterType (CompilerEnvironment env, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeId, CST.TypeEnvironment typeEnv, TypeTrace typeTrace) { var typeBoundTypeParameterIds = new Seq <JST.Identifier>(); for (var i = 0; i < typeEnv.Type.Arity; i++) { typeBoundTypeParameterIds.Add(nameSupply.GenSym()); } var res = new TypeCompilerEnvironment (typeEnv.Global, typeEnv.SkolemDefs, typeEnv.Assembly, typeEnv.Type, typeEnv.TypeBoundArguments, env, nameSupply, rootId, assemblyId, typeId, typeBoundTypeParameterIds, typeTrace); res.BindSpecial(); return(res); }
private void InheritBindings(TypeCompilerEnvironment outer) { foreach (var kv in outer.boundAssemblies) { boundAssemblies.Add(kv.Key, kv.Value); } foreach (var kv in outer.boundTypes) { boundTypes.Add(kv.Key, kv.Value); } }
public TypeCompiler(TypeDefinitionCompiler parent) { // Type compiler is always in context of it's type definition Env = parent.Env; Parent = parent; var typeEnv = parent.TyconEnv.AddSelfTypeBoundArguments(); NameSupply = typeEnv.Type.Arity > 0 ? parent.NameSupply.Fork() : parent.NameSupply; RootId = parent.RootId; AssemblyId = parent.AssemblyId; TypeDefinitionId = parent.TypeDefinitionId; TypeId = typeEnv.Type.Arity > 0 ? NameSupply.GenSym() : parent.TypeDefinitionId; TypeCompEnv = TypeCompilerEnvironment.EnterType(Env, NameSupply, RootId, AssemblyId, TypeId, typeEnv, parent.TypeTrace); }
public TypeCompilerEnvironment EnterFunction() { var res = new TypeCompilerEnvironment (Global, SkolemDefs, Assembly, Type, TypeBoundArguments, env, NameSupply.Fork(), rootId, assemblyId, typeId, TypeBoundTypeParameterIds, typeTrace); res.InheritBindings(this); return(res); }
public static TypeCompilerEnvironment EnterType (CompilerEnvironment env, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeId, CST.TypeEnvironment typeEnv, TypeTrace typeTrace) { var typeBoundTypeParameterIds = new Seq<JST.Identifier>(); for (var i = 0; i < typeEnv.Type.Arity; i++) typeBoundTypeParameterIds.Add(nameSupply.GenSym()); var res = new TypeCompilerEnvironment (typeEnv.Global, typeEnv.SkolemDefs, typeEnv.Assembly, typeEnv.Type, typeEnv.TypeBoundArguments, env, nameSupply, rootId, assemblyId, typeId, typeBoundTypeParameterIds, typeTrace); res.BindSpecial(); return res; }
private void InheritBindings(TypeCompilerEnvironment outer) { foreach (var kv in outer.boundAssemblies) boundAssemblies.Add(kv.Key, kv.Value); foreach (var kv in outer.boundTypes) boundTypes.Add(kv.Key, kv.Value); }
public TypeCompilerEnvironment EnterFunction() { var res = new TypeCompilerEnvironment (Global, SkolemDefs, Assembly, Type, TypeBoundArguments, env, NameSupply.Fork(), rootId, assemblyId, typeId, TypeBoundTypeParameterIds, typeTrace); res.InheritBindings(this); return res; }
public void EmitReflection(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, JST.Expression lhs) { var level = default(ReflectionLevel); Env.AttributeHelper.GetValueFromType (innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, Env.AttributeHelper.ReflectionAttributeRef, Env.AttributeHelper.TheReflectionLevelProperty, true, true, ref level); if (level == ReflectionLevel.None && innerTypeCompEnv.Type.IsAttributeType(Env.Global, innerTypeCompEnv.Assembly)) level = ReflectionLevel.Names; if (level >= ReflectionLevel.Names) { if (Env.DebugMode) body.Add(new JST.CommentStatement("Reflection")); // ReflectionName body.Add (JST.Statement.DotAssignment (lhs, Constants.TypeReflectionName, ReflectionNameExpression(body, innerTypeCompEnv, false))); // ReflectionFullName body.Add (JST.Statement.DotAssignment (lhs, Constants.TypeReflectionFullName, ReflectionNameExpression(body, innerTypeCompEnv, true))); // ReflectionNamespace body.Add (JST.Statement.DotAssignment (lhs, Constants.TypeReflectionNamespace, ReflectionNamespaceExpression(body, innerTypeCompEnv))); if (level >= ReflectionLevel.Full) { // ReflectionMemberInfos body.Add (JST.Statement.DotAssignment (lhs, Constants.TypeReflectionMemberInfos, MemberInfoExpression(body, innerTypeCompEnv))); // CustomAttributes body.Add (JST.Statement.DotAssignment (lhs, Constants.TypeReflectionCustomAttributes, CustomAttributesExpression (body, innerTypeCompEnv, CST.MessageContextBuilders.Env(TypeCompEnv), TypeCompEnv.Type.CustomAttributes))); } } }
// Array of custom attributes private JST.Expression CustomAttributesExpression(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, MessageContext ctxt, IImSeq<CST.CustomAttribute> attributes) { var objs = new Seq<JST.Expression>(); foreach (var attribute in attributes) { var obj = CustomAttributeExpression(body, innerTypeCompEnv, ctxt, attribute); if (obj != null) objs.Add(obj); } return new JST.ArrayLiteral(objs); }
private JST.Expression ReflectionNameExpression(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, bool isFullName) { var nm = CST.CSTWriter.WithAppend (Env.Global, isFullName ? CST.WriterStyle.ReflectionFullName : CST.WriterStyle.ReflectionName, innerTypeCompEnv.Type.EffectiveName(Env.Global).Append); var lit = new JST.StringLiteral(nm); if (innerTypeCompEnv.Type.Arity == 0) return lit; else { return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionName, lit, new JST.ArrayLiteral (innerTypeCompEnv.TypeBoundArguments.Select(t => innerTypeCompEnv.ResolveType(t, TypePhase.Id)).ToSeq()), new JST.BooleanLiteral(isFullName)); } }
private JST.Expression MemberInfoExpression(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv) { var sharedMethodInfos = new Map<CST.MethodSignature, JST.Identifier>(); var id = default(JST.Identifier); foreach (var propDef in Parent.Properties) { if (propDef.Get != null) { var infoExp = MethodInfoFromMethod(body, innerTypeCompEnv, innerTypeCompEnv.Type.ResolveMethod(propDef.Get)); if (infoExp != null) { id = innerTypeCompEnv.NameSupply.GenSym(); body.Add(JST.Statement.Var(id, infoExp)); sharedMethodInfos.Add(propDef.Get, id); } } if (propDef.Set != null) { var infoExp = MethodInfoFromMethod(body, innerTypeCompEnv, innerTypeCompEnv.Type.ResolveMethod(propDef.Set)); if (infoExp != null) { id = innerTypeCompEnv.NameSupply.GenSym(); body.Add(JST.Statement.Var(id, infoExp)); sharedMethodInfos.Add(propDef.Set, id); } } } foreach (var eventDef in Parent.Events) { if (eventDef.Add != null) { var infoExp = MethodInfoFromMethod(body, innerTypeCompEnv, innerTypeCompEnv.Type.ResolveMethod(eventDef.Add)); if (infoExp != null) { id = innerTypeCompEnv.NameSupply.GenSym(); body.Add(JST.Statement.Var(id, infoExp)); sharedMethodInfos.Add(eventDef.Add, id); } } if (eventDef.Remove != null) { var infoExp = MethodInfoFromMethod(body, innerTypeCompEnv, innerTypeCompEnv.Type.ResolveMethod(eventDef.Remove)); if (infoExp != null) { id = innerTypeCompEnv.NameSupply.GenSym(); body.Add(JST.Statement.Var(id, infoExp)); sharedMethodInfos.Add(eventDef.Remove, id); } } } var infoExps = new Seq<JST.Expression>(); foreach (var methodDef in Parent.Methods) { if (sharedMethodInfos.TryGetValue(methodDef.MethodSignature, out id)) infoExps.Add(id.ToE()); else { var infoExp = MethodInfoFromMethod(body, innerTypeCompEnv, methodDef); if (infoExp != null) infoExps.Add(infoExp); } } foreach (var fieldDef in Parent.Fields) { var infoExp = FieldInfoFromField(body, innerTypeCompEnv, fieldDef); if (infoExp != null) infoExps.Add(infoExp); } foreach (var propDef in Parent.Properties) { var infoExp = PropertyInfoFromProperty(body, innerTypeCompEnv, sharedMethodInfos, propDef); if (infoExp != null) infoExps.Add(infoExp); } foreach (var eventDef in Parent.Events) { var infoExp = EventInfoFromEvent(body, innerTypeCompEnv, sharedMethodInfos, eventDef); if (infoExp != null) infoExps.Add(infoExp); } return new JST.ArrayLiteral(infoExps); }
private JST.Expression EventInfoFromEvent(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, Map<CST.MethodSignature, JST.Identifier> sharedMethodInfos, CST.EventDef eventDef) { var slot = Env.GlobalMapping.ResolveEventDefToSlot(innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, eventDef); var slotExp = new JST.StringLiteral(Constants.ObjectEventSlot(slot)); return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionEventInfo, slotExp, TypeId.ToE(), new JST.BooleanLiteral(eventDef.IsStatic), new JST.BooleanLiteral(!eventDef.IsStatic), new JST.StringLiteral(eventDef.Name), CustomAttributesExpression (body, innerTypeCompEnv, CST.MessageContextBuilders.Member(Env.Global, innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, eventDef), eventDef.CustomAttributes), innerTypeCompEnv.ResolveType(eventDef.HandlerType, TypePhase.Constructed), eventDef.Add == null || !sharedMethodInfos.ContainsKey(eventDef.Add) ? (JST.Expression)new JST.NullExpression() : sharedMethodInfos[eventDef.Add].ToE(), eventDef.Remove == null || !sharedMethodInfos.ContainsKey(eventDef.Remove) ? (JST.Expression)new JST.NullExpression() : sharedMethodInfos[eventDef.Remove].ToE()); }
private JST.Expression PropertyInfoFromProperty(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, Map<CST.MethodSignature, JST.Identifier> sharedMethodInfos, CST.PropertyDef propDef) { var slot = Env.GlobalMapping.ResolvePropertyDefToSlot(innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, propDef); var slotExp = new JST.StringLiteral(Constants.ObjectPropertySlot(slot)); return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionPropertyInfo, slotExp, TypeId.ToE(), new JST.BooleanLiteral(propDef.IsStatic), new JST.BooleanLiteral(!propDef.IsStatic), new JST.StringLiteral(propDef.Name), CustomAttributesExpression (body, innerTypeCompEnv, CST.MessageContextBuilders.Member(Env.Global, innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, propDef), propDef.CustomAttributes), innerTypeCompEnv.ResolveType(propDef.FieldType, TypePhase.Constructed), propDef.Get == null || !sharedMethodInfos.ContainsKey(propDef.Get) ? (JST.Expression)new JST.NullExpression() : sharedMethodInfos[propDef.Get].ToE(), propDef.Set == null || !sharedMethodInfos.ContainsKey(propDef.Set) ? (JST.Expression)new JST.NullExpression() : sharedMethodInfos[propDef.Set].ToE()); }
private JST.Expression FieldInfoFromField(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, CST.FieldDef fieldDef) { if (Env.AttributeHelper.FieldHasAttribute (innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, fieldDef, Env.Global.CompilerGeneratedAttributeRef, false, false)) // Ignore compiler-generate fields return null; var slot = Env.GlobalMapping.ResolveFieldDefToSlot (innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, fieldDef); return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionFieldInfo, new JST.StringLiteral(slot), TypeId.ToE(), new JST.BooleanLiteral(fieldDef.IsStatic), new JST.BooleanLiteral(!fieldDef.IsStatic), new JST.StringLiteral(fieldDef.Name), CustomAttributesExpression (body, innerTypeCompEnv, CST.MessageContextBuilders.Member (Env.Global, innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, fieldDef), fieldDef.CustomAttributes), innerTypeCompEnv.ResolveType(fieldDef.FieldType, TypePhase.Constructed), new JST.NullExpression()); }
private JST.Expression MethodInfoFromMethod(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, CST.MethodDef methodDef) { if (methodDef.TypeArity > 0) // TODO: polymorphic methods return null; if (methodDef.Invalid != null || !methodDef.IsUsed || Env.InlinedMethods.IsInlinable(innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, methodDef)) // This is possible if method is a getter/setter/adder/removed for a used property // or event but the method itself is unused or inlined. return null; if (methodDef.IsOverriding) // MethodInfo will have been supplied by supertype return null; var slot = Env.GlobalMapping.ResolveMethodDefToSlot(innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, methodDef); var attrs = CustomAttributesExpression (body, innerTypeCompEnv, CST.MessageContextBuilders.Member (Env.Global, innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, methodDef), methodDef.CustomAttributes); var paramTypes = new JST.ArrayLiteral (methodDef.ValueParameters.Skip(methodDef.IsStatic ? 0 : 1).Select (p => innerTypeCompEnv.ResolveType(p.Type, TypePhase.Constructed)).ToSeq()); if (methodDef.IsConstructor) return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionConstructorInfo, new JST.StringLiteral(slot), TypeId.ToE(), new JST.BooleanLiteral(!methodDef.IsStatic), attrs, paramTypes); else return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionMethodInfo, new JST.StringLiteral(slot), TypeId.ToE(), new JST.BooleanLiteral(methodDef.IsStatic), new JST.BooleanLiteral(!methodDef.IsStatic), new JST.StringLiteral(methodDef.Name), attrs, new JST.BooleanLiteral(methodDef.IsVirtualOrAbstract), paramTypes, new JST.BooleanLiteral(true), methodDef.Result == null ? (JST.Expression)new JST.NullExpression() : innerTypeCompEnv.ResolveType(methodDef.Result.Type, TypePhase.Constructed)); }
private JST.Expression ReflectionNamespaceExpression(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv) { var nm = innerTypeCompEnv.Type.EffectiveName(Env.Global); var lit = nm.Namespace.Length == 0 ? (JST.Expression)new JST.NullExpression() : (JST.Expression)new JST.StringLiteral(nm.Namespace); if (innerTypeCompEnv.Type.Arity == 0) return lit; else { return JST.Expression.DotCall (RootId.ToE(), Constants.RootReflectionNamespace, lit, new JST.ArrayLiteral (innerTypeCompEnv.TypeBoundArguments.Select(t => innerTypeCompEnv.ResolveType(t, TypePhase.Id)).ToSeq())); } }
// ---------------------------------------------------------------------- // Reflection // ---------------------------------------------------------------------- // The object representing custom attribute private JST.Expression CustomAttributeExpression(Seq<JST.Statement> body, TypeCompilerEnvironment innerTypeCompEnv, MessageContext ctxt, CST.CustomAttribute attr) { if (Env.AttributeHelper.IsSpecialAttribute(attr)) return null; var attrTypeEnv = attr.Type.Enter(innerTypeCompEnv); if (attrTypeEnv.Type.Invalid != null || !attrTypeEnv.Type.IsUsed) { Env.Log (new UnimplementableFeatureMessage (ctxt, "custom attribute", String.Format("Type '{0}' is not marked as [Used] or is invalid", attr.Type))); return null; } var ctorDef = attrTypeEnv.Type.Members.OfType<CST.MethodDef>().Where (m => m.Invalid == null && m.IsUsed && m.IsConstructor && !m.IsStatic && m.Arity == attr.PositionalProperties.Count + 1).FirstOrDefault(); if (ctorDef == null) { Env.Log (new UnimplementableFeatureMessage (ctxt, "custom attribute", String.Format ("Type '{0}' does not have a constructor for {1} positional parameters", attr.Type, attr.PositionalProperties.Count))); return null; } var ctorRef = new CST.MethodRef(attr.Type, ctorDef.MethodSignature, null); var args = new Seq<JST.Expression>(); for (var i = 0; i < attr.PositionalProperties.Count; i++) { var t = attrTypeEnv.SubstituteType(ctorDef.ValueParameters[i + 1].Type); var o = attr.PositionalProperties[i]; var e = Env.JSTHelpers.InitializerExpression(innerTypeCompEnv, ctxt, o, t); args.Add(e); } var id = innerTypeCompEnv.NameSupply.GenSym(); body.Add(JST.Statement.Var(id)); Env.JSTHelpers.ConstructorExpression(innerTypeCompEnv, innerTypeCompEnv.NameSupply, body, id.ToE(), ctorRef, args); foreach (var kv in attr.NamedProperties) { var stmnt = default(JST.Statement); foreach (var memberDef in attrTypeEnv.Type.Members.Where (m => !m.IsStatic && m.Name.Equals(kv.Key, StringComparison.Ordinal))) { switch (memberDef.Flavor) { case CST.MemberDefFlavor.Field: { var fieldDef = (CST.FieldDef)memberDef; if (fieldDef.Invalid == null && fieldDef.IsUsed) { var t = attrTypeEnv.SubstituteType(fieldDef.FieldType); var o = kv.Value; var e = Env.JSTHelpers.InitializerExpression(innerTypeCompEnv, ctxt, o, t); var slot = Env.GlobalMapping.ResolveFieldDefToSlot (attrTypeEnv.Assembly, attrTypeEnv.Type, fieldDef); stmnt = JST.Statement.DotAssignment (id.ToE(), new JST.Identifier(Constants.ObjectInstanceFieldSlot(slot)), e); } break; } case CST.MemberDefFlavor.Property: { var propDef = (CST.PropertyDef)memberDef; if (propDef.Invalid == null) { var t = attrTypeEnv.SubstituteType(propDef.FieldType); var o = kv.Value; var e = Env.JSTHelpers.InitializerExpression(innerTypeCompEnv, ctxt, o, t); if (propDef.Set != null) { var setMethodDef = attrTypeEnv.Type.ResolveMethod(propDef.Set); if (setMethodDef != null && setMethodDef.Invalid == null && setMethodDef.IsUsed && setMethodDef.Arity == 2 && !Env.InlinedMethods.IsInlinable(innerTypeCompEnv.Assembly, innerTypeCompEnv.Type, setMethodDef)) { var setMethodRef = new CST.MethodRef (attr.Type, setMethodDef.MethodSignature, null); stmnt = new JST.ExpressionStatement (innerTypeCompEnv.MethodCallExpression (setMethodRef, innerTypeCompEnv.NameSupply, false, new Seq<JST.Expression>(id.ToE(), e))); } } } break; } case CST.MemberDefFlavor.Method: case CST.MemberDefFlavor.Event: break; default: throw new ArgumentOutOfRangeException(); } } if (stmnt == null) { Env.Log (new UnimplementableFeatureMessage (ctxt, "custom attribute", String.Format ("Type '{0}' does not have a field or set-able property for named parameter '{1}'", kv.Key))); } else body.Add(stmnt); } return id.ToE(); }