############################################################################ # # File: calc.icn # # Subject: Program to simulate desk calculator # # Author: Ralph E. Griswold # # Date: January 3, 1993 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This is a simple Polish "desk calculator". It accepts as values Icon # integers, reals, csets, and strings (as they would appear in an Icon # program) as well as an empty line for the null value. # # Other lines of input are interpreted as operations. These may be Icon # operators, functions, or the commands listed below. # # In the case of operator symbols, such as +, that correspond to both unary # and binary operations, the binary one is used. Thus, the unary operation # is not available. # # In case of Icon functions like write() that take an arbitrary number of # arguments, one argument is used. # # The commands are: # # clear remove all values from the calculator's stack # dump write out the contents of the stack # quit exit from the calculator # # Example: the input lines # # "abc" # 3 # repl # write # # writes abcabcabc and leaves this as the top value on the stack. # # Failure and most errors are detected, but in these cases, arguments are # consumed and not restored to the stack. # ############################################################################ # # Links: ivalue, usage # ############################################################################ invocable all link ivalue, usage global stack procedure main() local line stack := [] while line := read() do (operation | value | command)(line) | Error("erroneous input ", image(line)) end procedure command(line) case line of { "clear": stack := [] "dump": every write(image(!stack)) "quit": exit() default: fail } return end procedure operation(line) local p, n, arglist if p := proc(line, 2 | 1 | 3) then { # function or operation? n := abs(args(p)) arglist := stack[-n : *stack + 1] | { Error("too few arguments") fail } stack := stack[1 : -n] &error := 1 # anticipate possible error put(stack, p ! arglist) | { # invoke if &error = 0 then Error("error ", &errornumber, " evaluating ", image(line)) else Error("failure evaluating ", image(line)) stack |||:= arglist # restore unused arguments } &error := 0 return } else fail end procedure value(line) put(stack,ivalue(line)) | fail return end