diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2021-07-04 21:36:36 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-04 21:36:36 +0100 |
| commit | 8cab52b28709e2e730a973ed9d27068d01651a8e (patch) | |
| tree | 581383ca22dc9b8781f3bb77b2af8e0034c4b49e | |
| parent | a8e6749c38aa8a71df18d6655c54f03bdc1776b6 (diff) | |
| parent | 72d693e1246626f0d6ea2a1aa06c49fca174f3b3 (diff) | |
| download | perlweeklychallenge-club-8cab52b28709e2e730a973ed9d27068d01651a8e.tar.gz perlweeklychallenge-club-8cab52b28709e2e730a973ed9d27068d01651a8e.tar.bz2 perlweeklychallenge-club-8cab52b28709e2e730a973ed9d27068d01651a8e.zip | |
Merge pull request #4415 from drbaggy/master
Really minor stuff this time - but talk about using a dispatch table.
| -rw-r--r-- | challenge-119/james-smith/README.md | 66 | ||||
| -rw-r--r-- | challenge-119/james-smith/cesil/cesil.pl | 50 |
2 files changed, 78 insertions, 38 deletions
diff --git a/challenge-119/james-smith/README.md b/challenge-119/james-smith/README.md index 3d4b5701ff..84f389fefc 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 dispatch 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 0bbd61888e..25e79e8982 100644 --- a/challenge-119/james-smith/cesil/cesil.pl +++ b/challenge-119/james-smith/cesil/cesil.pl @@ -1,45 +1,55 @@ 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 ', '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{_err('i') unless @in;$reg=shift@in}, -'STORE' ,sub{$mem{$_[0]}=$reg}, -'LOAD' ,sub{_err('m') unless exists$mem{$_[0]};$reg=$mem{$_[0]}}, -'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{$reg/=$_[0]=~m{^-?\d+$}?$_[0]:exists$mem{$_[0]}?$mem{$_[0]}:(_err('m'));$reg=int$reg}, -'JINEG' ,sub{_err('l') unless exists $ptrs{$_[0]}; $ptr=$ptrs{$_[0]}-1 if $reg<0}, -'JIZERO' ,sub{_err('l') unless exists $ptrs{$_[0]}; $ptr=$ptrs{$_[0]}-1 if $reg==0}, -'JUMP' ,sub{_err('l') unless exists $ptrs{$_[0]}; $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+(.*)}; 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; +die "\n** Exited without HALT\n" if $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; -} |
