public COWValueInternal(ASTVisitorContext visitorContext, SymbolDefinition symbol) { this.symbol = this.originalSymbol = symbol; this.visitorContext = visitorContext; tableCreationScope = visitorContext.topTable; tableCreationScope.AddSymbolCOW(this); }
public void MarkDirty() { if (referenceCount == 0) { isDirty = true; symbol = null; return; } if (!isDirty) { SymbolDefinition temporary = visitorContext.topTable.CreateUnnamedSymbol(symbol.internalType, SymbolDeclTypeFlags.Internal | SymbolDeclTypeFlags.Local); visitorContext.uasmBuilder.AddCopy(temporary, symbol, " Copy-on-write symbol value dirtied"); symbol = temporary; isDirty = true; } }
// Where we handle creating constants and such public override void VisitLiteralExpression(LiteralExpressionSyntax node) { UpdateSyntaxNode(node); SymbolDefinition expressionConstant = null; switch (node.Kind()) { case SyntaxKind.NumericLiteralExpression: // The Roslyn AST figures out the type automagically for you based on how the token is declared :D // Can probably flatten out the other ones into this too expressionConstant = visitorContext.topTable.CreateConstSymbol(node.Token.Value.GetType(), node.Token.Value); break; case SyntaxKind.StringLiteralExpression: expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(string), node.Token.Value); break; case SyntaxKind.CharacterLiteralExpression: expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(char), node.Token.Value); break; case SyntaxKind.TrueLiteralExpression: expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(bool), true); break; case SyntaxKind.FalseLiteralExpression: expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(bool), false); break; case SyntaxKind.NullLiteralExpression: expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(object), null); break; default: base.VisitLiteralExpression(node); return; } if (expressionConstant != null && visitorContext.topCaptureScope != null) { visitorContext.topCaptureScope.SetToLocalSymbol(expressionConstant); } }
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); }
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); }
public void AddCopy(SymbolDefinition target, SymbolDefinition source, string comment = "") { AddPush(source); AddPush(target); AddCopy(comment); }
public void AddReturnSequence(SymbolDefinition returnTrampolineSymbol, string comment = "") { AddPush(returnTrampolineSymbol, comment); AddCopy(); AddJumpIndirect(returnTrampolineSymbol); }
public void AddJumpIndirect(SymbolDefinition addressSymbol, string comment = "") { AppendCommentedLine($"JUMP_INDIRECT, {addressSymbol.symbolUniqueName}", comment); programCounter += UdonSharpUtils.GetUdonInstructionSize("JUMP_INDIRECT"); }
public void AddJumpIfFalse(JumpLabel jumpTarget, SymbolDefinition conditionSymbol, string comment = "") { AddPush(conditionSymbol); AddJumpIfFalse(jumpTarget, comment); }
public void AddPush(SymbolDefinition heapAddressSymbol, string comment = "") { AddPush(heapAddressSymbol.symbolUniqueName, comment); }
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 FieldDefinition(SymbolDefinition symbol) { fieldSymbol = symbol; fieldAttributes = new List <System.Attribute>(); }