Exemplo n.º 1
0
Variant EvalCreateFunction::InvokeImpl(VariableEnvironment &env,
                                       CArrRef params) {
  int size = params.size();
  if (size != 2) return invalid_function_call("create_function");
  Variant var = params.rvalAt(0);
  Variant body = params.rvalAt(1);

  vector<StaticStatementPtr> statics;
  Block::VariableIndices variableIndices;
  ostringstream fnStream;
  string id(RequestEvalState::unique());
  fnStream << "<?php function lambda_" << id << "(" << var.toString().data() <<
    ") {" << body.toString().data() << "}\n";
  StatementPtr bodyAst = Parser::ParseString(fnStream.str().c_str(), statics,
                                             variableIndices);
  if (!bodyAst) return false;
  ostringstream nameStream;
  nameStream << "$lambda_" << id;
  StatementListStatement *sl = bodyAst->cast<StatementListStatement>();
  FunctionStatement *f = sl->stmts()[0]->cast<FunctionStatement>();
  ASSERT(f);
  f->changeName(nameStream.str());
  SmartPtr<CodeContainer> cc(new StringCodeContainer(bodyAst));
  RequestEvalState::addCodeContainer(cc);
  f->eval(env);
  return f->name();
}
Exemplo n.º 2
0
void
SemanticAnalysis::analyzeShadowedFunctions(FunctionSymbol *sym)
{
    // We do not yet support overloading, so two functions with the same name
    // and a body are illegal. We consider natives to be implemented.
    FunctionStatement *impl = nullptr;

    // We support non-native implementations of a forwarded function.
    FunctionStatement *forward = nullptr;

    for (size_t i = 0; i < sym->shadows()->length(); i++) {
        FunctionStatement *stmt = sym->shadows()->at(i);
        switch (stmt->token()) {
        case TOK_FORWARD:
            if (forward) {
                cc_.report(stmt->loc(), rmsg::function_redeclared)
                        << stmt->name()
                        << (cc_.note(forward->loc(), rmsg::previous_location));
                continue;
            }
            forward = stmt;
            break;
        case TOK_NATIVE:
        case TOK_FUNCTION:
            if (impl) {
                cc_.report(stmt->loc(), rmsg::function_redeclared)
                        << stmt->name()
                        << (cc_.note(impl->loc(), rmsg::previous_location));
                continue;
            }
            impl = stmt;
            break;
        default:
            assert(false);
            break;
        }
    }

    // If we have both an impl and a forward, make sure they match.
    if (impl && forward)
        checkForwardedFunction(forward, impl);
}