Skip to content

Commit

Permalink
- Added support for construct for var in array { ... }
Browse files Browse the repository at this point in the history
The code is natively translated into an equivalent Perl loop: `for my $var(@{array}) {...}`

Example:
	for i in [1,2,3,4] {
		say i;			# prints each element from the array
	}
  • Loading branch information
trizen committed Nov 17, 2015
1 parent 6f5fefb commit 436a730
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 1 deletion.
2 changes: 2 additions & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ lib/Sidef/Types/Block/Do.pm
lib/Sidef/Types/Block/Do.pod
lib/Sidef/Types/Block/For.pm
lib/Sidef/Types/Block/For.pod
lib/Sidef/Types/Block/ForArray.pm
lib/Sidef/Types/Block/Fork.pm
lib/Sidef/Types/Block/Fork.pod
lib/Sidef/Types/Block/Gather.pm
Expand Down Expand Up @@ -607,6 +608,7 @@ scripts/Tests/find_the_missing_permutation.sf
scripts/Tests/first_class_functions_analogously.sf
scripts/Tests/floyds_triangle.sf
scripts/Tests/for_two_vars.sf
scripts/Tests/for_var_in_array.sf
scripts/Tests/forward_difference.sf
scripts/Tests/function_composition.sf
scripts/Tests/functional_modules.sf
Expand Down
3 changes: 3 additions & 0 deletions META.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@
"Sidef::Types::Block::For" : {
"file" : "lib/Sidef/Types/Block/For.pm"
},
"Sidef::Types::Block::ForArray" : {
"file" : "lib/Sidef/Types/Block/ForArray.pm"
},
"Sidef::Types::Block::Fork" : {
"file" : "lib/Sidef/Types/Block/Fork.pm"
},
Expand Down
2 changes: 2 additions & 0 deletions META.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ provides:
file: lib/Sidef/Types/Block/Do.pm
Sidef::Types::Block::For:
file: lib/Sidef/Types/Block/For.pm
Sidef::Types::Block::ForArray:
file: lib/Sidef/Types/Block/ForArray.pm
Sidef::Types::Block::Fork:
file: lib/Sidef/Types/Block/Fork.pm
Sidef::Types::Block::Gather:
Expand Down
7 changes: 7 additions & 0 deletions lib/Sidef/Deparse/Perl.pm
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,13 @@ HEADER
elsif ($ref eq 'Sidef::Types::Block::For') {
## ok
}
elsif ($ref eq 'Sidef::Types::Block::ForArray') {
$code =
'for my '
. $self->deparse_expr({self => $obj->{var}}) . '(@{'
. $self->deparse_expr({self => $obj->{array}}) . '})'
. $self->deparse_bare_block($obj->{block}->{code});
}
elsif ($ref eq 'Sidef::Types::Block::If') {
## ok
}
Expand Down
6 changes: 6 additions & 0 deletions lib/Sidef/Deparse/Sidef.pm
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@ package Sidef::Deparse::Sidef {
elsif ($ref eq 'Sidef::Types::Block::Loop') {
$code = 'loop ' . $self->deparse_expr({self => $obj->{block}});
}
elsif ($ref eq 'Sidef::Types::Block::ForArray') {
$code = 'for '
. $self->deparse_expr({self => $obj->{var}}) . ' in ('
. $self->deparse_expr({self => $obj->{array}}) . ') '
. $self->deparse_bare_block($obj->{block}->{code});
}
elsif ($ref eq 'Sidef::Math::Math') {
$code = 'Math';
}
Expand Down
51 changes: 50 additions & 1 deletion lib/Sidef/Parser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -2243,7 +2243,56 @@ package Sidef::Parser {
if (defined $obj) {
push @{$struct{$self->{class}}}, {self => $obj};

if ($obj_key) {
# for var in array { ... }
if (ref($obj) eq 'Sidef::Types::Block::For' and /\Gfor\h+($self->{var_name_re})\h+in\h+/gc) {
my ($var_name, $class_name) = $self->get_name_and_class($1);

my $array = (
/\G(?=\()/
? $self->parse_arguments(code => $opt{code})
: $self->parse_obj(code => $opt{code})
);

my $variable = Sidef::Variable::Variable->new(
class => $class_name,
name => $var_name,
type => 'var',
);

my $vars_len = $#{$self->{vars}{$class_name}} + 1;

unshift @{$self->{vars}{$class_name}},
{
obj => $variable,
name => $var_name,
count => 1,
type => 'var',
line => $self->{line},
};

my $block = (
/\G\h*(?=\{)/gc
? $self->parse_block(code => $opt{code})
: $self->fatal_error(
error => "expected a block after the token 'in': for $var_name in { ... }",
code => $_,
pos => pos($_),
)
);

# Remove the loop variable from the current scope
splice(@{$self->{vars}{$class_name}}, $#{$self->{vars}{$class_name}} - $vars_len, 1);

# Replace the old Block::For object with Block::ForArray
$struct{$self->{class}}[-1]{self} =
Sidef::Types::Block::ForArray->new(
var => $variable,
block => $block,
array => $array,
);
}

elsif ($obj_key) {
my ($method) = $self->get_method_name(code => $opt{code});
if (defined $method) {

Expand Down
9 changes: 9 additions & 0 deletions lib/Sidef/Types/Block/ForArray.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package Sidef::Types::Block::ForArray {

sub new {
my (undef, %opt) = @_;
bless \%opt, __PACKAGE__;
}
}

1;
29 changes: 29 additions & 0 deletions scripts/Tests/for_var_in_array.sf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/ruby

var arr = [1,2,3,4];

for i in arr {
next if i==2;
if (i == 2) {
die "next error!";
}
}

var i = 42;
assert_eq(i, 42);

for i in arr {
break if i==2;
if (i >= 2) {
die "break error!";
}
}

assert_eq(i, 42);
i = 99;

for i in arr {
say i;
}

assert_eq(i, 99);

0 comments on commit 436a730

Please sign in to comment.