I've finished Game Scripting Mastery, and it's a pretty good book overall. I think it could have done with a bit more on optimisation, although I suppose that's out of the scope of the book really. Overall 8.5/10. Definitely worth buying if you want to make your own scripting language.
I've started work on DruinkScript, using the same ideas from the book - start with an assembler, then make the VB, then a compiler. Except in my case it'll be in the following order:
- Assembler
- VM
- Basic debugger framework
- Compiler
- Complete Debugger
The debugger will interface with the VM (And will be completely compiled away in release builds), and will let you step through the code. The VM will do a blocking socket read to determine when to continue, so the app being debugged will behave just as if it was in the MSVC debugger. It's probably overkill, but I think it'll be nice.
Anyway, I'm working on DruinkASM just now and so far the lexer is pretty much complete, and the parser is in a good state. I can assemble the following file correctly, although it doesn't do a lot:
; Test.DASM; Test DruinkScript assembly file#define num 5func StringTest{ pop r1 pop r0}func _Main{ mov r1, 0xa ; r1 = 10 mov r2, num ; r2 = num (5) mul r1, r2 ; r1 *= r2 mov r0, "This is a test string with \"escaped\" bits" push r0 push r1 call StringTest}
#define statements are just direct substitutions. You can only #define an integer, float or string. I probably won't add support for anything else, since that should be quite enough for most use. I certainly don't want a complete preprocessor (Since it's not preprocessed at all, I just handle #defines as a special case).
I intend DruinkScript to have opcodes for pretty much any string operation, so a lot of string manipulation will be done in C code rather than script code. DruinkScript will probably have several types of string that can be used, and you'll choose which one to use at compile time. The basic string will just be a std::string wrapper. The more advanced one will be a linked list of string chunks. Each chunk is maybe 32 bytes, and you can build up strings by inserting chunks into the string list.
Assuming I use 8 byte chunks, you could do stuff like this:
Replacing "lol" with "I LIKE TO MOVE IT MOVE IT!" in the string:
"This is a loller string. yay."
Initially, it'll be made up like this:
- Chunk1 - - Chunk2 - - Chunk3 - - Chunk4 -
"This is " "a loller" " string." " yay.###"
Where # is a NULL or unused byte.
Searching through and replacing the "lol", gives:
- Chunk1 - - Chunk2 - - Chunk3 - - Chunk4 - - Chunk5 - - Chunk6 - - Chunk7 - - Chunk8 -
"This is " "a I LIKE" "TO MOVE " "IT MOVE " "IT######" "ler#####" " string." " yay.###"
What happened is the string was split after the "lol", and moved into a new chunk (Chunk6). The rest of chunk 2 was used, then new chunks were inserted to fill up the rest of the chain, then it was linked back to the rest of the string.
Well, that's the theory anyway. It might end up being more expensive to do it this way. I'll be using fake free lists for this (A pre-reserved std::vector of string chunks) so the runtime allocation should be practically nill.
Anyway, that'll do for now. I'm supposed to be going out tonight, but nobosy replied to my text of "Gathering at mine", so I'll be heading out to a friends house then Opium I expect. Just for a change...