This commit is contained in:
2026-01-13 22:52:55 +08:00
commit 211a837468
18 changed files with 2831 additions and 0 deletions

211
value.h Normal file
View File

@@ -0,0 +1,211 @@
#ifndef CAMELLYA_VALUE_H
#define CAMELLYA_VALUE_H
#include <memory>
#include <vector>
#include <map>
#include <string>
#include <variant>
#include <functional>
namespace camellya {
class Value;
using ValuePtr = std::shared_ptr<Value>;
using NativeFunction = std::function<ValuePtr(const std::vector<ValuePtr>&)>;
enum class Type {
NIL,
NUMBER,
STRING,
BOOL,
LIST,
MAP,
FUNCTION,
CLASS,
INSTANCE
};
class Value {
public:
virtual ~Value() = default;
virtual Type type() const = 0;
virtual std::string to_string() const = 0;
virtual ValuePtr clone() const = 0;
};
class NilValue : public Value {
public:
Type type() const override { return Type::NIL; }
std::string to_string() const override { return "nil"; }
ValuePtr clone() const override { return std::make_shared<NilValue>(); }
};
class NumberValue : public Value {
public:
double value;
explicit NumberValue(double value) : value(value) {}
Type type() const override { return Type::NUMBER; }
std::string to_string() const override;
ValuePtr clone() const override { return std::make_shared<NumberValue>(value); }
};
class StringValue : public Value {
public:
std::string value;
explicit StringValue(std::string value) : value(std::move(value)) {}
Type type() const override { return Type::STRING; }
std::string to_string() const override { return value; }
ValuePtr clone() const override { return std::make_shared<StringValue>(value); }
};
class BoolValue : public Value {
public:
bool value;
explicit BoolValue(bool value) : value(value) {}
Type type() const override { return Type::BOOL; }
std::string to_string() const override { return value ? "true" : "false"; }
ValuePtr clone() const override { return std::make_shared<BoolValue>(value); }
};
class ListValue : public Value {
public:
std::vector<ValuePtr> elements;
ListValue() = default;
explicit ListValue(std::vector<ValuePtr> elements) : elements(std::move(elements)) {}
Type type() const override { return Type::LIST; }
std::string to_string() const override;
ValuePtr clone() const override;
void push(ValuePtr value) { elements.push_back(std::move(value)); }
ValuePtr get(size_t index) const;
void set(size_t index, ValuePtr value);
size_t size() const { return elements.size(); }
};
class MapValue : public Value {
public:
std::map<std::string, ValuePtr> pairs;
MapValue() = default;
explicit MapValue(std::map<std::string, ValuePtr> pairs) : pairs(std::move(pairs)) {}
Type type() const override { return Type::MAP; }
std::string to_string() const override;
ValuePtr clone() const override;
void set(const std::string& key, ValuePtr value) { pairs[key] = std::move(value); }
ValuePtr get(const std::string& key) const;
bool has(const std::string& key) const { return pairs.find(key) != pairs.end(); }
};
// Forward declarations
struct FunctionDecl;
class ClassValue;
class InstanceValue;
class FunctionValue : public Value {
public:
std::string name;
std::vector<std::pair<std::string, std::string>> parameters;
std::string return_type;
std::shared_ptr<FunctionDecl> declaration;
NativeFunction native_func;
bool is_native;
std::shared_ptr<InstanceValue> bound_instance;
// Script function
FunctionValue(std::string name, std::shared_ptr<FunctionDecl> declaration,
std::shared_ptr<InstanceValue> bound_instance = nullptr)
: name(std::move(name)), declaration(std::move(declaration)),
is_native(false), bound_instance(std::move(bound_instance)) {}
// Native function
FunctionValue(std::string name, NativeFunction func)
: name(std::move(name)), native_func(std::move(func)), is_native(true) {}
Type type() const override { return Type::FUNCTION; }
std::string to_string() const override { return "<function " + name + ">"; }
ValuePtr clone() const override { return std::make_shared<FunctionValue>(*this); }
};
class ClassValue : public Value {
public:
std::string name;
std::map<std::string, std::string> fields; // field_name -> type_name
std::map<std::string, std::shared_ptr<FunctionValue>> methods;
explicit ClassValue(std::string name) : name(std::move(name)) {}
Type type() const override { return Type::CLASS; }
std::string to_string() const override { return "<class " + name + ">"; }
ValuePtr clone() const override;
void add_field(const std::string& name, const std::string& type) {
fields[name] = type;
}
void add_method(const std::string& name, std::shared_ptr<FunctionValue> method) {
methods[name] = std::move(method);
}
};
class InstanceValue : public Value, public std::enable_shared_from_this<InstanceValue> {
public:
std::shared_ptr<ClassValue> klass;
std::map<std::string, ValuePtr> fields;
explicit InstanceValue(std::shared_ptr<ClassValue> klass) : klass(std::move(klass)) {
// Initialize fields with nil
for (const auto& [field_name, type_name] : this->klass->fields) {
fields[field_name] = std::make_shared<NilValue>();
}
}
Type type() const override { return Type::INSTANCE; }
std::string to_string() const override { return "<instance of " + klass->name + ">"; }
ValuePtr clone() const override;
ValuePtr get(const std::string& name) const;
void set(const std::string& name, ValuePtr value);
};
// Helper functions
inline bool is_truthy(const ValuePtr& value) {
if (!value || value->type() == Type::NIL) return false;
if (value->type() == Type::BOOL) {
return std::dynamic_pointer_cast<BoolValue>(value)->value;
}
return true;
}
inline bool values_equal(const ValuePtr& a, const ValuePtr& b) {
if (!a || !b) return false;
if (a->type() != b->type()) return false;
switch (a->type()) {
case Type::NIL:
return true;
case Type::NUMBER:
return std::dynamic_pointer_cast<NumberValue>(a)->value ==
std::dynamic_pointer_cast<NumberValue>(b)->value;
case Type::STRING:
return std::dynamic_pointer_cast<StringValue>(a)->value ==
std::dynamic_pointer_cast<StringValue>(b)->value;
case Type::BOOL:
return std::dynamic_pointer_cast<BoolValue>(a)->value ==
std::dynamic_pointer_cast<BoolValue>(b)->value;
default:
return false;
}
}
} // namespace camellya
#endif // CAMELLYA_VALUE_H