init
This commit is contained in:
151
interpreter.h
Normal file
151
interpreter.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef CAMELLYA_INTERPRETER_H
|
||||
#define CAMELLYA_INTERPRETER_H
|
||||
|
||||
#include "ast.h"
|
||||
#include "value.h"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace camellya {
|
||||
|
||||
class RuntimeError : public std::runtime_error {
|
||||
public:
|
||||
explicit RuntimeError(const std::string& message) : std::runtime_error(message) {}
|
||||
};
|
||||
|
||||
class ReturnException : public std::exception {
|
||||
public:
|
||||
ValuePtr value;
|
||||
explicit ReturnException(ValuePtr value) : value(std::move(value)) {}
|
||||
};
|
||||
|
||||
class Environment {
|
||||
public:
|
||||
std::shared_ptr<Environment> parent;
|
||||
std::map<std::string, ValuePtr> values;
|
||||
|
||||
Environment() : parent(nullptr) {}
|
||||
explicit Environment(std::shared_ptr<Environment> parent) : parent(std::move(parent)) {}
|
||||
|
||||
void define(const std::string& name, ValuePtr value) {
|
||||
values[name] = std::move(value);
|
||||
}
|
||||
|
||||
ValuePtr get(const std::string& name) const {
|
||||
auto it = values.find(name);
|
||||
if (it != values.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
if (parent && parent->has(name)) {
|
||||
return parent->get(name);
|
||||
}
|
||||
|
||||
// Fallback: resolve as field on 'this' instance if present
|
||||
const Environment* env = this;
|
||||
while (env) {
|
||||
auto this_it = env->values.find("this");
|
||||
if (this_it != env->values.end() &&
|
||||
this_it->second && this_it->second->type() == Type::INSTANCE) {
|
||||
auto instance = std::dynamic_pointer_cast<InstanceValue>(this_it->second);
|
||||
auto field_it = instance->fields.find(name);
|
||||
if (field_it != instance->fields.end()) {
|
||||
return field_it->second;
|
||||
}
|
||||
break;
|
||||
}
|
||||
env = env->parent.get();
|
||||
}
|
||||
|
||||
throw RuntimeError("Undefined variable '" + name + "'.");
|
||||
}
|
||||
|
||||
void set(const std::string& name, ValuePtr value) {
|
||||
auto it = values.find(name);
|
||||
if (it != values.end()) {
|
||||
it->second = std::move(value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent && parent->has(name)) {
|
||||
parent->set(name, std::move(value));
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: assign to field on 'this' instance if present
|
||||
Environment* env = this;
|
||||
while (env) {
|
||||
auto this_it = env->values.find("this");
|
||||
if (this_it != env->values.end() &&
|
||||
this_it->second && this_it->second->type() == Type::INSTANCE) {
|
||||
auto instance = std::dynamic_pointer_cast<InstanceValue>(this_it->second);
|
||||
auto field_it = instance->fields.find(name);
|
||||
if (field_it != instance->fields.end()) {
|
||||
field_it->second = std::move(value);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
env = env->parent.get();
|
||||
}
|
||||
|
||||
throw RuntimeError("Undefined variable '" + name + "'.");
|
||||
}
|
||||
|
||||
bool has(const std::string& name) const {
|
||||
if (values.find(name) != values.end()) {
|
||||
return true;
|
||||
}
|
||||
if (parent) {
|
||||
return parent->has(name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class Interpreter {
|
||||
public:
|
||||
Interpreter();
|
||||
|
||||
void execute(const Program& program);
|
||||
ValuePtr evaluate(const Expr& expr);
|
||||
void execute_statement(const Stmt& stmt);
|
||||
|
||||
std::shared_ptr<Environment> environment;
|
||||
std::shared_ptr<Environment> global_environment;
|
||||
|
||||
private:
|
||||
void register_native_functions();
|
||||
|
||||
ValuePtr eval_binary(const BinaryExpr& expr);
|
||||
ValuePtr eval_unary(const UnaryExpr& expr);
|
||||
ValuePtr eval_literal(const LiteralExpr& expr);
|
||||
ValuePtr eval_variable(const VariableExpr& expr);
|
||||
ValuePtr eval_assign(const AssignExpr& expr);
|
||||
ValuePtr eval_call(const CallExpr& expr);
|
||||
ValuePtr eval_get(const GetExpr& expr);
|
||||
ValuePtr eval_set(const SetExpr& expr);
|
||||
ValuePtr eval_index(const IndexExpr& expr);
|
||||
ValuePtr eval_index_set(const IndexSetExpr& expr);
|
||||
ValuePtr eval_list(const ListExpr& expr);
|
||||
ValuePtr eval_map(const MapExpr& expr);
|
||||
|
||||
void exec_expr_stmt(const ExprStmt& stmt);
|
||||
void exec_var_decl(const VarDecl& stmt);
|
||||
void exec_block(const BlockStmt& stmt);
|
||||
void exec_if(const IfStmt& stmt);
|
||||
void exec_while(const WhileStmt& stmt);
|
||||
void exec_for(const ForStmt& stmt);
|
||||
void exec_return(const ReturnStmt& stmt);
|
||||
void exec_function_decl(const FunctionDecl& stmt);
|
||||
void exec_class_decl(const ClassDecl& stmt);
|
||||
|
||||
ValuePtr call_function(const FunctionValue& func, const std::vector<ValuePtr>& arguments);
|
||||
|
||||
ValuePtr create_default_value(const std::string& type_name);
|
||||
};
|
||||
|
||||
} // namespace camellya
|
||||
|
||||
#endif // CAMELLYA_INTERPRETER_H
|
||||
Reference in New Issue
Block a user