xo-expression: + environment implementation
This commit is contained in:
parent
829bffd007
commit
d836f13b88
3 changed files with 139 additions and 0 deletions
23
include/xo/expression/Environment.hpp
Normal file
23
include/xo/expression/Environment.hpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* file Environment.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jun 2024
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "Variable.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
class Environment : public ref::Refcount {
|
||||
public:
|
||||
/** lookup variable-expression @p vname in this environment
|
||||
**/
|
||||
virtual ref::brw<Variable> lookup_var(const std::string & vname) const = 0;
|
||||
};
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end Environment.hpp */
|
||||
46
include/xo/expression/GlobalEnv.hpp
Normal file
46
include/xo/expression/GlobalEnv.hpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/* file GlobalEnv.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jun 2024
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Environment.hpp"
|
||||
#include <map>
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
class GlobalEnv : public Environment {
|
||||
public:
|
||||
ref::brw<Variable> require_global(ref::brw<Variable> var) {
|
||||
const std::string & vname = var->name();
|
||||
|
||||
auto ix = var_map_.find(vname);
|
||||
|
||||
if (ix == var_map_.end()) {
|
||||
var_map_[vname] = var.get();
|
||||
return var;
|
||||
} else {
|
||||
return ix->second;
|
||||
}
|
||||
} /*require_global*/
|
||||
|
||||
// ----- Environment -----
|
||||
|
||||
virtual ref::brw<Variable> lookup_var(const std::string & vname) const {
|
||||
auto ix = var_map_.find(vname);
|
||||
|
||||
if (ix == var_map_.end())
|
||||
return ref::brw<Variable>::from_native(nullptr);
|
||||
|
||||
return ix->second;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, ref::rp<Variable>> var_map_;
|
||||
};
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end GlobalEnv.hpp */
|
||||
70
include/xo/expression/LocalEnv.hpp
Normal file
70
include/xo/expression/LocalEnv.hpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/* file LocalEnv.hpp
|
||||
*
|
||||
* author: Roland Conybeare, Jun 2024
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Environment.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace ast {
|
||||
/** @brief LocalEnv
|
||||
*
|
||||
* @class Local environment for a lambda.
|
||||
* Lists the Variables corresponding to this lambda's formal
|
||||
* parameters, but also links to @ref Environment for
|
||||
* innermost enclosing @ref Lambda.
|
||||
**/
|
||||
class LocalEnv : public Environment {
|
||||
public:
|
||||
using TypeDescr = xo::reflect::TypeDescr;
|
||||
|
||||
public:
|
||||
/** named ctor idiom. Create instance with local variables per @p argv **/
|
||||
static ref::rp<LocalEnv> make(const std::vector<ref::rp<Variable>> & argv) {
|
||||
return new LocalEnv(argv);
|
||||
}
|
||||
|
||||
const std::vector<ref::rp<Variable>> & argv() const { return argv_; }
|
||||
int n_arg() const { return argv_.size(); }
|
||||
TypeDescr fn_arg(uint32_t i) const { return argv_[i]->valuetype(); }
|
||||
|
||||
/** single-assign this environment's parent **/
|
||||
void assign_parent(ref::brw<Environment> p) {
|
||||
assert(parent_env_.get() == nullptr);
|
||||
parent_env_ = p.get();
|
||||
}
|
||||
|
||||
// ----- Environment -----
|
||||
|
||||
virtual ref::brw<Variable> lookup_var(const std::string & target) const override {
|
||||
for (const auto & arg : argv_) {
|
||||
if (arg->name() == target)
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* here: target not found in local vars,
|
||||
* delegate to innermost ancestor
|
||||
*/
|
||||
return parent_env_->lookup_var(target);
|
||||
}
|
||||
|
||||
private:
|
||||
LocalEnv(const std::vector<ref::rp<Variable>> & argv)
|
||||
: argv_(argv) {}
|
||||
|
||||
private:
|
||||
/** formal argument names **/
|
||||
std::vector<ref::rp<Variable>> argv_;
|
||||
|
||||
/** parent environment. Free variable in this lambda's
|
||||
* body, will be resolved by referring them to @ref parent_env_.
|
||||
**/
|
||||
ref::rp<Environment> parent_env_;
|
||||
};
|
||||
} /*namespace ast*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end LocalEnv.hpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue