public void AddFunction(string functionName, IfsType functionType) { if (functionsTypes.ContainsKey(functionName)) { throw new Exception($"Function {functionName} already exists in current scope"); } functionsTypes.Add(functionName, functionType); }
public void AddVar(string varName, IfsType varType) { if (varType.Name == "function") { if (functionsTypes.ContainsKey(varName)) { throw new Exception($"Function {varName} already exists in current scope"); } functionsTypes.Add(varName, varType); } if (varsTypes.ContainsKey(varName)) { throw new Exception($"Variable {varName} already exists in current scope"); } varsTypes.Add(varName, varType); }
public void ScopeVarOrFuncTypeChangedHandler(string oldTypeName, IfsType newType) { if (this.Text != "TYPE" || oldTypeName != NodeType.Name) { if (NodeType.Name == "function") { fsType nodeTyped = NodeType as fsType; for (int i = 0; i < nodeTyped.Types.Count; i++) { if (nodeTyped.Types[i].Name == oldTypeName) { nodeTyped.Types[i] = newType; } } } return; } NodeType = newType; }
private void UnifyWrapper(ref IfsType t1, ref IfsType t2, fsScope scope) { bool isT1FromScope = false; bool isT2FromScope = false; string t1ScopeName = ""; string t1NameBeforeUnification = t1.Name; string t2ScopeName = ""; string t2NameBeforeUnification = t2.Name; if (t1 is fsTypeVar) { isT1FromScope = (t1 as fsTypeVar).IsFromScope; t1ScopeName = (t1 as fsTypeVar).ScopeVarName; } if (t2 is fsTypeVar) { isT2FromScope = (t2 as fsTypeVar).IsFromScope; t2ScopeName = (t2 as fsTypeVar).ScopeVarName; } Unify(ref t1, ref t2, scope); if (isT1FromScope) { scope.ChangeVarOrFuncType(t1ScopeName, t1NameBeforeUnification, t1); } if (isT2FromScope) { scope.ChangeVarOrFuncType(t2ScopeName, t2NameBeforeUnification, t2); } }
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 Prune(IfsType type) { fsTypeVar a; if ((a = type as fsTypeVar)?.Instance != null) { a.Instance = Prune(a.Instance); return a.Instance; } return type; }
private bool OccursInTypeArray(IfsType type, List<IfsType> types) { foreach (var t in types) { if (OccursInType(type, t)) { return true; } } return false; }
private bool OccursInType(IfsType t1, IfsType t2) { t2 = Prune(t2); if (t2.Equals(t1)) { return true; } else if (t2 is fsType) { return OccursInTypeArray(t1, (t2 as fsType).Types); } return false; }
private IfsType InferBinaryOpType(ITree node, fsScope scope, IfsType availableType) { IfsType leftOperandType = Analyse(node.GetChild(0), scope); IfsType rightOperandType = Analyse(node.GetChild(1), scope); UnifyWrapper(ref leftOperandType, ref availableType, scope); UnifyWrapper(ref rightOperandType, ref availableType, scope); UnifyWrapper(ref leftOperandType, ref rightOperandType, scope); return leftOperandType; }
public void ChangeVarOrFuncType(string varName, string oldTypeName, IfsType newType) { ScopeVarOrFuncTypeChanged(oldTypeName, newType); }
public fsTreeNode(IfsType type) : base(new CommonToken(fsharp_ssParser.TYPE, type.Name)) { this.Text = "TYPE"; this.NodeType = type; }