예제 #1
0
        public void PrintFunParseException(FunParseException e, string file, string script, string test, int startLine)
        {
            Console.BackgroundColor = ConsoleColor.Yellow;
            Console.ForegroundColor = ConsoleColor.Black;
            Console.Write("ERROR [FU" + e.Code + "] ");
            PrintLineAndResetColor($" {e.Message} ");
            Console.WriteLine("FILE:       {0}\nTEST:       {1}\nSTARTLINE:  {2}", file, test, startLine);
            Console.WriteLine("\r\n");
            if (e.End != -1)
            {
                if (e.Start > 0)
                {
                    Console.Write(script.Substring(0, e.Start));
                }

                Console.BackgroundColor = ConsoleColor.Yellow;
                Console.ForegroundColor = ConsoleColor.Black;

                Console.Write(e.Interval.SubString(script));
                Console.ResetColor();
                if (script.Length >= e.End)
                {
                    Console.Write(script.Substring(e.End));
                }
                Console.WriteLine();
            }

            Console.WriteLine();
        }
예제 #2
0
파일: TokenHelper.cs 프로젝트: tmteam/NFun
        public static Tok MoveIfOrThrow(this TokFlow flow, TokType tokType)
        {
            var cur = flow.Current;

            if (cur == null)
            {
                var prev = flow.Previous;
                if (prev == null)
                {
                    throw FunParseException.ErrorStubToDo($"\"{tokType}\" is missing at end of stream");
                }
                else
                {
                    throw FunParseException.ErrorStubToDo($"\"{tokType}\" is missing at end of stream");
                }
            }

            if (!cur.Is(tokType))
            {
                throw FunParseException.ErrorStubToDo(
                          $"\"{tokType}\" is missing but was \"{cur}\"");
            }

            flow.MoveNext();
            return(cur);
        }
예제 #3
0
파일: TokenHelper.cs 프로젝트: tmteam/NFun
        public static FunnyType ReadType(this TokFlow flow)
        {
            var cur      = flow.Current;
            var readType = ToFunnyType(cur);

            flow.MoveNext();
            var lastPosition = cur.Finish;

            while (flow.IsCurrent(TokType.ArrOBr))
            {
                if (flow.Current.Start != lastPosition)
                {
                    throw FunParseException.ErrorStubToDo("unexpected space before []");
                }

                flow.MoveNext();
                lastPosition = flow.Current.Finish;
                if (!flow.MoveIf(TokType.ArrCBr))
                {
                    throw ErrorFactory.ArrTypeCbrMissed(new Interval(cur.Start, flow.Current.Start));
                }
                readType = FunnyType.ArrayOf(readType);
            }

            return(readType);
        }
예제 #4
0
        public override IConcreteFunction CreateConcrete(FunnyType[] concreteTypes)
        {
            var from = concreteTypes[1];
            var to   = concreteTypes[0];

            if (to == FunnyType.Anything || from == to)
            {
                return(new ConcreteConverter(o => o, from, to));
            }
            if (to == FunnyType.Text)
            {
                return(new ConcreteConverter(o => o.ToString(), from, to));
            }
            var safeConverter = VarTypeConverter.GetConverterOrNull(from, to);

            if (safeConverter != null)
            {
                return(new ConcreteConverter(safeConverter, from, to));
            }

            if (to.ArrayTypeSpecification?.FunnyType == FunnyType.UInt8)
            {
                var serializer = CreateSerializerOrNull(from);
                if (serializer != null)
                {
                    return(new ConcreteConverter(serializer, from, to));
                }
            }
            else if (to.ArrayTypeSpecification?.FunnyType == FunnyType.Bool)
            {
                var serializer = CreateBinarizerOrNull(from);

                if (serializer != null)
                {
                    return(new ConcreteConverter(serializer, from, to));
                }
            }

            if (from.ArrayTypeSpecification?.FunnyType == FunnyType.UInt8)
            {
                var deserializer = CreateDeserializerOrNull(to);
                if (deserializer != null)
                {
                    return(new ConcreteConverter(deserializer, from, to));
                }
            }
            else if (from.IsText)
            {
                var parser = CreateParserOrNull(to);
                if (parser != null)
                {
                    return(new ConcreteConverter(parser, from, to));
                }
            }

            throw FunParseException.ErrorStubToDo($"Impossible explicit convertation {from}->{to}");
        }
