home *** CD-ROM | disk | FTP | other *** search
Prolog Source | 1986-06-10 | 9.1 KB | 365 lines |
- /* TPCALC.PRO */
- /* Copyright Craig Fleming, 1986. Rights granted for all */
- /* not-for-profit usage and distribution. */
-
- /* This Program takes advantage of the scratchpad memory routines
- introduced in SCRTCH.PRO to implement a four register RPN calculator.
- RPN is Reverse Polish Notation (of course), the same scheme used for HP
- Calculators. Operations are performed on a four register stack. There
- is also a fifth stack (not shown) which captures entries popped out of
- stack four, and pushes them back again when the register stacks drop.
- Total time to implement the calculator was about 4 hours, so it
- may not be as elegant as possible. Even so it provides an impressive
- display of Turbo Prolog's power. Improvements and Enhancements are
- encouraged. For example, add macro programming capabilities to attach
- special function key definitions.
- A word of philosophy: Prolog's real power lies in its symbolic
- processing capabilities. If you want to calculate heat flux across
- a pipe with liquid flowing through it -- choose Fortran or Pascal.
- It's just nice to know that you can crunch numbers if and when the
- need arises. By the way Jerrold Kaplan of Lotus Development (quoted
- in Byte 5/86) argues that spreadsheets are actually "object oriented
- declarative programming languages". Interesting. */
-
-
-
- domains
- name = symbol
-
- database
- sp(name,real)
-
- predicates
- /* The basic scratchpad memory routines. Their names
- describe their functions. */
- remember(name,real)
- recall(name,real)
- forget(name)
- replace(name,real)
-
- /* The calculator engine */
- process
- action(real,string,string)
- start
-
- /* Various Utilities */
- set_up_calc
- set_window_values(integer)
- help_window
- write_regs
- write_reg(integer)
- read_next(string)
- roll_regs_down(integer)
- roll_regs_up(integer)
- exchange_1_2
-
- goal
- start.
-
- clauses
-
- /* The basic scratchpad memory routines. */
- remember(Name,Value):-
- asserta(sp(Name,Value)).
-
- forget(Name) :-
- retract(sp(Name,_)).
-
- replace(Name,Value):-
- retract(sp(Name,_)),
- asserta(sp(Name,Value)).
-
- recall(Name,Value) :- sp(Name,Value).
-
-
- /* The calculator engine */
- /* Note the usage of the state variable to control execution.
- Taken together, process and action constitute a simple ATN --
- Augmented Transition Network. */
-
- start:- forget(state),fail.
- start:-
- set_up_calc,
- write_regs,
- remember(state,1),
- remember(last_char,0),
- process.
-
- process:-
- recall(state,State),
- State=3,!.
-
- process:-
- read_next(Instring),
- recall(state,State),
- action(State,Instring,""),
- process.
-
-
- read_next(Instring):-
- readchar(Inchar),
- str_char(Instring,Inchar),
- write(Instring).
-
- /* These first few action predicates are responsible for reading in
- numeric entries. Entries are terminated by an =, CR, or an
- operation. When readchar reads -- where is it reading from?
- It is not window One. I'll show you later. */
-
-
- action(1,String,_):-
- str_int(String,No),
- No>=0,No<=9,
- roll_regs_up(4),
- replace("1",No),
- write_regs,
- replace(state,2),
- read_next(Instring),
- action(2,Instring,String).
-
-
- action(2,String,Buffer1):-
- str_int(String,No),
- No>=0,No<=9,
- concat(Buffer1,String,Buffer2),
- str_real(Buffer2,Value),
- replace("1",Value),
- write_reg(1),
- read_next(Instring),
- action(2,Instring,Buffer2).
-
- /* Decimal Points, anyone? */
- action(2,String,Buffer1):-
- String=".",
- concat(Buffer1,String,Buffer2),
- str_real(Buffer2,Value),
- replace("1",Value),
- write_reg(1),
- read_next(Instring),
- action(2,Instring,Buffer2).
-
- /* How about elementary operators */
- /* (Where is Turbo Prolog's ^ operator? */
- action(_,String,_):-
- String="+",
- recall("1",X),
- recall("2",Y),
- Z=X+Y,
- replace("1",Z),
- roll_regs_down(2),
- write_regs,
- replace(state,1),!.
-
- action(_,String,_):-
- String="-",
- recall("1",X),
- recall("2",Y),
- Z=Y-X,
- replace("1",Z),
- roll_regs_down(2),
- write_regs,
- replace(state,1),!.
-
- action(_,String,_):-
- String="*",
- recall("1",X),
- recall("2",Y),
- Z=X*Y,
- replace("1",Z),
- roll_regs_down(2),
- write_regs,
- replace(state,1),!.
-
- action(_,String,_):-
- String="/",
- recall("1",X),
- recall("2",Y),
- Z=Y/X,
- replace("1",Z),
- roll_regs_down(2),
- write_regs,
- replace(state,1),!.
-
-
- action(_,String,_):-
- String="=",
- replace(state,1),!.
-
- action(_,String,_):-
- String="\13",
- replace(state,1),!.
-
- /* Swaps registers one and two. Handy. */
- action(_,String,_):- String="e",exchange_1_2.
- action(_,String,_):- String="E",exchange_1_2.
-
- /* Roll registers down. Also provides a Clear Entry Function. */
- action(_,String,_):-
- String="d",
- roll_regs_down(1),
- write_regs,
- replace(state,1),!.
-
- action(_,String,_):-
- String="D",
- roll_regs_down(1),
- write_regs,
- replace(state,1),!.
-
- /* What goes down must come up! */
- action(_,String,_):-
- String="u",
- roll_regs_up(4),
- write_regs,
- replace(state,1),!.
- action(_,String,_):-
- String="U",
- roll_regs_up(4),
- write_regs,
- replace(state,1),!.
-
- /* Aha - the function keys
- 059 ==> F1
- 060 ==> F2
- 061 ==> F3, etc. */
-
- /*Problem 1: On my system, I can't trap F3 as written here.
- Does it work on your system? Why or Why Not?
- Have you noticed that if you use the prompt
- statement to redefine function keys in association
- with ANSI.SYS in Dos, that Turbo Prolog does not
- mask these definitions on entry?
- Problem 2: Why does the error indicator beep when a function
- key is depressed? */
-
- action(_,String,_):-
- String="\59",
- /* F1 ==> Sqrt */
- recall("1",Value),
- NewValue=sqrt(Value),
- replace("1",NewValue),
- write_regs,
- replace(state,1),!.
-
-
- action(_,String,_):-
- String="\60",
- /* F2 ==> ln */
- recall("1",Value),
- NewValue=ln(Value),
- replace("1",NewValue),
- write_regs,
- replace(state,1),!.
-
- action(_,String,_):-
- String="\61",
- /* F3 ==> exp */
- recall("1",Value),
- NewValue=exp(Value),
- replace("1",NewValue),
- write_regs,
- replace(state,1),!.
-
- /* The way out */
-
- action(_,String,_):-
- String="q",
- replace(state,3),!.
- action(_,String,_):-
- String="Q",
- replace(state,3),!.
-
- /* Notify about bad key presses. Also guarantees a true
- true evaluation at the end of any action string. */
- action(_,_,Buffer):-!,
- sound(1,3000),
- recall(state,State),
- read_next(Instring),
- action(State,Instring,Buffer).
-
- /* Looks simple enough */
- write_regs:-
- write_reg(1),write_reg(2),write_reg(3),write_reg(4).
-
- write_reg(No) :-
- str_int(Reg,No),
- recall(Reg,Value),
- shiftwindow(No),
- nl,
- write(Value),
- shiftwindow(5).
- /* What is window 5? Why do we keep going back to it? */
-
- /* Whee!!!! I'm recursive! */
- roll_regs_up(0):-
- replace("1",0),!.
- roll_regs_up(No) :-
- str_int(Reg,No),
- recall(Reg,Value),
- RegUpNo=No+1,
- str_int(RegUp,RegUpNo),
- replace(RegUp,Value),
- NextReg=No-1,
- roll_regs_up(NextReg).
-
- /* Big deal. So am I. */
- roll_regs_down(5):-!.
- roll_regs_down(No) :-
- str_int(Reg,No),
- RegDnNo=No+1,
- str_int(RegDn,RegDnNo),
- recall(RegDn,Value),
- replace(Reg,Value),
- NextReg=No+1,
- roll_regs_down(NextReg).
-
-
- /* No mysteries here. */
- exchange_1_2:-
- recall("1",X),
- recall("2",Y),
- replace("1",Y),
- replace("2",X),
- write_regs,
- replace(state,1),!.
-
-
-
- /* Defines the calculators windows. Note the attribute definition
- of Window 5 */
- set_up_calc :-
- makewindow(8,17,33,"",0,0,25,80),
- makewindow(7,18,33,"Calculator Functions",2,41,14,35),
- help_window,
- makewindow(6,18,33,"Turbo Prolog Calculator",2,3,16,35),
- makewindow(1,33,18,"One",13,6,3,29),
- makewindow(2,33,18,"Two",10,6,3,29),
- makewindow(3,33,18,"Three",7,6,3,29),
- makewindow(4,33,18,"Four",4,6,3,29),
- makewindow(5,17,17,"Invisible Window",17,41,3,25),
- set_window_values(1),
- set_window_values(2),
- set_window_values(3),
- set_window_values(4),
- remember("5",0.00).
-
- set_window_values(No) :-str_int(Reg,No),recall(Reg,_),!.
- set_window_values(No) :-str_int(Reg,No),remember(Reg,0).
-
- /* You could make this a pop-up feature. Actually, why not pop up
- the calculator in the midst of your program as needed? Are you
- ready for the Turbo Desktop Environment? Not that I would
- abandon my trusty Sidekick! */
-
- help_window :-
- cursor(1,1),write("Operators"),cursor(1,12),write("Function"),
- cursor(2,1),write("+ - * /"),cursor(2,12),write("Math Operators"),
- cursor(3,1),write("E"),cursor(3,12),write("Exchange 1<-->2"),
- cursor(4,1),write("U"),cursor(4,12),write("Roll Registers Up"),
- cursor(5,1),write("D"),cursor(5,12),write("Roll Registers Down"),
- cursor(6,1),write("Q"),cursor(6,12),write("Quit"),
- cursor(8,1),write("F1"),cursor(8,12),write("Square Root"),
- cursor(9,1),write("F2"),cursor(9,12),write("Ln One"),
- cursor(10,1),write("F3"),cursor(10,12),write("e^One").
-