예제 #1
0
파일: Solver.cs 프로젝트: nobikik9/kju
        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)));
        }
예제 #2
0
        private static IEnumerable <IHerbrandObject> GetAllHerbrandObjects(IHerbrandObject root)
        {
            yield return(root);

            foreach (var obj in root.GetArguments().SelectMany(GetAllHerbrandObjects))
            {
                yield return(obj);
            }
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
파일: Solver.cs 프로젝트: nobikik9/kju
        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);
                }
            }
        }
예제 #5
0
파일: TypeChecker.cs 프로젝트: nobikik9/kju
 private Clause EqualityClause(Expression node, IHerbrandObject t)
 {
     return(new Clause((node.Type, t), node.InputRange));
 }
예제 #6
0
파일: TypeChecker.cs 프로젝트: nobikik9/kju
 private Clause EqualityClause(IHerbrandObject a, IHerbrandObject b, Node node)
 {
     return(new Clause((a, b), node.InputRange));
 }
예제 #7
0
파일: TypeChecker.cs 프로젝트: nobikik9/kju
            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;
                }
예제 #8
0
 private static IEnumerable <TypeVariable> GetAllTypeVariables(IHerbrandObject root)
 {
     return(GetAllHerbrandObjects(root)
            .Where(obj => obj is TypeVariable)
            .Select(obj => (TypeVariable)obj));
 }