Better Late Than Never--VAL() in HP-71B BASIC



#27

I was looking at the HP-71B Math Solutions book. I discovered, to my surprise and delight, that the HP-71B function VAL goes way beyond the typical VAL implementations found in other BASIC interpreters. The HP-71B runs the argument of VAL through the BASIC interpreter engine allow you to evaluate strings as functions. For example, if I have already assigned the value of 1 to variable X, then VAL("X^2-3*x+6") yields 4!! Using this feature you can define the function:

DEF FNX(E$,X) = VAL(E$)

To evaluate functions dynamically as long as the expression in parameter E$ is a string that represents a valid expression of X. Of course the arguments for parameter X in FNX() can be any variable or expression, since VAL(E$) evaluates E$ using the argument for parameter X (and not a variable named X defined in the program).

I was delighted to discover this feature of VAL() .... Oh well .... better late than never!!

Namir


#28

For those who want more info about the different BASIC variants: I've prepared a spreadsheet which compares many BASIC dialects. The VAL() functionality Namir has found should be in the sheet as the 71B is one of the systems discussed.

Here you are: http://www.mvcsys.de/doc/basic_compare.html.


#29

Impressive comparison table!!!

As I suspected, the HP-71B and HP-75 implement the VAL() function that goes beyond simply converting a string image of a number into a number.

Using a function like VAL() (and EVAULATE() in Excel VBA) allows you to write programs that handle functions dynamically. Of course, the price to pay for this flexibility is speed.

Namir


Edited: 6 May 2011, 12:20 p.m.


#30

This was always an irritant to me in other BASICs of the era - most if not all of those MS BASICs (Commodore, Apple, etc.) just implemented an "atof()" function.

I recall I was able to take C64 BASIC's "USR(x)" function and hotwire it to pull a string instead of numeric argument - and then call the FRMEVL routine at $AD9E to do 'formula evaluation'. I think I had to also tokenize the string before calling FRMEVL.

Bill Wiese

San Jose CA

Edited: 6 May 2011, 2:20 p.m.


#31

You could do something similar as well on the Apple ][. Another form of synthetic programming. Your program always started at the same location in memory, so if you made your first line:

10 ::::::::::::::::::::::::::::::::: RETURN

Then you could use POKE to enter your tokenized string in place of the :

CALL 10

would execute your line. And the manuals in those days were so thorough that they gave you all of the addresses and token values needed to pull off things like that.

#32

While GW-BASIC implemented a simple VAL() function, I resorted to another trick to support dynamic functions at run time. I used this kind of trick in regression programs that allowed the user to enter transformations for data at run time. My program would convert the user's input into a short/small line-numbered BASIC program that's written out to disk and then use the CHAIN MERGE command to chain/merge the current program with that small programs. This approach turned the dynamic functions and expressions into BASIC statements that are then handled by the interpreter.

When I moved from GW-BASIC to Turbo-Pascal (a compiler) I sure missed that trick!

Namir

Edited: 6 May 2011, 2:53 p.m.


#33

Nowdays in C++, one can use LLVM to generate object code on the fly. It doesn't parse expressions from a human-readable string representation, though.

#34

How does Val() deal with "2^8" (two power eight), or "5!" (five factorial)? ;-)

As other dynamic languages these days, JavaScript has an eval() function that allows you not only to evaluate constant expressions, but any JavaScript code. Also, functions are data and can be constructed on-the-fly.

If you want to write a calculator, though, you still need an expression parser to deal with cases like above (and types other than Reals).

One of the reasons why MorphEngine is called MorphEngine, is because it takes expressions and "morphs" them into dynamically-created functions (written via a LALR parser, fed by a BNR grammar).

I understand, (RPL) HPs have a compiler/decompiler to accomplish making expressions executable, and vice versa.


#35

As implemented on the 71b, VAL() parses the string as BASIC text, so any functions known to the interpreter can be used. The string must represent a valid expression as defined for the language.


#36

Quote:
As implemented on the 71b, VAL() parses the string as BASIC text, so any functions known to the interpreter can be used. The string must represent a valid expression as defined for the language.

What happens when you call VAL(E$) and E$ contains the string "VAL(E$)"?


#37

You get an "Invalid Arg" error.


#38

No, the HP71B goes into infinite recursive calls!!

