# emulate the Babylonian Unix dc program (this time using overload) # Binary operators: two entries are popped off the stack # and a result is pushed on the stack in their place: # + The top two values on the stack are added. # - The top two values on the stack are subtracted. # * The top two values on the stack are multiplied. # / The top two values on the stack are divided. # % The top two values on the stack are remaindered. # ^ The top two values on the stack are exponentiated. # Other operators: # c All values on the stack are popped. # d The top value on the stack is duplicated. # f All values on the stack are printed. # p The top value on the stack is printed. # q Exits the program. # r Reverses (swaps) the top two values on the stack. # v Replaces the top element on the stack by its square root. use warnings; use strict; use Sexagesimal; my %operators = ( "+" => sub { my ($s) = @_; push(@$s, pop(@$s) + pop(@$s)) }, "-" => sub { my ($s) = @_; my $subtrahend = pop(@$s); push(@$s, pop(@$s) - $subtrahend) }, "*" => sub { my ($s) = @_; push(@$s, pop(@$s) * pop(@$s)) }, "/" => sub { my ($s) = @_; my $divisor = pop(@$s); push(@$s, pop(@$s) / $divisor) }, "%" => sub { my ($s) = @_; my $divisor = pop(@$s); push(@$s, pop(@$s) % $divisor) }, "^" => sub { my ($s) = @_; my $exponent = pop(@$s); push(@$s, pop(@$s) ** int($exponent)) }, "c" => sub { my ($s) = @_; @$s = () }, "d" => sub { my ($s) = @_; push(@$s, @$s[-1]) }, "f" => sub { my ($s) = @_; print(join("\n", reverse(@$s)), "\n") }, "p" => sub { my ($s) = @_; print("@$s[-1]\n") }, "q" => sub { exit }, "r" => sub { my ($s) = @_; my $top = pop(@$s); push(@$s, $top, pop(@$s)) }, "v" => sub { my ($s) = @_; push(@$s, sqrt(pop(@$s))) }, ); my @stack = (); while (<>) { foreach my $token (split) { if (exists $operators{$token}) { &{$operators{$token}}(\@stack); # invoke the code ref } elsif ($token =~ m/\d+/) { push(@stack, Sexagesimal->new($token)); } else { print "$token is unimplemented\n"; } } }