125 lines
3.3 KiB
C++
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
|