private IfsType Analyse(ITree node, fsScope scope) { IfsType nodeType = null; if (inferenceFunctions.ContainsKey(node.Type)) { nodeType = inferenceFunctions[node.Type](node, scope); ITree childTypeNode = GetChildByType(node, fsharp_ssParser.TYPE); if (childTypeNode != null) { node.DeleteChild(GetChildIndexByType(node, fsharp_ssParser.TYPE)); } fsTreeNode typeNameNode = new fsTreeNode(nodeType); fsScope.ScopeVarOrFuncTypeChanged += typeNameNode.ScopeVarOrFuncTypeChangedHandler; node.AddChild(typeNameNode); } else { throw new Exception($"Can`t infer type for node: {node.Text}"); } return nodeType; }
private IfsType InferFuncCallType(ITree node, fsScope scope) { List<IfsType> factualArgsTypes = new List<IfsType>(); string callFunctionName = GetChildByType(node, fsharp_ssParser.NAME).GetChild(0).Text; ITree args = GetChildByType(node, fsharp_ssParser.ARGS); for (int i = 0; i < args.ChildCount; i++) { ITree currentArg = args.GetChild(i); IfsType argType = Analyse(currentArg, scope); //if (argType is fsTypeVar) //{ // if (!(currentArg is fsTreeNode)) // { // currentArg = new fsTreeNode(argType); // } // fsScope.ScopeVarOrFuncTypeChanged += (args.GetChild(i) as fsTreeNode).ScopeVarOrFuncTypeChangedHandler; //} factualArgsTypes.Add(argType); } if (scope.GetVarInfo(callFunctionName, false).PositionInScopeType == ScopePositionType.functionArg) { fsTreeNode typeFANode = new fsTreeNode(scope.GetVarInfo(callFunctionName, false)); node.AddChild(typeFANode); List<string> argsNames = new List<string>(); for (int i = 0; i < args.ChildCount; i++) { argsNames.Add(args.GetChild(i).Text); } fsDerFuncInfo faDerFuncInfo = new fsDerFuncInfo(callFunctionName, argsNames, 0, argsNames.Count, null); node.AddChild(new fsTreeNode(faDerFuncInfo)); return scope.GetVarType(callFunctionName); } if (callFunctionName.Length >= "printf".Length && callFunctionName.Substring(0, "printf".Length) == "printf") { callFunctionName += $"_{uniqueFuctionId++}"; functionsInfos.Add(callFunctionName, functionsInfos["printf"]); scope.AddFunction(callFunctionName, fsType.GetFunctionType(factualArgsTypes)); scope.SetVarInfo(callFunctionName, ScopePositionType.functionClass); } IfsType formalFunctionType = scope.GetFunctionType(callFunctionName); if (formalFunctionType == null) { formalFunctionType = scope.GetVarType(callFunctionName); } if (formalFunctionType == null) { throw new Exception($"Undeclared function: {callFunctionName}"); } IfsType returningType = (formalFunctionType as fsType).Types[(formalFunctionType as fsType).Types.Count - 1]; factualArgsTypes.Add(returningType); IfsType factualFunctionType = fsType.GetFunctionType(factualArgsTypes); UnifyWrapper(ref factualFunctionType, ref formalFunctionType, scope); returningType = (formalFunctionType as fsType).Types[(formalFunctionType as fsType).Types.Count - 1]; fsDerFuncInfo oldFuncInfo; if (functionsInfos.ContainsKey(callFunctionName)) { oldFuncInfo = functionsInfos[callFunctionName]; } else { oldFuncInfo = varDerFuncTable[callFunctionName]; } derFunction = new fsDerFuncInfo(oldFuncInfo.Name, new List<string>(oldFuncInfo.ArgsNames), oldFuncInfo.BeforePassedArgsNum, oldFuncInfo.AfterPassedArgsNum, oldFuncInfo.ContextFuncName); if (callFunctionName.Length < "printf".Length || callFunctionName.Substring(0, "printf".Length) != "printf") { derFunction.BeforePassedArgsNum = derFunction.AfterPassedArgsNum; derFunction.AfterPassedArgsNum += args.ChildCount; } node.AddChild(new fsTreeNode(derFunction)); fsTreeNode typeNode = new fsTreeNode(scope.GetVarInfo(callFunctionName, false)); node.AddChild(typeNode); return returningType; }
private IfsType InferIDType(ITree node, fsScope scope) { IfsType type = scope.GetFunctionType(node.Text) ?? scope.GetVarType(node.Text); if (type == null) { throw new Exception($"Undeclared variable: {node.Text}"); } if (type is fsTypeVar) { (type as fsTypeVar).IsFromScope = true; (type as fsTypeVar).ScopeVarName = node.Text; } if (GetChildByType(node, VAR_INFO) == null) { fsTreeNode typeNode = new fsTreeNode(scope.GetVarInfo(node.Text, false)); node.AddChild(typeNode); } return type; }
private IfsType InferBodyType(ITree node, fsScope scope) { IfsType exprType = null; for (int i = 0; i < node.GetChild(0).ChildCount; i++) { ITree childNode = node.GetChild(0).Text == "elif" ? node.GetChild(0) : node.GetChild(0).GetChild(i); ITree funcNameNode = null; bool isLambda = false; if (childNode.Type == fsharp_ssParser.FUNCTION_DEFN) { funcNameNode = GetChildByType(childNode, fsharp_ssParser.NAME); if (funcNameNode == null) { isLambda = true; funcNameNode = new fsTreeNode("NAME", fsharp_ssParser.NAME); funcNameNode.AddChild(new fsTreeNode(GetUniqueFunctionName())); childNode.AddChild(funcNameNode); } } exprType = Analyse(childNode, scope); if (childNode.Type == fsharp_ssParser.FUNCTION_DEFN) { scope.AddFunction(funcNameNode.GetChild(0).Text, exprType); scope.SetVarInfo(funcNameNode.GetChild(0).Text, ScopePositionType.functionClass); if (isLambda) { fsTreeNode lambdaCall = new fsTreeNode("FUNCTION_CALL", fsharp_ssParser.FUNCTION_CALL); fsTreeNode lambdaCallArgs = new fsTreeNode("ARGS", fsharp_ssParser.ARGS); lambdaCall.AddChild(funcNameNode); lambdaCall.AddChild(lambdaCallArgs); node.GetChild(0).AddChild(lambdaCall); } } else if (childNode.Type == fsharp_ssParser.VALUE_DEFN) { string varName = GetChildByType(childNode, fsharp_ssParser.NAME).GetChild(0).Text; scope.AddVar(varName, exprType); scope.SetVarInfo(varName, ScopePositionType.local); } } if (exprType == null) { throw new Exception("Cannot recognize body type"); } return exprType; }