#include "Evaluator/Core/ExprResult.hpp" #include #include #include #include namespace Fig { ExprResult Evaluator::evalVarExpr(Ast::VarExpr var, ContextPtr ctx) { const FString &name = var->name; // 调试信息 // std::cerr << "=== DEBUG evalVarExpr ===" << std::endl; // std::cerr << "Looking for: " << name.toBasicString() << std::endl; // std::cerr << "Context: " << ctx->getScopeName().toBasicString() << std::endl; // // 打印上下文 // ContextPtr current = ctx; // int depth = 0; // while (current) // { // std::cerr << " [" << depth << "] " << current->getScopeName().toBasicString(); // if (current->containsInThisScope(name)) // { // std::cerr << " -> FOUND HERE!" << std::endl; // auto slot = current->get(name); // std::cerr << " Type: " << slot->declaredType.toString().toBasicString() << std::endl; // std::cerr << " Value: " << (slot->value ? slot->value->toString().toBasicString() : "null") // << std::endl; // } // else // { // std::cerr << " -> not found" << std::endl; // } // current = current->parent; // depth++; // } // end if (!ctx->contains(name)) { throw EvaluatorError(u8"UndeclaredIdentifierError", name, var); } return LvObject(ctx->get(name), ctx); } ExprResult Evaluator::evalMemberExpr(Ast::MemberExpr me, ContextPtr ctx) { // LvObject base = evalLv(me->base, ctx); RvObject baseVal = check_unwrap(eval(me->base, ctx)); const FString &member = me->member; if (baseVal->getTypeInfo() == ValueType::Module) { // std::cerr << "=== DEBUG evalMemberExpr (Module) ===" << std::endl; // std::cerr << "Module object: " << baseVal->toString().toBasicString() << std::endl; const Module &mod = baseVal->as(); // std::cerr << "Module context: " << mod.ctx->getScopeName().toBasicString() << std::endl; // std::cerr << "Looking for member: " << member.toBasicString() << std::endl; // if (mod.ctx->contains(member)) // { // std::cerr << "Found in module context!" << std::endl; // if (mod.ctx->isVariablePublic(member)) { std::cerr << "And it's public!" << std::endl; } // else // { // std::cerr << "But it's NOT public!" << std::endl; // } // } // else // { // std::cerr << "NOT found in module context!" << std::endl; // } if (mod.ctx->contains(member) && mod.ctx->isVariablePublic(member)) { return LvObject(mod.ctx->get(member), ctx); } else { throw EvaluatorError(u8"VariableNotFoundError", std::format("`{}` has not variable '{}', check if it is public", baseVal->toString().toBasicString(), member.toBasicString()), me->base); } } if (baseVal->hasMemberFunction(member)) { return LvObject(std::make_shared( member, std::make_shared(Function( member, [baseVal, member](ObjectPtr self, std::vector args) -> ObjectPtr { if (self) { return baseVal->getMemberFunction(member)(self, args); } return baseVal->getMemberFunction(member)(baseVal, args); }, baseVal->getMemberFunctionParaCount(member))), ValueType::Function, AccessModifier::PublicConst), ctx); // fake l-value } if (ctx->hasMethodImplemented(baseVal->getTypeInfo(), member)) { // builtin type implementation! // e.g. impl xxx for Int auto &fn = ctx->getImplementedMethod(baseVal->getTypeInfo(), member); Function boundFn(member, fn.paras, fn.retType, fn.body, ctx // current context ); return LvObject( std::make_shared( member, std::make_shared(boundFn), ValueType::Function, AccessModifier::PublicConst), ctx); } if (baseVal->getTypeInfo() != ValueType::StructInstance) // and not member function found { throw EvaluatorError( u8"NoAttributeError", std::format("`{}` has not attribute '{}'", baseVal->toString().toBasicString(), member.toBasicString()), me->base); } const StructInstance &si = baseVal->as(); if (ctx->hasMethodImplemented(si.parentType, member)) { auto &fn = ctx->getImplementedMethod(si.parentType, member); Function boundFn(member, fn.paras, fn.retType, fn.body, si.localContext // create a new function and set closure context // to struct instance context ); return LvObject( std::make_shared( member, std::make_shared(boundFn), ValueType::Function, AccessModifier::PublicConst), ctx); } else if (si.localContext->containsInThisScope(member) && si.localContext->isVariablePublic(member)) { return LvObject(si.localContext->get(member), ctx); } else if (ctx->hasDefaultImplementedMethod(si.parentType, member)) { const auto &ifm = ctx->getDefaultImplementedMethod(si.parentType, member); Function fn(member, ifm.paras, actualType(check_unwrap(eval(ifm.returnType, ctx))), ifm.defaultBody, ctx); return LvObject(std::make_shared( member, std::make_shared(fn), ValueType::Function, AccessModifier::PublicConst), ctx); } else { throw EvaluatorError(u8"NoAttributeError", std::format("`{}` has not attribute '{}' and no interfaces have been implemented it", baseVal->toString().toBasicString(), member.toBasicString()), me->base); } } ExprResult Evaluator::evalIndexExpr(Ast::IndexExpr ie, ContextPtr ctx) { RvObject base = check_unwrap(eval(ie->base, ctx)); RvObject index = check_unwrap(eval(ie->index, ctx)); const TypeInfo &type = base.get()->getTypeInfo(); if (type == ValueType::List) { if (index->getTypeInfo() != ValueType::Int) { throw EvaluatorError( u8"TypeError", std::format("Type `List` indices must be `Int`, got '{}'", prettyType(index).toBasicString()), ie->index); } List &list = base.get()->as(); ValueType::IntClass indexVal = index->as(); if (indexVal >= list.size()) { throw EvaluatorError( u8"IndexOutOfRangeError", std::format("Index {} out of list `{}` range", indexVal, base->toString().toBasicString()), ie->index); } return LvObject(base, indexVal, LvObject::Kind::ListElement, ctx); } else if (type == ValueType::Map) { return LvObject(base, index, LvObject::Kind::MapElement, ctx); } else if (type == ValueType::String) { if (index->getTypeInfo() != ValueType::Int) { throw EvaluatorError( u8"TypeError", std::format("Type `String` indices must be `Int`, got '{}'", prettyType(index).toBasicString()), ie->index); } FString &string = base->as(); ValueType::IntClass indexVal = index->as(); if (indexVal >= string.length()) { throw EvaluatorError( u8"IndexOutOfRangeError", std::format("Index {} out of string `{}` range", indexVal, base->toString().toBasicString()), ie->index); } return LvObject(base, indexVal, LvObject::Kind::StringElement, ctx); } else { throw EvaluatorError( u8"NoSubscriptableError", std::format("`{}` object is not subscriptable", base->getTypeInfo().toString().toBasicString()), ie->base); } } ExprResult Evaluator::evalLv(Ast::Expression exp, ContextPtr ctx) { using Ast::Operator; using Ast::AstType; switch (exp->getType()) { case AstType::VarExpr: { Ast::VarExpr var = std::static_pointer_cast(exp); return evalVarExpr(var, ctx); } case AstType::MemberExpr: { Ast::MemberExpr me = std::static_pointer_cast(exp); return evalMemberExpr(me, ctx); } case AstType::IndexExpr: { Ast::IndexExpr ie = std::static_pointer_cast(exp); return evalIndexExpr(ie, ctx); } default: { throw EvaluatorError( u8"TypeError", std::format("Expression '{}' doesn't refer to a lvalue", exp->typeName().toBasicString()), exp); } } } }; // namespace Fig