diff options
| author | drbaggy <js5@sanger.ac.uk> | 2021-07-04 07:57:07 +0100 |
|---|---|---|
| committer | drbaggy <js5@sanger.ac.uk> | 2021-07-04 07:57:07 +0100 |
| commit | 935bf81e2f3ef8bd501694ba9431472d3e7c1220 (patch) | |
| tree | 5fc4885ff84693ada83cf2d47f8c0c89dc216fa8 | |
| parent | 7352e4f3bbff855816a008dc18ca031b13beb1e9 (diff) | |
| download | perlweeklychallenge-club-935bf81e2f3ef8bd501694ba9431472d3e7c1220.tar.gz perlweeklychallenge-club-935bf81e2f3ef8bd501694ba9431472d3e7c1220.tar.bz2 perlweeklychallenge-club-935bf81e2f3ef8bd501694ba9431472d3e7c1220.zip | |
tidied up code
| -rw-r--r-- | challenge-119/james-smith/README.md | 66 | ||||
| -rw-r--r-- | challenge-119/james-smith/cesil/cesil.pl | 50 |
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; |
