mirror of
https://codeberg.org/scip/rpnc.git
synced 2025-12-17 04:21:01 +01:00
optimized calc switching code
This commit is contained in:
91
rpnc
91
rpnc
@@ -12,7 +12,7 @@ my $term = Term::ReadLine->new('rpn calc');
|
|||||||
my $debug = 0;
|
my $debug = 0;
|
||||||
my $showstack = 1;
|
my $showstack = 1;
|
||||||
my $tty = 1;
|
my $tty = 1;
|
||||||
my $VERSION = '1.00';
|
my $VERSION = '1.01';
|
||||||
my $sub = 0;
|
my $sub = 0;
|
||||||
my $op;
|
my $op;
|
||||||
|
|
||||||
@@ -54,19 +54,13 @@ if ($op) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# management commands
|
||||||
my %commands = (
|
my %commands = (
|
||||||
q => sub { exit; },
|
q => sub { exit; },
|
||||||
'?' => sub { help(); },
|
'?' => sub { help(); },
|
||||||
s => sub { dumpstack(); },
|
s => sub { dumpstack(); },
|
||||||
c => sub { clearstack(); },
|
c => sub { clearstack(); },
|
||||||
d => sub {
|
d => sub { $debug ^= 1; },
|
||||||
if ($debug) {
|
|
||||||
$debug = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$debug = 1;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
u => sub { undo(); dumpstack(); },
|
u => sub { undo(); dumpstack(); },
|
||||||
r => sub { reversestack(); },
|
r => sub { reversestack(); },
|
||||||
R => sub { rotatestack(); },
|
R => sub { rotatestack(); },
|
||||||
@@ -74,6 +68,39 @@ my %commands = (
|
|||||||
')' => sub { $sub = 0 },
|
')' => sub { $sub = 0 },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
# executed 1:1, or aliased
|
||||||
|
my %alias = qw(^ ** x ^ < << > >> + + - - / / * * & & | |);
|
||||||
|
|
||||||
|
# hand coded functions
|
||||||
|
my %func = (
|
||||||
|
'%' => sub {
|
||||||
|
if (scalar @_ == 2) {
|
||||||
|
my ($a, $b) = @_;
|
||||||
|
return "($a / 100) * $b";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
print "percent only possible with 2 values\n";
|
||||||
|
undo();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'V' => sub {
|
||||||
|
if (scalar @_ == 2) {
|
||||||
|
my ($a, $b) = @_;
|
||||||
|
return "$a ** (1 / $b)";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
my $a = pop @_;
|
||||||
|
return "$a ** (1 / 2)";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'pr' => sub {
|
||||||
|
# parallel resistance, maybe add ~/.rpncrc support
|
||||||
|
# where to add such custom functions...
|
||||||
|
return "1 / (" . join(' + ', map { "1 / $_"} @_) . ")";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
my $OUT = $term->OUT || \*STDOUT;
|
my $OUT = $term->OUT || \*STDOUT;
|
||||||
while ( defined ($_ = $term->readline(prompt())) ) {
|
while ( defined ($_ = $term->readline(prompt())) ) {
|
||||||
foreach my $tok (split /\s+/) {
|
foreach my $tok (split /\s+/) {
|
||||||
@@ -83,10 +110,10 @@ while ( defined ($_ = $term->readline(prompt())) ) {
|
|||||||
dumpstack();
|
dumpstack();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($tok =~ /^[\(\)csdrRuq\?]+?$/) {
|
if (exists $commands{$tok}) {
|
||||||
cmd($tok);
|
cmd($tok);
|
||||||
}
|
}
|
||||||
elsif ($tok =~ /^[V<>x\%\|\&\^+\-\*\/]$/) {
|
else {
|
||||||
print calc($tok);
|
print calc($tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -241,46 +268,20 @@ sub calc {
|
|||||||
my @last = getlast();
|
my @last = getlast();
|
||||||
|
|
||||||
if (@last) {
|
if (@last) {
|
||||||
# map operators
|
if (exists $alias{$op}) {
|
||||||
if ($op eq '^') {
|
$op = $alias{$op};
|
||||||
$op = '**';
|
$code = join(" $op ", @last);
|
||||||
}
|
}
|
||||||
elsif ($op eq 'x') {
|
elsif (exists $func{$op}) {
|
||||||
$op = '^';
|
my $sub = $func{$op};
|
||||||
}
|
$code = &$sub(@last);
|
||||||
elsif ($op eq '<') {
|
return unless $code;
|
||||||
$op = '<<';
|
|
||||||
}
|
|
||||||
elsif ($op eq '>') {
|
|
||||||
$op = '>>';
|
|
||||||
}
|
|
||||||
|
|
||||||
# direct and special ops
|
|
||||||
if ($op eq '%') {
|
|
||||||
if (scalar @last == 2) {
|
|
||||||
my ($a, $b) = @last;
|
|
||||||
$code = "($a / 100) * $b";
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print "percent only possible with 2 values\n";
|
print "syntax error or unknown command!\n";
|
||||||
undo();
|
undo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
elsif ($op eq 'V') {
|
|
||||||
if (scalar @last == 2) {
|
|
||||||
my ($a, $b) = @last;
|
|
||||||
$code = "$a ** (1 / $b)";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
my $a = pop @last;
|
|
||||||
$code = "$a ** (1 / 2)";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# rpn op
|
|
||||||
$code = join(" $op ", @last);
|
|
||||||
}
|
|
||||||
|
|
||||||
# execute
|
# execute
|
||||||
eval "\$res = $code";
|
eval "\$res = $code";
|
||||||
|
|||||||
Reference in New Issue
Block a user