On Aug 27, 2012, at 4:44 PM, openbios-request@openbios.org wrote:
Message: 4 Date: Mon, 27 Aug 2012 22:35:40 +0200 From: Segher Boessenkool segher@kernel.crashing.org To: The OpenBIOS Mailinglist openbios@openbios.org Subject: Re: [OpenBIOS] [PATCH] Adds local variable support to OpenBIOS. Message-ID: F74BFA60-0824-49A9-B592-D6862E0ACFB7@kernel.crashing.org Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed
Let me comment on the code, independently of if I think using local var names is a good idea at all.
- DEPTH 0= IF
CR ." Please specify an array size." CR
EXIT
- THEN
You shouldn't blindly continue when you detect an error; use ABORT instead, or ABORT" since you want to print something.
Thanks for catching this. It has been corrected.
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.
- CREATE CELL * ALLOT \ creates and initializes the instance
CELL * is CELLS (which is a standard Forth word, CELL is not).
Thanks for letting me know about CELL. I have changed them all to CELLS
- 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.
+; immediate
Defining words should not be immediate in most cases, including here.
+\ Declare the local-base-address VALUE +0 VALUE local-base-address
+\ returns the base address used for the local words +: getBaseAddress ( - addr )
- local-base-address
+;
: really-get-base-address getBaseAddress ; : really-really-get-base-address really-get-base-address ;
And don't use CamelCase.
Is this some official naming convention, or your own taste?
+\ Sets the first local variable's value +: Local0! ( x - )
- 0 CELL * getBaseAddress + !
+;
You can do something smarter than this...
+\ Sets the twelfth local variable's value +: Local11! ( x - )
- 11 CELL * getBaseAddress + !
+;
...why stop at 11?
As far as I know, Apple's code only uses two local variables at most. I figured 12 local variables per word should be enough.
+: calculateNeededMemory ( "char" - n )
- 0 TO variableCount
in @ \ keep track of where the pointer was- begin
parse-word
0= if \ if there is no more text to parse
drop
true
else
dup " ;" comp
0= if \ if the semicolon is encountered
drop \ drop the duplicated address
false
else
" }" comp
0= if \ if '}' character is encountered
true \ end loop because '}' marks end of local variables
else
variableCount 1 + TO variableCount
false
then
then
then
- until
in ! \ reset the pointer- variableCount CELL *
+;
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.
+: allocateMemory ( n - addr )
- alloc-mem dup 0= if
drop
cr cr 10 spaces abort" Failed to allocate memory for local
variables!" cr cr
- then
+;
alloc-mem is way too slow to be used on every function call. Statically allocate a locals stack, or put it on an existing stack, or something like that.
I agree. That is why it is only used at compile time.
+\ Declares the size of the local variable table +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.
+: getLocalRecordCount
- arrayCount 4 /
+;
Oh. Use a struct?
The little documentation on struct I found did not indicate it was a better replacement for Array.
I'll stop here. There are two good ways to implement locals (or anything else, really): 1) Make it _simple_: you can do locals in about 20 or 30 lines of code. 60 is fine, too. 2) Make it efficient: don't allocate from a heap, don't run much code on the hot paths. This will be much smaller code as well, but perhaps trickier to understand.
What is a hot path?
Segher