aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrbaggy <js5@sanger.ac.uk>2021-07-04 07:57:07 +0100
committerdrbaggy <js5@sanger.ac.uk>2021-07-04 07:57:07 +0100
commit935bf81e2f3ef8bd501694ba9431472d3e7c1220 (patch)
tree5fc4885ff84693ada83cf2d47f8c0c89dc216fa8
parent7352e4f3bbff855816a008dc18ca031b13beb1e9 (diff)
downloadperlweeklychallenge-club-935bf81e2f3ef8bd501694ba9431472d3e7c1220.tar.gz
perlweeklychallenge-club-935bf81e2f3ef8bd501694ba9431472d3e7c1220.tar.bz2
perlweeklychallenge-club-935bf81e2f3ef8bd501694ba9431472d3e7c1220.zip
tidied up code
-rw-r--r--challenge-119/james-smith/README.md66
-rw-r--r--challenge-119/james-smith/cesil/cesil.pl50
2 files changed, 77 insertions, 39 deletions
diff --git a/challenge-119/james-smith/README.md b/challenge-119/james-smith/README.md
index 4c06522b9d..1215f85fd1 100644
--- a/challenge-119/james-smith/README.md
+++ b/challenge-119/james-smith/README.md
@@ -134,36 +134,66 @@ End LINE
### Side note... an intepreter for CESIL...
Didn't like the idea of relying on JAVA... so here is a bare bones
-interpreter...
+interpreter... This uses a dispatcher table to execute the commands
+- a list of "anonymous" subroutines stored in a hash.
+
```perl
-$| = 1;
-my( $ptr, @in, %mem, @code, %ptrs, $reg ) = 0;
+use strict;
+use warnings;
+
+$| = 1; # Set auto-flush...
+## Initialize state
+my($MAX_LOOPS, $ptr, $reg, @in, %mem, @code, %ptrs) = (1e6,0,0);
+
+## Define error messages
+my %messages = (
+ 'i' => 'No further input',
+ 'd' => 'Division by zero ',
+ 'm' => 'Unitialized memory at ',
+ 'l' => 'Unknown pointer ',
+);
+
+## Support functions
+sub _err { die sprintf "\n** %s%s [cmd %s - line %d]\n",
+ $messages{$_[0]}, $code[$ptr][1], $code[$ptr][0], 1+$ptr; }
+sub _j { exists$ptrs{$_}?($ptr=$ptrs{$_}-1):_err 'l'; }
+sub _v { /^-?\d+$/?$_:exists$mem{$_}?$mem{$_}:_err 'm'; }
+
+## Command dispatch table
my %commands = (
'LINE' ,sub{print "\n"},
'OUT' ,sub{print $reg},
-'PRINT' ,sub{print $_[0]=~s{^"}{}r=~s{"$}{}r;},
-'IN' ,sub{die 'OUT OF INPUT' unless @in;$reg=shift@in},
-'STORE' ,sub{$mem{$_[0]}=$reg},
-'LOAD' ,sub{$reg=$mem{$_[0]}},
-'ADD' ,sub{$reg+=$_[0]=~m{^-?\d+$}?$_[0]:$mem{$_[0]}},
-'SUBTRACT',sub{$reg-=$_[0]=~m{^-?\d+$}?$_[0]:$mem{$_[0]}},
-'MULTIPLY',sub{$reg*=$_[0]=~m{^-?\d+$}?$_[0]:$mem{$_[0]}},
-'DIVIDE' ,sub{$reg/=$_[0]=~m{^-?\d+$}?$_[0]:$mem{$_[0]};$reg=int$reg},
-'JINEG' ,sub{$ptr=$ptrs{$_[0]}-1 if $reg<0},
-'JIZERO' ,sub{$ptr=$ptrs{$_[0]}-1 if $reg==0},
-'JUMP' ,sub{$ptr=$ptrs{$_[0]}-1},
+'PRINT' ,sub{print s/^"//r=~s/"$//r},
+'IN' ,sub{@in?($reg=shift@in):_err 'i'},
+'STORE' ,sub{$mem{$_}=$reg},
+'LOAD' ,sub{$reg=_v},
+'ADD' ,sub{$reg+=_v},
+'SUBTRACT',sub{$reg-=_v},
+'MULTIPLY',sub{$reg*=_v},
+'DIVIDE' ,sub{$_=_v;$reg=$_?int($reg/$_):_err 'd'},
+'JINEG' ,sub{_j if $reg<0},
+'JIZERO' ,sub{_j if !$reg},
+'JUMP' ,sub{_j},
'HALT' ,sub{exit},
);
+## Parser loop
while(<>) {
- ((@in = map { 0+$_ } <> ),last) if m{^ {8}%};
+ ((@in = map {/^\s+-?\d+\s*$/?0+$_:()} <> ),last) if m{^ {8}%};
($ptrs{$1},$_)=(scalar @code,$2) if m{^(\S{1,7})\s+(.*)};
- push @code, [ split m{\s+}, s{^\s+}{}r=~s{\s+$}{}r, 2 ];
+ my($cmd,$data) = split m{\s+}, s{^\s+}{}r=~s{\s+$}{}r, 2;
+ die "\n** Unknown command [cmd $cmd - line ",1+@code,"]\n"
+ unless exists $commands{$cmd};
+ push @code, [$cmd,$data||''];
}
-my $MAX_LOOPS = 1e6;
-($commands{$code[$ptr][0]}($code[$ptr][1]),$ptr++)
+
+## Execution loop
+($commands{$code[$ptr][0]}($_=$code[$ptr][1]),$ptr++)
while --$MAX_LOOPS && $ptr<@code;
+
+## Error if did not exit with HALT..
+die "\n** Exited without HALT\n" if $ptr >= @code;
```
# Task 2 - Sequence without 1-on-1
diff --git a/challenge-119/james-smith/cesil/cesil.pl b/challenge-119/james-smith/cesil/cesil.pl
index c4020aec7e..99ed9585f2 100644
--- a/challenge-119/james-smith/cesil/cesil.pl
+++ b/challenge-119/james-smith/cesil/cesil.pl
@@ -1,9 +1,12 @@
use strict;
use warnings;
+# Set auto-flush...
$| = 1;
-my( $ptr, $reg, @in, %mem, @code, %ptrs ) = 0;
+## Initialize state
+my($MAX_LOOPS, $ptr, $reg, @in, %mem, @code, %ptrs) = (1e6,0,0);
+## Define error messages
my %messages = (
'i' => 'No further input',
'd' => 'Division by zero ',
@@ -11,36 +14,41 @@ my %messages = (
'l' => 'Unknown pointer ',
);
+## Support functions
+sub _err { die sprintf "\n** %s%s [cmd %s - line %d]\n",
+ $messages{$_[0]}, $code[$ptr][1], $code[$ptr][0], 1+$ptr; }
+sub _j { exists$ptrs{$_}?($ptr=$ptrs{$_}-1):_err 'l'; }
+sub _v { /^-?\d+$/?$_:exists$mem{$_}?$mem{$_}:_err 'm'; }
+
+## Command dispatch table
my %commands = (
'LINE' ,sub{print "\n"},
'OUT' ,sub{print $reg},
-'PRINT' ,sub{print $_[0]=~s{^"}{}r=~s{"$}{}r},
-'IN' ,sub{@in?($reg=shift@in):_err('i')},
-'STORE' ,sub{$mem{$_[0]}=$reg},
-'LOAD' ,sub{exists $mem{$_[0]}?($reg=$mem{$_[0]}):_err('m')},
-'ADD' ,sub{$reg+=$_[0]=~m{^-?\d+$}?$_[0]:exists$mem{$_[0]}?$mem{$_[0]}:_err('m')},
-'SUBTRACT',sub{$reg-=$_[0]=~m{^-?\d+$}?$_[0]:exists$mem{$_[0]}?$mem{$_[0]}:_err('m')},
-'MULTIPLY',sub{$reg*=$_[0]=~m{^-?\d+$}?$_[0]:exists$mem{$_[0]}?$mem{$_[0]}:_err('m')},
-'DIVIDE' ,sub{$a=$_[0]=~m{^-?\d+$}?$_[0]:exists$mem{$_[0]}?$mem{$_[0]}:_err('m');$reg=$a?int($reg/$a):_err('d')},
-'JINEG' ,sub{($reg<0)&&(exists $ptrs{$_[0]}?($ptr=$ptrs{$_[0]}-1):_err('l'))},
-'JIZERO' ,sub{($reg==0)&&(exists $ptrs{$_[0]}?($ptr=$ptrs{$_[0]}-1):_err('l'))},
-'JUMP' ,sub{exists $ptrs{$_[0]}?($ptr=$ptrs{$_[0]}-1):_err('l')},
+'PRINT' ,sub{print s/^"//r=~s/"$//r},
+'IN' ,sub{@in?($reg=shift@in):_err 'i'},
+'STORE' ,sub{$mem{$_}=$reg},
+'LOAD' ,sub{$reg=_v},
+'ADD' ,sub{$reg+=_v},
+'SUBTRACT',sub{$reg-=_v},
+'MULTIPLY',sub{$reg*=_v},
+'DIVIDE' ,sub{$_=_v;$reg=$_?int($reg/$_):_err 'd'},
+'JINEG' ,sub{_j if $reg<0},
+'JIZERO' ,sub{_j if !$reg},
+'JUMP' ,sub{_j},
'HALT' ,sub{exit},
);
+## Parser loop
while(<>) {
- ((@in = map { 0+$_ } <> ),last) if m{^ {8}%};
+ ((@in = map {/^\s+-?\d+\s*$/?0+$_:()} <> ),last) if m{^ {8}%};
($ptrs{$1},$_)=(scalar @code,$2) if m{^(\S{1,7})\s+(.*)};
my($cmd,$data) = split m{\s+}, s{^\s+}{}r=~s{\s+$}{}r, 2;
- die "Unknown command [cmd $cmd - line ",1+@code,"]\n" unless exists $commands{$cmd};
+ die "\n** Unknown command [cmd $cmd - line ",1+@code,"]\n"
+ unless exists $commands{$cmd};
push @code, [$cmd,$data||''];
}
-my $MAX_LOOPS = 1e6;
-($commands{$code[$ptr][0]}($code[$ptr][1]),$ptr++)
+## Execution loop
+($commands{$code[$ptr][0]}($_=$code[$ptr][1]),$ptr++)
while --$MAX_LOOPS && $ptr<@code;
-
-sub _err {
- my $flag = shift;
- die sprintf "\n%s%s [cmd %s - line %d]\n", $messages{$flag}, $code[$ptr][1], $code[$ptr][0], 1+$ptr;
-}
+die "\n** Exited without HALT\n" if $ptr >= @code;