public function compile($env) { $rules = array(); $match = false; $isOneFound = false; $candidates = array(); $defaultUsed = false; $conditionResult = array(); $args = array(); foreach ($this->arguments as $a) { $args[] = array('name' => $a['name'], 'value' => $a['value']->compile($env)); } foreach ($env->frames as $frame) { $mixins = $frame->find($this->selector); if (!$mixins) { continue; } $isOneFound = true; $defNone = 0; $defTrue = 1; $defFalse = 2; // To make `default()` function independent of definition order we have two "subpasses" here. // At first we evaluate each guard *twice* (with `default() == true` and `default() == false`), // and build candidate list with corresponding flags. Then, when we know all possible matches, // we make a final decision. $mixins_len = count($mixins); for ($m = 0; $m < $mixins_len; $m++) { $mixin = $mixins[$m]; if ($this->IsRecursive($env, $mixin)) { continue; } if ($mixin->matchArgs($args, $env)) { $candidate = array('mixin' => $mixin, 'group' => $defNone); if ($mixin instanceof Less_Tree_Ruleset) { for ($f = 0; $f < 2; $f++) { Less_Tree_DefaultFunc::value($f); $conditionResult[$f] = $mixin->matchCondition($args, $env); } if ($conditionResult[0] || $conditionResult[1]) { if ($conditionResult[0] != $conditionResult[1]) { $candidate['group'] = $conditionResult[1] ? $defTrue : $defFalse; } $candidates[] = $candidate; } } else { $candidates[] = $candidate; } $match = true; } } Less_Tree_DefaultFunc::reset(); $count = array(0, 0, 0); for ($m = 0; $m < count($candidates); $m++) { $count[$candidates[$m]['group']]++; } if ($count[$defNone] > 0) { $defaultResult = $defFalse; } else { $defaultResult = $defTrue; if ($count[$defTrue] + $count[$defFalse] > 1) { throw new Exception('Ambiguous use of `default()` found when matching for `' . $this->format($args) + '`'); } } $candidates_length = count($candidates); $length_1 = $candidates_length == 1; for ($m = 0; $m < $candidates_length; $m++) { $candidate = $candidates[$m]['group']; if ($candidate === $defNone || $candidate === $defaultResult) { try { $mixin = $candidates[$m]['mixin']; if (!$mixin instanceof Less_Tree_Mixin_Definition) { $mixin = new Less_Tree_Mixin_Definition('', array(), $mixin->rules, null, false); $mixin->originalRuleset = $mixins[$m]->originalRuleset; } $rules = array_merge($rules, $mixin->evalCall($env, $args, $this->important)->rules); } catch (Exception $e) { //throw new Less_Exception_Compiler($e->getMessage(), $e->index, null, $this->currentFileInfo['filename']); throw new Less_Exception_Compiler($e->getMessage(), null, null, $this->currentFileInfo); } } } if ($match) { if (!$this->currentFileInfo || !isset($this->currentFileInfo['reference']) || !$this->currentFileInfo['reference']) { Less_Tree::ReferencedArray($rules); } return $rules; } } if ($isOneFound) { throw new Less_Exception_Compiler('No matching definition was found for `' . $this->Format($args) . '`', null, $this->index, $this->currentFileInfo); } else { throw new Less_Exception_Compiler(trim($this->selector->toCSS()) . " is undefined in " . $this->currentFileInfo['filename'], null, $this->index); } }
/** * Compile the selectors and create a new ruleset object for the compile() method * */ private function PrepareRuleset($env) { $hasOnePassingSelector = false; $selectors = array(); if ($this->selectors) { Less_Tree_DefaultFunc::error("it is currently only allowed in parametric mixin guards,"); foreach ($this->selectors as $s) { $selector = $s->compile($env); $selectors[] = $selector; if ($selector->evaldCondition) { $hasOnePassingSelector = true; } } Less_Tree_DefaultFunc::reset(); } else { $hasOnePassingSelector = true; } if ($this->rules && $hasOnePassingSelector) { $rules = $this->rules; } else { $rules = array(); } $ruleset = new Less_Tree_Ruleset($selectors, $rules, $this->strictImports); $ruleset->originalRuleset = $this->ruleset_id; $ruleset->root = $this->root; $ruleset->firstRoot = $this->firstRoot; $ruleset->allowImports = $this->allowImports; // push the current ruleset to the frames stack $env->unshiftFrame($ruleset); // Evaluate imports if ($ruleset->root || $ruleset->allowImports || !$ruleset->strictImports) { $ruleset->evalImports($env); } return $ruleset; }