Пример #1
0
 static function wrap($name, $exps)
 {
     if ($exps->is_empty() || last($exps->expressions)->jumps()) {
         return $exps;
     }
     return $exps->push(yy('Call', yy('Value', yy('Literal', $name), array(yy('Access', yy('Literal', 'push')))), array($exps->pop())));
 }
Пример #2
0
 function compile_node($options)
 {
     $options['indent'] .= TAB;
     $set = '';
     $body = $this->body;
     if ($body->is_empty()) {
         $body = '';
     } else {
         if ($this->returns) {
             $body->make_return($rvar = $options['scope']->free_variable('results'));
             $set = "{$this->tab}{$rvar} = [];\n";
         }
         if ($this->guard) {
             if (count($body->expressions) > 1) {
                 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)));
             }
         }
         $body = "\n" . $body->compile($options, LEVEL_TOP) . "\n{$this->tab}";
     }
     $code = $set . $this->tab . 'while (' . $this->condition->compile($options, LEVEL_PAREN) . ") {{$body}}";
     if ($this->returns) {
         $code .= "\n{$this->tab}return {$rvar};";
     }
     return $code;
 }
Пример #3
0
 function compile_node($options)
 {
     $options['indent'] .= TAB;
     $set = '';
     $body = $this->body;
     if ($body->is_empty()) {
         $body = '';
     } else {
         if ($options['level'] > LEVEL_TOP || $this->returns) {
             $rvar = $options['scope']->free_variable('results');
             $set = "{$this->tab}{$rvar} = [];\n";
             if ($body) {
                 $body = yy_Push::wrap($rvar, $body);
             }
         }
         if ($this->guard) {
             $body = yy_Block::wrap(array(yy('If', $this->guard, $body)));
         }
         $body = "\n" . $body->compile($options, LEVEL_TOP) . "\n{$this->tab}";
     }
     $code = $set . $this->tab . 'while (' . $this->condition->compile($options, LEVEL_PAREN) . ") {{$body}}";
     if ($this->returns) {
         $code .= "\n{$this->tab}return {$rvar};";
     }
     return $code;
 }
Пример #4
0
 function compile_node($options)
 {
     $props = $this->properties;
     $prop_names = array();
     foreach ($this->properties as $prop) {
         if ($prop->is_complex()) {
             $prop = isset($prop->variable) ? $prop->variable : NULL;
         }
         if ($prop) {
             $prop_name = $prop->unwrap_all();
             $prop_name = isset($prop_name->value) ? $prop_name->value . '' : NULL;
             if (in_array($prop_name, $prop_names)) {
                 throw new SyntaxError('multiple object literal properties named "' . $prop_name . '"');
             }
             $prop_names[] = $prop_name;
         }
     }
     if (!count($props)) {
         return $this->front ? '({})' : '{}';
     }
     if ($this->generated) {
         foreach ($props as $node) {
             if ($node instanceof yy_Value) {
                 throw new Error('cannot have an implicit value in an implicit object');
             }
         }
     }
     $idt = $options['indent'] .= TAB;
     $last_non_com = $this->last_non_comment($this->properties);
     foreach ($props as $i => $prop) {
         if ($i === count($props) - 1) {
             $join = '';
         } else {
             if ($prop === $last_non_com || $prop instanceof yy_Comment) {
                 $join = "\n";
             } else {
                 $join = ",\n";
             }
         }
         $indent = $prop instanceof yy_Comment ? '' : $idt;
         if ($prop instanceof yy_Value && (isset($prop->this) && $prop->this)) {
             $prop = yy('Assign', $prop->properties[0]->name, $prop, 'object');
         }
         if (!$prop instanceof yy_Comment) {
             if (!$prop instanceof yy_Assign) {
                 $prop = yy('Assign', $prop, $prop, 'object');
             }
             if (isset($prop->variable->base)) {
                 $prop->variable->base->as_key = TRUE;
             } else {
                 $prop->variable->as_key = TRUE;
             }
         }
         $props[$i] = $indent . $prop->compile($options, LEVEL_TOP) . $join;
     }
     $props = implode('', $props);
     $obj = '{' . ($props ? "\n{$props}\n{$this->tab}" : '') . '}';
     return $this->front ? "({$obj})" : $obj;
 }
