85 lines
2.5 KiB
C++
85 lines
2.5 KiB
C++
#include "Environment.h"
|
|
#include "Parser.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
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<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
|
|
Variable::Variable(const std::function < Variable(std::vector<Variable>)>& 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<Number>(other.value) == std::get<Number>(value);
|
|
case Type::String:
|
|
return std::get<std::string>(other.value) == std::get<std::string>(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<std::string>(obj.value);
|
|
case Parse::Type::Number:
|
|
return Variable(std::get<Number>(obj.value));
|
|
case Parse::Type::String:
|
|
return Variable(std::get<std::string>(obj.value));
|
|
case Parse::Type::Array:
|
|
{
|
|
std::vector<Variable> v{};
|
|
for (const auto& x : std::get<std::vector<Parse::Object>>(obj.value))
|
|
v.push_back(Eval(x));
|
|
return Variable(v);
|
|
}
|
|
case Parse::Type::Subexpression:
|
|
{
|
|
return Apply(std::get<std::vector<Parse::Object>>(obj.value));
|
|
}
|
|
}
|
|
}
|
|
|
|
Variable Apply(const Parse::Command& c) {
|
|
std::vector<Variable> args{};
|
|
for (int i = 1; i < c.size(); i++)
|
|
args.push_back(Eval(c[i]));
|
|
return std::get<std::function<Variable(std::vector<Variable>)>>(ENVIRONMENT.get(std::get<std::string>(c[0].value)).value)(args);
|
|
}
|
|
|
|
void EvalScene(const Parse::Scene& s) {
|
|
for (const auto& c : s.get())
|
|
Apply(c);
|
|
}
|
|
}
|