Skip to content

Commit

Permalink
- Topic variables (_) are better localized now. They are no longer de…
Browse files Browse the repository at this point in the history
…clared in every single block of the program, but only in places where it makes sense.

For example, no topic variable will be generated inside the blocks of a if/else construct.

A side effect of this change is reflected in the calling of blocks as functions: it will fail when called without arguments, because every real-block has a topic variable.

Example:
	var block = { say "hi" };
	block.run;			# perfect
	block.call(nil);		# ok
	block();			# error
  • Loading branch information
trizen committed Dec 10, 2015
1 parent 600f12d commit c723701
Show file tree
Hide file tree
Showing 18 changed files with 85 additions and 80 deletions.
8 changes: 4 additions & 4 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ scripts/permutations_rec.sf
'scripts/Project Euler/0071-ordered_fractions.sf'
'scripts/Project Euler/0076-counting_summations.sf'
'scripts/Project Euler/0077-prime_summations.sf'
'scripts/Project Euler/0080-square_root_digital_expansion.sf'
'scripts/Project Euler/0097-large_non-mersenne_prime.sf'
'scripts/Project Euler/0120-square_remainders.sf'
'scripts/Project Euler/0137-fibonacci_golden_nuggets.sf'
Expand Down Expand Up @@ -506,9 +507,12 @@ scripts/RosettaCode/word_wrap.sf
scripts/RosettaCode/zeckendorf_number_representation.sf
scripts/RosettaCode/zig-zag_matrix.sf
scripts/sets.sf
scripts/sierpinski_carpet.sf
scripts/sierpinski_triangle.sf
scripts/simple_moving_average.sf
scripts/simple_moving_average_oo.sf
scripts/smart_word_wrap.sf
scripts/smart_word_wrap_simple.sf
scripts/space_collisions.sf
scripts/stack.sf
scripts/stern-brocot_sequence.sf
Expand Down Expand Up @@ -695,16 +699,12 @@ scripts/Tests/sidef_executor.sf
scripts/Tests/sidef_keywords.sf
scripts/Tests/sidef_to_json.sf
scripts/Tests/sierpinski_alphabet.sf
scripts/Tests/sierpinski_carpet.sf
scripts/Tests/sierpinski_diamond.sf
scripts/Tests/sierpinski_penta.sf
scripts/Tests/sierpinski_sidef.sf
scripts/Tests/sierpinski_triangle.sf
scripts/Tests/sierpinski_triangle_90.sf
scripts/Tests/sierpinski_x.sf
scripts/Tests/smart_match_operator.sf
scripts/Tests/smart_word_wrap.sf
scripts/Tests/smart_word_wrap_simple.sf
scripts/Tests/sort_disjoint_sublist.sf
scripts/Tests/sort_with_custom_cmp.sf
scripts/Tests/soundex.sf
Expand Down
40 changes: 12 additions & 28 deletions lib/Sidef/Deparse/Perl.pm
Original file line number Diff line number Diff line change
Expand Up @@ -661,14 +661,7 @@ HEADER
$code = 'Sidef::Types::Block::Block->new(code => __SUB__';

if (exists($obj->{init_vars}) and @{$obj->{init_vars}{vars}}) {
my @vars = @{$obj->{init_vars}{vars}};

# Remove the underscore (_) variable
if (@vars > 1 or (@vars == 1 and $vars[0]{name} eq '_')) {
pop @vars;
}

$code .= ', ' . $self->_dump_var_attr(@vars);
$code .= ', ' . $self->_dump_var_attr(@{$obj->{init_vars}{vars}});
}

$code .= ')';
Expand Down Expand Up @@ -750,18 +743,11 @@ HEADER
$code .= "\n" . (" " x ($Sidef::SPACES - $Sidef::SPACES_INCR)) . "code => sub {\n";

if (exists($obj->{init_vars}) and @{$obj->{init_vars}{vars}}) {
my @vars = @{$obj->{init_vars}{vars}};

# Remove the underscore (_) variable
if (@vars > 1) {
pop @vars;
}

$code .= $self->_dump_sub_init_vars(@vars);
$code .= $self->_dump_sub_init_vars(@{$obj->{init_vars}{vars}});
}