>endall
>destroyall
>mem
9135
>e$="val(e$)"
>val(e$)
ERR:Insufficient Memory
>mem
2810
>endall
>mem
9128

(tested on Emu71. On a real HP-71B, you may have to break the long recursion time with INIT 1]


J-F


#39

Interesting! The first time I tried:

E$="VAL(E$)"
VAL(E$)

I got the invalid arg error using the EMU71. When I do:

ENDALL
DESTROY ALL
E$="VAL(E$)"
VAL(E$)

I get "insufficient memory" with the EMU71.

Namir

Edited: 7 May 2011, 6:49 a.m.

#40

Do you have any plans to re-implement the EMU71 so that it can run under Windows 7 64 Bit? To run the EMU71 I have to run "VMLite XP Mode" which runs as 32 Bit OS.

Namir

Edited: 7 May 2011, 6:53 a.m.


#41

As far as I understand, EMU71 is written in x86 16 Bit assembly. Porting will be a huge task!

Have you tried DOSBOX or, as an alternative, plain DOS in any virtual machine like Virtual PC?


Edited: 7 May 2011, 7:08 a.m.


#42

I am using the regular DOS box in VMlite Windows XP.

I will try to locate DOSBOX. Thanks for the tip.

#43

Marcus,

I found DOSBOX and it works fine with EMU71. The only feature not supported from the plain DOS box is the ability to pasted source code into the emulator (J-F Garnier had suggested this tip on the site a few months ago). Garnier's tip works when I use the DOS box under VMlite Windows XP.

Namir

Edited: 7 May 2011, 2:02 p.m.

#44

On my Commodore PET (8K original one) I used to do something similar. You could print an expression (or statement) on the screen followed by a RUN or GOTO command; then stuff the keystroke buffer with cursor moments and RETURN characters and end the program. The keystroke buffer would be read out by the "operating system" and execute your commands then start up the program again.

It, made for great self modifying code not just dynamic expression evaluation.

-Katie


#45

That cool ... sounds similar to using CHAIN MERGE in GW-BASIC.

I doubled checked the HP-85 owner's manual to see how the VAL() function works. I was hoping that it matched the VAL() function in the HP-71B. My hopes were dashed :-(

Namir

Edited: 6 May 2011, 6:47 p.m.

#46

Quote:
I discovered, to my surprise and delight, that the HP-71B function VAL goes way beyond the typical VAL implementations found in other BASIC interpreters. The HP-71B runs the argument of VAL through the BASIC interpreter engine allow you to evaluate strings as functions. For example, if I have already assigned the value of 1 to variable X, then VAL("X^2-3*x+6") yields 4!!
The Sinclair ZX Spectrum had this feature, too.

BTW, I'm using a similar function in php to have the user define some conditions inside a semiautomatic risk analysis software. Very useful.


#47

I have been playing with Rocky Mountain BASIC again the last couple of days. At least in version 2.1, there's no string evaluation routine. At least I can't find it in the reference manual. It seems like the people in Fort Collins could have taken a hint from the guys in Corvallis in this regard.

You can do recursion in RMB though.


#48

You can say that again! After having been quite familiar with my 71's BASIC (along with a lot of extensions from the user groups), I started working with HP Rocky Mountain BASIC 5.1 and was extremely disappointed. The HP-71 was far better.


#49

I think that the finest version of Basic that HP ever created was
Business BASIC for the HP 3000 series computers. The statement called COMMAND could dynamically execute almost any command in Basic, not just evaluate an expression. It was also pretty fast because it had a compiler in addition to the interpreter. I wrote a ton of code in this language including a complete email system (before the internet was common place). One of my favorite languages, ever.

The original 3000 series was equally awesome with it's stack-based architecture and (sort of) high-level systems programming language instead of assembly. The good old days.......

#50

There are things in RMB that the 71B lacks, however. Long variable names, COM blocks (ala FORTRAN) , REPEAT/UNTIL, WHILE, SELECT/CASE are all nice. The integrated code editor/execution environment was my first introduction to such things. It topped my list for productivity until I figured out how to use EMACS with gcc/gdb a couple of years later.

