136 lines
3.2 KiB
C++
136 lines
3.2 KiB
C++
#include "state.h"
|
|
#include <fstream>
|
|
#include <sstream>
|
|
|
|
namespace camellya {
|
|
|
|
State::State() : interpreter_(std::make_unique<Interpreter>()) {}
|
|
|
|
bool State::do_string(const std::string& script) {
|
|
try {
|
|
Lexer lexer(script);
|
|
auto tokens = lexer.tokenize();
|
|
|
|
Parser parser(std::move(tokens));
|
|
Program program = parser.parse();
|
|
|
|
interpreter_->execute(program);
|
|
|
|
last_error_.clear();
|
|
return true;
|
|
} catch (const std::exception& e) {
|
|
last_error_ = e.what();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool State::do_file(const std::string& filename) {
|
|
std::ifstream file(filename);
|
|
if (!file.is_open()) {
|
|
last_error_ = "Failed to open file: " + filename;
|
|
return false;
|
|
}
|
|
|
|
std::stringstream buffer;
|
|
buffer << file.rdbuf();
|
|
return do_string(buffer.str());
|
|
}
|
|
|
|
void State::register_function(const std::string& name, NativeFunction func) {
|
|
auto func_value = std::make_shared<FunctionValue>(name, func);
|
|
interpreter_->global_environment->define(name, func_value);
|
|
}
|
|
|
|
ValuePtr State::get_global(const std::string& name) {
|
|
return interpreter_->global_environment->get(name);
|
|
}
|
|
|
|
void State::set_global(const std::string& name, ValuePtr value) {
|
|
interpreter_->global_environment->define(name, value);
|
|
}
|
|
|
|
void State::push_number(double value) {
|
|
stack_.push_back(std::make_shared<NumberValue>(value));
|
|
}
|
|
|
|
void State::push_string(const std::string& value) {
|
|
stack_.push_back(std::make_shared<StringValue>(value));
|
|
}
|
|
|
|
void State::push_bool(bool value) {
|
|
stack_.push_back(std::make_shared<BoolValue>(value));
|
|
}
|
|
|
|
void State::push_nil() {
|
|
stack_.push_back(std::make_shared<NilValue>());
|
|
}
|
|
|
|
void State::push_value(ValuePtr value) {
|
|
stack_.push_back(std::move(value));
|
|
}
|
|
|
|
double State::to_number(int index) {
|
|
ValuePtr val = get_stack_value(index);
|
|
if (val && val->type() == Type::NUMBER) {
|
|
return std::dynamic_pointer_cast<NumberValue>(val)->value;
|
|
}
|
|
return 0.0;
|
|
}
|
|
|
|
std::string State::to_string(int index) {
|
|
ValuePtr val = get_stack_value(index);
|
|
if (val) {
|
|
return val->to_string();
|
|
}
|
|
return "";
|
|
}
|
|
|
|
bool State::to_bool(int index) {
|
|
ValuePtr val = get_stack_value(index);
|
|
return is_truthy(val);
|
|
}
|
|
|
|
ValuePtr State::to_value(int index) {
|
|
return get_stack_value(index);
|
|
}
|
|
|
|
void State::set_top(int index) {
|
|
if (index < 0) {
|
|
index = static_cast<int>(stack_.size()) + index + 1;
|
|
}
|
|
|
|
if (index < 0) {
|
|
stack_.clear();
|
|
} else if (static_cast<size_t>(index) < stack_.size()) {
|
|
stack_.resize(index);
|
|
} else {
|
|
while (static_cast<size_t>(index) > stack_.size()) {
|
|
stack_.push_back(std::make_shared<NilValue>());
|
|
}
|
|
}
|
|
}
|
|
|
|
void State::pop(int n) {
|
|
if (n > static_cast<int>(stack_.size())) {
|
|
stack_.clear();
|
|
} else {
|
|
stack_.resize(stack_.size() - n);
|
|
}
|
|
}
|
|
|
|
ValuePtr State::get_stack_value(int index) {
|
|
if (index < 0) {
|
|
index = static_cast<int>(stack_.size()) + index;
|
|
} else {
|
|
index -= 1; // Convert to 0-based
|
|
}
|
|
|
|
if (index < 0 || static_cast<size_t>(index) >= stack_.size()) {
|
|
return nullptr;
|
|
}
|
|
|
|
return stack_[index];
|
|
}
|
|
|
|
} // namespace camellya
|