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

125 lines
3.3 KiB
C++

#include "value.h"
#include <sstream>
#include <iomanip>
#include <cmath>
namespace camellya {
std::string NumberValue::to_string() const {
if (std::floor(value) == value) {
return std::to_string(static_cast<int64_t>(value));
}
std::ostringstream oss;
oss << std::fixed << std::setprecision(6) << value;
std::string str = oss.str();
str.erase(str.find_last_not_of('0') + 1, std::string::npos);
if (str.back() == '.') str.pop_back();
return str;
}
std::string ListValue::to_string() const {
std::ostringstream oss;
oss << "[";
for (size_t i = 0; i < elements.size(); ++i) {
if (i > 0) oss << ", ";
oss << elements[i]->to_string();
}
oss << "]";
return oss.str();
}
ValuePtr ListValue::clone() const {
std::vector<ValuePtr> cloned_elements;
cloned_elements.reserve(elements.size());
for (const auto& elem : elements) {
cloned_elements.push_back(elem->clone());
}
return std::make_shared<ListValue>(std::move(cloned_elements));
}
ValuePtr ListValue::get(size_t index) const {
if (index >= elements.size()) {
return std::make_shared<NilValue>();
}
return elements[index];
}
void ListValue::set(size_t index, ValuePtr value) {
if (index >= elements.size()) {
elements.resize(index + 1, std::make_shared<NilValue>());
}
elements[index] = std::move(value);
}
std::string MapValue::to_string() const {
std::ostringstream oss;
oss << "{";
bool first = true;
for (const auto& [key, value] : pairs) {
if (!first) oss << ", ";
first = false;
oss << key << ": " << value->to_string();
}
oss << "}";
return oss.str();
}
ValuePtr MapValue::clone() const {
std::map<std::string, ValuePtr> cloned_pairs;
for (const auto& [key, value] : pairs) {
cloned_pairs[key] = value->clone();
}
return std::make_shared<MapValue>(std::move(cloned_pairs));
}
ValuePtr MapValue::get(const std::string& key) const {
auto it = pairs.find(key);
if (it == pairs.end()) {
return std::make_shared<NilValue>();
}
return it->second;
}
ValuePtr ClassValue::clone() const {
auto cloned = std::make_shared<ClassValue>(name);
cloned->fields = fields;
cloned->methods = methods;
return cloned;
}
ValuePtr InstanceValue::clone() const {
auto cloned = std::make_shared<InstanceValue>(klass);
for (const auto& [key, value] : fields) {
cloned->fields[key] = value->clone();
}
return cloned;
}
ValuePtr InstanceValue::get(const std::string& name) const {
// First check fields
auto field_it = fields.find(name);
if (field_it != fields.end()) {
return field_it->second;
}
// Then check methods and bind 'this'
auto method_it = klass->methods.find(name);
if (method_it != klass->methods.end()) {
auto bound = std::make_shared<FunctionValue>(*method_it->second);
auto self = std::static_pointer_cast<InstanceValue>(
const_cast<InstanceValue*>(this)->shared_from_this());
bound->bound_instance = self;
return bound;
}
return std::make_shared<NilValue>();
}
void InstanceValue::set(const std::string& name, ValuePtr value) {
if (fields.find(name) != fields.end()) {
fields[name] = std::move(value);
}
}
} // namespace camellya