예제 #1
0
 static function compile_splatted_array($options, $list, $apply = FALSE)
 {
     $index = -1;
     while (isset($list[++$index]) && ($node = $list[$index]) && !$node instanceof yy_Splat) {
         continue;
     }
     if ($index >= count($list)) {
         return '';
     }
     if (count($list) === 1) {
         $code = $list[0]->compile($options, LEVEL_LIST);
         if ($apply) {
             return $code;
         }
         return utility('slice') . ".call({$code})";
     }
     $args = array_slice($list, $index);
     foreach ($args as $i => $node) {
         $code = $node->compile($options, LEVEL_LIST);
         $args[$i] = $node instanceof yy_Splat ? utility('slice') . ".call({$code})" : "[{$code}]";
     }
     if ($index === 0) {
         return $args[0] . '.concat(' . implode(', ', array_slice($args, 1)) . ')';
     }
     $base = array();
     foreach (array_slice($list, 0, $index) as $node) {
         $base[] = $node->compile($options, LEVEL_LIST);
     }
     return '[' . implode(', ', $base) . '].concat(' . implode(', ', $args) . ')';
 }
예제 #2
0
 function add_bound_functions($options)
 {
     if ($this->bound_funcs) {
         foreach ($this->bound_funcs as $bvar) {
             $lhs = yy('Value', yy('Literal', 'this'), array(yy('Access', $bvar)))->compile($options);
             $this->ctor->body->unshift(yy('Literal', "{$lhs} = " . utility('bind') . "({$lhs}, this)"));
         }
     }
 }
예제 #3
0
 function add_bound_functions($options)
 {
     if ($this->bound_funcs) {
         foreach ($this->bound_funcs as $bvar) {
             $bname = $bvar->compile($options);
             $this->ctor->body->unshift(yy('Literal', "this.{$bname} = " . utility('bind') . "(this.{$bname}, this)"));
         }
     }
 }
예제 #4
0
 function compile_loop_test($options)
 {
     list($sub, $ref) = $this->object->cache($options, LEVEL_LIST);
     $code = utility('indexOf') . ".call(" . $this->array->compile($options, LEVEL_LIST) . ", {$ref}) " . ($this->negated ? '< 0' : '>= 0');
     if ($sub === $ref) {
         return $code;
     }
     $code = $sub . ', ' . $code;
     return isset($options['level']) && $options['level'] < LEVEL_LIST ? $code : "({$code})";
 }
예제 #5
0
 function add_bound_functions($options)
 {
     if (count($this->bound_funcs)) {
         foreach ($this->bound_funcs as $bvar) {
             $bname = $bvar->compile($options);
             $body = is_array($this->ctor->body) ? $this->ctor->body : array($this->ctor->body);
             array_unshift($body, yy('Literal', "this.{$bname} = " . utility('bind') . "(this.{$bname}, this)"));
         }
     }
 }
