Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // Compile a declaration in Token. Returns 1 if compiled, 0 if not.
- //
- INT FScriptCompiler::CompileDeclaration( FToken& Token, UBOOL& NeedSemicolon )
- {
- if( Token.Matches(NAME_Class) && (TopNest->Allow & ALLOW_Class) )
- {
- // Start of a class block.
- CheckAllow( TEXT("'class'"), ALLOW_Class );
- // Class name.
- if( !GetToken(Token) )
- appThrowf( TEXT("Missing class name") );
- if( appIsDigit( **FString(Token.Identifier).Right(1) ) )
- Warn->Logf( NAME_Warning, TEXT("Class names shouldn't end in a digit"), Token.Identifier );
- if( !Token.Matches(Class->GetName()) )
- appThrowf( TEXT("Class must be named %s, not %s"), Class->GetName(), Token.Identifier );
- // Get parent class.
- if( MatchIdentifier(NAME_Extends) )
- {
- // Set the superclass.
- UClass* TempClass = GetQualifiedClass( TEXT("'extends'") );
- if( Class->GetSuperClass() == NULL )
- Class->SuperField = TempClass;
- else if( Class->GetSuperClass() != TempClass )
- appThrowf( TEXT("%s's superclass must be %s, not %s"), *Class->GetPathName(), *Class->GetSuperClass()->GetPathName(), *TempClass->GetPathName() );
- Class->MinAlignment = Max(Class->MinAlignment,TempClass->MinAlignment);
- }
- else if( Class->GetSuperClass() )
- appThrowf( TEXT("class: missing 'Extends %s'"), Class->GetSuperClass()->GetName() );
- // Get outer class.
- if( MatchIdentifier(NAME_Within) )
- {
- // Set the outer class.
- UClass* TempClass = GetQualifiedClass( TEXT("'within'") );
- if( Class->ClassWithin == NULL || Class->ClassWithin==UObject::StaticClass() )
- Class->ClassWithin = TempClass;
- else if( Class->ClassWithin != TempClass )
- appThrowf( TEXT("%s must be within %s, not %s"), *Class->GetPathName(), *Class->ClassWithin->GetPathName(), *TempClass->GetPathName() );
- }
- else Class->ClassWithin = Class->GetSuperClass() ? Class->GetSuperClass()->ClassWithin : UObject::StaticClass();
- UClass* ExpectedWithin = Class->GetSuperClass() ? Class->GetSuperClass()->ClassWithin : UObject::StaticClass();
- if( !Class->ClassWithin->IsChildOf(ExpectedWithin) )
- appThrowf( TEXT("'within': within %s is not a generalization of superclass within '%s'"), Class->ClassWithin->GetName(), ExpectedWithin->GetName() );
- // Keep track of whether "config(ini)" was used.
- UBOOL DeclaresConfigFile = 0;
- // Class attributes.
- FToken Token;
- for( ; ; )
- {
- GetToken(Token);
- if( Token.Matches(NAME_Intrinsic) || Token.Matches(NAME_Native) )//oldver
- {
- // Note that this class has C++ code dependencies.
- if( Class->GetSuperClass() && !(Class->GetSuperClass()->GetFlags() & RF_Native) )
- appThrowf( TEXT("Native classes cannot expand non-native classes") );
- Class->SetFlags( RF_Native );
- // Parse an optional class header filename.
- if( MatchSymbol(TEXT("(")) )
- {
- FToken Token;
- if( !GetIdentifier(Token, 0) )
- appThrowf( TEXT("native: Missing native header filename") );
- Class->ClassHeaderFilename = Token.Identifier;
- RequireSymbol(TEXT(")"), TEXT("native") );
- }
- }
- else if( Token.Matches(NAME_NoExport) )
- {
- // Don't export to C++ header.
- Class->ClassFlags |= CLASS_NoExport;
- }
- else if( Token.Matches(NAME_EditInlineNew) )
- {
- // Class can be constructed from the New button in editinline
- Class->ClassFlags |= CLASS_EditInlineNew;
- }
- else if( Token.Matches(NAME_NotEditInlineNew) )
- {
- // Class cannot be constructed from the New button in editinline
- Class->ClassFlags &= ~CLASS_EditInlineNew;
- }
- else if( Token.Matches(NAME_Placeable) )
- {
- // Allow the class to be placed in the editor.
- Class->ClassFlags |= CLASS_Placeable;
- }
- else if( Token.Matches(NAME_NotPlaceable) )
- {
- // Allow the class to be placed in the editor.
- if ( Class->ClassFlags & CLASS_Placeable )
- Class->ClassFlags -= CLASS_Placeable;
- }
- else if( Token.Matches(NAME_HideDropDown) )
- {
- // Prevents class from appearing in class comboboxes in the property window
- Class->ClassFlags |= CLASS_HideDropDown;
- }
- else if( Token.Matches(NAME_NativeReplication) )
- {
- // Replication is native.
- Class->ClassFlags |= CLASS_NativeReplication;
- }
- else if( Token.Matches(NAME_DependsOn) )
- {
- RequireSymbol(TEXT("("), TEXT("dependsOn") );
- FToken Token;
- if( !GetIdentifier(Token, 0) )
- appThrowf( TEXT("dependsOn: Missing dependent name") );
- RequireSymbol(TEXT(")"), TEXT("dependsOn") );
- }
- else if( Token.Matches(NAME_PerObjectConfig) )
- {
- // Don't export to C++ header.
- Class->ClassFlags |= CLASS_PerObjectConfig;
- }
- else if( Token.Matches(NAME_Abstract) )
- {
- // Hide all editable properties.
- Class->ClassFlags |= CLASS_Abstract;
- }
- else if ( Token.Matches(NAME_Deprecated) )
- {
- Class->ClassFlags |= CLASS_Deprecated;
- }
- else if( Token.Matches(NAME_Guid) )
- {
- // Get the class's GUID.
- RequireSymbol( TEXT("("), TEXT("'Guid'") );
- GetConstInt(*(INT*)&Class->ClassGuid.A);
- RequireSymbol( TEXT(","), TEXT("'Guid'") );
- GetConstInt(*(INT*)&Class->ClassGuid.B);
- RequireSymbol( TEXT(","), TEXT("'Guid'") );
- GetConstInt(*(INT*)&Class->ClassGuid.C);
- RequireSymbol( TEXT(","), TEXT("'Guid'") );
- GetConstInt(*(INT*)&Class->ClassGuid.D);
- RequireSymbol( TEXT(")"), TEXT("'Guid'") );
- }
- else if( Token.Matches(NAME_Transient) )
- {
- // Transient class.
- Class->ClassFlags |= CLASS_Transient;
- }
- else if( Token.Matches(NAME_Localized) )
- {
- // Localized class.
- //oldver
- appThrowf( TEXT("Class 'localized' keyword is no longer required") );
- }
- else if( Token.Matches(NAME_Config) )
- {
- // Transient class.
- if( MatchSymbol(TEXT("(")) )
- {
- FToken Token;
- if( !GetIdentifier(Token, 0) )
- appThrowf( TEXT("config: Missing configuration name") );
- Class->ClassConfigName = Token.Identifier;
- RequireSymbol(TEXT(")"), TEXT("config") );
- DeclaresConfigFile = 1;
- }
- else
- appThrowf( TEXT("config: Missing configuration name") );
- }
- else if( Token.Matches(NAME_SafeReplace) )
- {
- // Safely replaceable.
- Class->ClassFlags |= CLASS_SafeReplace;
- }
- else if( Token.Matches(NAME_HideCategories) )
- {
- RequireSymbol( TEXT("("), TEXT("'HideCategories'") );
- do
- {
- FToken Category;
- if( !GetIdentifier( Category, 1 ) )
- appThrowf( TEXT("HideCategories: Expected category name") );
- Class->HideCategories.AddItem( FName( Category.Identifier ) );
- }
- while( MatchSymbol(TEXT(",")) );
- RequireSymbol( TEXT(")"), TEXT("'HideCategories'") );
- }
- else if( Token.Matches(NAME_AutoExpandCategories) )
- {
- RequireSymbol( TEXT("("), TEXT("'AutoExpandCategories'") );
- do
- {
- FToken Category;
- if( !GetIdentifier( Category, 1 ) )
- appThrowf( TEXT("AutoExpandCategories: Expected category name") );
- Class->AutoExpandCategories.AddItem( FName( Category.Identifier ) );
- }
- while( MatchSymbol(TEXT(",")) );
- RequireSymbol( TEXT(")"), TEXT("'AutoExpandCategories'") );
- }
- else if( Token.Matches(NAME_ShowCategories) )
- {
- RequireSymbol( TEXT("("), TEXT("'ShowCategories'") );
- do
- {
- FToken Category;
- if( !GetIdentifier( Category, 1 ) )
- appThrowf( TEXT("ShowCategories: Expected category name") );
- Class->HideCategories.RemoveItem( FName( Category.Identifier ) );
- }
- while( MatchSymbol(TEXT(",")) );
- RequireSymbol( TEXT(")"), TEXT("'ShowCategories'") );
- }
- else if( Token.Matches(NAME_CollapseCategories) )
- {
- // Class' properties should not be shown categorized in the editor.
- Class->ClassFlags |= CLASS_CollapseCategories;
- }
- else if( Token.Matches(NAME_DontCollapseCategories) )
- {
- // Class' properties should be shown categorized in the editor.
- Class->ClassFlags &= ~CLASS_CollapseCategories;
- }
- else
- {
- UngetToken(Token);
- break;
- }
- }
- // Validate.
- if( (Class->ClassFlags&CLASS_NoExport) && !(Class->GetFlags()&RF_Native) )
- appThrowf( TEXT("'noexport': Only valid for native classes") );
- // Invalidate config name if not specifically declared.
- if( !DeclaresConfigFile )
- Class->ClassConfigName = NAME_None;
- // Get semicolon.
- RequireSymbol( TEXT(";"), TEXT("'Class'") );
- NeedSemicolon=0;
- // Init variables.
- Class->Script.Empty();
- Class->Children = NULL;
- Class->Next = NULL;
- Class->ProbeMask = 0;
- Class->IgnoreMask = 0;
- Class->StateFlags = 0;
- Class->LabelTableOffset = 0;
- Class->NetFields.Empty();
- // Make visible outside the package.
- Class->ClearFlags( RF_Transient );
- check(Class->GetFlags()&RF_Public);
- check(Class->GetFlags()&RF_Standalone);
- // Setup initial package imports to include the packages and the package imports
- // of all base classes.
- Class->PackageImports.Empty();
- for( UClass* C = Class; C; C=C->GetSuperClass() )
- {
- Class->PackageImports.AddUniqueItem( C->GetOuter()->GetFName() );
- for( INT i=0; i<C->PackageImports.Num(); i++ )
- Class->PackageImports.AddUniqueItem( C->PackageImports( i ) );
- }
- // Copy properties from parent class.
- Class->Defaults.Empty();
- if( Class->GetSuperClass() )
- {
- Class->SetPropertiesSize( Class->GetSuperClass()->GetPropertiesSize() );
- Class->Defaults = Class->GetSuperClass()->Defaults;
- }
- // Push the class nesting.
- PushNest( NEST_Class, Class->GetName(), NULL );
- }
- else if( Token.Matches(NAME_Import) )
- {
- CheckAllow( TEXT("'Uses'"), ALLOW_VarDecl );
- if( TopNest->NestType != NEST_Class )
- appThrowf( TEXT("'Uses' is are only allowed at class scope") );
- // Get thing to import.
- FToken ImportThing;
- GetToken( ImportThing );
- if( !ImportThing.Matches(NAME_Enum) && !ImportThing.Matches(NAME_Package) )
- appThrowf( TEXT("'import': Missing 'enum', 'struct', or 'package'") );
- // Get name to import.
- FToken ImportName;
- if( !GetIdentifier(ImportName) )
- appThrowf( TEXT("'import': Missing package, enum, or struct name to import") );
- // Handle package, enum, or struct.
- if( ImportThing.Matches(NAME_Package) )
- {
- // Import a package.
- Class->PackageImports.AddUniqueItem( FName(ImportName.Identifier) );
- }
- else if( ImportThing.Matches(NAME_Enum) )
- {
- // From package.
- UPackage* Pkg = CastChecked<UPackage>(Class->GetOuter());
- if( MatchIdentifier(NAME_From) )
- {
- FToken ImportPackage;
- if( GetIdentifier( ImportPackage ) )
- {
- Pkg = FindObject<UPackage>( NULL, ImportPackage.Identifier );
- if( !Pkg )
- appThrowf( TEXT("'Uses': Unrecognized package '%s'"), ImportPackage.Identifier );
- }
- }
- else appThrowf( TEXT("'Uses': Unrecognized '%s'"), ImportThing.Identifier );
- new( Pkg, ImportName.Identifier )UEnum( NULL );
- }
- }
- else if
- ( Token.Matches(NAME_Function)
- || Token.Matches(NAME_Operator)
- || Token.Matches(NAME_PreOperator)
- || Token.Matches(NAME_PostOperator)
- || Token.Matches(NAME_Intrinsic) //oldver
- || Token.Matches(NAME_Native)
- || Token.Matches(NAME_Final)
- || Token.Matches(NAME_Private)
- || Token.Matches(NAME_Protected)
- || Token.Matches(NAME_Public)
- || Token.Matches(NAME_Latent)
- || Token.Matches(NAME_Iterator)
- || Token.Matches(NAME_Singular)
- || Token.Matches(NAME_Static)
- || Token.Matches(NAME_Exec)
- || Token.Matches(NAME_Delegate)
- || (Token.Matches(NAME_Event) && (TopNest->Allow & ALLOW_Function) )
- || (Token.Matches(NAME_Simulated) && !PeekIdentifier(NAME_State)) )
- {
- // Function or operator.
- const TCHAR* NestName = NULL;
- FRetryPoint FuncNameRetry;
- FFuncInfo FuncInfo;
- FuncInfo.FunctionFlags = FUNC_Public;
- UStruct* Scope = TopNode;
- // Process all specifiers.
- for( ;; )
- {
- InitRetry(FuncNameRetry);
- if( Token.Matches(NAME_Function) )
- {
- // Get function name.
- CheckAllow( TEXT("'Function'"),ALLOW_Function);
- NestName = TEXT("function");
- }
- else if( Token.Matches(NAME_Operator) )
- {
- // Get operator name or symbol.
- CheckAllow( TEXT("'Operator'"), ALLOW_Function );
- NestName = TEXT("operator");
- FuncInfo.FunctionFlags |= FUNC_Operator;
- FuncInfo.ExpectParms = 3;
- if( !MatchSymbol(TEXT("(")) )
- appThrowf( TEXT("Missing '(' and precedence after 'Operator'") );
- else if( !GetConstInt(FuncInfo.Precedence) )
- appThrowf( TEXT("Missing precedence value") );
- else if( FuncInfo.Precedence<0 || FuncInfo.Precedence>255 )
- appThrowf( TEXT("Bad precedence value") );
- else if( !MatchSymbol(TEXT(")")) )
- appThrowf( TEXT("Missing ')' after operator precedence") );
- }
- else if( Token.Matches(NAME_PreOperator) )
- {
- // Get operator name or symbol.
- CheckAllow( TEXT("'PreOperator'"), ALLOW_Function );
- NestName = TEXT("preoperator");
- FuncInfo.ExpectParms = 2;
- FuncInfo.FunctionFlags |= FUNC_Operator | FUNC_PreOperator;
- }
- else if( Token.Matches(NAME_PostOperator) )
- {
- // Get operator name or symbol.
- CheckAllow( TEXT("'PostOperator'"), ALLOW_Function );
- NestName = TEXT("postoperator");
- FuncInfo.FunctionFlags |= FUNC_Operator;
- FuncInfo.ExpectParms = 2;
- }
- else if( Token.Matches(NAME_Intrinsic) || Token.Matches(NAME_Native) )//oldver
- {
- // Get internal id.
- FuncInfo.FunctionFlags |= FUNC_Native;
- if( MatchSymbol(TEXT("(")) )
- {
- if( !GetConstInt(FuncInfo.iNative) )
- appThrowf( TEXT("Missing native id") );
- else if( !MatchSymbol(TEXT(")")) )
- appThrowf( TEXT("Missing ')' after internal id") );
- }
- }
- else if( Token.Matches(NAME_Event) )
- {
- CheckAllow( TEXT("'Function'"), ALLOW_Function );
- NestName = TEXT("event");
- FuncInfo.FunctionFlags |= FUNC_Event;
- }
- else if( Token.Matches(NAME_Static) )
- {
- FuncInfo.FunctionFlags |= FUNC_Static;
- if( TopNode->GetClass()==UState::StaticClass() )
- appThrowf( TEXT("Static functions cannot exist in a state") );
- }
- else if( Token.Matches(NAME_Simulated) )
- {
- FuncInfo.FunctionFlags |= FUNC_Simulated;
- }
- else if( Token.Matches(NAME_Iterator) )
- {
- FuncInfo.FunctionFlags |= FUNC_Iterator;
- }
- else if( Token.Matches(NAME_Singular) )
- {
- FuncInfo.FunctionFlags |= FUNC_Singular;
- }
- else if( Token.Matches(NAME_Latent) )
- {
- FuncInfo.FunctionFlags |= FUNC_Latent;
- }
- else if( Token.Matches(NAME_Exec) )
- {
- FuncInfo.FunctionFlags |= FUNC_Exec;
- }
- else if( Token.Matches(NAME_Delegate) )
- {
- CheckAllow( TEXT("'Function'"),ALLOW_Function);
- NestName = TEXT("delegate");
- FuncInfo.FunctionFlags |= FUNC_Delegate;
- }
- else if( Token.Matches(NAME_Final) )
- {
- // This is a final (prebinding, non-overridable) function or operator.
- FuncInfo.FunctionFlags |= FUNC_Final;
- }
- else if( Token.Matches(NAME_Private) )
- {
- FuncInfo.FunctionFlags &= ~FUNC_Public;
- FuncInfo.FunctionFlags |= FUNC_Private;
- }
- else if( Token.Matches(NAME_Protected) )
- {
- FuncInfo.FunctionFlags &= ~FUNC_Public;
- FuncInfo.FunctionFlags |= FUNC_Protected;
- }
- else if( Token.Matches(NAME_Public) )
- {
- FuncInfo.FunctionFlags |= FUNC_Public;
- }
- else break;
- GetToken(Token);
- }
- UngetToken(Token);
- // Make sure we got a function.
- if( !NestName )
- appThrowf( TEXT("Missing 'function'") );
- // Warn if native doesn't actually exist.
- #if CHECK_NATIVE_MATCH
- if( FuncInfo.iNative!=0 )
- if( FuncInfo.iNative<EX_FirstNative || FuncInfo.iNative>EX_Max || GNatives[FuncInfo.iNative]==execUndefined )
- appThrowf( TEXT("Bad native function id %i\r\n"),FuncInfo.iNative);
- #endif
- // Get return type.
- FRetryPoint Start; InitRetry(Start);
- DWORD ObjectFlags = 0;
- FPropertyBase ReturnType( CPT_None );
- FToken TestToken;
- UBOOL HasReturnValue = 0;
- if( GetIdentifier(TestToken,1) )
- {
- if( !PeekSymbol(TEXT("(")) )
- {
- PerformRetry( Start );
- HasReturnValue = GetVarType( TopNode, ReturnType, ObjectFlags, ~0, NULL );
- }
- else PerformRetry( Start );
- }
- // Get function or operator name.
- if( !GetIdentifier(FuncInfo.Function) && (!(FuncInfo.FunctionFlags&FUNC_Operator) || !GetSymbol(FuncInfo.Function)) )
- appThrowf( TEXT("Missing %s name"), NestName );
- if( !MatchSymbol(TEXT("(")) )
- appThrowf( TEXT("Bad %s definition"), NestName );
- // Validate flag combinations.
- if( FuncInfo.FunctionFlags & FUNC_Native )
- {
- if( FuncInfo.iNative && !(FuncInfo.FunctionFlags & FUNC_Final) )
- appThrowf( TEXT("Numbered native functions must be final") );
- }
- else
- {
- if( FuncInfo.FunctionFlags & FUNC_Latent )
- appThrowf( TEXT("Only native functions may use 'Latent'") );
- if( FuncInfo.FunctionFlags & FUNC_Iterator )
- appThrowf( TEXT("Only native functions may use 'Iterator'") );
- }
- // If operator, figure out the function signature.
- TCHAR Signature[NAME_SIZE]=TEXT("");
- if( FuncInfo.FunctionFlags & FUNC_Operator )
- {
- // Name.
- const TCHAR* In = FuncInfo.Function.Identifier;
- while( *In )
- appStrncat( Signature, CppTags[*In++-32], NAME_SIZE );
- // Parameter signature.
- FRetryPoint Retry;
- InitRetry( Retry );
- if( !MatchSymbol(TEXT(")")) )
- {
- // Parameter types.
- appStrncat( Signature, TEXT("_"), NAME_SIZE );
- if( FuncInfo.FunctionFlags & FUNC_PreOperator )
- appStrncat( Signature, TEXT("Pre"), NAME_SIZE );
- do
- {
- // Get parameter type.
- FPropertyBase Property(CPT_None);
- DWORD ObjectFlags;
- GetVarType( TopNode, Property, ObjectFlags, ~CPF_ParmFlags, TEXT("Function parameter") );
- GetVarNameAndDim( TopNode, Property, ObjectFlags, 0, 1, NULL, TEXT("Function parameter"), NAME_None, 1 );
- // Add to signature.
- if
- ( Property.Type==CPT_ObjectReference
- || Property.Type==CPT_Struct )
- {
- appStrncat( Signature, Property.PropertyClass->GetName(), NAME_SIZE );
- }
- else
- {
- TCHAR Temp[NAME_SIZE];
- appStrcpy( Temp, *FName((EName)Property.Type) );
- if( appStrstr( Temp, TEXT("Property") ) )
- *appStrstr( Temp, TEXT("Property") ) = 0;
- appStrncat( Signature, Temp, NAME_SIZE );
- }
- } while( MatchSymbol(TEXT(",")) );
- RequireSymbol( TEXT(")"), TEXT("parameter list") );
- }
- PerformRetry( Retry, 1, 1 );
- }
- else
- {
- appStrcpy( Signature, FuncInfo.Function.Identifier );
- }
- // Allocate local property frame, push nesting level and verify
- // uniqueness at this scope level.
- PushNest( NEST_Function, Signature, NULL );
- UFunction* TopFunction = ((UFunction*)TopNode);
- TopFunction->FunctionFlags |= FuncInfo.FunctionFlags;
- TopFunction->OperPrecedence = FuncInfo.Precedence;
- TopFunction->iNative = FuncInfo.iNative;
- TopFunction->FriendlyName = FName( FuncInfo.Function.Identifier, FNAME_Add );
- // Get parameter list.
- if( !MatchSymbol(TEXT(")")) )
- {
- UBOOL Optional=0;
- do
- {
- // Get parameter type.
- FPropertyBase Property(CPT_None);
- DWORD ObjectFlags;
- GetVarType( TopNode, Property, ObjectFlags, ~CPF_ParmFlags, TEXT("Function parameter") );
- Property.PropertyFlags |= CPF_Parm;
- UProperty* Prop = GetVarNameAndDim( TopNode, Property, ObjectFlags, 0, 1, NULL, TEXT("Function parameter"), NAME_None, 0 );
- TopFunction->NumParms++;
- // Check parameters.
- if( (FuncInfo.FunctionFlags & FUNC_Operator) && (Property.PropertyFlags & ~CPF_ParmFlags) )
- appThrowf( TEXT("Operator parameters may not have modifiers") );
- else if( Property.Type==CPT_Bool && (Property.PropertyFlags & CPF_OutParm) )
- appThrowf( TEXT("Booleans may not be out parameters") );
- else if
- ( (Property.PropertyFlags & CPF_SkipParm)
- && (!(TopFunction->FunctionFlags&FUNC_Native) || !(TopFunction->FunctionFlags&FUNC_Operator) || TopFunction->NumParms!=2) )
- appThrowf( TEXT("Only parameter 2 of native operators may be 'Skip'") );
- // Default value.
- if( MatchSymbol( TEXT("=") ) )
- {
- Prop->PropertyFlags |= CPF_OptionalParm;
- }
- // Handle optionality.
- if( Prop->PropertyFlags & CPF_OptionalParm )
- Optional = 1;
- else if( Optional )
- appThrowf( TEXT("After an optional parameters, all other parmeters must be optional") );
- } while( MatchSymbol(TEXT(",")) );
- RequireSymbol( TEXT(")"), TEXT("parameter list") );
- }
- // Get return type, if any.
- if( HasReturnValue )
- {
- ReturnType.PropertyFlags |= CPF_Parm | CPF_OutParm | CPF_ReturnParm;
- GetVarNameAndDim( TopNode, ReturnType, ObjectFlags, 1, 1, TEXT("ReturnValue"), TEXT("Function return type"), NAME_None, 0 );
- TopFunction->NumParms++;
- }
- // Check overflow.
- if( TopFunction->NumParms > MAX_FUNC_PARMS )
- appThrowf( TEXT("'%s': too many parameters"), TopNode->GetName() );
- // For operators, verify that: the operator is either binary or unary, there is
- // a return value, and all parameters have the same type as the return value.
- if( FuncInfo.FunctionFlags & FUNC_Operator )
- {
- INT n = TopFunction->NumParms;
- if( n != FuncInfo.ExpectParms )
- appThrowf( TEXT("%s must have %i parameters"), NestName, FuncInfo.ExpectParms-1 );
- if( !TopFunction->GetReturnProperty() )
- appThrowf( TEXT("Operator must have a return value") );
- if( !(FuncInfo.FunctionFlags & FUNC_Final) )
- appThrowf( TEXT("Operators must be declared as 'Final'") );
- }
- // Make new UDelegateProperty for delegate
- if( TopFunction->FunctionFlags & FUNC_Delegate )
- {
- UProperty* Prev=NULL;
- for( TFieldIterator<UProperty,CLASS_IsAUProperty> It(Scope); It && It.GetStruct()==Scope; ++It )
- {
- Prev = *It;
- }
- // check for any delegate properties that reference this delegate
- for (TObjectIterator<UDelegateProperty> It; It; ++It)
- {
- UDelegateProperty *delegateProp = Cast<UDelegateProperty>(*It);
- if (delegateProp != NULL &&
- delegateProp->Function == NULL &&
- delegateProp->DelegateName == TopFunction->FriendlyName)
- {
- // and fix up the function reference
- delegateProp->Function = TopFunction;
- debugf(TEXT("Fixed up delegate reference %s to %s"),delegateProp->GetName(),*TopFunction->FriendlyName);
- }
- }
- FName PropName = FName(*FString::Printf(TEXT("__%s__Delegate"),*TopFunction->FriendlyName), FNAME_Add);
- UProperty* NewProperty = new(Scope, PropName, RF_Public)UDelegateProperty;
- Cast<UDelegateProperty>(NewProperty)->Function = TopFunction;
- if( Prev )
- {
- NewProperty->Next = Prev->Next;
- Prev->Next = NewProperty;
- }
- else
- {
- NewProperty->Next = Scope->Children;
- Scope->Children = NewProperty;
- }
- }
- // Detect whether the function is being defined or declared.
- if( PeekSymbol(TEXT(";")) )
- {
- // Function is just being declared, not defined.
- check( (TopFunction->FunctionFlags & FUNC_Defined)==0 );
- }
- else
- {
- // Function is being defined.
- TopFunction->FunctionFlags |= FUNC_Defined;
- if( TopFunction->FunctionFlags & FUNC_Native )
- appThrowf( TEXT("Native functions may only be declared, not defined") );
- // Require bracket.
- RequireSymbol( TEXT("{"), NestName );
- NeedSemicolon=0;
- }
- // Verify parameter list and return type compatibility within the
- // function, if any, that it overrides.
- for( INT i=NestLevel-2; i>=1; i-- )
- {
- for( TFieldIterator<UFunction> Function(Nest[i].Node); Function; ++Function )
- {
- // Allow private functions to be redefined.
- if
- ( Function->GetFName()==TopNode->GetFName()
- && *Function!=TopNode
- && (Function->FunctionFlags & FUNC_Private) )
- {
- TopNode->SuperField = NULL;
- goto Found;
- }
- // If the other function's name matches this one's, process it.
- if
- ( Function->GetFName()==TopNode->GetFName()
- && *Function!=TopNode
- && ((Function->FunctionFlags ^ TopFunction->FunctionFlags) & (FUNC_Operator | FUNC_PreOperator))==0 )
- {
- // Check precedence.
- if( Function->OperPrecedence!=TopFunction->OperPrecedence && Function->NumParms==TopFunction->NumParms )
- appThrowf( TEXT("Overloaded operator differs in precedence") );
- // See if all parameters match.
- if
- ( TopFunction->NumParms!=Function->NumParms
- || (!TopFunction->GetReturnProperty())!=(!Function->GetReturnProperty()) )
- appThrowf( TEXT("Redefinition of '%s %s' differs from original"), NestName, FuncInfo.Function.Identifier );
- // Check all individual parameters.
- INT Count=0;
- for( TFieldIterator<UProperty,CLASS_IsAUProperty> It1(TopFunction),It2(*Function); Count<Function->NumParms; ++It1,++It2,++Count )
- {
- if( !FPropertyBase(*It1).MatchesType(FPropertyBase(*It2), 1) )
- {
- if( It1->PropertyFlags & CPF_ReturnParm )
- appThrowf( TEXT("Redefinition of %s %s differs only by return type"), NestName, FuncInfo.Function.Identifier );
- else if( !(FuncInfo.FunctionFlags & FUNC_Operator) )
- appThrowf( TEXT("Redefinition of '%s %s' differs from original"), NestName, FuncInfo.Function.Identifier );
- break;
- }
- }
- if( Count<TopFunction->NumParms )
- continue;
- // Function flags to copy from parent.
- FuncInfo.FunctionFlags |= (Function->FunctionFlags & FUNC_FuncInherit);
- // Balk if required specifiers differ.
- if( (Function->FunctionFlags&FUNC_FuncOverrideMatch) != (FuncInfo.FunctionFlags&FUNC_FuncOverrideMatch) )
- appThrowf( TEXT("Function '%s' specifiers differ from original"), Function->GetName() );
- // Are we overriding a function?
- if( TopNode==Function->GetOuter() )
- {
- // Duplicate.
- PerformRetry( FuncNameRetry );
- appThrowf( TEXT("Duplicate function '%s'"), Function->GetName() );
- }
- else
- {
- // Overriding an existing function.
- if( Function->FunctionFlags & FUNC_Final )
- {
- PerformRetry(FuncNameRetry);
- appThrowf( TEXT("%s: Can't override a 'final' function"), Function->GetName() );
- }
- }
- // Here we have found the original.
- TopNode->SuperField = *Function;
- goto Found;
- }
- }
- }
- Found:
- // Bind the function.
- TopFunction->Bind();
- // If declaring a function, end the nesting.
- if( !(TopFunction->FunctionFlags & FUNC_Defined) )
- PopNest( NEST_Function, NestName );
- }
- else if( Token.Matches(NAME_Const) )
- {
- CompileConst( Class );
- }
- else if( Token.Matches(NAME_Var) || Token.Matches(NAME_Local) )
- {
- // Variable definition.
- QWORD Disallow;
- if( Token.Matches(NAME_Var) )
- {
- // Declaring per-object variables.
- CheckAllow( TEXT("'Var'"), ALLOW_VarDecl );
- if( TopNest->NestType != NEST_Class )
- appThrowf( TEXT("Instance variables are only allowed at class scope (use 'local'?)") );
- Disallow = CPF_ParmFlags;
- }
- else
- {
- // Declaring local variables.
- CheckAllow( TEXT("'Local'"), ALLOW_VarDecl );
- if( TopNest->NestType == NEST_Class )
- appThrowf( TEXT("Local variables are only allowed in functions") );
- Disallow = ~0;
- }
- // Get category, if any.
- FName EdCategory = NAME_None;
- QWORD EdFlags = 0;
- if( MatchSymbol(TEXT("(")) )
- {
- // Get optional property editing category.
- EdFlags |= CPF_Edit;
- FToken Category;
- if( GetIdentifier( Category, 1 ) ) EdCategory = FName( Category.Identifier );
- else EdCategory = Class->GetFName();
- if( !MatchSymbol(TEXT(")")) )
- appThrowf( TEXT("Missing ')' after editable category") );
- }
- // Compile the variable type.
- FPropertyBase OriginalProperty(CPT_None);
- DWORD ObjectFlags=0;
- GetVarType( TopNode, OriginalProperty, ObjectFlags, Disallow, TEXT("Variable declaration") );
- OriginalProperty.PropertyFlags |= EdFlags;
- // If editable but no category was specified, the category name is our class name.
- if( (OriginalProperty.PropertyFlags & CPF_Edit) && (EdCategory==NAME_None) )
- EdCategory = Class->GetFName();
- // Validate combinations.
- if( (OriginalProperty.PropertyFlags & (CPF_Transient|CPF_Native)) && TopNest->NestType!=NEST_Class )
- appThrowf( TEXT("Static and local variables may not be transient or native") );
- if( OriginalProperty.PropertyFlags & CPF_ParmFlags )
- appThrowf( TEXT("Illegal type modifiers in variable") );
- // Process all variables of this type.
- do
- {
- UProperty* newProperty;
- FPropertyBase Property = OriginalProperty;
- newProperty = GetVarNameAndDim( TopNode, Property, ObjectFlags, 0, 0, NULL, TEXT("Variable declaration"), EdCategory, 0 );
- if( newProperty )
- {
- UnReferencedLocal *newLocal = new UnReferencedLocal;
- newLocal->next = unReferencedLocals;
- newLocal->property = newProperty;
- newLocal->declarationLine = InputLine;
- unReferencedLocals = newLocal;
- }
- } while( MatchSymbol(TEXT(",")) );
- // Propagate alignment restrictions.
- if( Token.Matches(NAME_Var) && (OriginalProperty.Type == CPT_Struct) && OriginalProperty.Struct && (OriginalProperty.ArrayDim != 0) )
- Class->MinAlignment = Max( Class->MinAlignment, OriginalProperty.Struct->MinAlignment );
- }
- else if( Token.Matches(NAME_Enum) )
- {
- // Enumeration definition.
- CheckAllow( TEXT("'Enum'"), ALLOW_VarDecl );
- // Compile enumeration.
- CompileEnum( Class );
- }
- else if( Token.Matches(NAME_Struct) )
- {
- // Struct definition.
- CheckAllow( TEXT("'struct'"), ALLOW_VarDecl );
- // Compile struct.
- CompileStruct( Class );
- }
- else if
- ( Token.Matches(NAME_State)
- || Token.Matches(NAME_Auto)
- || Token.Matches(NAME_Simulated) )
- {
- // State block.
- check(TopNode!=NULL);
- CheckAllow( TEXT("'State'"), ALLOW_State );
- DWORD StateFlags=0, GotState=0;
- // Process all specifiers.
- for( ;; )
- {
- if( Token.Matches(NAME_State) )
- {
- GotState=1;
- if( MatchSymbol(TEXT("(")) )
- {
- RequireSymbol( TEXT(")"), TEXT("'State'") );
- StateFlags |= STATE_Editable;
- }
- }
- else if( Token.Matches(NAME_Simulated) )
- {
- StateFlags |= STATE_Simulated;
- }
- else if( Token.Matches(NAME_Auto) )
- {
- StateFlags |= STATE_Auto;
- }
- else
- {
- UngetToken(Token);
- break;
- }
- GetToken(Token);
- }
- if( !GotState )
- appThrowf( TEXT("Missing 'State'") );
- // Get name and default parent state.
- FToken NameToken;
- if( !GetIdentifier(NameToken) )
- appThrowf( TEXT("Missing state name") );
- UState* ParentState = Cast<UState>(FindField( TopNode, NameToken.Identifier, UState::StaticClass(), TEXT("'state'") ));
- if( ParentState && ParentState->GetOwnerClass()==Class )
- appThrowf( TEXT("Duplicate state '%s'"), NameToken.Identifier );
- // Check for 'extends' keyword.
- if( MatchIdentifier(NAME_Extends) )
- {
- FToken ParentToken;
- if( ParentState )
- appThrowf( TEXT("'Extends' not allowed here: state '%s' overrides version in parent class"), NameToken.Identifier );
- if( !GetIdentifier(ParentToken) )
- appThrowf( TEXT("Missing parent state name") );
- ParentState = Cast<UState>(FindField( TopNode, ParentToken.Identifier, UState::StaticClass(), TEXT("'state'") ));
- if( !ParentState )
- appThrowf( TEXT("'extends': Parent state '%s' not found"), ParentToken.Identifier );
- }
- // Begin the state block.
- PushNest( NEST_State, NameToken.Identifier, NULL );
- UState* State = CastChecked<UState>( TopNode );
- State->StateFlags |= StateFlags;
- State->SuperField = ParentState;
- RequireSymbol( TEXT("{"), TEXT("'State'") );
- NeedSemicolon=0;
- SupressDebugInfo = -1;
- }
- else if( Token.Matches(NAME_Ignores) )
- {
- // Probes to ignore in this state.
- CheckAllow( TEXT("'Ignores'"), ALLOW_Ignores );
- for( ; ; )
- {
- FToken IgnoreFunction;
- if( !GetToken(IgnoreFunction) )
- appThrowf( TEXT("'Ignores': Missing probe function name") );
- if
- ( IgnoreFunction.TokenName==NAME_None
- || IgnoreFunction.TokenName.GetIndex() < NAME_PROBEMIN
- || IgnoreFunction.TokenName.GetIndex() >= NAME_PROBEMAX )
- {
- for( INT i=NestLevel-2; i>=1; i-- )
- {
- for( TFieldIterator<UFunction> Function(Nest[i].Node); Function; ++Function )
- {
- if( Function->GetFName()==IgnoreFunction.TokenName )
- {
- // Verify that function is ignoreable.
- if( Function->FunctionFlags & FUNC_Final )
- appThrowf( TEXT("'%s': Cannot ignore final functions"), Function->GetName() );
- // Insert empty function definition to intercept the call.
- PushNest( NEST_Function, Function->GetName(), NULL );
- UFunction* TopFunction = ((UFunction*) TopNode );
- TopFunction->FunctionFlags |= (Function->FunctionFlags & FUNC_FuncOverrideMatch);
- TopFunction->NumParms = Function->NumParms;
- TopFunction->SuperField = *Function;
- // Copy parameters.
- UField** PrevLink = &TopFunction->Children;
- check(*PrevLink==NULL);
- for( TFieldIterator<UProperty,CLASS_IsAUProperty> It(*Function); It && (It->PropertyFlags & CPF_Parm); ++It )
- {
- UProperty* NewProperty=NULL;
- if( It->IsA(UByteProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UByteProperty;
- Cast<UByteProperty>(NewProperty)->Enum = Cast<UByteProperty>(*It)->Enum;
- }
- else if( It->IsA(UIntProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UIntProperty;
- }
- else if( It->IsA(UBoolProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UBoolProperty;
- }
- else if( It->IsA(UFloatProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UFloatProperty;
- }
- else if( It->IsA(UClassProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UClassProperty;
- Cast<UObjectProperty>(NewProperty)->PropertyClass = Cast<UObjectProperty>(*It)->PropertyClass;
- Cast<UClassProperty>(NewProperty)->MetaClass = Cast<UClassProperty>(*It)->MetaClass;
- }
- else if( It->IsA(UObjectProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UObjectProperty;
- Cast<UObjectProperty>(NewProperty)->PropertyClass = Cast<UObjectProperty>(*It)->PropertyClass;
- }
- else if( It->IsA(UNameProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UNameProperty;
- }
- else if( It->IsA(UStrProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UStrProperty;
- }
- else if( It->IsA(UStructProperty::StaticClass()) )
- {
- NewProperty = new(TopFunction,It->GetName(),RF_Public)UStructProperty;
- Cast<UStructProperty>(NewProperty)->Struct = Cast<UStructProperty>(*It)->Struct;
- }
- else appErrorf( TEXT("Unknown property type %s"), It->GetClass()->GetName() );
- NewProperty->ArrayDim = It->ArrayDim;
- NewProperty->PropertyFlags = It->PropertyFlags;
- *PrevLink = NewProperty;
- PrevLink = &(*PrevLink)->Next;
- }
- // Finish up.
- PopNest( NEST_Function, TEXT("Ignores") );
- goto FoundIgnore;
- }
- }
- }
- appThrowf( TEXT("'Ignores': '%s' is not a function"), IgnoreFunction.Identifier );
- FoundIgnore:;
- }
- else
- {
- // Ignore a probe function.
- UState* State = CastChecked<UState>( TopNode );
- State->IgnoreMask &= ~((QWORD)1 << (IgnoreFunction.TokenName.GetIndex() - NAME_PROBEMIN));
- }
- // More?
- if( !MatchSymbol(TEXT(",")) )
- break;
- }
- }
- else if( Token.Matches(NAME_Replication) )
- {
- // Network replication definition.
- if( TopNest->NestType != NEST_Class )
- appThrowf( TEXT("'Replication' is not allowed here") );
- RequireSymbol( TEXT("{"), TEXT("'Replication'") );
- TopNode->TextPos = InputPos;
- TopNode->Line = InputLine;
- SkipStatements( 1, TEXT("'Replication'") );
- NeedSemicolon=0;
- }
- else if( Token.Matches(TEXT("#")) )
- {
- // Compiler directive.
- CompileDirective();
- NeedSemicolon=0;
- }
- else
- {
- // Not a declaration.
- return 0;
- }
- return 1;
- }
Add Comment
Please, Sign In to add comment