private bool Unify(IHerbrandObject x, IHerbrandObject y) { x = this.findUnion.GetRepresentant(x); y = this.findUnion.GetRepresentant(y); if (x == y) { return(true); } if (y is TypeVariable) { (x, y) = (y, x); } if (x is TypeVariable) { this.findUnion.Union(x, y); return(true); } if (x.GetTag() != y.GetTag() || x.GetArguments().Count() != y.GetArguments().Count()) { return(false); } this.findUnion.Union(x, y); return(x.GetArguments() .Zip(y.GetArguments(), (first, second) => (first, second)) .All(tuple => this.Unify(tuple.first, tuple.second))); }
private static IEnumerable <IHerbrandObject> GetAllHerbrandObjects(IHerbrandObject root) { yield return(root); foreach (var obj in root.GetArguments().SelectMany(GetAllHerbrandObjects)) { yield return(obj); } }
private static IHerbrandObject TieReferences(IHerbrandObject obj, IDictionary <TypeVariable, IHerbrandObject> mapping) { switch (obj) { case TypeVariable typeVariable: return(mapping[typeVariable]); case ArrayType arrayType: return(new ArrayType((DataType)TieReferences(arrayType.ElementType, mapping))); case FunType funType: var argTypes = funType.ArgTypes.Select(type => (DataType)TieReferences(type, mapping)); var resultType = (DataType)TieReferences(funType.ResultType, mapping); return(new FunType(argTypes, resultType)); default: return(obj); } }
private void Dfs( IHerbrandObject v, ISet <IHerbrandObject> visited, IDictionary <TypeVariable, IHerbrandObject> variableMapping) { if (visited.Contains(v)) { return; } visited.Add(v); if (v is TypeVariable typeVariable) { variableMapping.Add(typeVariable, this.findUnion.GetRepresentant(v)); } else { foreach (var child in v.GetArguments()) { this.Dfs(child, visited, variableMapping); } } }
private Clause EqualityClause(Expression node, IHerbrandObject t) { return(new Clause((node.Type, t), node.InputRange)); }
private Clause EqualityClause(IHerbrandObject a, IHerbrandObject b, Node node) { return(new Clause((a, b), node.InputRange)); }
private IEnumerable <Clause> GenerateClauses(Expression node) { switch (node) { case NullLiteral _: break; case InstructionBlock _: case FunctionDeclaration _: case StructDeclaration _: case BreakStatement _: case ContinueStatement _: yield return(this.EqualityClause(node, UnitType.Instance)); break; case VariableDeclaration decl: if (decl.Value != null) { yield return(this.EqualityClause(decl.Value, decl.VariableType)); } yield return(this.EqualityClause(node, UnitType.Instance)); break; case WhileStatement whileNode: yield return(this.EqualityClause(whileNode.Condition, BoolType.Instance)); yield return(this.EqualityClause(node, UnitType.Instance)); break; case IfStatement ifNode: yield return(this.EqualityClause(ifNode.Condition, BoolType.Instance)); yield return(this.EqualityClause(node, UnitType.Instance)); break; case FunctionCall funCall: { Clause clause = this.OverloadsClause(funCall); this.callOptions[funCall] = clause; yield return(clause); break; } case ReturnStatement returnNode: yield return(returnNode.Value == null ? this.EqualityClause(this.returnType.Peek(), UnitType.Instance, returnNode) : this.EqualityClause(returnNode.Value, this.returnType.Peek())); yield return(this.EqualityClause(returnNode, returnNode.Value?.Type ?? UnitType.Instance)); break; case Variable variable: yield return(this.EqualityClause(variable, variable.Declaration.VariableType)); break; case BoolLiteral boolNode: yield return(this.EqualityClause(boolNode, BoolType.Instance)); break; case IntegerLiteral integerNode: yield return(this.EqualityClause(integerNode, IntType.Instance)); break; case UnitLiteral unitNode: yield return(this.EqualityClause(unitNode, UnitType.Instance)); break; case Assignment assignment: yield return(this.EqualityClause(assignment.Value, assignment.Lhs.Declaration.VariableType)); yield return(this.EqualityClause(assignment, assignment.Value.Type)); break; case CompoundAssignment assignment: yield return(this.EqualityClause(assignment.Lhs.Declaration.VariableType, IntType.Instance, assignment.Lhs)); yield return(this.EqualityClause(assignment.Value, IntType.Instance)); yield return(this.EqualityClause(assignment, IntType.Instance)); break; case ArithmeticOperation operationNode: yield return(this.EqualityClause(operationNode.LeftValue, IntType.Instance)); yield return(this.EqualityClause(operationNode.RightValue, IntType.Instance)); yield return(this.EqualityClause(operationNode, IntType.Instance)); break; case Comparison cmp: { switch (cmp.OperationType) { case ComparisonType.Equal: case ComparisonType.NotEqual: yield return(this.EqualityClause(cmp.LeftValue.Type, cmp.RightValue.Type, cmp)); break; case ComparisonType.Less: case ComparisonType.LessOrEqual: case ComparisonType.Greater: case ComparisonType.GreaterOrEqual: yield return(this.EqualityClause(cmp.LeftValue, IntType.Instance)); yield return(this.EqualityClause(cmp.RightValue, IntType.Instance)); break; } yield return(this.EqualityClause(cmp, BoolType.Instance)); break; } case UnaryOperation op: { IHerbrandObject type = UnaryOperationToType[op.UnaryOperationType]; yield return(this.EqualityClause(op.Value, type)); yield return(this.EqualityClause(op, type)); break; } case LogicalBinaryOperation op: yield return(this.EqualityClause(op.LeftValue, BoolType.Instance)); yield return(this.EqualityClause(op.RightValue, BoolType.Instance)); yield return(this.EqualityClause(op, BoolType.Instance)); break; case ArrayAlloc alloc: yield return(this.EqualityClause(alloc.Size, IntType.Instance)); yield return(this.EqualityClause(alloc, new ArrayType(alloc.ElementType))); break; case ArrayAccess access: yield return(this.EqualityClause(access.Index, IntType.Instance)); yield return(this.EqualityClause(access.Lhs, new ArrayType(access.Type))); break; case ComplexAssignment assignment: yield return(this.EqualityClause(assignment.Lhs, assignment.Value.Type)); yield return(this.EqualityClause(assignment, assignment.Value.Type)); break; case ComplexCompoundAssignment assignment: yield return(this.EqualityClause(assignment.Lhs, IntType.Instance)); yield return(this.EqualityClause(assignment.Value, IntType.Instance)); yield return(this.EqualityClause(assignment, IntType.Instance)); break; case FieldAccess access: yield return(this.StructCandidatesClause(access)); break; case StructAlloc alloc: yield return(this.EqualityClause(alloc, StructType.GetInstance(alloc.Declaration))); break; case Application app: yield return(this.EqualityClause( app.Function, new FunType(app.Arguments.Select(arg => arg.Type), app.Type))); break; case UnApplication unapp: { Clause clause = new Clause( unapp.Candidates .Select(decl => new Alternative { (unapp.Type, new FunType(decl)) }) .ToList(), unapp.InputRange); this.unappOptions[unapp] = clause; yield return(clause); break; }
private static IEnumerable <TypeVariable> GetAllTypeVariables(IHerbrandObject root) { return(GetAllHerbrandObjects(root) .Where(obj => obj is TypeVariable) .Select(obj => (TypeVariable)obj)); }