summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/name.h
blob: a10168d9f463b3345f925d894259e8069c4dbeb1 (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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/*****
 * name.h
 * Andy Hammerlindl 2002/07/14
 *
 * Qualified names (such as x, f, builtin.sin, a.b.c.d, etc.) can be used
 * either as variables or a type names.  This class stores qualified
 * names used in nameExp and nameTy in the abstract syntax, and
 * implements the exp and type functions.
 *****/

#ifndef NAME_H
#define NAME_H

#include "absyn.h"
#include "types.h"
#include "frame.h"
#include "access.h"

namespace trans {
class coenv;
class varEntry;
class tyEntry;
}
namespace types {
class record;
}

namespace absyntax {

using trans::coenv;
using trans::action;
using types::record;
using std::ostream;

class name : public absyn {
public:
  name(position pos)
    : absyn(pos) {}

  // Helper function - ensures target and source match up, using casting in the
  // case of a read.  Issues errors on failure.
  void forceEquivalency(action act, coenv &e,
                        types::ty *target, types::ty *source);

  // Used for determining the type when the context does not establish
  // the name as a variable or a type.  First, the function looks for a
  // non-function variable fitting the description.  If one fits, the
  // type of the variable is returned.  Failing that, the function looks
  // for a fitting type and returns that.  If nothing is found, an
  // appropriate error is reported and ty_error is returned.
  // Because this is used only on qualifiers (ie. names to the left of a
  // dot), it does not look at function variables.
  // Tacit means that no error messages will be reported to the user.
  virtual types::ty *getType(coenv &e, bool tacit = false);

  // Pushes the highest level frame possible onto the stack.  Returning
  // the frame pushed.  If no frame can be pushed, returns 0.
  // NOTE: This duplicates some functionality with getVarEntry.
  virtual trans::frame *frameTrans(coenv &e);
  // Helper function for the case where the name is known to be a type.
  virtual trans::frame *tyFrameTrans(coenv &e) = 0;

  // Constructs the varEntry part of the tyEntry for the name.  Like
  // getType, this is called on the qualifier, instead of the full name.
  // This reports no errors, and returns 0 if there is no varEntry to
  // use.
  virtual trans::varEntry *getVarEntry(coenv &e) = 0;

  // As a variable:
  // Translates the name (much like an expression).
  virtual void varTrans(action act, coenv &e, types::ty *target) = 0;
  // Returns the possible variable types.  Unlike exp, returns 0 if none
  // match.
  virtual types::ty *varGetType(coenv &e) = 0;
  virtual trans::varEntry *getCallee(coenv &e, types::signature *sig) = 0;

  // As a type:
  // Determines the type, as used in a variable declaration.
  virtual types::ty *typeTrans(coenv &e, bool tacit = false) = 0;
  // Constructs the tyEntry of the name, needed so that we know the
  // parent frame for allocating new objects of that type.  Reports
  // errors as typeTrans() does with tacit=false.
  virtual trans::tyEntry *tyEntryTrans(coenv &e) = 0;

  virtual void prettyprint(ostream &out, Int indent) = 0;
  virtual void print(ostream& out) const {
    out << "<base name>";
  }

  virtual symbol getName() = 0;
};

inline ostream& operator<< (ostream& out, const name& n) {
  n.print(out);
  return out;
}

class simpleName : public name {
  symbol id;

public:
  simpleName(position pos, symbol id)
    : name(pos), id(id) {}

  trans::varEntry *getVarEntry(coenv &e);

  // As a variable:
  void varTrans(action act, coenv &e, types::ty *target);
  types::ty *varGetType(coenv &);
  trans::varEntry *getCallee(coenv &e, types::signature *sig);

  // As a type:
  types::ty *typeTrans(coenv &e, bool tacit = false);
  virtual trans::tyEntry *tyEntryTrans(coenv &e);
  trans::frame *tyFrameTrans(coenv &e);

  void prettyprint(ostream &out, Int indent);
  void print(ostream& out) const {
    out << id;
  }
  symbol getName() {
    return id;
  }
};


class qualifiedName : public name {
  name *qualifier;
  symbol id;

  // Gets the record type associated with the qualifier. Reports an
  // error and returns null if the type is not a record.
  record *castToRecord(types::ty *t, bool tacit = false);

  // Translates as a virtual field, if possible.  qt is the type of the
  // qualifier.  Return true if there was a matching virtual field. 
  bool varTransVirtual(action act, coenv &e,
                       types::ty *target, types::ty *qt);
  
  // Translates as an ordinary (non-virtual) field of a record, r.
  void varTransField(action act, coenv &e,
                     types::ty *target, record *r);
public:
  qualifiedName(position pos, name *qualifier, symbol id)
    : name(pos), qualifier(qualifier), id(id) {}

  trans::varEntry *getVarEntry(coenv &e);

  // As a variable:
  void varTrans(action act, coenv &, types::ty *target);
  types::ty *varGetType(coenv &);
  trans::varEntry *getCallee(coenv &e, types::signature *sig);

  // As a type:
  types::ty *typeTrans(coenv &e, bool tacit = false);
  trans::tyEntry *tyEntryTrans(coenv &e);
  trans::frame *tyFrameTrans(coenv &e);

  void prettyprint(ostream &out, Int indent);
  void print(ostream& out) const {
    out << *qualifier << "." << id;
  }
  symbol getName() {
    return id;
  }
};

} // namespace absyntax

#endif