Spicy
Public Types | Public Member Functions | Static Public Attributes | List of all members
hilti::ASTContext Class Reference

#include <ast-context.h>

Inheritance diagram for hilti::ASTContext:

Public Types

using DeclarationSet = std::set< Declaration *, ast::detail::DeclarationPtrCmp >
 

Public Member Functions

 ASTContext (Context *context)
 
 ~ASTContext ()
 
auto * compilerContext () const
 
auto root () const
 
Result< declaration::module::UIDparseSource (Builder *builder, const hilti::rt::filesystem::path &path, std::optional< hilti::rt::filesystem::path > process_extension={})
 
Result< declaration::module::UIDimportModule (Builder *builder, const ID &id, const ID &scope, const hilti::rt::filesystem::path &parse_extension, const std::optional< hilti::rt::filesystem::path > &process_extension, std::vector< hilti::rt::filesystem::path > search_dirs)
 
declaration::ModulenewModule (Builder *builder, ID id, const hilti::rt::filesystem::path &process_extension)
 
declaration::Modulemodule (const declaration::module::UID &uid) const
 
Result< NothingprocessAST (Builder *builder, Driver *driver)
 
Driverdriver () const
 
std::set< declaration::module::UIDdependencies (const declaration::module::UID &uid, bool recursive=false) const
 
const DeclarationSet & dependentDeclarations (Declaration *n)
 
void updateModuleUID (const declaration::module::UID &old_uid, const declaration::module::UID &new_uid)
 
ast::DeclarationIndex register_ (Declaration *decl)
 
Declarationlookup (ast::DeclarationIndex index)
 
void replace (Declaration *old, Declaration *new_)
 
ast::TypeIndex register_ (UnqualifiedType *type)
 
UnqualifiedTypelookup (ast::TypeIndex index)
 
void replace (UnqualifiedType *old, UnqualifiedType *new_)
 
ID uniqueCanononicalID (const ID &id)
 
void dump (const hilti::logging::DebugStream &stream, const std::string &prefix) const
 
void dump (std::ostream &out, bool include_state) const
 
template<typename T , typename... Args>
T * make (Args &&... args)
 
template<typename T , typename... Args>
T * make (ASTContext *ctx, std::initializer_list< Node * > children, Args &&... args)
 
template<typename T , typename... Args>
T * make (ASTContext *ctx, type::Wildcard &&wildcard, std::initializer_list< Node * > children, Args &&... args)
 
void clearErrors (Node *node=nullptr)
 
void clearScopes (Node *node=nullptr)
 
Result< NothingcollectErrors ()
 
void checkAST (bool finished=true) const
 
void garbageCollect ()
 
void clear ()
 

Static Public Attributes

static constexpr unsigned int MaxASTIterationRounds = 100
 

Detailed Description

Environment for AST-wide state. The context maintains the AST root node and owns all nodes added to it or, recursively, any of if children. Each node can be part of just one AST context. Over time, the context also builds up further state about the AST.

Constructor & Destructor Documentation

◆ ASTContext()

ASTContext::ASTContext ( Context context)

Constructor.

Parameters
contextcompiler context to use for logging and error reporting

◆ ~ASTContext()

ASTContext::~ASTContext ( )

Destructor.

Member Function Documentation

◆ checkAST()

void ASTContext::checkAST ( bool  finished = true) const

Performs internal consistency checks on the AST.

Available in debug builds only as it can affect performance.

Parameters
finishedif true, indicates that AST processing has finished; it then runs some checks that might not hold while the AST is still being processed.

◆ clear()

void ASTContext::clear ( )

Release all state.

◆ clearErrors()

void ASTContext::clearErrors ( Node node = nullptr)

Clears out any error state recorded in the AST.

Parameters
nodeif given, only clears errors for subtree rooted at node; otherwise clears errors for the whole AST

◆ clearScopes()

void ASTContext::clearScopes ( Node node = nullptr)

Clears out scopes recorded in the AST.

Parameters
nodeif given, only clears scopes for subtree rooted at node; otherwise clears scopes for the whole AST

◆ collectErrors()

Result< Nothing > ASTContext::collectErrors ( )

Reports any error recorded in the AST to the user.

Returns
success if there are no errors (and hence nothing reported either)

◆ compilerContext()

auto* hilti::ASTContext::compilerContext ( ) const
inline

Returns the current compiler context in use.

◆ dependencies()

std::set<declaration::module::UID> hilti::ASTContext::dependencies ( const declaration::module::UID uid,
bool  recursive = false 
) const

Returns direct & indirect dependencies that a module imports. This information will be available only once the AST has been resolved.

