protected function doLevelFunction(&$result) { if ($this->mCur->type == AFPToken::TID && isset(self::$mFunctions[$this->mCur->value])) { wfProfileIn(__METHOD__); $func = self::$mFunctions[$this->mCur->value]; $this->move(); if ($this->mCur->type != AFPToken::TBrace || $this->mCur->value != '(') { throw new AFPUserVisibleException('expectednotfound', $this->mCur->pos, array('(', $this->mCur->type, $this->mCur->value)); } if ($this->mShortCircuit) { $this->skipOverBraces(); $this->move(); wfProfileOut(__METHOD__); return; // The result doesn't matter. } wfProfileIn(__METHOD__ . '-loadargs'); $args = array(); do { $r = new AFPData(); $this->doLevelSemicolon($r); $args[] = $r; } while ($this->mCur->type == AFPToken::TComma); if ($this->mCur->type != AFPToken::TBrace || $this->mCur->value != ')') { throw new AFPUserVisibleException('expectednotfound', $this->mCur->pos, array(')', $this->mCur->type, $this->mCur->value)); } $this->move(); wfProfileOut(__METHOD__ . '-loadargs'); wfProfileIn(__METHOD__ . "-{$func}"); $funcHash = md5($func . serialize($args)); if (isset(self::$funcCache[$funcHash]) && !in_array($func, self::$ActiveFunctions)) { $result = self::$funcCache[$funcHash]; } else { AbuseFilter::triggerLimiter(); $result = self::$funcCache[$funcHash] = $this->{$func}($args); } if (count(self::$funcCache) > 1000) { self::$funcCache = array(); } wfProfileOut(__METHOD__ . "-{$func}"); wfProfileOut(__METHOD__); } else { $this->doLevelAtom($result); } }