public IEnumerable <SyntaxNode> SetComponent(TranslationContext context, ExpressionSyntax entity, Type componentType, ExpressionSyntax componentDeclaration) { var type = TypeSystem.BuildTypeSyntax(componentType); var expressionId = typeof(ISharedComponentData).IsAssignableFrom(componentType) ? nameof(EntityCommandBuffer.Concurrent.SetSharedComponent) : nameof(EntityCommandBuffer.Concurrent.SetComponent); yield return(RoslynBuilder.MethodInvocation( expressionId, context.GetOrDeclareCommandBuffer(true), m_Concurrent ? new[] { Argument(IdentifierName(context.GetJobIndexParameterName())), Argument(entity), Argument(componentDeclaration) } : new[] { Argument(entity), Argument(componentDeclaration) }, new[] { type })); }
public static IEnumerable <SyntaxNode> BuildFunctionCall(this RoslynTranslator translator, FunctionCallNodeModel call, IPortModel portModel) { if (call.MethodInfo == null) { yield break; } var instance = BuildArgumentList(translator, call, out var argumentList); var typeArgumentList = new List <TypeSyntax>(); if (call.MethodInfo.IsGenericMethod) { foreach (var typeArgument in call.TypeArguments) { typeArgumentList.Add(TypeSystem.BuildTypeSyntax(typeArgument.Resolve(translator.Stencil))); } } TypeArgumentListSyntax typeArgList = null; if (typeArgumentList.Any()) { typeArgList = SyntaxFactory.TypeArgumentList(SyntaxFactory.SingletonSeparatedList(typeArgumentList.First())); } SyntaxNode method = RoslynBuilder.MethodInvocation(call.Title, call.MethodInfo, instance, argumentList, typeArgList); yield return(method); }
IEnumerable <MemberDeclarationSyntax> BuildComponentMembers(RoslynTranslator translator) { var states = new List <SwitchSectionSyntax>(); var variables = new Dictionary <string, FieldDeclarationSyntax>(); var stateIndex = 0; // Add members (MoveNext + variables) from coroutine nodes in stack var stack = Parent.IterationContext.Query; BuildStack(translator, stack, ref variables, ref states, ref stateIndex); // Fields var members = new List <MemberDeclarationSyntax> { RoslynBuilder.DeclareField( typeof(int), RoslynEcsBuilder.CoroutineStateVariableName, AccessibilityFlags.Private) }; members.AddRange(variables.Values); // Parameters + Arguments foreach (var component in m_AccessedComponents) { var componentName = GetComponentVariableName(IterationContext.Query, component); var componentType = component.Resolve(IterationContext.Stencil); m_Parameters.Add( Argument(IdentifierName(componentName)) .WithRefOrOutKeyword(Token(SyntaxKind.RefKeyword)), Parameter(Identifier(componentName)) .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword))) .WithType(TypeSystem.BuildTypeSyntax(componentType))); } foreach (var localVariable in IterationContext.Query.FunctionVariableModels) { m_Parameters.Add( Argument(IdentifierName(localVariable.Name)), Parameter(Identifier(localVariable.Name)) .WithType(TypeSystem.BuildTypeSyntax(localVariable.DataType.Resolve(IterationContext.Stencil)))); } // Create MoveNext method members.Add( RoslynBuilder.DeclareMethod(k_MoveNext, AccessibilityFlags.Public, typeof(bool)) .WithParameterList( ParameterList(SeparatedList(m_Parameters.Values))) .WithBody( Block( SwitchStatement(IdentifierName(RoslynEcsBuilder.CoroutineStateVariableName)) .WithOpenParenToken(Token(SyntaxKind.OpenParenToken)) .WithCloseParenToken(Token(SyntaxKind.CloseParenToken)) .WithSections(List(states)), ReturnStatement( LiteralExpression(SyntaxKind.FalseLiteralExpression))))); return(members); }
public override ExpressionSyntax GetCachedValue(string key, ExpressionSyntax value, TypeHandle type, params IdentifierNameSyntax[] attributes) { var constant = base.GetCachedValue(key, value, type, attributes); // Use the same identifier as the parentJob. This avoid things like myCoroutine.FixedTime0 = FixedTime var variableName = constant is IdentifierNameSyntax ins ? ins.Identifier.Text : key.Replace(".", "_"); var found = m_Parameters.FirstOrDefault(p => p.Value.Identifier.Text.Equals(variableName)); if (found.Value != null) { return(IdentifierName(found.Value.Identifier)); } var param = Parameter(Identifier(variableName)) .WithType(TypeSystem.BuildTypeSyntax(type.Resolve(IterationContext.Stencil))); if (attributes.Any()) { param.AddAttributeLists(AttributeList(SeparatedList(attributes.Select(Attribute)))); } m_Parameters.Add(Argument(constant), param); return(IdentifierName(param.Identifier)); }
public static IEnumerable <SyntaxNode> Build( this RoslynEcsTranslator translator, GetSingletonNodeModel model) { if (model.ComponentType == TypeHandle.Unknown) { yield break; } var singletonType = model.ComponentType.Resolve(translator.Stencil); var typeArguments = TypeArgumentList(SingletonSeparatedList(TypeSystem.BuildTypeSyntax(singletonType))); var bindingFlags = BindingFlags.Public | BindingFlags.Instance; var methodInfo = typeof(EntityQuery).GetMethod(nameof(EntityQuery.GetSingleton), bindingFlags) ?.GetGenericMethodDefinition() .MakeGenericMethod(singletonType); var method = RoslynBuilder.MethodInvocation( nameof(EntityQuery.GetSingleton), methodInfo, InvocationExpression( IdentifierName("GetEntityQuery")) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument(TypeOfExpression(singletonType.ToTypeSyntax()))))), new List <ArgumentSyntax>(), typeArguments) as ExpressionSyntax; yield return(method); }
public override ExpressionSyntax GetSingletonVariable(IVariableDeclarationModel variable) { var ext = Parent.GetSingletonVariable(variable); if (!HasParameter(RootContext.SingletonVariableName)) { // If not jobContext (readOnly access) we have to pass the singleton component as reference if (IsJobContext) { m_Parameters.Add( Argument(ext), Parameter(Identifier(((IdentifierNameSyntax)ext).Identifier.Text)) .WithType(TypeSystem.BuildTypeSyntax(variable.DataType.Resolve(IterationContext.Stencil)))); } else { m_Parameters.Add( Argument(IdentifierName(RootContext.SingletonVariableName)) .WithRefOrOutKeyword(Token(SyntaxKind.RefKeyword)), Parameter(Identifier(RootContext.SingletonVariableName)) .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword))) .WithType(IdentifierName(RootContext.SingletonComponentTypeName))); } } return(ext); }
public static IEnumerable <SyntaxNode> BuildGetComponent(this RoslynEcsTranslator translator, GetOrCreateComponentNodeModel model, IPortModel portModel) { var entity = translator.BuildPort(model.EntityPort).First() as ExpressionSyntax; TypeSyntax componentType = TypeSystem.BuildTypeSyntax(model.ComponentType.Resolve(translator.Stencil)); yield return(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(EntityManager)), GenericName( Identifier(model.CreateIfNeeded ? nameof(EcsHelper.GetOrCreateComponentData) : nameof(EntityManager.GetComponentData))) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( componentType ) ) ) ) ) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( entity))))); }
public override string GetOrDeclareComponentArray(RoslynEcsTranslator.IterationContext ctx, ComponentDefinition componentDefinition, out LocalDeclarationStatementSyntax arrayInitialization, out StatementSyntax arrayDisposal) { var declaration = Parent.GetOrDeclareComponentArray( ctx, componentDefinition, out arrayInitialization, out arrayDisposal); var parameter = declaration.ToCamelCase(); if (!(Parent is JobContext) || m_DeclaredComponentArray.Contains(componentDefinition)) { return(parameter); } var componentType = componentDefinition.TypeHandle.Resolve(ctx.Stencil); var arrayType = typeof(NativeArray <>).MakeGenericType(componentType); m_Parameters.Add( Argument(IdentifierName(declaration)), Parameter(Identifier(parameter)) .WithType(TypeSystem.BuildTypeSyntax(arrayType))); m_DeclaredComponentArray.Add(componentDefinition); return(parameter); }
public static MethodDeclarationSyntax DeclareMethod(string name, AccessibilityFlags accessibility, Type returnValueType) { return(SyntaxFactory.MethodDeclaration( TypeSystem.BuildTypeSyntax(returnValueType), SyntaxFactory.Identifier(name)) .WithModifiers(SyntaxFactory.TokenList(AccessibilityToSyntaxToken(accessibility).ToArray()))); }
public override string GetJobIndexParameterName() { var declaration = Parent.GetJobIndexParameterName(); var parameter = declaration.ToCamelCase(); m_Parameters.Add( Argument(IdentifierName(declaration)), Parameter(Identifier(parameter)).WithType(TypeSystem.BuildTypeSyntax(typeof(int)))); return(parameter); }
internal static StructDeclarationSyntax DeclareComponent(string componentName, Type componentType, IEnumerable <MemberDeclarationSyntax> members = null) { return(StructDeclaration(componentName) .WithModifiers( TokenList( Token(SyntaxKind.PublicKeyword))) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType(TypeSystem.BuildTypeSyntax(componentType))))) .WithMembers(List(members))); }
public override string GetJobIndexParameterName() { var declaration = Parent.GetJobIndexParameterName(); if (!HasParameter(declaration)) { m_Parameters.Add( Argument(IdentifierName(declaration)), Parameter(Identifier(declaration)).WithType(TypeSystem.BuildTypeSyntax(typeof(int)))); } return(declaration); }
public override void RecordEntityAccess(IVariableDeclarationModel model) { Parent.RecordEntityAccess(model); if (HasParameter(model.Name)) { return; } m_Parameters.Add( Argument(IdentifierName(model.Name)), Parameter(Identifier(model.Name)) .WithType(TypeSystem.BuildTypeSyntax(typeof(Entity)))); }
protected IEnumerable <MemberDeclarationSyntax> BuildComponentMembers() { // Fields var members = new List <MemberDeclarationSyntax> { RoslynBuilder.DeclareField( typeof(int), k_CoroutineStateVariableName, AccessibilityFlags.Public) }; members.AddRange(m_ComponentVariables.Values); foreach (var component in m_AccessedComponents) { var componentName = GetComponentVariableName(IterationContext.Query, component); var componentType = component.Resolve(IterationContext.Stencil); m_Parameters.Add( Argument(IdentifierName(componentName)) .WithRefOrOutKeyword(Token(SyntaxKind.RefKeyword)), Parameter(Identifier(componentName)) .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword))) .WithType(TypeSystem.BuildTypeSyntax(componentType))); } foreach (var localVariable in IterationContext.Query.FunctionVariableModels) { m_Parameters.Add( Argument(IdentifierName(localVariable.Name)), Parameter(Identifier(localVariable.Name)) .WithType(TypeSystem.BuildTypeSyntax(localVariable.DataType.Resolve(IterationContext.Stencil)))); } if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) != 0) { m_Parameters.Add( Argument(GetRecorderName()) .WithRefOrOutKeyword(Token(SyntaxKind.RefKeyword)), Parameter(GetRecorderName().Identifier) .WithModifiers(SyntaxTokenList.Create(Token(SyntaxKind.RefKeyword))) .WithType((IsJobContext ? typeof(GraphStream.Writer) : typeof(DebuggerTracer.EntityFrameTrace)) .ToTypeSyntax())); } return(members); }
public override IdentifierNameSyntax GetEventBufferWriter(RoslynEcsTranslator.IterationContext iterationContext, ExpressionSyntax entity, Type eventType, out StatementSyntax bufferInitialization) { var declaration = Parent.GetEventBufferWriter(iterationContext, entity, eventType, out bufferInitialization); var parameter = declaration.Identifier.Text.ToCamelCase(); m_Parameters.Add( Argument(declaration), Parameter(Identifier(parameter)) .WithType( GenericName(Identifier("DynamicBuffer")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList(TypeSystem.BuildTypeSyntax(eventType)))))); return(IdentifierName(parameter)); }
public override IdentifierNameSyntax GetOrDeclareCommandBuffer(bool isConcurrent) { var declaration = Parent.GetOrDeclareCommandBuffer(isConcurrent); var name = declaration.Identifier.Text; if (!HasParameter(name)) { var parameter = IdentifierName(name); var cmdType = declaration.Identifier.Text != nameof(ComponentSystem.PostUpdateCommands) ? typeof(EntityCommandBuffer.Concurrent) : typeof(EntityCommandBuffer); m_Parameters.Add( Argument(IdentifierName(declaration.Identifier)), Parameter(parameter.Identifier).WithType(TypeSystem.BuildTypeSyntax(cmdType))); } return(declaration); }
public IEnumerable <SyntaxNode> SetComponent(TranslationContext context, ExpressionSyntax entity, Type componentType, ExpressionSyntax componentDeclaration) { var type = TypeSystem.BuildTypeSyntax(componentType); var expressionId = typeof(ISharedComponentData).IsAssignableFrom(componentType) ? nameof(EntityManager.SetSharedComponentData) : nameof(EntityManager.SetComponentData); yield return(RoslynBuilder.MethodInvocation( expressionId, IdentifierName(nameof(EntityManager)), new[] { Argument(entity), Argument(componentDeclaration) }, new[] { type })); }
public static List <ParameterSyntax> BuildArguments(Stencil stencil, IFunctionModel stack) { var argumentNodes = new List <ParameterSyntax>(); foreach (var paramDecl in stack.FunctionParameterModels) { switch (paramDecl.VariableType) { case VariableType.FunctionParameter: argumentNodes.Add(SyntaxFactory.Parameter( SyntaxFactory.Identifier(paramDecl.Name)) .WithType( TypeSystem.BuildTypeSyntax(paramDecl.DataType.Resolve(stencil)))); break; } } return(argumentNodes); }
public IEnumerable <SyntaxNode> GetComponent(TranslationContext context, ExpressionSyntax entity, Type componentType) { var type = TypeSystem.BuildTypeSyntax(componentType); context.RecordComponentAccess( context.IterationContext, componentType.GenerateTypeHandle(context.IterationContext.Stencil), RoslynEcsTranslator.AccessMode.Read); var expressionId = typeof(ISharedComponentData).IsAssignableFrom(componentType) ? nameof(EntityManager.GetSharedComponentData) : nameof(EntityManager.GetComponentData); yield return(RoslynBuilder.MethodInvocation( expressionId, IdentifierName(nameof(EntityManager)), new[] { Argument(entity) }, new[] { type })); }
protected override StatementSyntax GetOrDeclareEntityArray(RoslynEcsTranslator.IterationContext context, out StatementSyntax arrayDisposal) { if (Parent is JobContext) { m_Parameters.Add( Argument(IdentifierName(context.EntitiesArrayName)), Parameter(Identifier(context.EntitiesArrayName)) .WithType(TypeSystem.BuildTypeSyntax(typeof(NativeArray <Entity>)))); } else { m_Parameters.Add( Argument(IdentifierName(context.GroupName)), Parameter(Identifier(context.GroupName)) .WithType(TypeSystem.BuildTypeSyntax(typeof(EntityQuery)))); } return(base.GetOrDeclareEntityArray(context, out arrayDisposal)); }
public override IdentifierNameSyntax GetOrDeclareCommandBuffer(bool isConcurrent) { var declaration = Parent.GetOrDeclareCommandBuffer(isConcurrent); var parameter = IdentifierName(declaration.Identifier.Text.ToCamelCase()); if (m_DeclaredCommandBuffers.Contains(parameter)) { return(parameter); } var cmdType = isConcurrent && Parent is JobContext ? typeof(EntityCommandBuffer.Concurrent) : typeof(EntityCommandBuffer); m_Parameters.Add( Argument(IdentifierName(declaration.Identifier)), Parameter(parameter.Identifier).WithType(TypeSystem.BuildTypeSyntax(cmdType))); m_DeclaredCommandBuffers.Add(parameter); return(parameter); }
internal static ExpressionSyntax MakeInitComponentDataArrayExpression( RoslynEcsTranslator.IterationContext ctx, Type componentType) { return(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(ctx.GroupName), GenericName( Identifier("ToComponentDataArray")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( TypeSystem.BuildTypeSyntax(componentType)))))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(Allocator)), IdentifierName(ctx.AllocatorType.ToString())))))) .NormalizeWhitespace()); }
public virtual ExpressionSyntax Constant(object value, Stencil stencil, Type generatedType = null) { switch (value) { case float f: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(f))); case decimal d: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(d))); case int i: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(i))); case double d: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(d))); case bool b: return(LiteralExpression(b ? SyntaxKind.TrueLiteralExpression : SyntaxKind.FalseLiteralExpression)); case string s: return(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal(s))); case char c: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(c))); case Vector2 _: case Vector3 _: case Vector4 _: case Quaternion _: case Color _: if (generatedType == null) { generatedType = value.GetType(); } return(RoslynBuilder.CreateConstantInitializationExpression(value, generatedType)); case Enum _: return(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName(value.GetType().Name), IdentifierName(value.ToString()) )); case EnumValueReference e: return(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, TypeSystem.BuildTypeSyntax(e.EnumType.Resolve(stencil)), IdentifierName(e.ValueAsEnum(stencil).ToString()) )); case AnimationCurve _: return(DefaultExpression(TypeSyntaxFactory.ToTypeSyntax(typeof(AnimationCurve)))); case LayerMask m: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(m.value))); case InputName inputName: return(inputName.name == null ? LiteralExpression(SyntaxKind.NullLiteralExpression) : LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(inputName.name))); case SceneAsset asset: return(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(AssetDatabase.GetAssetPath(asset)))); default: return(DefaultExpression(TypeSystem.BuildTypeSyntax(value.GetType()))); } }
StructDeclarationSyntax Build() { if (IterationContext.UpdateMode == UpdateMode.OnEnd) { throw new RoslynEcsTranslator.JobSystemNotCompatibleException("Exit stacks are not compatible with jobs yet"); } // Todo: disabled at the moment - job scheduling needs to use the enter query which uses an excluded component if (IterationContext.UpdateMode == UpdateMode.OnStart) { throw new RoslynEcsTranslator.JobSystemNotCompatibleException("Enter stacks are not compatible with jobs yet"); } if (m_UpdateSingletonRequested) { throw new RoslynEcsTranslator.JobSystemNotCompatibleException("Setting a blackboard variable is not compatible with jobs yet"); } var stateComponentName = IterationContext.UpdateMode == UpdateMode.OnUpdate || IterationContext.UpdateMode == UpdateMode.OnEvent ? null : IncludeTrackingSystemStateComponent(IterationContext.Query.ComponentQueryDeclarationModel, IterationContext.UpdateMode == UpdateMode.OnEnd); var functionParameters = new List <ParameterSyntax> { Parameter(Identifier(EntityName)).WithType(TypeSystem.BuildTypeSyntax(typeof(Entity))), Parameter(Identifier(GetJobIndexParameterName())).WithType(PredefinedType(Token(SyntaxKind.IntKeyword))) }; var baseTypeSyntax = MakeJobBaseType(IterationContext, functionParameters, out Type eventType); if (baseTypeSyntax == null) { return(null); } StructDeclarationSyntax structDeclaration = StructDeclaration(m_JobName); if (BurstCompileJobs) { structDeclaration = structDeclaration.AddAttributeLists( AttributeList().AddAttributes( Attribute(IdentifierName("BurstCompile")))); } structDeclaration = DeclareExcludedComponents(structDeclaration); var makeJobUpdateOverride = MakeJobUpdateOverride(functionParameters, m_UpdateStatements, stateComponentName, eventType); structDeclaration = structDeclaration .AddBaseListTypes(baseTypeSyntax) .WithMembers(List(m_MemberDeclarations)) .AddMembers(makeJobUpdateOverride); return(structDeclaration); StructDeclarationSyntax DeclareExcludedComponents(StructDeclarationSyntax declaration) { if (m_ExcludedComponents.Count == 0) { return(declaration); } List <AttributeArgumentSyntax> componentsToExclude = new List <AttributeArgumentSyntax>(); foreach (var excludedComponent in m_ExcludedComponents) { var arg = AttributeArgument(TypeOfExpression(excludedComponent.ToTypeSyntax(IterationContext.Stencil))); componentsToExclude.Add(arg); } var syntaxNodes = new SyntaxNodeOrToken[componentsToExclude.Count * 2 - 1]; syntaxNodes[0] = componentsToExclude[0]; for (var index = 1; index < componentsToExclude.Count; index++) { syntaxNodes[index * 2 - 1] = Token(SyntaxKind.CommaToken); syntaxNodes[index * 2] = componentsToExclude[index]; } declaration = declaration.AddAttributeLists( AttributeList().AddAttributes( Attribute(IdentifierName("ExcludeComponent")) .WithArgumentList( AttributeArgumentList(SeparatedList <AttributeArgumentSyntax>(syntaxNodes))))); return(declaration); } }
public static SyntaxNode MethodInvocation(string name, MethodBase methodInfo, SyntaxNode instance, List <ArgumentSyntax> argumentList, TypeArgumentListSyntax typeArgumentList) { var sepList = SyntaxFactory.SeparatedList(argumentList); if (methodInfo == null) { return(SyntaxFactory.EmptyStatement()); } var propertyInfos = methodInfo.DeclaringType?.GetProperties(); var isSetAccessor = propertyInfos?.FirstOrDefault(prop => prop.GetSetMethod() == methodInfo); var isGetAccessor = propertyInfos?.FirstOrDefault(prop => prop.GetGetMethod() == methodInfo); bool isProperty = isSetAccessor != null || isGetAccessor != null; var methodName = methodInfo.Name; if (isProperty) { methodName = name.Substring(4); } bool isGenericMethod = methodInfo.IsGenericMethod; ExpressionSyntax finalExpressionSyntax = null; ExpressionSyntax memberAccessExpression = instance == null?SyntaxFactory.IdentifierName(methodInfo.DeclaringType?.Name) : instance as ExpressionSyntax; if (!isProperty) { if (methodInfo.IsConstructor) { finalExpressionSyntax = SyntaxFactory.ObjectCreationExpression( TypeSystem.BuildTypeSyntax(methodInfo.DeclaringType)) .WithArgumentList(SyntaxFactory.ArgumentList(sepList)); } else { SimpleNameSyntax genericName = isGenericMethod ? (SimpleNameSyntax)SyntaxFactory.GenericName( SyntaxFactory.Identifier(methodName)) .WithTypeArgumentList(typeArgumentList) : SyntaxFactory.IdentifierName(methodName); InvocationExpressionSyntax invocation = SyntaxFactory.InvocationExpression( SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, memberAccessExpression, genericName ) ); finalExpressionSyntax = invocation .WithArgumentList(SyntaxFactory.ArgumentList(sepList)); } } else { if (isGetAccessor != null) { if (isGetAccessor.GetIndexParameters().Length > 0) { finalExpressionSyntax = SyntaxFactory.ElementAccessExpression( memberAccessExpression, SyntaxFactory.BracketedArgumentList(sepList)); } else { finalExpressionSyntax = SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, memberAccessExpression, SyntaxFactory.IdentifierName(methodName)); } } else if (isSetAccessor != null) { ExpressionSyntax left; if (isSetAccessor.GetIndexParameters().Length > 0) { left = SyntaxFactory.ElementAccessExpression(memberAccessExpression, SyntaxFactory.BracketedArgumentList( SyntaxFactory.SeparatedList(argumentList.Take(argumentList.Count - 1)) )); } else { left = SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, memberAccessExpression, SyntaxFactory.IdentifierName(methodName)); } finalExpressionSyntax = SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, left, argumentList.Last().Expression); } } return(finalExpressionSyntax); }
protected override StatementSyntax OnPopContext() { BlockSyntax forBody = Block(); var loopIndexName = IterationContext.IndexVariableName; List <StatementSyntax> reassignComponentDataArrays = new List <StatementSyntax>(); BlockSyntax blockSyntax = Block(); // foreach in a job: the entity array will be declared as a job field, initialized at job creation StatementSyntax initEntitiesArray = GetOrDeclareEntityArray(IterationContext, out var disposeEntitiesArray); foreach (ComponentDefinition definition in IterationContext.FlattenedComponentDefinitions()) { if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess(definition.TypeHandle, true, out var componentType, IterationContext.Stencil, out bool isShared, out bool isGameObjectComponent) || isGameObjectComponent) { continue; } if (!m_WrittenComponents.TryGetValue(definition.TypeHandle, out var mode)) { mode = RoslynEcsTranslator.AccessMode.None; } if (mode == RoslynEcsTranslator.AccessMode.None) { continue; } ExpressionSyntax initValue; if (isShared) { initValue = InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, IdentifierName(nameof(EntityManager)), GenericName( Identifier(nameof(EntityManager.GetSharedComponentData))) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList( TypeSystem.BuildTypeSyntax(componentType)))))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName(EntityName))))); } else { string compArrayName = GetOrDeclareComponentArray(IterationContext, definition, out var componentDataArrayInitialization, out var componentDataArrayDisposal); if (componentDataArrayInitialization != null) { m_InitComponentDataArrays.Add(componentDataArrayInitialization); } if (componentDataArrayDisposal != null) { m_DisposeComponentDataArrays.Add(componentDataArrayDisposal); } initValue = ElementAccessExpression(IdentifierName(compArrayName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(loopIndexName))))); } // per-entity component variable StatementSyntax componentVarDeclaration = RoslynBuilder.DeclareLocalVariable( componentType, IterationContext.GetComponentDataName(componentType), initValue, RoslynBuilder.VariableDeclarationType.InferredType); forBody = forBody.AddStatements(componentVarDeclaration); if (mode == RoslynEcsTranslator.AccessMode.Write) { reassignComponentDataArrays.Add(ExpressionStatement( GetEntityManipulationTranslator().SetComponent( this, ElementAccessExpression(IdentifierName(IterationContext.EntitiesArrayName)) .WithArgumentList( BracketedArgumentList( SingletonSeparatedList( Argument( IdentifierName(IterationContext.IndexVariableName))))), componentType, IdentifierName(IterationContext.GetComponentDataName(componentType))) .Cast <ExpressionSyntax>() .Single()) ); } } forBody = forBody.AddStatements(m_UpdateStatements.ToArray()); forBody = forBody.AddStatements(reassignComponentDataArrays.ToArray()); if (forBody.Statements.Count != 0) // strip the iteration loop if empty { forBody = forBody.WithStatements(forBody.Statements.Insert(0, m_EntityDeclaration)); if (initEntitiesArray != null) { blockSyntax = blockSyntax.AddStatements(initEntitiesArray); } blockSyntax = blockSyntax .AddStatements(m_InitComponentDataArrays.ToArray()) .AddStatements(RoslynEcsTranslatorExtensions.ComponentQueryForLoop(forBody, loopIndexName, IterationContext.EntitiesArrayName)) .AddStatements(m_DisposeComponentDataArrays.ToArray()); if (disposeEntitiesArray != null) { blockSyntax = blockSyntax.AddStatements(disposeEntitiesArray); } } return(AddMissingEventBuffers(IterationContext, blockSyntax)); }
BaseTypeSyntax MakeJobBaseType(RoslynEcsTranslator.IterationContext iterationContext, List <ParameterSyntax> functionParameters, out Type eventType) { var genericArguments = new List <TypeSyntax>(); eventType = null; int componentCount = 0; int bufferCount = 0; if (iterationContext.UpdateMode != UpdateMode.OnEnd) { if (iterationContext.UpdateMode == UpdateMode.OnEvent) // add DynamicBuffer<eventType> { eventType = ((OnEventNodeModel)iterationContext.Query).EventTypeHandle.Resolve(iterationContext.Stencil); var eventTypeSyntax = TypeSystem.BuildTypeSyntax(eventType); var bufferType = GenericName("DynamicBuffer") .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(eventTypeSyntax))); var parameterSyntax = Parameter( Identifier(OnEventNodeModel.GetBufferName(eventType))) .WithType(bufferType); AddReadOnlyAttribute(ref parameterSyntax); bufferCount = 1; functionParameters.Add(parameterSyntax); genericArguments.Add(eventTypeSyntax); } foreach (ComponentDefinition definition in iterationContext.FlattenedComponentDefinitions().Where(def => !def.Subtract)) { if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess(definition.TypeHandle, true, out Type resolvedType, iterationContext.Stencil, out bool isShared, out bool isGameObjectComponent) || isGameObjectComponent) { continue; } if (isShared) { throw new RoslynEcsTranslator.JobSystemNotCompatibleException("Shared Components are not supported in jobs yet"); } genericArguments.Add(TypeSystem.BuildTypeSyntax(resolvedType)); var parameterSyntax = Parameter( Identifier(GetComponentVariableName(iterationContext.Query, definition.TypeHandle))) .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword))) .WithType(TypeSystem.BuildTypeSyntax(resolvedType)); if (!m_WrittenComponents.Contains(definition.TypeHandle)) { AddReadOnlyAttribute(ref parameterSyntax); } functionParameters.Add( parameterSyntax); componentCount++; } if (genericArguments.Count == 0) { return(null); } } string CleanGenericName(string s) { var index = s.IndexOf('`'); return(index == -1 ? s : s.Substring(0, index)); } // IJobForEachWitEntity_EBBCCC string suffix = componentCount > 0 || bufferCount > 0 ? $"_E{new String('B', bufferCount)}{new String('C', componentCount)}" : ""; return(SimpleBaseType( GenericName( Identifier(CleanGenericName(typeof(IJobForEachWithEntity <>).Name) + suffix)) .WithTypeArgumentList( TypeArgumentList( SeparatedList( genericArguments))))); ParameterSyntax AddReadOnlyAttribute(ref ParameterSyntax parameterSyntax) { return(parameterSyntax = parameterSyntax.WithAttributeLists( SingletonList( AttributeList( SingletonSeparatedList( Attribute( IdentifierName(nameof(ReadOnlyAttribute)))))))); } }