/// <summary> /// Optimize expressions /// </summary> public static void Convert(AstBlock ast) { var variableExpressions = ast.GetExpressions().Where(x => x.Operand is AstVariable).ToList(); var allVariables = variableExpressions.Select(x => (AstVariable)x.Operand).Distinct().ToList(); var allStructVariables = allVariables.Where(x => x.Type.IsStruct()).ToList(); var index = 0; foreach (var iterator in allStructVariables) { var variable = iterator; if (variable.IsThis || variable.IsParameter) { continue; } if (variableExpressions.Any(x => (x.Operand == variable) && (x.Code == AstCode.Stloc))) { continue; } // Get struct type var structType = variable.Type.Resolve(); var defaultCtorDef = StructCallConverter.GetDefaultValueCtor(structType); var defaultCtor = variable.Type.CreateReference(defaultCtorDef); // Variable is not initialized var newObjExpr = new AstExpression(ast.SourceLocation, AstCode.Newobj, defaultCtor).SetType(variable.Type); var initExpr = new AstExpression(ast.SourceLocation, AstCode.Stloc, variable, newObjExpr).SetType(variable.Type); ast.Body.Insert(index++, initExpr); } }
private static void ConvertUnboxStruct(AstExpression node, XTypeReference resultType, XTypeSystem typeSystem) { // Structs must never be null. We have to handle structs here, since a newobj // might need generic arguments. These would be difficult to provide at "UnboxFromGeneric", // but will be automatically filled in by the GenericInstanceConverter // convert to (temp$ = (T)x) != null ? temp$ : default(T) // replace any unbox, but keep if otherwise. var clone = node.Code == AstCode.Unbox ? new AstExpression(node.Arguments[0]) : new AstExpression(node); // make sure we don't evaluate the expression twice. var tempVar = new AstGeneratedVariable("temp$", "") { Type = typeSystem.Object }; // T(x) var txExpr = new AstExpression(node.SourceLocation, AstCode.SimpleCastclass, resultType, clone) .SetType(resultType); // temporary storage var storeTempVar = new AstExpression(node.SourceLocation, AstCode.Stloc, tempVar, txExpr) { ExpectedType = resultType }; var loadTempVar = new AstExpression(node.SourceLocation, AstCode.Ldloc, tempVar) .SetType(resultType); // default (T) var defaultT = new AstExpression(node.SourceLocation, AstCode.DefaultValue, resultType).SetType(resultType); var constructor = StructCallConverter.GetDefaultValueCtor(resultType.Resolve()); StructCallConverter.ConvertDefaultValue(defaultT, constructor); // Combine var conditional = new AstExpression(node.SourceLocation, AstCode.Conditional, resultType, storeTempVar, loadTempVar, defaultT) .SetType(resultType); node.CopyFrom(conditional); }