Elementary Cellular Automata demo animation

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Elementary Cellular Automata demo animation

iSol
Hello,

here is a Cellular Automata animation implemented in Jack. Since project 9 is pick your own subject I think it is OK if I made my code public for others to study or criticize.

Video demo:
https://www.youtube.com/watch?v=1BdujXIdgOU

Code on Github:
https://github.com/sol-prog/Cellular_Automata

 
Reply | Threaded
Open this post in threaded view
|

Re: Elementary Cellular Automata demo animation

cadet1620
Administrator
Nice program.



Here are some general comments about Jack programming.

Main.jack:

The built in type is 'boolean'.  'bool' is an object class, but since Jack is untyped, it makes no difference.  My code was full of 'bool's until I added a warning to my Jack compiler to complain about them.
    do Output.printString("Celluar Automata demo:");
Every time this line executes, it allocates a String object in the heap that is never deallocated.  You need to do something like
    let s = "Celluar Automata demo:";
    do Output.printString(s);
    do s.dispose();
to deallocate the string constants.  This is such a PITA that I wrote a helper class OutUtil with functions like
    function void printStringConst(String s) {
        do Output.printString(s);
        do s.dispose();
        return;
    }

CA.jack
    field int row_size, ruleset_size, row_size;
row_size is declared twice.  JackCompiler doesn't complain about it, mine does.


Utils.jack

Multiplication and division can really slow thing down.  The Hack platform doesn't do a good job with right shifting, as you saw.  Many algorithms that traditionally use right-shifting can be modified to use left-shifting (aka addition).

For instance bitAt() can be written something like this (typos included free of charge)
    function int bitAt(int number, int bitPosition) {
        bitPosition = 15-bitPosition;
        while (bitPosition > 0) {
            let number += number;
            let bitPosition = bitPosition-1;
        }
        if (number < 0) {   // test sign bit
            return 1; }
        return 0;
    }
(Or if you want more obscure code, "return -(number < 0);" instead of the if and returns.)

--Mark
Reply | Threaded
Open this post in threaded view
|

Re: Elementary Cellular Automata demo animation

iSol
Thanks. Great advice.

I suspected constant strings created by printString were never deallocated after after I've checked the generated vm code for the simple "HelloWorld.jack" program, but I wasn't 100% sure. I'll make sure my OS implementation doesn't leak.
Reply | Threaded
Open this post in threaded view
|

Re: Elementary Cellular Automata demo animation

ivant
You cannot distinguish between "constant" and variable usage in the OS. That's because they only seem to be constant. To properly fix this, you'll need to change the VM to support constant strings and you'll need to make your Jack compiler put constants there.

Alternatively, you can write your alloc to use garbage collection, which is no small feat either.

Mark's solution is much easier as it works with the existing tool chain. Of course, you need to be aware which method you should call.
Reply | Threaded
Open this post in threaded view
|

Re: Elementary Cellular Automata demo animation

iSol
What I had in mind was to let the compiler insert some extra code if printString has a constant string as an argument and leave it as it is if the argument is a variable string.

A simple approach is to inject code similar with the one suggested by Mark for constant strings.

The idea is to have support in the OS for printString/printConstantString and let the compiler decide which to use.
Reply | Threaded
Open this post in threaded view
|

Re: Elementary Cellular Automata demo animation

ivant
That sounds like a good idea and it shouldn't be very hard to implement.
Reply | Threaded
Open this post in threaded view
|

Re: Elementary Cellular Automata demo animation

cadet1620
Administrator
In reply to this post by iSol
Consider the problem with
    let name = "My App"";
    let version = 3;
    do Main.printHeader(name, version);
A better approach might be to add a constant property to the String class.

The compiler adds a call to String.makeConstant() following the appendChar() calls that build the string constant. The return value from makeConstant() is a constant string. Calling dispose on a constant string will do nothing.

To prevent filling memory with constants, String should keep a list of constant strings. makeConstant() scans this list looking for a match and if found, deallocates the new string and returns the existing constant string, otherwise it puts the new string into the constant list.

All operations that change String objects would need to need a new system error "attempt to modify constant string".

Some additional functions would also be useful.  For instance, String.duplicate() that returns a non-constant copy of a string. This allows string constants to be used as templates:
    let prefix = "LOOP";
    ...
    let label = prefix.duplicate();
    do addSerialNumber(label);

Also, large amounts of single-use string literals, as may appear on a help screen are still a problem. Once the screen is displayed, they will remain in the heap for the duration of the program.

--Mark