NouVeL/NVL/Environment.cpp

85 lines
2.5 KiB
C++
Raw Normal View History

2021-12-12 22:20:28 -05:00
#include "Environment.h"
2021-12-17 01:05:38 -05:00
#include "Parser.h"
2021-12-12 22:20:28 -05:00
2021-12-17 01:05:38 -05:00
#include <stdexcept>
namespace NVL::Environment {
Environment ENVIRONMENT;
2022-08-18 12:17:43 -04:00
Variable::Variable() : type(Type::Nil), length(0) { }
Variable::Variable(Type t) : type(t), length(0) {
2021-12-17 01:05:38 -05:00
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 String& v) : type(Type::String), value(v), length(1) {}
2021-12-17 01:05:38 -05:00
Variable::Variable(const std::vector<Variable>& v) : type(Type::Array), value(v), length(v.size()) {}
2022-08-18 12:17:43 -04:00
Variable::Variable(const std::function < Variable(std::vector<Variable>)>& v, u32 l) : type(Type::Procedure), value(v), length(l) {}
2021-12-12 22:20:28 -05:00
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<String>(other.value) == std::get<NVL::String>(value);
2021-12-12 22:20:28 -05:00
default:
return false;
}
}
void Environment::enter(const String& name, Variable p) {
2021-12-12 22:20:28 -05:00
if (env.find(name) != env.end())
throw std::runtime_error("Redefinition of symbol in environment");
2022-08-18 12:17:43 -04:00
env.emplace(name, p);
2021-12-12 22:20:28 -05:00
}
void Environment::set(const String& name, Variable p) {
2021-12-12 22:20:28 -05:00
if (env.find(name) == env.end())
throw std::runtime_error("Attempting to set undefined variable");
env[name] = p;
}
Variable& Environment::get(const String& name) {
2021-12-12 22:20:28 -05:00
return env.at(name);
}
bool Environment::exists(const String& name) {
2021-12-12 22:20:28 -05:00
return env.find(name) != env.end();
}
2021-12-17 01:05:38 -05:00
Variable Eval(const Parse::Object& obj) {
switch (obj.type) {
case Parse::Type::Symbol:
return std::get<String>(obj.value);
2021-12-17 01:05:38 -05:00
case Parse::Type::Number:
return Variable(std::get<Number>(obj.value));
case Parse::Type::String:
return Variable(std::get<String>(obj.value));
2021-12-17 01:05:38 -05:00
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{};
2022-08-18 12:17:43 -04:00
for (u32 i = 1; i < c.size(); i++)
2021-12-17 01:05:38 -05:00
args.push_back(Eval(c[i]));
return std::get<std::function<Variable(std::vector<Variable>)>>(ENVIRONMENT.get(std::get<String>(c[0].value)).value)(args);
2021-12-17 01:05:38 -05:00
}
void EvalScene(const Parse::Scene& s) {
for (const auto& c : s.get())
Apply(c);
}
2021-12-13 14:04:12 -05:00
}