Example #1
0
        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;
        }
Example #2
0
            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;
            }