private void Unify(ref IfsType t1, ref IfsType t2, fsScope scope) { if (t1.Name == "identity") { t1 = t2; return; } if (t2.Name == "identity") { t2 = t1; return; } IfsType t1Pruned = Prune(t1); IfsType t2Pruned = Prune(t2); if (t1Pruned.Name != "composite") { t1 = t1Pruned; } if (t2Pruned.Name != "composite") { t2 = t2Pruned; } if (t1 is fsTypeVar) { if (!t1.Equals(t2)) { if (OccursInType(t1, t2)) { throw new Exception("Recursive unification"); } if (t2.Name == "composite") { (t1 as fsTypeVar).Instance = t2; } else { t1 = t2; } } } else if(t1 is fsType && t2 is fsTypeVar) { UnifyWrapper(ref t2, ref t1, scope); } else if (t1 is fsType && t2 is fsType) { fsType type1 = t1 as fsType; fsType type2 = t2 as fsType; if (type1.Name == "composite") { if (type2.Name != "composite") { UnifyWrapper(ref t2, ref t1, scope); return; } List<IfsType> commonTypes = new List<IfsType>(); for (int i = 0; i < type1.Types.Count; i++) { for (int j = 0; j < type2.Types.Count; j++) { if (type1.Types[i].Equals(type2.Types[j])) { commonTypes.Add(type1.Types[i]); } } } if (commonTypes.Count < 1) { throw new Exception($"Cannot unify types {type1.Name} and {type2.Name}"); } else if (commonTypes.Count == 0) { t1 = t2 = commonTypes[0]; } else { fsTypeVar commonType = new fsTypeVar(); commonType.Instance = fsType.GetCompositeType(commonTypes); t1 = t2 = commonType; } return; } if (type2.Name == "composite") { for (int i = 0; i < type2.Types.Count; i++) { if (type1.Equals(type2.Types[i])) { t1 = t2 = type1; return; } } throw new Exception($"Cannot unify types {type1.Name} and {type2.Name}"); } if (!type1.Equals(type2)) { throw new Exception($"Cannot unify types {type1.Name} and {type2.Name}"); } if (type1.Name == "function") { if (type1.Types.Count == type2.Types.Count) { IfsType returningType = type2.Types[type2.Types.Count - 1]; for (int i = 0; i < type1.Types.Count - 1; i++) { IfsType t1Child = type1.Types[i]; IfsType t2Child = type2.Types[i]; string t2NameBeforeUnification = t2Child.Name; //Changed !!!!!!! UnifyWrapper(ref t2Child, ref t1Child, scope); type1.Types[i] = t1Child; type2.Types[i] = t2Child; if (returningType.Name == t2NameBeforeUnification) { UnifyWrapper(ref returningType, ref t1Child, scope); type1.Types[i] = returningType; type2.Types[type2.Types.Count - 1] = t2Child; } } } else if (type1.Types.Count < type2.Types.Count) { int difference = type2.Types.Count - type1.Types.Count; for (int i = 0; i < type1.Types.Count - 1; i++) { IfsType t1Child = type1.Types[i]; IfsType t2Child = type2.Types[i]; string t2NameBeforeUnification = t2Child.Name; //Changed !!!!!!! UnifyWrapper(ref t2Child, ref t1Child, scope); type1.Types[i] = t1Child; type2.Types[i] = t2Child; for (int j = difference; j < type2.Types.Count; j++) { IfsType bufType = type2.Types[j]; if (bufType.Name == t2NameBeforeUnification) { UnifyWrapper(ref t1Child, ref bufType, scope); type1.Types[i] = bufType; type2.Types[j] = t2Child; } } } List<IfsType> rest = type2.Types.GetRange(type1.Types.Count - 1, difference + 1); type1.Types[type1.Types.Count - 1] = fsType.GetFunctionType(rest); t1 = t2 = type1; } else { throw new Exception($"Cannot unify types {type1.Name} and {type2.Name}"); } } } else { throw new Exception($"Cannot unify types {t1.Name} and {t2.Name}"); } }
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; }