public TypeRepresentation(InstanceState state, int numExportsBoundToInstance, int numStepsToRootType, JST.Expression keyField, JST.Expression typeClassifier, bool undefininedIsNotNull) { State = state; NumExportsBoundToInstance = numExportsBoundToInstance; NumStepsToRootType = numStepsToRootType; KeyField = keyField; TypeClassifier = typeClassifier; UndefininedIsNotNull = undefininedIsNotNull; }
private void BindBaseTypes(CST.TypeEnvironment thisTypeEnv, JST.Expression thisType) { if (thisTypeEnv.Type.Extends != null) { var baseTypeEnv = thisTypeEnv.Type.Extends.Enter(thisTypeEnv); var baseType = JST.Expression.Dot(thisType, Constants.TypeBaseType); if (!boundTypes.ContainsKey(baseTypeEnv.TypeRef)) { boundTypes.Add(baseTypeEnv.TypeRef, new ExpressionAndPhase(baseType, TypePhase.Slots)); } if (baseTypeEnv.Type.Arity > 0) { if (!boundTypes.ContainsKey(baseTypeEnv.TypeConstructorRef)) { boundTypes.Add(baseTypeEnv.TypeConstructorRef, new ExpressionAndPhase(JST.Expression.Dot(baseType, Constants.TypeApplicand), TypePhase.Slots)); } } BindBaseTypes(baseTypeEnv, baseType); } }
public ExpressionAndPhase(JST.Expression expression, TypePhase phase) { Expression = expression; Phase = phase; }
// ---------------------------------------------------------------------- // Methods // ---------------------------------------------------------------------- // Emit bindings for static or instance methods, but not for virtuals or interface methods // - Invoked from TypeDefinitionCompiler for higher-kinded type definitions // - Invoked from TypeCompiler for first-kinded type definitions public void EmitMethods(Seq <JST.Statement> body, JST.Expression lhs, JST.NameSupply outerNameSupply, JST.Expression target, bool isStatic) { switch (Env.CompilationMode) { case CompilationMode.Plain: { // Method definitions are bound directly into target foreach (var methodDef in Methods.Where(m => m.Invalid == null)) { if (Env.InteropManager.IsStatic(TyconEnv.Assembly, TyconEnv.Type, methodDef) == isStatic) { var compiler = new MethodCompiler(this, outerNameSupply, methodDef, MethodCompilationMode.DirectBind); compiler.Emit(body, target); } } break; } case CompilationMode.Collecting: { // Method definitions are bound into MethodCache, redirectors are bound into target foreach (var methodDef in Methods.Where(m => m.Invalid == null)) { if (Env.InteropManager.IsStatic(TyconEnv.Assembly, TyconEnv.Type, methodDef) == isStatic) { var slot = Env.GlobalMapping.ResolveMethodDefToSlot(TyconEnv.Assembly, TyconEnv.Type, methodDef); var methodName = CST.CSTWriter.WithAppend (Env.Global, CST.WriterStyle.Uniform, methodDef.MethodSignature.Append); body.Add (JST.Statement.DotCall (RootId.ToE(), Constants.RootCollectingBindMethodBuilder, lhs, new JST.BooleanLiteral(isStatic), new JST.StringLiteral(slot), new JST.StringLiteral(methodName))); var compiler = new MethodCompiler(this, outerNameSupply, methodDef, MethodCompilationMode.DirectBind); compiler.Emit(body, JST.Expression.Dot(target, Constants.TypeMethodCache)); } } break; } case CompilationMode.Traced: { // Methods in the initial trace or this trace will be bound directly. // Methods in a trace other than above are bound via builder which is given trace name. // Remaining methods are built via builder with null trace name. var traceToArgs = new Map <string, Seq <JST.Expression> >(); var remainingArgs = new Seq <JST.Expression>(); remainingArgs.Add(TypeDefinitionId.ToE()); remainingArgs.Add(new JST.BooleanLiteral(isStatic)); remainingArgs.Add(new JST.NullExpression()); foreach (var methodDef in Methods.Where(m => m.Invalid == null)) { if (Env.InteropManager.IsStatic(TyconEnv.Assembly, TyconEnv.Type, methodDef) == isStatic) { var slot = Env.GlobalMapping.ResolveMethodDefToSlot(TyconEnv.Assembly, TyconEnv.Type, methodDef); var defTrace = Env.Traces.MethodToTrace[methodDef.QualifiedMemberName(Env.Global, TyconEnv.Assembly, TyconEnv.Type)]; if (defTrace.Flavor == TraceFlavor.OnDemand && defTrace != TypeTrace.Parent.Parent) { // Method definition in in another trace, bind redirector for it. var args = default(Seq <JST.Expression>); if (!traceToArgs.TryGetValue(defTrace.Name, out args)) { args = new Seq <JST.Expression>(); args.Add(lhs); args.Add(new JST.BooleanLiteral(isStatic)); args.Add(new JST.StringLiteral(defTrace.Name)); traceToArgs.Add(defTrace.Name, args); } args.Add(new JST.StringLiteral(slot)); } else if (defTrace.Flavor == TraceFlavor.Remainder) { // Method definition is in a stand-alone loader, bind redirector for it. remainingArgs.Add(new JST.StringLiteral(slot)); } else { // Method definition is bound directly var compiler = new MethodCompiler(this, outerNameSupply, methodDef, MethodCompilationMode.DirectBind); compiler.Emit(body, target); } } } foreach (var kv in traceToArgs) { body.Add(JST.Statement.DotCall(RootId.ToE(), Constants.RootBindMethodBuilders, kv.Value)); } if (remainingArgs.Count > 3) { body.Add(JST.Statement.DotCall(RootId.ToE(), Constants.RootBindMethodBuilders, remainingArgs)); } break; } default: throw new ArgumentOutOfRangeException(); } }