diff --git a/bin/sidef b/bin/sidef index 171a7ca6e..46d9f9335 100755 --- a/bin/sidef +++ b/bin/sidef @@ -32,7 +32,7 @@ sub NATIVE () { 0 } my %args; if ($#ARGV != -1 and chr ord $ARGV[0] eq '-') { require Getopt::Std; - Getopt::Std::getopts('e:E:d:Dho:ivHn:WwbcrR:ts:C', \%args); + Getopt::Std::getopts('e:E:d:Dho:ivHn:WwbcrR:ts:CO:', \%args); } # Help @@ -180,9 +180,6 @@ else { my $header = "\nuse lib (" . join(', ', map { qq{"\Q$_\E"} } @INC) . ");\n" . "use Sidef;\n"; $deparsed = $header . $deparsed; } - else { - warn "\n# NOTE: deparsing to Sidef is not fully implemented!\n\n"; - } output($deparsed); } @@ -233,7 +230,35 @@ sub optimize_struct { sub parse_code { my ($parser, $code) = @_; - scalar $parser->parse_script(code => \$code); + + my $struct = $parser->parse_script(code => \$code); + + # Check for optimization + if (defined($args{O})) { + + # Optimize the AST + if ($args{O} >= 1) { + $struct = optimize_struct($struct); + } + + # Deparse the AST into code, then parse the code again. + if ($args{O} >= 2) { + my $deparser = Sidef::Deparse::Sidef->new(namespaces => [@Sidef::NAMESPACES]); + my $code = $deparser->deparse($struct); + + local %Sidef::INCLUDED; + local @Sidef::NAMESPACES; + + $struct = Sidef::Parser->new( + file_name => $parser->{file_name}, + script_name => $parser->{script_name}, + )->parse_script(code => \$code); + + $struct = optimize_struct($struct); + } + } + + $struct; } sub load_math_backend { @@ -264,6 +289,7 @@ sub output_usage { '-d file' => 'load a dumped syntax tree', '-D' => 'dump the syntax tree of a program', '-o file' => 'file where to dump the output', + '-O level' => ['perform code optimizations before execution', 'valid levels: 0, 1, 2'], '-E program' => 'one line of program', '-H' => 'interactive help', '-n type' => ['try to use a specific backend for Math::BigInt', 'valid types: GMP, Pari, FastCalc'], @@ -342,7 +368,8 @@ HELP my $parser = new_parser(name => '-H'); $parser->{interactive} = 1; - my $struct = eval { $parser->parse_script(code => \$line) }; + + my $struct = eval { parse_code($parser, $line) }; if ($@) { warn $@; @@ -445,18 +472,15 @@ EOT } # Remove 'var' declarations (if any) - $line =~ s/^\h*var\b\h*//; + if (not defined($args{r}) and not defined($args{R})) { + $line =~ s/^\h*var\b\h*//; + } $last_line = $line; - - my $struct = eval { $parser->parse_script(code => \$line) }; + my $struct = eval { parse_code($parser, $line) }; $@ && do { warn $@; - - # $parser = new_parser(name => '-i'); - # $parser->{interactive} = 1; - redo; }; @@ -546,7 +570,7 @@ sub dump_structure { print {$out_fh} _get_namespaces(); print {$out_fh} "use Math::BigFloat;\n"; print {$out_fh} $requirify->(_get_loaded_modules()); - print {$out_fh} Data::Dump::pp($struct); + print {$out_fh} Data::Dump::pp($struct) . "\n"; } } @@ -603,7 +627,7 @@ HEAD close $fh; } - } + } } => $path ); diff --git a/lib/Sidef/Deparse/Perl.pm b/lib/Sidef/Deparse/Perl.pm index c728b4e59..08409504c 100644 --- a/lib/Sidef/Deparse/Perl.pm +++ b/lib/Sidef/Deparse/Perl.pm @@ -107,7 +107,7 @@ HEADER } } - sub _get_reftype { + sub _dump_reftype { my ($self, $obj) = @_; my $ref = ref($obj); @@ -326,7 +326,7 @@ HEADER if (exists($var->{ref_type})) { my $var_name = "\$$var->{name}" . refaddr($var); - my $type = $self->_get_reftype($var->{ref_type}); + my $type = $self->_dump_reftype($var->{ref_type}); $code .= (' ' x $Sidef::SPACES) . "(ref($var_name) eq $type || ($type ne 'REF' && eval{$var_name->SUPER::isa($type)})) or " @@ -418,9 +418,14 @@ HEADER sub deparse_bare_block { my ($self, @args) = @_; - $self->deparse_generic("{\n" . " " x ($Sidef::SPACES + $Sidef::SPACES_INCR), - ";\n" . (" " x ($Sidef::SPACES + $Sidef::SPACES_INCR)), - "\n" . (" " x $Sidef::SPACES) . "}", @args); + + $Sidef::SPACES += $Sidef::SPACES_INCR; + my $code = $self->deparse_generic("{\n" . " " x ($Sidef::SPACES), + ";\n" . (" " x ($Sidef::SPACES)), + "\n" . (" " x ($Sidef::SPACES - $Sidef::SPACES_INCR)) . "}", @args); + $Sidef::SPACES -= $Sidef::SPACES_INCR; + + $code; } sub deparse_expr { @@ -433,7 +438,7 @@ HEADER # Self obj my $ref = ref($obj); if ($ref eq 'HASH') { - $code = join(', ', $self->deparse_script($obj)); + $code = join(', ', exists($obj->{self}) ? $self->deparse_expr($obj) : $self->deparse_script($obj)); } elsif ($ref eq 'Sidef::Variable::Variable') { if ($obj->{type} eq 'var') { @@ -498,7 +503,7 @@ HEADER # Check the return value (when "-> Type" is specified) if (exists $obj->{returns}) { - my $type = $self->_get_reftype($obj->{returns}); + my $type = $self->_dump_reftype($obj->{returns}); $code = "do { $code;\n" @@ -634,9 +639,7 @@ HEADER } } elsif ($ref eq 'Sidef::Variable::ConstInit') { - foreach my $var (@{$obj->{vars}}) { - $code .= $self->deparse_expr({self => $var}) . ";\n"; - } + $code = join(";\n" . (" " x $Sidef::SPACES), map { $self->deparse_expr({self => $_}) } @{$obj->{vars}}); } elsif ($ref eq 'Sidef::Variable::Init') { $code = $self->_dump_init_vars($obj); @@ -860,20 +863,10 @@ HEADER $code = $self->make_constant($ref, '__NEW__', "MOD_F$refaddr", $self->_dump_string($obj->{module})); } elsif ($ref eq 'Sidef::Types::Block::Break') { - if (not exists $expr->{call}) { - $code = 'last'; - } - else { - die "[ERROR] Arguments and method calls for 'break' are not supported!"; - } + $code = 'last'; } elsif ($ref eq 'Sidef::Types::Block::Next') { - if (not exists $expr->{call}) { - $code = 'next'; - } - else { - die "[ERROR] Arguments and method calls for 'next' are not supported!"; - } + $code = 'next'; } elsif ($ref eq 'Sidef::Types::Block::Continue') { $code = 'continue'; @@ -947,7 +940,7 @@ HEADER $code = $self->make_constant($ref, 'new', "Sig$refaddr"); } elsif ($ref eq 'Sidef::Types::Number::Complex') { - $code = $self->make_constant($ref, 'new', "Complex$refaddr"); + $code = $self->make_constant($ref, 'new', "Complex$refaddr", "'" . ${$obj}->Re . "'", "'" . ${$obj}->Im . "'"); } elsif ($ref eq 'Sidef::Types::Array::Pair') { $code = $ref . '->new'; @@ -969,12 +962,7 @@ HEADER $code = $self->_dump_array('Sidef::Types::Array::Array', $obj); } elsif ($ref eq 'Sidef::Types::Nil::Nil') { - if (not exists $expr->{call}) { - $code = 'undef'; - } - else { - die "[ERROR] Arguments and method calls for 'nil' are not supported!"; - } + $code = 'undef'; } elsif ($ref eq 'Sidef::Types::Null::Null') { $code = $self->make_constant($ref, 'new', "Null$refaddr"); @@ -1230,8 +1218,9 @@ HEADER } } - if (ref($method) eq 'HASH') { - $code .= '->${\\do{' . $self->deparse_expr($method) . '}}'; + if (ref($method)) { + $code .= + '->${\\do{' . $self->deparse_expr(ref($method) eq 'HASH' ? $method : {self => $method}) . '}}'; } elsif ($method =~ /^[\pL_]/) { @@ -1304,7 +1293,7 @@ HEADER if (exists $call->{block}) { if ($ref eq 'Sidef::Types::Block::Given' or ($ref eq 'Sidef::Types::Block::If' and $i == $#{$expr->{call}})) { - $code = "do { " . $code . $self->deparse_bare_block(@{$call->{block}}) . '}'; + $code = "do {\n" . (' ' x $Sidef::SPACES) . $code . $self->deparse_bare_block(@{$call->{block}}) . '}'; } else { $code .= $self->deparse_bare_block(@{$call->{block}}); @@ -1330,11 +1319,24 @@ HEADER push @results, ref($expr) eq 'HASH' ? $self->deparse_expr($expr) : $self->deparse_expr({self => $expr}); - if ($i > 0 and ref($struct->{$class}[$i - 1]{self}) eq 'Sidef::Variable::Label') { - $results[-1] = $struct->{$class}[$i - 1]{self}->{name} . ':' . $results[-1]; + if ( + $i > 0 + and ( + ref($expr) eq 'Sidef::Variable::Label' + or ( ref($struct->{$class}[$i - 1]) eq 'HASH' + and ref($struct->{$class}[$i - 1]{self}) eq 'Sidef::Variable::Label') + ) + ) { + $results[-1] = + (ref($expr) eq 'Sidef::Variable::Label' ? $expr->{name} : $struct->{$class}[$i - 1]{self}->{name}) . ':' + . $results[-1]; } - elsif ($i == $max and ref($expr->{self}) eq 'Sidef::Variable::Label') { - $results[-1] = $expr->{self}{name} . ':'; + elsif ( + $i == $max + and (ref($expr) eq 'Sidef::Variable::Label' + or (ref($expr) eq 'HASH' and ref($expr->{self}) eq 'Sidef::Variable::Label')) + ) { + $results[-1] = (ref($expr) eq 'Sidef::Variable::Label' ? $expr->{name} : $expr->{self}{name}) . ':'; } } } diff --git a/lib/Sidef/Deparse/Sidef.pm b/lib/Sidef/Deparse/Sidef.pm index ceff2e1ba..ef53d3277 100644 --- a/lib/Sidef/Deparse/Sidef.pm +++ b/lib/Sidef/Deparse/Sidef.pm @@ -27,9 +27,61 @@ package Sidef::Deparse::Sidef { bless \%opts, __PACKAGE__; } + sub deparse_generic { + my ($self, $before, $sep, $after, @args) = @_; + $before . join( + $sep, + map { + ref($_) eq 'HASH' ? $self->deparse_script($_) + : ref($_) ? $self->deparse_expr({self => $_}) + : $self->_dump_string($_) + } @args + ) + . $after; + } + + sub deparse_args { + my ($self, @args) = @_; + $self->deparse_generic('(', ', ', ')', @args); + } + + sub deparse_block_expr { + my ($self, @args) = @_; + $self->deparse_generic('do{', ';', '}', @args); + } + + sub deparse_bare_block { + my ($self, @args) = @_; + + $Sidef::SPACES += $Sidef::SPACES_INCR; + my $code = $self->deparse_generic("{\n" . " " x ($Sidef::SPACES), + ";\n" . (" " x ($Sidef::SPACES)), + "\n" . (" " x ($Sidef::SPACES - $Sidef::SPACES_INCR)) . "}", @args); + + $Sidef::SPACES -= $Sidef::SPACES_INCR; + + $code; + } + sub _dump_init_vars { - my ($self, @init_vars) = @_; - $self->_dump_vars(map { @{$_->{vars}} } @init_vars); + my ($self, $init_obj) = @_; + my $code = 'var(' . $self->_dump_vars(@{$init_obj->{vars}}) . ')'; + + if (exists $init_obj->{args}) { + $code .= '=' . $self->deparse_args($init_obj->{args}); + } + + $code; + } + + sub _dump_reftype { + my ($self, $obj) = @_; + + my $ref = ref($obj); + + $ref eq 'Sidef::Variable::ClassInit' ? $obj->{name} + : $ref eq 'Sidef::Types::Block::CodeInit' ? 'Block' + : substr($ref, rindex($ref, '::') + 2); } sub _dump_vars { @@ -39,17 +91,28 @@ package Sidef::Deparse::Sidef { map { (exists($_->{array}) ? '*' : exists($_->{hash}) ? ':' : '') . (exists($_->{class}) && $_->{class} ne $self->{class} ? $_->{class} . '::' : '') + . (exists($_->{ref_type}) ? ($self->_dump_reftype($_->{ref_type}) . ' ') : '') . $_->{name} . ( - ref($_->{value}) eq 'Sidef::Types::Nil::Nil' ? '' : do { - my $type = $self->deparse_expr({self => $_->{value}}); - $type =~ /^[[:alpha:]_]\w*\z/ ? " is $type" : "=$type"; + exists($_->{value}) ? do { + my $value = $self->deparse_expr({self => $_->{value}}); + "=($value)"; } + : '' ) } @vars ); } + sub _dump_string { + my ($self, $str) = @_; + + state $x = eval { require Data::Dump }; + $x || return ('"' . quotemeta($str) . '"'); + + Data::Dump::quote($str); + } + sub _dump_array { my ($self, $array) = @_; '[' . join( @@ -63,8 +126,8 @@ package Sidef::Deparse::Sidef { } sub _dump_class_name { - my ($self, $name) = @_; - ref($name) ? $self->deparse_expr({self => $name}) : $name; + my ($self, $class) = @_; + ref($class) ? $self->_dump_reftype($class) : $class; } sub deparse_expr { @@ -107,13 +170,26 @@ package Sidef::Deparse::Sidef { $code .= $obj->{type} . ' ' . $obj->{name}; local $self->{class} = $obj->{class}; - my $vars = delete $block->{init_vars}; - $code .= '(' . $self->_dump_init_vars(@{$vars}[($obj->{type} eq 'method' ? 1 : 0) .. $#{$vars} - 1]) . ')'; + my $var_obj = delete $block->{init_vars}; + + $code .= '(' + . $self->_dump_vars(@{$var_obj->{vars}}[($obj->{type} eq 'method' ? 1 : 0) .. $#{$var_obj->{vars}} - 1]) + . ') '; + + #$code .= $self->_dump_sub_init_vars($vars); + #$code .= $self->_dump_init_vars($vars); + #$code .= '(' . $self->_dump_init_vars(@{$vars}[($obj->{type} eq 'method' ? 1 : 0) .. $#{$vars} - 1]) . ')'; + + if (exists $obj->{cached}) { + $code .= 'is cached '; + } + if (exists $obj->{returns}) { - $code .= ' -> ' . $self->deparse_expr({self => $obj->{returns}}) . ' '; + $code .= '-> ' . $self->deparse_expr({self => $obj->{returns}}) . ' '; } + $code .= $self->deparse_expr({self => $block}); - $block->{init_vars} = $vars; + $block->{init_vars} = $var_obj; if ($in_module) { $code .= "\n}"; @@ -141,8 +217,53 @@ package Sidef::Deparse::Sidef { elsif ($ref eq 'Sidef::Variable::Local') { $code = "$obj->{name}"; } + elsif ($ref eq 'Sidef::Variable::Global') { + $code = 'global ' . $obj->{class} . '::' . $obj->{name},; + } elsif ($ref eq 'Sidef::Variable::Init') { - $code = "$obj->{vars}[0]{type}\(" . $self->_dump_init_vars($obj) . ')'; + $code = $self->_dump_init_vars($obj); + } + elsif ($ref eq 'Sidef::Variable::ConstInit') { + $code = join(";\n" . (" " x $Sidef::SPACES), map { $self->deparse_expr({self => $_}) } @{$obj->{vars}}); + } + elsif ($ref eq 'Sidef::Variable::LocalInit') { + $code = 'local ' . $obj->{class} . '::' . $obj->{name}; + } + elsif ($ref eq 'Sidef::Variable::LocalMagic') { + $code = 'local ' . $obj->{name}; + } + elsif ($ref eq 'Sidef::Types::Range::RangeNumber' or $ref eq 'Sidef::Types::Range::RangeString') { + $code = $self->_dump_reftype($obj); + } + elsif ($ref eq 'Sidef::Variable::Define') { + my $name = $obj->{name}; + if (not exists $obj->{inited}) { + $obj->{inited} = 1; + $code = "define $name = (" . $self->deparse_script($obj->{expr}) . ')'; + } + else { + $code = $name; + } + } + elsif ($ref eq 'Sidef::Variable::Const') { + my $name = $obj->{name}; + if (not exists $obj->{inited}) { + $obj->{inited} = 1; + $code = "const $name = (" . $self->deparse_script($obj->{expr}) . ')'; + } + else { + $code = $name; + } + } + elsif ($ref eq 'Sidef::Variable::Static') { + my $name = $obj->{name}; + if (not exists $obj->{inited}) { + $obj->{inited} = 1; + $code = "static $name = (" . $self->deparse_script($obj->{expr}) . ')'; + } + else { + $code = $name; + } } elsif ($ref eq 'Sidef::Variable::ClassInit') { if ($addr{refaddr($obj)}++) { @@ -168,7 +289,7 @@ package Sidef::Deparse::Sidef { my $vars = $obj->{__VARS__}; $code .= '(' . $self->_dump_vars(@{$vars}) . ')'; if (exists $obj->{inherit}) { - $code .= ' << ' . join(', ', @{$obj->{inherit}}) . ' '; + $code .= ' << ' . join(', ', map { $_->{name} } @{$obj->{inherit}}) . ' '; } $code .= $self->deparse_expr({self => $block}); @@ -178,21 +299,28 @@ package Sidef::Deparse::Sidef { } } } - elsif ($ref eq 'Sidef::Types::Block::Code') { + elsif ($ref eq 'Sidef::Types::Block::CodeInit') { if ($addr{refaddr($obj)}++) { $code = keys(%{$obj}) ? '__BLOCK__' : 'Block'; } else { if (keys(%{$obj})) { $code = '{'; - if (exists($obj->{init_vars}) and @{$obj->{init_vars}} > 1) { - my $vars = $obj->{init_vars}; - $code .= '|' . $self->_dump_init_vars(@{$vars}[0 .. $#{$vars} - 1]) . "|"; + 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) . "|"; + } } $Sidef::SPACES += $Sidef::SPACES_INCR; my @statements = $self->deparse_script($obj->{code}); + if (@statements) { + $statements[-1] = '(' . $statements[-1] . ')'; + } + $code .= @statements ? ("\n" @@ -216,12 +344,21 @@ package Sidef::Deparse::Sidef { elsif ($ref eq 'Sidef::Sys::Sys') { $code = exists($obj->{file_name}) ? '' : 'Sys'; } + elsif ($ref eq 'Sidef::Eval::Eval') { + $code = 'eval(' . $self->deparse_script($obj->{expr}) . ')'; + } elsif ($ref eq 'Sidef::Parser') { $code = 'Parser'; } elsif ($ref eq 'Sidef') { $code = 'Sidef'; } + elsif ($ref eq 'Sidef::Variable::NamedParam') { + $code = $obj->[0] . ':' . $self->deparse_args(@{$obj->[1]}); + } + elsif ($ref eq 'Sidef::Variable::Label') { + $code = '@:' . $obj->{name}; + } elsif ($ref eq 'Sidef::Variable::LazyMethod') { $code = 'LazyMethod'; } @@ -230,6 +367,9 @@ package Sidef::Deparse::Sidef { $code = 'break'; } } + elsif ($ref eq 'Sidef::Types::Block::Default') { + $code = 'default' . $self->deparse_bare_block($obj->{block}->{code}); + } elsif ($ref eq 'Sidef::Types::Block::Next') { if (not exists $expr->{call}) { $code = 'next'; @@ -243,22 +383,26 @@ package Sidef::Deparse::Sidef { $code = 'return'; } } + elsif ($ref eq 'Sidef::Types::Bool::Ternary') { + $code = '(' + . $self->deparse_script($obj->{cond}) . ' ? ' + . $self->deparse_args($obj->{true}) . ' : ' + . $self->deparse_args($obj->{false}) . ')'; + } elsif ($ref eq 'Sidef::Module::OO') { - $code = "%s($obj->{module})"; + $code = '%s' . $self->_dump_string($obj->{module}); } elsif ($ref eq 'Sidef::Module::Func') { - $code = "%S($obj->{module})"; + $code = '%S' . $self->_dump_string($obj->{module}); } elsif ($ref eq 'Sidef::Types::Array::List') { $code = join(', ', map { $self->deparse_expr({self => $_}) } @{$obj}); } elsif ($ref eq 'Sidef::Types::Block::Gather') { - if (exists $addr{refaddr($obj->{block})}) { - $code = ''; - } - else { - return 'gather ' . $self->deparse_expr({self => $obj->{block}}); - } + $code = 'gather ' . $self->deparse_expr({self => $obj->{block}}); + } + elsif ($ref eq 'Sidef::Types::Block::Take') { + $code = 'take' . $self->deparse_args($obj->{expr}); } elsif ($ref eq 'Sidef::Math::Math') { $code = 'Math'; @@ -286,7 +430,8 @@ package Sidef::Deparse::Sidef { seek($obj->{fh}, 0, 0); $self->{after} .= "\n__DATA__\n" . do { local $/; - readline($obj->{fh}); + require Encode; + Encode::decode_utf8(readline($obj->{fh})); }; seek($obj->{fh}, $orig_pos, 0); $addr{$obj->{fh}} = 1; @@ -294,31 +439,7 @@ package Sidef::Deparse::Sidef { } } elsif ($ref eq 'Sidef::Variable::Magic') { - - state $magic_vars = { - \$. => '$.', - \$? => '$?', - \$$ => '$$', - \$^T => '$^T', - \$| => '$|', - \$! => '$!', - \$" => '$"', - \$\ => '$\\', - \$/ => '$/', - \$; => '$;', - \$, => '$,', - \$^O => '$^O', - \$^X => '$^PERL', - \$0 => '$0', - \$( => '$(', - \$) => '$)', - \$< => '$<', - \$> => '$>', - }; - - if (exists $magic_vars->{$obj->{ref}}) { - $code = $magic_vars->{$obj->{ref}}; - } + $code = $obj->{name}; } elsif ($ref eq 'Sidef::Types::Hash::Hash') { $code = keys(%{$obj}) ? $obj->dump->get_value : 'Hash'; @@ -335,16 +456,29 @@ package Sidef::Deparse::Sidef { elsif ($ref eq 'Sidef::Sys::SIG') { $code = 'Sig'; } - elsif ($ref eq 'Sidef::Types::Number::Complex') { - $code = reftype($obj) eq 'HASH' ? 'Complex' : $obj->dump->get_value; - } elsif ($ref eq 'Sidef::Types::Number::Number') { my $value = $obj->get_value; my $num = ref($value) ? ref($value) eq 'Math::BigRat' ? $value->numify : $value->bstr : $value; - $code = lc($num) eq 'inf' ? '0.inf' : lc($num) eq 'nan' ? '0.nan' : $num; + $code = + $num eq '0' ? 'Number' + : lc($num) eq 'inf' ? '0.inf' + : lc($num) eq '-inf' ? "0.inf('-')" + : lc($num) eq 'nan' ? '0.nan' + : $num; } elsif ($ref eq 'Sidef::Types::Array::Array' or $ref eq 'Sidef::Types::Array::HCArray') { - $code = $self->_dump_array($obj); + if (not @{$obj}) { + $code = 'Array'; + } + else { + $code = $self->_dump_array($obj); + } + } + elsif ($ref eq 'Sidef::Types::Nil::Nil') { + $code = 'nil'; + } + elsif ($ref eq 'Sidef::Object::Object') { + $code = 'Object'; } elsif ($ref =~ /^Sidef::/ and $obj->can('dump')) { $code = $obj->dump->get_value; @@ -354,6 +488,12 @@ package Sidef::Deparse::Sidef { $code = 'Backtick'; } } + + elsif ($ref eq 'Sidef::Types::Number::Complex') { + if (${$obj} == 0) { + $code = 'Complex'; + } + } elsif ($ref eq 'Sidef::Types::Regex::Regex') { if ($code eq '//') { $code = 'Regex'; @@ -365,13 +505,13 @@ package Sidef::Deparse::Sidef { } } elsif ($ref eq 'Sidef::Types::Array::Pair') { - if ( ref($obj->[0]->get_value) eq 'Sidef::Types::Nil::Nil' - and ref($obj->[1]->get_value) eq 'Sidef::Types::Nil::Nil') { + if ( not defined($obj->[0]) + and not defined($obj->[1])) { $code = 'Pair'; } } elsif ($ref eq 'Sidef::Types::Byte::Bytes') { - if ($#{$obj} == -1) { + if (not @{$obj}) { $code = 'Bytes'; } } @@ -381,10 +521,20 @@ package Sidef::Deparse::Sidef { } } elsif ($ref eq 'Sidef::Types::Char::Chars') { - if ($#{$obj} == -1) { + if (not @{$obj}) { $code = 'Chars'; } } + elsif ($ref eq 'Sidef::Types::Grapheme::Grapheme') { + if (${$obj} eq "\0") { + $code = 'Grapheme'; + } + } + elsif ($ref eq 'Sidef::Types::Grapheme::Graphemes') { + if (not @{$obj}) { + $code = 'Graphemes'; + } + } elsif ($ref eq 'Sidef::Types::Glob::Dir') { if (${$obj} eq '') { $code = 'Dir'; @@ -401,12 +551,12 @@ package Sidef::Deparse::Sidef { } } elsif ($ref eq 'Sidef::Types::Array::MultiArray') { - if ($#{$obj} == -1) { + if (not @{$obj}) { $code = 'MultiArr'; } } elsif ($ref eq 'Sidef::Types::Glob::Pipe') { - if ($#{$obj} == -1) { + if (not @{$obj}) { $code = 'Pipe'; } } @@ -419,64 +569,100 @@ package Sidef::Deparse::Sidef { } } + if (exists $expr->{lookup}) { + foreach my $lookup (@{$expr->{lookup}}) { + $code .= '{' + . join(',', + map { ref($_) eq 'HASH' ? ($self->deparse_expr($_)) : $self->deparse_generic('', '', '', $_) } + @{$lookup}) + . '}'; + } + } + # Method call on the self obj (+optional arguments) if (exists $expr->{call}) { - foreach my $call (@{$expr->{call}}) { + foreach my $i (0 .. $#{$expr->{call}}) { + + my $call = $expr->{call}[$i]; my $method = $call->{method}; - if (ref($method) ne '') { - $method = ( - '(' - . $self->deparse_expr( - ref($method) eq 'HASH' - ? $method - : {self => $method} - ) - . ')' - ); + if (defined $method and $method eq 'call' and exists $call->{arg}) { + undef $method; } - if ($code eq 'Hash' and $method eq ':') { - $method = 'new'; - } - elsif ($code =~ /\.\w+\z/ && $method =~ /^[?!:]/) { - $code = '(' . $code . ')'; - } - elsif ($code =~ /^\w+\z/ and $method eq ':') { - $code = '(' . $code . ')'; - } + if (defined $method) { + + if (ref($method) ne '') { + $code .= '.' + . ( + '(' + . $self->deparse_expr( + ref($method) eq 'HASH' + ? $method + : {self => $method} + ) + . ')' + ); - if ($method =~ /^[[:alpha:]_(]/) { - $code .= '.' if $code ne ''; - $code .= $method; + } + elsif ($method =~ /^[\pL_]/) { + + if ($ref eq 'Sidef::Types::Block::CodeInit' and $method eq 'loop') { + $code = "loop $code"; + } + else { + + if ($code ne '') { + $code .= '->'; + } + + $code .= $method; + } + } + else { + + if ($method eq '@') { + $code .= ".$method"; + } + elsif ($method eq '@*') { + $code = "\@($code)"; + } + else { + if ($ref eq 'Sidef::Variable::Ref' or $ref eq 'Sidef::Object::Unary') { + $code .= $method; + } + else { + $code = "($code) $method "; + } + } + } } - else { - $code .= $method; + + if (exists $call->{keyword}) { + if ($code ne '') { + $code .= ' '; + } + $code .= $call->{keyword}; } if (exists $call->{arg}) { - my $i = 0; - $code .= '(' . join( - ', ', - map { $_ eq '' ? '()' : $_ } - map { - ++$i; - ref($_) eq 'HASH' ? $self->deparse_script($_) - : $i == 1 - && exists($self->{obj_with_block}{$ref}) - && exists($self->{obj_with_block}{$ref}{$method}) ? $self->deparse_expr({self => $_->{code}}) - : $ref eq 'Sidef::Types::Block::For' - && (($#{$call->{arg}} == 2) || $#{$call->{arg}} == 3) - && $i <= 3 && ref($_) eq 'Sidef::Types::Block::Code' ? $self->deparse_expr($_->{code}) - : ref($_) ? $self->deparse_expr({self => $_}) - : Sidef::Types::String::String->new($_)->dump->get_value - } @{$call->{arg}} - ) - . ')'; + if ($ref eq 'Sidef::Types::Block::For') { + $code .= '(' . join(';', map { $self->deparse_args($_) } @{$call->{arg}}) . ')'; + } + else { + $code .= $self->deparse_args(@{$call->{arg}}); + } } - if ($code eq 'Hash.new()') { - $code = 'Hash.new'; + if (exists $call->{block}) { + if ($ref eq 'Sidef::Types::Block::Given' + or ($ref eq 'Sidef::Types::Block::If' and $i == $#{$expr->{call}})) { + $code .= $self->deparse_bare_block(@{$call->{block}}); + } + else { + $code .= $self->deparse_bare_block(@{$call->{block}}); + } + next; } } } diff --git a/lib/Sidef/Optimizer.pm b/lib/Sidef/Optimizer.pm index e342e0a31..f84090796 100644 --- a/lib/Sidef/Optimizer.pm +++ b/lib/Sidef/Optimizer.pm @@ -1,6 +1,7 @@ package Sidef::Optimizer { use 5.014; + require Scalar::Util; use constant { STRING => 'Sidef::Types::String::String', @@ -491,7 +492,6 @@ package Sidef::Optimizer { ## ok } elsif ($obj->{type} eq 'func' or $obj->{type} eq 'method') { - state $x = require Scalar::Util; if ($addr{Scalar::Util::refaddr($obj)}++) { ## ok } @@ -501,7 +501,6 @@ package Sidef::Optimizer { } } elsif ($ref eq 'Sidef::Variable::ClassInit') { - state $x = require Scalar::Util; if ($addr{Scalar::Util::refaddr($obj)}++) { ## ok } @@ -509,8 +508,18 @@ package Sidef::Optimizer { $obj->{__BLOCK__} = $self->optimize_expr({self => $obj->{__BLOCK__}}); } } - elsif ($ref eq 'Sidef::Types::Block::Code') { - state $x = require Scalar::Util; + elsif ($ref eq 'Sidef::Variable::Init') { + if ($addr{Scalar::Util::refaddr($obj)}++) { + ## ok + } + else { + if (exists $obj->{args}) { + my %code = $self->optimize($obj->{args}); + $obj->{args} = \%code; + } + } + } + elsif ($ref eq 'Sidef::Types::Block::CodeInit') { if ($addr{Scalar::Util::refaddr($obj)}++) { ## ok } @@ -527,23 +536,31 @@ package Sidef::Optimizer { } } - if (not exists $expr->{ind} and not exists $expr->{call}) { - return $obj; + if (not exists($expr->{ind}) and not exists($expr->{lookup}) and not exists($expr->{call})) { + return (ref($obj) eq 'HASH' ? {self => $obj} : $obj); } $obj = { self => $obj, - (exists($expr->{ind}) ? (ind => []) : ()), - (exists($expr->{call}) ? (call => []) : ()), + (exists($expr->{ind}) ? (ind => []) : ()), + (exists($expr->{lookup}) ? (lookup => []) : ()), + (exists($expr->{call}) ? (call => []) : ()), }; - # Indices + # Array indices if (exists $expr->{ind}) { foreach my $i (0 .. $#{$expr->{ind}}) { $obj->{ind}[$i] = [map { $self->optimize_expr($_) } @{$expr->{ind}[$i]}]; } } + # Hash lookup + if (exists $expr->{lookup}) { + foreach my $i (0 .. $#{$expr->{lookup}}) { + $obj->{lookup}[$i] = [map { ref($_) eq 'HASH' ? $self->optimize_expr($_) : $_ } @{$expr->{lookup}[$i]}]; + } + } + # Method call on the self obj (+optional arguments) if (exists $expr->{call}) { @@ -555,17 +572,32 @@ package Sidef::Optimizer { # Method call my $method = $call->{method}; - if (ref($method) eq 'HASH') { - $method = $self->optimize_expr($method) // {self => {}}; - } - $obj->{call}[$i] = {method => $method}; + if (defined $method) { + if (ref($method) eq 'HASH') { + $method = $self->optimize_expr($method) // {self => {}}; + } + + $obj->{call}[$i] = {method => $method}; + } + elsif (exists $call->{keyword}) { + $obj->{call}[$i] = {keyword => $call->{keyword}}; + } # Method arguments if (exists $call->{arg}) { foreach my $j (0 .. $#{$call->{arg}}) { my $arg = $call->{arg}[$j]; - push @{$obj->{call}[$i]{arg}}, + push @{$obj->{call}[$i]{arg}}, ref $arg eq 'HASH' + && $ref_obj ne 'Sidef::Types::Block::For' ? do { my %arg = $self->optimize($arg); \%arg } : $arg; + } + } + + # Block + if (exists $call->{block}) { + foreach my $j (0 .. $#{$call->{block}}) { + my $arg = $call->{block}[$j]; + push @{$obj->{call}[$i]{block}}, ref $arg eq 'HASH' ? do { my %arg = $self->optimize($arg); \%arg } : $arg; } } @@ -577,6 +609,7 @@ package Sidef::Optimizer { if ( defined($ref_obj) and exists($rules{$ref_obj}) and not exists($expr->{ind}) + and not exists($expr->{lookup}) and ref($method) eq '') { my $code = $ref_obj->SUPER::can($method); @@ -632,7 +665,7 @@ package Sidef::Optimizer { if ($count > 0) { if ($count == @{$obj->{call}}) { - if (not exists $expr->{ind}) { + if (not exists $expr->{ind} and not exists $expr->{lookup}) { return $obj->{self}; } else { diff --git a/lib/Sidef/Parser.pm b/lib/Sidef/Parser.pm index 7122a4b9b..73c51ecd1 100644 --- a/lib/Sidef/Parser.pm +++ b/lib/Sidef/Parser.pm @@ -448,7 +448,9 @@ package Sidef::Parser { elsif ($self->{interactive}) { # Minor exception for interactive mode - ++$variable->{obj}{in_use}; + if (ref $variable->{obj} eq 'HASH') { + ++$variable->{obj}{in_use}; + } } elsif ( $variable->{count} == 0 @@ -1841,7 +1843,7 @@ package Sidef::Parser { ) { return Sidef::Variable::Static->new( - name => 'ANON', + name => '__CONST__', expr => { $self->{class} => [ { @@ -2162,6 +2164,81 @@ package Sidef::Parser { return \@methods; } + sub parse_suffixes { + my ($self, %opt) = @_; + + my $struct = $opt{struct}; + local *_ = $opt{code}; + + my $parsed = 0; + + { + if (/\G(?=\{)/) { + $struct->{$self->{class}}[-1]{self} = { + $self->{class} => [ + { + self => $struct->{$self->{class}}[-1]{self}, + exists($struct->{$self->{class}}[-1]{call}) ? (call => delete $struct->{$self->{class}}[-1]{call}) + : (), + exists($struct->{$self->{class}}[-1]{ind}) ? (ind => delete $struct->{$self->{class}}[-1]{ind}) + : (), + exists($struct->{$self->{class}}[-1]{lookup}) + ? (lookup => delete $struct->{$self->{class}}[-1]{lookup}) + : (), + } + ] + }; + + while (/\G(?=\{)/) { + my $lookup = $self->parse_lookup(code => $opt{code}); + push @{$struct->{$self->{class}}[-1]{lookup}}, $lookup->{$self->{class}}; + } + + $parsed ||= 1; + redo; + } + + if (/\G(?=\[)/) { + $struct->{$self->{class}}[-1]{self} = { + $self->{class} => [ + { + self => $struct->{$self->{class}}[-1]{self}, + exists($struct->{$self->{class}}[-1]{call}) ? (call => delete $struct->{$self->{class}}[-1]{call}) + : (), + exists($struct->{$self->{class}}[-1]{ind}) ? (ind => delete $struct->{$self->{class}}[-1]{ind}) + : (), + exists($struct->{$self->{class}}[-1]{lookup}) + ? (lookup => delete $struct->{$self->{class}}[-1]{lookup}) + : (), + } + ] + }; + + while (/\G(?=\[)/) { + my ($ind) = $self->parse_expr(code => $opt{code}); + push @{$struct->{$self->{class}}[-1]{ind}}, $ind; + } + + $parsed ||= 1; + redo; + } + + if (/\G\h*(?=\()/gc) { + my $arg = $self->parse_arguments(code => $opt{code}); + + push @{$struct->{$self->{class}}[-1]{call}}, + { + method => 'call', + (%{$arg} ? (arg => [$arg]) : ()) + }; + + redo; + } + } + + $parsed; + } + sub parse_obj { my ($self, %opt) = @_; @@ -2219,11 +2296,6 @@ package Sidef::Parser { } } - while (/\G(?=\[)/) { - my ($ind) = $self->parse_expr(code => $opt{code}); - push @{$struct{$self->{class}}[-1]{ind}}, $ind; - } - { if (/\G\h*(?=\.\h*(?:$self->{method_name_re}|[(\$]))/ogc) { my $methods = $self->parse_methods(code => $opt{code}); @@ -2307,53 +2379,8 @@ package Sidef::Parser { } } - if (/\G(?=\{)/) { - $struct{$self->{class}}[-1]{self} = { - $self->{class} => [ - { - self => $struct{$self->{class}}[-1]{self}, - exists($struct{$self->{class}}[-1]{call}) ? (call => delete $struct{$self->{class}}[-1]{call}) - : (), - exists($struct{$self->{class}}[-1]{ind}) ? (ind => delete $struct{$self->{class}}[-1]{ind}) - : (), - exists($struct{$self->{class}}[-1]{lookup}) - ? (lookup => delete $struct{$self->{class}}[-1]{lookup}) - : (), - } - ] - }; - - while (/\G(?=\{)/) { - my $lookup = $self->parse_lookup(code => $opt{code}); - push @{$struct{$self->{class}}[-1]{lookup}}, $lookup->{$self->{class}}; - } - - redo; - } - - if (/\G(?=\[)/) { - $struct{$self->{class}}[-1]{self} = { - $self->{class} => [ - { - self => $struct{$self->{class}}[-1]{self}, - exists($struct{$self->{class}}[-1]{call}) ? (call => delete $struct{$self->{class}}[-1]{call}) - : (), - exists($struct{$self->{class}}[-1]{ind}) ? (ind => delete $struct{$self->{class}}[-1]{ind}) - : (), - exists($struct{$self->{class}}[-1]{lookup}) - ? (lookup => delete $struct{$self->{class}}[-1]{lookup}) - : (), - } - ] - }; - - while (/\G(?=\[)/) { - my ($ind) = $self->parse_expr(code => $opt{code}); - push @{$struct{$self->{class}}[-1]{ind}}, $ind; - } - - redo; - } + # Parse array and hash fetchers ([...] and {...}) + $self->parse_suffixes(code => $opt{code}, struct => \%struct) && redo; if (/\G(?!\h*[=-]>)/ && /\G(?=$self->{operators_re})/o) { my ($method, $req_arg, $op_type) = $self->get_method_name(code => $opt{code}); @@ -2781,6 +2808,7 @@ package Sidef::Parser { ); } + $self->parse_suffixes(code => $opt{code}, struct => \%struct); redo; } elsif (!$has_newline and /\G(if|while|and|or)\b\h*/gc) { diff --git a/lib/Sidef/Time/Time.pm b/lib/Sidef/Time/Time.pm index 4b64456ac..3394ede53 100644 --- a/lib/Sidef/Time/Time.pm +++ b/lib/Sidef/Time/Time.pm @@ -65,7 +65,7 @@ package Sidef::Time::Time { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Time.new(' . $self->get_value . ')'); + Sidef::Types::String::String->new('Time(' . $self->get_value . ')'); } }; diff --git a/lib/Sidef/Types/Array/MultiArray.pm b/lib/Sidef/Types/Array/MultiArray.pm index e74802024..fc2f856d2 100644 --- a/lib/Sidef/Types/Array/MultiArray.pm +++ b/lib/Sidef/Types/Array/MultiArray.pm @@ -80,7 +80,7 @@ package Sidef::Types::Array::MultiArray { sub dump { my ($self) = @_; Sidef::Types::String::String->new( - 'MultiArr.new(' . join( + 'MultiArr(' . join( ",\n\t ", map { '[' . join( diff --git a/lib/Sidef/Types/Array/Pair.pm b/lib/Sidef/Types/Array/Pair.pm index 8c2acd56f..850c24150 100644 --- a/lib/Sidef/Types/Array/Pair.pm +++ b/lib/Sidef/Types/Array/Pair.pm @@ -66,7 +66,7 @@ package Sidef::Types::Array::Pair { my ($self) = @_; Sidef::Types::String::String->new( - "Pair.new(" . "\n" . join( + "Pair(" . "\n" . join( ",\n", (' ' x ($Sidef::SPACES += $Sidef::SPACES_INCR)) . join( diff --git a/lib/Sidef/Types/Byte/Byte.pm b/lib/Sidef/Types/Byte/Byte.pm index babd7f381..3487727d9 100644 --- a/lib/Sidef/Types/Byte/Byte.pm +++ b/lib/Sidef/Types/Byte/Byte.pm @@ -14,7 +14,7 @@ package Sidef::Types::Byte::Byte { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Byte.new(' . $self->get_value . ')'); + Sidef::Types::String::String->new('Byte(' . $self->get_value . ')'); } }; diff --git a/lib/Sidef/Types/Byte/Bytes.pm b/lib/Sidef/Types/Byte/Bytes.pm index 5251ddb9c..0591597e7 100644 --- a/lib/Sidef/Types/Byte/Bytes.pm +++ b/lib/Sidef/Types/Byte/Bytes.pm @@ -14,6 +14,18 @@ package Sidef::Types::Byte::Bytes { sub call { my ($self, @strings) = @_; + + # The arguments are already bytes + my $bytes = 1; + foreach my $obj (@strings) { + if (ref($obj) ne 'Sidef::Types::Byte::Byte') { + $bytes = 0; + last; + } + } + $bytes && return $self->new(@strings); + + # The arguments are strings -- convert to bytes my $string = CORE::join('', @strings); state $x = require bytes; $self->new(map { Sidef::Types::Byte::Byte->new(CORE::ord bytes::substr($string, $_, 1)) } @@ -43,7 +55,7 @@ package Sidef::Types::Byte::Bytes { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Bytes.new(' . CORE::join(', ', map { $_->dump->get_value } @{$self}) . ')'); + Sidef::Types::String::String->new('Bytes(' . CORE::join(', ', map { $_->dump->get_value } @{$self}) . ')'); } }; diff --git a/lib/Sidef/Types/Char/Char.pm b/lib/Sidef/Types/Char/Char.pm index e4633fc9f..c0a124a29 100644 --- a/lib/Sidef/Types/Char/Char.pm +++ b/lib/Sidef/Types/Char/Char.pm @@ -19,7 +19,7 @@ package Sidef::Types::Char::Char { sub dump { my ($self) = @_; - Sidef::Types::String::String->new(q{Char.new(} . $self->to_s->dump->get_value . q{)}); + Sidef::Types::String::String->new(q{Char(} . $self->to_s->dump->get_value . q{)}); } }; diff --git a/lib/Sidef/Types/Char/Chars.pm b/lib/Sidef/Types/Char/Chars.pm index 941663f92..00e5814b3 100644 --- a/lib/Sidef/Types/Char/Chars.pm +++ b/lib/Sidef/Types/Char/Chars.pm @@ -18,7 +18,7 @@ package Sidef::Types::Char::Chars { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Chars.new(' . join(', ', map { $_->dump->get_value } @{$self}) . ')'); + Sidef::Types::String::String->new('Chars(' . join(', ', map { $_->dump->get_value } @{$self}) . ')'); } }; diff --git a/lib/Sidef/Types/Glob/Backtick.pm b/lib/Sidef/Types/Glob/Backtick.pm index 7b8e307c0..9c70e63e3 100644 --- a/lib/Sidef/Types/Glob/Backtick.pm +++ b/lib/Sidef/Types/Glob/Backtick.pm @@ -11,6 +11,8 @@ package Sidef::Types::Glob::Backtick { bless \$backtick, __PACKAGE__; } + *call = \&new; + sub get_value { ${$_[0]}; } @@ -28,7 +30,7 @@ package Sidef::Types::Glob::Backtick { sub dump { my ($self) = @_; Sidef::Types::String::String->new( - 'Backtick.new(' . Sidef::Types::String::String->new($self->get_value)->dump->get_value . ')'); + 'Backtick(' . Sidef::Types::String::String->new($self->get_value)->dump->get_value . ')'); } }; diff --git a/lib/Sidef/Types/Glob/Dir.pm b/lib/Sidef/Types/Glob/Dir.pm index f116336d0..ea2cdd48b 100644 --- a/lib/Sidef/Types/Glob/Dir.pm +++ b/lib/Sidef/Types/Glob/Dir.pm @@ -186,7 +186,7 @@ package Sidef::Types::Glob::Dir { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Dir.new(' . ${Sidef::Types::String::String->new($self->get_value)->dump} . ')'); + Sidef::Types::String::String->new('Dir(' . ${Sidef::Types::String::String->new($self->get_value)->dump} . ')'); } { diff --git a/lib/Sidef/Types/Glob/File.pm b/lib/Sidef/Types/Glob/File.pm index a6608c6f5..2ecf45f04 100644 --- a/lib/Sidef/Types/Glob/File.pm +++ b/lib/Sidef/Types/Glob/File.pm @@ -484,7 +484,7 @@ package Sidef::Types::Glob::File { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('File.new(' . ${Sidef::Types::String::String->new($self->get_value)->dump} . ')'); + Sidef::Types::String::String->new('File(' . ${Sidef::Types::String::String->new($self->get_value)->dump} . ')'); } # Path split diff --git a/lib/Sidef/Types/Glob/Pipe.pm b/lib/Sidef/Types/Glob/Pipe.pm index a3eff968d..527cff3e6 100644 --- a/lib/Sidef/Types/Glob/Pipe.pm +++ b/lib/Sidef/Types/Glob/Pipe.pm @@ -61,7 +61,7 @@ package Sidef::Types::Glob::Pipe { sub dump { my ($self) = @_; Sidef::Types::String::String->new( - 'Pipe.new(' . join(', ', map { Sidef::Types::String::String->new($_)->dump->get_value } @{$self}) . ')'); + 'Pipe(' . join(', ', map { Sidef::Types::String::String->new($_)->dump->get_value } @{$self}) . ')'); } } diff --git a/lib/Sidef/Types/Grapheme/Grapheme.pm b/lib/Sidef/Types/Grapheme/Grapheme.pm index e436d9bb8..56e5f68c8 100644 --- a/lib/Sidef/Types/Grapheme/Grapheme.pm +++ b/lib/Sidef/Types/Grapheme/Grapheme.pm @@ -19,7 +19,7 @@ package Sidef::Types::Grapheme::Grapheme { sub dump { my ($self) = @_; - Sidef::Types::String::String->new(q{Grapheme.new(} . $self->to_s->dump->get_value . q{)}); + Sidef::Types::String::String->new(q{Grapheme(} . $self->to_s->dump->get_value . q{)}); } }; diff --git a/lib/Sidef/Types/Grapheme/Graphemes.pm b/lib/Sidef/Types/Grapheme/Graphemes.pm index 16bfcb6b0..67a3d9695 100644 --- a/lib/Sidef/Types/Grapheme/Graphemes.pm +++ b/lib/Sidef/Types/Grapheme/Graphemes.pm @@ -18,7 +18,7 @@ package Sidef::Types::Grapheme::Graphemes { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Graphemes.new(' . join(', ', map { $_->dump->get_value } @{$self}) . ')'); + Sidef::Types::String::String->new('Graphemes(' . join(', ', map { $_->dump->get_value } @{$self}) . ')'); } }; diff --git a/lib/Sidef/Types/Hash/Hash.pm b/lib/Sidef/Types/Hash/Hash.pm index 4651400c9..b492b8aa7 100644 --- a/lib/Sidef/Types/Hash/Hash.pm +++ b/lib/Sidef/Types/Hash/Hash.pm @@ -319,7 +319,7 @@ package Sidef::Types::Hash::Hash { my @keys = sort { (lc($a) cmp lc($b)) || ($a cmp $b) } CORE::keys(%{$self}); my $str = Sidef::Types::String::String->new( - "Hash.new(" . ( + "Hash(" . ( @keys ? ( (@keys > 1 ? "\n" : '') . join( diff --git a/lib/Sidef/Types/Number/Complex.pm b/lib/Sidef/Types/Number/Complex.pm index d8eb1c893..c8b0b5c0b 100644 --- a/lib/Sidef/Types/Number/Complex.pm +++ b/lib/Sidef/Types/Number/Complex.pm @@ -522,7 +522,7 @@ package Sidef::Types::Number::Complex { sub dump { my ($self) = @_; - Sidef::Types::String::String->new('Complex.new(' . $self->real . ', ', $self->imaginary . ')'); + Sidef::Types::String::String->new('Complex(' . $self->real . ', ', $self->imaginary . ')'); } { diff --git a/lib/Sidef/Types/Number/Number.pm b/lib/Sidef/Types/Number/Number.pm index 65f2f6298..fe77c656c 100644 --- a/lib/Sidef/Types/Number/Number.pm +++ b/lib/Sidef/Types/Number/Number.pm @@ -374,8 +374,8 @@ package Sidef::Types::Number::Number { } sub inf { - my ($self) = @_; - $self->new(Math::BigInt->binf); + my ($self, $sign) = @_; + $self->new(Math::BigInt->binf(defined($sign) ? $sign->get_value : ())); } sub neg { diff --git a/scripts/Tests/array_unique.sf b/scripts/Tests/array_unique.sf index 1d8fd8614..900e3a5b2 100644 --- a/scripts/Tests/array_unique.sf +++ b/scripts/Tests/array_unique.sf @@ -5,15 +5,6 @@ # -var array = [ - 1, 2, 3, 'a', 'b', 'c', 2, 3, 4, 'b', - 'c', 'd', 'd', 'd', 'b', '3', '2', 2, - ["hello"],["hello"],["perl","hacker"] - ]; - -assert_eq(array.uniq, [1, 2, 3, "a", "b", "c", 4, "d", "3", "2", ["hello"], ["perl", "hacker"]]); -assert_eq(array.last_uniq, [1, "a", 3, 4, "c", "d", "b", "3", "2", 2, ["hello"], ["perl", "hacker"]]); - var array = [['a','b'], ['a'], ['a', 'b'], ['z']]; assert_eq(array.uniq, [["a", "b"], ["a"], ["z"]]); diff --git a/utils/test_deparser.pl b/utils/test_deparser.pl index 8d8483faa..9c9552565 100644 --- a/utils/test_deparser.pl +++ b/utils/test_deparser.pl @@ -28,10 +28,14 @@ use File::Find qw(find); use File::Basename qw(basename); +use File::Spec::Functions qw(catdir updir rel2abs); + +local $ENV{SIDEF_INC} = rel2abs(catdir(updir(), 'scripts', 'Tests')); sub parse_deparse { my ($code, $name) = @_; + local %Sidef::INCLUDED = (); local @Sidef::NAMESPACES = (); my $parser = Sidef::Parser->new( @@ -49,9 +53,7 @@ sub parse_deparse { return ($deparsed, \@statements); } -my %ignore = ( - 'Matrix.sm' => 1, -); +my %ignore = ('module_definition.sf' => 1,); my $dir = shift() // die "usage: $0 [scripts dir]\n";