Parameters
uidUID of module to return dependencies for; the module must be known, otherwise an internal error is reported
recursiveif true, return the transitive closure of all dependent units, vs just direct dependencies of the specified unit
Returns
set of dependencies

◆ dependentDeclarations()

const ASTContext::DeclarationSet & ASTContext::dependentDeclarations ( Declaration n)

Returns direct & indirect, global dependencies of a given global declaration. A "global declaration" is any declaration declared at either the root or the module level (i.e., node depth <= 2). The result will likewise include only such global declarations.

This information will be available only once the AST has been resolved. If called before that, the method will abort with an internal error.

Parameters
ddeclaration to return dependencies for, which must be part of the AST and declared at the root or module level
Returns
dependencies of d, which will all be root or module-level nodes as well; will include the declaration d itself iff there's a dependency cycle where any of the children depends in turn on the declaration itself; will return an empty set if the declaration has no dependencies, including if d is not actually a global declaration

◆ driver()

Driver* hilti::ASTContext::driver ( ) const
inline

During AST processing, returns the current compiler driver. If called outside of `processAST() executing, it will return null.

◆ dump() [1/2]

void ASTContext::dump ( const hilti::logging::DebugStream stream,
const std::string &  prefix 
) const

Dumps the current, complete AST of all modules to a debug stream.

Parameters
streamdebug stream to write to
prefixprefix line to start output with

◆ dump() [2/2]

void ASTContext::dump ( std::ostream &  out,
bool  include_state 
) const

Dumps the current, complete AST of all modules to an output stream.

Parameters
outoutput stream to write to
include_stateif true, also dumps the context's accumulated state

◆ garbageCollect()

void ASTContext::garbageCollect ( )

Clears up any AST nodes that are not currently retained by anybody.

◆ importModule()

Result< declaration::module::UID > ASTContext::importModule ( Builder builder,
const ID id,
const ID scope,
const hilti::rt::filesystem::path &  parse_extension,
const std::optional< hilti::rt::filesystem::path > &  process_extension,
std::vector< hilti::rt::filesystem::path >  search_dirs 
)

Imports a module from an external source file and adds it to the AST as a new module. This implements HILTI's import statement. If a module for the requested import is already part of the AST, returns the existing module without any further AST changes.

Parameters
builderbuilder to use for constructing the parsed AST
idname of the module to import (as in: import <id>)
scopesearch scope for the import (as in: import ... from <scope>)
parse_extensionfile extension indicating which plugin to use for parsing the module's source code
process_extensionif given, file extension indicating which plugin to use later for processing the resulting AST; if not given, the same plugin will be used as for parsing
search_dirslist of directories to search for the module's source (in addition to any globally configured search directories)
Returns
UID of the parsed module (which is now a part of the AST), or an error if parsing failed

◆ lookup() [1/2]

Declaration * ASTContext::lookup ( ast::DeclarationIndex  index)

Returns the declaration associated with an index.

Parameters
indexindex to lookup, which must have been registered before to not trigger an internal error; unless its None, in which case it returns null.

◆ lookup() [2/2]

UnqualifiedType * ASTContext::lookup ( ast::TypeIndex  index)

Returns the type associated with an index.

Parameters
indexindex to lookup, which must have been registered before to not trigger an internal error; unless its None, in which case it returns null.

◆ make() [1/3]

template<typename T , typename... Args>
T* hilti::ASTContext::make ( Args &&...  args)
inline

Factory function creating a new node of type T. This allocates the new through the context-wide memory resource.

Parameters
argsarguments to pass to the constructor of T

◆ make() [2/3]

template<typename T , typename... Args>
T* hilti::ASTContext::make ( ASTContext ctx,
std::initializer_list< Node * >  children,
Args &&...  args 
)
inline

Factory function creating a new node of type T. This allocates the new through the context-wide memory resource.

We need this variant because std::initializer_list cannot be passed through the generic std::forward.

Parameters
ctxfirst argument to pass to the constructor of T; must be this
childrensecond argument to pass to the constructor of T
argsremaining arguments to pass to the constructor of T

◆ make() [3/3]

template<typename T , typename... Args>
T* hilti::ASTContext::make ( ASTContext ctx,
type::Wildcard &&  wildcard,
std::initializer_list< Node * >  children,
Args &&...  args 
)
inline

Factory function creating a new node of type T. This allocates the new through the context-wide memory resource.

We need this variant because std::initializer_list cannot be passed through the generic std::forward.

Parameters
ctxfirst argument to pass to the constructor of T; must be this
wildcardsecond argument to pass to the constructor of T; must be this
childrenthird second argument to pass to the constructor of T
argsremaining arguments to pass to the constructor of T

◆ module()

declaration::Module* hilti::ASTContext::module ( const declaration::module::UID uid) const
inline

Retrieves a module node from the AST given its UID. Returns null if no such module exists.

Parameters
uidUID of module to return

◆ newModule()

declaration::Module * ASTContext::newModule ( Builder builder,
ID  id,
const hilti::rt::filesystem::path &  process_extension 
)

Adds a new, empty module to the AST.

◆ parseSource()

Result< declaration::module::UID > ASTContext::parseSource ( Builder builder,
const hilti::rt::filesystem::path &  path,
std::optional< hilti::rt::filesystem::path >  process_extension = {} 
)
   Parses a source file and adds it to the AST as a new module. If a module
   for this file is already part of the AST, returns the existing module
   without any further AST changes.

*

   @param builder builder to use for constructing the parsed AST
   @param path path to source file to parse
   @param process_extension if given, file extension indicating which
   plugin to use later for processing the resulting AST for the module; if
   not given, the same plugin will be used as for parsing (which is
   determined by the path's extension)
   @return UID of the parsed module (which is now a part of the AST), or an
   error if parsing failed

◆ processAST()

Result< Nothing > ASTContext::processAST ( Builder builder,
Driver driver 
)

Processes the whole AST with all of the compiler's visitor passes. This is the top-level entry point for all resolving/validating/optimizing. If successful, the will be fully resolved and validated; and ready for code generation.

Parameters
buildercurrent compiler builder, which AST processing may access
drivercurrent compiler driver, which AST processing may access

◆ register_() [1/2]

ast::DeclarationIndex ASTContext::register_ ( Declaration decl)

Registers a declaration with the context, assigning it a unique index through which it can later be retrieved. That index is automatically stored with the declaration as its `declarationindex().

