public IExpressionNode Visit(SuperAnonymFunctionSyntaxNode arrowAnonymFunNode)
        {
            var outputTypeFunDefinition = arrowAnonymFunNode.OutputType.FunTypeSpecification;

            if (outputTypeFunDefinition == null)
            {
                throw new ImpossibleException("Fun definition expected");
            }
            string[] argNames = null;
            if (outputTypeFunDefinition.Inputs.Length == 1)
            {
                argNames = new[] { "it" }
            }
            ;
            else
            {
                argNames = new string[outputTypeFunDefinition.Inputs.Length];
                for (int i = 0; i < outputTypeFunDefinition.Inputs.Length; i++)
                {
                    argNames[i] = $"it{i + 1}";
                }
            }

            //Prepare local variable scope
            //Capture all outerscope variables
            var localVariables = new VariableDictionary(_variables.GetAllSources());

            var arguments = new VariableSource[argNames.Length];

            for (var i = 0; i < argNames.Length; i++)
            {
                var arg    = argNames[i];
                var type   = outputTypeFunDefinition.Inputs[i];
                var source = VariableSource.CreateWithoutStrictTypeLabel(arg, type, false);
                //collect argument
                arguments[i] = source;
                //add argument to local scope
                //if argument with it* name already exist - replace it
                localVariables.AddOrReplace(source);
            }

            var body = arrowAnonymFunNode.Body;

            return(BuildAnonymousFunction(arrowAnonymFunNode.Interval, body, localVariables, arguments));
        }
Exemple #2
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);
        }
        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));
        }