示例#1
0
 private static IExpressionNode BuildExpression(
     ISyntaxNode node,
     IFunctionDictionary functions,
     VariableDictionary variables,
     TypeInferenceResults typeInferenceResults,
     TicTypesConverter typesConverter) =>
 node.Accept(new ExpressionBuilderVisitor(functions, variables, typeInferenceResults, typesConverter));
示例#2
0
        public static TypeInferenceResults SolveBodyOrThrow(
            SyntaxTree syntaxTree,
            IFunctionDictionary functions,
            IConstantList constants,
            AprioriTypesMap aprioriTypes)
        {
            try
            {
                var resultBuilder = new TypeInferenceResultsBuilder();
                var typeGraph     = new GraphBuilder(syntaxTree.MaxNodeId);

                if (!TicSetupVisitor.SetupTicForBody(
                        tree:      syntaxTree,
                        ticGraph:  typeGraph,
                        functions: functions,
                        constants: constants,
                        aprioriTypes: aprioriTypes,
                        results:   resultBuilder))
                {
                    throw ErrorFactory.TypesNotSolved(syntaxTree);
                }

                var bodyTypeSolving = typeGraph.Solve();
                if (bodyTypeSolving == null)
                {
                    throw ErrorFactory.TypesNotSolved(syntaxTree);
                }
                resultBuilder.SetResults(bodyTypeSolving);
                return(resultBuilder.Build());
            }
            catch (TicException e) { throw ErrorFactory.TranslateTicError(e, syntaxTree); }
        }
示例#3
0
        private static TypeInferenceResults SolveBodyTypes(
            SyntaxTree syntaxTree,
            IConstantList constants,
            IFunctionDictionary functionDictionary,
            AprioriTypesMap aprioriTypes)
        {
            var bodyTypeSolving = RuntimeBuilderHelper.SolveBodyOrThrow(
                syntaxTree, functionDictionary, constants, aprioriTypes);

            var enterVisitor = new ApplyTiResultEnterVisitor(bodyTypeSolving, TicTypesConverter.Concrete);
            var exitVisitor  = new ApplyTiResultsExitVisitor();

            foreach (var syntaxNode in syntaxTree.Nodes)
            {
                //function nodes were solved above
                if (syntaxNode is UserFunctionDefinitionSyntaxNode)
                {
                    continue;
                }

                //set types to nodes
                syntaxNode.ComeOver(enterVisitor, exitVisitor);
            }

            return(bodyTypeSolving);
        }
示例#4
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);
        }
示例#5
0
 private ExpressionBuilderVisitor(
     IFunctionDictionary functions,
     VariableDictionary variables,
     TypeInferenceResults typeInferenceResults,
     TicTypesConverter typesConverter)
 {
     _functions            = functions;
     _variables            = variables;
     _typeInferenceResults = typeInferenceResults;
     _typesConverter       = typesConverter;
 }
示例#6
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));
        }
示例#7
0
        public static Exception FunctionOverloadNotFound(FunCallSyntaxNode node, IFunctionDictionary functions)
        {
            var           candidates = functions.SearchAllFunctionsIgnoreCase(node.Id, node.Args.Length);
            StringBuilder msg        = new StringBuilder($"Function '{node.Id}({string.Join(",", node.Args.Select(_ => "_"))})' is not found. ");

            if (candidates.Any())
            {
                var candidate = candidates.First();
                msg.Append(
                    $"\r\nDid you mean function '{TypeHelper.GetFunSignature(candidate.Name, candidate.ReturnType, candidate.ArgTypes)}' ?");
            }
            return(new FunParseException(533, msg.ToString(), node.Interval));
        }
示例#8
0
        public static FunRuntime Build(string script, IFunctionDictionary functionDictionary, IConstantList constants = null, AprioriTypesMap aprioriTypesMap = null)
        {
            aprioriTypesMap ??= AprioriTypesMap.Empty;

            var flow       = Tokenizer.ToFlow(script);
            var syntaxTree = Parser.Parse(flow);

            //Set node numbers
            var setNodeNumberVisitor = new SetNodeNumberVisitor();

            syntaxTree.ComeOver(setNodeNumberVisitor);
            syntaxTree.MaxNodeId = setNodeNumberVisitor.LastUsedNumber;
            return(Build(syntaxTree, functionDictionary, constants ?? EmptyConstantList.Instance, aprioriTypesMap));
        }
