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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
#pragma once
#include "Core/Array.h"
#include "Thread.h"
#include "NamedFlags.h"
#include "Value.h"
#include "Visibility.h"
#include "Scope.h"
#include "Doc.h"
#include "ReplaceContext.h"
#include "ReplaceTasks.h"
namespace storm {
STORM_PKG(core.lang);
class Named;
class NameSet;
class SimpleName;
class SimplePart;
/**
* Interface for objects that can look up names.
*/
class NameLookup : public ObjectOn<Compiler> {
STORM_CLASS;
public:
STORM_CTOR NameLookup();
STORM_CTOR NameLookup(NameLookup *parent);
// Find a named entity that corresponds to the specified `SimplePart` in this object.
// Returns `null` if it is not found. The parameter `source` indicates in what context the
// name lookup is performed, and it is used to determine the visibility of entities.
virtual MAYBE(Named *) STORM_FN find(SimplePart *part, Scope source);
// Convenience overloads for `find`.
MAYBE(Named *) STORM_FN find(Str *name, Array<Value> *params, Scope source);
MAYBE(Named *) STORM_FN find(Str *name, Value param, Scope source);
MAYBE(Named *) STORM_FN find(Str *name, Scope source);
MAYBE(Named *) find(const wchar *name, Array<Value> *params, Scope source);
MAYBE(Named *) find(const wchar *name, Value param, Scope source);
MAYBE(Named *) find(const wchar *name, Scope source);
// Check if this entity has a particular parent, either directly or indirectly. If `parent`
// is null, then false is always returned.
Bool STORM_FN hasParent(MAYBE(NameLookup *) parent) const;
// Get the parent object to this lookup, or `null` if none.
virtual MAYBE(NameLookup *) STORM_FN parent() const;
// Parent name lookup. This should be set by the parent. If it is `null`, the default
// `parent` implementation asserts. Therefore, root objects need to override `parent` in
// order to return `null`.
MAYBE(NameLookup *) STORM_FN parentLookup() const { return pLookup; }
void STORM_ASSIGN parentLookup(MAYBE(NameLookup *) parent);
protected:
// Called when `parentLookup` was changed. The parameter indicates whether or not we have
// been added to a `NameSet` before or not.
virtual void STORM_FN onNewParent(MAYBE(NameLookup *) parent, Bool addedToNameSet);
// Set the parent of `other` to `this`. This is done with the intention of making `other`
// into a child that is kept track of and traversed as appropriately.
void STORM_FN makeChild(NameLookup *other);
private:
// The actual parent lookup.
MAYBE(NameLookup *) pLookup;
};
// Find the first instance of a specific type of thing.
MAYBE(NameLookup *) STORM_FN findTopmost(NameLookup *at, Type *type) ON(Compiler);
/**
* An extension of NameLookup with a position.
*
* This is useful to build linked structures for a Scope in order to indicate that we're at a
* particular location, which is useful for name lookups etc.
*/
class LookupPos : public NameLookup {
STORM_CLASS;
public:
// Create.
STORM_CTOR LookupPos();
STORM_CTOR LookupPos(SrcPos pos);
STORM_CTOR LookupPos(MAYBE(NameLookup *) parent, SrcPos pos);
// Our location in source code.
SrcPos pos;
};
/**
* Denotes a named object in the compiler. Named objects are for example functions, types.
*/
class Named : public LookupPos {
STORM_CLASS;
public:
// Create without parameters.
STORM_CTOR Named(Str *name);
STORM_CTOR Named(SrcPos pos, Str *name);
// Create with parameters.
STORM_CTOR Named(Str *name, Array<Value> *params);
STORM_CTOR Named(SrcPos pos, Str *name, Array<Value> *params);
// Our name. Note: may be null for a while during compiler startup.
Str *name;
// Our parameters. Note: may be null for a while during compiler startup.
Array<Value> *params;
// Visibility. 'null' means 'visible from everywhere'.
MAYBE(Visibility *) visibility;
// Documentation (if present).
MAYBE(NamedDoc *) documentation;
// Get a 'Doc' object for this entity. Uses 'documentation' if available, otherwise
// generates a dummy object. This could be a fairly expensive operation, since all
// documentation is generally *not* held in main memory.
Doc *STORM_FN findDoc();
// Check if this named entity is visible from 'source'.
Bool STORM_FN visibleFrom(Scope source);
Bool STORM_FN visibleFrom(MAYBE(NameLookup *) source);
// Flags for this named object.
NamedFlags flags;
// Late initialization. Called twice during startup. Once after the system has advanced far
// enough to use templates, and again when it has advanced far enough to use packages.
virtual void lateInit();
// Compute a path to this entity. Utilizes the parent pointers to traverse the name tree.
// Will assert if not properly added to the name tree.
SimpleName *STORM_FN path() const;
// Compute a path to this entity. Ignores the case where some parent was not found, and
// provides a truncated name in such cases. This is useful for messages, where it is not
// important that the name can be used to find the same entity again.
SimpleName *safePath() const;
// Get a human-readable identifier for this named object. May return an incomplete
// identifier if the entity is not properly added to the name tree.
virtual Str *STORM_FN identifier() const;
// Get a short version of the identifier. Only includes the name at this level with parameters.
virtual Str *STORM_FN shortIdentifier() const;
// Better asserts for 'parent'.
virtual MAYBE(NameLookup *) STORM_FN parent() const;
// Receive notifications from NameSet objects. (TODO: Move into separate class?)
virtual void STORM_FN notifyAdded(NameSet *to, Named *added);
// Receive notifications from NameSet objects. (TODO: Move into semarate class?)
virtual void STORM_FN notifyRemoved(NameSet *to, Named *removed);
// Force compilation of this entity (and any sub-objects contained in here).
virtual void STORM_FN compile();
// Discard references to source code stored in here. This is used to discard information
// required to re-compile the entity from source to save memory. Packages and types do this
// automatically unless instructed otherwise.
virtual void STORM_FN discardSource();
// Called when looking for equivalent types during a replacement. Should call 'addEq' for
// all equivalent types in the supplied context.
virtual void STORM_FN findEquivalentTypes(Named *old, ReplaceContext *ctx);
// See if this named entity is able to replace 'old'. If possible, null is returned. If not,
// a string containing an appropriate error message is returned. If this function does not
// return an error, it shall be safe to call 'replace' without errors. May also throw an
// exception to inhibit the system to try other approaches that would be tried if this
// function were to return an error message.
virtual MAYBE(Str *) STORM_FN canReplace(Named *old, ReplaceContext *ctx);
// Make this entity replace 'old'. If 'canReplace' did not return an error, this shall
// succeed without issues. Override 'doReplace' to customize the behavior of this function.
// Do not expect 'old' to be in a functional state after having been replaced.
void STORM_FN replace(Named *old, ReplaceTasks *tasks, ReplaceContext *ctx);
// Automatic replace: called by the system when entities marked with `namedAllowReplace` are
// replaced by the system. This does not happen during an operation requested by the system,
// which is why it is handled differently from regular calls to `replace`. Currently, this
// is more or less only used when the system silently inserts custom overrides of functions
// from TObject, when they are replaced with something user-defined. As such, we don't have
// to make sure that changes are immediate in this case (as is the case with the more
// advanced replacement mechanisms).
virtual void STORM_FN automaticReplace(Named *old);
// String representation.
virtual void STORM_FN toS(StrBuf *buf) const;
// Output the visibility to a string buffer.
void STORM_FN putVisibility(StrBuf *to) const;
protected:
// Called by 'replace' after verifying that 'canReplace' did not return an error.
virtual void STORM_FN doReplace(Named *old, ReplaceTasks *tasks, ReplaceContext *ctx);
// Keep track of when our parent lookup changes, so that we can discard our source as
// appropriate.
virtual void STORM_FN onNewParent(MAYBE(NameLookup *) parent, Bool addedToNameSet);
private:
// Find closest named parent.
MAYBE(Named *) closestNamed() const;
MAYBE(Named *) safeClosestNamed() const;
};
/**
* A pair of named items. Used to remember what to update during a reload.
*/
class NamedPair {
STORM_VALUE;
public:
STORM_CTOR NamedPair(Named *from, Named *to) {
this->from = from;
this->to = to;
}
Named *from;
Named *to;
// Output.
inline void STORM_FN toS(StrBuf *to) const {
*to << from << S(" -> ") << to;
}
};
}
|