示例#1
0
        public bool Visit(UserFunctionDefinitionSyntaxNode node)
        {
            var argNames = new string[node.Args.Count];
            int i        = 0;

            foreach (var arg in node.Args)
            {
                argNames[i] = arg.Id;
                i++;
                if (arg.FunnyType != FunnyType.Empty)
                {
                    _ticTypeGraph.SetVarType(arg.Id, arg.FunnyType.ConvertToTiType());
                }
            }

            ITypeState returnType = null;

            if (node.ReturnType != FunnyType.Empty)
            {
                returnType = (ITypeState)node.ReturnType.ConvertToTiType();
            }

            #if DEBUG
            TraceLog.WriteLine(
                $"Enter {node.OrderNumber}. UFun {node.Id}({string.Join(",", argNames)})->{node.Body.OrderNumber}:{returnType?.ToString() ?? "empty"}");
            #endif
            var fun = _ticTypeGraph.SetFunDef(
                name: node.Id + "'" + node.Args.Count,
                returnId: node.Body.OrderNumber,
                returnType: returnType,
                varNames: argNames);
            _resultsBuilder.RememberUserFunctionSignature(node.Id, fun);

            return(VisitChildren(node));
        }
示例#2
0
        public static GenericUserFunction Create(
            TypeInferenceResults typeInferenceResults,
            UserFunctionDefinitionSyntaxNode syntaxNode,
            IFunctionDictionary dictionary)
        {
            var ticGenerics    = typeInferenceResults.Generics;
            var langConstrains = new GenericConstrains[ticGenerics.Length];

            for (int i = 0; i < ticGenerics.Length; i++)
            {
                var ticConstrains = ticGenerics[i];
                langConstrains[i] = GenericConstrains.FromTicConstrains(ticConstrains);
            }
            var ticFunName         = syntaxNode.Id + "'" + syntaxNode.Args.Count;
            var ticSignature       = (StateFun)typeInferenceResults.GetVariableType(ticFunName);
            var signatureConverter = TicTypesConverter.GenericSignatureConverter(ticGenerics);

            var argTypes = new FunnyType[ticSignature.ArgNodes.Length];

            for (var i = 0; i < ticSignature.ArgNodes.Length; i++)
            {
                argTypes[i] = signatureConverter.Convert(ticSignature.ArgNodes[i].State);
            }
            var retType = signatureConverter.Convert(ticSignature.ReturnType);

#if DEBUG
            TraceLog.WriteLine($"CREATE GENERIC FUN {syntaxNode.Id}({string.Join(",",argTypes)}):{retType}");
            TraceLog.WriteLine($"    ...where {string.Join(", ", langConstrains)}");
#endif
            var function = new GenericUserFunction(typeInferenceResults, syntaxNode, dictionary, langConstrains, retType, argTypes);
            return(function);
        }
示例#3
0
 private void AssertParsed(UserFunctionDefinitionSyntaxNode fun, string expectedExpr, params string[] variables)
 {
     Assert.Multiple(() =>
     {
         CollectionAssert.AreEqual(variables, fun.Args.Select(a => a.Id));
         AssertParsed(fun.Body, expectedExpr);
     });
 }