예제 #5
0
        public IExpressionNode Visit(StructFieldAccessSyntaxNode node)
        {
            var structNode = ReadNode(node.Source);

            //Funtic allows default values for not specified types
            // so call:
            //  y = {}.missingField
            // is allowed, but it semantically incorrect

            if (!structNode.Type.StructTypeSpecification.ContainsKey(node.FieldName))
            {
                throw FunParseException.ErrorStubToDo($"Access to non exist field {node.FieldName}");
            }
            return(new StructFieldAccessExpressionNode(node.FieldName, structNode, node.Interval));
        }
예제 #6
0
        public StructInitSyntaxNode(List <EquationSyntaxNode> equations, Interval interval)
        {
            var fields = new List <FieldDefenition>(equations.Count);

            foreach (var equation in equations)
            {
                if (equation.TypeSpecificationOrNull != null)
                {
                    throw FunParseException.ErrorStubToDo("Field type specification is not supported yet");
                }
                fields.Add(new FieldDefenition(equation.Id, equation.Expression));
            }

            Fields   = fields;
            Interval = interval;
        }
예제 #7
0
        public IExpressionNode Visit(StructInitSyntaxNode node)
        {
            var types = new Dictionary <string, FunnyType>(node.Fields.Count);
            var names = new string[node.Fields.Count];
            var nodes = new IExpressionNode[node.Fields.Count];

            for (int i = 0; i < node.Fields.Count; i++)
            {
                var field = node.Fields[i];
                nodes[i] = ReadNode(field.Node);
                names[i] = field.Name;
                types.Add(field.Name, field.Node.OutputType);
            }

            foreach (var field in node.OutputType.StructTypeSpecification)
            {
                if (!types.ContainsKey(field.Key))
                {
                    throw FunParseException.ErrorStubToDo($"Field {field.Key} is missed in struct");
                }
            }
            return(new StructInitExpressionNode(names, nodes, node.Interval, FunnyType.StructOf(types)));
        }
예제 #8
0
        private IExpressionNode BuildAnonymousFunction(Interval interval, ISyntaxNode body,
                                                       VariableDictionary localVariables, VariableSource[] arguments)
        {
            var sources         = localVariables.GetAllSources().ToArray();
            var originVariables = new string[sources.Length];

            for (int i = 0; i < originVariables.Length; i++)
            {
                originVariables[i] = sources[i].Name;
            }

            var expr = BuildExpression(body, _functions, localVariables, _typeInferenceResults, _typesConverter);

            //New variables are new closured
            var closured = localVariables.GetAllUsages()
                           .Where(s => !originVariables.Contains(s.Source.Name))
                           .ToList();

            if (closured.Any(c => Helper.DoesItLooksLikeSuperAnonymousVariable(c.Source.Name)))
            {
                throw FunParseException.ErrorStubToDo("Unexpected it* variable");
            }

            //Add closured vars to outer-scope dictionary
            foreach (var newVar in closured)
            {
                _variables.TryAdd(newVar); //add full usage info to allow analyze outer errors
            }
            var fun = ConcreteUserFunction.Create(
                isRecursive: false,
                name: "anonymous",
                variables: arguments,
                isReturnTypeStrictlyTyped: false,
                expression: expr);

            return(new FunVariableExpressionNode(fun, interval));
        }
예제 #9
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));
        }
예제 #10
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);
            }
        }
예제 #11
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));
        }