public static TypeCompatibilityResult AreTypesCompatible(Type Source, Type Destination, ParseScope Scope) { if (Object.ReferenceEquals(Destination, Generic)) return TypeCompatibilityResult.NoConversionRequired; if (Object.ReferenceEquals(Source, Destination)) return TypeCompatibilityResult.NoConversionRequired; var super = Source.Super; while (super != null) { if (Object.ReferenceEquals(super, Destination)) return TypeCompatibilityResult.NoConversionRequired; super = super.Super; } var conversionArguments = new List<Ast.Node>(); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "convert" })); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "0" }) { ResultType = Source }); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "to" })); conversionArguments.Add(new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = Destination.Name })); var possibleConversions = Scope.FindAllPossibleMacroMatches(conversionArguments); Declaration matchingConversion = null; foreach (var possibleConversion in possibleConversions) if (Object.ReferenceEquals(Source, possibleConversion.Terms[1].DeclaredType)) { matchingConversion = possibleConversion; break; } if (matchingConversion != null) { if (!Object.ReferenceEquals(matchingConversion.ReturnType, Destination)) throw new CompileError("Conversion function does not return the correct type.", matchingConversion.Body.Body.Source); return new TypeCompatibilityResult { Compatible = true, ConversionRequired = true, ConversionMacro = matchingConversion }; } return TypeCompatibilityResult.Incompatible; }
public override Ast.Node Transform(ParseScope Scope) { List = List.Transform(Scope); ResultType = List.ResultType; //Try to find an access macro for this type. var getterArguments = DummyArguments(Keyword("GET"), Keyword("AT"), Term(Scope.FindType("NUMBER")), Keyword("FROM"), Term(List.ResultType)); var indexerMacro = Scope.FindAllPossibleMacroMatches(getterArguments).Where(d => ExactDummyMatch(d.Terms, getterArguments)).FirstOrDefault(); if (indexerMacro == null) throw new CompileError("No macro of the form GET AT NUMBER FROM " + List.ResultType.Name + " found.", Source); var lengthArguments = DummyArguments(Keyword("LENGTH"), Keyword("OF"), Term(List.ResultType)); var lengthMacro = Scope.FindAllPossibleMacroMatches(lengthArguments).Where(d => ExactDummyMatch(d.Terms, lengthArguments)).FirstOrDefault(); if (lengthMacro == null) throw new CompileError("No macro of the form LENGTH OF " + List.ResultType.Name + " found.", Source); var nestedScope = Scope.Push(ScopeType.Block); ResultVariable = nestedScope.NewLocal("__result@" + VariableName, Scope.FindType("LIST")); ListVariable = nestedScope.NewLocal("__list@" + VariableName, Scope.FindType("LIST")); TotalVariable = nestedScope.NewLocal("__total@" + VariableName, Scope.FindType("NUMBER")); CounterVariable = nestedScope.NewLocal("__counter@" + VariableName, Scope.FindType("NUMBER")); ValueVariable = nestedScope.NewLocal(VariableName, indexerMacro.ReturnType); Indexer = Ast.StaticInvokation.CreateCorrectInvokationNode(Source, nestedScope, indexerMacro, new List<Ast.Node>(new Ast.Node[] { new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "__counter@"+VariableName }), new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "__list@"+VariableName }) })).Transform(nestedScope); LengthFunc = Ast.StaticInvokation.CreateCorrectInvokationNode(Source, nestedScope, lengthMacro, new List<Ast.Node>(new Ast.Node[] { new Ast.Identifier(new Token { Type = TokenType.Identifier, Value = "__list@"+VariableName }) })).Transform(nestedScope); Condition = Condition.Transform(nestedScope); if (Condition.ResultType.Name != "BOOLEAN") throw new CompileError("Condition to where clause must return boolean", Source); return this; }