public override IConcreteFunction CreateConcrete(FunnyType[] concreteTypes) { BuiltCount++; var id = string.Join(",", concreteTypes); if (_concreteFunctionsCache.TryGetValue(id, out var alreadyExists)) { return(alreadyExists); } //set types to nodes var converter = TicTypesConverter.ReplaceGenericTypesConverter(_constrainsMap, concreteTypes); var ticSignature = _typeInferenceResults.GetVariableType(_syntaxNode.Id + "'" + _syntaxNode.Args.Count); var funType = converter.Convert(ticSignature); var returnType = funType.FunTypeSpecification.Output; var argTypes = funType.FunTypeSpecification.Inputs; // Create a function prototype and put it to cache for recursive cases // If the function is recursive - function will take recursive prototype from cache var concretePrototype = new ConcreteUserFunctionPrototype(Name, returnType, argTypes); _concreteFunctionsCache.Add(id, concretePrototype); _syntaxNode.ComeOver( enterVisitor: new ApplyTiResultEnterVisitor( solving: _typeInferenceResults, tiToLangTypeConverter: converter), exitVisitor: new ApplyTiResultsExitVisitor()); var function = _syntaxNode.BuildConcrete( argTypes: argTypes, returnType: returnType, functionsDictionary: _dictionary, results: _typeInferenceResults, converter: converter); concretePrototype.SetActual(function, _syntaxNode.Interval); return(function); }
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); } }