示例#4
0
        /// <summary>
        /// Gets order of calculating the functions, based on its co using.
        /// </summary>
        public static UserFunctionDefinitionSyntaxNode[] FindFunctionSolvingOrderOrThrow(this SyntaxTree syntaxTree)
        {
            var userFunctions = syntaxTree.Children.OfType <UserFunctionDefinitionSyntaxNode>().ToArray();

            if (userFunctions.Length == 0)
            {
                return(userFunctions);
            }

            var userFunctionsNames = new Dictionary <string, int>();
            int i = 0;

            foreach (var userFunction in userFunctions)
            {
                var alias = userFunction.GetFunAlias();
                if (userFunctionsNames.ContainsKey(alias))
                {
                    throw ErrorFactory.FunctionAlreadyExist(userFunction);
                }
                userFunctionsNames.Add(alias, i);
                i++;
            }

            int[][] dependenciesGraph = new int[i][];
            int     j = 0;

            foreach (var userFunction in userFunctions)
            {
                var visitor = new FindFunctionDependenciesVisitor(userFunction.GetFunAlias(), userFunctionsNames);
                if (!userFunction.ComeOver(visitor))
                {
                    throw new InvalidOperationException("User fun come over");
                }

                userFunction.IsRecursive = visitor.HasSelfRecursion;

                dependenciesGraph[j] = visitor.GetFoundDependencies();
                j++;
            }

            var sortResults = GraphTools.SortCycledTopology(dependenciesGraph);

            var functionSolveOrder = new UserFunctionDefinitionSyntaxNode[sortResults.NodeNames.Length];

            for (int k = 0; k < sortResults.NodeNames.Length; k++)
            {
                var id = sortResults.NodeNames[k];
                functionSolveOrder[k] = userFunctions[id];
            }

            if (sortResults.HasCycle)
            {
                //if functions has cycle, then function solve order is cycled
                throw ErrorFactory.ComplexRecursion(functionSolveOrder);
            }

            return(functionSolveOrder);
        }
示例#5
0
        public static bool SetupTicForUserFunction(
            UserFunctionDefinitionSyntaxNode userFunctionNode,
            GraphBuilder ticGraph,
            IFunctionDictionary functions,
            IConstantList constants,
            TypeInferenceResultsBuilder results)
        {
            var visitor = new TicSetupVisitor(ticGraph, functions, constants, results, AprioriTypesMap.Empty);

            return(userFunctionNode.Accept(visitor));
        }
示例#6
0
 private GenericUserFunction(
     TypeInferenceResults typeInferenceResults,
     UserFunctionDefinitionSyntaxNode syntaxNode,
     IFunctionDictionary dictionary,
     GenericConstrains[] constrains,
     FunnyType returnType,
     FunnyType[] argTypes
     ) : base(syntaxNode.Id, constrains, returnType, argTypes)
 {
     _typeInferenceResults = typeInferenceResults;
     _constrainsMap        = _typeInferenceResults.Generics;
     _syntaxNode           = syntaxNode;
     _dictionary           = dictionary;
 }
示例#7
0
        public static ConcreteUserFunction BuildConcrete(
            this UserFunctionDefinitionSyntaxNode functionSyntax,
            FunnyType[] argTypes,
            FunnyType returnType,
            IFunctionDictionary functionsDictionary,
            TypeInferenceResults results,
            TicTypesConverter converter)
        {
            var vars = new VariableDictionary(functionSyntax.Args.Count);

            for (int i = 0; i < functionSyntax.Args.Count; i++)
            {
                var variableSource = RuntimeBuilderHelper.CreateVariableSourceForArgument(
                    argSyntax: functionSyntax.Args[i],
                    actualType: argTypes[i]);

                if (!vars.TryAdd(variableSource))
                {
                    throw ErrorFactory.FunctionArgumentDuplicates(functionSyntax, functionSyntax.Args[i]);
                }
            }

            var bodyExpression = ExpressionBuilderVisitor.BuildExpression(
                node: functionSyntax.Body,
                functions: functionsDictionary,
                outputType: returnType,
                variables: vars,
                typeInferenceResults: results,
                typesConverter: converter);

            vars.ThrowIfSomeVariablesNotExistsInTheList(
                functionSyntax.Args.Select(a => a.Id));

            var function = ConcreteUserFunction.Create(
                isRecursive: functionSyntax.IsRecursive,
                name: functionSyntax.Id,
                variables: vars.GetAllSources().ToArray(),
                isReturnTypeStrictlyTyped: functionSyntax.ReturnType != FunnyType.Empty,
                expression: bodyExpression);

            return(function);
        }
示例#8
0
 public IExpressionNode Visit(UserFunctionDefinitionSyntaxNode node)
 => ThrowNotAnExpression(node);
示例#9
0
 public static Exception FunctionArgumentDuplicates(UserFunctionDefinitionSyntaxNode lexFunction, TypedVarDefSyntaxNode lexFunctionArg)
 => new FunParseException(554, $"'Argument name '{lexFunctionArg.Id}' duplicates at  {ErrorsHelper.Signature(lexFunction.Id, lexFunction.Args)} ", lexFunction.Head.Interval);