Пример #5
0
 function constructor($name)
 {
     if (is_object($name)) {
         $this->name = $name;
     } else {
         $this->name = yy('Literal', $name);
     }
     return $this;
 }
Пример #6
0
 static function unfold_soak($options, $parent, $name)
 {
     if (!(isset($parent->{$name}) && $parent->{$name} && ($ifn = $parent->{$name}->unfold_soak($options)))) {
         return NULL;
     }
     $parent->{$name} = $ifn->body;
     $ifn->body = yy('Value', $parent);
     return $ifn;
 }
Пример #7
0
 function make_return($res = NULL)
 {
     foreach ($this->cases as $pair) {
         $pair[1]->make_return($res);
     }
     if ($res && !$this->otherwise) {
         $this->otherwise = yy('Block', array(yy('Literal', 'void 0')));
     }
     if ($this->otherwise) {
         $this->otherwise->make_return($res);
     }
     return $this;
 }
Пример #8
0
 static function wrap($expressions, $statement = NULL, $no_return = FALSE)
 {
     if ($expressions->jumps()) {
         return $expressions;
     }
     $func = yy('Code', array(), yy_Block::wrap(array($expressions)));
     $args = array();
     if (($mentions_args = $expressions->contains('yy_Closure::literal_args')) || $expressions->contains('yy_Closure::literal_this')) {
         $meth = yy('Literal', $mentions_args ? 'apply' : 'call');
         $args = array(yy('Literal', 'this'));
         if ($mentions_args) {
             $args[] = yy('Literal', 'arguments');
         }
         $func = yy('Value', $func, array(yy('Access', $meth)));
     }
     $func->no_return = $no_return;
     $call = yy('Call', $func, $args);
     return $statement ? yy_Block::wrap(array($call)) : $call;
 }
Пример #9
0
 function as_reference($options)
 {
     if (isset($this->reference) && $this->reference) {
         return $this->reference;
     }
     $node = $this->name;
     if (isset($node->this) && $node->this) {
         $node = $node->properties[0]->name;
         if (isset($this->value->reserved) && $this->value->reserved) {
             $node = yy('Literal', $options['scope']->free_variable($node->value));
         }
     } else {
         if ($node->is_complex()) {
             $node = yy('Literal', $options['scope']->free_variable('arg'));
         }
     }
     $node = yy('Value', $node);
     if ($this->splat) {
         $node = yy('Splat', $node);
     }
     return $this->reference = $node;
 }
Пример #10
0
 function filter_implicit_objects()
 {
     return call_user_func_array(array(yy('Call'), __FUNCTION__), func_get_args());
 }
Пример #11
0
 function unfold_soak($options)
 {
     if ($this->soak) {
         if ($this->variable) {
             if ($ifn = unfold_soak($options, $this, 'variable')) {
                 return $ifn;
             }
             $tmp = yy('Value', $this->variable);
             list($left, $rite) = $tmp->cache_reference($options);
         } else {
             $left = yy('Literal', $this->super_reference($options));
             $rite = yy('Value', $left);
         }
         $rite = yy('Call', $rite, $this->args);
         $rite->is_new($this->is_new());
         $left = yy('Literal', 'typeof ' . $left->compile($options) . ' === "function"');
         return yy('If', $left, yy('Value', $rite), array('soak' => TRUE));
     }
     $call = $this;
     $list = array();
     while (TRUE) {
         if ($call->variable instanceof yy_Call) {
             $list[] = $call;
             $call = $call->variable;
             continue;
         }
         if (!$call->variable instanceof yy_Value) {
             break;
         }
         $list[] = $call;
         if (!($call = $call->variable->base) instanceof yy_Call) {
             break;
         }
     }
     foreach (array_reverse($list) as $call) {
         if (isset($ifn)) {
             if ($call->variable instanceof yy_Call) {
                 $call->variable = $ifn;
             } else {
                 $call->variable->base = $ifn;
             }
         }
         $ifn = unfold_soak($options, $call, 'variable');
     }
     return isset($ifn) ? $ifn : NULL;
 }
Пример #12
0
 function pluck_direct_call($options, $body)
 {
     $defs = '';
     foreach ($body->expressions as $idx => $expr) {
         $expr = $expr->unwrap_all();
         if (!$expr instanceof yy_Call) {
             continue;
         }
         $val = $expr->variable->unwrap_all();
         if (!($val instanceof yy_Code || $val instanceof yy_Value && (isset($val->base) && $val->base && $val->base->unwrap_all() instanceof yy_Code && count($val->properties) === 1 && isset($val->properties[0]->name) && in_array($val->properties[0]->name['value'], array('call', 'apply'), TRUE)))) {
             continue;
         }
         $fn = isset($val->base) && $val->base ? $val->base->unwrap_all() : $val;
         $ref = yy('Literal', $options['scope']->free_variable('fn'));
         $base = yy('Value', $ref);
         if (isset($val->base) && $val->base) {
             list($val->base, $base) = array($base, $val);
         }
         $body->expressions[$idx] = yy('Call', $base, $expr->args);
         $tmp = yy('Assign', $ref, $fn);
         $defs .= $this->tab . $tmp->compile($options, LEVEL_TOP) . ";\n";
     }
     return $defs;
 }
Пример #13
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})";
 }
Пример #14
0
 function make_return($res = NULL)
 {
     $me = $this->unwrap_all();
     if ($res) {
         return yy('Call', yy('Literal', "{$res}.push"), array($me));
     } else {
         return yy('Return', $me);
     }
 }
Пример #15
0
 function make_return()
 {
     if ($this->body) {
         $this->body = yy('Block', array($this->body->make_return()));
     }
     if ($this->else_body) {
         $this->else_body = yy('Block', array($this->else_body->make_return()));
     }
     return $this;
 }
Пример #16
0
 function make_return()
 {
     return yy('Return', $this);
 }
Пример #17
0
 function invert()
 {
     if ($this->is_chainable() && $this->first->is_chainable()) {
         $all_invertable = TRUE;
         $curr = $this;
         while ($curr && (isset($curr->operator) && $curr->operator)) {
             $all_invertable = $all_invertable && isset(self::$INVERSIONS[$curr->operator]);
             $curr = $curr->first;
         }
         if (!$all_invertable) {
             $tmp = yy('Parens', $this);
             return $tmp->invert();
         }
         $curr = $this;
         while ($curr && (isset($curr->operator) && $curr->operator)) {
             $curr->invert = !(isset($curr->invert) && $curr->invert);
             $curr->operator = self::$INVERSIONS[$curr->operator];
             $curr = $curr->first;
         }
         return $this;
     } else {
         if (isset(self::$INVERSIONS[$this->operator]) && ($op = self::$INVERSIONS[$this->operator])) {
             $this->operator = $op;
             if ($this->first->unwrap() instanceof yy_Op) {
                 $this->first->invert();
             }
             return $this;
         } else {
             if ($this->second) {
                 $tmp = yy('Parens', $this);
                 return $tmp->invert();
             } else {
                 if ($this->operator === '!' && ($fst = $this->first->unwrap()) instanceof yy_Op && in_array($fst->operator, array('!', 'in', 'instanceof'), TRUE)) {
                     return $fst;
                 } else {
                     return yy('Op', '!', $this);
                 }
             }
         }
     }
 }
Пример #18
0
 function compile($options)
 {
     $tmp = yy('Call', yy('Value', yy('Literal', utility('extends'))), array($this->child, $this->parent));
     return $tmp->compile($options);
 }
Пример #19
0
 function make_return()
 {
     return $this->is_statement() ? $this : yy('Return', $this);
 }
Пример #20
0
 function generate_do($exp)
 {
     $passed_params = array();
     $func = $exp;
     if ($exp instanceof yy_Assign && ($ref = $exp->value->unwrap()) instanceof yy_Code) {
         $func = $ref;
     }
     foreach (isset($func->params) && $func->params ? $func->params : array() as $param) {
         if (isset($param->value) && $param->value) {
             $passed_params[] = $param->value;
             unset($param->value);
         } else {
             $passed_params[] = $param;
         }
     }
     $call = yy('Call', $exp, $passed_params);
     $call->do = TRUE;
     return $call;
 }
Пример #21
0
 function unfold_soak($options)
 {
     if (isset($this->unfolded_soak)) {
         return $this->unfolded_soak;
     }
     $result = NULL;
     if ($ifn = $this->base->unfold_soak($options)) {
         $ifn->body->properties = array_merge($ifn->body->properties, $this->properties);
         $result = $ifn;
     } else {
         foreach ($this->properties as $i => $prop) {
             if (isset($prop->soak) && $prop->soak) {
                 $prop->soak = FALSE;
                 $fst = yy('Value', $this->base, array_slice($this->properties, 0, $i));
                 $snd = yy('Value', $this->base, array_slice($this->properties, $i));
                 if ($fst->is_complex()) {
                     $ref = yy('Literal', $options['scope']->free_variable('ref'));
                     $fst = yy('Parens', yy('Assign', $ref, $fst));
                     $snd->base = $ref;
                 }
                 $result = yy('If', yy('Existence', $fst), $snd, array('soak' => TRUE));
             }
         }
     }
     $this->unfolded_soak = $result ? $result : FALSE;
     return $this->unfolded_soak;
 }
Пример #22
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;
 }
Пример #23
0
 function make_return($res = NULL)
 {
     if (!(isset($this->else_body) && $this->else_body)) {
         if ($res) {
             $this->else_body = yy('Block', array(yy('Literal', 'void 0')));
         }
     }
     if ($this->body) {
         $this->body = yy('Block', array($this->body->make_return($res)));
     }
     if ($this->else_body) {
         $this->else_body = yy('Block', array($this->else_body->make_return($res)));
     }
     return $this;
 }
Пример #24
0
 static function wrap($nodes)
 {
     if (!is_array($nodes)) {
         $nodes = array($nodes);
     }
     if (count($nodes) === 1 && $nodes[0] instanceof yy_Block) {
         return $nodes[0];
     }
     return yy('Block', $nodes);
 }
Пример #25
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']);
     unset($options['isExistentialEquals']);
     $params = array();
     $exprs = array();
     foreach ($this->param_names() as $name) {
         if (!$options['scope']->check($name)) {
             $options['scope']->parameter($name);
         }
     }
     foreach ($this->params as $param) {
         if ($param->splat) {
             if (isset($param->name->value) && $param->name->value) {
                 $options['scope']->add($param->name->value, 'var', TRUE);
             }
             $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 (isset($param->value) && $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)) {
             $params[] = $ref;
         }
     }
     $was_empty = $this->body->is_empty();
     if (isset($splats) && $splats) {
         array_unshift($exprs, $splats);
     }
     if ($exprs) {
         foreach (array_reverse($exprs) as $expr) {
             array_unshift($this->body->expressions, $expr);
         }
     }
     foreach ($params as $i => $p) {
         $options['scope']->parameter($params[$i] = $p->compile($options));
     }
     $uniqs = array();
     foreach ($this->param_names() as $name) {
         if (in_array($name, $uniqs)) {
             throw new SyntaxError("multiple parameters named {$name}");
         }
         $uniqs[] = $name;
     }
     if (!($was_empty || $this->no_return)) {
         $this->body->make_return();
     }
     if ($this->bound) {
         if (isset($options['scope']->parent->method->bound) && $options['scope']->parent->method->bound) {
             $this->bound = $this->context = $options['scope']->parent->method->context;
         } else {
             if (!(isset($this->static) && $this->static)) {
                 $options['scope']->parent->assign('_this', 'this');
             }
         }
     }
     $idt = $options['indent'];
     $code = 'function';
     if ($this->ctor) {
         $code .= ' ' . $this->name;
     }
     $code .= '(' . implode(', ', $params) . ') {';
     if (!$this->body->is_empty()) {
         $code .= "\n" . $this->body->compile_with_declarations($options) . "\n{$this->tab}";
     }
     $code .= '}';
     if ($this->ctor) {
         return $this->tab . $code;
     }
     return $this->front || $options['level'] >= LEVEL_ACCESS ? "({$code})" : $code;
 }
Пример #26
0
 function ensure_constructor($name)
 {
     if (!(isset($this->ctor) && $this->ctor)) {
         $this->ctor = yy('Code');
         if ($this->parent) {
             $this->ctor->body->push(yy('Literal', "{$name}.__super__.constructor.apply(this, arguments)"));
         }
         if (isset($this->external_ctor) && $this->external_ctor) {
             $this->ctor->body->push(yy('Literal', "{$this->external_ctor}.apply(this, arguments)"));
         }
         $this->ctor->body->make_return();
         array_unshift($this->body->expressions, $this->ctor);
     }
     $this->ctor->ctor = $this->ctor->name = $name;
     $this->ctor->klass = NULL;
     $this->ctor->no_return = TRUE;
 }