Quake C
Blitz3D Forums/Blitz3D Userlibs/Quake C
| ||
DO NOT USE THIS CODE!!! IT DOES NOT WORK!!! It's here for historical reasons only. --- EDIT4: I think I'll fork the projects actually - see if I can finish Noodle completely and then come back to this and build it to more closely imitate a QuakeLike, just for fun. EDIT3: GC is functional (it's a tracing GC based on HotSpot, so cyclic references ought not to be a problem), but there is no tenured storage yet (so very limited). EDIT2: New version is not quite ready for release, but you can download the incomplete version and keep an eye on the progress here. It'll be out as soon as the GC (yes, a GC) is EDIT: This doesn't really work as-is. Rather than fix it (it's borderline impossible to fix this coding disaster), I'm rewriting it from scratch, which will take a little longer but allow a few extra features (OK, OK, custom types and dynamic arrays are going in) as well as getting rid of that pesky GPL. The code remains here if you want to examine it anyway, but be warned that there are so many typos and holes that you could throw a brick through this and not see a difference. --- Quake C is a lightweight scripting language with C-like syntax, developed by ID to write scripts for the original Quake engine. I thought it might be fun to use it as a scripting solution for Blitz projects - here is the result so far. Please note that this is not extensively tested - I haven't tested arrays at all - and not necessarily complete. I am not yet sure about its speed compared to other options (in my only test, it was faster than GameScript, but that was most likely non-representative). First - language specification: http://www.gamers.org/dEngine/quake/spec/quake-spec34/qc-menu.htm (only the first page is really relevant due to the changes) This implementation has a few differences, however. Firstly, most obviously, Progs.dat is no longer relevant, so unless you especially want to compile to a file named that, the compiler simply outputs separate compiled scripts named scriptname.qcx (get used to recognising GameScript ideas). Source therefore needs to have a "main()" function and won't work without it. Secondly, "states" or "frame functions" are also absent, again being only relevant to the Quake engine, and the same goes for $-macros and the "field" data type. Thirdly, I have added simple preprocessor directives (#include, #define, #ifdef, #endif - #define is a simple copy and paste though, not a proper macro) and the ability to define simple arrays (after the fashion of Blitz arrays, they can be local and must be of constant size. You can use #defined constants for this, but not QuakeC constants). Since the interpreter now uses a stack instead of hundreds of global variables, it is now possible to call functions as parameters to other functions (composition) or operators (both impossible in the original). I have not added custom types and do not currently intend to do so. Special mention needs to go to built-in functions (even though I actually haven't changed that) because they do still need to be prototyped in the script's source (the idea being that you make your own list of builtins and hardcode complex types as your project requires). And no, the absence of integers is not an error, it is intentional. Add them if you want, but it adds complexity. The syntax is similar enough to C that a C IDE will provide context highlighting and indentation services, but not so similar that the code will compile. I don't ask for more than that from IDEs so I don't know if other features would work. Finally, before we get to the code, the reason this isn't going straight into the code archives to be ignored in the right place is because the Quake code was released under the GPL - keep reading! - and therefore the compiler, which is almost entirely straight copied from the original source, falls under the same licence. The interpreter I made without reference to the Quake source - it's obviously similar, because it reads the output of the compiler, but it is my own work (working in a significantly different way from the original) and therefore can be released to the public domain. In the unlikely event anyone uses this, you can use the interpreter in your projects, but do not put the compiler in your main source or the GPL will infect that as well. Distribute the compiler as a separate exe (and source, of course) and you will be safe from the GPL. The alert reader will notice some conventions (packing loaded scripts into "threads", compiling to extension+"x", etc.) are borrowed from GameScript. Conventions and stylistic ideas are all I borrowed - I have no idea how GameScript works because I don't have the patience to read through it (that's why I made my own alternative), so any non-stylistic similarities are coincidental, or at least unintentional. 1. The compiler 2. Its header 3. The interpreter 4. The interpreter's header [codebox] ;Blitz3D QuakeC Interpreter ;========================== ;Header ;------ Const MAX_VARS=1000 ; Const MAX_FUNCS=100 ;; Const MAX_OPS=10000 ;;; These are constants because the values are held in Blitz arrays. Feel free to increase them if necessary Const STACKSIZE=100 ;; Const LOCALSIZE=500 ; Const MAX_PARMS=8 Const STACKID=-1 Const NULLVAR=-2 Type Thread Field runstate ;0=ready, 1=running, 2=done Field vcount ;Number of variables and constants Field fcount ;Number of functions Field scount ;Number of instructions Field v.vdef[MAX_VARS] ;List of variables and constants Field f.fdef[MAX_FUNCS] ;List of functions Field s.sdef[MAX_OPS] ;List of instructions Field main.fdef ;Function main() Field insptr ;Current instruction Field cscope.fdef ;Current scope Field stack.vdef[STACKSIZE],stkptr Field localstack.vdef[LOCALSIZE],locptr Field junkptr ;Address of "junk value" to dump unwanted results End Type Type fdef ;Function definition Field ID Field name$ Field code ;offset of first statement Field rtype ;Return type Field builtin ;0 for scripted function, or number for a native function Field num_parms ;Number of parameters (-1=variable) Field fvar,lvar ;First and last variables local to function (including parameters) by ID Field parm_name$[MAX_PARMS-1] Field parm_type[MAX_PARMS-1] Field parm.vdef[MAX_PARMS-1] ;Store the ID rather than the vdef itself End Type Type vdef ;Variable definition Field name$ Field scope Field vtype Field array ;True if this is an array header Field f#,s$,e ;Value (float, string, handle) Field vx.vdef,vy.vdef,vz.vdef ;Vector field pointers (float variables) ;Add fields for other types as required End Type Type sdef ;Instruction ; Field ID Field op,a,b,c End Type ;Type constants Const ev_VOID=1, ev_STRING=2, ev_FLOAT=3, ev_VECTOR=4, ev_ENTITY=5, ev_FUNCTION=6 ;Opcode constants Const OP_DONE = 0 Const OP_MUL_F = 1 Const OP_MUL_V = 2 Const OP_MUL_FV = 3 Const OP_MUL_VF = 4 Const OP_DIV_F = 5 Const OP_ADD_F = 6 Const OP_ADD_V = 7 Const OP_SUB_F = 8 Const OP_SUB_V = 9 Const OP_CONC_S = 10 Const OP_EQ_F = 11 Const OP_EQ_V = 12 Const OP_EQ_S = 13 Const OP_EQ_E = 14 Const OP_NE_F = 15 Const OP_NE_V = 16 Const OP_NE_S = 17 Const OP_NE_E = 18 Const OP_LE = 19 Const OP_GE = 20 Const OP_LT = 21 Const OP_GT = 22 Const OP_STORE_F = 23 Const OP_STORE_V = 24 Const OP_STORE_S = 25 Const OP_STORE_ENT = 26 Const OP_RETURN = 27 Const OP_NOT_F = 28 Const OP_NOT_V = 29 Const OP_NOT_S = 30 Const OP_NOT_ENT = 31 Const OP_IF = 32 Const OP_IFNOT = 33 Const OP_CALL = 34 Const OP_GOTO = 35 Const OP_AND = 36 Const OP_OR = 37 Const OP_BITAND = 38 Const OP_BITOR = 39 Const OP_ARRAY = 40 ;Const OP_CLEARSTACK = 41 ;Built-in function IDs Built-in functions MUST be prototyped in the script. Const BF_RINT =1 ;Here for example's sake. Maths functions like these could equally well just be opcodes Const BF_FLOOR =2 Const BF_CEIL =3 Const BF_ABS =4 Const BF_RND =5 Const BF_FTOS =6 Const BF_VYAW =7 Const BF_VNORM =8 Const BF_VLEN =9 Const BF_VTO |
| ||
This looks exciting. |
| ||
. (EDIT: As above, whole thing is being rewritten because this version has too many bugs to fix, the biggest one being the GPL. By all means play with it, but don't expect it to work as advertised. The "new version" will actually have a different name, featureset and syntax, due to the fact that trying to force the QuakeC peg into the Blitz3D hole is the root of far too much messing about. The only similarity is the use of three address code, because it's awesome.) |