DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

Script_Compiler.cpp (72994B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #pragma hdrstop
     30 #include "../../idlib/precompiled.h"
     31 
     32 
     33 #include "../Game_local.h"
     34 
     35 #define FUNCTION_PRIORITY	2
     36 #define INT_PRIORITY		2
     37 #define NOT_PRIORITY		5
     38 #define TILDE_PRIORITY		5
     39 #define TOP_PRIORITY		7
     40 
     41 bool idCompiler::punctuationValid[ 256 ];
     42 char *idCompiler::punctuation[] = {
     43 	"+=", "-=", "*=", "/=", "%=", "&=", "|=", "++", "--",
     44 	"&&", "||", "<=", ">=", "==", "!=", "::", ";",  ",",
     45 	"~",  "!",  "*",  "/",  "%",  "(",   ")",  "-", "+",
     46 	"=",  "[",  "]",  ".",  "<",  ">" ,  "&",  "|", ":",  NULL
     47 };
     48 
     49 opcode_t idCompiler::opcodes[] = {
     50 	{ "<RETURN>", "RETURN", -1, false, &def_void, &def_void, &def_void },
     51 		
     52 	{ "++", "UINC_F", 1, true, &def_float, &def_void, &def_void },
     53 	{ "++", "UINCP_F", 1, true, &def_object, &def_field, &def_float },
     54 	{ "--", "UDEC_F", 1, true, &def_float, &def_void, &def_void },
     55 	{ "--", "UDECP_F", 1, true, &def_object, &def_field, &def_float },
     56 
     57 	{ "~", "COMP_F", -1, false, &def_float, &def_void, &def_float },
     58 	
     59 	{ "*", "MUL_F", 3, false, &def_float, &def_float, &def_float },
     60 	{ "*", "MUL_V", 3, false, &def_vector, &def_vector, &def_float },
     61 	{ "*", "MUL_FV", 3, false, &def_float, &def_vector, &def_vector },
     62 	{ "*", "MUL_VF", 3, false, &def_vector, &def_float, &def_vector },
     63 	
     64 	{ "/", "DIV", 3, false, &def_float, &def_float, &def_float },
     65 	{ "%", "MOD_F",	3, false, &def_float, &def_float, &def_float },
     66 	
     67 	{ "+", "ADD_F", 4, false, &def_float, &def_float, &def_float },
     68 	{ "+", "ADD_V", 4, false, &def_vector, &def_vector, &def_vector },
     69 	{ "+", "ADD_S", 4, false, &def_string, &def_string, &def_string },
     70 	{ "+", "ADD_FS", 4, false, &def_float, &def_string, &def_string },
     71 	{ "+", "ADD_SF", 4, false, &def_string, &def_float, &def_string },
     72 	{ "+", "ADD_VS", 4, false, &def_vector, &def_string, &def_string },
     73 	{ "+", "ADD_SV", 4, false, &def_string, &def_vector, &def_string },
     74 	
     75 	{ "-", "SUB_F", 4, false, &def_float, &def_float, &def_float },
     76 	{ "-", "SUB_V", 4, false, &def_vector, &def_vector, &def_vector },
     77 	
     78 	{ "==", "EQ_F", 5, false, &def_float, &def_float, &def_float },
     79 	{ "==", "EQ_V", 5, false, &def_vector, &def_vector, &def_float },
     80 	{ "==", "EQ_S", 5, false, &def_string, &def_string, &def_float },
     81 	{ "==", "EQ_E", 5, false, &def_entity, &def_entity, &def_float },
     82 	{ "==", "EQ_EO", 5, false, &def_entity, &def_object, &def_float },
     83 	{ "==", "EQ_OE", 5, false, &def_object, &def_entity, &def_float },
     84 	{ "==", "EQ_OO", 5, false, &def_object, &def_object, &def_float },
     85 	
     86 	{ "!=", "NE_F", 5, false, &def_float, &def_float, &def_float },
     87 	{ "!=", "NE_V", 5, false, &def_vector, &def_vector, &def_float },
     88 	{ "!=", "NE_S", 5, false, &def_string, &def_string, &def_float },
     89     { "!=", "NE_E", 5, false, &def_entity, &def_entity, &def_float },
     90 	{ "!=", "NE_EO", 5, false, &def_entity, &def_object, &def_float },
     91 	{ "!=", "NE_OE", 5, false, &def_object, &def_entity, &def_float },
     92 	{ "!=", "NE_OO", 5, false, &def_object, &def_object, &def_float },
     93 	
     94 	{ "<=", "LE", 5, false, &def_float, &def_float, &def_float },
     95 	{ ">=", "GE", 5, false, &def_float, &def_float, &def_float },
     96 	{ "<", "LT", 5, false, &def_float, &def_float, &def_float },
     97 	{ ">", "GT", 5, false, &def_float, &def_float, &def_float },
     98 	
     99 	{ ".", "INDIRECT_F", 1, false, &def_object, &def_field, &def_float },
    100 	{ ".", "INDIRECT_V", 1, false, &def_object, &def_field, &def_vector },
    101 	{ ".", "INDIRECT_S", 1, false, &def_object, &def_field, &def_string },
    102 	{ ".", "INDIRECT_E", 1, false, &def_object, &def_field, &def_entity },
    103 	{ ".", "INDIRECT_BOOL", 1, false, &def_object, &def_field, &def_boolean },
    104 	{ ".", "INDIRECT_OBJ", 1, false, &def_object, &def_field, &def_object },
    105 
    106 	{ ".", "ADDRESS", 1, false, &def_entity, &def_field, &def_pointer },
    107 
    108 	{ ".", "EVENTCALL", 2, false, &def_entity, &def_function, &def_void },
    109 	{ ".", "OBJECTCALL", 2, false, &def_object, &def_function, &def_void },
    110 	{ ".", "SYSCALL", 2, false, &def_void, &def_function, &def_void },
    111 
    112 	{ "=", "STORE_F", 6, true, &def_float, &def_float, &def_float },
    113 	{ "=", "STORE_V", 6, true, &def_vector, &def_vector, &def_vector },
    114 	{ "=", "STORE_S", 6, true, &def_string, &def_string, &def_string },
    115 	{ "=", "STORE_ENT", 6, true, &def_entity, &def_entity, &def_entity },
    116 	{ "=", "STORE_BOOL", 6, true, &def_boolean, &def_boolean, &def_boolean },
    117 	{ "=", "STORE_OBJENT", 6, true, &def_object, &def_entity, &def_object },
    118 	{ "=", "STORE_OBJ", 6, true, &def_object, &def_object, &def_object },
    119 	{ "=", "STORE_OBJENT", 6, true, &def_entity, &def_object, &def_object },
    120 	
    121 	{ "=", "STORE_FTOS", 6, true, &def_string, &def_float, &def_string },
    122 	{ "=", "STORE_BTOS", 6, true, &def_string, &def_boolean, &def_string },
    123 	{ "=", "STORE_VTOS", 6, true, &def_string, &def_vector, &def_string },
    124 	{ "=", "STORE_FTOBOOL", 6, true, &def_boolean, &def_float, &def_boolean },
    125 	{ "=", "STORE_BOOLTOF", 6, true, &def_float, &def_boolean, &def_float },
    126 
    127 	{ "=", "STOREP_F", 6, true, &def_pointer, &def_float, &def_float },
    128 	{ "=", "STOREP_V", 6, true, &def_pointer, &def_vector, &def_vector },
    129 	{ "=", "STOREP_S", 6, true, &def_pointer, &def_string, &def_string },
    130 	{ "=", "STOREP_ENT", 6, true, &def_pointer, &def_entity, &def_entity },
    131 	{ "=", "STOREP_FLD", 6, true, &def_pointer, &def_field, &def_field },
    132 	{ "=", "STOREP_BOOL", 6, true, &def_pointer, &def_boolean, &def_boolean },
    133 	{ "=", "STOREP_OBJ", 6, true, &def_pointer, &def_object, &def_object },
    134 	{ "=", "STOREP_OBJENT", 6, true, &def_pointer, &def_object, &def_object },
    135 
    136 	{ "<=>", "STOREP_FTOS", 6, true, &def_pointer, &def_float, &def_string },
    137 	{ "<=>", "STOREP_BTOS", 6, true, &def_pointer, &def_boolean, &def_string },
    138 	{ "<=>", "STOREP_VTOS", 6, true, &def_pointer, &def_vector, &def_string },
    139 	{ "<=>", "STOREP_FTOBOOL", 6, true, &def_pointer, &def_float, &def_boolean },
    140 	{ "<=>", "STOREP_BOOLTOF", 6, true, &def_pointer, &def_boolean, &def_float },
    141 	
    142 	{ "*=", "UMUL_F", 6, true, &def_float, &def_float, &def_void },
    143 	{ "*=", "UMUL_V", 6, true, &def_vector, &def_float, &def_void },
    144 	{ "/=", "UDIV_F", 6, true, &def_float, &def_float, &def_void },
    145 	{ "/=", "UDIV_V", 6, true, &def_vector, &def_float, &def_void },
    146 	{ "%=", "UMOD_F", 6, true, &def_float, &def_float, &def_void },
    147 	{ "+=", "UADD_F", 6, true, &def_float, &def_float, &def_void },
    148 	{ "+=", "UADD_V", 6, true, &def_vector, &def_vector, &def_void },
    149 	{ "-=", "USUB_F", 6, true, &def_float, &def_float, &def_void },
    150 	{ "-=", "USUB_V", 6, true, &def_vector, &def_vector, &def_void },
    151 	{ "&=", "UAND_F", 6, true, &def_float, &def_float, &def_void },
    152 	{ "|=", "UOR_F", 6, true, &def_float, &def_float, &def_void },
    153 	
    154 	{ "!", "NOT_BOOL", -1, false, &def_boolean, &def_void, &def_float },
    155 	{ "!", "NOT_F", -1, false, &def_float, &def_void, &def_float },
    156 	{ "!", "NOT_V", -1, false, &def_vector, &def_void, &def_float },
    157 	{ "!", "NOT_S", -1, false, &def_vector, &def_void, &def_float },
    158 	{ "!", "NOT_ENT", -1, false, &def_entity, &def_void, &def_float },
    159 
    160 	{ "<NEG_F>", "NEG_F", -1, false, &def_float, &def_void, &def_float },
    161 	{ "<NEG_V>", "NEG_V", -1, false, &def_vector, &def_void, &def_vector },
    162 
    163 	{ "int", "INT_F", -1, false, &def_float, &def_void, &def_float },
    164 	
    165 	{ "<IF>", "IF", -1, false, &def_float, &def_jumpoffset, &def_void },
    166 	{ "<IFNOT>", "IFNOT", -1, false, &def_float, &def_jumpoffset, &def_void },
    167 	
    168 	// calls returns REG_RETURN
    169 	{ "<CALL>", "CALL", -1, false, &def_function, &def_argsize, &def_void },
    170 	{ "<THREAD>", "THREAD", -1, false, &def_function, &def_argsize, &def_void },
    171 	{ "<THREAD>", "OBJTHREAD", -1, false, &def_function, &def_argsize, &def_void },
    172 	
    173 	{ "<PUSH>", "PUSH_F", -1, false, &def_float, &def_float, &def_void },
    174 	{ "<PUSH>", "PUSH_V", -1, false, &def_vector, &def_vector, &def_void },
    175 	{ "<PUSH>", "PUSH_S", -1, false, &def_string, &def_string, &def_void },
    176 	{ "<PUSH>", "PUSH_ENT", -1, false, &def_entity, &def_entity, &def_void },
    177 	{ "<PUSH>", "PUSH_OBJ", -1, false, &def_object, &def_object, &def_void },
    178 	{ "<PUSH>", "PUSH_OBJENT", -1, false, &def_entity, &def_object, &def_void },
    179 	{ "<PUSH>", "PUSH_FTOS", -1, false, &def_string, &def_float, &def_void },
    180 	{ "<PUSH>", "PUSH_BTOF", -1, false, &def_float, &def_boolean, &def_void },
    181 	{ "<PUSH>", "PUSH_FTOB", -1, false, &def_boolean, &def_float, &def_void },
    182 	{ "<PUSH>", "PUSH_VTOS", -1, false, &def_string, &def_vector, &def_void },
    183 	{ "<PUSH>", "PUSH_BTOS", -1, false, &def_string, &def_boolean, &def_void },
    184 	
    185 	{ "<GOTO>", "GOTO", -1, false, &def_jumpoffset, &def_void, &def_void },
    186 	
    187 	{ "&&", "AND", 7, false, &def_float, &def_float, &def_float },
    188 	{ "&&", "AND_BOOLF", 7, false, &def_boolean, &def_float, &def_float },
    189 	{ "&&", "AND_FBOOL", 7, false, &def_float, &def_boolean, &def_float },
    190 	{ "&&", "AND_BOOLBOOL", 7, false, &def_boolean, &def_boolean, &def_float },
    191 	{ "||", "OR", 7, false, &def_float, &def_float, &def_float },
    192 	{ "||", "OR_BOOLF", 7, false, &def_boolean, &def_float, &def_float },
    193 	{ "||", "OR_FBOOL", 7, false, &def_float, &def_boolean, &def_float },
    194 	{ "||", "OR_BOOLBOOL", 7, false, &def_boolean, &def_boolean, &def_float },
    195 	
    196 	{ "&", "BITAND", 3, false, &def_float, &def_float, &def_float },
    197 	{ "|", "BITOR", 3, false, &def_float, &def_float, &def_float },
    198 
    199 	{ "<BREAK>", "BREAK", -1, false, &def_float, &def_void, &def_void },
    200 	{ "<CONTINUE>", "CONTINUE", -1, false, &def_float, &def_void, &def_void },
    201 
    202 	{ NULL }
    203 };
    204 
    205 /*
    206 ================
    207 idCompiler::idCompiler()
    208 ================
    209 */
    210 idCompiler::idCompiler() {
    211 	char	**ptr;
    212 	int		id;
    213 
    214 	// make sure we have the right # of opcodes in the table
    215 	assert( ( sizeof( opcodes ) / sizeof( opcodes[ 0 ] ) ) == ( NUM_OPCODES + 1 ) );
    216 
    217 	parserPtr = &parser;
    218 
    219 	callthread			= false;
    220 	loopDepth			= 0;
    221 	eof					= false;
    222 	braceDepth			= 0;
    223 	immediateType		= NULL;
    224 	basetype			= NULL;
    225 	currentLineNumber	= 0;
    226 	currentFileNumber	= 0;
    227 	errorCount			= 0;
    228 	console				= false;
    229 	scope				= &def_namespace;
    230 
    231 	memset( &immediate, 0, sizeof( immediate ) );
    232 	memset( punctuationValid, 0, sizeof( punctuationValid ) );
    233 	for( ptr = punctuation; *ptr != NULL; ptr++ ) {
    234 		id = parserPtr->GetPunctuationId( *ptr );
    235 		if ( ( id >= 0 ) && ( id < 256 ) ) {
    236 			punctuationValid[ id ] = true;
    237 		}
    238 	}
    239 }
    240 
    241 /*
    242 ============
    243 idCompiler::Error
    244 
    245 Aborts the current file load
    246 ============
    247 */
    248 void idCompiler::Error( const char *message, ... ) const {
    249 	va_list	argptr;
    250 	char	string[ 1024 ];
    251 
    252 	va_start( argptr, message );
    253 	vsprintf( string, message, argptr );
    254 	va_end( argptr );
    255 
    256 	throw idCompileError( string );
    257 }
    258 
    259 /*
    260 ============
    261 idCompiler::Warning
    262 
    263 Prints a warning about the current line
    264 ============
    265 */
    266 void idCompiler::Warning( const char *message, ... ) const {
    267 	va_list	argptr;
    268 	char	string[ 1024 ];
    269 
    270 	va_start( argptr, message );
    271 	vsprintf( string, message, argptr );
    272 	va_end( argptr );
    273 
    274 	parserPtr->Warning( "%s", string );
    275 }
    276 
    277 /*
    278 ============
    279 idCompiler::VirtualFunctionConstant
    280 
    281 Creates a def for an index into a virtual function table
    282 ============
    283 */
    284 ID_INLINE idVarDef *idCompiler::VirtualFunctionConstant( idVarDef *func ) {
    285 	eval_t eval;
    286 
    287 	memset( &eval, 0, sizeof( eval ) );
    288 	eval._int = func->scope->TypeDef()->GetFunctionNumber( func->value.functionPtr );
    289 	if ( eval._int < 0 ) {
    290 		Error( "Function '%s' not found in scope '%s'", func->Name(), func->scope->Name() );
    291 	}
    292     
    293 	return GetImmediate( &type_virtualfunction, &eval, "" );
    294 }
    295 
    296 /*
    297 ============
    298 idCompiler::SizeConstant
    299 
    300 Creates a def for a size constant
    301 ============
    302 */
    303 ID_INLINE idVarDef *idCompiler::SizeConstant( int size ) {
    304 	eval_t eval;
    305 
    306 	memset( &eval, 0, sizeof( eval ) );
    307 	eval._int = size;
    308 	return GetImmediate( &type_argsize, &eval, "" );
    309 }
    310 
    311 /*
    312 ============
    313 idCompiler::JumpConstant
    314 
    315 Creates a def for a jump constant
    316 ============
    317 */
    318 ID_INLINE idVarDef *idCompiler::JumpConstant( int value ) {
    319 	eval_t eval;
    320 
    321 	memset( &eval, 0, sizeof( eval ) );
    322 	eval._int = value;
    323 	return GetImmediate( &type_jumpoffset, &eval, "" );
    324 }
    325 
    326 /*
    327 ============
    328 idCompiler::JumpDef
    329 
    330 Creates a def for a relative jump from one code location to another
    331 ============
    332 */
    333 ID_INLINE idVarDef *idCompiler::JumpDef( int jumpfrom, int jumpto ) {
    334 	return JumpConstant( jumpto - jumpfrom );
    335 }
    336 
    337 /*
    338 ============
    339 idCompiler::JumpTo
    340 
    341 Creates a def for a relative jump from current code location
    342 ============
    343 */
    344 ID_INLINE idVarDef *idCompiler::JumpTo( int jumpto ) {
    345 	return JumpDef( gameLocal.program.NumStatements(), jumpto );
    346 }
    347 
    348 /*
    349 ============
    350 idCompiler::JumpFrom
    351 
    352 Creates a def for a relative jump from code location to current code location
    353 ============
    354 */
    355 ID_INLINE idVarDef *idCompiler::JumpFrom( int jumpfrom ) {
    356 	return JumpDef( jumpfrom, gameLocal.program.NumStatements() );
    357 }
    358 
    359 /*
    360 ============
    361 idCompiler::Divide
    362 ============
    363 */
    364 ID_INLINE float idCompiler::Divide( float numerator, float denominator ) {
    365 	if ( denominator == 0 ) {
    366 		Error( "Divide by zero" );
    367 	}
    368 
    369 	return numerator / denominator;
    370 }
    371 
    372 /*
    373 ============
    374 idCompiler::FindImmediate
    375 
    376 tries to find an existing immediate with the same value
    377 ============
    378 */
    379 idVarDef *idCompiler::FindImmediate( const idTypeDef *type, const eval_t *eval, const char *string ) const {
    380 	idVarDef	*def;
    381 	etype_t		etype;
    382 
    383 	etype = type->Type();
    384 
    385 	// check for a constant with the same value
    386 	for( def = gameLocal.program.GetDefList( "<IMMEDIATE>" ); def != NULL; def = def->Next() ) {
    387 		if ( def->TypeDef() != type ) {
    388 			continue;
    389 		}
    390 
    391 		switch( etype ) {
    392 		case ev_field :
    393 			if ( *def->value.intPtr == eval->_int ) {
    394 				return def;
    395 			}
    396 			break;
    397 
    398 		case ev_argsize :
    399 			if ( def->value.argSize == eval->_int ) {
    400 				return def;
    401 			}
    402 			break;
    403 
    404 		case ev_jumpoffset :
    405 			if ( def->value.jumpOffset == eval->_int ) {
    406 				return def;
    407 			}
    408 			break;
    409 
    410 		case ev_entity :
    411 			if ( *def->value.intPtr == eval->entity ) {
    412 				return def;
    413 			}
    414 			break;
    415 
    416 		case ev_string :
    417 			if ( idStr::Cmp( def->value.stringPtr, string ) == 0 ) {
    418 				return def;
    419 			}
    420 			break;
    421 
    422 		case ev_float :
    423 			if ( *def->value.floatPtr == eval->_float ) {
    424 				return def;
    425 			}
    426 			break;
    427 
    428 		case ev_virtualfunction :
    429 			if ( def->value.virtualFunction == eval->_int ) {
    430 				return def;
    431 			}
    432 			break;
    433 
    434 
    435 		case ev_vector :
    436 			if ( ( def->value.vectorPtr->x == eval->vector[ 0 ] ) && 
    437 				( def->value.vectorPtr->y == eval->vector[ 1 ] ) && 
    438 				( def->value.vectorPtr->z == eval->vector[ 2 ] ) ) {
    439 				return def;
    440 			}
    441 			break;
    442 
    443 		default :
    444 			Error( "weird immediate type" );
    445 			break;
    446 		}
    447 	}
    448 
    449 	return NULL;
    450 }
    451 
    452 /*
    453 ============
    454 idCompiler::GetImmediate
    455 
    456 returns an existing immediate with the same value, or allocates a new one
    457 ============
    458 */
    459 idVarDef *idCompiler::GetImmediate( idTypeDef *type, const eval_t *eval, const char *string ) {
    460 	idVarDef *def;
    461 
    462 	def = FindImmediate( type, eval, string );
    463 	if ( def ) {
    464 		def->numUsers++;
    465 	} else {
    466 		// allocate a new def
    467 		def = gameLocal.program.AllocDef( type, "<IMMEDIATE>", &def_namespace, true );
    468 		if ( type->Type() == ev_string ) {
    469 			def->SetString( string, true );
    470 		} else {
    471 			def->SetValue( *eval, true );
    472 		}
    473 	}
    474 
    475 	return def;
    476 }
    477 
    478 /*
    479 ============
    480 idCompiler::OptimizeOpcode
    481 
    482 try to optimize when the operator works on constants only
    483 ============
    484 */
    485 idVarDef *idCompiler::OptimizeOpcode( const opcode_t *op, idVarDef *var_a, idVarDef *var_b ) {
    486 	eval_t		c;
    487 	idTypeDef	*type;
    488 
    489 	if ( var_a == NULL || var_a->initialized != idVarDef::initializedConstant ) {
    490 		return NULL;
    491 	}
    492 	if ( var_b == NULL || var_b->initialized != idVarDef::initializedConstant ) {
    493 		return NULL;
    494 	}
    495 
    496 	idVec3 &vec_c = *reinterpret_cast<idVec3 *>( &c.vector[ 0 ] );
    497 
    498 	memset( &c, 0, sizeof( c ) );
    499 	switch( op - opcodes ) {
    500 		case OP_ADD_F:		c._float = *var_a->value.floatPtr + *var_b->value.floatPtr; type = &type_float; break;
    501 		case OP_ADD_V:		vec_c = *var_a->value.vectorPtr + *var_b->value.vectorPtr; type = &type_vector; break;
    502 		case OP_SUB_F:		c._float = *var_a->value.floatPtr - *var_b->value.floatPtr; type = &type_float; break;
    503 		case OP_SUB_V:		vec_c = *var_a->value.vectorPtr - *var_b->value.vectorPtr; type = &type_vector; break;
    504 		case OP_MUL_F:		c._float = *var_a->value.floatPtr * *var_b->value.floatPtr; type = &type_float; break;
    505 		case OP_MUL_V:		c._float = *var_a->value.vectorPtr * *var_b->value.vectorPtr; type = &type_float; break;
    506 		case OP_MUL_FV:		vec_c = *var_b->value.vectorPtr * *var_a->value.floatPtr; type = &type_vector; break;
    507 		case OP_MUL_VF:		vec_c = *var_a->value.vectorPtr * *var_b->value.floatPtr; type = &type_vector; break;
    508 		case OP_DIV_F:		c._float = Divide( *var_a->value.floatPtr, *var_b->value.floatPtr ); type = &type_float; break;
    509 		case OP_MOD_F:		c._float = (int)*var_a->value.floatPtr % (int)*var_b->value.floatPtr; type = &type_float; break;
    510 		case OP_BITAND:		c._float = ( int )*var_a->value.floatPtr & ( int )*var_b->value.floatPtr; type = &type_float; break;
    511 		case OP_BITOR:		c._float = ( int )*var_a->value.floatPtr | ( int )*var_b->value.floatPtr; type = &type_float; break;
    512 		case OP_GE:			c._float = *var_a->value.floatPtr >= *var_b->value.floatPtr; type = &type_float; break;
    513 		case OP_LE:			c._float = *var_a->value.floatPtr <= *var_b->value.floatPtr; type = &type_float; break;
    514 		case OP_GT:			c._float = *var_a->value.floatPtr > *var_b->value.floatPtr; type = &type_float; break;
    515 		case OP_LT:			c._float = *var_a->value.floatPtr < *var_b->value.floatPtr; type = &type_float; break;
    516 		case OP_AND:		c._float = *var_a->value.floatPtr && *var_b->value.floatPtr; type = &type_float; break;
    517 		case OP_OR:			c._float = *var_a->value.floatPtr || *var_b->value.floatPtr; type = &type_float; break;
    518 		case OP_NOT_BOOL:	c._int = !*var_a->value.intPtr; type = &type_boolean; break;
    519 		case OP_NOT_F:		c._float = !*var_a->value.floatPtr; type = &type_float; break;
    520 		case OP_NOT_V:		c._float = !var_a->value.vectorPtr->x && !var_a->value.vectorPtr->y && !var_a->value.vectorPtr->z; type = &type_float; break;
    521 		case OP_NEG_F:		c._float = -*var_a->value.floatPtr; type = &type_float; break;
    522 		case OP_NEG_V:		vec_c = -*var_a->value.vectorPtr; type = &type_vector; break;
    523 		case OP_INT_F:		c._float = ( int )*var_a->value.floatPtr; type = &type_float; break;
    524 		case OP_EQ_F:		c._float = ( *var_a->value.floatPtr == *var_b->value.floatPtr ); type = &type_float; break;
    525 		case OP_EQ_V:		c._float = var_a->value.vectorPtr->Compare( *var_b->value.vectorPtr ); type = &type_float; break;
    526 		case OP_EQ_E:		c._float = ( *var_a->value.intPtr == *var_b->value.intPtr ); type = &type_float; break;
    527 		case OP_NE_F:		c._float = ( *var_a->value.floatPtr != *var_b->value.floatPtr ); type = &type_float; break;
    528 		case OP_NE_V:		c._float = !var_a->value.vectorPtr->Compare( *var_b->value.vectorPtr ); type = &type_float; break;
    529 		case OP_NE_E:		c._float = ( *var_a->value.intPtr != *var_b->value.intPtr ); type = &type_float; break;
    530 		case OP_UADD_F:		c._float = *var_b->value.floatPtr + *var_a->value.floatPtr; type = &type_float; break;
    531 		case OP_USUB_F:		c._float = *var_b->value.floatPtr - *var_a->value.floatPtr; type = &type_float; break;
    532 		case OP_UMUL_F:		c._float = *var_b->value.floatPtr * *var_a->value.floatPtr; type = &type_float; break;
    533 		case OP_UDIV_F:		c._float = Divide( *var_b->value.floatPtr, *var_a->value.floatPtr ); type = &type_float; break;
    534 		case OP_UMOD_F:		c._float = ( int ) *var_b->value.floatPtr % ( int )*var_a->value.floatPtr; type = &type_float; break;
    535 		case OP_UOR_F:		c._float = ( int )*var_b->value.floatPtr | ( int )*var_a->value.floatPtr; type = &type_float; break;
    536 		case OP_UAND_F: 	c._float = ( int )*var_b->value.floatPtr & ( int )*var_a->value.floatPtr; type = &type_float; break;
    537 		case OP_UINC_F:		c._float = *var_a->value.floatPtr + 1; type = &type_float; break;
    538 		case OP_UDEC_F:		c._float = *var_a->value.floatPtr - 1; type = &type_float; break;
    539 		case OP_COMP_F:		c._float = ( float )~( int )*var_a->value.floatPtr; type = &type_float; break;
    540 		default:			type = NULL; break;
    541 	}
    542 
    543 	if ( !type ) {
    544 		return NULL;
    545 	}
    546 
    547 	if ( var_a ) {
    548 		var_a->numUsers--;
    549 		if ( var_a->numUsers <= 0 ) {
    550 			gameLocal.program.FreeDef( var_a, NULL );
    551 		}
    552 	}
    553 	if ( var_b ) {
    554 		var_b->numUsers--;
    555 		if ( var_b->numUsers <= 0 ) {
    556 			gameLocal.program.FreeDef( var_b, NULL );
    557 		}
    558 	}
    559 
    560 	return GetImmediate( type, &c, "" );
    561 }
    562 
    563 /*
    564 ============
    565 idCompiler::EmitOpcode
    566 
    567 Emits a primitive statement, returning the var it places it's value in
    568 ============
    569 */
    570 idVarDef *idCompiler::EmitOpcode( const opcode_t *op, idVarDef *var_a, idVarDef *var_b ) {
    571 	statement_t	*statement;
    572 	idVarDef	*var_c;
    573 
    574 	var_c = OptimizeOpcode( op, var_a, var_b );
    575 	if ( var_c ) {
    576 		return var_c;
    577 	}
    578 
    579 	if ( var_a && !strcmp( var_a->Name(), RESULT_STRING ) ) {
    580 		var_a->numUsers++;
    581 	}
    582 	if ( var_b && !strcmp( var_b->Name(), RESULT_STRING ) ) {
    583 		var_b->numUsers++;
    584 	}
    585 	
    586 	statement = gameLocal.program.AllocStatement();
    587 	statement->linenumber	= currentLineNumber;
    588 	statement->file 		= currentFileNumber;
    589 	
    590 	if ( ( op->type_c == &def_void ) || op->rightAssociative ) {
    591 		// ifs, gotos, and assignments don't need vars allocated
    592 		var_c = NULL;
    593 	} else {
    594 		// allocate result space
    595 		// try to reuse result defs as much as possible
    596 		var_c = gameLocal.program.FindFreeResultDef( op->type_c->TypeDef(), RESULT_STRING, scope, var_a, var_b );
    597 		// set user count back to 1, a result def needs to be used twice before it can be reused
    598 		var_c->numUsers = 1;
    599 	}
    600 
    601 	statement->op	= op - opcodes;
    602 	statement->a	= var_a;
    603 	statement->b	= var_b;
    604 	statement->c	= var_c;
    605 
    606 	if ( op->rightAssociative ) {
    607 		return var_a;
    608 	}
    609 
    610 	return var_c;
    611 }
    612 
    613 /*
    614 ============
    615 idCompiler::EmitOpcode
    616 
    617 Emits a primitive statement, returning the var it places it's value in
    618 ============
    619 */
    620 ID_INLINE idVarDef *idCompiler::EmitOpcode( int op, idVarDef *var_a, idVarDef *var_b ) {
    621 	return EmitOpcode( &opcodes[ op ], var_a, var_b );
    622 }
    623 
    624 /*
    625 ============
    626 idCompiler::EmitPush
    627 
    628 Emits an opcode to push the variable onto the stack.
    629 ============
    630 */
    631 bool idCompiler::EmitPush( idVarDef *expression, const idTypeDef *funcArg ) {
    632 	opcode_t *op;
    633 	opcode_t *out;
    634 
    635 	out = NULL;
    636 	for( op = &opcodes[ OP_PUSH_F ]; op->name && !strcmp( op->name, "<PUSH>" ); op++ ) {
    637 		if ( ( funcArg->Type() == op->type_a->Type() ) && ( expression->Type() == op->type_b->Type() ) ) {
    638 			out = op;
    639 			break;
    640 		}
    641 	}
    642 
    643 	if ( !out ) {
    644 		if ( ( expression->TypeDef() != funcArg ) && !expression->TypeDef()->Inherits( funcArg ) ) {
    645 			return false;
    646 		}
    647 
    648 		out = &opcodes[ OP_PUSH_ENT ];
    649 	}
    650 
    651 	EmitOpcode( out, expression, 0 );
    652 
    653 	return true;
    654 }
    655 
    656 /*
    657 ==============
    658 idCompiler::NextToken
    659 
    660 Sets token, immediateType, and possibly immediate
    661 ==============
    662 */
    663 void idCompiler::NextToken() {
    664 	int i;
    665 
    666 	// reset our type
    667 	immediateType = NULL;
    668 	memset( &immediate, 0, sizeof( immediate ) );
    669 
    670 	// Save the token's line number and filename since when we emit opcodes the current 
    671 	// token is always the next one to be read 
    672 	currentLineNumber = token.line;
    673 	currentFileNumber = gameLocal.program.GetFilenum( parserPtr->GetFileName() );
    674 
    675 	if ( !parserPtr->ReadToken( &token ) ) {
    676 		eof = true;
    677 		return;
    678 	}
    679 
    680 	if ( currentFileNumber != gameLocal.program.GetFilenum( parserPtr->GetFileName() ) ) {
    681 		if ( ( braceDepth > 0 ) && ( token != "}" ) ) {
    682 			// missing a closing brace.  try to give as much info as possible.
    683 			if ( scope->Type() == ev_function ) {
    684 				Error( "Unexpected end of file inside function '%s'.  Missing closing braces.", scope->Name() );
    685 			} else if ( scope->Type() == ev_object ) {
    686 				Error( "Unexpected end of file inside object '%s'.  Missing closing braces.", scope->Name() );
    687 			} else if ( scope->Type() == ev_namespace ) {
    688 				Error( "Unexpected end of file inside namespace '%s'.  Missing closing braces.", scope->Name() );
    689 			} else {
    690 				Error( "Unexpected end of file inside braced section" );
    691 			}
    692 		}
    693 	}
    694 
    695 	switch( token.type ) {
    696 	case TT_STRING:
    697 		// handle quoted strings as a unit
    698 		immediateType = &type_string;
    699 		return;
    700 
    701 	case TT_LITERAL: {
    702 		// handle quoted vectors as a unit
    703 		immediateType = &type_vector;
    704 		idLexer lex( token, token.Length(), parserPtr->GetFileName(), LEXFL_NOERRORS );
    705 		idToken token2;
    706 		for( i = 0; i < 3; i++ ) {
    707 			if ( !lex.ReadToken( &token2 ) ) {
    708 				Error( "Couldn't read vector. '%s' is not in the form of 'x y z'", token.c_str() );
    709 			}
    710 			if ( token2.type == TT_PUNCTUATION && token2 == "-" ) {
    711 				if ( !lex.CheckTokenType( TT_NUMBER, 0, &token2 ) ) {
    712 					Error( "expected a number following '-' but found '%s' in vector '%s'", token2.c_str(), token.c_str() );
    713 				}
    714 				immediate.vector[ i ] = -token2.GetFloatValue();
    715 			} else if ( token2.type == TT_NUMBER ) {
    716 				immediate.vector[ i ] = token2.GetFloatValue();
    717 			} else {
    718 				Error( "vector '%s' is not in the form of 'x y z'.  expected float value, found '%s'", token.c_str(), token2.c_str() );
    719 			}
    720 		}
    721 		return;
    722 	}
    723 
    724 	case TT_NUMBER:
    725 		immediateType = &type_float;
    726 		immediate._float = token.GetFloatValue();
    727 		return;
    728 
    729 	case TT_PUNCTUATION:
    730 		// entity names
    731 		if ( token == "$" ) {
    732 			immediateType = &type_entity;
    733 			parserPtr->ReadToken( &token );
    734 			return;
    735 		}
    736 
    737 		if ( token == "{" ) {
    738 			braceDepth++;
    739 			return;
    740 		}
    741 
    742 		if ( token == "}" ) {
    743 			braceDepth--;
    744 			return;
    745 		}
    746 
    747 		if ( punctuationValid[ token.subtype ] ) {
    748 			return;
    749 		}
    750 
    751 		Error( "Unknown punctuation '%s'", token.c_str() );
    752 		break;
    753 
    754 	case TT_NAME:
    755 		return;
    756 
    757 	default:
    758 		Error( "Unknown token '%s'", token.c_str() );
    759 	}
    760 }
    761 
    762 /*
    763 =============
    764 idCompiler::ExpectToken
    765 
    766 Issues an Error if the current token isn't equal to string
    767 Gets the next token
    768 =============
    769 */
    770 void idCompiler::ExpectToken( const char *string ) {
    771 	if ( token != string ) {
    772 		Error( "expected '%s', found '%s'", string, token.c_str() );
    773 	}
    774 
    775 	NextToken();
    776 }
    777 
    778 /*
    779 =============
    780 idCompiler::CheckToken
    781 
    782 Returns true and gets the next token if the current token equals string
    783 Returns false and does nothing otherwise
    784 =============
    785 */
    786 bool idCompiler::CheckToken( const char *string ) {
    787 	if ( token != string ) {
    788 		return false;
    789 	}
    790 		
    791 	NextToken();
    792 	
    793 	return true;
    794 }
    795 
    796 /*
    797 ============
    798 idCompiler::ParseName
    799 
    800 Checks to see if the current token is a valid name
    801 ============
    802 */
    803 void idCompiler::ParseName( idStr &name ) {
    804 	if ( token.type != TT_NAME ) {
    805 		Error( "'%s' is not a name", token.c_str() );
    806 	}
    807 
    808 	name = token;
    809 	NextToken();
    810 }
    811 
    812 /*
    813 ============
    814 idCompiler::SkipOutOfFunction
    815 
    816 For error recovery, pops out of nested braces
    817 ============
    818 */
    819 void idCompiler::SkipOutOfFunction() {
    820 	while( braceDepth ) {
    821 		parserPtr->SkipBracedSection( false );
    822 		braceDepth--;
    823 	}
    824 	NextToken();
    825 }
    826 
    827 /*
    828 ============
    829 idCompiler::SkipToSemicolon
    830 
    831 For error recovery
    832 ============
    833 */
    834 void idCompiler::SkipToSemicolon() {
    835 	do {
    836 		if ( CheckToken( ";" ) ) {
    837 			return;
    838 		}
    839 
    840 		NextToken();
    841 	} while( !eof );
    842 }
    843 
    844 /*
    845 ============
    846 idCompiler::CheckType
    847 
    848 Parses a variable type, including functions types
    849 ============
    850 */
    851 idTypeDef *idCompiler::CheckType() {
    852 	idTypeDef *type;
    853 	
    854 	if ( token == "float" ) {
    855 		type = &type_float;
    856 	} else if ( token == "vector" ) {
    857 		type = &type_vector;
    858 	} else if ( token == "entity" ) {
    859 		type = &type_entity;
    860 	} else if ( token == "string" ) {
    861 		type = &type_string;
    862 	} else if ( token == "void" ) {
    863 		type = &type_void;
    864 	} else if ( token == "object" ) {
    865 		type = &type_object;
    866 	} else if ( token == "boolean" ) {
    867 		type = &type_boolean;
    868 	} else if ( token == "namespace" ) {
    869 		type = &type_namespace;
    870 	} else if ( token == "scriptEvent" ) {
    871 		type = &type_scriptevent;
    872 	} else {
    873 		type = gameLocal.program.FindType( token.c_str() );
    874 		if ( type != NULL && !type->Inherits( &type_object ) ) {
    875 			type = NULL;
    876 		}
    877 	}
    878 	
    879 	return type;
    880 }
    881 
    882 /*
    883 ============
    884 idCompiler::ParseType
    885 
    886 Parses a variable type, including functions types
    887 ============
    888 */
    889 idTypeDef *idCompiler::ParseType() {
    890 	idTypeDef *type;
    891 	
    892 	type = CheckType();
    893 	if ( !type ) {
    894 		Error( "\"%s\" is not a type", token.c_str() );
    895 	}
    896 
    897 	if ( ( type == &type_scriptevent ) && ( scope != &def_namespace ) ) {
    898 		Error( "scriptEvents can only defined in the global namespace" );
    899 	}
    900 
    901 	if ( ( type == &type_namespace ) && ( scope->Type() != ev_namespace ) ) {
    902 		Error( "A namespace may only be defined globally, or within another namespace" );
    903 	}
    904 
    905 	NextToken();
    906 	
    907 	return type;
    908 }
    909 
    910 /*
    911 ============
    912 idCompiler::ParseImmediate
    913 
    914 Looks for a preexisting constant
    915 ============
    916 */
    917 idVarDef *idCompiler::ParseImmediate() {
    918 	idVarDef *def;
    919 
    920 	def = GetImmediate( immediateType, &immediate, token.c_str() );
    921 	NextToken();
    922 
    923 	return def;
    924 }
    925 
    926 /*
    927 ============
    928 idCompiler::EmitFunctionParms
    929 ============
    930 */
    931 idVarDef *idCompiler::EmitFunctionParms( int op, idVarDef *func, int startarg, int startsize, idVarDef *object ) {
    932 	idVarDef		*e;
    933 	const idTypeDef	*type;
    934 	const idTypeDef	*funcArg;
    935 	idVarDef		*returnDef;
    936 	idTypeDef		*returnType;
    937 	int 			arg;
    938 	int 			size;
    939 	int				resultOp;
    940 
    941 	type = func->TypeDef();
    942 	if ( func->Type() != ev_function ) {
    943 		Error( "'%s' is not a function", func->Name() );
    944 	}
    945 
    946 	// copy the parameters to the global parameter variables
    947 	arg = startarg;
    948 	size = startsize;
    949 	if ( !CheckToken( ")" ) ) {
    950 		do {
    951 			if ( arg >= type->NumParameters() ) {
    952 				Error( "too many parameters" );
    953 			}
    954 
    955 			e = GetExpression( TOP_PRIORITY );
    956 
    957 			funcArg = type->GetParmType( arg );
    958 			if ( !EmitPush( e, funcArg ) ) {
    959 				Error( "type mismatch on parm %i of call to '%s'", arg + 1, func->Name() );
    960 			}
    961 
    962 			if ( funcArg->Type() == ev_object ) {
    963 				size += type_object.Size();
    964 			} else {
    965 				size += funcArg->Size();
    966 			}
    967 
    968 			arg++;
    969 		} while( CheckToken( "," ) );
    970 	
    971 		ExpectToken( ")" );
    972 	}
    973 
    974 	if ( arg < type->NumParameters() ) {
    975 		Error( "too few parameters for function '%s'", func->Name() );
    976 	}
    977 
    978 	if ( op == OP_CALL ) {
    979 		EmitOpcode( op, func, 0 );
    980 	} else if ( ( op == OP_OBJECTCALL ) || ( op == OP_OBJTHREAD ) ) {
    981 		EmitOpcode( op, object, VirtualFunctionConstant( func ) );
    982 
    983 		// need arg size seperate since script object may be NULL
    984 		statement_t &statement = gameLocal.program.GetStatement( gameLocal.program.NumStatements() - 1 );
    985 		statement.c = SizeConstant( func->value.functionPtr->parmTotal );
    986 	} else {
    987 		EmitOpcode( op, func, SizeConstant( size ) );
    988 	}
    989 
    990 	// we need to copy off the result into a temporary result location, so figure out the opcode
    991 	returnType = type->ReturnType();
    992 	if ( returnType->Type() == ev_string ) {
    993 		resultOp = OP_STORE_S;
    994 		returnDef = gameLocal.program.returnStringDef;
    995 	} else {
    996 		gameLocal.program.returnDef->SetTypeDef( returnType );
    997 		returnDef = gameLocal.program.returnDef;
    998 
    999 		switch( returnType->Type() ) {
   1000 		case ev_void :
   1001 			resultOp = OP_STORE_F;
   1002 			break;
   1003 
   1004 		case ev_boolean :
   1005 			resultOp = OP_STORE_BOOL;
   1006 			break;
   1007 
   1008 		case ev_float :
   1009 			resultOp = OP_STORE_F;
   1010 			break;
   1011 
   1012 		case ev_vector :
   1013 			resultOp = OP_STORE_V;
   1014 			break;
   1015 
   1016 		case ev_entity :
   1017 			resultOp = OP_STORE_ENT;
   1018 			break;
   1019 
   1020 		case ev_object :
   1021 			resultOp = OP_STORE_OBJ;
   1022 			break;
   1023 
   1024 		default :
   1025 			// shut up compiler
   1026 			resultOp = OP_STORE_OBJ;
   1027 			Error( "Invalid return type for function '%s'", func->Name() );
   1028 		}
   1029 	}
   1030 
   1031 	if ( returnType->Type() == ev_void ) {
   1032 		// don't need result space since there's no result, so just return the normal result def.
   1033 		return returnDef;
   1034 	}
   1035 
   1036 	// allocate result space
   1037 	// try to reuse result defs as much as possible
   1038 	statement_t &statement = gameLocal.program.GetStatement( gameLocal.program.NumStatements() - 1 );
   1039 	idVarDef *resultDef = gameLocal.program.FindFreeResultDef( returnType, RESULT_STRING, scope, statement.a, statement.b );
   1040 	// set user count back to 0, a result def needs to be used twice before it can be reused
   1041 	resultDef->numUsers = 0;
   1042 
   1043 	EmitOpcode( resultOp, returnDef, resultDef );
   1044 
   1045 	return resultDef;
   1046 }
   1047 
   1048 /*
   1049 ============
   1050 idCompiler::ParseFunctionCall
   1051 ============
   1052 */
   1053 idVarDef *idCompiler::ParseFunctionCall( idVarDef *funcDef ) {
   1054 	assert( funcDef );
   1055 
   1056 	if ( funcDef->Type() != ev_function ) {
   1057 		Error( "'%s' is not a function", funcDef->Name() );
   1058 	}
   1059 
   1060 	if ( funcDef->initialized == idVarDef::uninitialized ) {
   1061 		Error( "Function '%s' has not been defined yet", funcDef->GlobalName() );
   1062 	}
   1063 
   1064 	assert( funcDef->value.functionPtr );
   1065 	if ( callthread ) {
   1066 		if ( ( funcDef->initialized != idVarDef::uninitialized ) && funcDef->value.functionPtr->eventdef ) {
   1067 			Error( "Built-in functions cannot be called as threads" );
   1068 		}
   1069 		callthread = false;
   1070 		return EmitFunctionParms( OP_THREAD, funcDef, 0, 0, NULL );
   1071 	} else {
   1072 		if ( ( funcDef->initialized != idVarDef::uninitialized ) && funcDef->value.functionPtr->eventdef ) {
   1073 			if ( ( scope->Type() != ev_namespace ) && ( scope->scope->Type() == ev_object ) ) {
   1074 				// get the local object pointer
   1075 				idVarDef *thisdef = gameLocal.program.GetDef( scope->scope->TypeDef(), "self", scope );
   1076 				if ( !thisdef ) {
   1077 					Error( "No 'self' within scope" );
   1078 				}
   1079 
   1080 				return ParseEventCall( thisdef, funcDef );
   1081 			} else {
   1082 				Error( "Built-in functions cannot be called without an object" );
   1083 			}
   1084 		}
   1085 
   1086 		return EmitFunctionParms( OP_CALL, funcDef, 0, 0, NULL );
   1087 	}
   1088 }
   1089 
   1090 /*
   1091 ============
   1092 idCompiler::ParseObjectCall
   1093 ============
   1094 */
   1095 idVarDef *idCompiler::ParseObjectCall( idVarDef *object, idVarDef *func ) {
   1096 	EmitPush( object, object->TypeDef() );
   1097 	if ( callthread ) {
   1098 		callthread = false;
   1099 		return EmitFunctionParms( OP_OBJTHREAD, func, 1, type_object.Size(), object );
   1100 	} else {
   1101 		return EmitFunctionParms( OP_OBJECTCALL, func, 1, 0, object );
   1102 	}
   1103 }
   1104 
   1105 /*
   1106 ============
   1107 idCompiler::ParseEventCall
   1108 ============
   1109 */
   1110 idVarDef *idCompiler::ParseEventCall( idVarDef *object, idVarDef *funcDef ) {
   1111 	if ( callthread ) {
   1112 		Error( "Cannot call built-in functions as a thread" );
   1113 	}
   1114 
   1115 	if ( funcDef->Type() != ev_function ) {
   1116 		Error( "'%s' is not a function", funcDef->Name() );
   1117 	}
   1118 
   1119 	if ( !funcDef->value.functionPtr->eventdef ) {
   1120 		Error( "\"%s\" cannot be called with object notation", funcDef->Name() );
   1121 	}
   1122 
   1123 	if ( object->Type() == ev_object ) {
   1124 		EmitPush( object, &type_entity );
   1125 	} else {
   1126 		EmitPush( object, object->TypeDef() );
   1127 	}
   1128 
   1129 	return EmitFunctionParms( OP_EVENTCALL, funcDef, 0, type_object.Size(), NULL );
   1130 }
   1131 
   1132 /*
   1133 ============
   1134 idCompiler::ParseSysObjectCall
   1135 ============
   1136 */
   1137 idVarDef *idCompiler::ParseSysObjectCall( idVarDef *funcDef ) {
   1138 	if ( callthread ) {
   1139 		Error( "Cannot call built-in functions as a thread" );
   1140 	}
   1141 
   1142 	if ( funcDef->Type() != ev_function ) {
   1143 		Error( "'%s' is not a function", funcDef->Name() );
   1144 	}
   1145 
   1146 	if ( funcDef->value.functionPtr->eventdef == NULL ) {
   1147 		Error( "\"%s\" cannot be called with object notation", funcDef->Name() );
   1148 	}
   1149 
   1150 	assert( funcDef->value.functionPtr->eventdef != NULL ); // to remove stupid analyze warning
   1151 	if ( !idThread::Type.RespondsTo( *funcDef->value.functionPtr->eventdef ) ) {
   1152 		Error( "\"%s\" is not callable as a 'sys' function", funcDef->Name() );
   1153 	}
   1154 
   1155 	return EmitFunctionParms( OP_SYSCALL, funcDef, 0, 0, NULL );
   1156 }
   1157 
   1158 /*
   1159 ============
   1160 idCompiler::LookupDef
   1161 ============
   1162 */
   1163 idVarDef *idCompiler::LookupDef( const char *name, const idVarDef *baseobj ) {
   1164 	idVarDef	*def;
   1165 	idVarDef	*field;
   1166 	etype_t		type_b;
   1167 	etype_t		type_c;
   1168 	opcode_t	*op;
   1169 
   1170 	// check if we're accessing a field
   1171 	if ( baseobj && ( baseobj->Type() == ev_object ) ) {
   1172 		const idVarDef *tdef;
   1173 
   1174 		def = NULL;
   1175 		for( tdef = baseobj; tdef != &def_object; tdef = tdef->TypeDef()->SuperClass()->def ) {
   1176 			def = gameLocal.program.GetDef( NULL, name, tdef );
   1177 			if ( def ) {
   1178 				break;
   1179 			}
   1180 		}
   1181 	} else {
   1182 		// first look through the defs in our scope
   1183 		def = gameLocal.program.GetDef( NULL, name, scope );
   1184 		if ( !def ) {
   1185 			// if we're in a member function, check types local to the object
   1186 			if ( ( scope->Type() != ev_namespace ) && ( scope->scope->Type() == ev_object ) ) {
   1187 				// get the local object pointer
   1188 				idVarDef *thisdef = gameLocal.program.GetDef( scope->scope->TypeDef(), "self", scope );
   1189 
   1190 				field = LookupDef( name, scope->scope->TypeDef()->def );
   1191 				if ( !field ) {
   1192 					Error( "Unknown value \"%s\"", name );
   1193 				}
   1194 
   1195 				// type check
   1196 				type_b = field->Type();
   1197 				if ( field->Type() == ev_function ) {
   1198 					type_c = field->TypeDef()->ReturnType()->Type();
   1199 				} else {
   1200 					type_c = field->TypeDef()->FieldType()->Type();	// field access gets type from field
   1201 	                if ( CheckToken( "++" ) ) {
   1202 						if ( type_c != ev_float ) {
   1203 							Error( "Invalid type for ++" );
   1204 						}
   1205 						def = EmitOpcode( OP_UINCP_F, thisdef, field );
   1206 						return def;
   1207 					} else if ( CheckToken( "--" ) ) {
   1208 						if ( type_c != ev_float ) {
   1209 							Error( "Invalid type for --" );
   1210 						}
   1211 						def = EmitOpcode( OP_UDECP_F, thisdef, field );
   1212 						return def;
   1213 					}
   1214 				}
   1215 
   1216 				op = &opcodes[ OP_INDIRECT_F ];
   1217 				while( ( op->type_a->Type() != ev_object ) 
   1218 					|| ( type_b != op->type_b->Type() ) || ( type_c != op->type_c->Type() ) ) {
   1219 					if ( ( op->priority == FUNCTION_PRIORITY ) && ( op->type_a->Type() == ev_object ) && ( op->type_c->Type() == ev_void ) && 
   1220 						( type_c != op->type_c->Type() ) ) {
   1221 						// catches object calls that return a value
   1222 						break;
   1223 					}
   1224 					op++;
   1225 					if ( !op->name || strcmp( op->name, "." ) ) {
   1226 						Error( "no valid opcode to access type '%s'", field->TypeDef()->SuperClass()->Name() );
   1227 					}
   1228 				}
   1229 
   1230 				if ( ( op - opcodes ) == OP_OBJECTCALL ) {
   1231 					ExpectToken( "(" );
   1232 					def = ParseObjectCall( thisdef, field );
   1233 				} else {
   1234 					// emit the conversion opcode
   1235 					def = EmitOpcode( op, thisdef, field );
   1236 
   1237 					// field access gets type from field
   1238 					def->SetTypeDef( field->TypeDef()->FieldType() );
   1239 				}
   1240 			}
   1241 		}
   1242 	}
   1243 
   1244 	return def;
   1245 }
   1246 
   1247 /*
   1248 ============
   1249 idCompiler::ParseValue
   1250 
   1251 Returns the def for the current token
   1252 ============
   1253 */
   1254 idVarDef *idCompiler::ParseValue() {
   1255 	idVarDef	*def;
   1256 	idVarDef	*namespaceDef;
   1257 	idStr		name;
   1258 	
   1259 	if ( immediateType == &type_entity ) {
   1260 		// if an immediate entity ($-prefaced name) then create or lookup a def for it.
   1261 		// when entities are spawned, they'll lookup the def and point it to them.
   1262 		def = gameLocal.program.GetDef( &type_entity, "$" + token, &def_namespace );
   1263 		if ( !def ) {
   1264 			def = gameLocal.program.AllocDef( &type_entity, "$" + token, &def_namespace, true );
   1265 		}
   1266 		NextToken();
   1267 		return def;
   1268 	} else if ( immediateType ) {
   1269 		// if the token is an immediate, allocate a constant for it
   1270 		return ParseImmediate();
   1271 	}
   1272 
   1273 	ParseName( name );
   1274 	def = LookupDef( name, basetype );
   1275 	if ( def == NULL ) {
   1276 		if ( basetype ) {
   1277 			Error( "%s is not a member of %s", name.c_str(), basetype->TypeDef()->Name() );
   1278 		} else {
   1279 			Error( "Unknown value \"%s\"", name.c_str() );
   1280 		}
   1281 	// if namespace, then look up the variable in that namespace
   1282 	} else if ( def->Type() == ev_namespace ) {
   1283 		while( def->Type() == ev_namespace ) {
   1284 			ExpectToken( "::" );
   1285 			ParseName( name );
   1286 			namespaceDef = def;
   1287 			def = gameLocal.program.GetDef( NULL, name, namespaceDef );
   1288 			if ( def == NULL ) {
   1289 				if ( namespaceDef != NULL ) {
   1290 					Error( "Unknown value \"%s::%s\"", namespaceDef->GlobalName(), name.c_str() );
   1291 				} else {
   1292 					Error( "Unknown value \"%s\"", name.c_str() );
   1293 				}
   1294 				break;
   1295 			}
   1296 		}
   1297 		//def = LookupDef( name, basetype );
   1298 	}
   1299 
   1300 	return def;
   1301 }
   1302 
   1303 /*
   1304 ============
   1305 idCompiler::GetTerm
   1306 ============
   1307 */
   1308 idVarDef *idCompiler::GetTerm() {
   1309 	idVarDef	*e;
   1310 	int 		op;
   1311 	
   1312 	if ( !immediateType && CheckToken( "~" ) ) {
   1313 		e = GetExpression( TILDE_PRIORITY );
   1314 		switch( e->Type() ) {
   1315 		case ev_float :
   1316 			op = OP_COMP_F;
   1317 			break;
   1318 
   1319 		default :
   1320 			// shut up compiler
   1321 			op = OP_COMP_F;
   1322 			Error( "type mismatch for ~" );
   1323 		}
   1324 
   1325 		return EmitOpcode( op, e, 0 );
   1326 	}
   1327 
   1328 	if ( !immediateType && CheckToken( "!" ) ) {
   1329 		e = GetExpression( NOT_PRIORITY );
   1330 		switch( e->Type() ) {
   1331 		case ev_boolean :
   1332 			op = OP_NOT_BOOL;
   1333 			break;
   1334 
   1335 		case ev_float :
   1336 			op = OP_NOT_F;
   1337 			break;
   1338 
   1339 		case ev_string :
   1340 			op = OP_NOT_S;
   1341 			break;
   1342 
   1343 		case ev_vector :
   1344 			op = OP_NOT_V;
   1345 			break;
   1346 
   1347 		case ev_entity :
   1348 			op = OP_NOT_ENT;
   1349 			break;
   1350 
   1351 		case ev_function :
   1352 			// shut up compiler
   1353 			op = OP_NOT_F;
   1354 			Error( "Invalid type for !" );
   1355 			break;
   1356 		case ev_object :
   1357 			op = OP_NOT_ENT;
   1358 			break;
   1359 
   1360 		default :
   1361 			// shut up compiler
   1362 			op = OP_NOT_F;
   1363 			Error( "type mismatch for !" );
   1364 		}
   1365 
   1366 		return EmitOpcode( op, e, 0 );
   1367 	}
   1368 
   1369 	// check for negation operator
   1370 	if ( !immediateType && CheckToken( "-" ) ) {
   1371 		// constants are directly negated without an instruction
   1372 		if ( immediateType == &type_float ) {
   1373 			immediate._float = -immediate._float;
   1374 			return ParseImmediate();
   1375 		} else if ( immediateType == &type_vector ) {
   1376 			immediate.vector[0] = -immediate.vector[0];
   1377 			immediate.vector[1] = -immediate.vector[1];
   1378 			immediate.vector[2] = -immediate.vector[2];
   1379 			return ParseImmediate();
   1380 		} else {
   1381 			e = GetExpression( NOT_PRIORITY );
   1382 			switch( e->Type() ) {
   1383 			case ev_float :
   1384 				op = OP_NEG_F;
   1385 				break;
   1386 
   1387 			case ev_vector :
   1388 				op = OP_NEG_V;
   1389 				break;
   1390 			default :
   1391 				// shut up compiler
   1392 				op = OP_NEG_F;
   1393 				Error( "type mismatch for -" );
   1394 			}
   1395 			return EmitOpcode( &opcodes[ op ], e, 0 );
   1396 		}
   1397 	}
   1398 	
   1399 	if ( CheckToken( "int" ) ) {
   1400 		ExpectToken( "(" );
   1401 
   1402 		e = GetExpression( INT_PRIORITY );
   1403 		if ( e->Type() != ev_float ) {
   1404 			Error( "type mismatch for int()" );
   1405 		}
   1406 
   1407 		ExpectToken( ")" );
   1408 
   1409 		return EmitOpcode( OP_INT_F, e, 0 );
   1410 	}
   1411 	
   1412 	if ( CheckToken( "thread" ) ) {
   1413 		callthread = true;
   1414 		e = GetExpression( FUNCTION_PRIORITY );
   1415 
   1416 		if ( callthread ) {
   1417 			Error( "Invalid thread call" );
   1418 		}
   1419 
   1420 		// threads return the thread number
   1421 		gameLocal.program.returnDef->SetTypeDef( &type_float );
   1422 		return gameLocal.program.returnDef;
   1423 	}
   1424 	
   1425 	if ( !immediateType && CheckToken( "(" ) ) {
   1426 		e = GetExpression( TOP_PRIORITY );
   1427 		ExpectToken( ")" );
   1428 
   1429 		return e;
   1430 	}
   1431 	
   1432 	return ParseValue();
   1433 }
   1434 
   1435 /*
   1436 ==============
   1437 idCompiler::TypeMatches
   1438 ==============
   1439 */
   1440 bool idCompiler::TypeMatches( etype_t type1, etype_t type2 ) const {
   1441 	if ( type1 == type2 ) {
   1442 		return true;
   1443 	}
   1444 
   1445 	//if ( ( type1 == ev_entity ) && ( type2 == ev_object ) ) {
   1446 	//	return true;
   1447 	//}
   1448 		
   1449 	//if ( ( type2 == ev_entity ) && ( type1 == ev_object ) ) {
   1450 	//	return true;
   1451 	//}
   1452 
   1453 	return false;
   1454 }
   1455 
   1456 /*
   1457 ==============
   1458 idCompiler::GetExpression
   1459 ==============
   1460 */
   1461 idVarDef *idCompiler::GetExpression( int priority ) {
   1462 	opcode_t		*op;
   1463 	opcode_t		*oldop;
   1464 	idVarDef		*e;
   1465 	idVarDef		*e2;
   1466 	const idVarDef	*oldtype;
   1467 	etype_t 		type_a;
   1468 	etype_t 		type_b;
   1469 	etype_t 		type_c;
   1470 	
   1471 	if ( priority == 0 ) {
   1472 		return GetTerm();
   1473 	}
   1474 		
   1475 	e = GetExpression( priority - 1 );
   1476 	if ( token == ";" ) {
   1477 		// save us from searching through the opcodes unneccesarily
   1478 		return e;
   1479 	}
   1480 
   1481 	while( 1 ) {
   1482 		if ( ( priority == FUNCTION_PRIORITY ) && CheckToken( "(" ) ) {
   1483 			return ParseFunctionCall( e );
   1484 		}
   1485 
   1486 		// has to be a punctuation
   1487 		if ( immediateType ) {
   1488 			break;
   1489 		}
   1490 
   1491 		for( op = opcodes; op->name; op++ ) {
   1492 			if ( ( op->priority == priority ) && CheckToken( op->name ) ) {
   1493 				break;
   1494 			}
   1495 		}
   1496 
   1497 		if ( !op->name ) {
   1498 			// next token isn't at this priority level
   1499 			break;
   1500 		}
   1501 
   1502 		// unary operators act only on the left operand
   1503 		if ( op->type_b == &def_void ) {
   1504 			e = EmitOpcode( op, e, 0 );
   1505 			return e;
   1506 		}
   1507 
   1508 		// preserve our base type
   1509 		oldtype = basetype;
   1510 
   1511 		// field access needs scope from object
   1512 		if ( ( op->name[ 0 ] == '.' ) && e->TypeDef()->Inherits( &type_object ) ) {
   1513 			// save off what type this field is part of
   1514 			basetype = e->TypeDef()->def;
   1515 		}
   1516 
   1517 		if ( op->rightAssociative ) {
   1518 			// if last statement is an indirect, change it to an address of
   1519 			if ( gameLocal.program.NumStatements() > 0 ) {
   1520 				statement_t &statement = gameLocal.program.GetStatement( gameLocal.program.NumStatements() - 1 );
   1521 				if ( ( statement.op >= OP_INDIRECT_F ) && ( statement.op < OP_ADDRESS ) ) {
   1522 					statement.op = OP_ADDRESS;
   1523 					type_pointer.SetPointerType( e->TypeDef() );
   1524 					e->SetTypeDef( &type_pointer );
   1525 				}
   1526 			}
   1527 
   1528 			e2 = GetExpression( priority );
   1529 		} else {
   1530 			e2 = GetExpression( priority - 1 );
   1531 		}
   1532 
   1533 		// restore type
   1534 		basetype = oldtype;
   1535 			
   1536 		// type check
   1537 		type_a = e->Type();
   1538 		type_b = e2->Type();
   1539 
   1540 		// field access gets type from field
   1541 		if ( op->name[ 0 ] == '.' ) {
   1542 			if ( ( e2->Type() == ev_function ) && e2->TypeDef()->ReturnType() ) {
   1543 				type_c = e2->TypeDef()->ReturnType()->Type();
   1544 			} else if ( e2->TypeDef()->FieldType() ) {
   1545 				type_c = e2->TypeDef()->FieldType()->Type();
   1546 			} else {
   1547 				// not a field
   1548 				type_c = ev_error;
   1549 			}
   1550 		} else {
   1551 			type_c = ev_void;
   1552 		}
   1553 
   1554 		oldop = op;
   1555 		while( !TypeMatches( type_a, op->type_a->Type() ) || !TypeMatches( type_b, op->type_b->Type() ) ||
   1556 			( ( type_c != ev_void ) && !TypeMatches( type_c, op->type_c->Type() ) ) ) {
   1557 			if ( ( op->priority == FUNCTION_PRIORITY ) && TypeMatches( type_a, op->type_a->Type() ) && TypeMatches( type_b, op->type_b->Type() ) ) {
   1558 				break;
   1559 			}
   1560 
   1561 			op++;
   1562 			if ( !op->name || strcmp( op->name, oldop->name ) ) {
   1563 				Error( "type mismatch for '%s'", oldop->name );
   1564 			}
   1565 		}
   1566 
   1567 		switch( op - opcodes ) {
   1568 		case OP_SYSCALL :
   1569 			ExpectToken( "(" );
   1570 			e = ParseSysObjectCall( e2 );
   1571 			break;
   1572 
   1573 		case OP_OBJECTCALL :
   1574 			ExpectToken( "(" );
   1575 			if ( ( e2->initialized != idVarDef::uninitialized ) && e2->value.functionPtr->eventdef ) {
   1576 				e = ParseEventCall( e, e2 );
   1577 			} else {
   1578 				e = ParseObjectCall( e, e2 );
   1579 			}
   1580 			break;
   1581 		
   1582 		case OP_EVENTCALL :
   1583 			ExpectToken( "(" );
   1584 			if ( ( e2->initialized != idVarDef::uninitialized ) && e2->value.functionPtr->eventdef ) {
   1585 				e = ParseEventCall( e, e2 );
   1586 			} else {
   1587 				e = ParseObjectCall( e, e2 );
   1588 			}
   1589 			break;
   1590 
   1591 		default:
   1592 			if ( callthread ) {
   1593 				Error( "Expecting function call after 'thread'" );
   1594 			}
   1595 
   1596 			if ( ( type_a == ev_pointer ) && ( type_b != e->TypeDef()->PointerType()->Type() ) ) {
   1597 				// FIXME: need to make a general case for this
   1598 				if ( ( op - opcodes == OP_STOREP_F ) && ( e->TypeDef()->PointerType()->Type() == ev_boolean ) ) {
   1599 					// copy from float to boolean pointer
   1600 					op = &opcodes[ OP_STOREP_FTOBOOL ];
   1601 				} else if ( ( op - opcodes == OP_STOREP_BOOL ) && ( e->TypeDef()->PointerType()->Type() == ev_float ) ) {
   1602 					// copy from boolean to float pointer
   1603 					op = &opcodes[ OP_STOREP_BOOLTOF ];
   1604 				} else if ( ( op - opcodes == OP_STOREP_F ) && ( e->TypeDef()->PointerType()->Type() == ev_string ) ) {
   1605 					// copy from float to string pointer
   1606 					op = &opcodes[ OP_STOREP_FTOS ];
   1607 				} else if ( ( op - opcodes == OP_STOREP_BOOL ) && ( e->TypeDef()->PointerType()->Type() == ev_string ) ) {
   1608 					// copy from boolean to string pointer
   1609 					op = &opcodes[ OP_STOREP_BTOS ];
   1610 				} else if ( ( op - opcodes == OP_STOREP_V ) && ( e->TypeDef()->PointerType()->Type() == ev_string ) ) {
   1611 					// copy from vector to string pointer
   1612 					op = &opcodes[ OP_STOREP_VTOS ];
   1613 				} else if ( ( op - opcodes == OP_STOREP_ENT ) && ( e->TypeDef()->PointerType()->Type() == ev_object ) ) {
   1614 					// store an entity into an object pointer
   1615 					op = &opcodes[ OP_STOREP_OBJENT ];
   1616 				} else {
   1617 					Error( "type mismatch for '%s'", op->name );
   1618 				}
   1619 			}
   1620 			
   1621 			if ( op->rightAssociative ) {
   1622 				e = EmitOpcode( op, e2, e );
   1623 			} else {
   1624 				e = EmitOpcode( op, e, e2 );
   1625 			}
   1626 
   1627 			if ( op - opcodes == OP_STOREP_OBJENT ) {
   1628 				// statement.b points to type_pointer, which is just a temporary that gets its type reassigned, so we store the real type in statement.c
   1629 				// so that we can do a type check during run time since we don't know what type the script object is at compile time because it
   1630 				// comes from an entity
   1631 				statement_t &statement = gameLocal.program.GetStatement( gameLocal.program.NumStatements() - 1 );
   1632 				statement.c = type_pointer.PointerType()->def;
   1633 			}
   1634 
   1635 			// field access gets type from field
   1636 			if ( type_c != ev_void ) {
   1637 				e->SetTypeDef( e2->TypeDef()->FieldType() );
   1638 			}
   1639 			break;
   1640 		}
   1641 	}
   1642 
   1643 	return e;
   1644 }
   1645 
   1646 /*
   1647 ================
   1648 idCompiler::PatchLoop
   1649 ================
   1650 */
   1651 void idCompiler::PatchLoop( int start, int continuePos ) {
   1652 	int			i;
   1653 	statement_t	*pos;
   1654 
   1655 	pos = &gameLocal.program.GetStatement( start );
   1656 	for( i = start; i < gameLocal.program.NumStatements(); i++, pos++ ) {
   1657 		if ( pos->op == OP_BREAK ) {
   1658 			pos->op = OP_GOTO;
   1659 			pos->a = JumpFrom( i );
   1660 		} else if ( pos->op == OP_CONTINUE ) {
   1661 			pos->op = OP_GOTO;
   1662 			pos->a = JumpDef( i, continuePos );
   1663 		}
   1664 	}
   1665 }
   1666 
   1667 /*
   1668 ================
   1669 idCompiler::ParseReturnStatement
   1670 ================
   1671 */
   1672 void idCompiler::ParseReturnStatement() {
   1673 	idVarDef	*e;
   1674 	etype_t 	type_a;
   1675 	etype_t 	type_b;
   1676 	opcode_t	*op;
   1677 
   1678 	if ( CheckToken( ";" ) ) {
   1679 		if ( scope->TypeDef()->ReturnType()->Type() != ev_void ) {
   1680 			Error( "expecting return value" );
   1681 		}
   1682 
   1683 		EmitOpcode( OP_RETURN, 0, 0 );
   1684 		return;
   1685 	}
   1686 
   1687 	e = GetExpression( TOP_PRIORITY );
   1688 	ExpectToken( ";" );
   1689 
   1690 	type_a = e->Type();
   1691 	type_b = scope->TypeDef()->ReturnType()->Type();
   1692 
   1693 	if ( TypeMatches( type_a, type_b ) ) {
   1694 		EmitOpcode( OP_RETURN, e, 0 );
   1695 		return;
   1696 	}
   1697 
   1698 	for( op = opcodes; op->name; op++ ) {
   1699 		if ( !strcmp( op->name, "=" ) ) {
   1700 			break;
   1701 		}
   1702 	}
   1703 
   1704 	assert( op->name );
   1705 
   1706 	while( !TypeMatches( type_a, op->type_a->Type() ) || !TypeMatches( type_b, op->type_b->Type() ) ) {
   1707 		op++;
   1708 		if ( !op->name || strcmp( op->name, "=" ) ) {
   1709 			Error( "type mismatch for return value" );
   1710 		}
   1711 	}
   1712 
   1713 	idTypeDef *returnType = scope->TypeDef()->ReturnType();
   1714 	if ( returnType->Type() == ev_string ) {
   1715 		EmitOpcode( op, e, gameLocal.program.returnStringDef );
   1716 	} else {
   1717 		gameLocal.program.returnDef->SetTypeDef( returnType );
   1718 		EmitOpcode( op, e, gameLocal.program.returnDef );
   1719 	}
   1720 	EmitOpcode( OP_RETURN, 0, 0 );
   1721 }
   1722 	
   1723 /*
   1724 ================
   1725 idCompiler::ParseWhileStatement
   1726 ================
   1727 */
   1728 void idCompiler::ParseWhileStatement() {
   1729 	idVarDef	*e;
   1730 	int			patch1;
   1731 	int			patch2;
   1732 
   1733 	loopDepth++;
   1734 
   1735 	ExpectToken( "(" );
   1736 	
   1737 	patch2 = gameLocal.program.NumStatements();
   1738 	e = GetExpression( TOP_PRIORITY );
   1739 	ExpectToken( ")" );
   1740 
   1741 	if ( ( e->initialized == idVarDef::initializedConstant ) && ( *e->value.intPtr != 0 ) ) {
   1742 		//FIXME: we can completely skip generation of this code in the opposite case
   1743 		ParseStatement();
   1744 		EmitOpcode( OP_GOTO, JumpTo( patch2 ), 0 );
   1745 	} else {
   1746 		patch1 = gameLocal.program.NumStatements();
   1747         EmitOpcode( OP_IFNOT, e, 0 );
   1748 		ParseStatement();
   1749 		EmitOpcode( OP_GOTO, JumpTo( patch2 ), 0 );
   1750 		gameLocal.program.GetStatement( patch1 ).b = JumpFrom( patch1 );
   1751 	}
   1752 
   1753 	// fixup breaks and continues
   1754 	PatchLoop( patch2, patch2 );
   1755 
   1756 	loopDepth--;
   1757 }
   1758 
   1759 /*
   1760 ================
   1761 idCompiler::ParseForStatement
   1762 
   1763 Form of for statement with a counter:
   1764 
   1765 	a = 0;
   1766 start:					<< patch4
   1767 	if ( !( a < 10 ) ) {
   1768 		goto end;		<< patch1
   1769 	} else {
   1770 		goto process;	<< patch3
   1771 	}
   1772 
   1773 increment:				<< patch2
   1774 	a = a + 1;
   1775 	goto start;			<< goto patch4
   1776 
   1777 process:
   1778 	statements;
   1779 	goto increment;		<< goto patch2
   1780 
   1781 end:
   1782 
   1783 Form of for statement without a counter:
   1784 
   1785 	a = 0;
   1786 start:					<< patch2
   1787 	if ( !( a < 10 ) ) {
   1788 		goto end;		<< patch1
   1789 	}
   1790 
   1791 process:
   1792 	statements;
   1793 	goto start;			<< goto patch2
   1794 
   1795 end:
   1796 ================
   1797 */
   1798 void idCompiler::ParseForStatement() {
   1799 	idVarDef	*e;
   1800 	int			start;
   1801 	int			patch1;
   1802 	int			patch2;
   1803 	int			patch3;
   1804 	int			patch4;
   1805 
   1806 	loopDepth++;
   1807 
   1808 	start = gameLocal.program.NumStatements();
   1809 
   1810 	ExpectToken( "(" );
   1811 	
   1812 	// init
   1813 	if ( !CheckToken( ";" ) ) {
   1814 		do {
   1815 			GetExpression( TOP_PRIORITY );
   1816 		} while( CheckToken( "," ) );
   1817 
   1818 		ExpectToken( ";" );
   1819 	}
   1820 
   1821 	// condition
   1822 	patch2 = gameLocal.program.NumStatements();
   1823 
   1824 	e = GetExpression( TOP_PRIORITY );
   1825 	ExpectToken( ";" );
   1826 
   1827 	//FIXME: add check for constant expression
   1828 	patch1 = gameLocal.program.NumStatements();
   1829 	EmitOpcode( OP_IFNOT, e, 0 );
   1830 
   1831 	// counter
   1832 	if ( !CheckToken( ")" ) ) {
   1833 		patch3 = gameLocal.program.NumStatements();
   1834 		EmitOpcode( OP_IF, e, 0 );
   1835 
   1836 		patch4 = patch2;
   1837 		patch2 = gameLocal.program.NumStatements();
   1838 		do {
   1839 			GetExpression( TOP_PRIORITY );
   1840 		} while( CheckToken( "," ) );
   1841 		
   1842 		ExpectToken( ")" );
   1843 
   1844 		// goto patch4
   1845 		EmitOpcode( OP_GOTO, JumpTo( patch4 ), 0 );
   1846 
   1847 		// fixup patch3
   1848 		gameLocal.program.GetStatement( patch3 ).b = JumpFrom( patch3 );
   1849 	}
   1850 
   1851 	ParseStatement();
   1852 
   1853 	// goto patch2
   1854 	EmitOpcode( OP_GOTO, JumpTo( patch2 ), 0 );
   1855 
   1856 	// fixup patch1
   1857 	gameLocal.program.GetStatement( patch1 ).b = JumpFrom( patch1 );
   1858 
   1859 	// fixup breaks and continues
   1860 	PatchLoop( start, patch2 );
   1861 
   1862 	loopDepth--;
   1863 }
   1864 
   1865 /*
   1866 ================
   1867 idCompiler::ParseDoWhileStatement
   1868 ================
   1869 */
   1870 void idCompiler::ParseDoWhileStatement() {
   1871 	idVarDef	*e;
   1872 	int			patch1;
   1873 
   1874 	loopDepth++;
   1875 
   1876 	patch1 = gameLocal.program.NumStatements();
   1877 	ParseStatement();
   1878 	ExpectToken( "while" );
   1879 	ExpectToken( "(" );
   1880 	e = GetExpression( TOP_PRIORITY );
   1881 	ExpectToken( ")" );
   1882 	ExpectToken( ";" );
   1883 
   1884 	EmitOpcode( OP_IF, e, JumpTo( patch1 ) );
   1885 
   1886 	// fixup breaks and continues
   1887 	PatchLoop( patch1, patch1 );
   1888 
   1889 	loopDepth--;
   1890 }
   1891 
   1892 /*
   1893 ================
   1894 idCompiler::ParseIfStatement
   1895 ================
   1896 */
   1897 void idCompiler::ParseIfStatement() {
   1898 	idVarDef	*e;
   1899 	int			patch1;
   1900 	int			patch2;
   1901 
   1902 	ExpectToken( "(" );
   1903 	e = GetExpression( TOP_PRIORITY );
   1904 	ExpectToken( ")" );
   1905 
   1906 	//FIXME: add check for constant expression
   1907 	patch1 = gameLocal.program.NumStatements();
   1908 	EmitOpcode( OP_IFNOT, e, 0 );
   1909 
   1910 	ParseStatement();
   1911 	
   1912 	if ( CheckToken( "else" ) ) {
   1913 		patch2 = gameLocal.program.NumStatements();
   1914 		EmitOpcode( OP_GOTO, 0, 0 );
   1915 		gameLocal.program.GetStatement( patch1 ).b = JumpFrom( patch1 );
   1916 		ParseStatement();
   1917 		gameLocal.program.GetStatement( patch2 ).a = JumpFrom( patch2 );
   1918 	} else {
   1919 		gameLocal.program.GetStatement( patch1 ).b = JumpFrom( patch1 );
   1920 	}
   1921 }
   1922 
   1923 /*
   1924 ============
   1925 idCompiler::ParseStatement
   1926 ============
   1927 */
   1928 void idCompiler::ParseStatement() {
   1929 	if ( CheckToken( ";" ) ) {
   1930 		// skip semicolons, which are harmless and ok syntax
   1931 		return;
   1932 	}
   1933 
   1934 	if ( CheckToken( "{" ) ) {
   1935 		do {
   1936 			ParseStatement();
   1937 		} while( !CheckToken( "}" ) );
   1938 
   1939 		return;
   1940 	} 
   1941 
   1942 	if ( CheckToken( "return" ) ) {
   1943 		ParseReturnStatement();
   1944 		return;
   1945 	}
   1946 	
   1947 	if ( CheckToken( "while" ) ) {
   1948 		ParseWhileStatement();
   1949 		return;
   1950 	}
   1951 
   1952 	if ( CheckToken( "for" ) ) {
   1953 		ParseForStatement();
   1954 		return;
   1955 	}
   1956 
   1957 	if ( CheckToken( "do" ) ) {
   1958 		ParseDoWhileStatement();
   1959 		return;
   1960 	}
   1961 
   1962 	if ( CheckToken( "break" ) ) {
   1963 		ExpectToken( ";" );
   1964 		if ( !loopDepth ) {
   1965 			Error( "cannot break outside of a loop" );
   1966 		}
   1967 		EmitOpcode( OP_BREAK, 0, 0 );
   1968 		return;
   1969 	}
   1970 
   1971 	if ( CheckToken( "continue" ) ) {
   1972 		ExpectToken( ";" );
   1973 		if ( !loopDepth ) {
   1974 			Error( "cannot contine outside of a loop" );
   1975 		}
   1976 		EmitOpcode( OP_CONTINUE, 0, 0 );
   1977 		return;
   1978 	}
   1979 
   1980 	if ( CheckType() != NULL ) {
   1981 		ParseDefs();
   1982 		return;
   1983 	}
   1984 
   1985 	if ( CheckToken( "if" ) ) {
   1986 		ParseIfStatement();
   1987 		return;
   1988 	}
   1989 
   1990 	GetExpression( TOP_PRIORITY );
   1991 	ExpectToken(";");
   1992 }
   1993 
   1994 /*
   1995 ================
   1996 idCompiler::ParseObjectDef
   1997 ================
   1998 */
   1999 void idCompiler::ParseObjectDef( const char *objname ) {
   2000 	idTypeDef	*objtype;
   2001 	idTypeDef	*type;
   2002 	idTypeDef	*parentType;
   2003 	idTypeDef	*fieldtype;
   2004 	idStr		name;
   2005 	const char  *fieldname;
   2006 	idTypeDef	newtype( ev_field, NULL, "", 0, NULL );
   2007 	idVarDef	*oldscope;
   2008 	int			num;
   2009 	int			i;
   2010 
   2011 	oldscope = scope;
   2012 	if ( scope->Type() != ev_namespace ) {
   2013 		Error( "Objects cannot be defined within functions or other objects" );
   2014 	}
   2015 
   2016 	// make sure it doesn't exist before we create it
   2017 	if ( gameLocal.program.FindType( objname ) != NULL ) {
   2018 		Error( "'%s' : redefinition; different basic types", objname );
   2019 	}
   2020 
   2021 	// base type
   2022 	if ( !CheckToken( ":" ) ) {
   2023 		parentType = &type_object;
   2024 	} else {
   2025 		parentType = ParseType();
   2026 		if ( !parentType->Inherits( &type_object ) ) {
   2027 			Error( "Objects may only inherit from objects." );
   2028 		}
   2029 	}
   2030 	
   2031 	objtype = gameLocal.program.AllocType( ev_object, NULL, objname, parentType == &type_object ? 0 : parentType->Size(), parentType );
   2032 	objtype->def = gameLocal.program.AllocDef( objtype, objname, scope, true );
   2033 	scope = objtype->def;
   2034 
   2035 	// inherit all the functions
   2036 	num = parentType->NumFunctions();
   2037 	for( i = 0; i < parentType->NumFunctions(); i++ ) {
   2038 		const function_t *func = parentType->GetFunction( i );
   2039 		objtype->AddFunction( func );
   2040 	}
   2041 
   2042 	ExpectToken( "{" );
   2043 
   2044 	do {
   2045 		if ( CheckToken( ";" ) ) {
   2046 			// skip semicolons, which are harmless and ok syntax
   2047 			continue;
   2048 		}
   2049 
   2050 		fieldtype = ParseType();
   2051 		newtype.SetFieldType( fieldtype );
   2052 
   2053 		fieldname = va( "%s field", fieldtype->Name() );
   2054 		newtype.SetName( fieldname );
   2055 
   2056 		ParseName( name );
   2057 
   2058 		// check for a function prototype or declaraction
   2059 		if ( CheckToken( "(" ) ) {
   2060 			ParseFunctionDef( newtype.FieldType(), name );
   2061 		} else {
   2062 			type = gameLocal.program.GetType( newtype, true );
   2063 			assert( !type->def );
   2064 			gameLocal.program.AllocDef( type, name, scope, true );
   2065 			objtype->AddField( type, name );
   2066 			ExpectToken( ";" );
   2067 		}
   2068 	} while( !CheckToken( "}" ) );
   2069 
   2070 	scope = oldscope;
   2071 
   2072 	ExpectToken( ";" );
   2073 }
   2074 
   2075 /*
   2076 ============
   2077 idCompiler::ParseFunction
   2078 
   2079 parse a function type
   2080 ============
   2081 */
   2082 idTypeDef *idCompiler::ParseFunction( idTypeDef *returnType, const char *name ) {
   2083 	idTypeDef	newtype( ev_function, NULL, name, type_function.Size(), returnType );
   2084 	idTypeDef	*type;
   2085 	
   2086 	if ( scope->Type() != ev_namespace ) {
   2087 		// create self pointer
   2088 		newtype.AddFunctionParm( scope->TypeDef(), "self" );
   2089 	}
   2090 
   2091 	if ( !CheckToken( ")" ) ) {
   2092 		idStr parmName;
   2093 		do {
   2094 			type = ParseType();
   2095 			ParseName( parmName );
   2096 			newtype.AddFunctionParm( type, parmName );
   2097 		} while( CheckToken( "," ) );
   2098 
   2099 		ExpectToken( ")" );
   2100 	}
   2101 
   2102 	return gameLocal.program.GetType( newtype, true );
   2103 }
   2104 
   2105 /*
   2106 ================
   2107 idCompiler::ParseFunctionDef
   2108 ================
   2109 */
   2110 void idCompiler::ParseFunctionDef( idTypeDef *returnType, const char *name ) {
   2111 	idTypeDef		*type;
   2112 	idVarDef		*def;
   2113 	const idVarDef	*parm;
   2114 	idVarDef		*oldscope;
   2115 	int 			i;
   2116 	int 			numParms;
   2117 	const idTypeDef	*parmType;
   2118 	function_t		*func;
   2119 	statement_t		*pos;
   2120 
   2121 	if ( ( scope->Type() != ev_namespace ) && !scope->TypeDef()->Inherits( &type_object ) ) {
   2122 		Error( "Functions may not be defined within other functions" );
   2123 	}
   2124 
   2125 	type = ParseFunction( returnType, name );
   2126 	def = gameLocal.program.GetDef( type, name, scope );
   2127 	if ( !def ) {
   2128 		def = gameLocal.program.AllocDef( type, name, scope, true );
   2129 		type->def = def;
   2130 
   2131 		func = &gameLocal.program.AllocFunction( def );
   2132 		if ( scope->TypeDef()->Inherits( &type_object ) ) {
   2133 			scope->TypeDef()->AddFunction( func );
   2134 		}
   2135 	} else {
   2136 		func = def->value.functionPtr;
   2137 		assert( func );
   2138 		if ( func->firstStatement ) {
   2139 			Error( "%s redeclared", def->GlobalName() );
   2140 		}
   2141 	}
   2142 
   2143 	// check if this is a prototype or declaration
   2144 	if ( !CheckToken( "{" ) ) {
   2145 		// it's just a prototype, so get the ; and move on
   2146 		ExpectToken( ";" );
   2147 		return;
   2148 	}
   2149 
   2150 	// calculate stack space used by parms
   2151 	numParms = type->NumParameters();
   2152 	func->parmSize.SetNum( numParms );
   2153 	for( i = 0; i < numParms; i++ ) {
   2154 		parmType = type->GetParmType( i );
   2155 		if ( parmType->Inherits( &type_object ) ) {
   2156 			func->parmSize[ i ] = type_object.Size();
   2157 		} else {
   2158 			func->parmSize[ i ] = parmType->Size();
   2159 		}
   2160 		func->parmTotal += func->parmSize[ i ];
   2161 	}
   2162 
   2163 	// define the parms
   2164 	for( i = 0; i < numParms; i++ ) {
   2165 		if ( gameLocal.program.GetDef( type->GetParmType( i ), type->GetParmName( i ), def ) ) {
   2166 			Error( "'%s' defined more than once in function parameters", type->GetParmName( i ) );
   2167 		}
   2168 		parm = gameLocal.program.AllocDef( type->GetParmType( i ), type->GetParmName( i ), def, false );
   2169 	}
   2170 
   2171 	oldscope = scope;
   2172 	scope = def;
   2173 
   2174 	func->firstStatement = gameLocal.program.NumStatements();
   2175 
   2176 	// check if we should call the super class constructor
   2177 	if ( oldscope->TypeDef()->Inherits( &type_object ) && !idStr::Icmp( name, "init" ) ) {
   2178 		idTypeDef *superClass;
   2179 		function_t *constructorFunc = NULL;
   2180 
   2181 		// find the superclass constructor
   2182 		for( superClass = oldscope->TypeDef()->SuperClass(); superClass != &type_object; superClass = superClass->SuperClass() ) {
   2183 			constructorFunc = gameLocal.program.FindFunction( va( "%s::init", superClass->Name() ) );
   2184 			if ( constructorFunc ) {
   2185 				break;
   2186 			}
   2187 		}
   2188 
   2189 		// emit the call to the constructor
   2190 		if ( constructorFunc ) {
   2191 			idVarDef *selfDef = gameLocal.program.GetDef( type->GetParmType( 0 ), type->GetParmName( 0 ), def );
   2192 			assert( selfDef );
   2193 			EmitPush( selfDef, selfDef->TypeDef() );
   2194 			EmitOpcode( &opcodes[ OP_CALL ], constructorFunc->def, 0 );
   2195 		}
   2196 	}
   2197 
   2198 	// parse regular statements
   2199 	while( !CheckToken( "}" ) ) {
   2200 		ParseStatement();
   2201 	}
   2202 
   2203 	// check if we should call the super class destructor
   2204 	if ( oldscope->TypeDef()->Inherits( &type_object ) && !idStr::Icmp( name, "destroy" ) ) {
   2205 		idTypeDef *superClass;
   2206 		function_t *destructorFunc = NULL;
   2207 
   2208 		// find the superclass destructor
   2209 		for( superClass = oldscope->TypeDef()->SuperClass(); superClass != &type_object; superClass = superClass->SuperClass() ) {
   2210 			destructorFunc = gameLocal.program.FindFunction( va( "%s::destroy", superClass->Name() ) );
   2211 			if ( destructorFunc ) {
   2212 				break;
   2213 			}
   2214 		}
   2215 
   2216 		if ( destructorFunc ) {
   2217 			if ( func->firstStatement < gameLocal.program.NumStatements() ) {
   2218 				// change all returns to point to the call to the destructor
   2219 				pos = &gameLocal.program.GetStatement( func->firstStatement );
   2220 				for( i = func->firstStatement; i < gameLocal.program.NumStatements(); i++, pos++ ) {
   2221 					if ( pos->op == OP_RETURN ) {
   2222 						pos->op = OP_GOTO;
   2223 						pos->a = JumpDef( i, gameLocal.program.NumStatements() );
   2224 					}
   2225 				}
   2226 			}
   2227 
   2228 			// emit the call to the destructor
   2229 			idVarDef *selfDef = gameLocal.program.GetDef( type->GetParmType( 0 ), type->GetParmName( 0 ), def );
   2230 			assert( selfDef );
   2231 			EmitPush( selfDef, selfDef->TypeDef() );
   2232 			EmitOpcode( &opcodes[ OP_CALL ], destructorFunc->def, 0 );
   2233 		}
   2234 	}
   2235 
   2236 // Disabled code since it caused a function to fall through to the next function when last statement is in the form "if ( x ) { return; }"
   2237 #if 0
   2238 	// don't bother adding a return opcode if the "return" statement was used.
   2239 	if ( ( func->firstStatement == gameLocal.program.NumStatements() ) || ( gameLocal.program.GetStatement( gameLocal.program.NumStatements() - 1 ).op != OP_RETURN ) ) {
   2240 		// emit an end of statements opcode
   2241 		EmitOpcode( OP_RETURN, 0, 0 );
   2242 	}
   2243 #else
   2244 	// always emit the return opcode
   2245 	EmitOpcode( OP_RETURN, 0, 0 );
   2246 #endif
   2247 
   2248 	// record the number of statements in the function
   2249 	func->numStatements = gameLocal.program.NumStatements() - func->firstStatement;
   2250 
   2251 	scope = oldscope;
   2252 }
   2253 
   2254 /*
   2255 ================
   2256 idCompiler::ParseVariableDef
   2257 ================
   2258 */
   2259 void idCompiler::ParseVariableDef( idTypeDef *type, const char *name ) {
   2260 	idVarDef	*def, *def2;
   2261 	bool		negate;
   2262 
   2263 	def = gameLocal.program.GetDef( type, name, scope );
   2264 	if ( def ) {
   2265 		Error( "%s redeclared", name );
   2266 	}
   2267 	
   2268 	def = gameLocal.program.AllocDef( type, name, scope, false );
   2269 
   2270 	// check for an initialization
   2271 	if ( CheckToken( "=" ) ) {
   2272 		// if a local variable in a function then write out interpreter code to initialize variable
   2273 		if ( scope->Type() == ev_function ) {
   2274 			def2 = GetExpression( TOP_PRIORITY );
   2275 			if ( ( type == &type_float ) && ( def2->TypeDef() == &type_float ) ) {
   2276 				EmitOpcode( OP_STORE_F, def2, def );
   2277 			} else if ( ( type == &type_vector ) && ( def2->TypeDef() == &type_vector ) ) {
   2278 				EmitOpcode( OP_STORE_V, def2, def );
   2279 			} else if ( ( type == &type_string ) && ( def2->TypeDef() == &type_string ) ) {
   2280 				EmitOpcode( OP_STORE_S, def2, def );
   2281 			} else if ( ( type == &type_entity ) && ( ( def2->TypeDef() == &type_entity ) || ( def2->TypeDef()->Inherits( &type_object ) ) ) ) {
   2282 				EmitOpcode( OP_STORE_ENT, def2, def );
   2283 			} else if ( ( type->Inherits( &type_object ) ) && ( def2->TypeDef() == &type_entity ) ) {
   2284 				EmitOpcode( OP_STORE_OBJENT, def2, def );
   2285 			} else if ( ( type->Inherits( &type_object ) ) && ( def2->TypeDef()->Inherits( type ) ) ) {
   2286 				EmitOpcode( OP_STORE_OBJ, def2, def );
   2287 			} else if ( ( type == &type_boolean ) && ( def2->TypeDef() == &type_boolean ) ) {
   2288 				EmitOpcode( OP_STORE_BOOL, def2, def );
   2289 			} else if ( ( type == &type_string ) && ( def2->TypeDef() == &type_float ) ) {
   2290 				EmitOpcode( OP_STORE_FTOS, def2, def );
   2291 			} else if ( ( type == &type_string ) && ( def2->TypeDef() == &type_boolean ) ) {
   2292 				EmitOpcode( OP_STORE_BTOS, def2, def );
   2293 			} else if ( ( type == &type_string ) && ( def2->TypeDef() == &type_vector ) ) {
   2294 				EmitOpcode( OP_STORE_VTOS, def2, def );
   2295 			} else if ( ( type == &type_boolean ) && ( def2->TypeDef() == &type_float ) ) {
   2296 				EmitOpcode( OP_STORE_FTOBOOL, def2, def );
   2297 			} else if ( ( type == &type_float ) && ( def2->TypeDef() == &type_boolean ) ) {
   2298 				EmitOpcode( OP_STORE_BOOLTOF, def2, def );
   2299 			} else {
   2300 				Error( "bad initialization for '%s'", name );
   2301 			}
   2302 		} else {
   2303 			// global variables can only be initialized with immediate values
   2304 			negate = false;
   2305 			if ( token.type == TT_PUNCTUATION && token == "-" ) {
   2306 				negate = true;
   2307 				NextToken();
   2308 				if ( immediateType != &type_float ) {
   2309 					Error( "wrong immediate type for '-' on variable '%s'", name );
   2310 				}
   2311 			}
   2312 
   2313 			if ( immediateType != type ) {
   2314 				Error( "wrong immediate type for '%s'", name );
   2315 			}
   2316 
   2317 			// global variables are initialized at start up
   2318 			if ( type == &type_string ) {
   2319 				def->SetString( token, false );
   2320 			} else {
   2321 				if ( negate ) {
   2322 					immediate._float = -immediate._float;
   2323 				}
   2324 				def->SetValue( immediate, false );
   2325 			}
   2326 			NextToken();
   2327 		}
   2328 	} else if ( type == &type_string ) {
   2329 		// local strings on the stack are initialized in the interpreter
   2330 		if ( scope->Type() != ev_function ) {
   2331 			def->SetString( "", false );
   2332 		}
   2333 	} else if ( type->Inherits( &type_object ) ) {
   2334 		if ( scope->Type() != ev_function ) {
   2335 			def->SetObject( NULL );
   2336 		}
   2337 	}
   2338 }
   2339 
   2340 /*
   2341 ================
   2342 idCompiler::GetTypeForEventArg
   2343 ================
   2344 */
   2345 idTypeDef *idCompiler::GetTypeForEventArg( char argType ) {
   2346 	idTypeDef *type;
   2347 
   2348 	switch( argType ) {
   2349 	case D_EVENT_INTEGER :
   2350 		// this will get converted to int by the interpreter
   2351 		type = &type_float;
   2352 		break;
   2353 
   2354 	case D_EVENT_FLOAT :
   2355 		type = &type_float;
   2356 		break;
   2357 
   2358 	case D_EVENT_VECTOR :
   2359 		type = &type_vector;
   2360 		break;
   2361 
   2362 	case D_EVENT_STRING :
   2363 		type = &type_string;
   2364 		break;
   2365 
   2366 	case D_EVENT_ENTITY :
   2367 	case D_EVENT_ENTITY_NULL :
   2368 		type = &type_entity;
   2369 		break;
   2370 
   2371 	case D_EVENT_VOID :
   2372 		type = &type_void;
   2373 		break;
   2374 
   2375 	case D_EVENT_TRACE :
   2376 		// This data type isn't available from script
   2377 		type = NULL;
   2378 		break;
   2379 
   2380 	default:
   2381 		// probably a typo
   2382 		type = NULL;
   2383 		break;
   2384 	}
   2385 	
   2386 	return type;
   2387 }
   2388 
   2389 /*
   2390 ================
   2391 idCompiler::ParseEventDef
   2392 ================
   2393 */
   2394 void idCompiler::ParseEventDef( idTypeDef *returnType, const char *name ) {
   2395 	const idTypeDef	*expectedType;
   2396 	idTypeDef		*argType;
   2397 	idTypeDef		*type;
   2398 	int 			i;
   2399 	int				num;
   2400 	const char		*format;
   2401 	const idEventDef *ev;
   2402 	idStr			parmName;
   2403 
   2404 	ev = idEventDef::FindEvent( name );
   2405 	if ( ev == NULL ) {
   2406 		Error( "Unknown event '%s'", name );
   2407 		return;
   2408 	}
   2409 
   2410 	// set the return type
   2411 	expectedType = GetTypeForEventArg( ev->GetReturnType() );
   2412 	if ( expectedType == NULL ) {
   2413 		Error( "Invalid return type '%c' in definition of '%s' event.", ev->GetReturnType(), name );
   2414 		return;
   2415 	}
   2416 	if ( returnType != expectedType ) {
   2417 		Error( "Return type doesn't match internal return type '%s'", expectedType->Name() );
   2418 	}
   2419 
   2420 	idTypeDef newtype( ev_function, NULL, name, type_function.Size(), returnType );
   2421 
   2422 	ExpectToken( "(" );
   2423 
   2424 	format = ev->GetArgFormat();
   2425 	num = strlen( format );
   2426 	for( i = 0; i < num; i++ ) {
   2427 		expectedType = GetTypeForEventArg( format[ i ] );
   2428 		if ( expectedType == NULL || ( expectedType == &type_void ) ) {
   2429 			Error( "Invalid parameter '%c' in definition of '%s' event.", format[ i ], name );
   2430 			return;
   2431 		}
   2432 
   2433 		argType = ParseType();
   2434 		ParseName( parmName );
   2435 		if ( argType != expectedType ) {
   2436 			Error( "The type of parm %d ('%s') does not match the internal type '%s' in definition of '%s' event.", 
   2437 				i + 1, parmName.c_str(), expectedType->Name(), name );
   2438 		}
   2439 
   2440 		newtype.AddFunctionParm( argType, "" );
   2441 
   2442 		if ( i < num - 1 ) {
   2443 			if ( CheckToken( ")" ) ) {
   2444 				Error( "Too few parameters for event definition.  Internal definition has %d parameters.", num );
   2445 			}
   2446 			ExpectToken( "," );
   2447 		}
   2448 	}
   2449 	if ( !CheckToken( ")" ) ) {
   2450 		Error( "Too many parameters for event definition.  Internal definition has %d parameters.", num );
   2451 	}
   2452 	ExpectToken( ";" );
   2453 
   2454 	type = gameLocal.program.FindType( name );
   2455 	if ( type ) {
   2456 		if ( !newtype.MatchesType( *type ) || ( type->def->value.functionPtr->eventdef != ev ) ) {
   2457 			Error( "Type mismatch on redefinition of '%s'", name );
   2458 		}
   2459 	} else {
   2460 		type = gameLocal.program.AllocType( newtype );
   2461 		type->def = gameLocal.program.AllocDef( type, name, &def_namespace, true );
   2462 
   2463 		function_t &func	= gameLocal.program.AllocFunction( type->def );
   2464 		func.eventdef		= ev;
   2465 		func.parmSize.SetNum( num );
   2466 		for( i = 0; i < num; i++ ) {
   2467 			argType = newtype.GetParmType( i );
   2468 			func.parmTotal		+= argType->Size();
   2469 			func.parmSize[ i ]	= argType->Size();
   2470 		}
   2471 
   2472 		// mark the parms as local
   2473 		func.locals	= func.parmTotal;
   2474 	}
   2475 }
   2476 
   2477 /*
   2478 ================
   2479 idCompiler::ParseDefs
   2480 
   2481 Called at the outer layer and when a local statement is hit
   2482 ================
   2483 */
   2484 void idCompiler::ParseDefs() {
   2485 	idStr 		name;
   2486 	idTypeDef	*type;
   2487 	idVarDef	*def;
   2488 	idVarDef	*oldscope;
   2489 
   2490 	if ( CheckToken( ";" ) ) {
   2491 		// skip semicolons, which are harmless and ok syntax
   2492 		return;
   2493 	}
   2494 
   2495 	type = ParseType();
   2496 	if ( type == &type_scriptevent ) {
   2497 		type = ParseType();
   2498 		ParseName( name );
   2499 		ParseEventDef( type, name );
   2500 		return;
   2501 	}
   2502     
   2503 	ParseName( name );
   2504 
   2505 	if ( type == &type_namespace ) {
   2506 		def = gameLocal.program.GetDef( type, name, scope );
   2507 		if ( !def ) {
   2508 			def = gameLocal.program.AllocDef( type, name, scope, true );
   2509 		}
   2510 		ParseNamespace( def );
   2511 	} else if ( CheckToken( "::" ) ) {
   2512 		def = gameLocal.program.GetDef( NULL, name, scope );
   2513 		if ( !def ) {
   2514 			Error( "Unknown object name '%s'", name.c_str() );
   2515 		}
   2516 		ParseName( name );
   2517 		oldscope = scope;
   2518 		scope = def;
   2519 
   2520 		ExpectToken( "(" );
   2521 		ParseFunctionDef( type, name.c_str() );
   2522 		scope = oldscope;
   2523 	} else if ( type == &type_object ) {
   2524 		ParseObjectDef( name.c_str() );
   2525 	} else if ( CheckToken( "(" ) ) {		// check for a function prototype or declaraction
   2526 		ParseFunctionDef( type, name.c_str() );
   2527 	} else {
   2528 		ParseVariableDef( type, name.c_str() );
   2529 		while( CheckToken( "," ) ) {
   2530 			ParseName( name );
   2531 			ParseVariableDef( type, name.c_str() );
   2532 		}
   2533 		ExpectToken( ";" );
   2534 	}
   2535 }
   2536 
   2537 /*
   2538 ================
   2539 idCompiler::ParseNamespace
   2540 
   2541 Parses anything within a namespace definition
   2542 ================
   2543 */
   2544 void idCompiler::ParseNamespace( idVarDef *newScope ) {
   2545 	idVarDef *oldscope;
   2546 
   2547 	oldscope = scope;
   2548 	if ( newScope != &def_namespace ) {
   2549 		ExpectToken( "{" );
   2550 	}
   2551 
   2552 	while( !eof ) {
   2553 		scope		= newScope;
   2554 		callthread	= false;
   2555 
   2556 		if ( ( newScope != &def_namespace ) && CheckToken( "}" ) ) {
   2557 			break;
   2558 		}
   2559 
   2560 		ParseDefs();
   2561 	}
   2562 
   2563 	scope = oldscope;
   2564 }
   2565 
   2566 /*
   2567 ============
   2568 idCompiler::CompileFile
   2569 
   2570 compiles the 0 terminated text, adding definitions to the program structure
   2571 ============
   2572 */
   2573 void idCompiler::CompileFile( const char *text, const char *filename, bool toConsole ) {
   2574 	idTimer compile_time;
   2575 	bool error;
   2576 
   2577 	compile_time.Start();
   2578 
   2579 	scope				= &def_namespace;
   2580 	basetype			= NULL;
   2581 	callthread			= false;
   2582 	loopDepth			= 0;
   2583 	eof					= false;
   2584 	braceDepth			= 0;
   2585 	immediateType		= NULL;
   2586 	currentLineNumber	= 0;
   2587 	console				= toConsole;
   2588 	
   2589 	memset( &immediate, 0, sizeof( immediate ) );
   2590 
   2591 	parser.SetFlags( LEXFL_ALLOWMULTICHARLITERALS );
   2592 	parser.LoadMemory( text, strlen( text ), filename );
   2593 	parserPtr = &parser;
   2594 
   2595 	// unread tokens to include script defines
   2596 	token = SCRIPT_DEFAULTDEFS;
   2597 	token.type = TT_STRING;
   2598 	token.subtype = token.Length();
   2599 	token.line = token.linesCrossed = 0;
   2600 	parser.UnreadToken( &token );
   2601 
   2602 	token = "include";
   2603 	token.type = TT_NAME;
   2604 	token.subtype = token.Length();
   2605 	token.line = token.linesCrossed = 0;
   2606 	parser.UnreadToken( &token );
   2607 
   2608 	token = "#";
   2609 	token.type = TT_PUNCTUATION;
   2610 	token.subtype = P_PRECOMP;
   2611 	token.line = token.linesCrossed = 0;
   2612 	parser.UnreadToken( &token );
   2613 
   2614 	// init the current token line to be the first line so that currentLineNumber is set correctly in NextToken
   2615 	token.line = 1;
   2616 
   2617 	error = false;
   2618 	try {
   2619 		// read first token
   2620 		NextToken();
   2621 		while( !eof && !error ) {
   2622 			// parse from global namespace
   2623 			ParseNamespace( &def_namespace );
   2624 		}
   2625 	}
   2626 		
   2627 	catch( idCompileError &err ) {
   2628 		idStr error;
   2629 
   2630 		if ( console ) {
   2631 			// don't print line number of an error if were calling script from the console using the "script" command
   2632 			sprintf( error, "Error: %s\n", err.GetError() );
   2633 		} else {
   2634 			sprintf( error, "Error: file %s, line %d: %s\n", gameLocal.program.GetFilename( currentFileNumber ), currentLineNumber, err.GetError() );
   2635 		}
   2636 
   2637 		parser.FreeSource();
   2638 
   2639 		throw idCompileError( error );
   2640 	}
   2641 
   2642 	parser.FreeSource();
   2643 
   2644 	compile_time.Stop();
   2645 	if ( !toConsole ) {
   2646 		gameLocal.Printf( "Compiled '%s': %.1f ms\n", filename, compile_time.Milliseconds() );
   2647 	}
   2648 }