示例#9
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;
 }
示例#10
0
        private TicSetupVisitor(GraphBuilder ticTypeGraph,
                                IFunctionDictionary dictionary,
                                IConstantList constants,
                                TypeInferenceResultsBuilder resultsBuilder,
                                AprioriTypesMap aprioriTypesMap)
        {
            _aliasScope     = new VariableScopeAliasTable();
            _dictionary     = dictionary;
            _constants      = constants;
            _resultsBuilder = resultsBuilder;
            _ticTypeGraph   = ticTypeGraph;

            foreach (var apriori in aprioriTypesMap)
            {
                _ticTypeGraph.SetVarType(apriori.Key, apriori.Value.ConvertToTiType());
            }
        }
示例#11
0
        public static IExpressionNode BuildExpression(
            ISyntaxNode node,
            IFunctionDictionary functions,
            FunnyType outputType,
            VariableDictionary variables,
            TypeInferenceResults typeInferenceResults,
            TicTypesConverter typesConverter)
        {
            var result = node.Accept(
                new ExpressionBuilderVisitor(functions, variables, typeInferenceResults, typesConverter));

            if (result.Type == outputType)
            {
                return(result);
            }
            var converter = VarTypeConverter.GetConverterOrThrow(result.Type, outputType, node.Interval);

            return(new CastExpressionNode(result, outputType, converter, node.Interval));
        }
示例#12
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);
        }
示例#13
0
        public static bool SetupTicForBody(
            SyntaxTree tree,
            GraphBuilder ticGraph,
            IFunctionDictionary functions,
            IConstantList constants,
            AprioriTypesMap aprioriTypes,
            TypeInferenceResultsBuilder results)
        {
            var visitor = new TicSetupVisitor(ticGraph, functions, constants, results, aprioriTypes);

            foreach (var syntaxNode in tree.Children)
            {
                if (syntaxNode is UserFunctionDefinitionSyntaxNode)
                {
                    continue;
                }

                if (!syntaxNode.Accept(visitor))
                {
                    return(false);
                }
            }
            return(true);
        }