if ($is_function) {
$code .= (' ' x $Sidef::SPACES) . 'my @return;' . "\n";
}
if ($is_function) {
$code .= (' ' x $Sidef::SPACES) . 'my @return;' . "\n";
}
}

Expand Down Expand Up @@ -822,14 +808,7 @@ HEADER
}

if (exists($obj->{init_vars}) and @{$obj->{init_vars}{vars}}) {
my @vars = @{$obj->{init_vars}{vars}};

# Remove the underscore (_) variable
if (@vars > 1 or (@vars == 1 and $vars[0]{name} eq '_')) {
pop @vars;
}

$code .= ', ' . $self->_dump_var_attr(@vars);
$code .= ', ' . $self->_dump_var_attr(@{$obj->{init_vars}{vars}});
}
$code .= ')';
}
Expand Down Expand Up @@ -949,7 +928,12 @@ HEADER
}
elsif ($ref eq 'Sidef::Types::Block::Given') {
$self->top_add(qq{use experimental 'smartmatch';\n});
$code = 'do{given ' . $self->deparse_args($obj->{expr}) . $self->deparse_bare_block($obj->{block}{code}) . '}';
my $dvar = $self->_dump_var($obj->{block}{init_vars}->{vars}[0]);
$code =
'do{given (my '
. $dvar . '='
. $self->deparse_args($obj->{expr}) . ')'
. $self->deparse_bare_block($obj->{block}{code}) . '}';
}
elsif ($ref eq 'Sidef::Types::Block::When') {
$code = 'when($_ ~~ ' . $self->deparse_args($obj->{expr}) . ')' . $self->deparse_bare_block($obj->{block}{code});
Expand Down
6 changes: 2 additions & 4 deletions lib/Sidef/Deparse/Sidef.pm
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ package Sidef::Deparse::Sidef {
my $var_obj = delete $block->{init_vars};

$code .= '('
. $self->_dump_vars(@{$var_obj->{vars}}[($obj->{type} eq 'method' ? 1 : 0) .. $#{$var_obj->{vars}} - 1])
. $self->_dump_vars(@{$var_obj->{vars}}[($obj->{type} eq 'method' ? 1 : 0) .. $#{$var_obj->{vars}}])
. ') ';

if (exists $obj->{cached}) {
Expand Down Expand Up @@ -264,8 +264,7 @@ package Sidef::Deparse::Sidef {

local $self->{class} = $obj->{class};
$code .= "class " . $self->_dump_class_name($obj->{name});
my $vars = $obj->{vars};
$code .= '(' . $self->_dump_vars(@{$vars}) . ')';
$code .= '(' . $self->_dump_vars(@{$obj->{vars}}) . ')';
if (exists $obj->{inherit}) {
$code .= ' << ' . join(', ', map { $_->{name} } @{$obj->{inherit}}) . ' ';
}
Expand All @@ -286,7 +285,6 @@ package Sidef::Deparse::Sidef {
$code = '{';
if (exists($obj->{init_vars}) and @{$obj->{init_vars}{vars}}) {
my @vars = @{$obj->{init_vars}{vars}};
pop @vars;
if (@vars) {
$code .= '| ' . $self->_dump_vars(@vars) . ' |';
}
Expand Down
42 changes: 21 additions & 21 deletions lib/Sidef/Parser.pm
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ package Sidef::Parser {

if (/\G(?=\{)/) {
my $code = substr($_, pos);
$self->parse_block(code => \$code);
$self->parse_block(code => \$code, topic_var => 1);
$vars[-1] .= substr($_, pos($_), pos($code));
pos($_) += pos($code);
}
Expand Down Expand Up @@ -733,7 +733,7 @@ package Sidef::Parser {
if (defined($end_delim)) {

if (/\G\h*(?=\{)/gc) {
$where_block = $self->parse_block(code => $opt{code});
$where_block = $self->parse_block(code => $opt{code}, topic_var => 1);
}
elsif (/\G\h*(?=\()/gc) {
$where_expr = $self->parse_arguments(code => $opt{code});
Expand Down Expand Up @@ -978,7 +978,7 @@ package Sidef::Parser {

# Block as object
if (/\G(?=\{)/) {
my $obj = $self->parse_block(code => $opt{code});
my $obj = $self->parse_block(code => $opt{code}, topic_var => 1);
return $obj;
}

Expand Down Expand Up @@ -1593,7 +1593,7 @@ package Sidef::Parser {
local $self->{current_given} = $given_obj;
my $block = (
/\G\h*(?=\{)/gc
? $self->parse_block(code => $opt{code})
? $self->parse_block(code => $opt{code}, topic_var => 1)
: $self->fatal_error(
error => "expected a block after `given(expr)`",
code => $_,
Expand Down Expand Up @@ -2093,7 +2093,7 @@ package Sidef::Parser {
/\G\h*/gc; # remove any horizontal whitespace
my $arg = (
/\G(?=\()/ ? $self->parse_arguments(code => $opt{code})
: /\G(?=\{)/ ? $self->parse_block(code => $opt{code})
: /\G(?=\{)/ ? $self->parse_block(code => $opt{code}, topic_var => 1)
: $self->parse_obj(code => $opt{code})
);

Expand Down Expand Up @@ -2264,21 +2264,19 @@ package Sidef::Parser {
type => 'var');
}

{ # special '_' variable
# Special '_' variable
if ($opt{topic_var} and not @{$var_objs}) {
my $var_obj = bless({name => '_', type => 'var', class => $self->{class}}, 'Sidef::Variable::Variable');
push @{$var_objs}, $var_obj;

my (undef, $code) = $self->find_var('_', $self->{class});
if (not defined($code) or $code == 0) {
unshift @{$self->{vars}{$self->{class}}},
{
obj => $var_obj,
name => '_',
count => 0,
type => 'var',
line => $self->{line},
};
}
push @{$var_objs}, $var_obj;
unshift @{$self->{vars}{$self->{class}}},
{
obj => $var_obj,
name => '_',
count => 0,
type => 'var',
line => $self->{line},
};
}

my $obj = $self->parse_script(code => $opt{code});
Expand Down Expand Up @@ -2347,7 +2345,7 @@ package Sidef::Parser {
my $arg = (
/\G(?=\()/ ? $self->parse_arguments(code => \$code)
: ($req_arg || exists($self->{binpost_ops}{$method})) ? $self->parse_obj(code => \$code)
: /\G(?=\{)/ ? $self->parse_block(code => \$code)
: /\G(?=\{)/ ? $self->parse_block(code => \$code, topic_var => 1)
: die "[PARSING ERROR] Something is wrong in the if condition"
);

Expand Down Expand Up @@ -2594,19 +2592,21 @@ package Sidef::Parser {
and exists $self->{special_constructs}{ref($obj)}
and /\G\h*(?=\{)/gc) {

my $arg = $self->parse_block(code => $opt{code});

if (ref($obj) eq 'Sidef::Types::Block::For') {
if ($#{$struct{$self->{class}}[-1]{call}[-1]{arg}} == 0) {
my $arg = $self->parse_block(code => $opt{code}, topic_var => 1);
$struct{$self->{class}}[-1]{self} = shift @{delete $struct{$self->{class}}[-1]{call}[-1]{arg}};
push @{$struct{$self->{class}}[-1]{call}[-1]{arg}}, $arg;
}
else {
my $arg = $self->parse_block(code => $opt{code});
push @{$struct{$self->{class}}[-1]{call}[-1]{block}}, $arg->{code};
}
}
else {

my $arg = $self->parse_block(code => $opt{code});

push @{$struct{$self->{class}}[-1]{call}[-1]{block}}, $arg->{code};

if (ref($obj) eq 'Sidef::Types::Block::If') {
Expand Down
2 changes: 1 addition & 1 deletion lib/Sidef/Types/Block/Block.pm
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ package Sidef::Types::Block::Block {

my %seen;
my @left_args;
my @vars = @{$method->{vars}};
my @vars = exists($method->{vars}) ? @{$method->{vars}} : ();

foreach my $arg (@args) {
if (ref($arg) eq 'Sidef::Variable::NamedParam') {
Expand Down
25 changes: 25 additions & 0 deletions scripts/Project Euler/0080-square_root_digital_expansion.sf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/ruby

# For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits for all the irrational square roots.

# https://projecteuler.net/problem=80

# Answer: 40886

var sum = 0;
Math.accuracy(102);

for (1 ..^ 100) { |i|

var sr = i.sqrt;
next if sr.is_int;

var x = sr.to_s;
x -= /\./;
x.substr!(0, 100);

sum += x.to_i.digits.sum;
}

say sum.int;
Math.accuracy(0);
6 changes: 3 additions & 3 deletions scripts/Tests/amb.sf
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var w = [
"slowly|,quickly|",
];

for (w.map{'{'+_+'}'}->join.glob) {
_.gsub!('|', ' ') ~~
/\w+?(\w) \1\w+?(\w) \2\w+?(\w) \3\w+/ && (_.say);
for (w.map{'{'+_+'}'}->join.glob) { |i|
i.gsub!('|', ' ') ~~
/\w+?(\w) \1\w+?(\w) \2\w+?(\w) \3\w+/ && (i.say);
}
2 changes: 1 addition & 1 deletion scripts/Tests/classes_and_objects.sf
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
class Task(callback, dependencies=[]) {
method perform {
dependencies.each { .perform };
callback();
callback.run;
}
}

Expand Down
4 changes: 2 additions & 2 deletions scripts/Tests/man_or_boy.sf
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
func a(k, x1, x2, x3, x4, x5) {
func b { a(--k, b, x1, x2, x3, x4) };
k <= 0 ? (x4() + x5()) : b();
};
}

assert_eq(a(10, {1}, {-1}, {-1}, {1}, {0}), -67);
assert_eq(a(10, ->{1}, ->{-1}, ->{-1}, ->{1}, ->{0}), -67);

say "** Test passed!";
2 changes: 1 addition & 1 deletion scripts/Tests/man_or_boy_2.sf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/ruby

func a(k, x1, x2, x3, x4, x5) {
k <= 0 ? (x4() + x5())
k <= 0 ? (x4.run + x5.run)
: func b { a(--k, b, x1, x2, x3, x4) }();
};

Expand Down
2 changes: 1 addition & 1 deletion scripts/Tests/man_or_boy_3.sf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
class Test {
method a(k, x1, x2, x3, x4, x5) {
func b { self.a(--k, b, x1, x2, x3, x4) };
k <= 0 ? (x4() + x5()) : b();
k <= 0 ? (x4.run + x5.run) : b();
}
}

Expand Down
2 changes: 1 addition & 1 deletion scripts/Tests/man_or_boy_cached.sf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

func a(k, x1, x2, x3, x4, x5) is cached -> Number {
func b() -> Number { a(--k, b, x1, x2, x3, x4) };
k <= 0 ? (x4() + x5()) : b();
k <= 0 ? (x4.run + x5.run) : b();
}

assert_eq(a(10, {1}, {-1}, {-1}, {1}, {0}), -67);
Expand Down
8 changes: 4 additions & 4 deletions scripts/Tests/power_numbers.sf
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/ruby

for (1..15) {
var pow = (1 << (_-1) / _);
for (1..15) { |i|
var pow = (1 << (i-1) / i);

var num = (_**_);
{num=(num.sqrt)} * (_-1);
var num = (i**i);
{num=(num.sqrt)} * (i-1);

"%3.0f\t%s\n".printf(num**pow, pow);
}
6 changes: 2 additions & 4 deletions scripts/Tests/run_length_encoding.sf
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ func encode (str) {

var output = Chars.new;

for (chars.range) {
var index = _;
chars.range.each { |index|

if (i > 0 && (chars[index] != lc)) {
output.append(i.to_s + (lc.to_s)); i = 0;
Expand All @@ -33,9 +32,8 @@ func decode (str) {
var acc = '';
var output = '';

for (chars.range) {
chars.range.each { |index|

var index = _;
var sc = chars[index].to_s;

if (sc != ' '){
Expand Down
4 changes: 2 additions & 2 deletions scripts/Tests/run_length_encoding_2.sf
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ func decode (encoded) {

var output = '';

for (encoded) {
output += (_[1].to_s * _[0]);
for i in (encoded) {
output += (i[1].to_s * i[0]);
}

return(output);
Expand Down
2 changes: 1 addition & 1 deletion scripts/continued_fraction.sf
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/ruby

func continued_fraction(a, b, n=100) {
a() + (n > 0 && (b() / continued_fraction(a, b, n-1)));
a.run + (n > 0 && (b.run / continued_fraction(a, b, n-1)));
}

var f = Hash.new(
Expand Down
Loading

0 comments on commit c723701

Please sign in to comment.