Nearly CC
An educational compiler skeleton
symtab.h
1 // Copyright (c) 2021-2023, David H. Hovemeyer <david.hovemeyer@gmail.com>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the "Software"),
5 // to deal in the Software without restriction, including without limitation
6 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 // and/or sell copies of the Software, and to permit persons to whom the
8 // Software is furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included
11 // in all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
17 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
19 // OTHER DEALINGS IN THE SOFTWARE.
20 
21 #ifndef SYMTAB_H
22 #define SYMTAB_H
23 
24 #include <map>
25 #include <vector>
26 #include <string>
27 #include <memory>
28 #include "type.h"
29 #ifdef SOLUTION
30 #include "storage.h"
31 #endif
32 
33 class SymbolTable;
34 
35 enum class SymbolKind {
36  FUNCTION,
37  VARIABLE,
38  TYPE,
39 };
40 
41 class Symbol {
42 private:
43  SymbolKind m_kind;
44  std::string m_name;
45  std::shared_ptr<Type> m_type;
46  SymbolTable *m_symtab;
47 #ifdef SOLUTION
48  unsigned m_flags;
49  unsigned m_offset;
50  int m_vreg;
51 #endif
52  bool m_is_defined;
53 
54  // value semantics prohibited
55  Symbol(const Symbol &);
56  Symbol &operator=(const Symbol &);
57 
58 public:
59 #ifdef SOLUTION
60  // flags
61  enum Flag {
62  MEMORY = 1,
63  GLOBAL = 2,
64  };
65 #endif
66  Symbol(SymbolKind kind, const std::string &name, const std::shared_ptr<Type> &type, SymbolTable *symtab, bool is_defined);
67  ~Symbol();
68 
69  // a function, variable, or type can be declared
70  // and then later defined, so allow m_is_defined to
71  // be updated
72  void set_is_defined(bool is_defined);
73 
74  SymbolKind get_kind() const;
75  const std::string &get_name() const;
76  std::shared_ptr<Type> get_type() const;
77  SymbolTable *get_symtab() const;
78  bool is_defined() const;
79 #ifdef SOLUTION
80 
81  void set_flag(Flag flag) { m_flags |= unsigned(flag); }
82  void clear_flag(Flag flag) { m_flags &= ~(unsigned(flag)); }
83  bool has_flag(Flag flag) const { return (m_flags & unsigned(flag)) != 0U; }
84 
85  void set_offset(unsigned offset) { m_offset = offset; }
86  unsigned get_offset() const { return m_offset; }
87 
88  void set_vreg(int vreg) { m_vreg = vreg; }
89  int get_vreg() const { return m_vreg; }
90 #endif
91 };
92 
93 class SymbolTable {
94 private:
95  SymbolTable *m_parent;
96  std::vector<Symbol *> m_symbols;
97  std::map<std::string, unsigned> m_lookup;
98 #ifdef SOLUTION
99  bool m_report;
100  bool m_add_fields;
101  int m_next_vreg;
102 #endif
103  bool m_has_params; // true if this symbol table contains function parameters
104  std::shared_ptr<Type> m_fn_type; // this is set to the type of the enclosing function (if any)
105 
106  // value semantics prohibited
107  SymbolTable(const SymbolTable &);
108  SymbolTable &operator=(const SymbolTable &);
109 
110 public:
111  SymbolTable(SymbolTable *parent);
112  ~SymbolTable();
113 
114  SymbolTable *get_parent() const;
115 
116  bool has_params() const;
117  void set_has_params(bool has_params);
118 
119  // Operations limited to the current (local) scope.
120  // Note that the caller should verify that a name is not defined
121  // in the current scope before calling declare or define.
122  bool has_symbol_local(const std::string &name) const;
123  Symbol *lookup_local(const std::string &name) const;
124  Symbol *declare(SymbolKind sym_kind, const std::string &name, const std::shared_ptr<Type> &type);
125  Symbol *define(SymbolKind sym_kind, const std::string &name, const std::shared_ptr<Type> &type);
126 
127  // Iterate through the symbol table entries in the order in which they were added
128  // to the symbol table. This is important for struct types, where the representation
129  // of the type needs to record the fields (and their types) in the exact order
130  // in which they appeared in the source code.
131  typedef std::vector<Symbol *>::const_iterator const_iterator;
132  const_iterator cbegin() const { return m_symbols.cbegin(); }
133  const_iterator cend() const { return m_symbols.cend(); }
134 
135  // Operations that search recursively starting from the current (local)
136  // scope and expanding to outer scopes as necessary
137  Symbol *lookup_recursive(const std::string &name) const;
138 
139  // This can be called on the symbol table representing the function parameter
140  // scope of a function to record the exact type of the function
141  void set_fn_type(const std::shared_ptr<Type> &fn_type);
142 
143  // This returns the function type of the enclosing function, or nullptr
144  // if there is no enclosing function. This is helpful for type checking
145  // a return statement, to make sure that the value returned is
146  // assignment-compatible with the function's return type.
147  std::shared_ptr<Type> get_fn_type() const;
148 #ifdef SOLUTION
149 
150  void set_report(bool en) { m_report = en; }
151  bool add_fields() const { return m_add_fields; }
152  void set_add_fields(bool en) { m_add_fields = en; }
153 
154  bool is_global_scope() const { return m_parent == nullptr; }
155 
156  bool is_parameter_scope() const { return bool(m_fn_type) && m_fn_type->is_function(); }
157 #endif
158 
159  int get_depth() const;
160 
161 private:
162  void add_symbol(Symbol *sym);
163 };
164 
165 #endif // SYMTAB_H
Definition: symtab.h:93
Definition: symbol.h:28