aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2021-07-04 21:36:36 +0100
committerGitHub <noreply@github.com>2021-07-04 21:36:36 +0100
commit8cab52b28709e2e730a973ed9d27068d01651a8e (patch)
tree581383ca22dc9b8781f3bb77b2af8e0034c4b49e
parenta8e6749c38aa8a71df18d6655c54f03bdc1776b6 (diff)
parent72d693e1246626f0d6ea2a1aa06c49fca174f3b3 (diff)
downloadperlweeklychallenge-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.md66
-rw-r--r--challenge-119/james-smith/cesil/cesil.pl50
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;
-}