xo-expression: + environment implementation

This commit is contained in:
Roland Conybeare 2024-06-30 19:10:56 -04:00
commit d836f13b88
3 changed files with 139 additions and 0 deletions

View 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 */

View 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 */

View 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 */