#ifndef CAMELLYA_INTERPRETER_H #define CAMELLYA_INTERPRETER_H #include "ast.h" #include "value.h" #include #include #include 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 parent; std::map values; Environment() : parent(nullptr) {} explicit Environment(std::shared_ptr 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(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(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; std::shared_ptr 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& arguments); ValuePtr create_default_value(const std::string& type_name); }; } // namespace camellya #endif // CAMELLYA_INTERPRETER_H