The {for} block currently only works with real numbers, it does not
support variables. The implementation of this function is very old,
from before Outline, when I was merely experimenting - it needs to
be rewritten to support variables and expressions ...
What I have so far, is a replacement for OutlineSystem::for_block
public function for_block($args) {
preg_match(
'/(\$[\w\d_]*)\s+from\s+(.*)\sto\s(.*(?=\sby\s)|.*)(\sby\s(.+))?/',
$args,
$exp
);
$var = $from = $to = null; $by = 1; $c = count($exp);
if ($c==4 || $c==6) {
list($var, $from, $to, $by) = array($exp[1], $exp[2], $exp[3],
isset($exp[5]) ? $exp[5] : 1);
} else {
throw new OutlineException("syntax error in for-statement", $this-
>compiler);
}
if (in_array($var, $this->for_stack)) throw new
OutlineException("use of same iterator '$var' in nested {for}
statements", $this->compiler);
$this->for_stack[] = $var;
$this->compiler->code("{$var} = new OutlineIterator({$from}, {$to},
{$by});");
$this->compiler->code("while ({$var}->next()) {");
}
And at the end of engine.php, add the following new class:
class OutlineIterator {
public $index, $start, $end, $step;
public function __construct($start, $end, $step) {
$this->start = $start;
$this->end = $end;
$this->step = ($end<$start && $step>0 ? -$step : $step);
$this->index = $start - $this->step;
}
public function next() {
$more = ($this->step>0 ? $this->index<$this->end : $this->index>
$this->end);
$this->index += $this->step;
return $more;
}
public function __toString() { return strval($this->index); }
}
This is not very elegant (or fast) yet, so I don't want to commit
this.
__toString() unfortunately is not good enough, as you might rely on
using the index value of the iterator for other things than just
printing it out - if you try to use it as an array index, for example,
you will have problems ... for the time being, you would have to use
something like $myarray[$var->index] instead of $myarray[$var] as
before ...
it's not convenient. I'm thinking about simpler solutions...