summaryrefslogtreecommitdiff
path: root/Source/Core/TypeAmbiguitySeeker.ssc
blob: 762b9c043fddfb15670955e63ed436ce0a44bea9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System;

// Visitor to search for types proxies that could not completely be
// determined by type inference. If this happens, a warning is
// generated and the proxies are instantiated in a more or less arbitrary
// fashion.

namespace Microsoft.Boogie 
{

  public class TypeAmbiguitySeeker : StandardVisitor {

    private readonly InTypeSeeker! inTypeSeeker = new InTypeSeeker ();
    private readonly TypecheckingContext! TC;

    public TypeAmbiguitySeeker(TypecheckingContext! tc) {
      TC = tc;
    }

    private void CheckTypeParams(Absy! node, TypeParamInstantiation! insts) {
      foreach (TypeVariable! var in insts.FormalTypeParams) {
        Type! inst = insts[var];
        inTypeSeeker.FoundAmbiguity = false;
        inTypeSeeker.Visit(inst);
        if (inTypeSeeker.FoundAmbiguity)
          TC.Warning(node,
                     "type parameter {0} is ambiguous, instantiating to {1}",
                     var, inst);
      }
    }

    public override Expr! VisitNAryExpr(NAryExpr! node)
    {
      CheckTypeParams(node, (!)node.TypeParameters);
      return base.VisitNAryExpr(node);
    }

    public override AssignLhs! VisitMapAssignLhs(MapAssignLhs! node) {
      CheckTypeParams(node, (!)node.TypeParameters);
      return base.VisitMapAssignLhs(node);      
    }
  }

  internal class InTypeSeeker : StandardVisitor {
    
    internal bool FoundAmbiguity = false;

    // called when an uninstantiated proxy was found
    private Type! Instantiate(Type! node, Type! inst) {
       FoundAmbiguity = true;
       bool success = node.Unify(inst);
       assert success;
       return node;
    }

    public override Type! VisitTypeProxy(TypeProxy! node) {
      if (node.ProxyFor != null)
        return base.VisitTypeProxy(node);

       return Instantiate(node, Type.Int);
    }

    public override Type! VisitMapTypeProxy(MapTypeProxy! node) {
      if (node.ProxyFor != null)
        return base.VisitMapTypeProxy(node);

       TypeVariableSeq! typeParams = new TypeVariableSeq ();
       TypeSeq! arguments = new TypeSeq ();
       for (int i = 0; i < node.Arity; ++i) {
         TypeVariable! param = new TypeVariable (Token.NoToken, "arg" + i);
         typeParams.Add(param);
         arguments.Add(param);
       }
       TypeVariable! result = new TypeVariable (Token.NoToken, "res");
       typeParams.Add(result);

       Type! instantiation = new MapType (Token.NoToken, typeParams, arguments, result);

       return Instantiate(node, instantiation);
    }

    public override Type! VisitBvTypeProxy(BvTypeProxy! node) {
      if (node.ProxyFor != null)
        return base.VisitBvTypeProxy(node);

       return Instantiate(node, new BvType (node.MinBits));
    }
  }

}