perl: Replace _clone() with a ->clone method.
authorBen Harris <bjh21@bjh21.me.uk>
Sat, 27 Jul 2019 09:20:47 +0000 (10:20 +0100)
committerBen Harris <bjh21@bjh21.me.uk>
Tue, 30 Jul 2019 08:46:59 +0000 (09:46 +0100)
This means that each class is responsible for cloning itself, which
helps with encapsulation.

perl/core.pm
perl/step8_macros.pl
perl/step9_try.pl
perl/stepA_mal.pl
perl/types.pm

index 712b4aa..9e7e2d7 100644 (file)
@@ -8,7 +8,7 @@ use List::Util qw(pairmap);
 use Time::HiRes qw(time);
 
 use readline;
-use types qw(_sequential_Q _equal_Q _clone $nil $true $false
+use types qw(_sequential_Q _equal_Q $nil $true $false
              _number_Q _symbol _symbol_Q _string_Q _keyword _keyword_Q _list_Q _vector_Q _sub_Q _function_Q
              _hash_map _hash_map_Q _atom_Q);
 use reader qw(read_str);
@@ -113,7 +113,7 @@ sub mal_map {
 
 sub conj {
     my $seq = shift;
-    my $new_seq = _clone($seq);
+    my $new_seq = $seq->clone;
     if (_list_Q($new_seq)) {
         unshift @$new_seq, reverse @_;
     } else {
@@ -145,7 +145,7 @@ fieldhash my %meta;
 
 # Metadata functions
 sub with_meta {
-    my $new_obj = _clone($_[0]);
+    my $new_obj = $_[0]->clone;
     $meta{$new_obj} = $_[1];
     return $new_obj;
 }
index b9dcfa4..6ab72ce 100644 (file)
@@ -10,7 +10,7 @@ use List::Util qw(pairs pairmap);
 use Scalar::Util qw(blessed);
 
 use readline qw(mal_readline set_rl_mode);
-use types qw($nil $true $false _symbol_Q _list_Q _clone);
+use types qw($nil $true $false _symbol_Q _list_Q);
 use reader;
 use printer;
 use env;
@@ -125,7 +125,7 @@ sub EVAL {
             # Continue loop (TCO)
         }
         when ('defmacro!') {
-            my $func = _clone(EVAL($a2, $env));
+            my $func = EVAL($a2, $env)->clone;
             $func->{ismacro} = 1;
             return $env->set($a1, $func);
         }
index a4de43c..2f1a175 100644 (file)
@@ -10,7 +10,7 @@ use List::Util qw(pairs pairmap);
 use Scalar::Util qw(blessed);
 
 use readline qw(mal_readline set_rl_mode);
-use types qw($nil $true $false _symbol_Q _list_Q _clone);
+use types qw($nil $true $false _symbol_Q _list_Q);
 use reader;
 use printer;
 use env;
@@ -126,7 +126,7 @@ sub EVAL {
             # Continue loop (TCO)
         }
         when ('defmacro!') {
-            my $func = _clone(EVAL($a2, $env));
+            my $func = EVAL($a2, $env)->clone;
             $func->{ismacro} = 1;
             return $env->set($a1, $func);
         }
index 8b1544e..133906b 100644 (file)
@@ -10,7 +10,7 @@ use List::Util qw(pairs pairmap);
 use Scalar::Util qw(blessed);
 
 use readline qw(mal_readline set_rl_mode);
-use types qw($nil $true $false _symbol_Q _list_Q _clone);
+use types qw($nil $true $false _symbol_Q _list_Q);
 use reader;
 use printer;
 use env;
@@ -125,7 +125,7 @@ sub EVAL {
             # Continue loop (TCO)
         }
         when ('defmacro!') {
-            my $func = _clone(EVAL($a2, $env));
+            my $func = EVAL($a2, $env)->clone;
             $func->{ismacro} = 1;
             return $env->set($a1, $func);
         }
index 3673732..4cab804 100644 (file)
@@ -4,7 +4,7 @@ use warnings;
 
 use Data::Dumper;
 use Exporter 'import';
-our @EXPORT_OK = qw(_sequential_Q _equal_Q _clone
+our @EXPORT_OK = qw(_sequential_Q _equal_Q
                     $nil $true $false
                     _number_Q _symbol _symbol_Q _string_Q _keyword _keyword_Q _list_Q _vector_Q _sub_Q _function_Q
                     _hash_map _hash_map_Q _atom_Q);
@@ -48,15 +48,6 @@ sub _equal_Q {
     return 0;
 }
 
-sub _clone {
-    no overloading '%{}';
-    my ($obj) = @_;
-    if ($obj->isa('Mal::CoreFunction')) {
-       return Mal::FunctionRef->new( $obj );
-    } else {
-       return bless {%{$obj}}, ref $obj;
-    }
-}
 
 # Errors/Exceptions
 
@@ -137,6 +128,7 @@ sub _keyword_Q { $_[0]->isa('Mal::String') && ${$_[0]} =~ /^\x{029e}/; }
     #sub _val { $_[0]->{val}->[$_[1]]->{val}; } # return value of nth item
     sub rest { my @arr = @{$_[0]->{val}}; Mal::List->new([@arr[1..$#arr]]); }
     sub slice { my @arr = @{$_[0]->{val}}; Mal::List->new([@arr[$_[1]..$_[2]]]); }
+    sub clone { my $self = shift; ref($self)->new([@$self]) }
 }
 
 # Lists
@@ -165,6 +157,7 @@ sub _vector_Q { $_[0]->isa('Mal::Vector') }
     package Mal::HashMap;
     use parent -norequire, 'Mal::Type';
     sub new  { my $class = shift; bless $_[0], $class }
+    sub clone { my $self = shift; ref($self)->new({%$self}) }
 }
 
 sub _hash_map { Mal::HashMap->new( { pairmap { $$a => $b } @_ } ) }
@@ -196,6 +189,7 @@ sub _hash_map_Q { $_[0]->isa('Mal::HashMap') }
         my $self = $_[0];
         return &{ $self->{eval} }($self->{ast}, gen_env($self, $_[1]));
     }
+    sub clone {        my $self = shift; bless { %$self }, ref($self) }
 }
 
 sub _sub_Q { $_[0]->isa('Mal::CoreFunction') ||  $_[0]->isa('Mal::FunctionRef') }
@@ -212,12 +206,14 @@ sub _function_Q { $_[0]->isa('Mal::Function') }
         my ($class, $code) = @_;
         bless {'code'=>$code}, $class
     }
+    sub clone { my $self = shift; ref($self)->new($self->{code}) }
 }
 
 # Core Functions
 
 {
     package Mal::CoreFunction;
+    sub clone { my $self = shift; FunctionRef->new($self) }
 }
 
 
@@ -228,6 +224,7 @@ sub _function_Q { $_[0]->isa('Mal::Function') }
     use parent -norequire, 'Mal::Type';
     use overload '${}' => sub { \($_[0]->{val}) }, fallback => 1;
     sub new  { my $class = shift; bless {'val'=>$_[0]}, $class }
+    sub clone { my $self = shift; ref($self)->new($$self) }
 }
 
 sub _atom_Q { $_[0]->isa('Mal::Atom') }