示例#10
0
 public static Exception FunctionAlreadyExist(UserFunctionDefinitionSyntaxNode userFun)
 => new FunParseException(545, $"Function  {ErrorsHelper.Signature(userFun.Id, userFun.Args)} already exist",
                          new Interval(userFun.Head.Interval.Start, userFun.Body.Interval.Finish));
示例#11
0
        private static IFunctionSignature BuildFunctionAndPutItToDictionary(
            UserFunctionDefinitionSyntaxNode functionSyntaxNode,
            IConstantList constants,
            ScopeFunctionDictionary functionsDictionary)
        {
#if DEBUG
            TraceLog.WriteLine($"\r\n====BUILD {functionSyntaxNode.Id}(..) ====");
#endif
            ////introduce function variable
            var         graphBuider    = new GraphBuilder();
            var         resultsBuilder = new TypeInferenceResultsBuilder();
            ITicResults types;

            try
            {
                if (!TicSetupVisitor.SetupTicForUserFunction(
                        userFunctionNode: functionSyntaxNode,
                        ticGraph:  graphBuider,
                        functions: functionsDictionary,
                        constants: constants,
                        results:   resultsBuilder))
                {
                    throw FunParseException.ErrorStubToDo($"Function '{functionSyntaxNode.Id}' is not solved");
                }

                // solve the types
                types = graphBuider.Solve();
            }
            catch (TicException e) { throw ErrorFactory.TranslateTicError(e, functionSyntaxNode); }

            resultsBuilder.SetResults(types);
            var typeInferenceResuls = resultsBuilder.Build();

            if (!types.HasGenerics)
            {
                #region concreteFunction

                //set types to nodes
                functionSyntaxNode.ComeOver(
                    enterVisitor: new ApplyTiResultEnterVisitor(
                        solving: typeInferenceResuls,
                        tiToLangTypeConverter: TicTypesConverter.Concrete),
                    exitVisitor: new ApplyTiResultsExitVisitor());

                var funType = TicTypesConverter.Concrete.Convert(
                    typeInferenceResuls.GetVariableType(functionSyntaxNode.Id + "'" + functionSyntaxNode.Args.Count));

                var returnType = funType.FunTypeSpecification.Output;
                var argTypes   = funType.FunTypeSpecification.Inputs;
                if (TraceLog.IsEnabled)
                {
                    TraceLog.WriteLine($"\r\n=====> Generic {functionSyntaxNode.Id} {funType}");
                }
                //make function prototype
                var prototype = new ConcreteUserFunctionPrototype(functionSyntaxNode.Id, returnType, argTypes);
                //add prototype to dictionary for future use
                functionsDictionary.Add(prototype);
                var function =
                    functionSyntaxNode.BuildConcrete(
                        argTypes:   argTypes,
                        returnType: returnType,
                        functionsDictionary: functionsDictionary,
                        results:    typeInferenceResuls,
                        converter:  TicTypesConverter.Concrete);

                prototype.SetActual(function, functionSyntaxNode.Interval);
                return(function);

                #endregion
            }
            else
            {
                var function = GenericUserFunction.Create(typeInferenceResuls, functionSyntaxNode, functionsDictionary);
                functionsDictionary.Add(function);
                if (TraceLog.IsEnabled)
                {
                    TraceLog.WriteLine($"\r\n=====> Concrete {functionSyntaxNode.Id} {function}");
                }
                return(function);
            }
        }
示例#12
0
 public virtual VisitorEnterResult Visit(UserFunctionDefinitionSyntaxNode node) => DefaultVisitEnter(node);
示例#13
0
 public string Visit(UserFunctionDefinitionSyntaxNode node) => $"{node.Id}(...) = ...";
示例#14
0
 public virtual bool Visit(UserFunctionDefinitionSyntaxNode node) => true;
示例#15
0
 public override VisitorEnterResult Visit(UserFunctionDefinitionSyntaxNode node)
 => VisitorEnterResult.Continue;
示例#16
0
 public static string GetFunAlias(this UserFunctionDefinitionSyntaxNode syntaxNode)
 => GetFunAlias(syntaxNode.Id, syntaxNode.Args.Count);