public override void VisitClassDeclaration(ClassDeclarationSyntax node) { if (++classCount > 1) { throw new System.NotSupportedException("Only one class declaration per file is currently supported by UdonSharp"); } using (ExpressionCaptureScope classTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { foreach (string namespaceToken in namespaceStack.Reverse()) { classTypeCapture.ResolveAccessToken(namespaceToken); } visitorContext.resolverContext.AddNamespace(classTypeCapture.captureNamespace); classTypeCapture.ResolveAccessToken(node.Identifier.ValueText); if (!classTypeCapture.IsType()) { throw new System.Exception($"User type {node.Identifier.ValueText} could not be found"); } classDefinition.userClassType = classTypeCapture.captureType; } base.VisitClassDeclaration(node); }
public override void VisitClassDeclaration(ClassDeclarationSyntax node) { UpdateSyntaxNode(node); using (ExpressionCaptureScope classTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { foreach (string namespaceToken in namespaceStack.Reverse()) { classTypeCapture.ResolveAccessToken(namespaceToken); if (classTypeCapture.IsNamespace()) { visitorContext.resolverContext.AddNamespace(classTypeCapture.captureNamespace); } } classTypeCapture.ResolveAccessToken(node.Identifier.ValueText); if (!classTypeCapture.IsType()) { throw new System.Exception($"User type {node.Identifier.ValueText} could not be found"); } } if (syntaxWalkerDepth == UdonSharpSyntaxWalkerDepth.ClassDefinitions || syntaxWalkerDepth == UdonSharpSyntaxWalkerDepth.ClassMemberBodies) { base.VisitClassDeclaration(node); } }
// Boilerplate to have resolution work correctly public override void VisitUsingDirective(UsingDirectiveSyntax node) { UpdateSyntaxNode(node); using (ExpressionCaptureScope namespaceCapture = new ExpressionCaptureScope(visitorContext, null)) { if (node.StaticKeyword.IsKind(SyntaxKind.StaticKeyword)) { throw new System.NotSupportedException("UdonSharp does not yet support static using directives"); } if (node.Alias != null) { throw new System.NotSupportedException("UdonSharp does not yet support namespace alias directives"); } Visit(node.Name); if (!namespaceCapture.IsNamespace()) { throw new System.Exception("Did not capture a valid namespace"); } visitorContext.resolverContext.AddNamespace(namespaceCapture.captureNamespace); } }
public override void VisitClassDeclaration(ClassDeclarationSyntax node) { using (ExpressionCaptureScope classTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { foreach (string namespaceToken in namespaceStack.Reverse()) { classTypeCapture.ResolveAccessToken(namespaceToken); if (classTypeCapture.IsNamespace()) { visitorContext.resolverContext.AddNamespace(classTypeCapture.captureNamespace); } } visitorContext.resolverContext.AddNamespace(classTypeCapture.captureNamespace); classTypeCapture.ResolveAccessToken(node.Identifier.ValueText); if (!classTypeCapture.IsType()) { throw new System.Exception($"User type {node.Identifier.ValueText} could not be found"); } } base.VisitClassDeclaration(node); }
public override void VisitFieldDeclaration(FieldDeclarationSyntax node) { UpdateSyntaxNode(node); bool isPublic = node.Modifiers.HasModifier("public"); System.Type fieldType = null; using (ExpressionCaptureScope fieldTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { UpdateSyntaxNode(node.Declaration.Type); Visit(node.Declaration.Type); fieldType = fieldTypeCapture.captureType; } if (fieldType == null) { throw new System.Exception($"The type or namespace name '{node.Declaration.Type}' could not be found (are you missing a using directive?)"); } foreach (VariableDeclaratorSyntax variableDeclarator in node.Declaration.Variables) { SymbolDefinition newSymbol = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, fieldType, isPublic ? SymbolDeclTypeFlags.Public : SymbolDeclTypeFlags.Private); classDefinition.fieldDefinitions.Add(new FieldDefinition(newSymbol)); } }
public override void VisitArrayType(ArrayTypeSyntax node) { using (ExpressionCaptureScope arrayTypeCaptureScope = new ExpressionCaptureScope(visitorContext, visitorContext.topCaptureScope)) { Visit(node.ElementType); arrayTypeCaptureScope.MakeArrayType(); } }
private UdonSyncMode GetSyncAttributeValue(FieldDeclarationSyntax node) { UdonSyncMode syncMode = UdonSyncMode.NotSynced; if (node.AttributeLists != null) { foreach (AttributeListSyntax attributeList in node.AttributeLists) { foreach (AttributeSyntax attribute in attributeList.Attributes) { using (ExpressionCaptureScope attributeTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { attributeTypeCapture.isAttributeCaptureScope = true; Visit(attribute.Name); if (attributeTypeCapture.captureType != typeof(UdonSyncedAttribute)) { continue; } if (attribute.ArgumentList == null || attribute.ArgumentList.Arguments == null || attribute.ArgumentList.Arguments.Count == 0) { syncMode = UdonSyncMode.None; } else { using (ExpressionCaptureScope attributeCaptureScope = new ExpressionCaptureScope(visitorContext, null)) { Visit(attribute.ArgumentList.Arguments[0].Expression); if (!attributeCaptureScope.IsEnum()) { throw new System.Exception("Invalid attribute argument provided for sync"); } syncMode = (UdonSyncMode)attributeCaptureScope.GetEnumValue(); } } break; } } if (syncMode != UdonSyncMode.NotSynced) { break; } } } return(syncMode); }
public override void VisitArrayType(ArrayTypeSyntax node) { using (ExpressionCaptureScope arrayTypeCaptureScope = new ExpressionCaptureScope(visitorContext, visitorContext.topCaptureScope)) { Visit(node.ElementType); for (int i = 0; i < node.RankSpecifiers.Count; ++i) { arrayTypeCaptureScope.MakeArrayType(); } } }
// Boilerplate to have resolution work correctly public override void VisitUsingDirective(UsingDirectiveSyntax node) { using (ExpressionCaptureScope namespaceCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Name); if (!namespaceCapture.IsNamespace()) { throw new System.Exception("Did not capture a valid namespace"); } visitorContext.resolverContext.AddNamespace(namespaceCapture.captureNamespace); } }
public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { MethodDefinition methodDefinition = new MethodDefinition(); methodDefinition.declarationFlags = node.Modifiers.HasModifier("public") ? MethodDeclFlags.Public : MethodDeclFlags.Private; methodDefinition.methodUdonEntryPoint = visitorContext.labelTable.GetNewJumpLabel("udonMethodEntryPoint"); methodDefinition.methodUserCallStart = visitorContext.labelTable.GetNewJumpLabel("userMethodCallEntry"); methodDefinition.methodReturnPoint = visitorContext.labelTable.GetNewJumpLabel("methodReturnPoint"); methodDefinition.originalMethodName = node.Identifier.ValueText; methodDefinition.uniqueMethodName = methodDefinition.originalMethodName; visitorContext.resolverContext.ReplaceInternalEventName(ref methodDefinition.uniqueMethodName); // Resolve the type arguments using (ExpressionCaptureScope returnTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.ReturnType); if (returnTypeCapture.captureType != typeof(void)) { //methodDefinition.returnType = returnTypeCapture.captureType; methodDefinition.returnSymbol = visitorContext.topTable.CreateNamedSymbol("returnValSymbol", returnTypeCapture.captureType, SymbolDeclTypeFlags.Internal); } } methodDefinition.parameters = new ParameterDefinition[node.ParameterList.Parameters.Count]; for (int i = 0; i < node.ParameterList.Parameters.Count; ++i) { ParameterSyntax parameter = node.ParameterList.Parameters[i]; ParameterDefinition paramDef = new ParameterDefinition(); using (ExpressionCaptureScope paramTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(parameter.Type); paramDef.type = paramTypeCapture.captureType; paramDef.symbolName = parameter.Identifier.ValueText; paramDef.paramSymbol = visitorContext.topTable.CreateNamedSymbol(parameter.Identifier.ValueText, paramDef.type, SymbolDeclTypeFlags.Local); } methodDefinition.parameters[i] = paramDef; } definedMethods.Add(methodDefinition); }
public override void VisitFieldDeclaration(FieldDeclarationSyntax node) { bool isPublic = node.Modifiers.HasModifier("public"); System.Type fieldType = null; using (ExpressionCaptureScope fieldTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Declaration.Type); fieldType = fieldTypeCapture.captureType; } foreach (VariableDeclaratorSyntax variableDeclarator in node.Declaration.Variables) { SymbolDefinition newSymbol = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, fieldType, isPublic ? SymbolDeclTypeFlags.Public : SymbolDeclTypeFlags.Private); classDefinition.fieldDefinitions.Add(new FieldDefinition(newSymbol)); } }
private List <System.Type> GetTypeArgumentList(TypeArgumentListSyntax typeArgumentList) { UpdateSyntaxNode(typeArgumentList); List <System.Type> argumentTypes = new List <System.Type>(); foreach (TypeSyntax typeSyntax in typeArgumentList.Arguments) { using (ExpressionCaptureScope typeCaptureScope = new ExpressionCaptureScope(visitorContext, null)) { Visit(typeSyntax); if (!typeCaptureScope.IsType()) { throw new System.ArgumentException("Generic argument must be a valid type"); } argumentTypes.Add(UdonSharpUtils.RemapBaseType(typeCaptureScope.captureType)); } } return(argumentTypes); }
public override void VisitTypeOfExpression(TypeOfExpressionSyntax node) { UpdateSyntaxNode(node); System.Type capturedType = null; using (ExpressionCaptureScope typeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Type); capturedType = typeCapture.captureType; // Just throw a compile error for now instead of letting people get the typeof a type that won't exist in game if (capturedType == typeof(UdonSharpBehaviour) || capturedType.IsSubclassOf(typeof(UdonSharpBehaviour))) { throw new System.NotSupportedException("UdonSharp does not currently support using `typeof` on user defined types"); } } if (visitorContext.topCaptureScope != null) { visitorContext.topCaptureScope.SetToLocalSymbol(visitorContext.topTable.CreateConstSymbol(typeof(System.Type), capturedType)); } }
bool HasRecursiveMethodAttribute(MethodDeclarationSyntax node) { if (node.AttributeLists != null) { foreach (AttributeListSyntax attributeList in node.AttributeLists) { foreach (AttributeSyntax attribute in attributeList.Attributes) { using (ExpressionCaptureScope attributeTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { attributeTypeCapture.isAttributeCaptureScope = true; Visit(attribute.Name); if (attributeTypeCapture.captureType == typeof(RecursiveMethodAttribute)) { return(true); } } } } } return(false); }
protected List <SymbolDefinition> HandleVariableDeclaration(VariableDeclarationSyntax node, SymbolDeclTypeFlags symbolType, UdonSyncMode syncMode) { UpdateSyntaxNode(node); bool isVar = node.Type.IsVar; System.Type variableType = null; if (!isVar) { using (ExpressionCaptureScope typeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Type); if (!typeCapture.IsType()) { throw new System.Exception($"The type or namespace name '{typeCapture.unresolvedAccessChain}' could not be found (are you missing a using directive?)"); } variableType = typeCapture.captureType; } } List <SymbolDefinition> newSymbols = new List <SymbolDefinition>(); foreach (VariableDeclaratorSyntax variableDeclarator in node.Variables) { SymbolDefinition newSymbol = null; string variableName = variableDeclarator.Identifier.ValueText; using (ExpressionCaptureScope symbolCreationScope = new ExpressionCaptureScope(visitorContext, null)) { if (!isVar) { newSymbol = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, variableType, symbolType); } // Run the initializer if it exists // Todo: Run the set on the new symbol scope from within the initializer scope for direct setting if (variableDeclarator.Initializer != null && symbolType.HasFlag(SymbolDeclTypeFlags.Local)) { using (ExpressionCaptureScope initializerCapture = new ExpressionCaptureScope(visitorContext, null, newSymbol)) { Visit(variableDeclarator.Initializer); if (newSymbol == null) { // TODO: Find a way to determine the return type before generating initializer code, to avoid a copy on 'var' local initializers variableType = initializerCapture.GetReturnType(true); newSymbol = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, variableType, symbolType); } symbolCreationScope.SetToLocalSymbol(newSymbol); symbolCreationScope.ExecuteSet(initializerCapture.ExecuteGet()); } } newSymbol.syncMode = syncMode; } VerifySyncValidForType(newSymbol.symbolCsType, syncMode); newSymbols.Add(newSymbol); } if (!visitorContext.resolverContext.IsValidUdonType(variableType)) { throw new System.NotSupportedException($"Udon does not support variables of type '{variableType.Name}' yet"); } return(newSymbols); }
public SymbolDefinition Invoke(SymbolDefinition[] invokeParams) { SymbolDefinition methodResult = null; System.Type resultSymbolType = null; string lookupSymbolName = null; switch (captureFunc) { case InternalFunc.TypeIDInstance: case InternalFunc.TypeIDGeneric: resultSymbolType = typeof(long); lookupSymbolName = "udonTypeID"; break; case InternalFunc.TypeNameInstance: case InternalFunc.TypeNameGeneric: resultSymbolType = typeof(string); lookupSymbolName = "udonTypeName"; break; default: throw new System.ArgumentException("Invalid internal method invocation"); } methodResult = visitorContext.topTable.CreateUnnamedSymbol(resultSymbolType, SymbolDeclTypeFlags.Internal); if (captureFunc == InternalFunc.TypeIDInstance || captureFunc == InternalFunc.TypeNameInstance) { SymbolDefinition invokeSymbol = captureScope.accessSymbol; using (ExpressionCaptureScope resultSetterScope = new ExpressionCaptureScope(visitorContext, null)) { resultSetterScope.SetToLocalSymbol(methodResult); using (ExpressionCaptureScope getInvokeScope = new ExpressionCaptureScope(visitorContext, null)) { getInvokeScope.SetToLocalSymbol(invokeSymbol); getInvokeScope.ResolveAccessToken(nameof(VRC.Udon.UdonBehaviour.GetProgramVariable)); string symbolName = visitorContext.topTable.GetReflectionSymbol(lookupSymbolName, resultSymbolType).symbolUniqueName; SymbolDefinition invokeResult = getInvokeScope.Invoke(new SymbolDefinition[] { visitorContext.topTable.CreateConstSymbol(typeof(string), symbolName) }); JumpLabel exitBranchJump = visitorContext.labelTable.GetNewJumpLabel("exitUdonTypeIdLoc"); JumpLabel falseBranchLoc = visitorContext.labelTable.GetNewJumpLabel("falseUdonTypeIdLoc"); SymbolDefinition nullCheckSymbol = null; using (ExpressionCaptureScope nullCheckCondition = new ExpressionCaptureScope(visitorContext, null)) { nullCheckCondition.SetToMethods(UdonSharpUtils.GetOperators(typeof(object), BuiltinOperatorType.Inequality)); nullCheckSymbol = nullCheckCondition.Invoke(new SymbolDefinition[] { invokeResult, visitorContext.topTable.CreateConstSymbol(typeof(object), null) }); } visitorContext.uasmBuilder.AddJumpIfFalse(falseBranchLoc, nullCheckSymbol); resultSetterScope.ExecuteSet(captureScope.CastSymbolToType(invokeResult, resultSymbolType, true)); visitorContext.uasmBuilder.AddJump(exitBranchJump); // If the value is null visitorContext.uasmBuilder.AddJumpLabel(falseBranchLoc); if (captureFunc == InternalFunc.TypeIDInstance) { resultSetterScope.ExecuteSet(visitorContext.topTable.CreateConstSymbol(typeof(long), 0L)); } else { resultSetterScope.ExecuteSet(visitorContext.topTable.CreateConstSymbol(typeof(string), "UnknownType")); } visitorContext.uasmBuilder.AddJumpLabel(exitBranchJump); } } } else { object resultSymbolValue = null; if (captureFunc == InternalFunc.TypeIDGeneric) { resultSymbolValue = Internal.UdonSharpInternalUtility.GetTypeID(genericType); } else if (captureFunc == InternalFunc.TypeNameGeneric) { resultSymbolValue = Internal.UdonSharpInternalUtility.GetTypeName(genericType); } methodResult = visitorContext.topTable.CreateConstSymbol(resultSymbolType, resultSymbolValue); } using (ExpressionCaptureScope propagateScope = new ExpressionCaptureScope(visitorContext, visitorContext.topCaptureScope)) { propagateScope.SetToLocalSymbol(methodResult); } return(methodResult); }
public override void VisitClassDeclaration(ClassDeclarationSyntax node) { UpdateSyntaxNode(node); using (ExpressionCaptureScope classTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { foreach (string namespaceToken in namespaceStack.Reverse()) { classTypeCapture.ResolveAccessToken(namespaceToken); if (classTypeCapture.IsNamespace()) { visitorContext.resolverContext.AddNamespace(classTypeCapture.captureNamespace); } } classTypeCapture.ResolveAccessToken(node.Identifier.ValueText); if (!classTypeCapture.IsType()) { throw new System.Exception($"User type {node.Identifier.ValueText} could not be found"); } } if (node.AttributeLists != null) { foreach (AttributeListSyntax attributeList in node.AttributeLists) { foreach (AttributeSyntax attribute in attributeList.Attributes) { System.Type captureType = null; using (ExpressionCaptureScope attributeTypeScope = new ExpressionCaptureScope(visitorContext, null)) { attributeTypeScope.isAttributeCaptureScope = true; Visit(attribute.Name); captureType = attributeTypeScope.captureType; } if (captureType != null && captureType == typeof(UdonBehaviourSyncModeAttribute)) { if (attribute.ArgumentList != null && attribute.ArgumentList.Arguments != null && attribute.ArgumentList.Arguments.Count == 1) { using (ExpressionCaptureScope attributeCaptureScope = new ExpressionCaptureScope(visitorContext, null)) { Visit(attribute.ArgumentList.Arguments[0].Expression); if (!attributeCaptureScope.IsEnum()) { throw new System.Exception("Invalid attribute argument provided for behaviour sync"); } visitorContext.behaviourSyncMode = (BehaviourSyncMode)attributeCaptureScope.GetEnumValue(); } } } } } } if (syntaxWalkerDepth == UdonSharpSyntaxWalkerDepth.ClassDefinitions || syntaxWalkerDepth == UdonSharpSyntaxWalkerDepth.ClassMemberBodies) { base.VisitClassDeclaration(node); } }
public InternalMethodHandler(ASTVisitorContext visitorContextIn, ExpressionCaptureScope captureScopeIn) { visitorContext = visitorContextIn; captureScope = captureScopeIn; }
public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { UpdateSyntaxNode(node); MethodDefinition methodDefinition = new MethodDefinition(); methodDefinition.declarationFlags = node.Modifiers.HasModifier("public") ? MethodDeclFlags.Public : MethodDeclFlags.Private; methodDefinition.methodUdonEntryPoint = visitorContext.labelTable.GetNewJumpLabel("udonMethodEntryPoint"); methodDefinition.methodUserCallStart = visitorContext.labelTable.GetNewJumpLabel("userMethodCallEntry"); methodDefinition.methodReturnPoint = visitorContext.labelTable.GetNewJumpLabel("methodReturnPoint"); string methodName = node.Identifier.ValueText; methodDefinition.originalMethodName = methodName; methodDefinition.uniqueMethodName = methodDefinition.originalMethodName; visitorContext.resolverContext.ReplaceInternalEventName(ref methodDefinition.uniqueMethodName); foreach (string builtinMethodName in builtinMethodNames) { if (methodName == builtinMethodName) { throw new System.Exception($"Cannot define method '{methodName}' with the same name as a built-in UdonSharpBehaviour method"); } } // Resolve the type arguments using (ExpressionCaptureScope returnTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.ReturnType); if (returnTypeCapture.captureType != typeof(void)) { methodDefinition.returnSymbol = visitorContext.topTable.CreateNamedSymbol("returnValSymbol", returnTypeCapture.captureType, SymbolDeclTypeFlags.Internal); if (!visitorContext.resolverContext.IsValidUdonType(returnTypeCapture.captureType)) { throw new System.NotSupportedException($"Udon does not support return values of type '{returnTypeCapture.captureType.Name}' yet"); } } } methodDefinition.parameters = new ParameterDefinition[node.ParameterList.Parameters.Count]; for (int i = 0; i < node.ParameterList.Parameters.Count; ++i) { ParameterSyntax parameter = node.ParameterList.Parameters[i]; ParameterDefinition paramDef = new ParameterDefinition(); using (ExpressionCaptureScope paramTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(parameter.Type); if (!paramTypeCapture.IsType()) { throw new System.TypeLoadException($"The type or namespace name '{parameter.Type}' could not be found (are you missing a using directive?)"); } if (!visitorContext.resolverContext.IsValidUdonType(paramTypeCapture.captureType)) { throw new System.NotSupportedException($"Udon does not support method parameters of type '{paramTypeCapture.captureType.Name}' yet"); } paramDef.type = paramTypeCapture.captureType; paramDef.symbolName = parameter.Identifier.ValueText; paramDef.paramSymbol = visitorContext.topTable.CreateNamedSymbol(parameter.Identifier.ValueText, paramDef.type, SymbolDeclTypeFlags.Local | SymbolDeclTypeFlags.MethodParameter); } methodDefinition.parameters[i] = paramDef; } definedMethods.Add(methodDefinition); }
public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) { UpdateSyntaxNode(node); PropertyDefinition propertyDefinition = new PropertyDefinition(); propertyDefinition.declarationFlags = node.Modifiers.HasModifier("public") ? PropertyDeclFlags.Public : PropertyDeclFlags.Private; propertyDefinition.originalPropertyName = node.Identifier.Text; Type type = null; using (ExpressionCaptureScope propertyTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Type); type = propertyTypeCapture.captureType; if (!visitorContext.resolverContext.IsValidUdonType(type)) { throw new NotSupportedException($"Udon does not support variable of type '{type}' yet"); } } BackingFieldDefinition backingField = new BackingFieldDefinition(); backingField.backingFieldName = $"{node.Identifier.Text}_k_BackingField"; if (node.AttributeLists != null && node.AttributeLists.Any()) { foreach (AttributeListSyntax attributes in node.AttributeLists) { if (attributes.Target != null && attributes.Target.Identifier.Kind() == SyntaxKind.FieldKeyword) { foreach (AttributeSyntax attribute in attributes.Attributes) { using (ExpressionCaptureScope attributeTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { attributeTypeCapture.isAttributeCaptureScope = true; Visit(attribute.Name); backingField.synced = true; if (attributeTypeCapture.captureType != typeof(UdonSyncedAttribute)) { continue; } if (attribute.ArgumentList == null || attribute.ArgumentList.Arguments == null || attribute.ArgumentList.Arguments.Count == 0) { backingField.syncMode = UdonSyncMode.None; } else { using (ExpressionCaptureScope attributeCaptureScope = new ExpressionCaptureScope(visitorContext, null)) { Visit(attribute.ArgumentList.Arguments[0].Expression); if (!attributeCaptureScope.IsEnum()) { throw new Exception("Invalid attribute argument provided for sync"); } backingField.syncMode = (UdonSyncMode)attributeCaptureScope.GetEnumValue(); } } break; } } } if (backingField.synced) { break; } } } backingField.type = type; propertyDefinition.type = type; backingField.type = type; if (node.AccessorList != null) { foreach (AccessorDeclarationSyntax accessor in node.AccessorList.Accessors) { bool isSetter = accessor.Keyword.Kind() == SyntaxKind.SetKeyword; if (isSetter) { SetterDefinition setter = new SetterDefinition(); setter.accessorName = $"_set_{node.Identifier.Text}"; setter.entryPoint = visitorContext.labelTable.GetNewJumpLabel("udonMethodEntryPoint"); setter.userCallStart = visitorContext.labelTable.GetNewJumpLabel("userMethodCallEntry"); setter.returnPoint = visitorContext.labelTable.GetNewJumpLabel("methodReturnPoint"); setter.backingField = (accessor.Body == null && accessor.ExpressionBody == null) ? backingField : null; setter.type = type; setter.declarationFlags = GetDeclFlags(accessor); setter.paramSymbol = visitorContext.topTable.CreateNamedSymbol("value", type, SymbolDeclTypeFlags.Local | SymbolDeclTypeFlags.MethodParameter); propertyDefinition.setter = setter; } else { GetterDefinition getter = new GetterDefinition(); getter.accessorName = $"_get_{node.Identifier.Text}"; getter.entryPoint = visitorContext.labelTable.GetNewJumpLabel("udonMethodEntryPoint"); getter.userCallStart = visitorContext.labelTable.GetNewJumpLabel("userMethodCallEntry"); getter.returnPoint = visitorContext.labelTable.GetNewJumpLabel("methodReturnPoint"); getter.backingField = (accessor.Body == null && accessor.ExpressionBody == null) ? backingField : null; getter.type = type; getter.declarationFlags = GetDeclFlags(accessor); using (ExpressionCaptureScope returnTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Type); getter.returnSymbol = visitorContext.topTable.CreateNamedSymbol("returnValSymbol", returnTypeCapture.captureType, SymbolDeclTypeFlags.Internal); } propertyDefinition.getter = getter; } } } else { GetterDefinition getter = new GetterDefinition(); getter.accessorName = $"_get_{node.Identifier.Text}"; getter.entryPoint = visitorContext.labelTable.GetNewJumpLabel("udonMethodEntryPoint"); getter.userCallStart = visitorContext.labelTable.GetNewJumpLabel("userMethodCallEntry"); getter.returnPoint = visitorContext.labelTable.GetNewJumpLabel("methodReturnPoint"); getter.type = type; getter.declarationFlags = PropertyDeclFlags.Public; using (ExpressionCaptureScope returnTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(node.Type); getter.returnSymbol = visitorContext.topTable.CreateNamedSymbol("returnValSymbol", returnTypeCapture.captureType, SymbolDeclTypeFlags.Internal); } propertyDefinition.getter = getter; } if (propertyDefinition.setter?.backingField != null || propertyDefinition.getter?.backingField != null) { backingField.fieldSymbol = visitorContext.topTable.CreateNamedSymbol("kBackingField", type, SymbolDeclTypeFlags.Internal | SymbolDeclTypeFlags.PropertyBackingField); backingField.fieldSymbol.syncMode = backingField.syncMode; if (backingField.synced) { VerifySyncValidForType(backingField.type, backingField.fieldSymbol.syncMode); } } definedProperties.Add(propertyDefinition); }
private List <System.Attribute> GetFieldAttributes(FieldDeclarationSyntax node) { List <System.Attribute> attributes = new List <System.Attribute>(); if (node.AttributeLists != null) { foreach (AttributeListSyntax attributeList in node.AttributeLists) { UpdateSyntaxNode(attributeList); foreach (AttributeSyntax attribute in attributeList.Attributes) { using (ExpressionCaptureScope attributeTypeCapture = new ExpressionCaptureScope(visitorContext, null)) { attributeTypeCapture.isAttributeCaptureScope = true; Visit(attribute.Name); System.Type captureType = attributeTypeCapture.captureType; if (captureType == typeof(UdonSyncedAttribute)) { UdonSyncMode syncMode = UdonSyncMode.NotSynced; if (attribute.ArgumentList == null || attribute.ArgumentList.Arguments == null || attribute.ArgumentList.Arguments.Count == 0) { syncMode = UdonSyncMode.None; } else { using (ExpressionCaptureScope attributeCaptureScope = new ExpressionCaptureScope(visitorContext, null)) { Visit(attribute.ArgumentList.Arguments[0].Expression); if (!attributeCaptureScope.IsEnum()) { throw new System.Exception("Invalid attribute argument provided for sync"); } syncMode = (UdonSyncMode)attributeCaptureScope.GetEnumValue(); } } attributes.Add(new UdonSyncedAttribute(syncMode)); } else if (captureType != null) { try { object attributeObject = null; if (attribute.ArgumentList == null || attribute.ArgumentList.Arguments == null || attribute.ArgumentList.Arguments.Count == 0) { attributeObject = System.Activator.CreateInstance(captureType); } else { // todo: requires constant folding to support decently object[] attributeArgs = new object[attribute.ArgumentList.Arguments.Count]; for (int i = 0; i < attributeArgs.Length; ++i) { AttributeArgumentSyntax attributeArg = attribute.ArgumentList.Arguments[i]; using (ExpressionCaptureScope attributeCapture = new ExpressionCaptureScope(visitorContext, null)) { Visit(attributeArg); SymbolDefinition attrSymbol = attributeCapture.ExecuteGet(); if (!attrSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant)) { throw new System.ArgumentException("Attributes do not support non-constant expressions"); } attributeArgs[i] = attrSymbol.symbolDefaultValue; } } attributeObject = System.Activator.CreateInstance(captureType, attributeArgs); } if (attributeObject != null) { attributes.Add((System.Attribute)attributeObject); } } catch (System.Reflection.TargetInvocationException constructionException) { throw constructionException.InnerException; } } } } } } return(attributes); }