diff --git a/src/compiler/core/Compiler.cs b/src/compiler/core/Compiler.cs index a3dbb0c4e..e6b93efcd 100644 --- a/src/compiler/core/Compiler.cs +++ b/src/compiler/core/Compiler.cs @@ -49,6 +49,7 @@ public class Compiler : LogObject, ICompiler, IScheduler public readonly NameResolver NameResolver; // Building + public readonly BuildQueue Queue; public readonly BlockBuilder BlockBuilder; public readonly BundleBuilder BundleBuilder; public readonly TypeBuilder TypeBuilder; @@ -91,8 +92,9 @@ public Compiler(Log log, Backend backend, SourceBundle bundle, CompilerOptions o var data = Data = new BuildData(il, extensions, ilf); var environment = Environment = new BuildEnvironment(backend, bundle, options, extensions, ilf, this); var input = Input = new SourceReader(log, bundle, environment); - var blockBuilder = BlockBuilder = new BlockBuilder(backend, il, ilf, resolver, this); - var typeBuilder = TypeBuilder = new TypeBuilder(environment, ilf, resolver, this); + var queue = Queue = new BuildQueue(log, environment, backend, this); + var blockBuilder = BlockBuilder = new BlockBuilder(backend, il, ilf, resolver, this, queue); + var typeBuilder = TypeBuilder = new TypeBuilder(environment, ilf, resolver, this, queue); BundleBuilder = new BundleBuilder(backend, environment, ilf, this); AstProcessor = new AstProcessor(il, blockBuilder, typeBuilder, resolver, environment); UxlProcessor = new UxlProcessor(disk, backend.Name, il, extensions, environment, ilf); @@ -132,20 +134,23 @@ public void Compile() if (Backend.CanLink(bundle)) bundle.Flags |= SourceBundleFlags.CanLink; - using (Log.StartProfiler(TypeBuilder)) - TypeBuilder.Build(); + using (Log.StartProfiler(Queue)) + Queue.BuildTypesAndFunctions(); + if (Log.HasErrors) return; - Backend.ShaderBackend.Initialize(this, BundleBuilder); + using (Log.StartProfiler(UxlProcessor)) + UxlProcessor.CompileDocuments(); - using (Log.StartProfiler(BlockBuilder)) - BlockBuilder.Build(); if (Log.HasErrors) return; - using (Log.StartProfiler(UxlProcessor)) - UxlProcessor.CompileDocuments(); + Backend.ShaderBackend.Initialize(this, BundleBuilder); + + using (Log.StartProfiler(Queue)) + Queue.BuildEverything(); + if (Log.HasErrors) return; @@ -205,7 +210,6 @@ public BackendResult Generate(Action callback) UxlProcessor.CompileRequirements(); ILStripper.Begin(); Run(_transforms); - TypeBuilder.BuildTypes(); using (Log.StartProfiler(ILStripper)) ILStripper.End(); diff --git a/src/compiler/core/IL/EntitySwapper.cs b/src/compiler/core/IL/EntitySwapper.cs index 95f7cd5d6..b729aea9f 100644 --- a/src/compiler/core/IL/EntitySwapper.cs +++ b/src/compiler/core/IL/EntitySwapper.cs @@ -65,7 +65,6 @@ DataType GetTypeInternal(DataType dt) args[i] = GetType(dt.FlattenedArguments[i]); result = TypeBuilder.Parameterize(result.Source, def, args); - TypeBuilder.BuildTypes(); SwapTypes.Add(dt, result); return result; } @@ -99,7 +98,6 @@ DataType GetTypeInternal(DataType dt) var def = result.IsGenericDefinition ? result : GetType(dt.GenericDefinition); result = TypeBuilder.Parameterize(dt.Source, def, args); - TypeBuilder.BuildTypes(); } SwapTypes.Add(dt, result); diff --git a/src/compiler/core/Syntax/Builders/BlockBuilder.CompileDraw.cs b/src/compiler/core/Syntax/Builders/BlockBuilder.CompileDraw.cs index d0e4ecf13..135ecb723 100644 --- a/src/compiler/core/Syntax/Builders/BlockBuilder.CompileDraw.cs +++ b/src/compiler/core/Syntax/Builders/BlockBuilder.CompileDraw.cs @@ -32,10 +32,8 @@ public Statement CompileDraw(Function func, List vscopeStack, Ast var result = new DrawBlock(draw.Source, parent, method, FlattenVariableScopes(vscopeStack)); method.DrawBlocks.Add(result); - - EnqueueBlock(result, x => PopulateBlock(draw.Block, x)); - _enqueuedDrawClasses.Add(method.DeclaringType); - + _queue.EnqueueBlock(result, x => PopulateBlock(draw.Block, x)); + _queue.EnqueueDrawClass(method.DeclaringType); return result.DrawScope; } diff --git a/src/compiler/core/Syntax/Builders/BlockBuilder.CreateBlock.cs b/src/compiler/core/Syntax/Builders/BlockBuilder.CreateBlock.cs index ffd352452..ff482a996 100644 --- a/src/compiler/core/Syntax/Builders/BlockBuilder.CreateBlock.cs +++ b/src/compiler/core/Syntax/Builders/BlockBuilder.CreateBlock.cs @@ -30,8 +30,7 @@ public Block CreateBlock(AstBlock ast, Namescope parent) Log.Error(src, ErrorCode.E3214, "Block declaration is not allowed in this scope"); _processedBlocks.Add(ast, result); - EnqueueBlock(result, x => PopulateBlock(ast, x)); - + _queue.EnqueueBlock(result, x => PopulateBlock(ast, x)); return result; } @@ -76,7 +75,7 @@ MetaBlock CreateNodeBlock(AstNode ast, BlockBase parent) return MetaBlock.Invalid; } - EnqueueBlock(result, x => PopulateBlock(ast, x)); + _queue.EnqueueBlock(result, x => PopulateBlock(ast, x)); return result; } } diff --git a/src/compiler/core/Syntax/Builders/BlockBuilder.CreateMetaProperty.cs b/src/compiler/core/Syntax/Builders/BlockBuilder.CreateMetaProperty.cs index 6826b3cad..06e46e792 100644 --- a/src/compiler/core/Syntax/Builders/BlockBuilder.CreateMetaProperty.cs +++ b/src/compiler/core/Syntax/Builders/BlockBuilder.CreateMetaProperty.cs @@ -58,12 +58,11 @@ MetaProperty CreateMetaProperty(AstMetaProperty ast, BlockBase parent) } var result = new MetaProperty(ast.Name.Source, parent, dt, ast.Name.Symbol, visibility); - _enqueuedProperties.Add(new KeyValuePair(ast, result)); - + _queue.EnqueueMetaProperty(ast, result); return result; } - void CompileMetaPropertyDefinitions(AstMetaProperty ast, MetaProperty mp) + internal void CompileMetaPropertyDefinitions(AstMetaProperty ast, MetaProperty mp) { var defs = new MetaDefinition[ast.Definitions.Count]; diff --git a/src/compiler/core/Syntax/Builders/BlockBuilder.FlattenType.cs b/src/compiler/core/Syntax/Builders/BlockBuilder.FlattenType.cs index a07ba3380..aba745493 100644 --- a/src/compiler/core/Syntax/Builders/BlockBuilder.FlattenType.cs +++ b/src/compiler/core/Syntax/Builders/BlockBuilder.FlattenType.cs @@ -8,7 +8,7 @@ public partial class BlockBuilder { internal readonly Dictionary> FlattenedTypes = new Dictionary>(); - void FlattenTypes() + internal void FlattenTypes() { FlattenTypes(_il); diff --git a/src/compiler/core/Syntax/Builders/BlockBuilder.cs b/src/compiler/core/Syntax/Builders/BlockBuilder.cs index f8539f08c..4c8330d11 100644 --- a/src/compiler/core/Syntax/Builders/BlockBuilder.cs +++ b/src/compiler/core/Syntax/Builders/BlockBuilder.cs @@ -22,20 +22,19 @@ public partial class BlockBuilder : LogObject readonly ILFactory _ilf; readonly NameResolver _resolver; readonly Compiler _compiler; + readonly BuildQueue _queue; readonly Dictionary _processedBlocks = new Dictionary(); - readonly List _enqueuedBlocks = new List(); - readonly List> _enqueuedProperties = new List>(); - readonly HashSet _enqueuedDrawClasses = new HashSet(); Block _terminals; readonly HashSet _terminalNames = new HashSet(); - public BlockBuilder( + internal BlockBuilder( Backend backend, Namespace il, ILFactory ilf, NameResolver resolver, - Compiler compiler) + Compiler compiler, + BuildQueue queue) : base(compiler) { _backend = backend; @@ -43,33 +42,7 @@ public BlockBuilder( _ilf = ilf; _resolver = resolver; _compiler = compiler; - } - - void EnqueueBlock(BlockBase b, Action populate) - { - b.Populating = populate; - _enqueuedBlocks.Add(b); - } - - public void Build() - { - FlattenTypes(); - - for (int i = 0; i < _enqueuedBlocks.Count; i++) - if (!_enqueuedBlocks[i].Source.Bundle.CanLink) - _enqueuedBlocks[i].Populate(); - - _enqueuedBlocks.Clear(); - - for (int i = 0; i < _enqueuedProperties.Count; i++) - CompileMetaPropertyDefinitions(_enqueuedProperties[i].Key, _enqueuedProperties[i].Value); - - _enqueuedProperties.Clear(); - - foreach (var dt in _enqueuedDrawClasses) - DrawCallGenerator.GenerateDrawCalls(_compiler, dt); - - _enqueuedDrawClasses.Clear(); + _queue = queue; } public Block TerminalProperties @@ -83,7 +56,6 @@ public Block TerminalProperties foreach (var t in _backend.ShaderBackend.InputProperties) CompileTerminalProperty(t); - foreach (var t in _backend.ShaderBackend.OutputProperties) CompileTerminalProperty(t); } diff --git a/src/compiler/core/Syntax/Builders/BuildQueue.cs b/src/compiler/core/Syntax/Builders/BuildQueue.cs new file mode 100644 index 000000000..66dc233ad --- /dev/null +++ b/src/compiler/core/Syntax/Builders/BuildQueue.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using Uno.Compiler.API.Backends; +using Uno.Compiler.API.Domain.AST.Members; +using Uno.Compiler.API.Domain.AST.Statements; +using Uno.Compiler.API.Domain.Graphics; +using Uno.Compiler.API.Domain.IL; +using Uno.Compiler.API.Domain.IL.Members; +using Uno.Compiler.Core.Syntax.Compilers; +using Uno.Compiler.Core.Syntax.Generators; +using Uno.Logging; + +namespace Uno.Compiler.Core.Syntax.Builders +{ + public class BuildQueue : LogObject + { + readonly BuildEnvironment _env; + readonly Backend _backend; + readonly Compiler _compiler; + readonly List _enqueuedBlocks = new List(); + readonly List> _enqueuedMetaProperties = new List>(); + readonly HashSet _enqueuedDrawClasses = new HashSet(); + readonly List _enqueuedFunctions = new List(); + readonly List _enqueuedAttributes = new List(); + readonly List _enqueuedTypes = new List(); + readonly List _enqueuedActions = new List(); + int _assignBaseTypeIndex; + int _populateMembersIndex; + + public BuildQueue(Log log, BuildEnvironment env, Backend backend, Compiler compiler) + : base(log) + { + _env = env; + _backend = backend; + _compiler = compiler; + } + + internal FunctionCompiler EnqueueFunction(Function func, DataType parameterizedParent, AstScope body) + { + var fc = new FunctionCompiler(_compiler, func, parameterizedParent, body); + func.Tag = fc; + + if (_env.IsGeneratingCode) + func.Stats |= EntityStats.CanLink; + else if (body != null) + _enqueuedFunctions.Add(fc); + else if (_compiler.Backend.CanLink(func)) + func.Stats |= EntityStats.CanLink; + + return fc; + } + + internal void EnqueueDrawClass(DataType declaringType) + { + _enqueuedDrawClasses.Add(declaringType); + } + + internal void EnqueueType(DataType dt, Action assignBaseType, Action populate) + { + if (_env.IsGeneratingCode) + { + assignBaseType(dt); + populate(dt); + return; + } + + dt.AssigningBaseType = assignBaseType; + dt.PopulatingMembers = x => + { + populate(x); + x.Stats &= ~EntityStats.PopulatingMembers; + }; + dt.Stats |= EntityStats.PopulatingMembers; + _enqueuedTypes.Add(dt); + } + + internal void EnqueueAttributes(Entity e, Action assign) + { + e.AssigningAttributes = assign; + _enqueuedAttributes.Add(e); + } + + internal void EnqueueAttributes(Member e, DataType parameterizedParent, IReadOnlyList attributes) + { + if (attributes.Count > 0) + EnqueueAttributes(e, x => e.SetAttributes(_compiler.CompileAttributes(parameterizedParent, attributes))); + } + + public void BuildTypes() + { + for (int count = 0, j = 0; count != _enqueuedTypes.Count && j < 10; j++) + { + count = _enqueuedTypes.Count; + + while (_assignBaseTypeIndex < count) + _enqueuedTypes[_assignBaseTypeIndex++].AssignBaseType(); + + for (int i = 0; i < _enqueuedAttributes.Count; i++) + _enqueuedAttributes[i].AssignAttributes(); + + _enqueuedAttributes.Clear(); + + while (_populateMembersIndex < count) + if (_backend.CanLink(_enqueuedTypes[_populateMembersIndex])) + _enqueuedTypes[_populateMembersIndex++].Stats |= EntityStats.CanLink; + else + _enqueuedTypes[_populateMembersIndex++].PopulateMembers(); + + for (int i = 0; i < _enqueuedActions.Count; i++) + _enqueuedActions[i](); + + _enqueuedActions.Clear(); + } + + for (; _populateMembersIndex < _enqueuedTypes.Count; _populateMembersIndex++) + Log.Warning(_enqueuedTypes[_populateMembersIndex].Source, ErrorCode.I0000, "Unable to parameterize " + _enqueuedTypes[_populateMembersIndex].Quote()); + + _assignBaseTypeIndex = _populateMembersIndex; + } + + public void BuildTypesAndFunctions() + { + BuildTypes(); + + for (var i = 0; i < _enqueuedFunctions.Count; i++) + { + _enqueuedFunctions[i].Compile(); + BuildTypes(); + } + + _enqueuedFunctions.Clear(); + _enqueuedTypes.Clear(); + + _assignBaseTypeIndex = 0; + _populateMembersIndex = 0; + } + + public void BuildEverything() + { + _compiler.BlockBuilder.FlattenTypes(); + + do + { + BuildTypesAndFunctions(); + BuildBlocks(); + BuildMetaProperties(); + + foreach (var dt in _enqueuedDrawClasses) + DrawCallGenerator.GenerateDrawCalls(_compiler, dt); + + _enqueuedDrawClasses.Clear(); + + } while (_enqueuedFunctions.Count > 0); + } + + public void BuildBlocks() + { + for (var i = 0; i < _enqueuedBlocks.Count; i++) + if (!_enqueuedBlocks[i].Source.Bundle.CanLink) + _enqueuedBlocks[i].Populate(); + + _enqueuedBlocks.Clear(); + } + + internal void EnqueueBlock(BlockBase b, Action populate) + { + b.Populating = populate; + _enqueuedBlocks.Add(b); + } + + public void BuildMetaProperties() + { + for (var i = 0; i < _enqueuedMetaProperties.Count; i++) + _compiler.BlockBuilder.CompileMetaPropertyDefinitions(_enqueuedMetaProperties[i].Key, _enqueuedMetaProperties[i].Value); + + _enqueuedMetaProperties.Clear(); + } + + public void EnqueueMetaProperty(AstMetaProperty ast, MetaProperty result) + { + _enqueuedMetaProperties.Add(new KeyValuePair(ast, result)); + } + + internal void Enqueue(Action action) + { + _enqueuedActions.Add(action); + } + } +} \ No newline at end of file diff --git a/src/compiler/core/Syntax/Builders/TypeBuilder.CreateClass.cs b/src/compiler/core/Syntax/Builders/TypeBuilder.CreateClass.cs index e9d471105..6bd6dd8ab 100644 --- a/src/compiler/core/Syntax/Builders/TypeBuilder.CreateClass.cs +++ b/src/compiler/core/Syntax/Builders/TypeBuilder.CreateClass.cs @@ -68,9 +68,9 @@ public void CreateClass(AstClass astClass, Namescope parent, IEnumerable 0) - EnqueueAttributes(result, x => + _queue.EnqueueAttributes(result, x => { - result.SetAttributes(_compiler.CompileAttributes(result.Parent, astClass.Attributes)); + result.SetAttributes(_compiler.CompileAttributes(parent, astClass.Attributes)); // Remove default constructor if TargetSpecificType if (result.HasAttribute(_ilf.Essentials.TargetSpecificTypeAttribute) && @@ -78,7 +78,7 @@ public void CreateClass(AstClass astClass, Namescope parent, IEnumerable CompileBaseTypes(x, astClass.Bases), x => PopulateClass(astClass, x)); } diff --git a/src/compiler/core/Syntax/Builders/TypeBuilder.CreateDelegate.cs b/src/compiler/core/Syntax/Builders/TypeBuilder.CreateDelegate.cs index 45043b0f9..f71510624 100644 --- a/src/compiler/core/Syntax/Builders/TypeBuilder.CreateDelegate.cs +++ b/src/compiler/core/Syntax/Builders/TypeBuilder.CreateDelegate.cs @@ -29,23 +29,23 @@ public void CreateDelegate(AstDelegate ast, Namescope parent) Log.Error(src, ErrorCode.I3019, "'delegate' cannot contain members"); if (ast.Attributes.Count > 0) - EnqueueAttributes(result, - x => result.SetAttributes(_compiler.CompileAttributes(result.Parent, ast.Attributes))); + _queue.EnqueueAttributes(result, + _ => result.SetAttributes(_compiler.CompileAttributes(parent, ast.Attributes))); - EnqueueType(result, + _queue.EnqueueType(result, assignBaseType: x => { var deferredActions = new List(); - var parameterizedType = Parameterize(result); + var parameterizedType = Parameterize(x); result.SetBase(_ilf.Essentials.Delegate); - result.SetReturnType(_resolver.GetType(result, ast.ReturnType)); - result.SetParameters(_compiler.CompileParameterList(result, ast.Parameters, deferredActions)); + result.SetReturnType(_resolver.GetType(x, ast.ReturnType)); + result.SetParameters(_compiler.CompileParameterList(x, ast.Parameters, deferredActions)); if (parameterizedType != result) { var parameterizedDelegate = (DelegateType)parameterizedType; - parameterizedDelegate.SetBase(result.Base); + parameterizedDelegate.SetBase(x.Base); parameterizedDelegate.SetReturnType(result.ReturnType); parameterizedDelegate.SetParameters(result.Parameters); } diff --git a/src/compiler/core/Syntax/Builders/TypeBuilder.CreateEnum.cs b/src/compiler/core/Syntax/Builders/TypeBuilder.CreateEnum.cs index edfacf516..24efa8ed2 100644 --- a/src/compiler/core/Syntax/Builders/TypeBuilder.CreateEnum.cs +++ b/src/compiler/core/Syntax/Builders/TypeBuilder.CreateEnum.cs @@ -39,10 +39,10 @@ public void CreateEnum(AstEnum ast, Namescope parent) Log.Error(result.Source, ErrorCode.I3037, "'enum' is not allowed in this context"); if (ast.Attributes.Count > 0) - EnqueueAttributes(result, - x => result.SetAttributes(_compiler.CompileAttributes(result.Parent, ast.Attributes))); + _queue.EnqueueAttributes(result, + _ => result.SetAttributes(_compiler.CompileAttributes(parent, ast.Attributes))); - EnqueueType(result, + _queue.EnqueueType(result, assignBaseType: x => { x.SetBase(ast.OptionalBaseType != null @@ -102,7 +102,7 @@ public void CreateEnum(AstEnum ast, Namescope parent) s.DocComment, Modifiers.Public, parameterizedType, TypedEnumValue(parameterizedType.Base, value)); if (s.Attributes.Count > 0) - EnqueueAttributes(literal, + _queue.EnqueueAttributes(literal, _ => literal.SetAttributes(_compiler.CompileAttributes(result, s.Attributes))); result.Literals.Add(literal); diff --git a/src/compiler/core/Syntax/Builders/TypeBuilder.Parameterize.cs b/src/compiler/core/Syntax/Builders/TypeBuilder.Parameterize.cs index 23bf9fc19..91115e3c1 100644 --- a/src/compiler/core/Syntax/Builders/TypeBuilder.Parameterize.cs +++ b/src/compiler/core/Syntax/Builders/TypeBuilder.Parameterize.cs @@ -186,9 +186,10 @@ public DataType Parameterize(Source src, DataType definition, params DataType[] result.SetMasterDefinition(definition.MasterDefinition); ParameterizeInnerTypes(definition, definition, map, result); - EnqueueType(result, + _queue.EnqueueType(result, x => ParameterizeBaseType(definition, map, x), x => ParameterizeMembers(definition, definition, map, x)); + return result; } @@ -292,7 +293,7 @@ DataType ParameterizeType(Dictionary map, DataType arg) if (result != null) { - map.Add(arg, result); + map[arg] = result; return result; } @@ -361,17 +362,23 @@ void ParameterizeInnerTypes(DataType definition, DataType current, Dictionary ParameterizeBaseType(e, map, x), x => ParameterizeMembers(definition, e, map, x)); + } + + for (int i = 0; i < current.NestedTypes.Count; i++) + { + var e = current.NestedTypes[i]; + var t = result.NestedTypes[i]; ParameterizeInnerTypes(definition, e, map, t); - result.NestedTypes.Add(t); } } diff --git a/src/compiler/core/Syntax/Builders/TypeBuilder.PopulateClass.cs b/src/compiler/core/Syntax/Builders/TypeBuilder.PopulateClass.cs index 208e0b154..1e0ef3616 100644 --- a/src/compiler/core/Syntax/Builders/TypeBuilder.PopulateClass.cs +++ b/src/compiler/core/Syntax/Builders/TypeBuilder.PopulateClass.cs @@ -52,15 +52,11 @@ void PopulateClass(AstClass astClass, DataType result) var pl = _compiler.CompileParameterList(gt ?? parameterizedType, md.Parameters, deferredActions); var rt = _resolver.GetType(gt ?? parameterizedType, md.ReturnType); var me = new Method(md.Name.Source, result, md.DocComment, GetMemberModifiers(md.Name.Source, parameterizedType, md.Modifiers), md.Name.Symbol, gt, rt, pl); + _queue.EnqueueAttributes(me, parameterizedType, md.Attributes); + _queue.EnqueueFunction(me, parameterizedType, md.OptionalBody); result.Methods.Add(me); - - if (md.Attributes.Count > 0) - EnqueueAttributes(me, x => me.SetAttributes(_compiler.CompileAttributes(parameterizedType, md.Attributes))); - gt?.Methods.Add(me); - EnqueueCompiler(new FunctionCompiler(_compiler, me, parameterizedType, md.OptionalBody)); - if (md.OptionalInterfaceType != null) { var it = _resolver.GetType(parameterizedType, md.OptionalInterfaceType); @@ -96,12 +92,8 @@ void PopulateClass(AstClass astClass, DataType result) var md = item as AstConstructor; var pl = _compiler.CompileParameterList(parameterizedType, md.Parameters, deferredActions); var ctor = new Constructor(md.Source, result, md.DocComment, md.Modifiers, pl); - - if (md.Attributes.Count > 0) - EnqueueAttributes(ctor, x => ctor.SetAttributes(_compiler.CompileAttributes(parameterizedType, md.Attributes))); - - var fc = new FunctionCompiler(_compiler, ctor, parameterizedType, md.OptionalBody); - EnqueueCompiler(fc); + var fc = _queue.EnqueueFunction(ctor, parameterizedType, md.OptionalBody); + _queue.EnqueueAttributes(ctor, parameterizedType, md.Attributes); if (ctor.IsStatic) { @@ -128,7 +120,8 @@ void PopulateClass(AstClass astClass, DataType result) if (ctor.Body == null) Log.Error(md.Source, ErrorCode.E0000, ctor.Quote() + " cannot call constructor without method body"); else if (md.CallType != AstConstructorCallType.Base || parameterizedType.Base != DataType.Invalid) - _enqueuedActions.Add(() => + _queue.Enqueue( + () => { var bt = md.CallType == AstConstructorCallType.Base ? parameterizedType.Base : parameterizedType; bt.PopulateMembers(); @@ -145,8 +138,8 @@ void PopulateClass(AstClass astClass, DataType result) parameterizedType.Base != null && parameterizedType.TypeType != TypeType.Struct && ctor.Body != null) - { - _enqueuedActions.Add(() => + _queue.Enqueue( + () => { Constructor callCtor; Expression[] callArgs; @@ -155,7 +148,6 @@ void PopulateClass(AstClass astClass, DataType result) else ctor.Body.Statements.Add(new CallConstructor(md.Source, callCtor, callArgs)); }); - } break; } case AstMemberType.Finalizer: @@ -163,15 +155,13 @@ void PopulateClass(AstClass astClass, DataType result) var fd = item as AstFinalizer; var pl = _compiler.CompileParameterList(parameterizedType, fd.Parameters, deferredActions); var finalizer = new Finalizer(fd.Source, result, fd.DocComment, fd.Modifiers, pl); - - if (fd.Attributes.Count > 0) - EnqueueAttributes(finalizer, x => finalizer.SetAttributes(_compiler.CompileAttributes(parameterizedType, fd.Attributes))); + _queue.EnqueueAttributes(finalizer, parameterizedType, fd.Attributes); + _queue.EnqueueFunction(finalizer, parameterizedType, fd.OptionalBody); if (result.Finalizer != null) Log.Error(fd.Source, ErrorCode.E3002, parameterizedType.Quote() + " already has a finalizer"); result.Finalizer = finalizer; - EnqueueCompiler(new FunctionCompiler(_compiler, finalizer, parameterizedType, fd.OptionalBody)); break; } case AstMemberType.Property: @@ -203,24 +193,21 @@ void PopulateClass(AstClass astClass, DataType result) { prop.CreateImplicitField(prop.Source); - var getScope = new Scope(pd.Get.Source); - prop.CreateGetMethod(pd.Get.Source, GetAccessorModifiers(pd.Get.Source, prop, pd.Get.Modifiers) | Modifiers.Generated, getScope); - - var setScope = new Scope(pd.Set.Source); - var setMethod = prop.CreateSetMethod(pd.Set.Source, GetAccessorModifiers(pd.Set.Source, prop, pd.Set.Modifiers) | Modifiers.Generated, setScope); + var getMethod = prop.CreateGetMethod(pd.Get.Source, GetAccessorModifiers(pd.Get.Source, prop, pd.Get.Modifiers) | Modifiers.Generated); + var setMethod = prop.CreateSetMethod(pd.Set.Source, GetAccessorModifiers(pd.Set.Source, prop, pd.Set.Modifiers) | Modifiers.Generated); var propIndex = result.Properties.Count - 1; - - _enqueuedActions.Add(() => + _queue.Enqueue( + () => { parameterizedType.PopulateMembers(); var obj = prop.Modifiers.HasFlag(Modifiers.Static) ? null : new This(prop.Source, parameterizedType).Address; var field = parameterizedType.Properties[propIndex].ImplicitField; - getScope.Statements.Add( - new Return(pd.Get.Source, new LoadField(pd.Get.Source, obj, field))); - setScope.Statements.Add( - new StoreField(pd.Set.Source, obj, field, new LoadArgument(pd.Set.Source, setMethod, 0))); + getMethod.SetBody(new Scope(pd.Get.Source, + new Return(pd.Get.Source, new LoadField(pd.Get.Source, obj, field)))); + setMethod.SetBody(new Scope(pd.Set.Source, + new StoreField(pd.Set.Source, obj, field, new LoadArgument(pd.Set.Source, setMethod, 0)))); }); hasImplicitImplementation = true; @@ -229,7 +216,7 @@ void PopulateClass(AstClass astClass, DataType result) } if (pd.Attributes.Count > 0) - EnqueueAttributes(prop, + _queue.EnqueueAttributes(prop, x => { prop.SetAttributes(_compiler.CompileAttributes(parameterizedType, pd.Attributes)); @@ -241,9 +228,9 @@ void PopulateClass(AstClass astClass, DataType result) if (!hasImplicitImplementation) { if (pd.Get != null) - EnqueueCompiler(new FunctionCompiler(_compiler, prop.CreateGetMethod(pd.Get.Source, GetAccessorModifiers(pd.Get.Source, prop, pd.Get.Modifiers)), parameterizedType, pd.Get.OptionalBody)); + _queue.EnqueueFunction(prop.CreateGetMethod(pd.Get.Source, GetAccessorModifiers(pd.Get.Source, prop, pd.Get.Modifiers)), parameterizedType, pd.Get.OptionalBody); if (pd.Set != null) - EnqueueCompiler(new FunctionCompiler(_compiler, prop.CreateSetMethod(pd.Set.Source, GetAccessorModifiers(pd.Set.Source, prop, pd.Set.Modifiers)), parameterizedType, pd.Set.OptionalBody)); + _queue.EnqueueFunction(prop.CreateSetMethod(pd.Set.Source, GetAccessorModifiers(pd.Set.Source, prop, pd.Set.Modifiers)), parameterizedType, pd.Set.OptionalBody); } if (pd.OptionalInterfaceType != null) @@ -270,11 +257,9 @@ void PopulateClass(AstClass astClass, DataType result) if (f.FieldModifiers.HasFlag(FieldModifiers.Const)) { var m = new Literal(f.Name.Source, result, f.Name.Symbol, f.DocComment, GetMemberModifiers(f.Name.Source, parameterizedType, f.Modifiers), dt, f.InitValue); + _queue.EnqueueAttributes(m, parameterizedType, f.Attributes); result.Literals.Add(m); - if (f.Attributes.Count > 0) - EnqueueAttributes(m, x => m.SetAttributes(_compiler.CompileAttributes(parameterizedType, f.Attributes))); - if (f.InitValue == null) Log.Error(f.Name.Source, ErrorCode.E3007, "'const' fields must provide a constant value"); else @@ -283,11 +268,9 @@ void PopulateClass(AstClass astClass, DataType result) else { var m = new Field(f.Name.Source, result, f.Name.Symbol, f.DocComment, GetMemberModifiers(f.Name.Source, parameterizedType, f.Modifiers), f.FieldModifiers, dt); + _queue.EnqueueAttributes(m, parameterizedType, f.Attributes); fieldInitializers.Add(f.InitValue); result.Fields.Add(m); - - if (f.Attributes.Count > 0) - EnqueueAttributes(m, x => m.SetAttributes(_compiler.CompileAttributes(parameterizedType, f.Attributes))); } break; } @@ -297,12 +280,9 @@ void PopulateClass(AstClass astClass, DataType result) var rt = _resolver.GetType(parameterizedType, od.ReturnType); var pl = _compiler.CompileParameterList(parameterizedType, od.Parameters, deferredActions); var op = new Operator(od.Source, result, od.Operator, od.DocComment, GetMemberModifiers(od.Source, parameterizedType, od.Modifiers), rt, pl); + _queue.EnqueueAttributes(op, parameterizedType, od.Attributes); + _queue.EnqueueFunction(op, parameterizedType, od.OptionalBody); result.Operators.Add(op); - - if (od.Attributes.Count > 0) - EnqueueAttributes(op, x => op.SetAttributes(_compiler.CompileAttributes(parameterizedType, od.Attributes))); - - EnqueueCompiler(new FunctionCompiler(_compiler, op, parameterizedType, od.OptionalBody)); break; } case AstMemberType.Converter: @@ -312,12 +292,9 @@ void PopulateClass(AstClass astClass, DataType result) var pl = _compiler.CompileParameterList(parameterizedType, cd.Parameters, deferredActions); var type = cd.Modifiers.HasFlag(Modifiers.Implicit) ? CastModifier.Implicit : CastModifier.Explicit; var cast = new Cast(cd.TargetType.Source, result, type, cd.DocComment, GetMemberModifiers(cd.TargetType.Source, parameterizedType, cd.Modifiers), rt, pl); + _queue.EnqueueAttributes(cast, parameterizedType, cd.Attributes); + _queue.EnqueueFunction(cast, parameterizedType, cd.OptionalBody); result.Casts.Add(cast); - - if (cd.Attributes.Count > 0) - EnqueueAttributes(cast, x => cast.SetAttributes(_compiler.CompileAttributes(parameterizedType, cd.Attributes))); - - EnqueueCompiler(new FunctionCompiler(_compiler, cast, parameterizedType, cd.OptionalBody)); break; } case AstMemberType.Indexer: @@ -329,7 +306,8 @@ void PopulateClass(AstClass astClass, DataType result) result.Properties.Add(indexer); if (id.Attributes.Count > 0) - EnqueueAttributes(indexer, + _queue.EnqueueAttributes( + indexer, x => { indexer.SetAttributes(_compiler.CompileAttributes(parameterizedType, id.Attributes)); @@ -338,9 +316,13 @@ void PopulateClass(AstClass astClass, DataType result) }); if (id.Get != null) - EnqueueCompiler(new FunctionCompiler(_compiler, indexer.CreateGetMethod(id.Get.Source, GetAccessorModifiers(id.Get.Source, indexer, id.Get.Modifiers)), parameterizedType, id.Get.OptionalBody)); + _queue.EnqueueFunction( + indexer.CreateGetMethod(id.Get.Source, GetAccessorModifiers(id.Get.Source, indexer, id.Get.Modifiers)), + parameterizedType, id.Get.OptionalBody); if (id.Set != null) - EnqueueCompiler(new FunctionCompiler(_compiler, indexer.CreateSetMethod(id.Set.Source, GetAccessorModifiers(id.Set.Source, indexer, id.Set.Modifiers)), parameterizedType, id.Set.OptionalBody)); + _queue.EnqueueFunction( + indexer.CreateSetMethod(id.Set.Source, GetAccessorModifiers(id.Set.Source, indexer, id.Set.Modifiers)), + parameterizedType, id.Set.OptionalBody); if (id.OptionalInterfaceType != null) { @@ -373,7 +355,7 @@ void PopulateClass(AstClass astClass, DataType result) result.Events.Add(ev); if (ed.Attributes.Count > 0) - EnqueueAttributes(ev, + _queue.EnqueueAttributes(ev, x => { ev.SetAttributes(_compiler.CompileAttributes(parameterizedType, ed.Attributes)); @@ -388,31 +370,32 @@ void PopulateClass(AstClass astClass, DataType result) { ev.CreateImplicitField(ed.Name.Source); - var addScope = new Scope(ed.Name.Source); - var addMethod = ev.CreateAddMethod(ev.Source, ev.Modifiers | Modifiers.Generated, addScope); - var removeScope = new Scope(ed.Name.Source); - var removeMethod = ev.CreateRemoveMethod(ev.Source, ev.Modifiers | Modifiers.Generated, removeScope); + var addMethod = ev.CreateAddMethod(ev.Source, ev.Modifiers | Modifiers.Generated); + var removeMethod = ev.CreateRemoveMethod(ev.Source, ev.Modifiers | Modifiers.Generated); var eventIndex = result.Events.Count - 1; - _enqueuedActions.Add(() => + _queue.Enqueue( + () => { parameterizedType.PopulateMembers(); - var obj = ev.IsStatic ? null : new This(ev.Source, parameterizedType).Address; + var obj = ev.IsStatic + ? null + : new This(ev.Source, parameterizedType).Address; var field = parameterizedType.Events[eventIndex].ImplicitField; - addScope.Statements.Add( + addMethod.SetBody(new Scope(ed.Name.Source, new StoreField(ev.Source, obj, field, new CastOp(ev.Source, ev.ReturnType, _ilf.CallMethod(ev.Source, _ilf.Essentials.Delegate, "Combine", new CastOp(ev.Source, _ilf.Essentials.Delegate, new LoadField(ev.Source, obj, field)), - new LoadArgument(ev.Source, addMethod, 0))))); - removeScope.Statements.Add( + new LoadArgument(ev.Source, addMethod, 0)))))); + removeMethod.SetBody(new Scope(ed.Name.Source, new StoreField(ev.Source, obj, field, new CastOp(ev.Source, ev.ReturnType, _ilf.CallMethod(ev.Source, _ilf.Essentials.Delegate, "Remove", new CastOp(ev.Source, _ilf.Essentials.Delegate, new LoadField(ev.Source, obj, field)), - new LoadArgument(ev.Source, removeMethod, 0))))); + new LoadArgument(ev.Source, removeMethod, 0)))))); }); } else @@ -428,9 +411,9 @@ void PopulateClass(AstClass astClass, DataType result) Log.Error(ed.Name.Source, ErrorCode.E3040, "Modifiers can not be placed on event accessor declarations"); if (ed.Add != null) - EnqueueCompiler(new FunctionCompiler(_compiler, ev.CreateAddMethod(ed.Add.Source, ev.Modifiers), parameterizedType, ed.Add.OptionalBody)); + _queue.EnqueueFunction(ev.CreateAddMethod(ed.Add.Source, ev.Modifiers), parameterizedType, ed.Add.OptionalBody); if (ed.Remove != null) - EnqueueCompiler(new FunctionCompiler(_compiler, ev.CreateRemoveMethod(ed.Remove.Source, ev.Modifiers), parameterizedType, ed.Remove.OptionalBody)); + _queue.EnqueueFunction(ev.CreateRemoveMethod(ed.Remove.Source, ev.Modifiers), parameterizedType, ed.Remove.OptionalBody); if (ed.OptionalInterfaceType != null) { @@ -502,7 +485,7 @@ void PopulateClass(AstClass astClass, DataType result) // Compile field initializers if (fieldInitializers.Count > 0) - _enqueuedActions.Add(() => CompileFieldInitializers(result, parameterizedType, fieldInitializers)); + _queue.Enqueue(() => CompileFieldInitializers(result, parameterizedType, fieldInitializers)); // Create default constructor in non-static classes if (result.IsClass && !result.IsStatic && result.Constructors.Count == 0) @@ -511,7 +494,7 @@ void PopulateClass(AstClass astClass, DataType result) (parameterizedType.IsAbstract ? Modifiers.Protected : Modifiers.Public) | Modifiers.Generated, ParameterList.Empty, new Scope(parameterizedType.Source)); result.Constructors.Add(ctor); - _enqueuedActions.Add(() => + _queue.Enqueue(() => { parameterizedType.AssignBaseType(); if (parameterizedType.Base == null) @@ -569,7 +552,10 @@ void PopulateClass(AstClass astClass, DataType result) if (!result.IsInterface && result.Interfaces.Length > 0) ImplementInterfaces(result); - _compiler.BlockBuilder.PopulateBlock(astClass, result.Block); + if (result.Block != null) + _queue.EnqueueBlock( + result.Block, + x => _compiler.BlockBuilder.PopulateBlock(astClass, x)); foreach (var action in deferredActions) action(); diff --git a/src/compiler/core/Syntax/Builders/TypeBuilder.cs b/src/compiler/core/Syntax/Builders/TypeBuilder.cs index d7b681749..a2c98ac2a 100644 --- a/src/compiler/core/Syntax/Builders/TypeBuilder.cs +++ b/src/compiler/core/Syntax/Builders/TypeBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using Uno.Compiler.API.Domain; using Uno.Compiler.API.Domain.AST; @@ -8,7 +8,6 @@ using Uno.Compiler.API.Domain.IL.Types; using Uno.Compiler.Core.IL.Utilities; using Uno.Compiler.Core.Syntax.Binding; -using Uno.Compiler.Core.Syntax.Compilers; using Uno.Logging; namespace Uno.Compiler.Core.Syntax.Builders @@ -19,113 +18,23 @@ public partial class TypeBuilder : LogObject readonly ILFactory _ilf; readonly NameResolver _resolver; readonly Compiler _compiler; + readonly BuildQueue _queue; readonly Dictionary _cachedClasses = new Dictionary(); readonly Dictionary _flattenedClasses = new Dictionary(); - readonly List _enqueuedCompilers = new List(); - readonly List _enqueuedAttributes = new List(); - readonly List _enqueuedTypes = new List(); - readonly List _enqueuedActions = new List(); - int _assignBaseTypeIndex; - int _populateMembersIndex; - public TypeBuilder( + internal TypeBuilder( BuildEnvironment env, ILFactory ilf, NameResolver resolver, - Compiler compiler) + Compiler compiler, + BuildQueue queue) : base(compiler) { _env = env; _ilf = ilf; _resolver = resolver; _compiler = compiler; - } - - void EnqueueCompiler(FunctionCompiler fc) - { - if (fc.Body != null) - { - _enqueuedCompilers.Add(fc); - fc.Function.Tag = fc; - } - else if (_compiler.Backend.CanLink(fc.Function)) - { - fc.Function.Stats |= EntityStats.CanLink; - } - } - - void EnqueueType(DataType dt, Action assignBaseType, Action populate) - { - dt.AssigningBaseType = assignBaseType; - dt.PopulatingMembers = x => - { - populate(x); - x.Stats &= ~EntityStats.PopulatingMembers; - }; - dt.Stats |= EntityStats.PopulatingMembers; - _enqueuedTypes.Add(dt); - } - - void EnqueueAttributes(Entity e, Action assign) - { - e.AssigningAttributes = assign; - _enqueuedAttributes.Add(e); - } - - public void BuildTypes() - { - for (int count = 0, j = 0; count != _enqueuedTypes.Count && j < 10; j++) - { - count = _enqueuedTypes.Count; - - while (_assignBaseTypeIndex < count) - _enqueuedTypes[_assignBaseTypeIndex++].AssignBaseType(); - - for (int i = 0; i < _enqueuedAttributes.Count; i++) - _enqueuedAttributes[i].AssignAttributes(); - - _enqueuedAttributes.Clear(); - - while (_populateMembersIndex < count) - { - if (_compiler.Backend.CanLink(_enqueuedTypes[_populateMembersIndex])) - _enqueuedTypes[_populateMembersIndex].Stats |= EntityStats.CanLink; - - _enqueuedTypes[_populateMembersIndex++].PopulateMembers(); - } - - for (int i = 0; i < _enqueuedActions.Count; i++) - _enqueuedActions[i](); - - _enqueuedActions.Clear(); - } - - for (; _populateMembersIndex < _enqueuedTypes.Count; _populateMembersIndex++) - Log.Warning(_enqueuedTypes[_populateMembersIndex].Source, ErrorCode.I0000, "Unable to parameterize " + _enqueuedTypes[_populateMembersIndex].Quote()); - - _assignBaseTypeIndex = _populateMembersIndex; - } - - public void Build() - { - BuildTypes(); - - if (Log.HasErrors) - return; - - for (int i = 0; i < _enqueuedCompilers.Count; i++) - { - BuildTypes(); - _enqueuedCompilers[i].Compile(); - } - - BuildTypes(); - - _enqueuedCompilers.Clear(); - _enqueuedTypes.Clear(); - - _assignBaseTypeIndex = 0; - _populateMembersIndex = 0; + _queue = queue; } public RefArrayType GetArray(DataType elementType) @@ -141,7 +50,7 @@ public RefArrayType GetArray(DataType elementType) Method CreateMethod(DataType owner, string name, DataType returnType, params Parameter[] parameterList) { return new Method(owner.Source, owner, null, - Modifiers.Public | Modifiers.Intrinsic | Modifiers.Generated, + Modifiers.Public | Modifiers.Intrinsic | Modifiers.Generated, name, returnType, parameterList); } @@ -211,7 +120,7 @@ void CreateGenericSignature(DataType gt, AstGenericSignature sig, bool isOverrid if (c.Parameter.Symbol == p.Symbol) { if (c.BaseTypes != null) - EnqueueType(result[i], x => CompileBaseTypes(x, c.BaseTypes), x => { }); + _queue.EnqueueType(result[i], x => CompileBaseTypes(x, c.BaseTypes), x => { }); if (c.Type != 0) result[i].SetConstraintType((GenericConstraintType) c.Type); @@ -224,7 +133,7 @@ void CreateGenericSignature(DataType gt, AstGenericSignature sig, bool isOverrid } if (result[i].AssigningBaseType == null) - EnqueueType(result[i], x => x.SetBase(_ilf.Essentials.Object), x => { }); + _queue.EnqueueType(result[i], x => x.SetBase(_ilf.Essentials.Object), x => { }); } gt.MakeGenericDefinition(result); @@ -232,10 +141,12 @@ void CreateGenericSignature(DataType gt, AstGenericSignature sig, bool isOverrid internal static Modifiers GetTypeModifiers(Namescope parent, Modifiers modifiers) { - if ((modifiers & Modifiers.ProtectionModifiers) == 0) - modifiers |= parent is DataType ? Modifiers.Private : Modifiers.Internal; - - return modifiers; + return (modifiers & Modifiers.ProtectionModifiers) == 0 + ? modifiers | ( + parent is DataType + ? Modifiers.Private + : Modifiers.Internal) + : modifiers; } Modifiers GetMemberModifiers(Source src, DataType parent, Modifiers modifiers) diff --git a/src/ux/markup/CompilerReflection/ILCache.cs b/src/ux/markup/CompilerReflection/ILCache.cs index 5c501b675..ca8051e1a 100644 --- a/src/ux/markup/CompilerReflection/ILCache.cs +++ b/src/ux/markup/CompilerReflection/ILCache.cs @@ -35,7 +35,7 @@ public static Compiler.Core.Compiler Create(Log log, SourceBundle project) try { - compiler.TypeBuilder.BuildTypes(); + compiler.Queue.BuildTypes(); } catch (Exception) {