User:Ian/LARSA Interpreter
My LARSA interpreter in Perl
our %DATA, $datstr="", $cmdstr, $state="", @i; our $ivalence, $ovalence, $var; @{$DATA{'0'}}=@{$DATA{'1'}}=(0,1); sub do_step { $_=shift; if (/^[01]$/) { $datstr.=$_; } elsif (length($datstr)<($_[0]||1)&&defined($_[5])) { $cmdstr=$_[5].$cmdstr; $state=$_[6]//$state; } else { $state=substr($_[4], ((1<<$_[3])-1-oct '0b' . substr $datstr, -$_[3], $_[3]), 1) if defined $_[4]; $cmdstr=(substr $_[2], ((1<<$_[0])-1-oct '0b' . substr $datstr, -$_[0], $_[0], '')*$_[1], $_[1]).$cmdstr; } } sub process { my $_; while (length $cmdstr) { $_=substr $cmdstr, 0, 1, ''; $_.=$state if defined $DATA{$_.$state}; do_step $_, @{$DATA{$_}}; print $state,'@',$datstr,'$',$cmdstr,"\n"; #stack trace } } while (<>) { while (/\\$/) {chomp; chop; $_.=<>} next if /^\$[01]=[^=]/; #Comment if (/^\$(..?)=(\d+)?(?:(?:@([^|]?))?\|(.*?))?(?:,(\d+)?(?:,(.*?)(?:(?:,(\d+))?,(.*))?)?)?$/) { #Assignment @i=@{$DATA{$1}}=($2//0,$5//int(length($6)/(1<<$2))//0,$6,$7//$2//0,$8,$4,$3); print $1,' (',$i[0],'--',$i[1],')=',$i[2],"\t@(",$i[3],')', defined($i[4])?'!':'','=',$i[4],defined($i[5])?"\t|". (defined($i[6])?'@!='.$i[6]:'').'|':'',$i[5],"\n"; } elsif (/^#(.(.)?)?(?:,(\d+))?=(.*)$/) { #Table Composition my $var = $1; chomp $4; $cmdbak=$4; my $istate=$2; my @output=(),@ostate=(),$output=""; my $datbak=$datstr, my $statebak=$state; my @vtrace=(), $ovalence=0; for (split //, $cmdbak) { $vtrace[++$#vtrace]=$DATA{$_}->[1]-$DATA{$_}->[0]+$vtrace[-1]//-1; $ovalence=$vtrace[-1]>0?$vtrace[-1]:$DATA{$_}->[1]>$ovalence?$DATA{$_}->[1]:$ovalence; } {local $,=", ";print @vtrace,"\n"}; $ivalence = -(sort {$a <=> $b} @vtrace)[0]+1; $ivalence = 0 if $ivalence<0; $ivalence = $3 if defined $3; print 'Examining function: valence (',$ivalence,',',$ovalence,")...\n"; for my $i (reverse 0..(1<<$ivalence)-1) { print 'Processing given ',$i," on the stack...\n"; $datstr=substr sprintf('%0'.$ivalence.'b', $i), 0, $ivalence; ($_, $state, $cmdstr)=($i, $istate, $cmdbak); process; print $var,"(",$i,"):(",$ivalence,",",length $datstr,")@",$state,"=",$datstr,"\n"; push @output, $datstr; push @ostate, $state; } ($datstr, $state)=($datbak, $statebak); $ovalence=(sort {$b <=> $a} map {length $_} @output)[0]; $output=join '', map {sprintf '%'.$ovalence.'s',$_} @output; $istate=join '', map {$_ eq ''?"\x7F":$_} @ostate; $istate =~ s/\x7F*$//; undef $istate unless length $istate; print "*",$var,"=",$ivalence,",",$ovalence,",",$output,$istate?(",".$istate):'',"\n"; @{$DATA{$var}}=($ivalence,$ovalence,$output,$ivalence,$istate); } else {chomp; $cmdstr=$_; process} #Evaluation }
About the Interpreter
In addition to accepting LARSA assignments and evaluations, it also has a "composition" or "currying" feature (#[var][state]=[...]) that takes a group of commands and optionally assigns them to a new command. For example, if the stack was pqrs, #a=&|> would do p>(q|(r&s)) to the number (note the RPN ordering). It accepts an input bit count, so, if there was a "+" command that incremented the stack as a single binary number, #p,8=+++++ will generate a command p for all values from 0 to 255 that adds 5 to the input. It also does constant folding, so #o=1| would generate a table that takes one value and replaces it with 1 (unary tautology). If you don't want to assign it to a new command, use #=[...] to just test it and output a table. If a state is given, that will determine the initial state for the commands. The composition assignment, like a regular assignment, does not interfere with the current stack or state.