/** * Interpret a builtin call. Yes, this can be slow because each time we invoke * this we must query the mapping in the builtins table to see if it can be * executed (builtin implementation). HOWEVER, this also allows us to swap out * builtin implementations on the fly. * * @return The interpreted element. */ Element Builtin_::InterpretCall( Environment& environment , Element const& builtin_element , std::vector<Element> const& parms ) { std::shared_ptr<Builtin_> builtin(std::dynamic_pointer_cast<Builtin_>(builtin_element.ElementHandle())); BuiltinsTable& table = *(builtin->table); BuiltinImplementation* impl = table.Get(builtin->Name()); Element result; if (0 != builtin && 0 != impl) { std::vector<Element> output_parameters; GlobalEnvironment globals(environment.Globals()); Environment output_environment = Environment::Create(globals); bool success = Funcall_::CreateEnvironment( environment , parms , output_parameters); if (success && (0 != impl)) { result = impl->Interpret( output_environment , output_parameters , builtin->AdditionalParameter() ); } } return result; }
/** * Interpret a function call. * * @param environment The environment to make the interpretation of a call * over. This could be another function environment. * We use it to parse arguments in and to obtain the * global environment. * @param function_element The function we want to evaluate the call of. * @param parms The container of parameters into the call. * * * @return The interpreted element. */ Element Function_::InterpretCall( Environment& environment , Element const& function_element , std::vector<Element> const& parms ) { GlobalEnvironment globals(environment.Globals()); bool hasFunction = false; Function function = CastToFunction(function_element, hasFunction); Element result; if (hasFunction) { bool tailRecursion = true; std::vector<Element> parameters(parms); while(tailRecursion) { tailRecursion = false; Environment function_environment = Environment::Create(globals); globals.PushCallStack(function, function_environment); bool success = Funcall_::CreateEnvironment( function.Arguments() , parameters , function_environment ); if (success) { Element body(function.Body()); result = body.Interpret(function_environment); // Making a recursive call using tail recursion. if (Types::TAILRECURSE == result.Type()) { TailRecurse tailRecurse = CastToTailRecurse(result, success); parameters = tailRecurse.Parameters(); // Go again! :D tailRecursion = true; } } globals.PopCallStack(); } } return result; }