| | |
| | | return mgr.callFunction(functionName_, argValues); |
| | | } |
| | | |
| | | // User-defined function |
| | | SymbolContainer *sc = Symbols::SymbolContainer::instance(); |
| | | const std::string currentNs = sc->currentScopeName(); |
| | | const std::string fnSymNs = currentNs + ".functions"; |
| | | auto sym = sc->get(fnSymNs, functionName_); |
| | | if (!sym || sym->getKind() != Kind::Function) { |
| | | throw std::runtime_error("Function not found: " + functionName_); |
| | | } |
| | | auto funcSym = std::static_pointer_cast<FunctionSymbol>(sym); |
| | | const auto ¶ms = funcSym->parameters(); |
| | | if (params.size() != argValues.size()) { |
| | | throw std::runtime_error( |
| | | "Function '" + functionName_ + "' expects " + std::to_string(params.size()) + |
| | | " args, got " + std::to_string(argValues.size())); |
| | | } |
| | | |
| | | // Enter function scope and bind parameters |
| | | const std::string fnOpNs = currentNs + "." + functionName_; |
| | | sc->enter(fnOpNs); |
| | | for (size_t i = 0; i < params.size(); ++i) { |
| | | const auto &p = params[i]; |
| | | const Value &v = argValues[i]; |
| | | auto varSym = SymbolFactory::createVariable(p.name, v, fnOpNs); |
| | | sc->add(varSym); |
| | | } |
| | | |
| | | // Execute function body operations and capture return |
| | | Symbols::Value returnValue; |
| | | auto ops = Operations::Container::instance()->getAll(fnOpNs); |
| | | for (const auto &op : ops) { |
| | | try { |
| | | interpreter.runOperation(*op); |
| | | } catch (const ReturnException &ret) { |
| | | returnValue = ret.value(); |
| | | break; |
| | | } |
| | | } |
| | | sc->enterPreviousScope(); |
| | | return returnValue; |
| | | // User-defined function: lookup through scope hierarchy |
| | | SymbolContainer *sc = SymbolContainer::instance(); |
| | | std::string lookupNs = sc->currentScopeName(); |
| | | std::shared_ptr<FunctionSymbol> funcSym; |
| | | // Search for function symbol in current and parent scopes |
| | | while (true) { |
| | | std::string fnSymNs = lookupNs + ".functions"; |
| | | auto sym = sc->get(fnSymNs, functionName_); |
| | | if (sym && sym->getKind() == Kind::Function) { |
| | | funcSym = std::static_pointer_cast<FunctionSymbol>(sym); |
| | | break; |
| | | } |
| | | auto pos = lookupNs.find_last_of('.'); |
| | | if (pos == std::string::npos) { |
| | | break; |
| | | } |
| | | lookupNs = lookupNs.substr(0, pos); |
| | | } |
| | | if (!funcSym) { |
| | | throw std::runtime_error("Function not found: " + functionName_); |
| | | } |
| | | const auto ¶ms = funcSym->parameters(); |
| | | if (params.size() != argValues.size()) { |
| | | throw std::runtime_error( |
| | | "Function '" + functionName_ + "' expects " + std::to_string(params.size()) + |
| | | " args, got " + std::to_string(argValues.size())); |
| | | } |
| | | // Enter function scope and bind parameters |
| | | const std::string fnOpNs = funcSym->context() + "." + functionName_; |
| | | sc->enter(fnOpNs); |
| | | for (size_t i = 0; i < params.size(); ++i) { |
| | | const auto &p = params[i]; |
| | | const Value &v = argValues[i]; |
| | | auto varSym = SymbolFactory::createVariable(p.name, v, fnOpNs); |
| | | sc->add(varSym); |
| | | } |
| | | // Execute function body operations and capture return |
| | | Symbols::Value returnValue; |
| | | auto ops = Operations::Container::instance()->getAll(fnOpNs); |
| | | for (const auto &op : ops) { |
| | | try { |
| | | interpreter.runOperation(*op); |
| | | } catch (const ReturnException &ret) { |
| | | returnValue = ret.value(); |
| | | break; |
| | | } |
| | | } |
| | | sc->enterPreviousScope(); |
| | | return returnValue; |
| | | } |
| | | |
| | | std::string toString() const override { |