private static IExpressionNode BuildExpression( ISyntaxNode node, IFunctionDictionary functions, VariableDictionary variables, TypeInferenceResults typeInferenceResults, TicTypesConverter typesConverter) => node.Accept(new ExpressionBuilderVisitor(functions, variables, typeInferenceResults, typesConverter));
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); } }
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); }
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 ExpressionBuilderVisitor( IFunctionDictionary functions, VariableDictionary variables, TypeInferenceResults typeInferenceResults, TicTypesConverter typesConverter) { _functions = functions; _variables = variables; _typeInferenceResults = typeInferenceResults; _typesConverter = typesConverter; }
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)); }
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)); }
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)); }
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; }
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()); } }
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)); }
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 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); }
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)); }
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)); }
public ScopeFunctionDictionary(IFunctionDictionary originalDictionary) { _originalDictionary = originalDictionary; }