I used the 9816 professionally, and it was a capable little beast for the era. It had an 8Mhz MC68000, which was fast enough to do a whole lot of simultaneous I/O. That CPU had 16MB of addressable memory. I believe the 9816 could only use half that for user memory, but it was still huge by contemporary standards. It was actually practical to have 1MB loaded into the 9816, plus an RS232 card, which together with HPIB made for an extremely capable and portable little computing package. I used these in offshore environments in the mid-1980s.

Nonetheless, I'm very fond of my 71B. The BASIC on that machine has a lot of very nice features. The LEX file concept is very cool, allowing a user to extend the BASIC, but RMB had a similar mechanism.


#51

One of the 71 modules available had the program structures like CASE and so on, but I never got that one. For longer variable names and vertical alignment and white space for readability and so on, what I did sometimes was write the program in text with my full-featured text editor (waaaaay better than what came in the Forth module for example) and then use another program to take out the blank lines and formatting lines, combine things that had to be on the same line which I had separated for readability, give it line numbers, replace the variable names with HP71-legal ones, remove comments, and TRANSFORM it to BASIC (while keeping a copy of the original file).

One thing I remember from RMB 5.1 running on the HP9000-series 68000 computer was that I couldn't just take lines I had already written and copy them somewhere else outside the structure or subprogram or something like that to reduce the amount of typing where I wanted a near-duplicate somewhere else. It would say that wasn't allowed. One program could not also refer to another program or subprogram in another file like the 71 can. It all had to be written into the same one. My memory of it is pretty foggy now, but I do remember that I kept running up against walls.

Edited: 8 May 2011, 3:47 a.m.


#52

Quote:
One of the 71 modules available had the program structures like CASE and so on ..

The JPCROM has that and more. I have that in EEPROM on m 71, and I love it.

I've set myself up to do editing of 71B programs on my Mac (in Aquamacs. Some habits die hard.) using the PIL-Box to transfer the programs back and forth as text. That's fine as far as it goes, but it doesn't get me an editing/execution environment like RMB's EDIT mode. The 71B itself provides a pretty nifty editor, but it's limited by the one line display.

Quote:
One thing I remember from RMB 5.1 running on the HP9000-series 68000 computer was that I couldn't just take lines I had already written and copy them somewhere else outside the structure or subprogram or something like that to reduce the amount of typing where I wanted a near-duplicate somewhere else.

You can do that with individual lines, by manually editing the line number, for example. But you can't delete or modify the FN or SUB definition or end markers once you've entered them. You have to delete the "entire context" meaning the whole sub or function. Also, you can't use REN to move lines relative to other lines. So if your renumber would cause the new lines to overlap other lines, or to move after or before preexisting lines, the renumber will fail.

That's annoying, but I have to say, quirks like that are one of the reasons I feel good about getting anything done on any of these old machines. :)

Regards,
Howard


Possibly Related Threads…
Thread Author Replies Views Last Post
  HP PRIME - Need help for basic program svp. dg1969 4 1,785 10-08-2013, 04:06 PM
Last Post: dg1969
  Easter Sunday Basic Trigs (HP-12C) Gerson W. Barbosa 29 8,898 04-04-2013, 02:19 PM
Last Post: Gerson W. Barbosa
  "The Basic HP-71" Jeff Davis 3 1,618 08-30-2012, 12:20 AM
Last Post: Howard Owen
  EMU41: A Little Late to The Party, but Loving It! Les Wright 3 1,528 05-09-2012, 03:28 PM
Last Post: Christoph Klug
  HP's Tired Basic Calculator Line Jeff 4 1,811 02-10-2012, 01:33 PM
Last Post: Dirk Mehldau
  Day Late, Dollar short. William L. Drylie 13 3,402 09-20-2011, 02:13 PM
Last Post: Namir
  After the 15c LE, better chance of a basic RPN calc from HP now? nick lidakis 80 16,144 09-18-2011, 08:15 AM
Last Post: snaggs
  BASIC BEEP Howard Owen 5 1,692 05-12-2011, 05:03 PM
Last Post: Garth Wilson
  Mardi Gras Basic Trigs (HP-12C) Gerson W. Barbosa 10 3,083 03-09-2011, 09:49 PM
Last Post: Gerson W. Barbosa
  OT: Sharp PC-1270 BASIC Compiler V3.3 XYZT 1 1,167 12-18-2010, 05:02 PM
Last Post: Thomas Okken

Forum Jump: