PluginProbe
MaxButtons – Create buttons / 6.28
MaxButtons – Create buttons v6.28
6.23 6.24 6.25 6.26 6.26.1 6.27 6.28 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.0 7.1 7.1.1 7.1.2 7.1.3 7.10 7.11 7.13 7.13.1 7.13.2 7.13.3 All 100 releases
← All changes | assets/libraries/scssphp/src/Compiler.php +495 -918 7.13.26.28 View file →
@@ -1,9 +1,9 @@
1 1 <?php
2 2 /**
3 3 * SCSSPHP
4 4 *
5 - * @copyright 2012-2018 Leaf Corcoran
5 + * @copyright 2012-2015 Leaf Corcoran
6 6 *
7 7 * @license http://opensource.org/licenses/MIT MIT
8 8 *
9 9 * @link http://leafo.github.io/scssphp
@@ -14,12 +14,10 @@
14 14 use Leafo\ScssPhp\Base\Range;
15 15 use Leafo\ScssPhp\Block;
16 16 use Leafo\ScssPhp\Colors;
17 17 use Leafo\ScssPhp\Compiler\Environment;
18 -use Leafo\ScssPhp\Exception\CompilerException;
19 18 use Leafo\ScssPhp\Formatter\OutputBlock;
20 19 use Leafo\ScssPhp\Node;
21 -use Leafo\ScssPhp\SourceMap\SourceMapGenerator;
22 20 use Leafo\ScssPhp\Type;
23 21 use Leafo\ScssPhp\Parser;
24 22 use Leafo\ScssPhp\Util;
25 23
@@ -64,16 +62,12 @@
64 62 const WITH_MEDIA = 2;
65 63 const WITH_SUPPORTS = 4;
66 64 const WITH_ALL = 7;
67 65
68 - const SOURCE_MAP_NONE = 0;
69 - const SOURCE_MAP_INLINE = 1;
70 - const SOURCE_MAP_FILE = 2;
71 -
72 66 /**
73 67 * @var array
74 68 */
75 - static protected $operatorNames = [
69 + static protected $operatorNames = array(
76 70 '+' => 'add',
77 71 '-' => 'sub',
78 72 '*' => 'mul',
79 73 '/' => 'div',
@@ -86,89 +80,65 @@
86 80
87 81 '<=' => 'lte',
88 82 '>=' => 'gte',
89 83 '<=>' => 'cmp',
90 - ];
84 + );
91 85
92 86 /**
93 87 * @var array
94 88 */
95 - static protected $namespaces = [
89 + static protected $namespaces = array(
96 90 'special' => '%',
97 91 'mixin' => '@',
98 92 'function' => '^',
99 - ];
93 + );
100 94
101 - static public $true = [Type::T_KEYWORD, 'true'];
102 - static public $false = [Type::T_KEYWORD, 'false'];
103 - static public $null = [Type::T_NULL];
104 - static public $nullString = [Type::T_STRING, '', []];
105 - static public $defaultValue = [Type::T_KEYWORD, ''];
106 - static public $selfSelector = [Type::T_SELF];
107 - static public $emptyList = [Type::T_LIST, '', []];
108 - static public $emptyMap = [Type::T_MAP, [], []];
109 - static public $emptyString = [Type::T_STRING, '"', []];
110 - static public $with = [Type::T_KEYWORD, 'with'];
111 - static public $without = [Type::T_KEYWORD, 'without'];
95 + static public $true = array(Type::T_KEYWORD, 'true');
96 + static public $false = array(Type::T_KEYWORD, 'false');
97 + static public $null = array(Type::T_NULL);
98 + static public $defaultValue = array(Type::T_KEYWORD, '');
99 + static public $selfSelector = array(Type::T_SELF);
100 + static public $emptyList = array(Type::T_LIST, '', array());
101 + static public $emptyMap = array(Type::T_MAP, array(), array());
102 + static public $emptyString = array(Type::T_STRING, '"', array());
103 + static public $with = array(Type::T_KEYWORD, 'with');
104 + static public $without = array(Type::T_KEYWORD, 'without');
112 105
113 - protected $importPaths = [''];
114 - protected $importCache = [];
115 - protected $importedFiles = [];
116 - protected $userFunctions = [];
117 - protected $registeredVars = [];
118 - protected $registeredFeatures = [
106 + protected $importPaths = array('');
107 + protected $importCache = array();
108 + protected $userFunctions = array();
109 + protected $registeredVars = array();
110 + protected $registeredFeatures = array(
119 111 'extend-selector-pseudoclass' => false,
120 112 'at-error' => true,
121 113 'units-level-3' => false,
122 114 'global-variable-shadowing' => false,
123 - ];
115 + );
124 116
125 - protected $encoding = null;
126 117 protected $lineNumberStyle = null;
127 118
128 - protected $sourceMap = self::SOURCE_MAP_NONE;
129 - protected $sourceMapOptions = [];
130 -
131 - /**
132 - * @var string|\Leafo\ScssPhp\Formatter
133 - */
134 119 protected $formatter = 'Leafo\ScssPhp\Formatter\Nested';
135 120
136 121 protected $rootEnv;
137 122 protected $rootBlock;
138 123
139 - /**
140 - * @var \Leafo\ScssPhp\Compiler\Environment
141 - */
142 - protected $env;
143 - protected $scope;
144 - protected $storeEnv;
145 - protected $charsetSeen;
146 - protected $sourceNames;
147 -
148 124 private $indentLevel;
149 125 private $commentsSeen;
150 126 private $extends;
151 127 private $extendsMap;
152 128 private $parsedFiles;
129 + private $env;
130 + private $scope;
153 131 private $parser;
132 + private $sourcePos;
133 + private $sourceParsers;
154 134 private $sourceIndex;
155 - private $sourceLine;
156 - private $sourceColumn;
135 + private $storeEnv;
136 + private $charsetSeen;
157 137 private $stderr;
158 138 private $shouldEvaluate;
159 - private $ignoreErrors;
160 139
161 140 /**
162 - * Constructor
163 - */
164 - public function __construct()
165 - {
166 - $this->parsedFiles = [];
167 - $this->sourceNames = [];
168 - }
169 -
170 - /**
171 141 * Compile scss
172 142 *
173 143 * @api
174 144 *
@@ -178,65 +148,37 @@
178 148 * @return string
179 149 */
180 150 public function compile($code, $path = null)
181 151 {
182 - $this->indentLevel = -1;
183 - $this->commentsSeen = [];
184 - $this->extends = [];
185 - $this->extendsMap = [];
186 - $this->sourceIndex = null;
187 - $this->sourceLine = null;
188 - $this->sourceColumn = null;
189 - $this->env = null;
190 - $this->scope = null;
191 - $this->storeEnv = null;
192 - $this->charsetSeen = null;
193 - $this->shouldEvaluate = null;
194 - $this->stderr = fopen('php://stderr', 'w');
152 + $locale = setlocale(LC_NUMERIC, 0);
153 + setlocale(LC_NUMERIC, 'C');
195 154
155 + $this->indentLevel = -1;
156 + $this->commentsSeen = array();
157 + $this->extends = array();
158 + $this->extendsMap = array();
159 + $this->parsedFiles = array();
160 + $this->sourceParsers = array();
161 + $this->sourceIndex = null;
162 + $this->env = null;
163 + $this->scope = null;
164 + $this->storeEnv = null;
165 + $this->stderr = fopen('php://stderr', 'w');
166 +
196 167 $this->parser = $this->parserFactory($path);
197 168 $tree = $this->parser->parse($code);
198 169
199 - $this->parser = null;
200 -
201 170 $this->formatter = new $this->formatter();
202 - $this->rootBlock = null;
203 - $this->rootEnv = $this->pushEnv($tree);
204 171
172 + $this->rootEnv = $this->pushEnv($tree);
205 173 $this->injectVariables($this->registeredVars);
206 174 $this->compileRoot($tree);
207 175 $this->popEnv();
208 176
209 - $sourceMapGenerator = null;
177 + $out = $this->formatter->format($this->scope);
210 178
211 - if ($this->sourceMap) {
212 - if (is_object($this->sourceMap) && $this->sourceMap instanceof SourceMapGenerator) {
213 - $sourceMapGenerator = $this->sourceMap;
214 - $this->sourceMap = self::SOURCE_MAP_FILE;
215 - } elseif ($this->sourceMap !== self::SOURCE_MAP_NONE) {
216 - $sourceMapGenerator = new SourceMapGenerator($this->sourceMapOptions);
217 - }
218 - }
179 + setlocale(LC_NUMERIC, $locale);
219 180
220 - $out = $this->formatter->format($this->scope, $sourceMapGenerator);
221 -
222 - if (! empty($out) && $this->sourceMap && $this->sourceMap !== self::SOURCE_MAP_NONE) {
223 - $sourceMap = $sourceMapGenerator->generateJson();
224 - $sourceMapUrl = null;
225 -
226 - switch ($this->sourceMap) {
227 - case self::SOURCE_MAP_INLINE:
228 - $sourceMapUrl = sprintf('data:application/json,%s', Util::encodeURIComponent($sourceMap));
229 - break;
230 -
231 - case self::SOURCE_MAP_FILE:
232 - $sourceMapUrl = $sourceMapGenerator->saveMap($sourceMap);
233 - break;
234 - }
235 -
236 - $out .= sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl);
237 - }
238 -
239 181 return $out;
240 182 }
241 183
242 184 /**
@@ -245,14 +187,13 @@
245 187 * @param string $path
246 188 *
247 189 * @return \Leafo\ScssPhp\Parser
248 190 */
249 - protected function parserFactory($path)
191 + private function parserFactory($path)
250 192 {
251 - $parser = new Parser($path, count($this->sourceNames), $this->encoding);
193 + $parser = new Parser($path, count($this->sourceParsers));
252 194
253 - $this->sourceNames[] = $path;
254 -
195 + $this->sourceParsers[] = $parser;
255 196 $this->addParsedFile($path);
256 197
257 198 return $parser;
258 199 }
@@ -278,13 +219,12 @@
278 219
279 220 /**
280 221 * Push extends
281 222 *
282 - * @param array $target
283 - * @param array $origin
284 - * @param \stdClass $block
223 + * @param array $target
224 + * @param array $origin
285 225 */
286 - protected function pushExtends($target, $origin, $block)
226 + protected function pushExtends($target, $origin)
287 227 {
288 228 if ($this->isSelfExtend($target, $origin)) {
289 229 return;
290 230 }
@@ -289,15 +229,15 @@
289 229 return;
290 230 }
291 231
292 232 $i = count($this->extends);
293 - $this->extends[] = [$target, $origin, $block];
233 + $this->extends[] = array($target, $origin);
294 234
295 235 foreach ($target as $part) {
296 236 if (isset($this->extendsMap[$part])) {
297 237 $this->extendsMap[$part][] = $i;
298 238 } else {
299 - $this->extendsMap[$part] = [$i];
239 + $this->extendsMap[$part] = array($i);
300 240 }
301 241 }
302 242 }
303 243
@@ -311,25 +251,15 @@
311 251 */
312 252 protected function makeOutputBlock($type, $selectors = null)
313 253 {
314 254 $out = new OutputBlock;
315 - $out->type = $type;
316 - $out->lines = [];
317 - $out->children = [];
318 - $out->parent = $this->scope;
319 - $out->selectors = $selectors;
320 - $out->depth = $this->env->depth;
255 + $out->type = $type;
256 + $out->lines = array();
257 + $out->children = array();
258 + $out->parent = $this->scope;
259 + $out->selectors = $selectors;
260 + $out->depth = $this->env->depth;
321 261
322 - if ($this->env->block instanceof Block) {
323 - $out->sourceName = $this->env->block->sourceName;
324 - $out->sourceLine = $this->env->block->sourceLine;
325 - $out->sourceColumn = $this->env->block->sourceColumn;
326 - } else {
327 - $out->sourceName = null;
328 - $out->sourceLine = null;
329 - $out->sourceColumn = null;
330 - }
331 -
332 262 return $out;
333 263 }
334 264
335 265 /**
@@ -342,37 +272,11 @@
342 272 $this->rootBlock = $this->scope = $this->makeOutputBlock(Type::T_ROOT);
343 273
344 274 $this->compileChildrenNoReturn($rootBlock->children, $this->scope);
345 275 $this->flattenSelectors($this->scope);
346 - $this->missingSelectors();
347 276 }
348 277
349 278 /**
350 - * Report missing selectors
351 - */
352 - protected function missingSelectors()
353 - {
354 - foreach ($this->extends as $extend) {
355 - if (isset($extend[3])) {
356 - continue;
357 - }
358 -
359 - list($target, $origin, $block) = $extend;
360 -
361 - // ignore if !optional
362 - if ($block[2]) {
363 - continue;
364 - }
365 -
366 - $target = implode(' ', $target);
367 - $origin = $this->collapseSelectors($origin);
368 -
369 - $this->sourceLine = $block[Parser::SOURCE_LINE];
370 - $this->throwError("\"$origin\" failed to @extend \"$target\". The selector \"$target\" was not found.");
371 - }
372 - }
373 -
374 - /**
375 279 * Flatten selectors
376 280 *
377 281 * @param \Leafo\ScssPhp\Formatter\OutputBlock $block
378 282 * @param string $parentKey
@@ -379,9 +283,9 @@
379 283 */
380 284 protected function flattenSelectors(OutputBlock $block, $parentKey = null)
381 285 {
382 286 if ($block->selectors) {
383 - $selectors = [];
287 + $selectors = array();
384 288
385 289 foreach ($block->selectors as $s) {
386 290 $selectors[] = $s;
387 291
@@ -405,9 +309,9 @@
405 309 });
406 310 }
407 311 }
408 312
409 - $block->selectors = [];
313 + $block->selectors = array();
410 314 $placeholderSelector = false;
411 315
412 316 foreach ($selectors as $selector) {
413 317 if ($this->hasSelectorPlaceholder($selector)) {
@@ -445,44 +349,25 @@
445 349 continue;
446 350 }
447 351
448 352 if ($this->matchExtendsSingle($part, $origin)) {
353 + $before = array_slice($selector, 0, $i);
449 354 $after = array_slice($selector, $i + 1);
450 - $before = array_slice($selector, 0, $i);
355 + $s = count($before);
451 356
452 - list($before, $nonBreakableBefore) = $this->extractRelationshipFromFragment($before);
453 -
454 357 foreach ($origin as $new) {
455 358 $k = 0;
456 359
457 360 // remove shared parts
458 361 if ($initial) {
459 - while ($k < $i && isset($new[$k]) && $selector[$k] === $new[$k]) {
362 + while ($k < $s && isset($new[$k]) && $before[$k] === $new[$k]) {
460 363 $k++;
461 364 }
462 365 }
463 366
464 - $replacement = [];
465 - $tempReplacement = $k > 0 ? array_slice($new, $k) : $new;
466 -
467 - for ($l = count($tempReplacement) - 1; $l >= 0; $l--) {
468 - $slice = $tempReplacement[$l];
469 - array_unshift($replacement, $slice);
470 -
471 - if (! $this->isImmediateRelationshipCombinator(end($slice))) {
472 - break;
473 - }
474 - }
475 -
476 - $afterBefore = $l != 0 ? array_slice($tempReplacement, 0, $l) : [];
477 -
478 - // Merge shared direct relationships.
479 - $mergedBefore = $this->mergeDirectRelationships($afterBefore, $nonBreakableBefore);
480 -
481 367 $result = array_merge(
482 368 $before,
483 - $mergedBefore,
484 - $replacement,
369 + $k > 0 ? array_slice($new, $k) : $new,
485 370 $after
486 371 );
487 372
488 373 if ($result === $selector) {
@@ -491,24 +376,16 @@
491 376
492 377 $out[] = $result;
493 378
494 379 // recursively check for more matches
495 - $this->matchExtends($result, $out, count($before) + count($mergedBefore), false);
380 + $this->matchExtends($result, $out, $i, false);
496 381
497 382 // selector sequence merging
498 383 if (! empty($before) && count($new) > 1) {
499 - $sharedParts = $k > 0 ? array_slice($before, 0, $k) : [];
500 - $postSharedParts = $k > 0 ? array_slice($before, $k) : $before;
501 -
502 - list($injectBetweenSharedParts, $nonBreakable2) = $this->extractRelationshipFromFragment($afterBefore);
503 -
504 384 $result2 = array_merge(
505 - $sharedParts,
506 - $injectBetweenSharedParts,
507 - $postSharedParts,
508 - $nonBreakable2,
509 - $nonBreakableBefore,
510 - $replacement,
385 + array_slice($new, 0, -1),
386 + $k > 0 ? array_slice($before, $k) : $before,
387 + array_slice($new, -1),
511 388 $after
512 389 );
513 390
514 391 $out[] = $result2;
@@ -527,10 +404,10 @@
527 404 * @return boolean
528 405 */
529 406 protected function matchExtendsSingle($rawSingle, &$outOrigin)
530 407 {
531 - $counts = [];
532 - $single = [];
408 + $counts = array();
409 + $single = array();
533 410
534 411 foreach ($rawSingle as $part) {
535 412 // matches Number
536 413 if (! is_string($part)) {
@@ -543,15 +420,8 @@
543 420 $single[] = $part;
544 421 }
545 422 }
546 423
547 - $extendingDecoratedTag = false;
548 -
549 - if (count($single) > 1) {
550 - $matches = null;
551 - $extendingDecoratedTag = preg_match('/^[a-z0-9]+$/i', $single[0], $matches) ? $matches[0] : false;
552 - }
553 -
554 424 foreach ($single as $part) {
555 425 if (isset($this->extendsMap[$part])) {
556 426 foreach ($this->extendsMap[$part] as $idx) {
557 427 $counts[$idx] = isset($counts[$idx]) ? $counts[$idx] + 1 : 1;
@@ -558,13 +428,13 @@
558 428 }
559 429 }
560 430 }
561 431
562 - $outOrigin = [];
432 + $outOrigin = array();
563 433 $found = false;
564 434
565 435 foreach ($counts as $idx => $count) {
566 - list($target, $origin, /* $block */) = $this->extends[$idx];
436 + list($target, $origin) = $this->extends[$idx];
567 437
568 438 // check count
569 439 if ($count !== count($target)) {
570 440 continue;
@@ -569,10 +439,8 @@
569 439 if ($count !== count($target)) {
570 440 continue;
571 441 }
572 442
573 - $this->extends[$idx][3] = true;
574 -
575 443 $rem = array_diff($single, $target);
576 444
577 445 foreach ($origin as $j => $new) {
578 446 // prevent infinite loop when target extends itself
@@ -579,23 +447,9 @@
579 447 if ($this->isSelfExtend($single, $origin)) {
580 448 return false;
581 449 }
582 450
583 - $replacement = end($new);
584 -
585 - // Extending a decorated tag with another tag is not possible.
586 - if ($extendingDecoratedTag && $replacement[0] != $extendingDecoratedTag &&
587 - preg_match('/^[a-z0-9]+$/i', $replacement[0])
588 - ) {
589 - unset($origin[$j]);
590 - continue;
591 - }
592 -
593 - $combined = $this->combineSelectorSingle($replacement, $rem);
594 -
595 - if (count(array_diff($combined, $origin[$j][count($origin[$j]) - 1]))) {
596 - $origin[$j][count($origin[$j]) - 1] = $combined;
597 - }
451 + $origin[$j][count($origin[$j]) - 1] = $this->combineSelectorSingle(end($new), $rem);
598 452 }
599 453
600 454 $outOrigin = array_merge($outOrigin, $origin);
601 455
@@ -604,42 +458,9 @@
604 458
605 459 return $found;
606 460 }
607 461
608 -
609 462 /**
610 - * Extract a relationship from the fragment.
611 - *
612 - * When extracting the last portion of a selector we will be left with a
613 - * fragment which may end with a direction relationship combinator. This
614 - * method will extract the relationship fragment and return it along side
615 - * the rest.
616 - *
617 - * @param array $fragment The selector fragment maybe ending with a direction relationship combinator.
618 - * @return array The selector without the relationship fragment if any, the relationship fragment.
619 - */
620 - protected function extractRelationshipFromFragment(array $fragment)
621 - {
622 - $parents = [];
623 - $children = [];
624 - $j = $i = count($fragment);
625 -
626 - for (;;) {
627 - $children = $j != $i ? array_slice($fragment, $j, $i - $j) : [];
628 - $parents = array_slice($fragment, 0, $j);
629 - $slice = end($parents);
630 -
631 - if (empty($slice) || ! $this->isImmediateRelationshipCombinator($slice[0])) {
632 - break;
633 - }
634 -
635 - $j -= 2;
636 - }
637 -
638 - return [$parents, $children];
639 - }
640 -
641 - /**
642 463 * Combine selector single
643 464 *
644 465 * @param array $base
645 466 * @param array $other
@@ -647,30 +468,23 @@
647 468 * @return array
648 469 */
649 470 protected function combineSelectorSingle($base, $other)
650 471 {
651 - $tag = [];
652 - $out = [];
653 - $wasTag = true;
472 + $tag = null;
473 + $out = array();
654 474
655 - foreach ([$base, $other] as $single) {
475 + foreach (array($base, $other) as $single) {
656 476 foreach ($single as $part) {
657 - if (preg_match('/^[\[.:#]/', $part)) {
477 + if (preg_match('/^[^\[.#:]/', $part)) {
478 + $tag = $part;
479 + } else {
658 480 $out[] = $part;
659 - $wasTag = false;
660 - } elseif (preg_match('/^[^_-]/', $part)) {
661 - $tag[] = $part;
662 - $wasTag = true;
663 - } elseif ($wasTag) {
664 - $tag[count($tag) - 1] .= $part;
665 - } else {
666 - $out[count($out) - 1] .= $part;
667 481 }
668 482 }
669 483 }
670 484
671 - if (count($tag)) {
672 - array_unshift($out, $tag[0]);
485 + if ($tag) {
486 + array_unshift($out, $tag);
673 487 }
674 488
675 489 return $out;
676 490 }
@@ -686,9 +500,9 @@
686 500
687 501 $mediaQuery = $this->compileMediaQuery($this->multiplyMedia($this->env));
688 502
689 503 if (! empty($mediaQuery)) {
690 - $this->scope = $this->makeOutputBlock(Type::T_MEDIA, [$mediaQuery]);
504 + $this->scope = $this->makeOutputBlock(Type::T_MEDIA, array($mediaQuery));
691 505
692 506 $parentScope = $this->mediaParent($this->scope);
693 507 $parentScope->children[] = $this->scope;
694 508
@@ -709,18 +523,12 @@
709 523 }
710 524
711 525 if ($needsWrap) {
712 526 $wrapped = new Block;
713 - $wrapped->sourceName = $media->sourceName;
714 - $wrapped->sourceIndex = $media->sourceIndex;
715 - $wrapped->sourceLine = $media->sourceLine;
716 - $wrapped->sourceColumn = $media->sourceColumn;
717 - $wrapped->selectors = [];
718 - $wrapped->comments = [];
719 - $wrapped->parent = $media;
720 - $wrapped->children = $media->children;
527 + $wrapped->selectors = array();
528 + $wrapped->children = $media->children;
721 529
722 - $media->children = [[Type::T_BLOCK, $wrapped]];
530 + $media->children = array(array(Type::T_BLOCK, $wrapped));
723 531 }
724 532
725 533 $this->compileChildrenNoReturn($media->children, $this->scope);
726 534
@@ -763,11 +571,11 @@
763 571 $s .= ' ' . $this->compileValue($block->value);
764 572 }
765 573
766 574 if ($block->name === 'keyframes' || substr($block->name, -10) === '-keyframes') {
767 - $this->compileKeyframeBlock($block, [$s]);
575 + $this->compileKeyframeBlock($block, array($s));
768 576 } else {
769 - $this->compileNestedBlock($block, [$s]);
577 + $this->compileNestedBlock($block, array($s));
770 578 }
771 579 }
772 580
773 581 /**
@@ -778,23 +586,21 @@
778 586 protected function compileAtRoot(Block $block)
779 587 {
780 588 $env = $this->pushEnv($block);
781 589 $envs = $this->compactEnv($env);
782 - $without = isset($block->with) ? $this->compileWith($block->with) : static::WITH_RULE;
590 + $without = isset($block->with) ? $this->compileWith($block->with) : self::WITH_RULE;
783 591
784 592 // wrap inline selector
785 593 if ($block->selector) {
786 594 $wrapped = new Block;
787 - $wrapped->sourceName = $block->sourceName;
788 - $wrapped->sourceIndex = $block->sourceIndex;
789 - $wrapped->sourceLine = $block->sourceLine;
790 - $wrapped->sourceColumn = $block->sourceColumn;
791 - $wrapped->selectors = $block->selector;
792 - $wrapped->comments = [];
793 - $wrapped->parent = $block;
794 - $wrapped->children = $block->children;
595 + $wrapped->parent = $block;
596 + $wrapped->sourcePosition = $block->sourcePosition;
597 + $wrapped->sourceIndex = $block->sourceIndex;
598 + $wrapped->selectors = $block->selector;
599 + $wrapped->comments = array();
600 + $wrapped->children = $block->children;
795 601
796 - $block->children = [[Type::T_BLOCK, $wrapped]];
602 + $block->children = array(array(Type::T_BLOCK, $wrapped));
797 603 }
798 604
799 605 $this->env = $this->filterWithout($envs, $without);
800 606 $newBlock = $this->spliceTree($envs, $block, $without);
@@ -827,9 +633,9 @@
827 633 if (! isset($e->block)) {
828 634 continue;
829 635 }
830 636
831 - if ($e->block === $block) {
637 + if (isset($e->block) && $e->block === $block) {
832 638 continue;
833 639 }
834 640
835 641 if (isset($e->block->type) && $e->block->type === Type::T_AT_ROOT) {
@@ -835,35 +641,39 @@
835 641 if (isset($e->block->type) && $e->block->type === Type::T_AT_ROOT) {
836 642 continue;
837 643 }
838 644
839 - if ($e->block && $this->isWithout($without, $e->block)) {
645 + if (($without & self::WITH_RULE) && isset($e->block->selectors)) {
840 646 continue;
841 647 }
842 648
649 + if (($without & self::WITH_MEDIA) &&
650 + isset($e->block->type) && $e->block->type === Type::T_MEDIA
651 + ) {
652 + continue;
653 + }
654 +
655 + if (($without & self::WITH_SUPPORTS) &&
656 + isset($e->block->type) && $e->block->type === Type::T_DIRECTIVE &&
657 + isset($e->block->name) && $e->block->name === 'supports'
658 + ) {
659 + continue;
660 + }
661 +
843 662 $b = new Block;
844 - $b->sourceName = $e->block->sourceName;
845 - $b->sourceIndex = $e->block->sourceIndex;
846 - $b->sourceLine = $e->block->sourceLine;
847 - $b->sourceColumn = $e->block->sourceColumn;
848 - $b->selectors = [];
849 - $b->comments = $e->block->comments;
850 - $b->parent = null;
851 663
852 - if ($newBlock) {
853 - $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
664 + if (isset($e->block->sourcePosition)) {
665 + $b->sourcePosition = $e->block->sourcePosition;
666 + }
854 667
855 - $b->children = [[$type, $newBlock]];
668 + if (isset($e->block->sourceIndex)) {
669 + $b->sourceIndex = $e->block->sourceIndex;
670 + }
856 671
857 - $newBlock->parent = $b;
858 - } elseif (count($block->children)) {
859 - foreach ($block->children as $child) {
860 - if ($child[0] === Type::T_BLOCK) {
861 - $child[1]->parent = $b;
862 - }
863 - }
672 + $b->selectors = array();
864 673
865 - $b->children = $block->children;
674 + if (isset($e->block->comments)) {
675 + $b->comments = $e->block->comments;
866 676 }
867 677
868 678 if (isset($e->block->type)) {
869 679 $b->type = $e->block->type;
@@ -880,14 +690,32 @@
880 690 if (isset($e->block->value)) {
881 691 $b->value = $e->block->value;
882 692 }
883 693
694 + if ($newBlock) {
695 + $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
696 +
697 + $b->children = array(array($type, $newBlock));
698 +
699 + $newBlock->parent = $b;
700 + } elseif (count($block->children)) {
701 + foreach ($block->children as $child) {
702 + if ($child[0] === Type::T_BLOCK) {
703 + $child[1]->parent = $b;
704 + }
705 + }
706 +
707 + $b->children = $block->children;
708 + }
709 +
710 + $b->parent = null;
711 +
884 712 $newBlock = $b;
885 713 }
886 714
887 715 $type = isset($newBlock->type) ? $newBlock->type : Type::T_BLOCK;
888 716
889 - return [$type, $newBlock];
717 + return array($type, $newBlock);
890 718 }
891 719
892 720 /**
893 721 * Compile @at-root's with: inclusion / without: exclusion into filter flags
@@ -897,22 +725,22 @@
897 725 * @return integer
898 726 */
899 727 private function compileWith($with)
900 728 {
901 - static $mapping = [
729 + static $mapping = array(
902 730 'rule' => self::WITH_RULE,
903 731 'media' => self::WITH_MEDIA,
904 732 'supports' => self::WITH_SUPPORTS,
905 733 'all' => self::WITH_ALL,
906 - ];
734 + );
907 735
908 736 // exclude selectors by default
909 - $without = static::WITH_RULE;
737 + $without = self::WITH_RULE;
910 738
911 - if ($this->libMapHasKey([$with, static::$with])) {
912 - $without = static::WITH_ALL;
739 + if ($this->libMapHasKey(array($with, self::$with))) {
740 + $without = self::WITH_ALL;
913 741
914 - $list = $this->coerceList($this->libMapGet([$with, static::$with]));
742 + $list = $this->coerceList($this->libMapGet(array($with, self::$with)));
915 743
916 744 foreach ($list[2] as $item) {
917 745 $keyword = $this->compileStringContent($this->coerceString($item));
918 746
@@ -921,12 +749,12 @@
921 749 }
922 750 }
923 751 }
924 752
925 - if ($this->libMapHasKey([$with, static::$without])) {
753 + if ($this->libMapHasKey(array($with, self::$without))) {
926 754 $without = 0;
927 755
928 - $list = $this->coerceList($this->libMapGet([$with, static::$without]));
756 + $list = $this->coerceList($this->libMapGet(array($with, self::$without)));
929 757
930 758 foreach ($list[2] as $item) {
931 759 $keyword = $this->compileStringContent($this->coerceString($item));
932 760
@@ -948,15 +776,28 @@
948 776 * @return \Leafo\ScssPhp\Compiler\Environment
949 777 */
950 778 private function filterWithout($envs, $without)
951 779 {
952 - $filtered = [];
780 + $filtered = array();
953 781
954 782 foreach ($envs as $e) {
955 - if ($e->block && $this->isWithout($without, $e->block)) {
783 + if (($without & self::WITH_RULE) && isset($e->block->selectors)) {
956 784 continue;
957 785 }
958 786
787 + if (($without & self::WITH_MEDIA) &&
788 + isset($e->block->type) && $e->block->type === Type::T_MEDIA
789 + ) {
790 + continue;
791 + }
792 +
793 + if (($without & self::WITH_SUPPORTS) &&
794 + isset($e->block->type) && $e->block->type === Type::T_DIRECTIVE &&
795 + isset($e->block->name) && $e->block->name === 'supports'
796 + ) {
797 + continue;
798 + }
799 +
959 800 $filtered[] = $e;
960 801 }
961 802
962 803 return $this->extractEnv($filtered);
@@ -962,31 +803,8 @@
962 803 return $this->extractEnv($filtered);
963 804 }
964 805
965 806 /**
966 - * Filter WITH rules
967 - *
968 - * @param integer $without
969 - * @param \Leafo\ScssPhp\Block $block
970 - *
971 - * @return boolean
972 - */
973 - private function isWithout($without, Block $block)
974 - {
975 - if ((($without & static::WITH_RULE) && isset($block->selectors)) ||
976 - (($without & static::WITH_MEDIA) &&
977 - isset($block->type) && $block->type === Type::T_MEDIA) ||
978 - (($without & static::WITH_SUPPORTS) &&
979 - isset($block->type) && $block->type === Type::T_DIRECTIVE &&
980 - isset($block->name) && $block->name === 'supports')
981 - ) {
982 - return true;
983 - }
984 -
985 - return false;
986 - }
987 -
988 - /**
989 807 * Compile keyframe block
990 808 *
991 809 * @param \Leafo\ScssPhp\Block $block
992 810 * @param array $selectors
@@ -996,9 +814,9 @@
996 814 $env = $this->pushEnv($block);
997 815
998 816 $envs = $this->compactEnv($env);
999 817
1000 - $this->env = $this->extractEnv(array_filter($envs, function (Environment $e) {
818 + $this->env = $this->extractEnv(array_filter($envs, function ($e) {
1001 819 return ! isset($e->block->selectors);
1002 820 }));
1003 821
1004 822 $this->scope = $this->makeOutputBlock($block->type, $selectors);
@@ -1061,22 +879,20 @@
1061 879 if (isset($this->lineNumberStyle) && count($env->selectors) && count($block->children)) {
1062 880 $annotation = $this->makeOutputBlock(Type::T_COMMENT);
1063 881 $annotation->depth = 0;
1064 882
1065 - $file = $this->sourceNames[$block->sourceIndex];
1066 - $line = $block->sourceLine;
883 + $parser = $this->sourceParsers[$block->sourceIndex];
884 + $file = $parser->getSourceName();
885 + $line = $parser->getLineNo($block->sourcePosition);
1067 886
1068 887 switch ($this->lineNumberStyle) {
1069 - case static::LINE_COMMENTS:
1070 - $annotation->lines[] = '/* line ' . $line
1071 - . ($file ? ', ' . $file : '')
1072 - . ' */';
888 + case self::LINE_COMMENTS:
889 + $annotation->lines[] = '/* line ' . $line . ', ' . $file . ' */';
1073 890 break;
1074 891
1075 - case static::DEBUG_INFO:
1076 - $annotation->lines[] = '@media -sass-debug-info{'
1077 - . ($file ? 'filename{font-family:"' . $file . '"}' : '')
1078 - . 'line{font-family:' . $line . '}}';
892 + case self::DEBUG_INFO:
893 + $annotation->lines[] = '@media -sass-debug-info{filename{font-family:"' . $file
894 + . '"}line{font-family:' . $line . '}}';
1079 895 break;
1080 896 }
1081 897
1082 898 $this->scope->children[] = $annotation;
@@ -1117,9 +933,9 @@
1117 933 protected function evalSelectors($selectors)
1118 934 {
1119 935 $this->shouldEvaluate = false;
1120 936
1121 - $selectors = array_map([$this, 'evalSelector'], $selectors);
937 + $selectors = array_map(array($this, 'evalSelector'), $selectors);
1122 938
1123 939 // after evaluating interpolates, we might need a second pass
1124 940 if ($this->shouldEvaluate) {
1125 941 $buffer = $this->collapseSelectors($selectors);
@@ -1125,9 +941,9 @@
1125 941 $buffer = $this->collapseSelectors($selectors);
1126 942 $parser = $this->parserFactory(__METHOD__);
1127 943
1128 944 if ($parser->parseSelector($buffer, $newSelectors)) {
1129 - $selectors = array_map([$this, 'evalSelector'], $newSelectors);
945 + $selectors = array_map(array($this, 'evalSelector'), $newSelectors);
1130 946 }
1131 947 }
1132 948
1133 949 return $selectors;
@@ -1141,9 +957,9 @@
1141 957 * @return array
1142 958 */
1143 959 protected function evalSelector($selector)
1144 960 {
1145 - return array_map([$this, 'evalSelectorPart'], $selector);
961 + return array_map(array($this, 'evalSelectorPart'), $selector);
1146 962 }
1147 963
1148 964 /**
1149 965 * Evaluate selector part; replaces all the interpolates, stripping quotes
@@ -1181,9 +997,9 @@
1181 997 * @return string
1182 998 */
1183 999 protected function collapseSelectors($selectors)
1184 1000 {
1185 - $parts = [];
1001 + $parts = array();
1186 1002
1187 1003 foreach ($selectors as $selector) {
1188 1004 $output = '';
1189 1005
@@ -1208,9 +1024,9 @@
1208 1024 * @return array
1209 1025 */
1210 1026 protected function flattenSelectorSingle($single)
1211 1027 {
1212 - $joined = [];
1028 + $joined = array();
1213 1029
1214 1030 foreach ($single as $part) {
1215 1031 if (empty($joined) ||
1216 1032 ! is_string($part) ||
@@ -1232,9 +1048,9 @@
1232 1048
1233 1049 /**
1234 1050 * Compile selector to string; self(&) should have been replaced by now
1235 1051 *
1236 - * @param string|array $selector
1052 + * @param array $selector
1237 1053 *
1238 1054 * @return string
1239 1055 */
1240 1056 protected function compileSelector($selector)
@@ -1245,9 +1061,9 @@
1245 1061
1246 1062 return implode(
1247 1063 ' ',
1248 1064 array_map(
1249 - [$this, 'compileSelectorPart'],
1065 + array($this, 'compileSelectorPart'),
1250 1066 $selector
1251 1067 )
1252 1068 );
1253 1069 }
@@ -1254,9 +1070,9 @@
1254 1070
1255 1071 /**
1256 1072 * Compile selector part
1257 1073 *
1258 - * @param array $piece
1074 + * @param arary $piece
1259 1075 *
1260 1076 * @return string
1261 1077 */
1262 1078 protected function compileSelectorPart($piece)
@@ -1294,9 +1110,9 @@
1294 1110 }
1295 1111
1296 1112 foreach ($selector as $parts) {
1297 1113 foreach ($parts as $part) {
1298 - if (strlen($part) && '%' === $part[0]) {
1114 + if ('%' === $part[0]) {
1299 1115 return true;
1300 1116 }
1301 1117 }
1302 1118 }
@@ -1337,10 +1153,8 @@
1337 1153 $ret = $this->compileChild($stm, $out);
1338 1154
1339 1155 if (isset($ret)) {
1340 1156 $this->throwError('@return may only be used within a function');
1341 -
1342 - return;
1343 1157 }
1344 1158 }
1345 1159 }
1346 1160
@@ -1357,9 +1171,9 @@
1357 1171 $first = true;
1358 1172
1359 1173 foreach ($queryList as $query) {
1360 1174 $type = null;
1361 - $parts = [];
1175 + $parts = array();
1362 1176
1363 1177 foreach ($query as $q) {
1364 1178 switch ($q[0]) {
1365 1179 case Type::T_MEDIA_TYPE:
@@ -1365,9 +1179,9 @@
1365 1179 case Type::T_MEDIA_TYPE:
1366 1180 if ($type) {
1367 1181 $type = $this->mergeMediaTypes(
1368 1182 $type,
1369 - array_map([$this, 'compileValue'], array_slice($q, 1))
1183 + array_map(array($this, 'compileValue'), array_slice($q, 1))
1370 1184 );
1371 1185
1372 1186 if (empty($type)) { // merge failed
1373 1187 return null;
@@ -1372,9 +1186,9 @@
1372 1186 if (empty($type)) { // merge failed
1373 1187 return null;
1374 1188 }
1375 1189 } else {
1376 - $type = array_map([$this, 'compileValue'], array_slice($q, 1));
1190 + $type = array_map(array($this, 'compileValue'), array_slice($q, 1));
1377 1191 }
1378 1192 break;
1379 1193
1380 1194 case Type::T_MEDIA_EXPRESSION:
@@ -1415,39 +1229,8 @@
1415 1229
1416 1230 return $out;
1417 1231 }
1418 1232
1419 - protected function mergeDirectRelationships($selectors1, $selectors2)
1420 - {
1421 - if (empty($selectors1) || empty($selectors2)) {
1422 - return array_merge($selectors1, $selectors2);
1423 - }
1424 -
1425 - $part1 = end($selectors1);
1426 - $part2 = end($selectors2);
1427 -
1428 - if (! $this->isImmediateRelationshipCombinator($part1[0]) || $part1 !== $part2) {
1429 - return array_merge($selectors1, $selectors2);
1430 - }
1431 -
1432 - $merged = [];
1433 -
1434 - do {
1435 - $part1 = array_pop($selectors1);
1436 - $part2 = array_pop($selectors2);
1437 -
1438 - if ($this->isImmediateRelationshipCombinator($part1[0]) && $part1 !== $part2) {
1439 - $merged = array_merge($selectors1, [$part1], $selectors2, [$part2], $merged);
1440 - break;
1441 - }
1442 -
1443 - array_unshift($merged, $part1);
1444 - array_unshift($merged, [array_pop($selectors1)[0] . array_pop($selectors2)[0]]);
1445 - } while (! empty($selectors1) && ! empty($selectors2));
1446 -
1447 - return $merged;
1448 - }
1449 -
1450 1233 /**
1451 1234 * Merge media types
1452 1235 *
1453 1236 * @param array $type1
@@ -1489,12 +1272,12 @@
1489 1272 if ($t1 === $t2) {
1490 1273 return null;
1491 1274 }
1492 1275
1493 - return [
1276 + return array(
1494 1277 $m1 === Type::T_NOT ? $m2 : $m1,
1495 1278 $m1 === Type::T_NOT ? $t2 : $t1,
1496 - ];
1279 + );
1497 1280 }
1498 1281
1499 1282 if ($m1 === Type::T_NOT && $m2 === Type::T_NOT) {
1500 1283 // CSS has no way of representing "neither screen nor print"
@@ -1501,9 +1284,9 @@
1501 1284 if ($t1 !== $t2) {
1502 1285 return null;
1503 1286 }
1504 1287
1505 - return [Type::T_NOT, $t1];
1288 + return array(Type::T_NOT, $t1);
1506 1289 }
1507 1290
1508 1291 if ($t1 !== $t2) {
1509 1292 return null;
@@ -1509,30 +1292,26 @@
1509 1292 return null;
1510 1293 }
1511 1294
1512 1295 // t1 == t2, neither m1 nor m2 are "not"
1513 - return [empty($m1)? $m2 : $m1, $t1];
1296 + return array(empty($m1)? $m2 : $m1, $t1);
1514 1297 }
1515 1298
1516 1299 /**
1517 1300 * Compile import; returns true if the value was something that could be imported
1518 1301 *
1519 - * @param array $rawPath
1520 - * @param array $out
1521 - * @param boolean $once
1302 + * @param array $rawPath
1303 + * @param array $out
1522 1304 *
1523 1305 * @return boolean
1524 1306 */
1525 - protected function compileImport($rawPath, $out, $once = false)
1307 + protected function compileImport($rawPath, $out)
1526 1308 {
1527 1309 if ($rawPath[0] === Type::T_STRING) {
1528 1310 $path = $this->compileStringContent($rawPath);
1529 1311
1530 1312 if ($path = $this->findImport($path)) {
1531 - if (! $once || ! in_array($path, $this->importedFiles)) {
1532 - $this->importFile($path, $out);
1533 - $this->importedFiles[] = $path;
1534 - }
1313 + $this->importFile($path, $out);
1535 1314
1536 1315 return true;
1537 1316 }
1538 1317
@@ -1570,23 +1349,12 @@
1570 1349 * @return array
1571 1350 */
1572 1351 protected function compileChild($child, OutputBlock $out)
1573 1352 {
1574 - $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
1575 - $this->sourceLine = isset($child[Parser::SOURCE_LINE]) ? $child[Parser::SOURCE_LINE] : -1;
1576 - $this->sourceColumn = isset($child[Parser::SOURCE_COLUMN]) ? $child[Parser::SOURCE_COLUMN] : -1;
1353 + $this->sourceIndex = isset($child[Parser::SOURCE_INDEX]) ? $child[Parser::SOURCE_INDEX] : null;
1354 + $this->sourcePos = isset($child[Parser::SOURCE_POSITION]) ? $child[Parser::SOURCE_POSITION] : -1;
1577 1355
1578 1356 switch ($child[0]) {
1579 - case Type::T_SCSSPHP_IMPORT_ONCE:
1580 - list(, $rawPath) = $child;
1581 -
1582 - $rawPath = $this->reduce($rawPath);
1583 -
1584 - if (! $this->compileImport($rawPath, $out, true)) {
1585 - $out->lines[] = '@import ' . $this->compileValue($rawPath) . ';';
1586 - }
1587 - break;
1588 -
1589 1357 case Type::T_IMPORT:
1590 1358 list(, $rawPath) = $child;
1591 1359
1592 1360 $rawPath = $this->reduce($rawPath);
@@ -1623,11 +1391,11 @@
1623 1391 case Type::T_ASSIGN:
1624 1392 list(, $name, $value) = $child;
1625 1393
1626 1394 if ($name[0] === Type::T_VARIABLE) {
1627 - $flags = isset($child[3]) ? $child[3] : [];
1628 - $isDefault = in_array('!default', $flags);
1629 - $isGlobal = in_array('!global', $flags);
1395 + $flag = isset($child[3]) ? $child[3] : null;
1396 + $isDefault = $flag === '!default';
1397 + $isGlobal = $flag === '!global';
1630 1398
1631 1399 if ($isGlobal) {
1632 1400 $this->set($name[1], $this->reduce($value), false, $this->rootEnv);
1633 1401 break;
@@ -1634,9 +1402,9 @@
1634 1402 }
1635 1403
1636 1404 $shouldSet = $isDefault &&
1637 1405 (($result = $this->get($name[1], false)) === null
1638 - || $result === static::$null);
1406 + || $result === self::$null);
1639 1407
1640 1408 if (! $isDefault || $shouldSet) {
1641 1409 $this->set($name[1], $this->reduce($value));
1642 1410 }
@@ -1662,9 +1430,9 @@
1662 1430 // the property should be discarded
1663 1431 if ($value[0] !== Type::T_NULL) {
1664 1432 $value = $this->reduce($value);
1665 1433
1666 - if ($value[0] === Type::T_NULL || $value === static::$nullString) {
1434 + if ($value[0] === Type::T_NULL) {
1667 1435 break;
1668 1436 }
1669 1437 }
1670 1438
@@ -1688,9 +1456,9 @@
1688 1456 case Type::T_MIXIN:
1689 1457 case Type::T_FUNCTION:
1690 1458 list(, $block) = $child;
1691 1459
1692 - $this->set(static::$namespaces[$block->type] . $block->name, $block);
1460 + $this->set(self::$namespaces[$block->type] . $block->name, $block);
1693 1461 break;
1694 1462
1695 1463 case Type::T_EXTEND:
1696 1464 list(, $selectors) = $child;
@@ -1695,15 +1463,15 @@
1695 1463 case Type::T_EXTEND:
1696 1464 list(, $selectors) = $child;
1697 1465
1698 1466 foreach ($selectors as $sel) {
1699 - $results = $this->evalSelectors([$sel]);
1467 + $results = $this->evalSelectors(array($sel));
1700 1468
1701 1469 foreach ($results as $result) {
1702 1470 // only use the first one
1703 1471 $result = current($result);
1704 1472
1705 - $this->pushExtends($result, $out->selectors, $child);
1473 + $this->pushExtends($result, $out->selectors);
1706 1474 }
1707 1475 }
1708 1476 break;
1709 1477
@@ -1736,9 +1504,9 @@
1736 1504 } else {
1737 1505 list(,, $values) = $this->coerceList($item);
1738 1506
1739 1507 foreach ($each->vars as $i => $var) {
1740 - $this->set($var, isset($values[$i]) ? $values[$i] : static::$null, true);
1508 + $this->set($var, isset($values[$i]) ? $values[$i] : self::$null, true);
1741 1509 }
1742 1510 }
1743 1511
1744 1512 $ret = $this->compileChildren($each->children, $out);
@@ -1780,23 +1548,14 @@
1780 1548 case Type::T_FOR:
1781 1549 list(, $for) = $child;
1782 1550
1783 1551 $start = $this->reduce($for->start, true);
1784 - $end = $this->reduce($for->end, true);
1785 -
1786 - if (! ($start[2] == $end[2] || $end->unitless())) {
1787 - $this->throwError('Incompatible units: "%s" and "%s".', $start->unitStr(), $end->unitStr());
1788 -
1789 - break;
1790 - }
1791 -
1792 - $unit = $start[2];
1793 1552 $start = $start[1];
1794 - $end = $end[1];
1795 -
1553 + $end = $this->reduce($for->end, true);
1554 + $end = $end[1];
1796 1555 $d = $start < $end ? 1 : -1;
1797 1556
1798 - for (;;) {
1557 + while (true) {
1799 1558 if ((! $for->until && $start - $d == $end) ||
1800 1559 ($for->until && $start == $end)
1801 1560 ) {
1802 1561 break;
@@ -1801,9 +1560,9 @@
1801 1560 ) {
1802 1561 break;
1803 1562 }
1804 1563
1805 - $this->set($for->var, new Node\Number($start, $unit));
1564 + $this->set($for->var, new Node\Number($start, ''));
1806 1565 $start += $d;
1807 1566
1808 1567 $ret = $this->compileChildren($for->children, $out);
1809 1568
@@ -1819,12 +1578,12 @@
1819 1578 }
1820 1579 break;
1821 1580
1822 1581 case Type::T_BREAK:
1823 - return [Type::T_CONTROL, true];
1582 + return array(Type::T_CONTROL, true);
1824 1583
1825 1584 case Type::T_CONTINUE:
1826 - return [Type::T_CONTROL, false];
1585 + return array(Type::T_CONTROL, false);
1827 1586
1828 1587 case Type::T_RETURN:
1829 1588 return $this->reduce($child[1], true);
1830 1589
@@ -1830,20 +1589,18 @@
1830 1589
1831 1590 case Type::T_NESTED_PROPERTY:
1832 1591 list(, $prop) = $child;
1833 1592
1834 - $prefixed = [];
1593 + $prefixed = array();
1835 1594 $prefix = $this->compileValue($prop->prefix) . '-';
1836 1595
1837 1596 foreach ($prop->children as $child) {
1838 - switch ($child[0]) {
1839 - case Type::T_ASSIGN:
1840 - array_unshift($child[1][2], $prefix);
1841 - break;
1597 + if ($child[0] === Type::T_ASSIGN) {
1598 + array_unshift($child[1][2], $prefix);
1599 + }
1842 1600
1843 - case Type::T_NESTED_PROPERTY:
1844 - array_unshift($child[1]->prefix[2], $prefix);
1845 - break;
1601 + if ($child[0] === Type::T_NESTED_PROPERTY) {
1602 + array_unshift($child[1]->prefix[2], $prefix);
1846 1603 }
1847 1604
1848 1605 $prefixed[] = $child;
1849 1606 }
@@ -1854,13 +1611,12 @@
1854 1611 case Type::T_INCLUDE:
1855 1612 // including a mixin
1856 1613 list(, $name, $argValues, $content) = $child;
1857 1614
1858 - $mixin = $this->get(static::$namespaces['mixin'] . $name, false);
1615 + $mixin = $this->get(self::$namespaces['mixin'] . $name, false);
1859 1616
1860 1617 if (! $mixin) {
1861 1618 $this->throwError("Undefined mixin $name");
1862 - break;
1863 1619 }
1864 1620
1865 1621 $callingScope = $this->getStoreEnv();
1866 1622
@@ -1867,15 +1623,12 @@
1867 1623 // push scope, apply args
1868 1624 $this->pushEnv();
1869 1625 $this->env->depth--;
1870 1626
1871 - $storeEnv = $this->storeEnv;
1872 - $this->storeEnv = $this->env;
1873 -
1874 1627 if (isset($content)) {
1875 1628 $content->scope = $callingScope;
1876 1629
1877 - $this->setRaw(static::$namespaces['special'] . 'content', $content, $this->env);
1630 + $this->setRaw(self::$namespaces['special'] . 'content', $content, $this->getStoreEnv());
1878 1631 }
1879 1632
1880 1633 if (isset($mixin->args)) {
1881 1634 $this->applyArguments($mixin->args, $argValues);
@@ -1884,21 +1637,19 @@
1884 1637 $this->env->marker = 'mixin';
1885 1638
1886 1639 $this->compileChildrenNoReturn($mixin->children, $out);
1887 1640
1888 - $this->storeEnv = $storeEnv;
1889 -
1890 1641 $this->popEnv();
1891 1642 break;
1892 1643
1893 1644 case Type::T_MIXIN_CONTENT:
1894 - $content = $this->get(static::$namespaces['special'] . 'content', false, $this->getStoreEnv())
1895 - ?: $this->get(static::$namespaces['special'] . 'content', false, $this->env);
1645 + $content = $this->get(self::$namespaces['special'] . 'content', false, $this->getStoreEnv());
1896 1646
1897 1647 if (! $content) {
1898 - $content = new \stdClass();
1899 - $content->scope = new \stdClass();
1900 - $content->children = $this->storeEnv->parent->block->children;
1648 + $this->throwError('Expected @content inside of mixin');
1649 + }
1650 +
1651 + if (! isset($content->children)) {
1901 1652 break;
1902 1653 }
1903 1654
1904 1655 $storeEnv = $this->storeEnv;
@@ -1911,9 +1662,9 @@
1911 1662
1912 1663 case Type::T_DEBUG:
1913 1664 list(, $value) = $child;
1914 1665
1915 - $line = $this->sourceLine;
1666 + $line = $this->parser->getLineNo($this->sourcePos);
1916 1667 $value = $this->compileValue($this->reduce($value, true));
1917 1668 fwrite($this->stderr, "Line $line DEBUG: $value\n");
1918 1669 break;
1919 1670
@@ -1919,17 +1670,17 @@
1919 1670
1920 1671 case Type::T_WARN:
1921 1672 list(, $value) = $child;
1922 1673
1923 - $line = $this->sourceLine;
1674 + $line = $this->parser->getLineNo($this->sourcePos);
1924 1675 $value = $this->compileValue($this->reduce($value, true));
1925 - fwrite($this->stderr, "Line $line WARN: $value\n");
1676 + echo "Line $line WARN: $value\n";
1926 1677 break;
1927 1678
1928 1679 case Type::T_ERROR:
1929 1680 list(, $value) = $child;
1930 1681
1931 - $line = $this->sourceLine;
1682 + $line = $this->parser->getLineNo($this->sourcePos);
1932 1683 $value = $this->compileValue($this->reduce($value, true));
1933 1684 $this->throwError("Line $line ERROR: $value\n");
1934 1685 break;
1935 1686
@@ -1950,11 +1701,11 @@
1950 1701 * @return array
1951 1702 */
1952 1703 protected function expToString($exp)
1953 1704 {
1954 - list(, $op, $left, $right, /* $inParens */, $whiteLeft, $whiteRight) = $exp;
1705 + list(, $op, $left, $right, $inParens, $whiteLeft, $whiteRight) = $exp;
1955 1706
1956 - $content = [$this->reduce($left)];
1707 + $content = array($this->reduce($left));
1957 1708
1958 1709 if ($whiteLeft) {
1959 1710 $content[] = ' ';
1960 1711 }
@@ -1966,9 +1717,9 @@
1966 1717 }
1967 1718
1968 1719 $content[] = $this->reduce($right);
1969 1720
1970 - return [Type::T_STRING, '', $content];
1721 + return array(Type::T_STRING, '', $content);
1971 1722 }
1972 1723
1973 1724 /**
1974 1725 * Is truthy?
@@ -1978,24 +1729,12 @@
1978 1729 * @return array
1979 1730 */
1980 1731 protected function isTruthy($value)
1981 1732 {
1982 - return $value !== static::$false && $value !== static::$null;
1733 + return $value !== self::$false && $value !== self::$null;
1983 1734 }
1984 1735
1985 1736 /**
1986 - * Is the value a direct relationship combinator?
1987 - *
1988 - * @param string $value
1989 - *
1990 - * @return boolean
1991 - */
1992 - protected function isImmediateRelationshipCombinator($value)
1993 - {
1994 - return $value === '>' || $value === '+' || $value === '~';
1995 - }
1996 -
1997 - /**
1998 1737 * Should $value cause its operand to eval
1999 1738 *
2000 1739 * @param array $value
2001 1740 *
@@ -2023,9 +1762,9 @@
2023 1762 *
2024 1763 * @param array $value
2025 1764 * @param boolean $inExp
2026 1765 *
2027 - * @return array|\Leafo\ScssPhp\Node\Number
1766 + * @return array
2028 1767 */
2029 1768 protected function reduce($value, $inExp = false)
2030 1769 {
2031 1770 list($type) = $value;
@@ -2033,9 +1772,9 @@
2033 1772 switch ($type) {
2034 1773 case Type::T_EXPRESSION:
2035 1774 list(, $op, $left, $right, $inParens) = $value;
2036 1775
2037 - $opName = isset(static::$operatorNames[$op]) ? static::$operatorNames[$op] : $op;
1776 + $opName = isset(self::$operatorNames[$op]) ? self::$operatorNames[$op] : $op;
2038 1777 $inExp = $inExp || $this->shouldEval($left) || $this->shouldEval($right);
2039 1778
2040 1779 $left = $this->reduce($left, true);
2041 1780
@@ -2066,51 +1805,53 @@
2066 1805 // 2. op[left type][right type] (passing the op as first arg
2067 1806 // 3. op[op name]
2068 1807 $fn = "op${ucOpName}${ucLType}${ucRType}";
2069 1808
2070 - if (is_callable([$this, $fn]) ||
1809 + if (is_callable(array($this, $fn)) ||
2071 1810 (($fn = "op${ucLType}${ucRType}") &&
2072 - is_callable([$this, $fn]) &&
1811 + is_callable(array($this, $fn)) &&
2073 1812 $passOp = true) ||
2074 1813 (($fn = "op${ucOpName}") &&
2075 - is_callable([$this, $fn]) &&
1814 + is_callable(array($this, $fn)) &&
2076 1815 $genOp = true)
2077 1816 ) {
2078 - $coerceUnit = false;
1817 + $unitChange = false;
2079 1818
2080 1819 if (! isset($genOp) &&
2081 1820 $left[0] === Type::T_NUMBER && $right[0] === Type::T_NUMBER
2082 1821 ) {
2083 - $coerceUnit = true;
1822 + if ($opName === 'mod' && ! $right->unitless()) {
1823 + $this->throwError(
1824 + 'Cannot modulo by a number with units: %s%s',
1825 + $right[1],
1826 + $right->unitStr()
1827 + );
1828 + }
2084 1829
2085 - switch ($opName) {
2086 - case 'mul':
2087 - $targetUnit = $left[2];
1830 + $unitChange = true;
1831 + $emptyUnit = $left->unitless() || $right->unitless();
1832 + $targetUnit = $left->unitless() ? $right[2] : $left[2];
2088 1833
2089 - foreach ($right[2] as $unit => $exp) {
2090 - $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) + $exp;
2091 - }
2092 - break;
1834 + if ($opName !== 'mul') {
1835 + $left[2] = $left->unitless() ? $targetUnit : $left[2];
1836 + $right[2] = $right->unitless() ? $targetUnit : $right[2];
1837 + }
2093 1838
2094 - case 'div':
2095 - $targetUnit = $left[2];
1839 + if ($opName !== 'mod') {
1840 + $left = $left->normalize();
1841 + $right = $right->normalize();
1842 + }
2096 1843
2097 - foreach ($right[2] as $unit => $exp) {
2098 - $targetUnit[$unit] = (isset($targetUnit[$unit]) ? $targetUnit[$unit] : 0) - $exp;
2099 - }
2100 - break;
2101 -
2102 - case 'mod':
2103 - $targetUnit = $left[2];
2104 - break;
2105 -
2106 - default:
2107 - $targetUnit = $left->unitless() ? $right[2] : $left[2];
1844 + if ($opName === 'div' && ! $emptyUnit && $left[2] === $right[2]) {
1845 + $targetUnit = '';
2108 1846 }
2109 1847
2110 - if (! $left->unitless() && ! $right->unitless()) {
2111 - $left = $left->normalize();
2112 - $right = $right->normalize();
1848 + if ($opName === 'mul') {
1849 + $left[2] = $left->unitless() ? $right[2] : $left[2];
1850 + $right[2] = $right->unitless() ? $left[2] : $right[2];
1851 + } elseif ($opName === 'div' && $left[2] === $right[2]) {
1852 + $left[2] = '';
1853 + $right[2] = '';
2113 1854 }
2114 1855 }
2115 1856
2116 1857 $shouldEval = $inParens || $inExp;
@@ -2121,9 +1862,9 @@
2121 1862 $out = $this->$fn($left, $right, $shouldEval);
2122 1863 }
2123 1864
2124 1865 if (isset($out)) {
2125 - if ($coerceUnit && $out[0] === Type::T_NUMBER) {
1866 + if ($unitChange && $out[0] === Type::T_NUMBER) {
2126 1867 $out = $out->coerce($targetUnit);
2127 1868 }
2128 1869
2129 1870 return $out;
@@ -2149,19 +1890,19 @@
2149 1890 }
2150 1891
2151 1892 if ($op === 'not') {
2152 1893 if ($inExp || $inParens) {
2153 - if ($exp === static::$false || $exp === static::$null) {
2154 - return static::$true;
1894 + if ($exp === self::$false) {
1895 + return self::$true;
2155 1896 }
2156 1897
2157 - return static::$false;
1898 + return self::$false;
2158 1899 }
2159 1900
2160 1901 $op = $op . ' ';
2161 1902 }
2162 1903
2163 - return [Type::T_STRING, '', [$op, $exp]];
1904 + return array(Type::T_STRING, '', array($op, $exp));
2164 1905
2165 1906 case Type::T_VARIABLE:
2166 1907 list(, $name) = $value;
2167 1908
@@ -2229,9 +1970,9 @@
2229 1970 return $returnValue;
2230 1971 }
2231 1972
2232 1973 // for CSS functions, simply flatten the arguments into a list
2233 - $listArgs = [];
1974 + $listArgs = array();
2234 1975
2235 1976 foreach ((array) $argValues as $arg) {
2236 1977 if (empty($arg[0])) {
2237 1978 $listArgs[] = $this->reduce($arg[1]);
@@ -2237,9 +1978,9 @@
2237 1978 $listArgs[] = $this->reduce($arg[1]);
2238 1979 }
2239 1980 }
2240 1981
2241 - return [Type::T_FUNCTION, $name, [Type::T_LIST, ',', $listArgs]];
1982 + return array(Type::T_FUNCTION, $name, array(Type::T_LIST, ',', $listArgs));
2242 1983 }
2243 1984
2244 1985 /**
2245 1986 * Normalize name
@@ -2269,9 +2010,9 @@
2269 2010 case Type::T_LIST:
2270 2011 $value = $this->extractInterpolation($value);
2271 2012
2272 2013 if ($value[0] !== Type::T_LIST) {
2273 - return [Type::T_KEYWORD, $this->compileValue($value)];
2014 + return array(Type::T_KEYWORD, $this->compileValue($value));
2274 2015 }
2275 2016
2276 2017 foreach ($value[2] as $key => $item) {
2277 2018 $value[2][$key] = $this->normalizeValue($item);
@@ -2279,15 +2020,15 @@
2279 2020
2280 2021 return $value;
2281 2022
2282 2023 case Type::T_STRING:
2283 - return [$type, '"', [$this->compileStringContent($value)]];
2024 + return array($type, '"', array($this->compileStringContent($value)));
2284 2025
2285 2026 case Type::T_NUMBER:
2286 2027 return $value->normalize();
2287 2028
2288 2029 case Type::T_INTERPOLATE:
2289 - return [Type::T_KEYWORD, $this->compileValue($value)];
2030 + return array(Type::T_KEYWORD, $this->compileValue($value));
2290 2031
2291 2032 default:
2292 2033 return $value;
2293 2034 }
@@ -2298,9 +2039,9 @@
2298 2039 *
2299 2040 * @param array $left
2300 2041 * @param array $right
2301 2042 *
2302 - * @return \Leafo\ScssPhp\Node\Number
2043 + * @return array
2303 2044 */
2304 2045 protected function opAddNumberNumber($left, $right)
2305 2046 {
2306 2047 return new Node\Number($left[1] + $right[1], $left[2]);
@@ -2311,9 +2052,9 @@
2311 2052 *
2312 2053 * @param array $left
2313 2054 * @param array $right
2314 2055 *
2315 - * @return \Leafo\ScssPhp\Node\Number
2056 + * @return array
2316 2057 */
2317 2058 protected function opMulNumberNumber($left, $right)
2318 2059 {
2319 2060 return new Node\Number($left[1] * $right[1], $left[2]);
@@ -2324,9 +2065,9 @@
2324 2065 *
2325 2066 * @param array $left
2326 2067 * @param array $right
2327 2068 *
2328 - * @return \Leafo\ScssPhp\Node\Number
2069 + * @return array
2329 2070 */
2330 2071 protected function opSubNumberNumber($left, $right)
2331 2072 {
2332 2073 return new Node\Number($left[1] - $right[1], $left[2]);
@@ -2337,14 +2078,14 @@
2337 2078 *
2338 2079 * @param array $left
2339 2080 * @param array $right
2340 2081 *
2341 - * @return array|\Leafo\ScssPhp\Node\Number
2082 + * @return array
2342 2083 */
2343 2084 protected function opDivNumberNumber($left, $right)
2344 2085 {
2345 2086 if ($right[1] == 0) {
2346 - return [Type::T_STRING, '', [$left[1] . $left[2] . '/' . $right[1] . $right[2]]];
2087 + return array(Type::T_STRING, '', array($left[1] . $left[2] . '/' . $right[1] . $right[2]));
2347 2088 }
2348 2089
2349 2090 return new Node\Number($left[1] / $right[1], $left[2]);
2350 2091 }
@@ -2354,9 +2095,9 @@
2354 2095 *
2355 2096 * @param array $left
2356 2097 * @param array $right
2357 2098 *
2358 - * @return \Leafo\ScssPhp\Node\Number
2099 + * @return array
2359 2100 */
2360 2101 protected function opModNumberNumber($left, $right)
2361 2102 {
2362 2103 return new Node\Number($left[1] % $right[1], $left[2]);
@@ -2407,9 +2148,9 @@
2407 2148 if (! $shouldEval) {
2408 2149 return;
2409 2150 }
2410 2151
2411 - if ($left !== static::$false and $left !== static::$null) {
2152 + if ($left !== self::$false) {
2412 2153 return $this->reduce($right, true);
2413 2154 }
2414 2155
2415 2156 return $left;
@@ -2429,9 +2170,9 @@
2429 2170 if (! $shouldEval) {
2430 2171 return;
2431 2172 }
2432 2173
2433 - if ($left !== static::$false and $left !== static::$null) {
2174 + if ($left !== self::$false) {
2434 2175 return $left;
2435 2176 }
2436 2177
2437 2178 return $this->reduce($right, true);
@@ -2447,11 +2188,11 @@
2447 2188 * @return array
2448 2189 */
2449 2190 protected function opColorColor($op, $left, $right)
2450 2191 {
2451 - $out = [Type::T_COLOR];
2192 + $out = array(Type::T_COLOR);
2452 2193
2453 - foreach ([1, 2, 3] as $i) {
2194 + foreach (array(1, 2, 3) as $i) {
2454 2195 $lval = isset($left[$i]) ? $left[$i] : 0;
2455 2196 $rval = isset($right[$i]) ? $right[$i] : 0;
2456 2197
2457 2198 switch ($op) {
@@ -2473,9 +2214,8 @@
2473 2214
2474 2215 case '/':
2475 2216 if ($rval == 0) {
2476 2217 $this->throwError("color: Can't divide by zero");
2477 - break 2;
2478 2218 }
2479 2219
2480 2220 $out[] = (int) ($lval / $rval);
2481 2221 break;
@@ -2487,9 +2227,8 @@
2487 2227 return $this->opNeq($left, $right);
2488 2228
2489 2229 default:
2490 2230 $this->throwError("color: unknown op $op");
2491 - break 2;
2492 2231 }
2493 2232 }
2494 2233
2495 2234 if (isset($left[4])) {
@@ -2516,9 +2255,9 @@
2516 2255
2517 2256 return $this->opColorColor(
2518 2257 $op,
2519 2258 $left,
2520 - [Type::T_COLOR, $value, $value, $value]
2259 + array(Type::T_COLOR, $value, $value, $value)
2521 2260 );
2522 2261 }
2523 2262
2524 2263 /**
@@ -2535,9 +2274,9 @@
2535 2274 $value = $left[1];
2536 2275
2537 2276 return $this->opColorColor(
2538 2277 $op,
2539 - [Type::T_COLOR, $value, $value, $value],
2278 + array(Type::T_COLOR, $value, $value, $value),
2540 2279 $right
2541 2280 );
2542 2281 }
2543 2282
@@ -2640,9 +2379,9 @@
2640 2379 *
2641 2380 * @param array $left
2642 2381 * @param array $right
2643 2382 *
2644 - * @return \Leafo\ScssPhp\Node\Number
2383 + * @return array
2645 2384 */
2646 2385 protected function opCmpNumberNumber($left, $right)
2647 2386 {
2648 2387 $n = $left[1] - $right[1];
@@ -2660,9 +2399,9 @@
2660 2399 * @return array
2661 2400 */
2662 2401 public function toBool($thing)
2663 2402 {
2664 - return $thing ? static::$true : static::$false;
2403 + return $thing ? self::$true : self::$false;
2665 2404 }
2666 2405
2667 2406 /**
2668 2407 * Compiles a primitive value into a CSS property value.
@@ -2702,11 +2441,9 @@
2702 2441 $g = round($g);
2703 2442 $b = round($b);
2704 2443
2705 2444 if (count($value) === 5 && $value[4] !== 1) { // rgba
2706 - $a = new Node\Number($value[4], '');
2707 -
2708 - return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $a . ')';
2445 + return 'rgba(' . $r . ', ' . $g . ', ' . $b . ', ' . $value[4] . ')';
2709 2446 }
2710 2447
2711 2448 $h = sprintf('#%02x%02x%02x', $r, $g, $b);
2712 2449
@@ -2717,9 +2454,9 @@
2717 2454
2718 2455 return $h;
2719 2456
2720 2457 case Type::T_NUMBER:
2721 - return $value->output($this);
2458 + return (string) $value;
2722 2459
2723 2460 case Type::T_STRING:
2724 2461 return $value[1] . $this->compileStringContent($value) . $value[1];
2725 2462
@@ -2740,9 +2477,9 @@
2740 2477 if ($delim !== ' ') {
2741 2478 $delim .= ' ';
2742 2479 }
2743 2480
2744 - $filtered = [];
2481 + $filtered = array();
2745 2482
2746 2483 foreach ($items as $item) {
2747 2484 if ($item[0] === Type::T_NULL) {
2748 2485 continue;
@@ -2755,9 +2492,9 @@
2755 2492
2756 2493 case Type::T_MAP:
2757 2494 $keys = $value[1];
2758 2495 $values = $value[2];
2759 - $filtered = [];
2496 + $filtered = array();
2760 2497
2761 2498 for ($i = 0, $s = count($keys); $i < $s; $i++) {
2762 2499 $filtered[$this->compileValue($keys[$i])] = $this->compileValue($values[$i]);
2763 2500 }
@@ -2788,47 +2525,14 @@
2788 2525 // strip quotes if it's a string
2789 2526 $reduced = $this->reduce($exp);
2790 2527
2791 2528 switch ($reduced[0]) {
2792 - case Type::T_LIST:
2793 - $reduced = $this->extractInterpolation($reduced);
2794 -
2795 - if ($reduced[0] !== Type::T_LIST) {
2796 - break;
2797 - }
2798 -
2799 - list(, $delim, $items) = $reduced;
2800 -
2801 - if ($delim !== ' ') {
2802 - $delim .= ' ';
2803 - }
2804 -
2805 - $filtered = [];
2806 -
2807 - foreach ($items as $item) {
2808 - if ($item[0] === Type::T_NULL) {
2809 - continue;
2810 - }
2811 -
2812 - $temp = $this->compileValue([Type::T_KEYWORD, $item]);
2813 - if ($temp[0] === Type::T_STRING) {
2814 - $filtered[] = $this->compileStringContent($temp);
2815 - } elseif ($temp[0] === Type::T_KEYWORD) {
2816 - $filtered[] = $temp[1];
2817 - } else {
2818 - $filtered[] = $this->compileValue($temp);
2819 - }
2820 - }
2821 -
2822 - $reduced = [Type::T_KEYWORD, implode("$delim", $filtered)];
2823 - break;
2824 -
2825 2529 case Type::T_STRING:
2826 - $reduced = [Type::T_KEYWORD, $this->compileStringContent($reduced)];
2530 + $reduced = array(Type::T_KEYWORD, $this->compileStringContent($reduced));
2827 2531 break;
2828 2532
2829 2533 case Type::T_NULL:
2830 - $reduced = [Type::T_KEYWORD, ''];
2534 + $reduced = array(Type::T_KEYWORD, '');
2831 2535 }
2832 2536
2833 2537 return $this->compileValue($reduced);
2834 2538
@@ -2860,9 +2564,9 @@
2860 2564 * @return string
2861 2565 */
2862 2566 protected function compileStringContent($string)
2863 2567 {
2864 - $parts = [];
2568 + $parts = array();
2865 2569
2866 2570 foreach ($string[2] as $part) {
2867 2571 if (is_array($part) || $part instanceof \ArrayAccess) {
2868 2572 $parts[] = $this->compileValue($part);
@@ -2886,12 +2590,12 @@
2886 2590 $items = $list[2];
2887 2591
2888 2592 foreach ($items as $i => $item) {
2889 2593 if ($item[0] === Type::T_INTERPOLATE) {
2890 - $before = [Type::T_LIST, $list[1], array_slice($items, 0, $i)];
2891 - $after = [Type::T_LIST, $list[1], array_slice($items, $i + 1)];
2594 + $before = array(Type::T_LIST, $list[1], array_slice($items, 0, $i));
2595 + $after = array(Type::T_LIST, $list[1], array_slice($items, $i + 1));
2892 2596
2893 - return [Type::T_INTERPOLATED, $item, $before, $after];
2597 + return array(Type::T_INTERPOLATED, $item, $before, $after);
2894 2598 }
2895 2599 }
2896 2600
2897 2601 return $list;
@@ -2906,10 +2610,10 @@
2906 2610 */
2907 2611 protected function multiplySelectors(Environment $env)
2908 2612 {
2909 2613 $envs = $this->compactEnv($env);
2910 - $selectors = [];
2911 - $parentSelectors = [[]];
2614 + $selectors = array();
2615 + $parentSelectors = array(array());
2912 2616
2913 2617 while ($env = array_pop($envs)) {
2914 2618 if (empty($env->selectors)) {
2915 2619 continue;
@@ -2914,9 +2618,9 @@
2914 2618 if (empty($env->selectors)) {
2915 2619 continue;
2916 2620 }
2917 2621
2918 - $selectors = [];
2622 + $selectors = array();
2919 2623
2920 2624 foreach ($env->selectors as $selector) {
2921 2625 foreach ($parentSelectors as $parent) {
2922 2626 $selectors[] = $this->joinSelectors($parent, $selector);
@@ -2939,21 +2643,21 @@
2939 2643 */
2940 2644 protected function joinSelectors($parent, $child)
2941 2645 {
2942 2646 $setSelf = false;
2943 - $out = [];
2647 + $out = array();
2944 2648
2945 2649 foreach ($child as $part) {
2946 - $newPart = [];
2650 + $newPart = array();
2947 2651
2948 2652 foreach ($part as $p) {
2949 - if ($p === static::$selfSelector) {
2653 + if ($p === self::$selfSelector) {
2950 2654 $setSelf = true;
2951 2655
2952 2656 foreach ($parent as $i => $parentPart) {
2953 2657 if ($i > 0) {
2954 2658 $out[] = $newPart;
2955 - $newPart = [];
2659 + $newPart = array();
2956 2660 }
2957 2661
2958 2662 foreach ($parentPart as $pp) {
2959 2663 $newPart[] = $pp;
@@ -2992,15 +2696,15 @@
2992 2696 }
2993 2697
2994 2698 $parentQueries = isset($env->block->queryList)
2995 2699 ? $env->block->queryList
2996 - : [[[Type::T_MEDIA_VALUE, $env->block->value]]];
2700 + : array(array(array(Type::T_MEDIA_VALUE, $env->block->value)));
2997 2701
2998 2702 if ($childQueries === null) {
2999 2703 $childQueries = $parentQueries;
3000 2704 } else {
3001 2705 $originalQueries = $childQueries;
3002 - $childQueries = [];
2706 + $childQueries = array();
3003 2707
3004 2708 foreach ($parentQueries as $parentQuery) {
3005 2709 foreach ($originalQueries as $childQuery) {
3006 2710 $childQueries []= array_merge($parentQuery, $childQuery);
@@ -3019,9 +2723,9 @@
3019 2723 * @return array
3020 2724 */
3021 2725 private function compactEnv(Environment $env)
3022 2726 {
3023 - for ($envs = []; $env; $env = $env->parent) {
2727 + for ($envs = array(); $env; $env = $env->parent) {
3024 2728 $envs[] = $env;
3025 2729 }
3026 2730
3027 2731 return $envs;
@@ -3054,9 +2758,9 @@
3054 2758 protected function pushEnv(Block $block = null)
3055 2759 {
3056 2760 $env = new Environment;
3057 2761 $env->parent = $this->env;
3058 - $env->store = [];
2762 + $env->store = array();
3059 2763 $env->block = $block;
3060 2764 $env->depth = isset($this->env->depth) ? $this->env->depth + 1 : 0;
3061 2765
3062 2766 $this->env = $env;
@@ -3163,30 +2867,22 @@
3163 2867 * @return mixed
3164 2868 */
3165 2869 public function get($name, $shouldThrow = true, Environment $env = null)
3166 2870 {
3167 - $normalizedName = $this->normalizeName($name);
3168 - $specialContentKey = static::$namespaces['special'] . 'content';
2871 + $name = $this->normalizeName($name);
3169 2872
3170 2873 if (! isset($env)) {
3171 2874 $env = $this->getStoreEnv();
3172 2875 }
3173 2876
3174 - $nextIsRoot = false;
3175 - $hasNamespace = $normalizedName[0] === '^' || $normalizedName[0] === '@' || $normalizedName[0] === '%';
2877 + $hasNamespace = $name[0] === '^' || $name[0] === '@' || $name[0] === '%';
3176 2878
3177 2879 for (;;) {
3178 - if (array_key_exists($normalizedName, $env->store)) {
3179 - return $env->store[$normalizedName];
2880 + if (array_key_exists($name, $env->store)) {
2881 + return $env->store[$name];
3180 2882 }
3181 2883
3182 2884 if (! $hasNamespace && isset($env->marker)) {
3183 - if (! $nextIsRoot && ! empty($env->store[$specialContentKey])) {
3184 - $env = $env->store[$specialContentKey]->scope;
3185 - $nextIsRoot = true;
3186 - continue;
3187 - }
3188 -
3189 2885 $env = $this->rootEnv;
3190 2886 continue;
3191 2887 }
3192 2888
@@ -3367,32 +3063,8 @@
3367 3063 $this->lineNumberStyle = $lineNumberStyle;
3368 3064 }
3369 3065
3370 3066 /**
3371 - * Enable/disable source maps
3372 - *
3373 - * @api
3374 - *
3375 - * @param integer $sourceMap
3376 - */
3377 - public function setSourceMap($sourceMap)
3378 - {
3379 - $this->sourceMap = $sourceMap;
3380 - }
3381 -
3382 - /**
3383 - * Set source map options
3384 - *
3385 - * @api
3386 - *
3387 - * @param array $sourceMapOptions
3388 - */
3389 - public function setSourceMapOptions($sourceMapOptions)
3390 - {
3391 - $this->sourceMapOptions = $sourceMapOptions;
3392 - }
3393 -
3394 - /**
3395 3067 * Register function
3396 3068 *
3397 3069 * @api
3398 3070 *
@@ -3401,9 +3073,9 @@
3401 3073 * @param array $prototype
3402 3074 */
3403 3075 public function registerFunction($name, $func, $prototype = null)
3404 3076 {
3405 - $this->userFunctions[$this->normalizeName($name)] = [$func, $prototype];
3077 + $this->userFunctions[$this->normalizeName($name)] = array($func, $prototype);
3406 3078 }
3407 3079
3408 3080 /**
3409 3081 * Unregister function
@@ -3468,18 +3140,16 @@
3468 3140 * @return string|null
3469 3141 */
3470 3142 public function findImport($url)
3471 3143 {
3472 - $urls = [];
3144 + $urls = array();
3473 3145
3474 3146 // for "normal" scss imports (ignore vanilla css and external requests)
3475 3147 if (! preg_match('/\.css$|^https?:\/\//', $url)) {
3476 3148 // try both normal and the _partial filename
3477 - $urls = [$url, preg_replace('/[^\/]+$/', '_\0', $url)];
3149 + $urls = array($url, preg_replace('/[^\/]+$/', '_\0', $url));
3478 3150 }
3479 3151
3480 - $hasExtension = preg_match('/[.]s?css$/', $url);
3481 -
3482 3152 foreach ($this->importPaths as $dir) {
3483 3153 if (is_string($dir)) {
3484 3154 // check urls for normal import paths
3485 3155 foreach ($urls as $full) {
@@ -3487,9 +3157,9 @@
3487 3157 . (! empty($dir) && substr($dir, -1) !== '/' ? '/' : '')
3488 3158 . $full;
3489 3159
3490 3160 if ($this->fileExists($file = $full . '.scss') ||
3491 - ($hasExtension && $this->fileExists($file = $full))
3161 + $this->fileExists($file = $full)
3492 3162 ) {
3493 3163 return $file;
3494 3164 }
3495 3165 }
@@ -3506,34 +3176,8 @@
3506 3176 return null;
3507 3177 }
3508 3178
3509 3179 /**
3510 - * Set encoding
3511 - *
3512 - * @api
3513 - *
3514 - * @param string $encoding
3515 - */
3516 - public function setEncoding($encoding)
3517 - {
3518 - $this->encoding = $encoding;
3519 - }
3520 -
3521 - /**
3522 - * Ignore errors?
3523 - *
3524 - * @api
3525 - *
3526 - * @param boolean $ignoreErrors
3527 - *
3528 - * @return \Leafo\ScssPhp\Compiler
3529 - */
3530 - public function setIgnoreErrors($ignoreErrors)
3531 - {
3532 - $this->ignoreErrors = $ignoreErrors;
3533 - }
3534 -
3535 - /**
3536 3180 * Throw error (exception)
3537 3181 *
3538 3182 * @api
3539 3183 *
@@ -3538,24 +3182,22 @@
3538 3182 * @api
3539 3183 *
3540 3184 * @param string $msg Message with optional sprintf()-style vararg parameters
3541 3185 *
3542 - * @throws \Leafo\ScssPhp\Exception\CompilerException
3186 + * @throws \Exception
3543 3187 */
3544 3188 public function throwError($msg)
3545 3189 {
3546 - if ($this->ignoreErrors) {
3547 - return;
3548 - }
3549 -
3550 3190 if (func_num_args() > 1) {
3551 3191 $msg = call_user_func_array('sprintf', func_get_args());
3552 3192 }
3553 3193
3554 - $line = $this->sourceLine;
3555 - $msg = "$msg: line: $line";
3194 + if ($this->sourcePos >= 0 && isset($this->sourceIndex)) {
3195 + $parser = $this->sourceParsers[$this->sourceIndex];
3196 + $parser->throwParseError($msg, $this->sourcePos);
3197 + }
3556 3198
3557 - throw new CompilerException($msg);
3199 + throw new \Exception($msg);
3558 3200 }
3559 3201
3560 3202 /**
3561 3203 * Handle import loop
@@ -3563,16 +3205,16 @@
3563 3205 * @param string $name
3564 3206 *
3565 3207 * @throws \Exception
3566 3208 */
3567 - protected function handleImportLoop($name)
3209 + private function handleImportLoop($name)
3568 3210 {
3569 3211 for ($env = $this->env; $env; $env = $env->parent) {
3570 - $file = $this->sourceNames[$env->block->sourceIndex];
3212 + $parser = $this->sourceParsers[$env->block->sourceIndex];
3213 + $file = $parser->getSourceName();
3571 3214
3572 3215 if (realpath($file) === $name) {
3573 3216 $this->throwError('An @import loop has been found: %s imports %s', $file, basename($file));
3574 - break;
3575 3217 }
3576 3218 }
3577 3219 }
3578 3220
@@ -3584,9 +3226,9 @@
3584 3226 * @return boolean
3585 3227 */
3586 3228 protected function fileExists($name)
3587 3229 {
3588 - return file_exists($name) && is_file($name);
3230 + return is_file($name);
3589 3231 }
3590 3232
3591 3233 /**
3592 3234 * Call SCSS @function
@@ -3591,9 +3233,9 @@
3591 3233 /**
3592 3234 * Call SCSS @function
3593 3235 *
3594 3236 * @param string $name
3595 - * @param array $argValues
3237 + * @param array $args
3596 3238 * @param array $returnValue
3597 3239 *
3598 3240 * @return boolean Returns true if returnValue is set; otherwise, false
3599 3241 */
@@ -3598,9 +3240,9 @@
3598 3240 * @return boolean Returns true if returnValue is set; otherwise, false
3599 3241 */
3600 3242 protected function callScssFunction($name, $argValues, &$returnValue)
3601 3243 {
3602 - $func = $this->get(static::$namespaces['function'] . $name, false);
3244 + $func = $this->get(self::$namespaces['function'] . $name, false);
3603 3245
3604 3246 if (! $func) {
3605 3247 return false;
3606 3248 }
@@ -3606,11 +3248,8 @@
3606 3248 }
3607 3249
3608 3250 $this->pushEnv();
3609 3251
3610 - $storeEnv = $this->storeEnv;
3611 - $this->storeEnv = $this->env;
3612 -
3613 3252 // set the args
3614 3253 if (isset($func->args)) {
3615 3254 $this->applyArguments($func->args, $argValues);
3616 3255 }
@@ -3616,20 +3255,18 @@
3616 3255 }
3617 3256
3618 3257 // throw away lines and children
3619 3258 $tmp = new OutputBlock;
3620 - $tmp->lines = [];
3621 - $tmp->children = [];
3259 + $tmp->lines = array();
3260 + $tmp->children = array();
3622 3261
3623 3262 $this->env->marker = 'function';
3624 3263
3625 3264 $ret = $this->compileChildren($func->children, $tmp);
3626 3265
3627 - $this->storeEnv = $storeEnv;
3628 -
3629 3266 $this->popEnv();
3630 3267
3631 - $returnValue = ! isset($ret) ? static::$defaultValue : $ret;
3268 + $returnValue = ! isset($ret) ? self::$defaultValue : $ret;
3632 3269
3633 3270 return true;
3634 3271 }
3635 3272
@@ -3651,9 +3288,9 @@
3651 3288 // see if we can find a user function
3652 3289 list($f, $prototype) = $this->userFunctions[$name];
3653 3290 } elseif (($f = $this->getBuiltinFunction($name)) && is_callable($f)) {
3654 3291 $libName = $f[1];
3655 - $prototype = isset(static::$$libName) ? static::$$libName : null;
3292 + $prototype = isset(self::$$libName) ? self::$$libName : null;
3656 3293 } else {
3657 3294 return false;
3658 3295 }
3659 3296
@@ -3692,14 +3329,16 @@
3692 3329 },
3693 3330 ucfirst($name)
3694 3331 );
3695 3332
3696 - return [$this, $libName];
3333 + return array($this, $libName);
3697 3334 }
3698 3335
3699 3336 /**
3700 3337 * Sorts keyword arguments
3701 3338 *
3339 + * @todo Merge with applyArguments()?
3340 + *
3702 3341 * @param array $prototype
3703 3342 * @param array $args
3704 3343 *
3705 3344 * @return array
@@ -3705,10 +3344,10 @@
3705 3344 * @return array
3706 3345 */
3707 3346 protected function sortArgs($prototype, $args)
3708 3347 {
3709 - $keyArgs = [];
3710 - $posArgs = [];
3348 + $keyArgs = array();
3349 + $posArgs = array();
3711 3350
3712 3351 // separate positional and keyword arguments
3713 3352 foreach ($args as $arg) {
3714 3353 list($key, $value) = $arg;
@@ -3722,9 +3361,9 @@
3722 3361 }
3723 3362 }
3724 3363
3725 3364 if (! isset($prototype)) {
3726 - return [$posArgs, $keyArgs];
3365 + return array($posArgs, $keyArgs);
3727 3366 }
3728 3367
3729 3368 // copy positional args
3730 3369 $finalArgs = array_pad($posArgs, count($prototype), null);
@@ -3737,9 +3376,9 @@
3737 3376 }
3738 3377 }
3739 3378 }
3740 3379
3741 - return [$finalArgs, $keyArgs];
3380 + return array($finalArgs, $keyArgs);
3742 3381 }
3743 3382
3744 3383 /**
3745 3384 * Apply argument values per definition
@@ -3756,20 +3395,20 @@
3756 3395 $env = new Environment;
3757 3396 $env->store = $storeEnv->store;
3758 3397
3759 3398 $hasVariable = false;
3760 - $args = [];
3399 + $args = array();
3761 3400
3762 3401 foreach ($argDef as $i => $arg) {
3763 3402 list($name, $default, $isVariable) = $argDef[$i];
3764 3403
3765 - $args[$name] = [$i, $name, $default, $isVariable];
3404 + $args[$name] = array($i, $name, $default, $isVariable);
3766 3405 $hasVariable |= $isVariable;
3767 3406 }
3768 3407
3769 - $keywordArgs = [];
3770 - $deferredKeywordArgs = [];
3771 - $remaining = [];
3408 + $keywordArgs = array();
3409 + $deferredKeywordArgs = array();
3410 + $remaining = array();
3772 3411
3773 3412 // assign the keyword args
3774 3413 foreach ((array) $argValues as $arg) {
3775 3414 if (! empty($arg[0])) {
@@ -3777,19 +3416,16 @@
3777 3416 if ($hasVariable) {
3778 3417 $deferredKeywordArgs[$arg[0][1]] = $arg[1];
3779 3418 } else {
3780 3419 $this->throwError("Mixin or function doesn't have an argument named $%s.", $arg[0][1]);
3781 - break;
3782 3420 }
3783 3421 } elseif ($args[$arg[0][1]][0] < count($remaining)) {
3784 3422 $this->throwError("The argument $%s was passed both by position and by name.", $arg[0][1]);
3785 - break;
3786 3423 } else {
3787 3424 $keywordArgs[$arg[0][1]] = $arg[1];
3788 3425 }
3789 3426 } elseif (count($keywordArgs)) {
3790 3427 $this->throwError('Positional arguments must come before keyword arguments.');
3791 - break;
3792 3428 } elseif ($arg[2] === true) {
3793 3429 $val = $this->reduce($arg[1], true);
3794 3430
3795 3431 if ($val[0] === Type::T_LIST) {
@@ -3822,9 +3458,9 @@
3822 3458 foreach ($args as $arg) {
3823 3459 list($i, $name, $default, $isVariable) = $arg;
3824 3460
3825 3461 if ($isVariable) {
3826 - $val = [Type::T_LIST, ',', [], $isVariable];
3462 + $val = array(Type::T_LIST, ',', array(), $isVariable);
3827 3463
3828 3464 for ($count = count($remaining); $i < $count; $i++) {
3829 3465 $val[2][] = $remaining[$i];
3830 3466 }
@@ -3839,9 +3475,8 @@
3839 3475 } elseif (! empty($default)) {
3840 3476 continue;
3841 3477 } else {
3842 3478 $this->throwError("Missing argument $name");
3843 - break;
3844 3479 }
3845 3480
3846 3481 $this->set($name, $this->reduce($val, true), true, $env);
3847 3482 }
@@ -3863,9 +3498,9 @@
3863 3498 * Coerce a php value into a scss one
3864 3499 *
3865 3500 * @param mixed $value
3866 3501 *
3867 - * @return array|\Leafo\ScssPhp\Node\Number
3502 + * @return array
3868 3503 */
3869 3504 private function coerceValue($value)
3870 3505 {
3871 3506 if (is_array($value) || $value instanceof \ArrayAccess) {
@@ -3876,9 +3511,9 @@
3876 3511 return $this->toBool($value);
3877 3512 }
3878 3513
3879 3514 if ($value === null) {
3880 - return static::$null;
3515 + $value = self::$null;
3881 3516 }
3882 3517
3883 3518 if (is_numeric($value)) {
3884 3519 return new Node\Number($value, '');
@@ -3884,35 +3519,12 @@
3884 3519 return new Node\Number($value, '');
3885 3520 }
3886 3521
3887 3522 if ($value === '') {
3888 - return static::$emptyString;
3523 + return self::$emptyString;
3889 3524 }
3890 3525
3891 - if (preg_match('/^(#([0-9a-f]{6})|#([0-9a-f]{3}))$/i', $value, $m)) {
3892 - $color = [Type::T_COLOR];
3893 -
3894 - if (isset($m[3])) {
3895 - $num = hexdec($m[3]);
3896 -
3897 - foreach ([3, 2, 1] as $i) {
3898 - $t = $num & 0xf;
3899 - $color[$i] = $t << 4 | $t;
3900 - $num >>= 4;
3901 - }
3902 - } else {
3903 - $num = hexdec($m[2]);
3904 -
3905 - foreach ([3, 2, 1] as $i) {
3906 - $color[$i] = $num & 0xff;
3907 - $num >>= 8;
3908 - }
3909 - }
3910 -
3911 - return $color;
3912 - }
3913 -
3914 - return [Type::T_KEYWORD, $value];
3526 + return array(Type::T_KEYWORD, $value);
3915 3527 }
3916 3528
3917 3529 /**
3918 3530 * Coerce something to map
@@ -3926,20 +3538,19 @@
3926 3538 if ($item[0] === Type::T_MAP) {
3927 3539 return $item;
3928 3540 }
3929 3541
3930 - if ($item === static::$emptyList) {
3931 - return static::$emptyMap;
3542 + if ($item === self::$emptyList) {
3543 + return self::$emptyMap;
3932 3544 }
3933 3545
3934 - return [Type::T_MAP, [$item], [static::$null]];
3546 + return array(Type::T_MAP, array($item), array(self::$null));
3935 3547 }
3936 3548
3937 3549 /**
3938 3550 * Coerce something to list
3939 3551 *
3940 - * @param array $item
3941 - * @param string $delim
3552 + * @param array $item
3942 3553 *
3943 3554 * @return array
3944 3555 */
3945 3556 protected function coerceList($item, $delim = ',')
@@ -3950,25 +3561,25 @@
3950 3561
3951 3562 if (isset($item) && $item[0] === Type::T_MAP) {
3952 3563 $keys = $item[1];
3953 3564 $values = $item[2];
3954 - $list = [];
3565 + $list = array();
3955 3566
3956 3567 for ($i = 0, $s = count($keys); $i < $s; $i++) {
3957 3568 $key = $keys[$i];
3958 3569 $value = $values[$i];
3959 3570
3960 - $list[] = [
3571 + $list[] = array(
3961 3572 Type::T_LIST,
3962 3573 '',
3963 - [[Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))], $value]
3964 - ];
3574 + array(array(Type::T_KEYWORD, $this->compileStringContent($this->coerceString($key))), $value)
3575 + );
3965 3576 }
3966 3577
3967 - return [Type::T_LIST, ',', $list];
3578 + return array(Type::T_LIST, ',', $list);
3968 3579 }
3969 3580
3970 - return [Type::T_LIST, $delim, ! isset($item) ? []: [$item]];
3581 + return array(Type::T_LIST, $delim, ! isset($item) ? array(): array($item));
3971 3582 }
3972 3583
3973 3584 /**
3974 3585 * Coerce color for expression
@@ -4005,10 +3616,10 @@
4005 3616 if (isset(Colors::$cssColors[$name])) {
4006 3617 $rgba = explode(',', Colors::$cssColors[$name]);
4007 3618
4008 3619 return isset($rgba[3])
4009 - ? [Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3]]
4010 - : [Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]];
3620 + ? array(Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2], (int) $rgba[3])
3621 + : array(Type::T_COLOR, (int) $rgba[0], (int) $rgba[1], (int) $rgba[2]);
4011 3622 }
4012 3623
4013 3624 return null;
4014 3625 }
@@ -4028,9 +3639,9 @@
4028 3639 if ($value[0] === Type::T_STRING) {
4029 3640 return $value;
4030 3641 }
4031 3642
4032 - return [Type::T_STRING, '', [$this->compileValue($value)]];
3643 + return array(Type::T_STRING, '', array($this->compileValue($value)));
4033 3644 }
4034 3645
4035 3646 /**
4036 3647 * Coerce value to a percentage
@@ -4041,9 +3652,9 @@
4041 3652 */
4042 3653 protected function coercePercent($value)
4043 3654 {
4044 3655 if ($value[0] === Type::T_NUMBER) {
4045 - if (! empty($value[2]['%'])) {
3656 + if ($value[2] === '%') {
4046 3657 return $value[1] / 100;
4047 3658 }
4048 3659
4049 3660 return $value[1];
@@ -4142,9 +3753,9 @@
4142 3753 * @return array
4143 3754 */
4144 3755 protected function fixColor($c)
4145 3756 {
4146 - foreach ([1, 2, 3] as $i) {
3757 + foreach (array(1, 2, 3) as $i) {
4147 3758 if ($c[$i] < 0) {
4148 3759 $c[$i] = 0;
4149 3760 }
4150 3761
@@ -4192,9 +3803,9 @@
4192 3803 $h = 60 * ($red - $green) / $d + 240;
4193 3804 }
4194 3805 }
4195 3806
4196 - return [Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1];
3807 + return array(Type::T_HSL, fmod($h, 360), $s * 100, $l / 5.1);
4197 3808 }
4198 3809
4199 3810 /**
4200 3811 * Hue to RGB helper
@@ -4255,9 +3866,9 @@
4255 3866 $r = $this->hueToRGB($m1, $m2, $h + 1/3) * 255;
4256 3867 $g = $this->hueToRGB($m1, $m2, $h) * 255;
4257 3868 $b = $this->hueToRGB($m1, $m2, $h - 1/3) * 255;
4258 3869
4259 - $out = [Type::T_COLOR, $r, $g, $b];
3870 + $out = array(Type::T_COLOR, $r, $g, $b);
4260 3871
4261 3872 return $out;
4262 3873 }
4263 3874
@@ -4262,9 +3873,9 @@
4262 3873 }
4263 3874
4264 3875 // Built in functions
4265 3876
4266 - //protected static $libCall = ['name', 'args...'];
3877 + //protected static $libCall = array('name', 'args...');
4267 3878 protected function libCall($args, $kwargs)
4268 3879 {
4269 3880 $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
4270 3881
@@ -4269,9 +3880,9 @@
4269 3880 $name = $this->compileStringContent($this->coerceString($this->reduce(array_shift($args), true)));
4270 3881
4271 3882 $args = array_map(
4272 3883 function ($a) {
4273 - return [null, $a, false];
3884 + return array(null, $a, false);
4274 3885 },
4275 3886 $args
4276 3887 );
4277 3888
@@ -4276,16 +3887,16 @@
4276 3887 );
4277 3888
4278 3889 if (count($kwargs)) {
4279 3890 foreach ($kwargs as $key => $value) {
4280 - $args[] = [[Type::T_VARIABLE, $key], $value, false];
3891 + $args[] = array(array(Type::T_VARIABLE, $key), $value, false);
4281 3892 }
4282 3893 }
4283 3894
4284 - return $this->reduce([Type::T_FUNCTION_CALL, $name, $args]);
3895 + return $this->reduce(array(Type::T_FUNCTION_CALL, $name, $args));
4285 3896 }
4286 3897
4287 - protected static $libIf = ['condition', 'if-true', 'if-false'];
3898 + protected static $libIf = array('condition', 'if-true', 'if-false');
4288 3899 protected function libIf($args)
4289 3900 {
4290 3901 list($cond, $t, $f) = $args;
4291 3902
@@ -4295,15 +3906,15 @@
4295 3906
4296 3907 return $this->reduce($t, true);
4297 3908 }
4298 3909
4299 - protected static $libIndex = ['list', 'value'];
3910 + protected static $libIndex = array('list', 'value');
4300 3911 protected function libIndex($args)
4301 3912 {
4302 3913 list($list, $value) = $args;
4303 3914
4304 3915 if ($value[0] === Type::T_MAP) {
4305 - return static::$null;
3916 + return self::$null;
4306 3917 }
4307 3918
4308 3919 if ($list[0] === Type::T_MAP ||
4309 3920 $list[0] === Type::T_STRING ||
@@ -4313,12 +3924,12 @@
4313 3924 $list = $this->coerceList($list, ' ');
4314 3925 }
4315 3926
4316 3927 if ($list[0] !== Type::T_LIST) {
4317 - return static::$null;
3928 + return self::$null;
4318 3929 }
4319 3930
4320 - $values = [];
3931 + $values = array();
4321 3932
4322 3933 foreach ($list[2] as $item) {
4323 3934 $values[] = $this->normalizeValue($item);
4324 3935 }
@@ -4324,26 +3935,29 @@
4324 3935 }
4325 3936
4326 3937 $key = array_search($this->normalizeValue($value), $values);
4327 3938
4328 - return false === $key ? static::$null : $key + 1;
3939 + return false === $key ? self::$null : $key + 1;
4329 3940 }
4330 3941
4331 - protected static $libRgb = ['red', 'green', 'blue'];
3942 + protected static $libRgb = array('red', 'green', 'blue');
4332 3943 protected function libRgb($args)
4333 3944 {
4334 3945 list($r, $g, $b) = $args;
4335 3946
4336 - return [Type::T_COLOR, $r[1], $g[1], $b[1]];
3947 + return array(Type::T_COLOR, $r[1], $g[1], $b[1]);
4337 3948 }
4338 3949
4339 - protected static $libRgba = [
4340 - ['red', 'color'],
4341 - 'green', 'blue', 'alpha'];
3950 + protected static $libRgba = array(
3951 + array('red', 'color'),
3952 + 'green', 'blue', 'alpha');
4342 3953 protected function libRgba($args)
4343 3954 {
4344 3955 if ($color = $this->coerceColor($args[0])) {
4345 - $num = isset($args[3]) ? $args[3] : $args[1];
3956 + // workaround https://github.com/facebook/hhvm/issues/5457
3957 + reset($args);
3958 +
3959 + $num = ! isset($args[1]) ? $args[3] : $args[1];
4346 3960 $alpha = $this->assertNumber($num);
4347 3961 $color[4] = $alpha;
4348 3962
4349 3963 return $color;
@@ -4350,9 +3964,9 @@
4350 3964 }
4351 3965
4352 3966 list($r, $g, $b, $a) = $args;
4353 3967
4354 - return [Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]];
3968 + return array(Type::T_COLOR, $r[1], $g[1], $b[1], $a[1]);
4355 3969 }
4356 3970
4357 3971 // helper function for adjust_color, change_color, and scale_color
4358 3972 protected function alterColor($args, $fn)
@@ -4358,9 +3972,12 @@
4358 3972 protected function alterColor($args, $fn)
4359 3973 {
4360 3974 $color = $this->assertColor($args[0]);
4361 3975
4362 - foreach ([1, 2, 3, 7] as $i) {
3976 + // workaround https://github.com/facebook/hhvm/issues/5457
3977 + reset($args);
3978 +
3979 + foreach (array(1, 2, 3, 7) as $i) {
4363 3980 if (isset($args[$i])) {
4364 3981 $val = $this->assertNumber($args[$i]);
4365 3982 $ii = $i === 7 ? 4 : $i; // alpha
4366 3983 $color[$ii] = call_user_func($fn, isset($color[$ii]) ? $color[$ii] : 0, $val, $i);
@@ -4369,9 +3986,9 @@
4369 3986
4370 3987 if (isset($args[4]) || isset($args[5]) || isset($args[6])) {
4371 3988 $hsl = $this->toHSL($color[1], $color[2], $color[3]);
4372 3989
4373 - foreach ([4, 5, 6] as $i) {
3990 + foreach (array(4, 5, 6) as $i) {
4374 3991 if (isset($args[$i])) {
4375 3992 $val = $this->assertNumber($args[$i]);
4376 3993 $hsl[$i - 3] = call_user_func($fn, $hsl[$i - 3], $val, $i);
4377 3994 }
@@ -4388,12 +4005,12 @@
4388 4005
4389 4006 return $color;
4390 4007 }
4391 4008
4392 - protected static $libAdjustColor = [
4009 + protected static $libAdjustColor = array(
4393 4010 'color', 'red', 'green', 'blue',
4394 4011 'hue', 'saturation', 'lightness', 'alpha'
4395 - ];
4012 + );
4396 4013 protected function libAdjustColor($args)
4397 4014 {
4398 4015 return $this->alterColor($args, function ($base, $alter, $i) {
4399 4016 return $base + $alter;
@@ -4399,12 +4016,12 @@
4399 4016 return $base + $alter;
4400 4017 });
4401 4018 }
4402 4019
4403 - protected static $libChangeColor = [
4020 + protected static $libChangeColor = array(
4404 4021 'color', 'red', 'green', 'blue',
4405 4022 'hue', 'saturation', 'lightness', 'alpha'
4406 - ];
4023 + );
4407 4024 protected function libChangeColor($args)
4408 4025 {
4409 4026 return $this->alterColor($args, function ($base, $alter, $i) {
4410 4027 return $alter;
@@ -4410,12 +4027,12 @@
4410 4027 return $alter;
4411 4028 });
4412 4029 }
4413 4030
4414 - protected static $libScaleColor = [
4031 + protected static $libScaleColor = array(
4415 4032 'color', 'red', 'green', 'blue',
4416 4033 'hue', 'saturation', 'lightness', 'alpha'
4417 - ];
4034 + );
4418 4035 protected function libScaleColor($args)
4419 4036 {
4420 4037 return $this->alterColor($args, function ($base, $scale, $i) {
4421 4038 // 1, 2, 3 - rgb
@@ -4449,18 +4066,18 @@
4449 4066 return ($max - $base) * $scale + $base;
4450 4067 });
4451 4068 }
4452 4069
4453 - protected static $libIeHexStr = ['color'];
4070 + protected static $libIeHexStr = array('color');
4454 4071 protected function libIeHexStr($args)
4455 4072 {
4456 4073 $color = $this->coerceColor($args[0]);
4457 - $color[4] = isset($color[4]) ? round(255 * $color[4]) : 255;
4074 + $color[4] = isset($color[4]) ? round(255*$color[4]) : 255;
4458 4075
4459 4076 return sprintf('#%02X%02X%02X%02X', $color[4], $color[1], $color[2], $color[3]);
4460 4077 }
4461 4078
4462 - protected static $libRed = ['color'];
4079 + protected static $libRed = array('color');
4463 4080 protected function libRed($args)
4464 4081 {
4465 4082 $color = $this->coerceColor($args[0]);
4466 4083
@@ -4466,9 +4083,9 @@
4466 4083
4467 4084 return $color[1];
4468 4085 }
4469 4086
4470 - protected static $libGreen = ['color'];
4087 + protected static $libGreen = array('color');
4471 4088 protected function libGreen($args)
4472 4089 {
4473 4090 $color = $this->coerceColor($args[0]);
4474 4091
@@ -4474,9 +4091,9 @@
4474 4091
4475 4092 return $color[2];
4476 4093 }
4477 4094
4478 - protected static $libBlue = ['color'];
4095 + protected static $libBlue = array('color');
4479 4096 protected function libBlue($args)
4480 4097 {
4481 4098 $color = $this->coerceColor($args[0]);
4482 4099
@@ -4482,9 +4099,9 @@
4482 4099
4483 4100 return $color[3];
4484 4101 }
4485 4102
4486 - protected static $libAlpha = ['color'];
4103 + protected static $libAlpha = array('color');
4487 4104 protected function libAlpha($args)
4488 4105 {
4489 4106 if ($color = $this->coerceColor($args[0])) {
4490 4107 return isset($color[4]) ? $color[4] : 1;
@@ -4493,9 +4110,9 @@
4493 4110 // this might be the IE function, so return value unchanged
4494 4111 return null;
4495 4112 }
4496 4113
4497 - protected static $libOpacity = ['color'];
4114 + protected static $libOpacity = array('color');
4498 4115 protected function libOpacity($args)
4499 4116 {
4500 4117 $value = $args[0];
4501 4118
@@ -4506,9 +4123,9 @@
4506 4123 return $this->libAlpha($args);
4507 4124 }
4508 4125
4509 4126 // mix two colors
4510 - protected static $libMix = ['color-1', 'color-2', 'weight'];
4127 + protected static $libMix = array('color-1', 'color-2', 'weight');
4511 4128 protected function libMix($args)
4512 4129 {
4513 4130 list($first, $second, $weight) = $args;
4514 4131
@@ -4529,22 +4146,22 @@
4529 4146
4530 4147 $w1 = (($w * $a === -1 ? $w : ($w + $a) / (1 + $w * $a)) + 1) / 2.0;
4531 4148 $w2 = 1.0 - $w1;
4532 4149
4533 - $new = [Type::T_COLOR,
4150 + $new = array(Type::T_COLOR,
4534 4151 $w1 * $first[1] + $w2 * $second[1],
4535 4152 $w1 * $first[2] + $w2 * $second[2],
4536 4153 $w1 * $first[3] + $w2 * $second[3],
4537 - ];
4154 + );
4538 4155
4539 4156 if ($firstAlpha != 1.0 || $secondAlpha != 1.0) {
4540 - $new[] = $firstAlpha * $weight + $secondAlpha * (1 - $weight);
4157 + $new[] = $firstAlpha * $weight + $secondAlpha * ($weight - 1);
4541 4158 }
4542 4159
4543 4160 return $this->fixColor($new);
4544 4161 }
4545 4162
4546 - protected static $libHsl = ['hue', 'saturation', 'lightness'];
4163 + protected static $libHsl = array('hue', 'saturation', 'lightness');
4547 4164 protected function libHsl($args)
4548 4165 {
4549 4166 list($h, $s, $l) = $args;
4550 4167
@@ -4550,9 +4167,9 @@
4550 4167
4551 4168 return $this->toRGB($h[1], $s[1], $l[1]);
4552 4169 }
4553 4170
4554 - protected static $libHsla = ['hue', 'saturation', 'lightness', 'alpha'];
4171 + protected static $libHsla = array('hue', 'saturation', 'lightness', 'alpha');
4555 4172 protected function libHsla($args)
4556 4173 {
4557 4174 list($h, $s, $l, $a) = $args;
4558 4175
@@ -4561,9 +4178,9 @@
4561 4178
4562 4179 return $color;
4563 4180 }
4564 4181
4565 - protected static $libHue = ['color'];
4182 + protected static $libHue = array('color');
4566 4183 protected function libHue($args)
4567 4184 {
4568 4185 $color = $this->assertColor($args[0]);
4569 4186 $hsl = $this->toHSL($color[1], $color[2], $color[3]);
@@ -4570,9 +4187,9 @@
4570 4187
4571 4188 return new Node\Number($hsl[1], 'deg');
4572 4189 }
4573 4190
4574 - protected static $libSaturation = ['color'];
4191 + protected static $libSaturation = array('color');
4575 4192 protected function libSaturation($args)
4576 4193 {
4577 4194 $color = $this->assertColor($args[0]);
4578 4195 $hsl = $this->toHSL($color[1], $color[2], $color[3]);
@@ -4579,9 +4196,9 @@
4579 4196
4580 4197 return new Node\Number($hsl[2], '%');
4581 4198 }
4582 4199
4583 - protected static $libLightness = ['color'];
4200 + protected static $libLightness = array('color');
4584 4201 protected function libLightness($args)
4585 4202 {
4586 4203 $color = $this->assertColor($args[0]);
4587 4204 $hsl = $this->toHSL($color[1], $color[2], $color[3]);
@@ -4601,9 +4218,9 @@
4601 4218
4602 4219 return $out;
4603 4220 }
4604 4221
4605 - protected static $libAdjustHue = ['color', 'degrees'];
4222 + protected static $libAdjustHue = array('color', 'degrees');
4606 4223 protected function libAdjustHue($args)
4607 4224 {
4608 4225 $color = $this->assertColor($args[0]);
4609 4226 $degrees = $this->assertNumber($args[1]);
@@ -4610,9 +4227,9 @@
4610 4227
4611 4228 return $this->adjustHsl($color, 1, $degrees);
4612 4229 }
4613 4230
4614 - protected static $libLighten = ['color', 'amount'];
4231 + protected static $libLighten = array('color', 'amount');
4615 4232 protected function libLighten($args)
4616 4233 {
4617 4234 $color = $this->assertColor($args[0]);
4618 4235 $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%');
@@ -4619,9 +4236,9 @@
4619 4236
4620 4237 return $this->adjustHsl($color, 3, $amount);
4621 4238 }
4622 4239
4623 - protected static $libDarken = ['color', 'amount'];
4240 + protected static $libDarken = array('color', 'amount');
4624 4241 protected function libDarken($args)
4625 4242 {
4626 4243 $color = $this->assertColor($args[0]);
4627 4244 $amount = Util::checkRange('amount', new Range(0, 100), $args[1], '%');
@@ -4628,9 +4245,9 @@
4628 4245
4629 4246 return $this->adjustHsl($color, 3, -$amount);
4630 4247 }
4631 4248
4632 - protected static $libSaturate = ['color', 'amount'];
4249 + protected static $libSaturate = array('color', 'amount');
4633 4250 protected function libSaturate($args)
4634 4251 {
4635 4252 $value = $args[0];
4636 4253
@@ -4643,9 +4260,9 @@
4643 4260
4644 4261 return $this->adjustHsl($color, 2, $amount);
4645 4262 }
4646 4263
4647 - protected static $libDesaturate = ['color', 'amount'];
4264 + protected static $libDesaturate = array('color', 'amount');
4648 4265 protected function libDesaturate($args)
4649 4266 {
4650 4267 $color = $this->assertColor($args[0]);
4651 4268 $amount = 100 * $this->coercePercent($args[1]);
@@ -4652,9 +4269,9 @@
4652 4269
4653 4270 return $this->adjustHsl($color, 2, -$amount);
4654 4271 }
4655 4272
4656 - protected static $libGrayscale = ['color'];
4273 + protected static $libGrayscale = array('color');
4657 4274 protected function libGrayscale($args)
4658 4275 {
4659 4276 $value = $args[0];
4660 4277
@@ -4664,15 +4281,15 @@
4664 4281
4665 4282 return $this->adjustHsl($this->assertColor($value), 2, -100);
4666 4283 }
4667 4284
4668 - protected static $libComplement = ['color'];
4285 + protected static $libComplement = array('color');
4669 4286 protected function libComplement($args)
4670 4287 {
4671 4288 return $this->adjustHsl($this->assertColor($args[0]), 1, 180);
4672 4289 }
4673 4290
4674 - protected static $libInvert = ['color'];
4291 + protected static $libInvert = array('color');
4675 4292 protected function libInvert($args)
4676 4293 {
4677 4294 $value = $args[0];
4678 4295
@@ -4688,9 +4305,9 @@
4688 4305 return $color;
4689 4306 }
4690 4307
4691 4308 // increases opacity by amount
4692 - protected static $libOpacify = ['color', 'amount'];
4309 + protected static $libOpacify = array('color', 'amount');
4693 4310 protected function libOpacify($args)
4694 4311 {
4695 4312 $color = $this->assertColor($args[0]);
4696 4313 $amount = $this->coercePercent($args[1]);
@@ -4700,9 +4317,9 @@
4700 4317
4701 4318 return $color;
4702 4319 }
4703 4320
4704 - protected static $libFadeIn = ['color', 'amount'];
4321 + protected static $libFadeIn = array('color', 'amount');
4705 4322 protected function libFadeIn($args)
4706 4323 {
4707 4324 return $this->libOpacify($args);
4708 4325 }
@@ -4707,9 +4324,9 @@
4707 4324 return $this->libOpacify($args);
4708 4325 }
4709 4326
4710 4327 // decreases opacity by amount
4711 - protected static $libTransparentize = ['color', 'amount'];
4328 + protected static $libTransparentize = array('color', 'amount');
4712 4329 protected function libTransparentize($args)
4713 4330 {
4714 4331 $color = $this->assertColor($args[0]);
4715 4332 $amount = $this->coercePercent($args[1]);
@@ -4719,15 +4336,15 @@
4719 4336
4720 4337 return $color;
4721 4338 }
4722 4339
4723 - protected static $libFadeOut = ['color', 'amount'];
4340 + protected static $libFadeOut = array('color', 'amount');
4724 4341 protected function libFadeOut($args)
4725 4342 {
4726 4343 return $this->libTransparentize($args);
4727 4344 }
4728 4345
4729 - protected static $libUnquote = ['string'];
4346 + protected static $libUnquote = array('string');
4730 4347 protected function libUnquote($args)
4731 4348 {
4732 4349 $str = $args[0];
4733 4350
@@ -4737,9 +4354,9 @@
4737 4354
4738 4355 return $str;
4739 4356 }
4740 4357
4741 - protected static $libQuote = ['string'];
4358 + protected static $libQuote = array('string');
4742 4359 protected function libQuote($args)
4743 4360 {
4744 4361 $value = $args[0];
4745 4362
@@ -4746,47 +4363,51 @@
4746 4363 if ($value[0] === Type::T_STRING && ! empty($value[1])) {
4747 4364 return $value;
4748 4365 }
4749 4366
4750 - return [Type::T_STRING, '"', [$value]];
4367 + return array(Type::T_STRING, '"', array($value));
4751 4368 }
4752 4369
4753 - protected static $libPercentage = ['value'];
4370 + protected static $libPercentage = array('value');
4754 4371 protected function libPercentage($args)
4755 4372 {
4756 4373 return new Node\Number($this->coercePercent($args[0]) * 100, '%');
4757 4374 }
4758 4375
4759 - protected static $libRound = ['value'];
4376 + protected static $libRound = array('value');
4760 4377 protected function libRound($args)
4761 4378 {
4762 4379 $num = $args[0];
4380 + $num[1] = round($num[1]);
4763 4381
4764 - return new Node\Number(round($num[1]), $num[2]);
4382 + return $num;
4765 4383 }
4766 4384
4767 - protected static $libFloor = ['value'];
4385 + protected static $libFloor = array('value');
4768 4386 protected function libFloor($args)
4769 4387 {
4770 4388 $num = $args[0];
4389 + $num[1] = floor($num[1]);
4771 4390
4772 - return new Node\Number(floor($num[1]), $num[2]);
4391 + return $num;
4773 4392 }
4774 4393
4775 - protected static $libCeil = ['value'];
4394 + protected static $libCeil = array('value');
4776 4395 protected function libCeil($args)
4777 4396 {
4778 4397 $num = $args[0];
4398 + $num[1] = ceil($num[1]);
4779 4399
4780 - return new Node\Number(ceil($num[1]), $num[2]);
4400 + return $num;
4781 4401 }
4782 4402
4783 - protected static $libAbs = ['value'];
4403 + protected static $libAbs = array('value');
4784 4404 protected function libAbs($args)
4785 4405 {
4786 4406 $num = $args[0];
4407 + $num[1] = abs($num[1]);
4787 4408
4788 - return new Node\Number(abs($num[1]), $num[2]);
4409 + return $num;
4789 4410 }
4790 4411
4791 4412 protected function libMin($args)
4792 4413 {
@@ -4794,9 +4415,9 @@
4794 4415 $min = null;
4795 4416
4796 4417 foreach ($numbers as $key => $number) {
4797 4418 if (null === $min || $number[1] <= $min[1]) {
4798 - $min = [$key, $number[1]];
4419 + $min = array($key, $number[1]);
4799 4420 }
4800 4421 }
4801 4422
4802 4423 return $args[$min[0]];
@@ -4808,9 +4429,9 @@
4808 4429 $max = null;
4809 4430
4810 4431 foreach ($numbers as $key => $number) {
4811 4432 if (null === $max || $number[1] >= $max[1]) {
4812 - $max = [$key, $number[1]];
4433 + $max = array($key, $number[1]);
4813 4434 }
4814 4435 }
4815 4436
4816 4437 return $args[$max[0]];
@@ -4826,14 +4447,13 @@
4826 4447 protected function getNormalizedNumbers($args)
4827 4448 {
4828 4449 $unit = null;
4829 4450 $originalUnit = null;
4830 - $numbers = [];
4451 + $numbers = array();
4831 4452
4832 4453 foreach ($args as $key => $item) {
4833 4454 if ($item[0] !== Type::T_NUMBER) {
4834 4455 $this->throwError('%s is not a number', $item[0]);
4835 - break;
4836 4456 }
4837 4457
4838 4458 $number = $item->normalize();
4839 4459
@@ -4841,9 +4461,8 @@
4841 4461 $unit = $number[2];
4842 4462 $originalUnit = $item->unitStr();
4843 4463 } elseif ($unit !== $number[2]) {
4844 4464 $this->throwError('Incompatible units: "%s" and "%s".', $originalUnit, $item->unitStr());
4845 - break;
4846 4465 }
4847 4466
4848 4467 $numbers[$key] = $number;
4849 4468 }
@@ -4850,9 +4469,9 @@
4850 4469
4851 4470 return $numbers;
4852 4471 }
4853 4472
4854 - protected static $libLength = ['list'];
4473 + protected static $libLength = array('list');
4855 4474 protected function libLength($args)
4856 4475 {
4857 4476 $list = $this->coerceList($args[0]);
4858 4477
@@ -4858,9 +4477,10 @@
4858 4477
4859 4478 return count($list[2]);
4860 4479 }
4861 4480
4862 - //protected static $libListSeparator = ['list...'];
4481 + // TODO: need a way to declare this built-in as varargs
4482 + //protected static $libListSeparator = array('list...');
4863 4483 protected function libListSeparator($args)
4864 4484 {
4865 4485 if (count($args) > 1) {
4866 4486 return 'comma';
@@ -4878,9 +4498,9 @@
4878 4498
4879 4499 return 'space';
4880 4500 }
4881 4501
4882 - protected static $libNth = ['list', 'n'];
4502 + protected static $libNth = array('list', 'n');
4883 4503 protected function libNth($args)
4884 4504 {
4885 4505 $list = $this->coerceList($args[0]);
4886 4506 $n = $this->assertNumber($args[1]);
@@ -4890,12 +4510,12 @@
4890 4510 } elseif ($n < 0) {
4891 4511 $n += count($list[2]);
4892 4512 }
4893 4513
4894 - return isset($list[2][$n]) ? $list[2][$n] : static::$defaultValue;
4514 + return isset($list[2][$n]) ? $list[2][$n] : self::$defaultValue;
4895 4515 }
4896 4516
4897 - protected static $libSetNth = ['list', 'n', 'value'];
4517 + protected static $libSetNth = array('list', 'n', 'value');
4898 4518 protected function libSetNth($args)
4899 4519 {
4900 4520 $list = $this->coerceList($args[0]);
4901 4521 $n = $this->assertNumber($args[1]);
@@ -4907,10 +4527,8 @@
4907 4527 }
4908 4528
4909 4529 if (! isset($list[2][$n])) {
4910 4530 $this->throwError('Invalid argument for "n"');
4911 -
4912 - return;
4913 4531 }
4914 4532
4915 4533 $list[2][$n] = $args[2];
4916 4534
@@ -4916,9 +4534,9 @@
4916 4534
4917 4535 return $list;
4918 4536 }
4919 4537
4920 - protected static $libMapGet = ['map', 'key'];
4538 + protected static $libMapGet = array('map', 'key');
4921 4539 protected function libMapGet($args)
4922 4540 {
4923 4541 $map = $this->assertMap($args[0]);
4924 4542 $key = $this->compileStringContent($this->coerceString($args[1]));
@@ -4928,30 +4546,30 @@
4928 4546 return $map[2][$i];
4929 4547 }
4930 4548 }
4931 4549
4932 - return static::$null;
4550 + return self::$null;
4933 4551 }
4934 4552
4935 - protected static $libMapKeys = ['map'];
4553 + protected static $libMapKeys = array('map');
4936 4554 protected function libMapKeys($args)
4937 4555 {
4938 4556 $map = $this->assertMap($args[0]);
4939 4557 $keys = $map[1];
4940 4558
4941 - return [Type::T_LIST, ',', $keys];
4559 + return array(Type::T_LIST, ',', $keys);
4942 4560 }
4943 4561
4944 - protected static $libMapValues = ['map'];
4562 + protected static $libMapValues = array('map');
4945 4563 protected function libMapValues($args)
4946 4564 {
4947 4565 $map = $this->assertMap($args[0]);
4948 4566 $values = $map[2];
4949 4567
4950 - return [Type::T_LIST, ',', $values];
4568 + return array(Type::T_LIST, ',', $values);
4951 4569 }
4952 4570
4953 - protected static $libMapRemove = ['map', 'key'];
4571 + protected static $libMapRemove = array('map', 'key');
4954 4572 protected function libMapRemove($args)
4955 4573 {
4956 4574 $map = $this->assertMap($args[0]);
4957 4575 $key = $this->compileStringContent($this->coerceString($args[1]));
@@ -4965,9 +4583,9 @@
4965 4583
4966 4584 return $map;
4967 4585 }
4968 4586
4969 - protected static $libMapHasKey = ['map', 'key'];
4587 + protected static $libMapHasKey = array('map', 'key');
4970 4588 protected function libMapHasKey($args)
4971 4589 {
4972 4590 $map = $this->assertMap($args[0]);
4973 4591 $key = $this->compileStringContent($this->coerceString($args[1]));
@@ -4980,33 +4598,17 @@
4980 4598
4981 4599 return false;
4982 4600 }
4983 4601
4984 - protected static $libMapMerge = ['map-1', 'map-2'];
4602 + protected static $libMapMerge = array('map-1', 'map-2');
4985 4603 protected function libMapMerge($args)
4986 4604 {
4987 4605 $map1 = $this->assertMap($args[0]);
4988 4606 $map2 = $this->assertMap($args[1]);
4989 4607
4990 - return [Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2])];
4608 + return array(Type::T_MAP, array_merge($map1[1], $map2[1]), array_merge($map1[2], $map2[2]));
4991 4609 }
4992 4610
4993 - protected static $libKeywords = ['args'];
4994 - protected function libKeywords($args)
4995 - {
4996 - $this->assertList($args[0]);
4997 -
4998 - $keys = [];
4999 - $values = [];
5000 -
5001 - foreach ($args[0][2] as $name => $arg) {
5002 - $keys[] = [Type::T_KEYWORD, $name];
5003 - $values[] = $arg;
5004 - }
5005 -
5006 - return [Type::T_MAP, $keys, $values];
5007 - }
5008 -
5009 4611 protected function listSeparatorForJoin($list1, $sep)
5010 4612 {
5011 4613 if (! isset($sep)) {
5012 4614 return $list1[1];
@@ -5023,9 +4625,9 @@
5023 4625 return $list1[1];
5024 4626 }
5025 4627 }
5026 4628
5027 - protected static $libJoin = ['list1', 'list2', 'separator'];
4629 + protected static $libJoin = array('list1', 'list2', 'separator');
5028 4630 protected function libJoin($args)
5029 4631 {
5030 4632 list($list1, $list2, $sep) = $args;
5031 4633
@@ -5032,12 +4634,12 @@
5032 4634 $list1 = $this->coerceList($list1, ' ');
5033 4635 $list2 = $this->coerceList($list2, ' ');
5034 4636 $sep = $this->listSeparatorForJoin($list1, $sep);
5035 4637
5036 - return [Type::T_LIST, $sep, array_merge($list1[2], $list2[2])];
4638 + return array(Type::T_LIST, $sep, array_merge($list1[2], $list2[2]));
5037 4639 }
5038 4640
5039 - protected static $libAppend = ['list', 'val', 'separator'];
4641 + protected static $libAppend = array('list', 'val', 'separator');
5040 4642 protected function libAppend($args)
5041 4643 {
5042 4644 list($list1, $value, $sep) = $args;
5043 4645
@@ -5043,9 +4645,9 @@
5043 4645
5044 4646 $list1 = $this->coerceList($list1, ' ');
5045 4647 $sep = $this->listSeparatorForJoin($list1, $sep);
5046 4648
5047 - return [Type::T_LIST, $sep, array_merge($list1[2], [$value])];
4649 + return array(Type::T_LIST, $sep, array_merge($list1[2], array($value)));
5048 4650 }
5049 4651
5050 4652 protected function libZip($args)
5051 4653 {
@@ -5052,13 +4654,13 @@
5052 4654 foreach ($args as $arg) {
5053 4655 $this->assertList($arg);
5054 4656 }
5055 4657
5056 - $lists = [];
4658 + $lists = array();
5057 4659 $firstList = array_shift($args);
5058 4660
5059 4661 foreach ($firstList[2] as $key => $item) {
5060 - $list = [Type::T_LIST, '', [$item]];
4662 + $list = array(Type::T_LIST, '', array($item));
5061 4663
5062 4664 foreach ($args as $arg) {
5063 4665 if (isset($arg[2][$key])) {
5064 4666 $list[2][] = $arg[2][$key];
@@ -5069,12 +4671,12 @@
5069 4671
5070 4672 $lists[] = $list;
5071 4673 }
5072 4674
5073 - return [Type::T_LIST, ',', $lists];
4675 + return array(Type::T_LIST, ',', $lists);
5074 4676 }
5075 4677
5076 - protected static $libTypeOf = ['value'];
4678 + protected static $libTypeOf = array('value');
5077 4679 protected function libTypeOf($args)
5078 4680 {
5079 4681 $value = $args[0];
5080 4682
@@ -5079,9 +4681,9 @@
5079 4681 $value = $args[0];
5080 4682
5081 4683 switch ($value[0]) {
5082 4684 case Type::T_KEYWORD:
5083 - if ($value === static::$true || $value === static::$false) {
4685 + if ($value === self::$true || $value === self::$false) {
5084 4686 return 'bool';
5085 4687 }
5086 4688
5087 4689 if ($this->coerceColor($value)) {
@@ -5102,21 +4704,21 @@
5102 4704 return $value[0];
5103 4705 }
5104 4706 }
5105 4707
5106 - protected static $libUnit = ['number'];
4708 + protected static $libUnit = array('number');
5107 4709 protected function libUnit($args)
5108 4710 {
5109 4711 $num = $args[0];
5110 4712
5111 4713 if ($num[0] === Type::T_NUMBER) {
5112 - return [Type::T_STRING, '"', [$num->unitStr()]];
4714 + return array(Type::T_STRING, '"', array($num->unitStr()));
5113 4715 }
5114 4716
5115 4717 return '';
5116 4718 }
5117 4719
5118 - protected static $libUnitless = ['number'];
4720 + protected static $libUnitless = array('number');
5119 4721 protected function libUnitless($args)
5120 4722 {
5121 4723 $value = $args[0];
5122 4724
@@ -5122,9 +4724,9 @@
5122 4724
5123 4725 return $value[0] === Type::T_NUMBER && $value->unitless();
5124 4726 }
5125 4727
5126 - protected static $libComparable = ['number-1', 'number-2'];
4728 + protected static $libComparable = array('number-1', 'number-2');
5127 4729 protected function libComparable($args)
5128 4730 {
5129 4731 list($number1, $number2) = $args;
5130 4732
@@ -5131,10 +4733,8 @@
5131 4733 if (! isset($number1[0]) || $number1[0] !== Type::T_NUMBER ||
5132 4734 ! isset($number2[0]) || $number2[0] !== Type::T_NUMBER
5133 4735 ) {
5134 4736 $this->throwError('Invalid argument(s) for "comparable"');
5135 -
5136 - return;
5137 4737 }
5138 4738
5139 4739 $number1 = $number1->normalize();
5140 4740 $number2 = $number2->normalize();
@@ -5141,9 +4741,9 @@
5141 4741
5142 4742 return $number1[2] === $number2[2] || $number1->unitless() || $number2->unitless();
5143 4743 }
5144 4744
5145 - protected static $libStrIndex = ['string', 'substring'];
4745 + protected static $libStrIndex = array('string', 'substring');
5146 4746 protected function libStrIndex($args)
5147 4747 {
5148 4748 $string = $this->coerceString($args[0]);
5149 4749 $stringContent = $this->compileStringContent($string);
@@ -5152,12 +4752,12 @@
5152 4752 $substringContent = $this->compileStringContent($substring);
5153 4753
5154 4754 $result = strpos($stringContent, $substringContent);
5155 4755
5156 - return $result === false ? static::$null : new Node\Number($result + 1, '');
4756 + return $result === false ? self::$null : new Node\Number($result + 1, '');
5157 4757 }
5158 4758
5159 - protected static $libStrInsert = ['string', 'insert', 'index'];
4759 + protected static $libStrInsert = array('string', 'insert', 'index');
5160 4760 protected function libStrInsert($args)
5161 4761 {
5162 4762 $string = $this->coerceString($args[0]);
5163 4763 $stringContent = $this->compileStringContent($string);
@@ -5166,14 +4766,14 @@
5166 4766 $insertContent = $this->compileStringContent($insert);
5167 4767
5168 4768 list(, $index) = $args[2];
5169 4769
5170 - $string[2] = [substr_replace($stringContent, $insertContent, $index - 1, 0)];
4770 + $string[2] = array(substr_replace($stringContent, $insertContent, $index - 1, 0));
5171 4771
5172 4772 return $string;
5173 4773 }
5174 4774
5175 - protected static $libStrLength = ['string'];
4775 + protected static $libStrLength = array('string');
5176 4776 protected function libStrLength($args)
5177 4777 {
5178 4778 $string = $this->coerceString($args[0]);
5179 4779 $stringContent = $this->compileStringContent($string);
@@ -5180,57 +4780,49 @@
5180 4780
5181 4781 return new Node\Number(strlen($stringContent), '');
5182 4782 }
5183 4783
5184 - protected static $libStrSlice = ['string', 'start-at', 'end-at'];
4784 + protected static $libStrSlice = array('string', 'start-at', 'end-at');
5185 4785 protected function libStrSlice($args)
5186 4786 {
5187 - if (isset($args[2]) && $args[2][1] == 0) {
5188 - return static::$nullString;
4787 + if ($args[2][1] == 0) {
4788 + return self::$null;
5189 4789 }
5190 4790
5191 4791 $string = $this->coerceString($args[0]);
5192 4792 $stringContent = $this->compileStringContent($string);
5193 4793
5194 - $start = (int) $args[1][1];
4794 + $start = (int) $args[1][1] ?: 1;
4795 + $end = (int) $args[2][1];
5195 4796
5196 - if ($start > 0) {
5197 - $start--;
5198 - }
4797 + $string[2] = array(substr($stringContent, $start - 1, ($end < 0 ? $end : $end - $start) + 1));
5199 4798
5200 - $end = (int) $args[2][1];
5201 - $length = $end < 0 ? $end + 1 : ($end > 0 ? $end - $start : $end);
5202 -
5203 - $string[2] = $length
5204 - ? [substr($stringContent, $start, $length)]
5205 - : [substr($stringContent, $start)];
5206 -
5207 4799 return $string;
5208 4800 }
5209 4801
5210 - protected static $libToLowerCase = ['string'];
4802 + protected static $libToLowerCase = array('string');
5211 4803 protected function libToLowerCase($args)
5212 4804 {
5213 4805 $string = $this->coerceString($args[0]);
5214 4806 $stringContent = $this->compileStringContent($string);
5215 4807
5216 - $string[2] = [function_exists('mb_strtolower') ? mb_strtolower($stringContent) : strtolower($stringContent)];
4808 + $string[2] = array(mb_strtolower($stringContent));
5217 4809
5218 4810 return $string;
5219 4811 }
5220 4812
5221 - protected static $libToUpperCase = ['string'];
4813 + protected static $libToUpperCase = array('string');
5222 4814 protected function libToUpperCase($args)
5223 4815 {
5224 4816 $string = $this->coerceString($args[0]);
5225 4817 $stringContent = $this->compileStringContent($string);
5226 4818
5227 - $string[2] = [function_exists('mb_strtoupper') ? mb_strtoupper($stringContent) : strtoupper($stringContent)];
4819 + $string[2] = array(mb_strtoupper($stringContent));
5228 4820
5229 4821 return $string;
5230 4822 }
5231 4823
5232 - protected static $libFeatureExists = ['feature'];
4824 + protected static $libFeatureExists = array('feature');
5233 4825 protected function libFeatureExists($args)
5234 4826 {
5235 4827 $string = $this->coerceString($args[0]);
5236 4828 $name = $this->compileStringContent($string);
@@ -5239,9 +4831,9 @@
5239 4831 array_key_exists($name, $this->registeredFeatures) ? $this->registeredFeatures[$name] : false
5240 4832 );
5241 4833 }
5242 4834
5243 - protected static $libFunctionExists = ['name'];
4835 + protected static $libFunctionExists = array('name');
5244 4836 protected function libFunctionExists($args)
5245 4837 {
5246 4838 $string = $this->coerceString($args[0]);
5247 4839 $name = $this->compileStringContent($string);
@@ -5246,9 +4838,9 @@
5246 4838 $string = $this->coerceString($args[0]);
5247 4839 $name = $this->compileStringContent($string);
5248 4840
5249 4841 // user defined functions
5250 - if ($this->has(static::$namespaces['function'] . $name)) {
4842 + if ($this->has(self::$namespaces['function'] . $name)) {
5251 4843 return true;
5252 4844 }
5253 4845
5254 4846 $name = $this->normalizeName($name);
@@ -5262,9 +4854,9 @@
5262 4854
5263 4855 return $this->toBool(is_callable($f));
5264 4856 }
5265 4857
5266 - protected static $libGlobalVariableExists = ['name'];
4858 + protected static $libGlobalVariableExists = array('name');
5267 4859 protected function libGlobalVariableExists($args)
5268 4860 {
5269 4861 $string = $this->coerceString($args[0]);
5270 4862 $name = $this->compileStringContent($string);
@@ -5271,18 +4863,18 @@
5271 4863
5272 4864 return $this->has($name, $this->rootEnv);
5273 4865 }
5274 4866
5275 - protected static $libMixinExists = ['name'];
4867 + protected static $libMixinExists = array('name');
5276 4868 protected function libMixinExists($args)
5277 4869 {
5278 4870 $string = $this->coerceString($args[0]);
5279 4871 $name = $this->compileStringContent($string);
5280 4872
5281 - return $this->has(static::$namespaces['mixin'] . $name);
4873 + return $this->has(self::$namespaces['mixin'] . $name);
5282 4874 }
5283 4875
5284 - protected static $libVariableExists = ['name'];
4876 + protected static $libVariableExists = array('name');
5285 4877 protected function libVariableExists($args)
5286 4878 {
5287 4879 $string = $this->coerceString($args[0]);
5288 4880 $name = $this->compileStringContent($string);
@@ -5293,19 +4885,16 @@
5293 4885 /**
5294 4886 * Workaround IE7's content counter bug.
5295 4887 *
5296 4888 * @param array $args
5297 - *
5298 - * @return array
5299 4889 */
5300 4890 protected function libCounter($args)
5301 4891 {
5302 - $list = array_map([$this, 'compileValue'], $args);
4892 + $list = array_map(array($this, 'compileValue'), $args);
5303 4893
5304 - return [Type::T_STRING, '', ['counter(' . implode(',', $list) . ')']];
4894 + return array(Type::T_STRING, '', array('counter(' . implode(',', $list) . ')'));
5305 4895 }
5306 4896
5307 - protected static $libRandom = ['limit'];
5308 4897 protected function libRandom($args)
5309 4898 {
5310 4899 if (isset($args[0])) {
5311 4900 $n = $this->assertNumber($args[0]);
@@ -5311,10 +4900,8 @@
5311 4900 $n = $this->assertNumber($args[0]);
5312 4901
5313 4902 if ($n < 1) {
5314 4903 $this->throwError("limit must be greater than or equal to 1");
5315 -
5316 - return;
5317 4904 }
5318 4905
5319 4906 return new Node\Number(mt_rand(1, $n), '');
5320 4907 }
@@ -5331,17 +4918,7 @@
5331 4918 }
5332 4919
5333 4920 $id += mt_rand(0, 10) + 1;
5334 4921
5335 - return [Type::T_STRING, '', ['u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)]];
5336 - }
5337 -
5338 - protected static $libInspect = ['value'];
5339 - protected function libInspect($args)
5340 - {
5341 - if ($args[0] === static::$null) {
5342 - return [Type::T_KEYWORD, 'null'];
5343 - }
5344 -
5345 - return $args[0];
4922 + return array(Type::T_STRING, '', array('u' . str_pad(base_convert($id, 10, 36), 8, '0', STR_PAD_LEFT)));
5346 4923 }
5347 4924 }