Files
camellya/state.cpp
2026-01-13 22:52:55 +08:00

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