If the declaration is a type declaration, the method also sets the declared type's declarationIndex() accordingly, linked the type with its declaration.

If the same declaration had already been registered earlier, nothing is changed; the method then simply returns the prior index.

Parameters
decldeclaration to register
Returns
the index now associated with the declaration; it's value is guaranteed to not be None (and hence be larger than zero).

◆ register_() [2/2]

ast::TypeIndex ASTContext::register_ ( UnqualifiedType type)

Registers a type with the context, assigning it a unique index through which it can later be retrieved. That index is automatically stored with the type as its `typeIndex().

If the same type had already been registered earlier, nothing is changed; the method then simply returns the prior index.

Parameters
decldeclaration to register
Returns
the index now associated with the type; it's value is guaranteed to not be None (and hence be larger than zero).

◆ replace() [1/2]

void ASTContext::replace ( Declaration old,
Declaration new_ 
)

Replaces a previously registered declaration with a new one. This means that any lookup for the existing declaration's index will now return the new declaration instead. The new declaration's declarationIndex() will automatically be set to index; the old declaration's declarationIndex() will not be changed.

If the new declaration is a type declaration, the method also sets the declared type's declarationIndex() accordingly, linking the type with its declaration. The old declaraed type is not changed.

Parameters
oldold declaration; if it has not been registered yet at all, the method returns without doing anything
newnew declaration to take the place of the old one

◆ replace() [2/2]

void ASTContext::replace ( UnqualifiedType old,
UnqualifiedType new_ 
)

Replaces a previously registered type with a new one. This means that any lookup for the existing type's index will now return the new type instead. The new type's typeIndex() will automatically be set to index; the old type's typeIndex() will not be changed.

Parameters
oldold type; if it has not been registered yet at all, the method returns without doing any tying
newnew type to take the place of the old one

◆ root()

auto hilti::ASTContext::root ( ) const
inline

Returns the AST's root node. This always exists.

◆ uniqueCanononicalID()

ID hilti::ASTContext::uniqueCanononicalID ( const ID id)
inline

Given an ID that's supposed to become a declaration's canonical ID, ensure that ID is globally unique within the context, returning an appropriately modified version if necessary.

◆ updateModuleUID()

void ASTContext::updateModuleUID ( const declaration::module::UID old_uid,
const declaration::module::UID new_uid 
)

Updates an existing UID with new information.

The given, old UID must correspond to a module parsed or imported into the context. This method then changes the module associated with that old UID to be associated with the new UID instead, and updates any context state accordingly, so that the module can now be found through the new UID.

Parameters
old_uidexisting UID; it's an internal error if this doesn't exist
new_uidnew UID to replace old_uid

Member Data Documentation

◆ MaxASTIterationRounds

constexpr unsigned int hilti::ASTContext::MaxASTIterationRounds = 100
staticconstexpr

Maximum number of rounds to perform during AST processing before assuming we are in an infinite loop without further progress being made. Once exceeded, processing aborts with an internal error as such as loop would indicate a bug in the compiler.


The documentation for this class was generated from the following files: