function constructor($body, $source) { $this->source = $source['source']; $this->guard = isset($source['guard']) ? $source['guard'] : NULL; $this->step = isset($source['step']) ? $source['step'] : NULL; $this->name = isset($source['name']) ? $source['name'] : NULL; $this->index = isset($source['index']) ? $source['index'] : NULL; $this->body = yy_Block::wrap(array($body)); $this->own = isset($source['own']) && $source['own']; $this->object = isset($source['object']) && $source['object']; if ($this->object) { $tmp = $this->name; $this->name = $this->index; $this->index = $tmp; } if ($this->index instanceof yy_Value) { throw SyntaxError('index cannot be a pattern matching expression'); } $this->range = $this->source instanceof yy_Value && $this->source->base instanceof yy_Range && !count($this->source->properties); $this->pattern = $this->name instanceof yy_Value; if ($this->range && $this->index) { throw SyntaxError('indexes do not apply to range loops'); } if ($this->range && $this->pattern) { throw SyntaxError('cannot pattern match over range loops'); } $this->returns = FALSE; return $this; }
function super_reference($options) { $method = $options['scope']->method; if (!$method) { throw SyntaxError('cannot call super outside of a function.'); } $name = $method->name; if (!$name) { throw SyntaxError('cannot call super on an anonymous function.'); } if (isset($method->klass) && $method->klass) { return $method->klass . '.__super__.' . $name; } else { return $name . '.__super__.constructor'; } }
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 = yy('Assign', $obj, $value); return $tmp->compile($options); } $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) { $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 { if ($obj instanceof yy_Splat) { $obj = $obj->name->compile($options); throw 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))); } $tmp = yy('Assign', $obj, $val, NULL, array('param' => $this->param)); $assigns[] = $tmp->compile($options, LEVEL_TOP); } if (!$top) { $assigns[] = $vvar; } $code = implode(', ', $assigns); return $options['level'] < LEVEL_LIST ? $code : "({$code})"; }