I've been working on the DNA module for the last few weeks, and this is the result. It's a command line interpreter for DNA. You can type in any DNA commands, and it will calculate them and show you the resulting stack.
Everything in the DNA should appear to work on a base 10 system. The stack has capacity for 9 digits (though this may increase in the future if I can find a clever way to multiply two longs without overflowing). A bots memory has a capacity for 4 digits. Memory exists between [0, 999]. Values outside this range are absolute valued and then modded into range.
Some commands may behave a little differently than you're used to. Sqrt for instance. I'll try to build a detailed in-console help system sometime in the future, but in the mean time, don't be afraid to ask questions.
Codules, chromosomes, and other features aren't coded yet.
I've implemented the in-place condition programming I talked about in another thread. stores and codule calls (not implemented yet, but it will be) will still pull values from the stack, but nothing will happen if the top value on the bool stack is false. An empty bool stack is treated as true.
Values will fizzle (not pull values from the stack, and do nothing) if there aren't enough values on the stack.
Things should be pretty robust, but I got a bit sloppy near the end of my work and I still need to go back and do some stronger testing. Be aggressive in your testing, and question anything that doesn't look right to you.
This is the full command list:
- add, sub - basic arithmetic, nothing fancy
- mult - multiplies two numbers and then uses only the 9 least significant digits.
- div - A divide by zero returns 0. Division always truncates the result, which is unusual to most other commands.
- mod - A divide by zero returns the original number. Mod always obeys the law a * n + b = r where a is the division result, b is the mod result, n is the divisor, and r is the original number.
- sqrt - returns the signed sqrt of a number. That is, -25 sqrt returns -5
- max, min - returns the maximum or minimum of a pair of numbers
- swap - swaps the top two values in the stack
- rand - returns a random number between (val, 0] or [0, val) depending on if val is positive or negative.
- abs - returns the absolute value of a number
- sgn - returns the sign of a number as either -1, 0, or 1
- neg - returns the negative of the top value on the stack.
- inc, dec - increments or deincrements the memory location pointed to by the top value in the stack.
- ref - returns the value of the memory location pointed to by the top value of the stack
- sin - returns the normalized sine of a number. This is actually a little weird, but basically a full circle is 1080 degrees (1080 is close to 1000, and has many integer denominators), and sin returns values in the range [-1080,1080] No cosine, since its so easy to convert a sine call to a cosine call using trig identities.
- atan - A binary operator that basically computes tan(angle) = y/x, or mirrors atan2 in most programming languages.
- store - operates like one would expect from experience with DarwinbotsII, however values are modded down to the 4 digits that memory stores.
- dup - Duplicates the top value on the stack.
- Comparisons - All 6 standard comparisons (> < >= <= = !=) are present.
- Logic - and, or, xor, not are all present
- true, false - the constants true and false are recognized
- stop - turns off DNA execution. DNA after it is basically ignored.
- start - starts the DNA executing again, and clears both the bool and integer stack
- dub, swab - mirrors the functionality of dup and swap, but for the boolean stack (note the p's are replaced with b's for "bool")
In addition, number constants are recognized, as are custom labels (and sysvars in the future, though it's not implemented yet). Instead of "10 .up store", you can now do "10 up store". In addition, a new feature called Explicits allows you to combine the location and action for memory (and eventually codule) manipulations.
For instance, "10 up store" can be done as "10 .up". The period prefix is now associated with storing instead of label lookup.
And something like *.nrg is now done as *nrg (Trying to do *.nrg will result in a syntax error).
For all explicits, labels and number constants are treated the same.
Lastly, I've set up functionality for something I'm calling Metatags. Metatags are information about
the DNA that needs to be processed before the DNA is parsed. Like preprocessor commands. So far the only one is def. You can use it like you're used to to register a custom label. def labelname 10 would cause labelname to push 10 onto the stack whenever it's encountered, for instance. I might later add in some inline macroing as well to allow people to construct their own custom commands that work the same as the default ones.
Requirements: You'll need .Net 2.0. Nothing else is needed. Download it here
Here's a quick example of using the command line interpreter. Type enter at the end of each line, in the order given, and watch what happens:
def mylabel 100
50 *mylabel add mylabel sub
The program is included as an attachment at the end of the post.