[OpenBIOS] [PATCH] Adds local variable support to OpenBIOS.

Tarl Neustaedter tarl-b2 at tarl.net
Tue Aug 28 03:18:08 CEST 2012


I'm not Segher, but I'll comment:
>> Don't check stack depth, it is useless.  It doesn't work when you
>> forgot to pass a parameter but there is other stuff on the stack
>> already (the common case).  Your check also doesn't work if there
>> is a negative number of parameters on the stack (the next most
>> common case...)
>> Just kill this part.
> I don't think ignoring all possible error situations is better than 
> handing a few of them.

Not really. If you can only catch occasional errors, you produce more 
confusion than illumination. In general, in any given forth code, you 
are going to get called with other stuff on the stack so your depth is 
meaningless. You almost never are at a stack depth of zero.

>>> +DEPTH 2 < IF
>>> +CR ." Please specify an index number." CR
>>> +drop\ removes the address of the array instance
>>> +-1 throw\ stop normal execution after error
>>> +THEN
>> -1 THROW   is   ABORT
>> Same thing here, just kill this code.
> The error handling makes the word more user friendly. Having it fail 
> and leaving the user clueless why doesn't sound right.

Not really. If sometimes you get an error message and sometimes you 
don't, and the difference is something entirely unrelated (like, you are 
inside a loop), it produces more confusion than elucidation. In general, 
forth code, because it's always called deep on the stack, doesn't assume 
any significant meaning from depth on the stack. Other than "underflow" 
when you've already screwed the pooch.

>> And don't use CamelCase.
> Is this some official naming convention, or your own taste?

In general (at least in the 1275 world), Forth is case-insensitive. The 
rare cases where it is made case sensitive (there are a couple in Sun's 
Openboot - see dropins.src) make use of mixed case very painful. The 
general standard is that methods and variables are lower case, defined 
constants and structure offsets are upper case. In some code, even they 
are lower case.

Mixed-case is generally confined to comments.

>> Factor this?  You shouldn't ever use a variable that is used as a temp
>> inside a word.
> I'm not sure why you suggest this. It is just such a pain having to 
> deal with the stack.

Because using a global variable gets you in trouble in recursion or when 
the same code is called at alarm level. As for stack being a pain, yes, 
that's forth. Stack manipulation as a way of life. Personally, I prefer 
"2over nip" rather than "2 pick" :-)

>>> +48 CONSTANT localTableSize
>>> +
>>> +\ Declare the local variable table
>>> +localTableSize ARRAY localVariableTable
>> You have 48 but can only access 12?
> That is four fields per local variable: 48 / 4 = 12.

At a minimum, any derived constants should be derived explicitly. Like:

12 constant #local-variables     \ Feels right. If you need more, add 
more code after Locals11.
4 constant /local-variable       \ Datastructures require four cells
#local-variables /local-variable * constant locals-table-size \ Size in 
cells, not bytes.

Ah. That points out another convention. When mashing together multiple 
words for a method or variable name, we tend to use dashes as separators 
(and please, don't use underscores. There is someone I know who *mixes* 
underscores and dashes in variable names!). Another is that sizes of 
things are usually /object (such as /n, /l, ...) and counts of objects 
are usually #object.

>>> +: getLocalRecordCount
>>> +arrayCount 4 /
>>> +;
>> Oh.  Use a struct?
> The little documentation on struct I found did not indicate it was a 
> better replacement for Array.

Struct will allow you define what the four separate words used in each 
local variable entry are used for. If you use structs, I'd expect to see 
something like:

    /n field >LOCAL-INIT
    /n field >LOCAL-ORDER
    /n field >LOCAL-LEN
    /n field >LOCAL-ADDR
constant /local-variable
12 constant #local-variables
/local-variable #local-variables constant locals-table-size

Note that the above provides the table size in bytes, rather than cells.

To use the above (assuming you are still using alloc-mem), you'd see 
something like:

     locals-table-size alloc-mem     ( table )
     #local-variables 0 do           ( table )
       i /local-variable *           ( table entry )
       0 over >LOCAL-INIT !          ( table entry )
       0 over >LOCAL-ORDER !         ( table entry )
       0 over >LOCAL-LEN !           ( table entry )
       0 swap >LOCAL-ADDR !          ( table )
    loop                             ( table )
> What is a hot path?

Anything that gets called in the run path of code. If it gets called 
only once at initialization, it's not in the hot path. If it gets called 
on every method invocation, it's a hot path.

More information about the OpenBIOS mailing list