예제 #6
0
 function compile_node($options)
 {
     $body = yy_Block::wrap(array($this->body));
     $last_jumps = last($body->expressions);
     $last_jumps = $last_jumps ? $last_jumps->jumps() : FALSE;
     if ($last_jumps && $last_jumps instanceof yy_Return) {
         $this->returns = FALSE;
     }
     if ($this->range) {
         $source = $this->source->base;
     } else {
         $source = $this->source;
     }
     $scope = $options['scope'];
     $name = $this->name ? $this->name->compile($options, LEVEL_LIST) : FALSE;
     $index = $this->index ? $this->index->compile($options, LEVEL_LIST) : FALSE;
     if ($name && !$this->pattern) {
         $scope->find($name, array('immediate' => TRUE));
     }
     if ($index) {
         $scope->find($index, array('immediate' => TRUE));
     }
     if ($this->returns) {
         $rvar = $scope->free_variable('results');
     }
     $ivar = $this->object ? $index : $scope->free_variable('i');
     $kvar = $this->range ? $name ? $name : ($index ? $index : $ivar) : ($index ? $index : $ivar);
     $kvar_assign = $kvar !== $ivar ? "{$kvar} = " : '';
     if ($this->step && !$this->range) {
         $stepvar = $scope->free_variable('step');
     }
     if ($this->pattern) {
         $name = $ivar;
     }
     $var_part = '';
     $guard_part = '';
     $def_part = '';
     $idt1 = $this->tab . TAB;
     if ($this->range) {
         $for_part = $source->compile(array_merge($options, array('index' => $ivar, 'name' => $name, 'step' => $this->step)));
     } else {
         $svar = $this->source->compile($options, LEVEL_LIST);
         if (($name || $this->own) && !preg_match(IDENTIFIER, $svar)) {
             $ref = $scope->free_variable('ref');
             $def_part = "{$this->tab}{$ref} = {$svar};\n";
             $svar = $ref;
         }
         if ($name && !$this->pattern) {
             $name_part = "{$name} = {$svar}[{$kvar}]";
         }
         if (!$this->object) {
             $lvar = $scope->free_variable('len');
             $for_var_part = "{$kvar_assign}{$ivar} = 0, {$lvar} = {$svar}.length";
             if ($this->step) {
                 $for_var_part .= ", {$stepvar} = " . $this->step->compile($options, LEVEL_OP);
             }
             $step_part = $kvar_assign . ($this->step ? "{$ivar} += {$stepvar}" : ($kvar !== $ivar ? "++{$ivar}" : "{$ivar}++"));
             $for_part = "{$for_var_part}; {$ivar} < {$lvar}; {$step_part}";
         }
     }
     if ($this->returns) {
         $result_part = "{$this->tab}{$rvar} = [];\n";
         $return_result = "\n{$this->tab}return {$rvar};";
         $body->make_return($rvar);
     }
     if ($this->guard) {
         if ($body->expressions) {
             array_unshift($body->expressions, yy('If', yy('Parens', $this->guard)->invert(), yy('Literal', 'continue')));
         } else {
             $body = yy_Block::wrap(array(yy('If', $this->guard, $body)));
         }
     }
     if ($this->pattern) {
         array_unshift($body->expressions, yy('Assign', $this->name, yy('Literal', "{$svar}[{$kvar}]")));
     }
     $def_part .= $this->pluck_direct_call($options, $body);
     if (isset($name_part) && $name_part) {
         $var_part = "\n{$idt1}{$name_part};";
     }
     if ($this->object) {
         $for_part = "{$kvar} in {$svar}";
         if ($this->own) {
             $guard_part = "\n{$idt1}if (!" . utility('hasProp') . ".call({$svar}, {$kvar})) continue;";
         }
     }
     $body = $body->compile(array_merge($options, array('indent' => $idt1)), LEVEL_TOP);
     if ($body) {
         $body = "\n{$body}\n";
     }
     return "{$def_part}" . (isset($result_part) ? $result_part : '') . "{$this->tab}for ({$for_part}) {{$guard_part}{$var_part}{$body}{$this->tab}}" . (isset($return_result) ? $return_result : '');
 }
예제 #7
0
 function compile_pattern_match($options)
 {
     $top = $options['level'] === LEVEL_TOP;
     $value = $this->value;
     $objects = $this->variable->base->objects;
     if (!($olen = count($objects))) {
         $code = $value->compile($options);
         return $options['level'] >= LEVEL_OP ? "({$code})" : $code;
     }
     $is_object = $this->variable->is_object();
     if ($top && $olen === 1 && !($obj = $objects[0]) instanceof yy_Splat) {
         if ($obj instanceof yy_Assign) {
             $idx = $obj->variable->base;
             $obj = $obj->value;
         } else {
             if ($obj->base instanceof yy_Parens) {
                 $tmp = yy('Value', $obj->unwrap_all());
                 list($obj, $idx) = $tmp->cache_reference($options);
             } else {
                 if ($is_object) {
                     $idx = $obj->this ? $obj->properties[0]->name : $obj;
                 } else {
                     $idx = yy('Literal', 0);
                 }
             }
         }
         $acc = preg_match(IDENTIFIER, $idx->unwrap()->value);
         $value = yy('Value', $value);
         if ($acc) {
             $value->properties[] = yy('Access', $idx);
         } else {
             $value->properties[] = yy('Index', $idx);
         }
         $tmp = $obj->unwrap();
         $tmp = isset($tmp->value) ? $tmp->value : NULL;
         if (in_array($tmp, Lexer::$COFFEE_RESERVED)) {
             throw new SyntaxError('assignment to a reserved word: ' . $obj->compile($options) . ' = ' . $value->compile($options));
         }
         return yy('Assign', $obj, $value, NULL, array('param' => $this->param))->compile($options, LEVEL_TOP);
     }
     $vvar = $value->compile($options, LEVEL_LIST);
     $assigns = array();
     $splat = FALSE;
     if (!preg_match(IDENTIFIER, $vvar) || $this->variable->assigns($vvar)) {
         $assigns[] = ($ref = $options['scope']->free_variable('ref')) . ' = ' . $vvar;
         $vvar = $ref;
     }
     foreach ($objects as $i => $obj) {
         $idx = $i;
         if ($is_object) {
             if ($obj instanceof yy_Assign) {
                 $idx = $obj->variable->base;
                 $obj = $obj->value;
             } else {
                 if ($obj->base instanceof yy_Parens) {
                     $tmp = yy('Value', $obj->unwrap_all());
                     list($obj, $idx) = $tmp->cache_reference($options);
                 } else {
                     $idx = $obj->this ? $obj->properties[0]->name : $obj;
                 }
             }
         }
         if (!$splat && $obj instanceof yy_Splat) {
             $name = $obj->name->unwrap()->value;
             $obj = $obj->unwrap();
             $val = "{$olen} <= {$vvar}.length ? " . utility('slice') . ".call({$vvar}, {$i}";
             $ivar = 'undefined';
             if ($rest = $olen - $i - 1) {
                 $ivar = $options['scope']->free_variable('i');
                 $val .= ", {$ivar} = {$vvar}.length - {$rest}) : ({$ivar} = {$i}, [])";
             } else {
                 $val .= ') : []';
             }
             $val = yy('Literal', $val);
             $splat = "{$ivar}++";
         } else {
             $name = $obj->unwrap();
             $name = isset($name->value) ? $name->value : NULL;
             if ($obj instanceof yy_Splat) {
                 $obj = $obj->name->compile($options);
                 throw new SyntaxError("multiple splats are disallowed in an assignment: {$obj}...");
             }
             if (is_numeric($idx)) {
                 $idx = yy('Literal', $splat ? $splat : $idx);
                 $acc = FALSE;
             } else {
                 $acc = $is_object ? preg_match(IDENTIFIER, $idx->unwrap()->value) : 0;
             }
             $val = yy('Value', yy('Literal', $vvar), array($acc ? yy('Access', $idx) : yy('Index', $idx)));
         }
         if (isset($name) && $name && in_array($name, Lexer::$COFFEE_RESERVED)) {
             throw new SyntaxError("assignment to a reserved word: " . $obj->compile($options) . ' = ' . $val->compile($options));
         }
         $tmp = yy('Assign', $obj, $val, NULL, array('param' => $this->param, 'subpattern' => TRUE));
         $assigns[] = $tmp->compile($options, LEVEL_TOP);
     }
     if (!($top || $this->subpattern)) {
         $assigns[] = $vvar;
     }
     $code = implode(', ', $assigns);
     return $options['level'] < LEVEL_LIST ? $code : "({$code})";
 }