示例#14
0
        private static FunRuntime Build(
            SyntaxTree syntaxTree,
            IFunctionDictionary functionsDictionary,
            IConstantList constants,
            AprioriTypesMap aprioriTypesMap)
        {
            #region build user functions
            //get topology sort of the functions call
            //result is the order of functions that need to be compiled
            //functions that not references other functions have to be compiled firstly
            //Then those functions will be compiled
            //that refer to already compiled functions
            var functionSolveOrder = syntaxTree.FindFunctionSolvingOrderOrThrow();
            List <IFunctionSignature> userFunctions;
            IFunctionDictionary       functionDictionary;
            if (functionSolveOrder.Length == 0)
            {
                functionDictionary = functionsDictionary;
                userFunctions      = EmptyUserFunctionsList;
            }
            else
            {
                userFunctions = new List <IFunctionSignature>();

                var scopeFunctionDictionary = new ScopeFunctionDictionary(functionsDictionary);
                functionDictionary = scopeFunctionDictionary;
                //build user functions
                foreach (var functionSyntaxNode in functionSolveOrder)
                {
                    //todo list capacity
                    var userFun = BuildFunctionAndPutItToDictionary(
                        functionSyntaxNode: functionSyntaxNode,
                        constants: constants,
                        functionsDictionary: scopeFunctionDictionary);
                    userFunctions.Add(userFun);
                }
            }

            #endregion

            var bodyTypeSolving = SolveBodyTypes(syntaxTree, constants, functionDictionary, aprioriTypesMap);

            #region build body
            var variables = new VariableDictionary();
            var equations = new List <Equation>();

            foreach (var treeNode in syntaxTree.Nodes)
            {
                if (treeNode is EquationSyntaxNode node)
                {
                    var equation = BuildEquationAndPutItToVariables(node, functionDictionary, variables, bodyTypeSolving);
                    equations.Add(equation);
                    if (Helper.DoesItLooksLikeSuperAnonymousVariable(equation.Id))
                    {
                        throw FunParseException.ErrorStubToDo("variable cannot starts with 'it'");
                    }
                    if (TraceLog.IsEnabled)
                    {
                        TraceLog.WriteLine($"\r\nEQUATION: {equation.Id}:{equation.Expression.Type} = ... \r\n");
                    }
                }
                else if (treeNode is VarDefinitionSyntaxNode varDef)
                {
                    if (Helper.DoesItLooksLikeSuperAnonymousVariable(varDef.Id))
                    {
                        throw FunParseException.ErrorStubToDo("variable cannot starts with 'it'");
                    }

                    var variableSource = VariableSource.CreateWithStrictTypeLabel(
                        varDef.Id,
                        varDef.FunnyType,
                        varDef.Interval,
                        isOutput: false,
                        varDef.Attributes);
                    if (!variables.TryAdd(variableSource))
                    {
                        var allUsages = variables.GetUsages(variableSource.Name);
                        throw ErrorFactory.VariableIsDeclaredAfterUsing(allUsages);
                    }
                    if (TraceLog.IsEnabled)
                    {
                        TraceLog.WriteLine($"\r\nVARIABLE: {variableSource.Name}:{variableSource.Type} = ... \r\n");
                    }
                }
                else if (treeNode is UserFunctionDefinitionSyntaxNode)
                {
                    continue;//user function was built above
                }
                else
                {
                    throw new InvalidOperationException($"Type {treeNode} is not supported as tree root");
                }
            }
            #endregion

            foreach (var userFunction in userFunctions)
            {
                if (userFunction is GenericUserFunction generic && generic.BuiltCount == 0)
                {
                    // Generic function is declared but concrete was not built.
                    // We have to build it at least once to search all possible errors
                    GenericUserFunction.CreateSomeConcrete(generic);
                }
            }
            return(new FunRuntime(equations, variables, userFunctions));
        }
示例#15
0
        private static Equation BuildEquationAndPutItToVariables(
            EquationSyntaxNode equation,
            IFunctionDictionary functionsDictionary,
            VariableDictionary variables,
            TypeInferenceResults typeInferenceResults)
        {
            var expression = ExpressionBuilderVisitor.BuildExpression(
                node:       equation.Expression,
                functions:  functionsDictionary,
                outputType: equation.OutputType,
                variables:  variables,
                typeInferenceResults: typeInferenceResults,
                typesConverter: TicTypesConverter.Concrete);

            VariableSource outputVariableSource;

            if (equation.OutputTypeSpecified)
            {
                outputVariableSource = VariableSource.CreateWithStrictTypeLabel(
                    name: equation.Id,
                    type: equation.OutputType,
                    typeSpecificationIntervalOrNull: equation.TypeSpecificationOrNull.Interval,
                    attributes: equation.Attributes,
                    isOutput: true);
            }
            else
            {
                outputVariableSource = VariableSource.CreateWithoutStrictTypeLabel(
                    name: equation.Id,
                    type: equation.OutputType,
                    isOutput: true,
                    equation.Attributes);
            }

            var itVariable = variables.GetSuperAnonymousVariableOrNull();

            if (itVariable != null)
            {
                throw FunParseException.ErrorStubToDo("Variable cannot starts with it");
            }


            if (!variables.TryAdd(outputVariableSource))
            {
                //some equation referenced the source before
                var usages = variables.GetUsages(equation.Id);
                if (usages.Source.IsOutput)
                {
                    throw ErrorFactory.OutputNameWithDifferentCase(equation.Id, equation.Expression.Interval);
                }
                else
                {
                    throw ErrorFactory.CannotUseOutputValueBeforeItIsDeclared(usages);
                }
            }


            //ReplaceInputType
            if (outputVariableSource.Type != expression.Type)
            {
                throw new ImpossibleException("fitless");
            }
            return(new Equation(equation.Id, expression, outputVariableSource));
        }
示例#16
0
 public ScopeFunctionDictionary(IFunctionDictionary originalDictionary)
 {
     _originalDictionary = originalDictionary;
 }