Q: When I build my project that has very deeply nested statements, NTK runs out of memory and quits. What's going wrong?
A: The deep nesting in your project is causing the compiler to overflow the stack space available in NTK. NTK 1.6 is more likely than than NTK 1.5 to suffer this problem due to new compiler code which nests deeper while parsing if-then-else statements, causing the stack to overflow into the application heap.
If you see an inadvertent crash in NTK during a save operation or a package build:
1) If you are familiar with MacsBug, examine the stack. This particular case will show up in the stack as several calls to the same function before the actual crash.
2) Otherwise, temporarily reduce the number of "else" branches and rebuild the package. If the problem disappears, stack overflow is the prime suspect.
There are at least three ways to avoid this problem and possibly improve performance at the same time:
1) Re-arrange the 'else' statements to resemble a balanced tree
2) Instead of If-then-else statements use:
An array of functions (with integers as selectors)
A frame of functions (with symbols as selectors)
3) Finally, as a temporary work around, you can increase the stack size using the ResEdit application.
Re-arrange the 'else' statements to resemble a balanced tree
This solution is the simplest to implement if you need to change existing code. It accommodates non-contiguous integer selectors, and in most cases is faster.
For example, the following code:
if x = 1 then
dosomething
else
if x = 2 then
doSomethingElse
else
if x = 3 then
doYetAnotherThing
else
if x = 4 then
doOneMoreThing
else
if x = 5 then
doSomethingSimple
else
if x = 6 then
doThatThing
else
if x = 7 then
doThisThing
else // x = 8
doTheOtherThing
...can be rewritten like this:
if x <= 4 then
if x <= 2 then
if x = 1 then
doSomething
else // x = 2
doSomethingElse
else
if x = 3 then
doYetAnotherThing
else // x = 4
doOneMoreThing
else
if x <= 6 then
if x = 5 then
doSomethingSimple
else // x = 6
doThatThing
else
if x = 7 then
doThisThing
else // x = 8
doTheOtherThing;
Note that the if/then/else statement nesting is "unusual" to illustrate the nesting that the compiler must make each statement is nested as the compiler would process it.
Use an array of functions with integer selectors
Replace a long if-then-else statement with an array of functions. The code is more compact and readable. For a large set of alternatives, the faster direct lookup should compensate for the extra function call. This approach is most useful for a contiguous range of selector values (e.g., 11 to 65). It can accommodate a few "holes" (for example, 11 to 32, 34 to 56, 58 to 65). It is not practical for non-contiguous selectors (e.g., 31, 77, 256, 1038...)
For example, the following code:
if x = 1 then
dosuchandsuch;
else
if x = 2 then
dosomethingelse;
else
if x = 3 then
andsoon;
...can be rewritten like this:
cmdArray := [func() dosuchandsuch,
func() dosomethingelse,
func() andsoon];
call cmdArray[x] with ();
Use a frame of functions with symbols for selectors
This alternative provides the flexibility of using symbols for selecting the outcome.
For example, the following code:
if x = 'foo then
dosuchandsuch;
else
if x = 'bar then
dosomethingelse;
else
if x = 'baz then
andsoon;
...can be rewritten like this:
cmdFrame := {foo: func() dosuchandsuch,
bar: func() dosomethingelse,
baz: func() andsoon};
call cmdFrame.(x) with ();
Increase NTK's stack size using the ResEdit application
Open the Newton Toolkit application with ResEdit.
Double-click on the "mem!
" resource icon
Double-click on resource ID 1000
named "Additional NTK Memory Requirements"
Change the fifth (and last) value. This is an hexadecimal number. In NTK 1.6, you should see "0001 8000
" which is 98304
bytes (or 96k
) to add to the total stack size. For example, to increase this value to 128k
= 131072
bytes change the hexadecimal value to "0002 0000
".