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)); }
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); }
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); }); }
/// <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); }
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)); }
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; }
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); }
public IExpressionNode Visit(UserFunctionDefinitionSyntaxNode node) => ThrowNotAnExpression(node);
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);
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));
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); } }
public virtual VisitorEnterResult Visit(UserFunctionDefinitionSyntaxNode node) => DefaultVisitEnter(node);
public string Visit(UserFunctionDefinitionSyntaxNode node) => $"{node.Id}(...) = ...";
public virtual bool Visit(UserFunctionDefinitionSyntaxNode node) => true;
public override VisitorEnterResult Visit(UserFunctionDefinitionSyntaxNode node) => VisitorEnterResult.Continue;
public static string GetFunAlias(this UserFunctionDefinitionSyntaxNode syntaxNode) => GetFunAlias(syntaxNode.Id, syntaxNode.Args.Count);