Skip to content

Commit

Permalink
- Fixed a stack bug for while loops with declared variables inside th…
Browse files Browse the repository at this point in the history
…e condition.

Example:
	while (var line = STDIN.readline) {
		say line; 		# now works correctly
		say line._stack_depth;  # always 1
	}

- Improved the `foreach` keyword. Now it calls directly the `Array.each` method.
- Removed the `try` and `loop` keywords from the Parser.
  • Loading branch information
trizen committed Jul 21, 2015
1 parent 3828759 commit d7eb89e
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 50 deletions.
4 changes: 2 additions & 2 deletions lib/Sidef/Exec.pm
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,11 @@ package Sidef::Exec {
my @arguments;
my $method = $call->{method};

if (ref $method eq 'HASH') {
if (ref($method) eq 'HASH') {
$method = $self->execute_expr($method) // '';
}

if (ref $method eq 'Sidef::Variable::Variable') {
if (ref($method) eq 'Sidef::Variable::Variable') {
$method = $method->get_value;
}

Expand Down
21 changes: 18 additions & 3 deletions lib/Sidef/Parser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,6 @@ package Sidef::Parser {
return
for foreach
if while
try loop
given switch
continue
require frequire
Expand Down Expand Up @@ -1986,23 +1985,39 @@ package Sidef::Parser {

if (/\G\h*(?!;)/gc) {

my $before = $#{$self->{ref_vars}->{$self->{class}}};

my $arg = (
/\G(?=\()/ ? $self->parse_arguments(code => $opt{code})
: exists($self->{obj_with_block}{ref $struct{$self->{class}}[-1]{self}})
&& /\G(?=\{)/ ? $self->parse_block(code => $opt{code})
: $self->parse_obj(code => $opt{code})
);

my $after = $#{$self->{ref_vars}->{$self->{class}}};

if (defined $arg) {
my @arg = ($arg);
if (exists $self->{obj_with_block}{ref $struct{$self->{class}}[-1]{self}}
and ref($arg) eq 'HASH') {
@arg = Sidef::Types::Block::Code->new($arg);
my $block = Sidef::Types::Block::Code->new($arg);

if ($before != $after) {
my @vars =
map { $_->{obj} }
grep { ref($_) eq 'HASH' }
@{$self->{ref_vars}->{$self->{class}}}[0 .. ($after - $before - 1)];
if (@vars) {
$block->{_special_stack_vars} = \@vars;
}
}

@arg = ($block);
}
elsif ( ref($struct{$self->{class}}[-1]{self}) eq 'Sidef::Types::Block::For'
and ref($arg) eq 'HASH'
and $#{$arg->{$self->{class}}} == 2) {
@arg = map { Sidef::Types::Block::Code->new($_) } @{$arg->{$self->{class}}};
@arg = (map { Sidef::Types::Block::Code->new($_) } @{$arg->{$self->{class}}});
}

push @{$struct{$self->{class}}[-1]{call}}, {method => $method, arg => \@arg};
Expand Down
5 changes: 5 additions & 0 deletions lib/Sidef/Types/Block/Code.pm
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ package Sidef::Types::Block::Code {
sub while {
my ($self, $condition, $old_self) = @_;

if (exists($condition->{_special_stack_vars}) and not exists($self->{_specialized})) {
$self->{_specialized} = 1;
push @{$self->{vars}}, @{$condition->{_special_stack_vars}};
}

while ($condition->run) {
defined($old_self) && ($old_self->{did_while} //= 1);
if (defined(my $res = $self->_run_code)) {
Expand Down
10 changes: 8 additions & 2 deletions lib/Sidef/Types/Block/For.pm
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,17 @@ package Sidef::Types::Block::For {
$self;
}

*foreach = \&for;
sub foreach {
my ($self, $arr) = @_;
$self->{arg} = $arr;
$self;
}

sub do {
my ($self, $code) = @_;
$code->for(@{$self->{arg}});
ref($self->{arg}) eq 'ARRAY'
? $code->for(@{$self->{arg}})
: $self->{arg}->each($code);
}
};

Expand Down
2 changes: 1 addition & 1 deletion scripts/array_callback.sf
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ for (a.range) { |i|
}

# using the array's items
foreach a { |item|
a.each { |item|
"mycallback(%d) = %d\n".printf(item, mycallback(item));
}

Expand Down
22 changes: 4 additions & 18 deletions scripts/break.sf
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,14 @@ while (i -= 1 >= 10) {
} for (["a","b","c"]);

#
## {...} for {;;}
## for (;;) {...}
#
{
var i;
{
for (var i = 1; i <= 10; i++) {
i.to_s.say;
i == 3 && (break);
i >= 3 && ("Error inside the 'for' loop!\n".die);
} for (i = 1; i<=10; i++);
}
}.run;

#
Expand All @@ -48,27 +47,14 @@ for ["a", "b", "c"] {

say "<<<: "+_;

foreach ["d", "e", "f"] {
for ["d", "e", "f"] {
say ">>>: "+_;
break;
}

if(_=="b"){break};
}

#
## for {;;} {...}
#
{
var i;
for (i = 0; i<= 10; i++) {
"Last result!".say;
break;
};

}.run;


#
## for (array) {...}
#
Expand Down
31 changes: 7 additions & 24 deletions scripts/levenshtein_distance.sf
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,11 @@

func levenshtein (s, t) {

######################################
## This is a valid way of creating a
## two-dimensional array at run-time
######################################

# var d = (Array.make(s.len+1, []));

# for (d.range) {
# d[_] = (Array.make(t.len+1, Num));
# }

######################################
## But I like more the following code:
######################################

func new_array (type, rows, cols) {
(1..rows).map { (1..cols).map{type} }
}

var d = (new_array(Num, s.len+1, t.len+1));

#########END-OF-MY-LIKED-CODE#########
var d = (
(s.len+1).of {
(t.len+1).of(0)
}
);

for (d.range) {
d[_][0] = _;
Expand All @@ -35,10 +18,10 @@ func levenshtein (s, t) {
d[0][_] = _;
}

foreach (1 .. (t.len)) {
(1 .. (t.len)).each {
var j = _;

foreach (1 .. (s.len)) {
(1 .. (s.len)).each {
var i = _;

if (s[i-1] == t[j-1]) {
Expand Down

0 comments on commit d7eb89e

Please sign in to comment.