/* ================ idTypeDef::PointerType If type is a pointer, then returns the type it points to ================ */ idTypeDef *idTypeDef::PointerType( void ) const { if ( type != ev_pointer ) { throw idCompileError( "idTypeDef::PointerType: tried to get pointer type on non-pointer" ); } return auxType; }
/* ================ idTypeDef::SetPointerType If type is a pointer, then sets the pointer's type ================ */ void idTypeDef::SetPointerType( idTypeDef *pointertype ) { if ( type != ev_pointer ) { throw idCompileError( "idTypeDef::SetPointerType: tried to set type on non-pointer" ); } auxType = pointertype; }
/* ================ idTypeDef::FieldType If type is a field, then returns it's type ================ */ idTypeDef *idTypeDef::FieldType( void ) const { if ( type != ev_field ) { throw idCompileError( "idTypeDef::FieldType: tried to get field type on non-field type" ); } return auxType; }
/* ================ idTypeDef::SetFieldType If type is a field, then sets the function's return type ================ */ void idTypeDef::SetFieldType( idTypeDef *fieldtype ) { if ( type != ev_field ) { throw idCompileError( "idTypeDef::SetFieldType: tried to set return type on non-function type" ); } auxType = fieldtype; }
/* ================ idTypeDef::ReturnType If type is a function, then returns the function's return type ================ */ idTypeDef *idTypeDef::ReturnType( void ) const { if ( type != ev_function ) { throw idCompileError( "idTypeDef::ReturnType: tried to get return type on non-function type" ); } return auxType; }
/* ================ idTypeDef::SetReturnType If type is a function, then sets the function's return type ================ */ void idTypeDef::SetReturnType( idTypeDef *returntype ) { if ( type != ev_function ) { throw idCompileError( "idTypeDef::SetReturnType: tried to set return type on non-function type" ); } auxType = returntype; }
/* ================ idTypeDef::SuperClass If type is an object, then returns the object's superclass ================ */ idTypeDef *idTypeDef::SuperClass( void ) const { if ( type != ev_object ) { throw idCompileError( "idTypeDef::SuperClass : tried to get superclass of a non-object type" ); } return auxType; }
/* ============ idProgram::GetDef If type is NULL, it will match any type ============ */ idVarDef *idProgram::GetDef( const idTypeDef *type, const char *name, const idVarDef *scope ) const { idVarDef *def; idVarDef *bestDef; int bestDepth; int depth; bestDepth = 0; bestDef = NULL; for( def = GetDefList( name ); def != NULL; def = def->Next() ) { if ( def->scope->Type() == ev_namespace ) { depth = def->DepthOfScope( scope ); if ( !depth ) { // not in the same namespace continue; } } else if ( def->scope != scope ) { // in a different function continue; } else { depth = 1; } if ( !bestDef || ( depth < bestDepth ) ) { bestDepth = depth; bestDef = def; } } // see if the name is already in use for another type if ( bestDef && type && ( bestDef->TypeDef() != type ) ) { throw idCompileError( va( "Type mismatch on redeclaration of %s", name ) ); } return bestDef; }
/* ================ idProgram::AllocStatement ================ */ statement_t *idProgram::AllocStatement( void ) { if( statements.Num() >= statements.Max() ) { throw idCompileError( va( "Exceeded maximum allowed number of statements (%d)", statements.Max() ) ); } return statements.Alloc(); }
/* ============ idVarDef::SetValue ============ */ void idVarDef::SetValue( const eval_t &_value, bool constant ) { assert( typeDef ); if ( constant ) { initialized = initializedConstant; } else { initialized = initializedVariable; } switch( typeDef->Type() ) { case ev_pointer : case ev_boolean : case ev_field : *value.intPtr = _value._int; break; case ev_jumpoffset : value.jumpOffset = _value._int; break; case ev_argsize : value.argSize = _value._int; break; case ev_entity : *value.entityNumberPtr = _value.entity; break; case ev_string : idStr::Copynz( value.stringPtr, _value.stringPtr, MAX_STRING_LEN ); break; case ev_float : *value.floatPtr = _value._float; break; case ev_vector : value.vectorPtr->x = _value.vector[ 0 ]; value.vectorPtr->y = _value.vector[ 1 ]; value.vectorPtr->z = _value.vector[ 2 ]; break; case ev_function : value.functionPtr = _value.function; break; case ev_virtualfunction : value.virtualFunction = _value._int; break; case ev_object : *value.entityNumberPtr = _value.entity; break; default : throw idCompileError( va( "weird type on '%s'", Name() ) ); break; } }
/* ================ idTypeDef::AddFunctionParm Adds a new parameter for a function type. ================ */ void idTypeDef::AddFunctionParm( idTypeDef *parmtype, const char *name ) { if ( type != ev_function ) { throw idCompileError( "idTypeDef::AddFunctionParm : tried to add parameter on non-function type" ); } parmTypes.Append( parmtype ); idStr &parmName = parmNames.Alloc(); parmName = name; }
/* ================ idProgram::CompileText ================ */ bool idProgram::CompileText( const char *source, const char *text, bool console ) { idCompiler compiler; int i; idVarDef *def; idStr ospath; // use a full os path for GetFilenum since it calls OSPathToRelativePath to convert filenames from the parser ospath = fileSystem->RelativePathToOSPath( source ); filenum = GetFilenum( ospath ); try { compiler.CompileFile( text, filename, console ); // check to make sure all functions prototyped have code for( i = 0; i < varDefs.Num(); i++ ) { def = varDefs[ i ]; if( ( def->Type() == ev_function ) && ( ( def->scope->Type() == ev_namespace ) || def->scope->TypeDef()->Inherits( &type_object ) ) ) { if( !def->value.functionPtr->eventdef && !def->value.functionPtr->firstStatement ) { throw idCompileError( va( "function %s was not defined\n", def->GlobalName() ) ); } } } } catch( idCompileError &err ) { if( console ) { gameLocal.Printf( "%s\n", err.error ); return false; } else { gameLocal.Error( "%s\n", err.error ); } }; if( !console ) { CompileStats(); } return true; }
/* ================ idTypeDef::AddField Adds a new field to an object type. ================ */ void idTypeDef::AddField( idTypeDef *fieldtype, const char *name ) { if ( type != ev_object ) { throw idCompileError( "idTypeDef::AddField : tried to add field to non-object type" ); } parmTypes.Append( fieldtype ); idStr &parmName = parmNames.Alloc(); parmName = name; if ( fieldtype->FieldType()->Inherits( &type_object ) ) { size += type_object.Size(); } else { size += fieldtype->FieldType()->Size(); } }
/* ================ idProgram::AllocFunction ================ */ function_t &idProgram::AllocFunction( idVarDef *def ) { if ( functions.Num() >= functions.Max() ) { throw idCompileError( va( "Exceeded maximum allowed number of functions (%d)", functions.Max() ) ); } // fill in the dfunction function_t &func = *functions.Alloc(); func.eventdef = NULL; func.def = def; func.type = def->TypeDef(); func.firstStatement = 0; func.numStatements = 0; func.parmTotal = 0; func.locals = 0; func.filenum = filenum; func.parmSize.SetGranularity( 1 ); func.SetName( def->GlobalName() ); def->SetFunction( &func ); return func; }
/* ============ idProgram::AllocDef ============ */ idVarDef *idProgram::AllocDef( idTypeDef *type, const char *name, idVarDef *scope, bool constant ) { idVarDef *def; idStr element; idVarDef *def_x; idVarDef *def_y; idVarDef *def_z; // allocate a new def def = new idVarDef( type ); def->scope = scope; def->numUsers = 1; def->num = varDefs.Append( def ); // add the def to the list with defs with this name and set the name pointer AddDefToNameList( def, name ); if( ( type->Type() == ev_vector ) || ( ( type->Type() == ev_field ) && ( type->FieldType()->Type() == ev_vector ) ) ) { // // vector // if( !strcmp( name, RESULT_STRING ) ) { // <RESULT> vector defs don't need the _x, _y and _z components assert( scope->Type() == ev_function ); def->value.stackOffset = scope->value.functionPtr->locals; def->initialized = idVarDef::stackVariable; scope->value.functionPtr->locals += type->Size(); } else if( scope->TypeDef()->Inherits( &type_object ) ) { idTypeDef newtype( ev_field, NULL, "float field", 0, &type_float ); idTypeDef *type = GetType( newtype, true ); // set the value to the variable's position in the object def->value.ptrOffset = scope->TypeDef()->Size(); // make automatic defs for the vectors elements // origin can be accessed as origin_x, origin_y, and origin_z sprintf( element, "%s_x", def->Name() ); def_x = AllocDef( type, element, scope, constant ); sprintf( element, "%s_y", def->Name() ); def_y = AllocDef( type, element, scope, constant ); def_y->value.ptrOffset = def_x->value.ptrOffset + type_float.Size(); sprintf( element, "%s_z", def->Name() ); def_z = AllocDef( type, element, scope, constant ); def_z->value.ptrOffset = def_y->value.ptrOffset + type_float.Size(); } else { // make automatic defs for the vectors elements // origin can be accessed as origin_x, origin_y, and origin_z sprintf( element, "%s_x", def->Name() ); def_x = AllocDef( &type_float, element, scope, constant ); sprintf( element, "%s_y", def->Name() ); def_y = AllocDef( &type_float, element, scope, constant ); sprintf( element, "%s_z", def->Name() ); def_z = AllocDef( &type_float, element, scope, constant ); // point the vector def to the x coordinate def->value = def_x->value; def->initialized = def_x->initialized; } } else if( scope->TypeDef()->Inherits( &type_object ) ) { // // object variable // // set the value to the variable's position in the object def->value.ptrOffset = scope->TypeDef()->Size(); } else if( scope->Type() == ev_function ) { // // stack variable // // since we don't know how many local variables there are, // we have to have them go backwards on the stack def->value.stackOffset = scope->value.functionPtr->locals; def->initialized = idVarDef::stackVariable; if( type->Inherits( &type_object ) ) { // objects only have their entity number on the stack, not the entire object scope->value.functionPtr->locals += type_object.Size(); } else { scope->value.functionPtr->locals += type->Size(); } } else { // // global variable // def->value.bytePtr = &variables[ numVariables ]; numVariables += def->TypeDef()->Size(); if( numVariables > sizeof( variables ) ) { throw idCompileError( va( "Exceeded global memory size (%d bytes)", sizeof( variables ) ) ); } memset( def->value.bytePtr, 0, def->TypeDef()->Size() ); } return def; }