private IfsType InferFunctionDefnType(ITree node, fsScope scope) { fsScope innerScope = new fsScope(scope); List<IfsType> functionTypes = new List<IfsType>(); string funcName = GetChildByType(node, fsharp_ssParser.NAME).GetChild(0).Text; ITree args = GetChildByType(node, fsharp_ssParser.ARGS); List<string> argsNames = new List<string>(); for (int i = 0; i < args.ChildCount; i++) { ITree arg = args.GetChild(i); IfsType argType; if (arg.ChildCount > 0) { ITree annotatedArgTypeNode = arg.GetChild(0); argType = new fsType(annotatedArgTypeNode.Text, null); } else { argType = new fsTypeVar(); } argsNames.Add(arg.Text); innerScope.AddVar(arg.Text, argType); innerScope.SetVarInfo(arg.Text, ScopePositionType.functionArg); } fsDerFuncInfo funcInfo = new fsDerFuncInfo(funcName, argsNames, 0, 0, enteredFunctionsNames[enteredFunctionsNames.Count - 1]); if (funcName != "main") { enteredFunctionsNames.Add(funcName); } functionsInfos.Add(funcName, funcInfo); node.AddChild(new fsTreeNode(funcInfo)); if (GetChildByType(node, fsharp_ssParser.REC) != null) { innerScope.AddFunction(funcName, fsType.GetIdentityType(innerScope, argsNames)); innerScope.SetVarInfo(funcName, ScopePositionType.functionClass); } IfsType bodyType = Analyse(GetChildByType(node, fsharp_ssParser.BODY), innerScope); ITree annotatedReturningTypeNode = GetChildByType(node, fsharp_ssParser.TYPE); if (annotatedReturningTypeNode != null && annotatedReturningTypeNode.ChildCount > 0) { IfsType annotatedReturningType = new fsType(annotatedReturningTypeNode.GetChild(0).Text, null); UnifyWrapper(ref bodyType, ref annotatedReturningType, innerScope); } for (int i = 0; i < argsNames.Count; i++) { functionTypes.Add(innerScope.GetVarType(argsNames[i])); } functionTypes.Add(bodyType); fsType functionType = fsType.GetFunctionType(functionTypes); enteredFunctionsNames.RemoveAt(enteredFunctionsNames.Count - 1); return functionType; }
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; }