public SymbolDefinition CreateReflectionSymbol(string name, System.Type type, object value) { if (value != null && !type.IsAssignableFrom(value.GetType())) { throw new ArgumentException($"Non-compatible value given for type {type.FullName}"); } SymbolDefinition symbolDefinition = GetReflectionSymbol(name, type); if (symbolDefinition == null) { symbolDefinition = CreateNamedSymbol(name, type, SymbolDeclTypeFlags.Internal | SymbolDeclTypeFlags.Constant | SymbolDeclTypeFlags.Reflection); symbolDefinition.symbolDefaultValue = value; } return(symbolDefinition); }
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; } }
public SymbolDefinition GetReflectionSymbol(string name, System.Type type) { SymbolDefinition symbolDefinition = null; SymbolTable globalSymbols = GetGlobalSymbolTable(); foreach (SymbolDefinition currentSymbol in globalSymbols.symbolDefinitions) { if (currentSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Reflection) && currentSymbol.symbolOriginalName == name && currentSymbol.symbolCsType == type) { symbolDefinition = currentSymbol; break; } } return(symbolDefinition); }
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)); } }
/// <summary> /// Tries to find a global constant that already has a given constant value to avoid duplication /// </summary> /// <param name="type"></param> /// <param name="value"></param> /// <param name="foundSymbol"></param> /// <returns></returns> public bool TryGetGlobalConstSymbol(System.Type type, object value, out SymbolDefinition foundSymbol) { SymbolTable globalSymTable = GetGlobalSymbolTable(); foreach (SymbolDefinition definition in globalSymTable.symbolDefinitions) { if (definition.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && definition.declarationType.HasFlag(SymbolDeclTypeFlags.Internal) && definition.symbolCsType == type && ((value == null && definition.symbolDefaultValue == null) || (definition.symbolDefaultValue != null && definition.symbolDefaultValue.Equals(value)))) { foundSymbol = definition; return(true); } } foundSymbol = null; return(false); }
/// <summary> /// Tries to find a global constant that already has a given constant value to avoid duplication /// </summary> /// <param name="type"></param> /// <param name="value"></param> /// <param name="foundSymbol"></param> /// <returns></returns> public bool TryGetGlobalSymbol(System.Type type, object value, out SymbolDefinition foundSymbol, SymbolDeclTypeFlags flags) { SymbolTable globalSymTable = GetGlobalSymbolTable(); foreach (SymbolDefinition definition in globalSymTable.symbolDefinitions) { bool hasFlags = ((int)flags & (int)definition.declarationType) == (int)flags; if (hasFlags && definition.symbolCsType == type && ((value == null && definition.symbolDefaultValue == null) || (definition.symbolDefaultValue != null && definition.symbolDefaultValue.Equals(value)))) { foundSymbol = definition; return(true); } } foundSymbol = null; return(false); }
public SymbolDefinition FindUserDefinedSymbol(string symbolName) { SymbolTable currentTable = this; while (currentTable != null) { //foreach (SymbolDefinition symbolDefinition in currentTable.symbolDefinitions) for (int i = currentTable.symbolDefinitions.Count - 1; i >= 0; --i) { SymbolDefinition symbolDefinition = currentTable.symbolDefinitions[i]; if (!symbolDefinition.declarationType.HasFlag(SymbolDeclTypeFlags.Internal) && symbolDefinition.symbolOriginalName == symbolName) { return(symbolDefinition); } } currentTable = currentTable.parentSymbolTable; } // Found nothing, return null return(null); }
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); }
/// <summary> /// Create a symbol given a name. At the moment assumes that only internal symbols get incremented, this means there's no masking at the moment for local variables. /// </summary> /// <param name="symbolName"></param> /// <param name="resolvedSymbolType"></param> /// <param name="declType"></param> /// <param name="appendType">Used to disable redundant type append from unnamed variable allocations</param> /// <returns></returns> private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Type resolvedSymbolType, SymbolDeclTypeFlags declType, bool appendType = true) { if (resolvedSymbolType == null || symbolName == null) { throw new System.ArgumentNullException(); } if (!declType.HasFlag(SymbolDeclTypeFlags.Internal) && symbolName.StartsWith("__")) { throw new System.ArgumentException($"Symbol {symbolName} cannot have name starting with \"__\", this naming is reserved for internal variables."); } string uniqueSymbolName = symbolName; bool hasGlobalDeclaration = false; if (declType.HasFlag(SymbolDeclTypeFlags.Internal)) { uniqueSymbolName = $"intnl_{uniqueSymbolName}"; } if (declType.HasFlag(SymbolDeclTypeFlags.Constant)) { uniqueSymbolName = $"const_{uniqueSymbolName}"; hasGlobalDeclaration = true; } if (declType.HasFlag(SymbolDeclTypeFlags.This)) { uniqueSymbolName = $"this_{uniqueSymbolName}"; hasGlobalDeclaration = true; } if (!declType.HasFlag(SymbolDeclTypeFlags.Public) && !declType.HasFlag(SymbolDeclTypeFlags.Private)) { if (appendType) { string sanitizedName = resolver.SanitizeTypeName(resolvedSymbolType.Name); uniqueSymbolName += $"_{sanitizedName}"; } if (hasGlobalDeclaration) { uniqueSymbolName = $"__{IncrementGlobalNameCounter(uniqueSymbolName)}_{uniqueSymbolName}"; } else { uniqueSymbolName = $"__{IncrementUniqueNameCounter(uniqueSymbolName)}_{uniqueSymbolName}"; } } System.Type typeForName = resolvedSymbolType; if (resolvedSymbolType == typeof(UdonSharpBehaviour) || resolvedSymbolType.IsSubclassOf(typeof(UdonSharpBehaviour))) { typeForName = typeof(VRC.Udon.UdonBehaviour); } else if (resolvedSymbolType.IsArray && (resolvedSymbolType.GetElementType() == typeof(UdonSharpBehaviour) || resolvedSymbolType.GetElementType().IsSubclassOf(typeof(UdonSharpBehaviour)))) { typeForName = typeof(Component[]); // Hack because VRC doesn't expose UdonBehaviour array type } string udonTypeName = resolver.GetUdonTypeName(typeForName); if (udonTypeName == null) { throw new System.ArgumentException($"Could not locate Udon type for system type {resolvedSymbolType.FullName}"); } udonTypeName = udonTypeName.Replace("VRCUdonCommonInterfacesIUdonEventReceiver", "VRCUdonUdonBehaviour"); SymbolDefinition symbolDefinition = new SymbolDefinition(); symbolDefinition.declarationType = declType; symbolDefinition.symbolCsType = resolvedSymbolType; symbolDefinition.symbolOriginalName = symbolName; symbolDefinition.symbolResolvedTypeName = udonTypeName; symbolDefinition.symbolUniqueName = uniqueSymbolName; if (hasGlobalDeclaration) { GetGlobalSymbolTable().symbolDefinitions.Add(symbolDefinition); } else { symbolDefinitions.Add(symbolDefinition); } return(symbolDefinition); }
public FieldDefinition(SymbolDefinition symbol) { fieldSymbol = symbol; fieldAttributes = new List <System.Attribute>(); }
public void AddJumpIndirect(SymbolDefinition addressSymbol, string comment = "") { //throw new System.NotImplementedException("Jump indirect instruction is not implemented in UdonSharp yet."); // I'm not sure why JUMP_INDIRECT both takes an address and pops an address from the stack AppendCommentedLine($"JUMP_INDIRECT, {addressSymbol.symbolUniqueName}", comment); programCounter += UdonSharpUtils.GetUdonInstructionSize("JUMP_INDIRECT"); }
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); }