예제 #8
0
 function compile($options)
 {
     $tmp = yy('Call', yy('Value', yy('Literal', utility('extends'))), array($this->child, $this->parent));
     return $tmp->compile($options);
 }
예제 #9
0
 function compile_node($options)
 {
     $options['scope'] = new Scope($options['scope'], $this->body, $this);
     $options['scope']->shared = del($options, 'sharedScope');
     $options['indent'] .= TAB;
     unset($options['bare']);
     $vars = array();
     $exprs = array();
     foreach ($this->params as $param) {
         if ($param->splat) {
             if (isset($param->name->value) && $param->name->value) {
                 $options['scope']->add($param->name->value, 'var');
             }
             $params = array();
             foreach ($this->params as $p) {
                 $params[] = $p->as_reference($options);
             }
             $splats = yy('Assign', yy('Value', yy('Arr', $params)), yy('Value', yy('Literal', 'arguments')));
             break;
         }
     }
     foreach ($this->params as $param) {
         if ($param->is_complex()) {
             $val = $ref = $param->as_reference($options);
             if ($param->value) {
                 $val = yy('Op', '?', $ref, $param->value);
             }
             $exprs[] = yy('Assign', yy('Value', $param->name), $val, '=', array('param' => TRUE));
         } else {
             $ref = $param;
             if ($param->value) {
                 $lit = yy('Literal', $ref->name->value . ' == null');
                 $val = yy('Assign', yy('Value', $param->name), $param->value, '=');
                 $exprs[] = yy('If', $lit, $val);
             }
         }
         if (!(isset($splats) && $splats)) {
             $vars[] = $ref;
         }
     }
     $was_empty = $this->body->is_empty();
     if (isset($splats) && $splats) {
         array_unshift($exprs, $splats);
     }
     if (count($exprs)) {
         $this->body->expressions = array_merge($this->body->expressions, $exprs);
     }
     if (!(isset($splats) && $splats)) {
         foreach ($vars as $i => $v) {
             $options['scope']->parameter($vars[$i] = $v->compile($options));
         }
     }
     if (!($was_empty || $this->no_return)) {
         $this->body->make_return();
     }
     $idt = $options['indent'];
     $code = 'function';
     if ($this->ctor) {
         $code .= ' ' . $this->name;
     }
     $code .= '(' . implode(', ', $vars) . ') {';
     if (!$this->body->is_empty()) {
         $code .= "\n" . $this->body->compile_with_declarations($options) . "\n{$this->tab}";
     }
     $code .= '}';
     if ($this->ctor) {
         return $this->tab . $code;
     }
     if ($this->bound) {
         return utility('bind') . "({$code}, {$this->context})";
     }
     return $this->front || $options['level'] >= LEVEL_ACCESS ? "({$code})" : $code;
 }