// Trace mode entry point public TypeDefinitionCompiler(AssemblyCompiler parent, TypeTrace typeTrace) { Env = parent.Env; Parent = parent; TyconEnv = parent.AssmEnv.AddType(typeTrace.Type); this.TypeTrace = typeTrace; if (typeTrace.IncludeType && typeTrace.Parent.Parent.Flavor == TraceFlavor.Remainder) { // Create a self-loader fragment file NameSupply = new JST.NameSupply(Constants.Globals); // Will be bound by function passed to root's BindType RootId = NameSupply.GenSym(); AssemblyId = NameSupply.GenSym(); TypeDefinitionId = NameSupply.GenSym(); } else { // Possibly inline type definition and/or method definitions into trace NameSupply = parent.NameSupply; // Already bound by parent RootId = parent.RootId; AssemblyId = parent.AssemblyId; // Will be bound locally TypeDefinitionId = NameSupply.GenSym(); } }
private TypeCompilerEnvironment (CST.Global global, IImSeq <CST.SkolemDef> skolemDefs, CST.AssemblyDef assembly, CST.TypeDef type, IImSeq <CST.TypeRef> typeBoundArguments, CompilerEnvironment env, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeId, IImSeq <JST.Identifier> typeBoundTypeParameterIds, TypeTrace typeTrace) : base( global, skolemDefs, assembly, type, typeBoundArguments) { this.env = env; NameSupply = nameSupply; this.rootId = rootId; this.assemblyId = assemblyId; this.typeId = typeId; TypeBoundTypeParameterIds = typeBoundTypeParameterIds; boundAssemblies = new Map <CST.AssemblyName, JST.Expression>(); boundTypes = new Map <CST.TypeRef, ExpressionAndPhase>(); this.typeTrace = typeTrace; }
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 TypeCompilerEnvironment (CST.Global global, IImSeq<CST.SkolemDef> skolemDefs, CST.AssemblyDef assembly, CST.TypeDef type, IImSeq<CST.TypeRef> typeBoundArguments, CompilerEnvironment env, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeId, IImSeq<JST.Identifier> typeBoundTypeParameterIds, TypeTrace typeTrace) : base( global, skolemDefs, assembly, type, typeBoundArguments) { this.env = env; NameSupply = nameSupply; this.rootId = rootId; this.assemblyId = assemblyId; this.typeId = typeId; TypeBoundTypeParameterIds = typeBoundTypeParameterIds; boundAssemblies = new Map<CST.AssemblyName, JST.Expression>(); boundTypes = new Map<CST.TypeRef, ExpressionAndPhase>(); this.typeTrace = typeTrace; }
// Collecting mode entry point public AssemblyCompiler(CompilerEnvironment env, CST.AssemblyDef assemblyDef) : this(env) { assmEnv = env.Global.Environment().AddAssembly(assemblyDef); assemblyTrace = null; NameSupply = new JST.NameSupply(Constants.Globals); rootId = NameSupply.GenSym(); assemblyId = NameSupply.GenSym(); }
public TraceCompiler(CompilerEnvironment env, Trace trace) { Env = env; Trace = trace; if (trace.Flavor != TraceFlavor.Remainder) { NameSupply = new JST.NameSupply(Constants.Globals); RootId = NameSupply.GenSym(); } }
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); }
// Collecting mode entry point public TypeDefinitionCompiler(AssemblyCompiler parent, CST.TypeDef typeDef) { Env = parent.Env; Parent = parent; TyconEnv = parent.AssmEnv.AddType(typeDef); TypeTrace = null; // Inline type definition and method definitions into overall assembly NameSupply = parent.NameSupply; // Already bound by parent RootId = parent.RootId; AssemblyId = parent.AssemblyId; // Will be bound locally TypeDefinitionId = NameSupply.GenSym(); }
// ---------------------------------------------------------------------- // Methods // ---------------------------------------------------------------------- public JST.Expression MethodCallExpression(CST.MethodRef methodRef, JST.NameSupply localNameSupply, bool isFactory, IImSeq <JST.Expression> arguments) { var groundMethodRef = SubstituteMember(methodRef); if (Method.IsStatic && groundMethodRef.Equals(MethodRef)) { var args = TypeBoundTypeParameterIds.Select(id => id.ToE()).Concat (MethodBoundTypeParameterIds.Select(id => id.ToE())).Concat(arguments).ToSeq(); return(new JST.CallExpression(MethodId.ToE(), args)); } else { return(env.JSTHelpers.DefaultMethodCallExpression (this, localNameSupply, groundMethodRef, isFactory, arguments)); } }
private MethodCompilerEnvironment (CST.Global global, IImSeq <CST.SkolemDef> skolemDefs, CST.AssemblyDef assembly, CST.TypeDef type, IImSeq <CST.TypeRef> typeBoundArguments, CST.MethodDef method, IImSeq <CST.TypeRef> methodBoundArguments, IMap <JST.Identifier, CST.Variable> variables, IImSeq <JST.Identifier> valueParameterIds, IImSeq <JST.Identifier> localIds, CompilerEnvironment env, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeDefinitionId, JST.Identifier methodId, IImSeq <JST.Identifier> typeBoundTypeParameterIds, IImSeq <JST.Identifier> methodBoundTypeParameterIds, TypeTrace typeTrace) : base( global, skolemDefs, assembly, type, typeBoundArguments, method, methodBoundArguments, variables, valueParameterIds, localIds) { this.env = env; NameSupply = nameSupply; this.rootId = rootId; this.assemblyId = assemblyId; this.typeDefinitionId = typeDefinitionId; MethodId = methodId; TypeBoundTypeParameterIds = typeBoundTypeParameterIds; MethodBoundTypeParameterIds = methodBoundTypeParameterIds; boundAssemblies = new Map <CST.AssemblyName, JST.Expression>(); boundTypes = new Map <CST.TypeRef, JST.Expression>(); boundVariablePointers = new Map <JST.Identifier, JST.Expression>(); this.typeTrace = typeTrace; }
// Traced mode entry point public AssemblyCompiler(TraceCompiler parent, AssemblyTrace assemblyTrace) : this(parent.Env) { assmEnv = parent.Env.Global.Environment().AddAssembly(assemblyTrace.Assembly); this.assemblyTrace = assemblyTrace; if (assemblyTrace.Parent.Flavor == TraceFlavor.Remainder) { NameSupply = new JST.NameSupply(Constants.Globals); rootId = NameSupply.GenSym(); assemblyId = NameSupply.GenSym(); } else { NameSupply = parent.NameSupply; rootId = parent.RootId; assemblyId = NameSupply.GenSym(); } }
public static MethodCompilerEnvironment EnterUntranslatedMethod (CompilerEnvironment env, JST.NameSupply outerNameSupply, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeDefinitonId, CST.MethodEnvironment methEnv, TypeTrace typeTrace) { return(EnterMethod (env, outerNameSupply, nameSupply, rootId, assemblyId, typeDefinitonId, methEnv.AddVariables(nameSupply, i => false), typeTrace)); }
// Compile all methods not already compiled by above private void CompileMethods(Seq <JST.Statement> body, JST.NameSupply outerNameSupply) { switch (Env.CompilationMode) { case CompilationMode.Plain: case CompilationMode.Collecting: // Already compiled above return; case CompilationMode.Traced: foreach (var methodDef in Methods.Where(d => TypeTrace.Methods.Contains(d.MethodSignature))) { if (TypeTrace.Parent.Parent.Flavor == TraceFlavor.Remainder) { // Compile method into stand-alone loader var compiler = new MethodCompiler(this, outerNameSupply, methodDef, MethodCompilationMode.SelfContained); compiler.Emit(body, null); } else { // Bind method definition into method cache var target = TypeDefinitionId.ToE(); if (TyconEnv.Type.Arity == 0 && !Env.InteropManager.IsStatic(TyconEnv.Assembly, TyconEnv.Type, methodDef)) { target = JST.Expression.Dot (target, Constants.TypeConstructObject, Constants.prototype); } target = JST.Expression.Dot(target, Constants.TypeMethodCache); var compiler = new MethodCompiler(this, outerNameSupply, methodDef, MethodCompilationMode.DirectBind); compiler.Emit(body, target); } } break; default: throw new ArgumentOutOfRangeException(); } }
public JST.Expression MethodCallExpression(CST.MethodRef methodRef, JST.NameSupply localNameSupply, bool isFactory, params JST.Expression[] arguments) { return(MethodCallExpression(methodRef, localNameSupply, isFactory, new Seq <JST.Expression>(arguments))); }
// ---------------------------------------------------------------------- // 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(); } }
// ---------------------------------------------------------------------- // Methods // ---------------------------------------------------------------------- public JST.Expression MethodCallExpression(CST.MethodRef methodRef, JST.NameSupply localNameSupply, bool isFactory, IImSeq <JST.Expression> arguments) { return(env.JSTHelpers.DefaultMethodCallExpression(this, localNameSupply, methodRef, isFactory, arguments)); }
public static MethodCompilerEnvironment EnterMethod (CompilerEnvironment env, JST.NameSupply outerNameSupply, JST.NameSupply nameSupply, JST.Identifier rootId, JST.Identifier assemblyId, JST.Identifier typeDefinitonId, CST.CompilationEnvironment compEnv, TypeTrace typeTrace) { // BUG: IE messes up scoping for function identifiers. To compensate we must allocate its // identifier in the outer scope var methodId = outerNameSupply.GenSym(); if (env.DebugMode) { var sb = new StringBuilder(); sb.Append(methodId.Value); sb.Append('_'); var namedTypeDef = compEnv.Type as CST.NamedTypeDef; if (namedTypeDef != null) { if (namedTypeDef.Name.Namespace.Length > 0) { JST.Lexemes.AppendStringToIdentifier(sb, namedTypeDef.Name.Namespace.Replace('.', '_')); sb.Append('_'); } foreach (var n in namedTypeDef.Name.Types) { JST.Lexemes.AppendStringToIdentifier(sb, n); sb.Append('_'); } } JST.Lexemes.AppendStringToIdentifier(sb, compEnv.Method.Name); methodId = new JST.Identifier(sb.ToString()); } var typeBoundTypeParameterIds = new Seq <JST.Identifier>(); for (var i = 0; i < compEnv.Type.Arity; i++) { typeBoundTypeParameterIds.Add(nameSupply.GenSym()); } var methodBoundTypeParameterIds = new Seq <JST.Identifier>(); for (var i = 0; i < compEnv.Method.TypeArity; i++) { methodBoundTypeParameterIds.Add(nameSupply.GenSym()); } var res = new MethodCompilerEnvironment (compEnv.Global, compEnv.SkolemDefs, compEnv.Assembly, compEnv.Type, compEnv.TypeBoundArguments, compEnv.Method, compEnv.MethodBoundArguments, compEnv.Variables, compEnv.ValueParameterIds, compEnv.LocalIds, env, nameSupply, rootId, assemblyId, typeDefinitonId, methodId, typeBoundTypeParameterIds, methodBoundTypeParameterIds, typeTrace); res.BindSpecial(); return(res); }