Statement CreateBuildError(Source src, bool isError, AstExpression value = null) { var type = "build_" + (isError ? "error" : "warning"); if (!IsFunctionScope) { return(Error(src, ErrorCode.E0000, type.Quote() + " can only be used in methods")); } var message = value != null ? Compiler.CompileConstant(value, Namescope, Essentials.String).Value as string ?? "<invalid>" : Function.Quote() + " does not support this build target"; if (isError) { /*if (!Compiler.Backend.IsDefault) * Log.Error(s.Source, ErrorCode.E0000, message);*/ return(new Throw(src, ILFactory.NewObject(src, Essentials.Exception, new Constant(src, Essentials.String, type + ": " + message)))); } if (!Compiler.Backend.IsDefault) { Log.Warning(src, ErrorCode.W0000, type + ": " + message); } return(new NoOp(src, message)); }
Field GetField(Draw draw) { var prog = GetProgram(draw); var key = Type + ":" + prog; Field result; if (!_fields.TryGetValue(key, out result)) { var src = draw.Source; var initMethod = Type.TryGetMethod("init_DrawCalls", false); if (initMethod == null) { throw new SourceException(src, "No 'init_DrawCalls()' method was found in " + Type.Quote()); } var dc = ILFactory.NewObject(src, "Uno.Graphics.OpenGL.GLDrawCall", prog); result = new Field(src, Type, "_draw_" + draw.State.Path.Suffix, null, Modifiers.Private | Modifiers.Generated, 0, dc.ReturnType); initMethod.Body.Statements.Add(new StoreField(src, new This(src, Type), result, dc)); Type.Fields.Add(result); _fields.Add(key, result); } return(result); }
Expression ProcessVertexBuffer(StageValue vertexBuffer) { Expression result; if (!VertexBuffers.TryGetValue(vertexBuffer.Value.ToString(), out result)) { var src = vertexBuffer.Value.Source; var type = ILFactory.GetType(src, "Uno.Graphics.VertexBuffer"); if (vertexBuffer.Value.ReturnType.Equals(type)) { result = ProcessStage(vertexBuffer, MetaStage.Volatile, MetaStage.Volatile).Value; VertexBuffers.Add(vertexBuffer.Value.ToString(), result); return(result); } var loc = LocationStack.Last(); var mp = GetProperty(loc); var name = CreateFieldName(mp, loc); var owner = Path.DrawBlock.Method.DeclaringType; var field = new Field(src, owner, name, null, Modifiers.Private | Modifiers.Generated, 0, type); owner.Fields.Add(field); result = new LoadField(src, new This(src, owner), field); VertexBuffers.Add(vertexBuffer.Value.ToString(), result); if (vertexBuffer.MinStage > MetaStage.Volatile) { Log.Error(src, ErrorCode.E5025, "Vertex buffer cannot be accessed from " + vertexBuffer.MinStage + " stage"); return(result); } else if (vertexBuffer.MinStage == MetaStage.Volatile) { InitScope.Statements.Add( new StoreField(src, new This(src, owner), field, ILFactory.NewObject(src, "Uno.Graphics.VertexBuffer", ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Dynamic")))); FrameScope.Statements.Add( ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Update", vertexBuffer.Value)); } else { InitScope.Statements.Add( new StoreField(src, new This(src, owner), field, ILFactory.NewObject(src, "Uno.Graphics.VertexBuffer", vertexBuffer.Value, ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Immutable")))); } FreeScope.Statements.Add( ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Dispose")); } return(result); }
private void RegisterTestMethods() { var registryObject = ILFactory.NewObject(_source, _testRegistryType); var registryVariable = new Variable(_source, _mainConstructor, "registry", _testRegistryType, VariableType.Default, registryObject); var body = new Scope(_source); body.Statements.Add(new CallConstructor(_source, _appClass.Constructors[0])); body.Statements.Add(new VariableDeclaration(registryVariable)); var methods = _methods; if (_testOptions.Filter != null) { var regex = new Regex(_testOptions.Filter, RegexOptions.CultureInvariant); methods = methods.Where(m => regex.IsMatch(m.FullName)).ToList(); } methods.Sort((a, b) => string.Compare(a.FullName, b.FullName, StringComparison.InvariantCultureIgnoreCase)); var ret = new List <TestMethod>(); foreach (var method in methods) { var testMethod = CreateTestMethod(method); var invokerMethod = CreateInvoker(method); var invokerInstance = InstantiateTestFixture(invokerMethod); var testExpression = RegisterTest(testMethod, new LoadLocal(_source, registryVariable), new NewDelegate(_source, _actionType, invokerInstance, invokerMethod)); body.Statements.Add(testExpression); ret.Add(testMethod); } var registryExpr = new LoadLocal(_source, registryVariable); var testSetupConstruction = ILFactory.NewObject(_source, _testSetupType, registryExpr); body.Statements.Add(new StoreField(_source, new This(_source, _mainClass), _testSetupField, testSetupConstruction)); _mainConstructor.SetBody(body); }
Closure CreateClosure(Closure parent, HashSet <Variable> locals) { if (parent != null && locals.Count == 0) { return(parent); } var type = new ClassType( Source.Unknown, Function.DeclaringType, Function.Name + " lambda closure", Modifiers.Private | Modifiers.Generated, Function.DeclaringType.GetUniqueIdentifier(Function.Name + "_$closure")); type.SetBase(Essentials.Object); var constrBody = new Scope( Source.Unknown, new CallConstructor(Source.Unknown, Essentials.Object.TryGetConstructor())); type.Constructors.Add( new Constructor( Source.Unknown, type, "", Modifiers.Public | Modifiers.Generated, ParameterList.Empty, constrBody)); Function.DeclaringType.NestedTypes.Add(type); _generatedTypes.Add(type); var decl = new VariableDeclaration( Source.Unknown, Function, Function.DeclaringType.GetUniqueIdentifier("generated_closure"), type, optionalValue: ILFactory.NewObject(type)); var statements = new List <Statement>(); statements.Add(decl); var result = new Closure(type, statements, new LoadLocal(Source.Unknown, decl.Variable), parent); // The root closure gets 'this' and the params if (parent == null) { if (_closureVars.This) { var field = new Field( Source.Unknown, type, type.GetUniqueIdentifier("self"), "", Modifiers.Public | Modifiers.Generated, 0, Function.DeclaringType); type.Fields.Add(field); statements.Add(result.StoreThis(new This(Function.DeclaringType))); } foreach (var p in _closureVars.Params) { var field = new Field( p.Source, type, type.GetUniqueIdentifier(p.Name), "", Modifiers.Public | Modifiers.Generated, 0, p.Type); type.Fields.Add(field); result.ParameterFields[p] = field; statements.Add(result.Store(p, new LoadArgument(Source.Unknown, Function, ParamIndex(p)))); } } // Non-root closures get a parent field for the parent closure else { type.Fields.Add( new Field( Source.Unknown, type, type.GetUniqueIdentifier("parent"), "", Modifiers.Public | Modifiers.Generated, 0, parent.Type)); statements.Add(result.StoreParent(parent.Expression)); } foreach (var v in locals) { var field = new Field( v.Source, type, type.GetUniqueIdentifier(v.Name), "", Modifiers.Public | Modifiers.Generated, 0, v.ValueType); type.Fields.Add(field); result.VariableFields[v] = field; } return(result); }
void ProcessIndexBuffer(Source vaSrc, StageValue indexBuffer, StageValue indexType) { if (IndexBuffer == null && indexBuffer.Value == null && IndexType == null && indexType.Value == null || indexBuffer.Value != null && IndexBuffer == indexBuffer.Value.ToString() && indexType.Value != null && IndexType == indexType.Value.ToString()) { // OK return; } if (IndexBuffer != null || indexBuffer.Value == null || IndexType != null || indexType.Value == null) { Log.Error(vaSrc, ErrorCode.E5023, "Index buffer argument must be consistent for all <vertex_attrib>s in " + Path.Quote()); return; } var src = indexBuffer.Value.Source; var type = ILFactory.GetType(src, "Uno.Graphics.IndexBuffer"); IndexBuffer = indexBuffer.Value.ToString(); IndexType = indexType.Value.ToString(); if (indexBuffer.Value.ReturnType.Equals(type)) { DrawState.OptionalIndices = new IndexBinding( ProcessStage(indexType, MetaStage.Volatile, MetaStage.Volatile).Value, ProcessStage(indexBuffer, MetaStage.Volatile, MetaStage.Volatile).Value); return; } var loc = LocationStack.Last(); var mp = GetProperty(loc); var name = CreateFieldName(mp, loc); var owner = Path.DrawBlock.Method.DeclaringType; var field = new Field(src, owner, name, null, Modifiers.Private | Modifiers.Generated, 0, type); owner.Fields.Add(field); DrawState.OptionalIndices = new IndexBinding( ProcessStage(indexType, MetaStage.Volatile, MetaStage.Volatile).Value, new LoadField(src, new This(src, owner), field)); if (indexBuffer.MinStage > MetaStage.Volatile) { Log.Error(src, ErrorCode.E5024, "Index buffer cannot be accessed from " + indexBuffer.MinStage + " stage"); return; } if (indexBuffer.MinStage == MetaStage.Volatile) { InitScope.Statements.Add( new StoreField(src, new This(src, owner), field, ILFactory.NewObject(src, "Uno.Graphics.IndexBuffer", ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Dynamic")))); FrameScope.Statements.Add( ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Update", indexBuffer.Value)); } else { InitScope.Statements.Add( new StoreField(src, new This(src, owner), field, ILFactory.NewObject(src, "Uno.Graphics.IndexBuffer", indexBuffer.Value, ILFactory.GetExpression(src, "Uno.Graphics.BufferUsage.Immutable")))); } FreeScope.Statements.Add( ILFactory.CallMethod(src, new LoadField(src, new This(src, owner), field), "Dispose")); }
Expression TryCompileImplicitCast(Source src, DataType expectedType, Expression value, bool reportErrorIfNotFound) { if (ImplicitCastStack.Contains(expectedType)) { ImplicitCastStack.Add(expectedType); } else { ImplicitCastStack.Add(expectedType); if (Equals(expectedType, value.ReturnType)) { return(value); } if (value.ReturnType is InvalidType || expectedType is InvalidType) { return(Expression.Invalid); } // (EnumType)0 if (expectedType is EnumType && value is Constant && value.ConstantValue is int && (int)value.ConstantValue == 0) { return(new Constant(value.Source, (EnumType)expectedType, (int)value.ConstantValue)); } // Null type (must be done before delegate) if (value.ReturnType.IsNull) { return(expectedType.IsReferenceType ? new Constant(src, expectedType, null) : !reportErrorIfNotFound ? null : Error(src, ErrorCode.E2043, "'<null>' has no implicit cast to " + expectedType.Quote() + " because that is not a reference type")); } // Delegate if (expectedType is DelegateType && value is MethodGroup) { var dt = expectedType as DelegateType; dt.AssignBaseType(); var mg = value as MethodGroup; var candidates = mg.Candidates; var compatibleMethods = new List <Method>(); foreach (var m in candidates) { if (!m.IsGenericDefinition && m.ReturnType.Equals(dt.ReturnType) && dt.CompareParameters(m)) { compatibleMethods.Add(m); } } if (compatibleMethods.Count == 0) { foreach (var c in candidates) { if (c.IsGenericDefinition) { var dummyArgs = new Expression[dt.Parameters.Length]; for (int i = 0; i < dummyArgs.Length; i++) { var p = dt.Parameters[i]; dummyArgs[i] = new Default(p.Source, p.Type); switch (p.Modifier) { case ParameterModifier.Const: dummyArgs[i] = new AddressOf(dummyArgs[i], AddressType.Const); break; case ParameterModifier.Ref: dummyArgs[i] = new AddressOf(dummyArgs[i], AddressType.Ref); break; case ParameterModifier.Out: dummyArgs[i] = new AddressOf(dummyArgs[i], AddressType.Out); break; } } candidates = CopyAndParameterizeGenericMethods(src, candidates, dummyArgs); foreach (var m in candidates) { if (!m.IsGenericDefinition && m.ReturnType.Equals(dt.ReturnType) && dt.CompareParameters(m)) { compatibleMethods.Add(m); } } break; } } if (compatibleMethods.Count == 0) { foreach (var m in candidates) { if (!m.IsGenericDefinition && (m.ReturnType.Equals(dt.ReturnType) || m.ReturnType.IsReferenceType && m.ReturnType.IsSubclassOfOrEqual(dt.ReturnType)) && dt.CompareParametersEqualOrSubclassOf(m)) { compatibleMethods.Add(m); } } } } if (compatibleMethods.Count == 1) { var m = compatibleMethods[0]; if (m.IsStatic) { return(new NewDelegate(src, dt, null, m)); } if (mg.Object != null && !mg.Object.ReturnType.IsReferenceType) { mg.Object = new CastOp(src, Essentials.Object, mg.Object.ActualValue); } return(new NewDelegate(src, dt, mg.Object, m)); } return(!reportErrorIfNotFound ? null : compatibleMethods.Count == 0 ? Error(src, ErrorCode.E2045, "No methods matches the parameter list and return type of delegate type " + dt.Quote()) : ReportAmbiguousMatchError(src, compatibleMethods)); } // Lambda if (expectedType is DelegateType && value is UncompiledLambda) { expectedType.AssignBaseType(); return(TryCompileImplicitLambdaCast((UncompiledLambda)value, (DelegateType)expectedType)); } // Constant if (value is Constant && expectedType.IsIntrinsic) { var constant = value as Constant; if (constant.Value is int) { int intValue = (int)constant.Value; switch (expectedType.BuiltinType) { case BuiltinType.SByte: if (intValue >= -0x80 && intValue <= 0x7f) { return(new Constant(constant.Source, expectedType, (sbyte)intValue)); } break; case BuiltinType.Byte: if (intValue >= 0 && intValue <= 0xff) { return(new Constant(constant.Source, expectedType, (byte)intValue)); } break; case BuiltinType.Short: if (intValue >= -0x8000 && intValue <= 0x7fff) { return(new Constant(constant.Source, expectedType, (short)intValue)); } break; case BuiltinType.UShort: if (intValue >= 0 && intValue <= 0xffff) { return(new Constant(constant.Source, expectedType, (ushort)intValue)); } break; case BuiltinType.UInt: if (intValue >= 0) { return(new Constant(constant.Source, expectedType, (uint)intValue)); } break; case BuiltinType.ULong: if (intValue >= 0) { return(new Constant(constant.Source, expectedType, (ulong)intValue)); } break; } } if (constant.Value is long) { long longValue = (long)constant.Value; switch (expectedType.BuiltinType) { case BuiltinType.ULong: if (longValue >= 0) { return(new Constant(constant.Source, expectedType, (ulong)longValue)); } break; } } } // Implict cast bool ambiguous; var cast = TryResolveCastOverload(src, NameResolver.GetTypeCasts(expectedType, value.ReturnType), ref value, reportErrorIfNotFound, out ambiguous); if (ambiguous) { goto ERROR; } if (cast != null && cast.IsImplicitCast) { return(new CallCast(src, cast, value)); } // Up cast if (expectedType == Essentials.Object || value.ReturnType.IsSubclassOf(expectedType) || expectedType.IsInterface && value.ReturnType.IsImplementingInterface(expectedType)) { return(new CastOp(src, expectedType, value)); } // Fixed Array if (expectedType.IsFixedArray && value.ReturnType.IsFixedArray) { var t1 = expectedType as FixedArrayType; var t2 = value.ReturnType as FixedArrayType; if (t1.ElementType.Equals(t2.ElementType) && ( t1.OptionalSize == null || t2.OptionalSize == null || t1.OptionalSize is Constant && t2.OptionalSize is Constant && Equals(t1.OptionalSize.ConstantValue, t2.OptionalSize.ConstantValue) )) { return(value); } } // T[] -> IEnumerable<T> if (value.ReturnType.IsRefArray && expectedType.MasterDefinition == Essentials.IEnumerable_T) { ImplicitCastStack.RemoveLast(); var arrayEnumerable = TypeBuilder.Parameterize(src, Essentials.ArrayEnumerable_T, value.ReturnType.ElementType); return(TryCompileImplicitCast(src, expectedType, ILFactory.NewObject(src, arrayEnumerable, value), reportErrorIfNotFound)); } } ERROR: return(!reportErrorIfNotFound ? null : Error(src, ErrorCode.E2047, "No implicit cast from " + value.ReturnType.Quote() + " to " + expectedType.Quote())); }