#include "Environment.h" #include "Parser.h" #include namespace NVL::Environment { Environment ENVIRONMENT; Variable::Variable() {} Variable::Variable(Type t) : type(t) { if (t != Type::Nil) throw std::runtime_error("Cannot create non-nil object with type alone"); } Variable::Variable(const Number& v) : type(Type::Number), value(v), length(1) {} Variable::Variable(const std::string& v) : type(Type::String), value(v), length(1) {} Variable::Variable(const std::vector& v) : type(Type::Array), value(v), length(v.size()) {} Variable::Variable(const std::function < Variable(std::vector)>& v, int l) : type(Type::Procedure), value(v), length(l) {} bool Variable::operator==(const Variable& other) const { if (other.type != type) return false; switch (type) { case Type::Number: return std::get(other.value) == std::get(value); case Type::String: return std::get(other.value) == std::get(value); default: return false; } } void Environment::enter(const std::string& name, Variable p) { if (env.find(name) != env.end()) throw std::runtime_error("Redefinition of symbol in environment"); env[name] = p; } void Environment::set(const std::string& name, Variable p) { if (env.find(name) == env.end()) throw std::runtime_error("Attempting to set undefined variable"); env[name] = p; } Variable& Environment::get(const std::string& name) { return env.at(name); } bool Environment::exists(const std::string& name) { return env.find(name) != env.end(); } Variable Eval(const Parse::Object& obj) { switch (obj.type) { case Parse::Type::Symbol: return std::get(obj.value); case Parse::Type::Number: return Variable(std::get(obj.value)); case Parse::Type::String: return Variable(std::get(obj.value)); case Parse::Type::Array: { std::vector v{}; for (const auto& x : std::get>(obj.value)) v.push_back(Eval(x)); return Variable(v); } case Parse::Type::Subexpression: { return Apply(std::get>(obj.value)); } } } Variable Apply(const Parse::Command& c) { std::vector args{}; for (int i = 1; i < c.size(); i++) args.push_back(Eval(c[i])); return std::get)>>(ENVIRONMENT.get(std::get(c[0].value)).value)(args); } void EvalScene(const Parse::Scene& s) { for (const auto& c : s.get()) Apply(c); } }