Guest User

Untitled

a guest
Jul 22nd, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 35.09 KB | None | 0 0
  1. //
  2. // Compile a declaration in Token. Returns 1 if compiled, 0 if not.
  3. //
  4. INT FScriptCompiler::CompileDeclaration( FToken& Token, UBOOL& NeedSemicolon )
  5. {
  6. if( Token.Matches(NAME_Class) && (TopNest->Allow & ALLOW_Class) )
  7. {
  8. // Start of a class block.
  9. CheckAllow( TEXT("'class'"), ALLOW_Class );
  10.  
  11. // Class name.
  12. if( !GetToken(Token) )
  13. appThrowf( TEXT("Missing class name") );
  14. if( appIsDigit( **FString(Token.Identifier).Right(1) ) )
  15. Warn->Logf( NAME_Warning, TEXT("Class names shouldn't end in a digit"), Token.Identifier );
  16. if( !Token.Matches(Class->GetName()) )
  17. appThrowf( TEXT("Class must be named %s, not %s"), Class->GetName(), Token.Identifier );
  18.  
  19. // Get parent class.
  20. if( MatchIdentifier(NAME_Extends) )
  21. {
  22. // Set the superclass.
  23. UClass* TempClass = GetQualifiedClass( TEXT("'extends'") );
  24. if( Class->GetSuperClass() == NULL )
  25. Class->SuperField = TempClass;
  26. else if( Class->GetSuperClass() != TempClass )
  27. appThrowf( TEXT("%s's superclass must be %s, not %s"), *Class->GetPathName(), *Class->GetSuperClass()->GetPathName(), *TempClass->GetPathName() );
  28. Class->MinAlignment = Max(Class->MinAlignment,TempClass->MinAlignment);
  29. }
  30. else if( Class->GetSuperClass() )
  31. appThrowf( TEXT("class: missing 'Extends %s'"), Class->GetSuperClass()->GetName() );
  32.  
  33. // Get outer class.
  34. if( MatchIdentifier(NAME_Within) )
  35. {
  36. // Set the outer class.
  37. UClass* TempClass = GetQualifiedClass( TEXT("'within'") );
  38. if( Class->ClassWithin == NULL || Class->ClassWithin==UObject::StaticClass() )
  39. Class->ClassWithin = TempClass;
  40. else if( Class->ClassWithin != TempClass )
  41. appThrowf( TEXT("%s must be within %s, not %s"), *Class->GetPathName(), *Class->ClassWithin->GetPathName(), *TempClass->GetPathName() );
  42. }
  43. else Class->ClassWithin = Class->GetSuperClass() ? Class->GetSuperClass()->ClassWithin : UObject::StaticClass();
  44.  
  45. UClass* ExpectedWithin = Class->GetSuperClass() ? Class->GetSuperClass()->ClassWithin : UObject::StaticClass();
  46. if( !Class->ClassWithin->IsChildOf(ExpectedWithin) )
  47. appThrowf( TEXT("'within': within %s is not a generalization of superclass within '%s'"), Class->ClassWithin->GetName(), ExpectedWithin->GetName() );
  48.  
  49. // Keep track of whether "config(ini)" was used.
  50. UBOOL DeclaresConfigFile = 0;
  51.  
  52. // Class attributes.
  53. FToken Token;
  54. for( ; ; )
  55. {
  56. GetToken(Token);
  57. if( Token.Matches(NAME_Intrinsic) || Token.Matches(NAME_Native) )//oldver
  58. {
  59. // Note that this class has C++ code dependencies.
  60. if( Class->GetSuperClass() && !(Class->GetSuperClass()->GetFlags() & RF_Native) )
  61. appThrowf( TEXT("Native classes cannot expand non-native classes") );
  62. Class->SetFlags( RF_Native );
  63.  
  64. // Parse an optional class header filename.
  65. if( MatchSymbol(TEXT("(")) )
  66. {
  67. FToken Token;
  68. if( !GetIdentifier(Token, 0) )
  69. appThrowf( TEXT("native: Missing native header filename") );
  70. Class->ClassHeaderFilename = Token.Identifier;
  71. RequireSymbol(TEXT(")"), TEXT("native") );
  72. }
  73. }
  74. else if( Token.Matches(NAME_NoExport) )
  75. {
  76. // Don't export to C++ header.
  77. Class->ClassFlags |= CLASS_NoExport;
  78. }
  79. else if( Token.Matches(NAME_EditInlineNew) )
  80. {
  81. // Class can be constructed from the New button in editinline
  82. Class->ClassFlags |= CLASS_EditInlineNew;
  83. }
  84. else if( Token.Matches(NAME_NotEditInlineNew) )
  85. {
  86. // Class cannot be constructed from the New button in editinline
  87. Class->ClassFlags &= ~CLASS_EditInlineNew;
  88. }
  89. else if( Token.Matches(NAME_Placeable) )
  90. {
  91. // Allow the class to be placed in the editor.
  92. Class->ClassFlags |= CLASS_Placeable;
  93. }
  94. else if( Token.Matches(NAME_NotPlaceable) )
  95. {
  96. // Allow the class to be placed in the editor.
  97. if ( Class->ClassFlags & CLASS_Placeable )
  98. Class->ClassFlags -= CLASS_Placeable;
  99. }
  100. else if( Token.Matches(NAME_HideDropDown) )
  101. {
  102. // Prevents class from appearing in class comboboxes in the property window
  103. Class->ClassFlags |= CLASS_HideDropDown;
  104. }
  105. else if( Token.Matches(NAME_NativeReplication) )
  106. {
  107. // Replication is native.
  108. Class->ClassFlags |= CLASS_NativeReplication;
  109. }
  110. else if( Token.Matches(NAME_DependsOn) )
  111. {
  112. RequireSymbol(TEXT("("), TEXT("dependsOn") );
  113. FToken Token;
  114. if( !GetIdentifier(Token, 0) )
  115. appThrowf( TEXT("dependsOn: Missing dependent name") );
  116. RequireSymbol(TEXT(")"), TEXT("dependsOn") );
  117. }
  118. else if( Token.Matches(NAME_PerObjectConfig) )
  119. {
  120. // Don't export to C++ header.
  121. Class->ClassFlags |= CLASS_PerObjectConfig;
  122. }
  123. else if( Token.Matches(NAME_Abstract) )
  124. {
  125. // Hide all editable properties.
  126. Class->ClassFlags |= CLASS_Abstract;
  127. }
  128. else if ( Token.Matches(NAME_Deprecated) )
  129. {
  130. Class->ClassFlags |= CLASS_Deprecated;
  131. }
  132. else if( Token.Matches(NAME_Guid) )
  133. {
  134. // Get the class's GUID.
  135. RequireSymbol( TEXT("("), TEXT("'Guid'") );
  136. GetConstInt(*(INT*)&Class->ClassGuid.A);
  137. RequireSymbol( TEXT(","), TEXT("'Guid'") );
  138. GetConstInt(*(INT*)&Class->ClassGuid.B);
  139. RequireSymbol( TEXT(","), TEXT("'Guid'") );
  140. GetConstInt(*(INT*)&Class->ClassGuid.C);
  141. RequireSymbol( TEXT(","), TEXT("'Guid'") );
  142. GetConstInt(*(INT*)&Class->ClassGuid.D);
  143. RequireSymbol( TEXT(")"), TEXT("'Guid'") );
  144. }
  145. else if( Token.Matches(NAME_Transient) )
  146. {
  147. // Transient class.
  148. Class->ClassFlags |= CLASS_Transient;
  149. }
  150. else if( Token.Matches(NAME_Localized) )
  151. {
  152. // Localized class.
  153. //oldver
  154. appThrowf( TEXT("Class 'localized' keyword is no longer required") );
  155. }
  156. else if( Token.Matches(NAME_Config) )
  157. {
  158. // Transient class.
  159. if( MatchSymbol(TEXT("(")) )
  160. {
  161. FToken Token;
  162. if( !GetIdentifier(Token, 0) )
  163. appThrowf( TEXT("config: Missing configuration name") );
  164. Class->ClassConfigName = Token.Identifier;
  165. RequireSymbol(TEXT(")"), TEXT("config") );
  166. DeclaresConfigFile = 1;
  167. }
  168. else
  169. appThrowf( TEXT("config: Missing configuration name") );
  170. }
  171. else if( Token.Matches(NAME_SafeReplace) )
  172. {
  173. // Safely replaceable.
  174. Class->ClassFlags |= CLASS_SafeReplace;
  175. }
  176. else if( Token.Matches(NAME_HideCategories) )
  177. {
  178. RequireSymbol( TEXT("("), TEXT("'HideCategories'") );
  179. do
  180. {
  181. FToken Category;
  182. if( !GetIdentifier( Category, 1 ) )
  183. appThrowf( TEXT("HideCategories: Expected category name") );
  184. Class->HideCategories.AddItem( FName( Category.Identifier ) );
  185. }
  186. while( MatchSymbol(TEXT(",")) );
  187. RequireSymbol( TEXT(")"), TEXT("'HideCategories'") );
  188. }
  189. else if( Token.Matches(NAME_AutoExpandCategories) )
  190. {
  191. RequireSymbol( TEXT("("), TEXT("'AutoExpandCategories'") );
  192. do
  193. {
  194. FToken Category;
  195. if( !GetIdentifier( Category, 1 ) )
  196. appThrowf( TEXT("AutoExpandCategories: Expected category name") );
  197. Class->AutoExpandCategories.AddItem( FName( Category.Identifier ) );
  198. }
  199. while( MatchSymbol(TEXT(",")) );
  200. RequireSymbol( TEXT(")"), TEXT("'AutoExpandCategories'") );
  201. }
  202. else if( Token.Matches(NAME_ShowCategories) )
  203. {
  204. RequireSymbol( TEXT("("), TEXT("'ShowCategories'") );
  205. do
  206. {
  207. FToken Category;
  208. if( !GetIdentifier( Category, 1 ) )
  209. appThrowf( TEXT("ShowCategories: Expected category name") );
  210. Class->HideCategories.RemoveItem( FName( Category.Identifier ) );
  211. }
  212. while( MatchSymbol(TEXT(",")) );
  213. RequireSymbol( TEXT(")"), TEXT("'ShowCategories'") );
  214. }
  215. else if( Token.Matches(NAME_CollapseCategories) )
  216. {
  217. // Class' properties should not be shown categorized in the editor.
  218. Class->ClassFlags |= CLASS_CollapseCategories;
  219. }
  220. else if( Token.Matches(NAME_DontCollapseCategories) )
  221. {
  222. // Class' properties should be shown categorized in the editor.
  223. Class->ClassFlags &= ~CLASS_CollapseCategories;
  224. }
  225. else
  226. {
  227. UngetToken(Token);
  228. break;
  229. }
  230. }
  231. // Validate.
  232. if( (Class->ClassFlags&CLASS_NoExport) && !(Class->GetFlags()&RF_Native) )
  233. appThrowf( TEXT("'noexport': Only valid for native classes") );
  234.  
  235. // Invalidate config name if not specifically declared.
  236. if( !DeclaresConfigFile )
  237. Class->ClassConfigName = NAME_None;
  238.  
  239. // Get semicolon.
  240. RequireSymbol( TEXT(";"), TEXT("'Class'") );
  241. NeedSemicolon=0;
  242.  
  243. // Init variables.
  244. Class->Script.Empty();
  245. Class->Children = NULL;
  246. Class->Next = NULL;
  247. Class->ProbeMask = 0;
  248. Class->IgnoreMask = 0;
  249. Class->StateFlags = 0;
  250. Class->LabelTableOffset = 0;
  251. Class->NetFields.Empty();
  252.  
  253. // Make visible outside the package.
  254. Class->ClearFlags( RF_Transient );
  255. check(Class->GetFlags()&RF_Public);
  256. check(Class->GetFlags()&RF_Standalone);
  257.  
  258. // Setup initial package imports to include the packages and the package imports
  259. // of all base classes.
  260. Class->PackageImports.Empty();
  261. for( UClass* C = Class; C; C=C->GetSuperClass() )
  262. {
  263. Class->PackageImports.AddUniqueItem( C->GetOuter()->GetFName() );
  264. for( INT i=0; i<C->PackageImports.Num(); i++ )
  265. Class->PackageImports.AddUniqueItem( C->PackageImports( i ) );
  266. }
  267.  
  268. // Copy properties from parent class.
  269. Class->Defaults.Empty();
  270. if( Class->GetSuperClass() )
  271. {
  272. Class->SetPropertiesSize( Class->GetSuperClass()->GetPropertiesSize() );
  273. Class->Defaults = Class->GetSuperClass()->Defaults;
  274. }
  275.  
  276. // Push the class nesting.
  277. PushNest( NEST_Class, Class->GetName(), NULL );
  278. }
  279. else if( Token.Matches(NAME_Import) )
  280. {
  281. CheckAllow( TEXT("'Uses'"), ALLOW_VarDecl );
  282. if( TopNest->NestType != NEST_Class )
  283. appThrowf( TEXT("'Uses' is are only allowed at class scope") );
  284.  
  285. // Get thing to import.
  286. FToken ImportThing;
  287. GetToken( ImportThing );
  288. if( !ImportThing.Matches(NAME_Enum) && !ImportThing.Matches(NAME_Package) )
  289. appThrowf( TEXT("'import': Missing 'enum', 'struct', or 'package'") );
  290.  
  291. // Get name to import.
  292. FToken ImportName;
  293. if( !GetIdentifier(ImportName) )
  294. appThrowf( TEXT("'import': Missing package, enum, or struct name to import") );
  295.  
  296. // Handle package, enum, or struct.
  297. if( ImportThing.Matches(NAME_Package) )
  298. {
  299. // Import a package.
  300. Class->PackageImports.AddUniqueItem( FName(ImportName.Identifier) );
  301. }
  302. else if( ImportThing.Matches(NAME_Enum) )
  303. {
  304. // From package.
  305. UPackage* Pkg = CastChecked<UPackage>(Class->GetOuter());
  306. if( MatchIdentifier(NAME_From) )
  307. {
  308. FToken ImportPackage;
  309. if( GetIdentifier( ImportPackage ) )
  310. {
  311. Pkg = FindObject<UPackage>( NULL, ImportPackage.Identifier );
  312. if( !Pkg )
  313. appThrowf( TEXT("'Uses': Unrecognized package '%s'"), ImportPackage.Identifier );
  314. }
  315. }
  316. else appThrowf( TEXT("'Uses': Unrecognized '%s'"), ImportThing.Identifier );
  317. new( Pkg, ImportName.Identifier )UEnum( NULL );
  318. }
  319.  
  320. }
  321. else if
  322. ( Token.Matches(NAME_Function)
  323. || Token.Matches(NAME_Operator)
  324. || Token.Matches(NAME_PreOperator)
  325. || Token.Matches(NAME_PostOperator)
  326. || Token.Matches(NAME_Intrinsic) //oldver
  327. || Token.Matches(NAME_Native)
  328. || Token.Matches(NAME_Final)
  329. || Token.Matches(NAME_Private)
  330. || Token.Matches(NAME_Protected)
  331. || Token.Matches(NAME_Public)
  332. || Token.Matches(NAME_Latent)
  333. || Token.Matches(NAME_Iterator)
  334. || Token.Matches(NAME_Singular)
  335. || Token.Matches(NAME_Static)
  336. || Token.Matches(NAME_Exec)
  337. || Token.Matches(NAME_Delegate)
  338. || (Token.Matches(NAME_Event) && (TopNest->Allow & ALLOW_Function) )
  339. || (Token.Matches(NAME_Simulated) && !PeekIdentifier(NAME_State)) )
  340. {
  341. // Function or operator.
  342. const TCHAR* NestName = NULL;
  343. FRetryPoint FuncNameRetry;
  344. FFuncInfo FuncInfo;
  345. FuncInfo.FunctionFlags = FUNC_Public;
  346. UStruct* Scope = TopNode;
  347.  
  348. // Process all specifiers.
  349. for( ;; )
  350. {
  351. InitRetry(FuncNameRetry);
  352. if( Token.Matches(NAME_Function) )
  353. {
  354. // Get function name.
  355. CheckAllow( TEXT("'Function'"),ALLOW_Function);
  356. NestName = TEXT("function");
  357. }
  358. else if( Token.Matches(NAME_Operator) )
  359. {
  360. // Get operator name or symbol.
  361. CheckAllow( TEXT("'Operator'"), ALLOW_Function );
  362. NestName = TEXT("operator");
  363. FuncInfo.FunctionFlags |= FUNC_Operator;
  364. FuncInfo.ExpectParms = 3;
  365.  
  366. if( !MatchSymbol(TEXT("(")) )
  367. appThrowf( TEXT("Missing '(' and precedence after 'Operator'") );
  368. else if( !GetConstInt(FuncInfo.Precedence) )
  369. appThrowf( TEXT("Missing precedence value") );
  370. else if( FuncInfo.Precedence<0 || FuncInfo.Precedence>255 )
  371. appThrowf( TEXT("Bad precedence value") );
  372. else if( !MatchSymbol(TEXT(")")) )
  373. appThrowf( TEXT("Missing ')' after operator precedence") );
  374. }
  375. else if( Token.Matches(NAME_PreOperator) )
  376. {
  377. // Get operator name or symbol.
  378. CheckAllow( TEXT("'PreOperator'"), ALLOW_Function );
  379. NestName = TEXT("preoperator");
  380. FuncInfo.ExpectParms = 2;
  381. FuncInfo.FunctionFlags |= FUNC_Operator | FUNC_PreOperator;
  382. }
  383. else if( Token.Matches(NAME_PostOperator) )
  384. {
  385. // Get operator name or symbol.
  386. CheckAllow( TEXT("'PostOperator'"), ALLOW_Function );
  387. NestName = TEXT("postoperator");
  388. FuncInfo.FunctionFlags |= FUNC_Operator;
  389. FuncInfo.ExpectParms = 2;
  390. }
  391. else if( Token.Matches(NAME_Intrinsic) || Token.Matches(NAME_Native) )//oldver
  392. {
  393. // Get internal id.
  394. FuncInfo.FunctionFlags |= FUNC_Native;
  395. if( MatchSymbol(TEXT("(")) )
  396. {
  397. if( !GetConstInt(FuncInfo.iNative) )
  398. appThrowf( TEXT("Missing native id") );
  399. else if( !MatchSymbol(TEXT(")")) )
  400. appThrowf( TEXT("Missing ')' after internal id") );
  401. }
  402. }
  403. else if( Token.Matches(NAME_Event) )
  404. {
  405. CheckAllow( TEXT("'Function'"), ALLOW_Function );
  406. NestName = TEXT("event");
  407. FuncInfo.FunctionFlags |= FUNC_Event;
  408. }
  409. else if( Token.Matches(NAME_Static) )
  410. {
  411. FuncInfo.FunctionFlags |= FUNC_Static;
  412. if( TopNode->GetClass()==UState::StaticClass() )
  413. appThrowf( TEXT("Static functions cannot exist in a state") );
  414. }
  415. else if( Token.Matches(NAME_Simulated) )
  416. {
  417. FuncInfo.FunctionFlags |= FUNC_Simulated;
  418. }
  419. else if( Token.Matches(NAME_Iterator) )
  420. {
  421. FuncInfo.FunctionFlags |= FUNC_Iterator;
  422. }
  423. else if( Token.Matches(NAME_Singular) )
  424. {
  425. FuncInfo.FunctionFlags |= FUNC_Singular;
  426. }
  427. else if( Token.Matches(NAME_Latent) )
  428. {
  429. FuncInfo.FunctionFlags |= FUNC_Latent;
  430. }
  431. else if( Token.Matches(NAME_Exec) )
  432. {
  433. FuncInfo.FunctionFlags |= FUNC_Exec;
  434. }
  435. else if( Token.Matches(NAME_Delegate) )
  436. {
  437. CheckAllow( TEXT("'Function'"),ALLOW_Function);
  438. NestName = TEXT("delegate");
  439. FuncInfo.FunctionFlags |= FUNC_Delegate;
  440. }
  441. else if( Token.Matches(NAME_Final) )
  442. {
  443. // This is a final (prebinding, non-overridable) function or operator.
  444. FuncInfo.FunctionFlags |= FUNC_Final;
  445. }
  446. else if( Token.Matches(NAME_Private) )
  447. {
  448. FuncInfo.FunctionFlags &= ~FUNC_Public;
  449. FuncInfo.FunctionFlags |= FUNC_Private;
  450. }
  451. else if( Token.Matches(NAME_Protected) )
  452. {
  453. FuncInfo.FunctionFlags &= ~FUNC_Public;
  454. FuncInfo.FunctionFlags |= FUNC_Protected;
  455. }
  456. else if( Token.Matches(NAME_Public) )
  457. {
  458. FuncInfo.FunctionFlags |= FUNC_Public;
  459. }
  460. else break;
  461. GetToken(Token);
  462. }
  463. UngetToken(Token);
  464.  
  465. // Make sure we got a function.
  466. if( !NestName )
  467. appThrowf( TEXT("Missing 'function'") );
  468.  
  469. // Warn if native doesn't actually exist.
  470. #if CHECK_NATIVE_MATCH
  471. if( FuncInfo.iNative!=0 )
  472. if( FuncInfo.iNative<EX_FirstNative || FuncInfo.iNative>EX_Max || GNatives[FuncInfo.iNative]==execUndefined )
  473. appThrowf( TEXT("Bad native function id %i\r\n"),FuncInfo.iNative);
  474. #endif
  475.  
  476. // Get return type.
  477. FRetryPoint Start; InitRetry(Start);
  478. DWORD ObjectFlags = 0;
  479. FPropertyBase ReturnType( CPT_None );
  480. FToken TestToken;
  481. UBOOL HasReturnValue = 0;
  482. if( GetIdentifier(TestToken,1) )
  483. {
  484. if( !PeekSymbol(TEXT("(")) )
  485. {
  486. PerformRetry( Start );
  487. HasReturnValue = GetVarType( TopNode, ReturnType, ObjectFlags, ~0, NULL );
  488. }
  489. else PerformRetry( Start );
  490. }
  491.  
  492. // Get function or operator name.
  493. if( !GetIdentifier(FuncInfo.Function) && (!(FuncInfo.FunctionFlags&FUNC_Operator) || !GetSymbol(FuncInfo.Function)) )
  494. appThrowf( TEXT("Missing %s name"), NestName );
  495. if( !MatchSymbol(TEXT("(")) )
  496. appThrowf( TEXT("Bad %s definition"), NestName );
  497.  
  498. // Validate flag combinations.
  499. if( FuncInfo.FunctionFlags & FUNC_Native )
  500. {
  501. if( FuncInfo.iNative && !(FuncInfo.FunctionFlags & FUNC_Final) )
  502. appThrowf( TEXT("Numbered native functions must be final") );
  503. }
  504. else
  505. {
  506. if( FuncInfo.FunctionFlags & FUNC_Latent )
  507. appThrowf( TEXT("Only native functions may use 'Latent'") );
  508. if( FuncInfo.FunctionFlags & FUNC_Iterator )
  509. appThrowf( TEXT("Only native functions may use 'Iterator'") );
  510. }
  511.  
  512. // If operator, figure out the function signature.
  513. TCHAR Signature[NAME_SIZE]=TEXT("");
  514. if( FuncInfo.FunctionFlags & FUNC_Operator )
  515. {
  516. // Name.
  517. const TCHAR* In = FuncInfo.Function.Identifier;
  518. while( *In )
  519. appStrncat( Signature, CppTags[*In++-32], NAME_SIZE );
  520.  
  521. // Parameter signature.
  522. FRetryPoint Retry;
  523. InitRetry( Retry );
  524. if( !MatchSymbol(TEXT(")")) )
  525. {
  526. // Parameter types.
  527. appStrncat( Signature, TEXT("_"), NAME_SIZE );
  528. if( FuncInfo.FunctionFlags & FUNC_PreOperator )
  529. appStrncat( Signature, TEXT("Pre"), NAME_SIZE );
  530. do
  531. {
  532. // Get parameter type.
  533. FPropertyBase Property(CPT_None);
  534. DWORD ObjectFlags;
  535. GetVarType( TopNode, Property, ObjectFlags, ~CPF_ParmFlags, TEXT("Function parameter") );
  536. GetVarNameAndDim( TopNode, Property, ObjectFlags, 0, 1, NULL, TEXT("Function parameter"), NAME_None, 1 );
  537.  
  538. // Add to signature.
  539. if
  540. ( Property.Type==CPT_ObjectReference
  541. || Property.Type==CPT_Struct )
  542. {
  543. appStrncat( Signature, Property.PropertyClass->GetName(), NAME_SIZE );
  544. }
  545. else
  546. {
  547. TCHAR Temp[NAME_SIZE];
  548. appStrcpy( Temp, *FName((EName)Property.Type) );
  549. if( appStrstr( Temp, TEXT("Property") ) )
  550. *appStrstr( Temp, TEXT("Property") ) = 0;
  551. appStrncat( Signature, Temp, NAME_SIZE );
  552. }
  553. } while( MatchSymbol(TEXT(",")) );
  554. RequireSymbol( TEXT(")"), TEXT("parameter list") );
  555. }
  556. PerformRetry( Retry, 1, 1 );
  557. }
  558. else
  559. {
  560. appStrcpy( Signature, FuncInfo.Function.Identifier );
  561. }
  562.  
  563. // Allocate local property frame, push nesting level and verify
  564. // uniqueness at this scope level.
  565. PushNest( NEST_Function, Signature, NULL );
  566. UFunction* TopFunction = ((UFunction*)TopNode);
  567. TopFunction->FunctionFlags |= FuncInfo.FunctionFlags;
  568. TopFunction->OperPrecedence = FuncInfo.Precedence;
  569. TopFunction->iNative = FuncInfo.iNative;
  570. TopFunction->FriendlyName = FName( FuncInfo.Function.Identifier, FNAME_Add );
  571.  
  572. // Get parameter list.
  573. if( !MatchSymbol(TEXT(")")) )
  574. {
  575. UBOOL Optional=0;
  576. do
  577. {
  578. // Get parameter type.
  579. FPropertyBase Property(CPT_None);
  580. DWORD ObjectFlags;
  581. GetVarType( TopNode, Property, ObjectFlags, ~CPF_ParmFlags, TEXT("Function parameter") );
  582. Property.PropertyFlags |= CPF_Parm;
  583. UProperty* Prop = GetVarNameAndDim( TopNode, Property, ObjectFlags, 0, 1, NULL, TEXT("Function parameter"), NAME_None, 0 );
  584. TopFunction->NumParms++;
  585.  
  586. // Check parameters.
  587. if( (FuncInfo.FunctionFlags & FUNC_Operator) && (Property.PropertyFlags & ~CPF_ParmFlags) )
  588. appThrowf( TEXT("Operator parameters may not have modifiers") );
  589. else if( Property.Type==CPT_Bool && (Property.PropertyFlags & CPF_OutParm) )
  590. appThrowf( TEXT("Booleans may not be out parameters") );
  591. else if
  592. ( (Property.PropertyFlags & CPF_SkipParm)
  593. && (!(TopFunction->FunctionFlags&FUNC_Native) || !(TopFunction->FunctionFlags&FUNC_Operator) || TopFunction->NumParms!=2) )
  594. appThrowf( TEXT("Only parameter 2 of native operators may be 'Skip'") );
  595.  
  596. // Default value.
  597. if( MatchSymbol( TEXT("=") ) )
  598. {
  599. Prop->PropertyFlags |= CPF_OptionalParm;
  600. }
  601.  
  602. // Handle optionality.
  603. if( Prop->PropertyFlags & CPF_OptionalParm )
  604. Optional = 1;
  605. else if( Optional )
  606. appThrowf( TEXT("After an optional parameters, all other parmeters must be optional") );
  607. } while( MatchSymbol(TEXT(",")) );
  608. RequireSymbol( TEXT(")"), TEXT("parameter list") );
  609. }
  610.  
  611. // Get return type, if any.
  612. if( HasReturnValue )
  613. {
  614. ReturnType.PropertyFlags |= CPF_Parm | CPF_OutParm | CPF_ReturnParm;
  615. GetVarNameAndDim( TopNode, ReturnType, ObjectFlags, 1, 1, TEXT("ReturnValue"), TEXT("Function return type"), NAME_None, 0 );
  616. TopFunction->NumParms++;
  617. }
  618.  
  619. // Check overflow.
  620. if( TopFunction->NumParms > MAX_FUNC_PARMS )
  621. appThrowf( TEXT("'%s': too many parameters"), TopNode->GetName() );
  622.  
  623. // For operators, verify that: the operator is either binary or unary, there is
  624. // a return value, and all parameters have the same type as the return value.
  625. if( FuncInfo.FunctionFlags & FUNC_Operator )
  626. {
  627. INT n = TopFunction->NumParms;
  628. if( n != FuncInfo.ExpectParms )
  629. appThrowf( TEXT("%s must have %i parameters"), NestName, FuncInfo.ExpectParms-1 );
  630.  
  631. if( !TopFunction->GetReturnProperty() )
  632. appThrowf( TEXT("Operator must have a return value") );
  633.  
  634. if( !(FuncInfo.FunctionFlags & FUNC_Final) )
  635. appThrowf( TEXT("Operators must be declared as 'Final'") );
  636. }
  637.  
  638. // Make new UDelegateProperty for delegate
  639. if( TopFunction->FunctionFlags & FUNC_Delegate )
  640. {
  641. UProperty* Prev=NULL;
  642. for( TFieldIterator<UProperty,CLASS_IsAUProperty> It(Scope); It && It.GetStruct()==Scope; ++It )
  643. {
  644. Prev = *It;
  645. }
  646.  
  647. // check for any delegate properties that reference this delegate
  648. for (TObjectIterator<UDelegateProperty> It; It; ++It)
  649. {
  650. UDelegateProperty *delegateProp = Cast<UDelegateProperty>(*It);
  651. if (delegateProp != NULL &&
  652. delegateProp->Function == NULL &&
  653. delegateProp->DelegateName == TopFunction->FriendlyName)
  654. {
  655. // and fix up the function reference
  656. delegateProp->Function = TopFunction;
  657. debugf(TEXT("Fixed up delegate reference %s to %s"),delegateProp->GetName(),*TopFunction->FriendlyName);
  658. }
  659. }
  660.  
  661. FName PropName = FName(*FString::Printf(TEXT("__%s__Delegate"),*TopFunction->FriendlyName), FNAME_Add);
  662. UProperty* NewProperty = new(Scope, PropName, RF_Public)UDelegateProperty;
  663. Cast<UDelegateProperty>(NewProperty)->Function = TopFunction;
  664.  
  665. if( Prev )
  666. {
  667. NewProperty->Next = Prev->Next;
  668. Prev->Next = NewProperty;
  669. }
  670. else
  671. {
  672. NewProperty->Next = Scope->Children;
  673. Scope->Children = NewProperty;
  674. }
  675. }
  676.  
  677. // Detect whether the function is being defined or declared.
  678. if( PeekSymbol(TEXT(";")) )
  679. {
  680. // Function is just being declared, not defined.
  681. check( (TopFunction->FunctionFlags & FUNC_Defined)==0 );
  682. }
  683. else
  684. {
  685. // Function is being defined.
  686. TopFunction->FunctionFlags |= FUNC_Defined;
  687. if( TopFunction->FunctionFlags & FUNC_Native )
  688. appThrowf( TEXT("Native functions may only be declared, not defined") );
  689.  
  690. // Require bracket.
  691. RequireSymbol( TEXT("{"), NestName );
  692.  
  693. NeedSemicolon=0;
  694. }
  695.  
  696. // Verify parameter list and return type compatibility within the
  697. // function, if any, that it overrides.
  698. for( INT i=NestLevel-2; i>=1; i-- )
  699. {
  700. for( TFieldIterator<UFunction> Function(Nest[i].Node); Function; ++Function )
  701. {
  702. // Allow private functions to be redefined.
  703. if
  704. ( Function->GetFName()==TopNode->GetFName()
  705. && *Function!=TopNode
  706. && (Function->FunctionFlags & FUNC_Private) )
  707. {
  708. TopNode->SuperField = NULL;
  709. goto Found;
  710. }
  711.  
  712. // If the other function's name matches this one's, process it.
  713. if
  714. ( Function->GetFName()==TopNode->GetFName()
  715. && *Function!=TopNode
  716. && ((Function->FunctionFlags ^ TopFunction->FunctionFlags) & (FUNC_Operator | FUNC_PreOperator))==0 )
  717. {
  718. // Check precedence.
  719. if( Function->OperPrecedence!=TopFunction->OperPrecedence && Function->NumParms==TopFunction->NumParms )
  720. appThrowf( TEXT("Overloaded operator differs in precedence") );
  721.  
  722. // See if all parameters match.
  723. if
  724. ( TopFunction->NumParms!=Function->NumParms
  725. || (!TopFunction->GetReturnProperty())!=(!Function->GetReturnProperty()) )
  726. appThrowf( TEXT("Redefinition of '%s %s' differs from original"), NestName, FuncInfo.Function.Identifier );
  727.  
  728. // Check all individual parameters.
  729. INT Count=0;
  730. for( TFieldIterator<UProperty,CLASS_IsAUProperty> It1(TopFunction),It2(*Function); Count<Function->NumParms; ++It1,++It2,++Count )
  731. {
  732. if( !FPropertyBase(*It1).MatchesType(FPropertyBase(*It2), 1) )
  733. {
  734. if( It1->PropertyFlags & CPF_ReturnParm )
  735. appThrowf( TEXT("Redefinition of %s %s differs only by return type"), NestName, FuncInfo.Function.Identifier );
  736. else if( !(FuncInfo.FunctionFlags & FUNC_Operator) )
  737. appThrowf( TEXT("Redefinition of '%s %s' differs from original"), NestName, FuncInfo.Function.Identifier );
  738. break;
  739. }
  740. }
  741. if( Count<TopFunction->NumParms )
  742. continue;
  743.  
  744. // Function flags to copy from parent.
  745. FuncInfo.FunctionFlags |= (Function->FunctionFlags & FUNC_FuncInherit);
  746.  
  747. // Balk if required specifiers differ.
  748. if( (Function->FunctionFlags&FUNC_FuncOverrideMatch) != (FuncInfo.FunctionFlags&FUNC_FuncOverrideMatch) )
  749. appThrowf( TEXT("Function '%s' specifiers differ from original"), Function->GetName() );
  750.  
  751. // Are we overriding a function?
  752. if( TopNode==Function->GetOuter() )
  753. {
  754. // Duplicate.
  755. PerformRetry( FuncNameRetry );
  756. appThrowf( TEXT("Duplicate function '%s'"), Function->GetName() );
  757. }
  758. else
  759. {
  760. // Overriding an existing function.
  761. if( Function->FunctionFlags & FUNC_Final )
  762. {
  763. PerformRetry(FuncNameRetry);
  764. appThrowf( TEXT("%s: Can't override a 'final' function"), Function->GetName() );
  765. }
  766. }
  767.  
  768. // Here we have found the original.
  769. TopNode->SuperField = *Function;
  770. goto Found;
  771. }
  772. }
  773. }
  774. Found:
  775.  
  776. // Bind the function.
  777. TopFunction->Bind();
  778.  
  779. // If declaring a function, end the nesting.
  780. if( !(TopFunction->FunctionFlags & FUNC_Defined) )
  781. PopNest( NEST_Function, NestName );
  782.  
  783. }
  784. else if( Token.Matches(NAME_Const) )
  785. {
  786. CompileConst( Class );
  787. }
  788. else if( Token.Matches(NAME_Var) || Token.Matches(NAME_Local) )
  789. {
  790. // Variable definition.
  791. QWORD Disallow;
  792. if( Token.Matches(NAME_Var) )
  793. {
  794. // Declaring per-object variables.
  795. CheckAllow( TEXT("'Var'"), ALLOW_VarDecl );
  796. if( TopNest->NestType != NEST_Class )
  797. appThrowf( TEXT("Instance variables are only allowed at class scope (use 'local'?)") );
  798. Disallow = CPF_ParmFlags;
  799. }
  800. else
  801. {
  802. // Declaring local variables.
  803. CheckAllow( TEXT("'Local'"), ALLOW_VarDecl );
  804. if( TopNest->NestType == NEST_Class )
  805. appThrowf( TEXT("Local variables are only allowed in functions") );
  806. Disallow = ~0;
  807. }
  808.  
  809. // Get category, if any.
  810. FName EdCategory = NAME_None;
  811. QWORD EdFlags = 0;
  812. if( MatchSymbol(TEXT("(")) )
  813. {
  814. // Get optional property editing category.
  815. EdFlags |= CPF_Edit;
  816. FToken Category;
  817. if( GetIdentifier( Category, 1 ) ) EdCategory = FName( Category.Identifier );
  818. else EdCategory = Class->GetFName();
  819.  
  820. if( !MatchSymbol(TEXT(")")) )
  821. appThrowf( TEXT("Missing ')' after editable category") );
  822. }
  823.  
  824. // Compile the variable type.
  825. FPropertyBase OriginalProperty(CPT_None);
  826. DWORD ObjectFlags=0;
  827. GetVarType( TopNode, OriginalProperty, ObjectFlags, Disallow, TEXT("Variable declaration") );
  828. OriginalProperty.PropertyFlags |= EdFlags;
  829.  
  830. // If editable but no category was specified, the category name is our class name.
  831. if( (OriginalProperty.PropertyFlags & CPF_Edit) && (EdCategory==NAME_None) )
  832. EdCategory = Class->GetFName();
  833.  
  834. // Validate combinations.
  835. if( (OriginalProperty.PropertyFlags & (CPF_Transient|CPF_Native)) && TopNest->NestType!=NEST_Class )
  836. appThrowf( TEXT("Static and local variables may not be transient or native") );
  837. if( OriginalProperty.PropertyFlags & CPF_ParmFlags )
  838. appThrowf( TEXT("Illegal type modifiers in variable") );
  839.  
  840. // Process all variables of this type.
  841. do
  842. {
  843. UProperty* newProperty;
  844. FPropertyBase Property = OriginalProperty;
  845. newProperty = GetVarNameAndDim( TopNode, Property, ObjectFlags, 0, 0, NULL, TEXT("Variable declaration"), EdCategory, 0 );
  846. if( newProperty )
  847. {
  848. UnReferencedLocal *newLocal = new UnReferencedLocal;
  849. newLocal->next = unReferencedLocals;
  850. newLocal->property = newProperty;
  851. newLocal->declarationLine = InputLine;
  852. unReferencedLocals = newLocal;
  853. }
  854. } while( MatchSymbol(TEXT(",")) );
  855.  
  856. // Propagate alignment restrictions.
  857. if( Token.Matches(NAME_Var) && (OriginalProperty.Type == CPT_Struct) && OriginalProperty.Struct && (OriginalProperty.ArrayDim != 0) )
  858. Class->MinAlignment = Max( Class->MinAlignment, OriginalProperty.Struct->MinAlignment );
  859. }
  860. else if( Token.Matches(NAME_Enum) )
  861. {
  862. // Enumeration definition.
  863. CheckAllow( TEXT("'Enum'"), ALLOW_VarDecl );
  864.  
  865. // Compile enumeration.
  866. CompileEnum( Class );
  867.  
  868. }
  869. else if( Token.Matches(NAME_Struct) )
  870. {
  871. // Struct definition.
  872. CheckAllow( TEXT("'struct'"), ALLOW_VarDecl );
  873.  
  874. // Compile struct.
  875. CompileStruct( Class );
  876. }
  877. else if
  878. ( Token.Matches(NAME_State)
  879. || Token.Matches(NAME_Auto)
  880. || Token.Matches(NAME_Simulated) )
  881. {
  882. // State block.
  883. check(TopNode!=NULL);
  884. CheckAllow( TEXT("'State'"), ALLOW_State );
  885. DWORD StateFlags=0, GotState=0;
  886.  
  887. // Process all specifiers.
  888. for( ;; )
  889. {
  890. if( Token.Matches(NAME_State) )
  891. {
  892. GotState=1;
  893. if( MatchSymbol(TEXT("(")) )
  894. {
  895. RequireSymbol( TEXT(")"), TEXT("'State'") );
  896. StateFlags |= STATE_Editable;
  897. }
  898. }
  899. else if( Token.Matches(NAME_Simulated) )
  900. {
  901. StateFlags |= STATE_Simulated;
  902. }
  903. else if( Token.Matches(NAME_Auto) )
  904. {
  905. StateFlags |= STATE_Auto;
  906. }
  907. else
  908. {
  909. UngetToken(Token);
  910. break;
  911. }
  912. GetToken(Token);
  913. }
  914. if( !GotState )
  915. appThrowf( TEXT("Missing 'State'") );
  916.  
  917. // Get name and default parent state.
  918. FToken NameToken;
  919. if( !GetIdentifier(NameToken) )
  920. appThrowf( TEXT("Missing state name") );
  921. UState* ParentState = Cast<UState>(FindField( TopNode, NameToken.Identifier, UState::StaticClass(), TEXT("'state'") ));
  922. if( ParentState && ParentState->GetOwnerClass()==Class )
  923. appThrowf( TEXT("Duplicate state '%s'"), NameToken.Identifier );
  924.  
  925. // Check for 'extends' keyword.
  926. if( MatchIdentifier(NAME_Extends) )
  927. {
  928. FToken ParentToken;
  929. if( ParentState )
  930. appThrowf( TEXT("'Extends' not allowed here: state '%s' overrides version in parent class"), NameToken.Identifier );
  931. if( !GetIdentifier(ParentToken) )
  932. appThrowf( TEXT("Missing parent state name") );
  933. ParentState = Cast<UState>(FindField( TopNode, ParentToken.Identifier, UState::StaticClass(), TEXT("'state'") ));
  934. if( !ParentState )
  935. appThrowf( TEXT("'extends': Parent state '%s' not found"), ParentToken.Identifier );
  936. }
  937.  
  938. // Begin the state block.
  939. PushNest( NEST_State, NameToken.Identifier, NULL );
  940. UState* State = CastChecked<UState>( TopNode );
  941. State->StateFlags |= StateFlags;
  942. State->SuperField = ParentState;
  943. RequireSymbol( TEXT("{"), TEXT("'State'") );
  944. NeedSemicolon=0;
  945. SupressDebugInfo = -1;
  946. }
  947. else if( Token.Matches(NAME_Ignores) )
  948. {
  949. // Probes to ignore in this state.
  950. CheckAllow( TEXT("'Ignores'"), ALLOW_Ignores );
  951. for( ; ; )
  952. {
  953. FToken IgnoreFunction;
  954. if( !GetToken(IgnoreFunction) )
  955. appThrowf( TEXT("'Ignores': Missing probe function name") );
  956. if
  957. ( IgnoreFunction.TokenName==NAME_None
  958. || IgnoreFunction.TokenName.GetIndex() < NAME_PROBEMIN
  959. || IgnoreFunction.TokenName.GetIndex() >= NAME_PROBEMAX )
  960. {
  961. for( INT i=NestLevel-2; i>=1; i-- )
  962. {
  963. for( TFieldIterator<UFunction> Function(Nest[i].Node); Function; ++Function )
  964. {
  965. if( Function->GetFName()==IgnoreFunction.TokenName )
  966. {
  967. // Verify that function is ignoreable.
  968. if( Function->FunctionFlags & FUNC_Final )
  969. appThrowf( TEXT("'%s': Cannot ignore final functions"), Function->GetName() );
  970.  
  971. // Insert empty function definition to intercept the call.
  972. PushNest( NEST_Function, Function->GetName(), NULL );
  973. UFunction* TopFunction = ((UFunction*) TopNode );
  974. TopFunction->FunctionFlags |= (Function->FunctionFlags & FUNC_FuncOverrideMatch);
  975. TopFunction->NumParms = Function->NumParms;
  976. TopFunction->SuperField = *Function;
  977.  
  978. // Copy parameters.
  979. UField** PrevLink = &TopFunction->Children;
  980. check(*PrevLink==NULL);
  981. for( TFieldIterator<UProperty,CLASS_IsAUProperty> It(*Function); It && (It->PropertyFlags & CPF_Parm); ++It )
  982. {
  983. UProperty* NewProperty=NULL;
  984. if( It->IsA(UByteProperty::StaticClass()) )
  985. {
  986. NewProperty = new(TopFunction,It->GetName(),RF_Public)UByteProperty;
  987. Cast<UByteProperty>(NewProperty)->Enum = Cast<UByteProperty>(*It)->Enum;
  988. }
  989. else if( It->IsA(UIntProperty::StaticClass()) )
  990. {
  991. NewProperty = new(TopFunction,It->GetName(),RF_Public)UIntProperty;
  992. }
  993. else if( It->IsA(UBoolProperty::StaticClass()) )
  994. {
  995. NewProperty = new(TopFunction,It->GetName(),RF_Public)UBoolProperty;
  996. }
  997. else if( It->IsA(UFloatProperty::StaticClass()) )
  998. {
  999. NewProperty = new(TopFunction,It->GetName(),RF_Public)UFloatProperty;
  1000. }
  1001. else if( It->IsA(UClassProperty::StaticClass()) )
  1002. {
  1003. NewProperty = new(TopFunction,It->GetName(),RF_Public)UClassProperty;
  1004. Cast<UObjectProperty>(NewProperty)->PropertyClass = Cast<UObjectProperty>(*It)->PropertyClass;
  1005. Cast<UClassProperty>(NewProperty)->MetaClass = Cast<UClassProperty>(*It)->MetaClass;
  1006. }
  1007. else if( It->IsA(UObjectProperty::StaticClass()) )
  1008. {
  1009. NewProperty = new(TopFunction,It->GetName(),RF_Public)UObjectProperty;
  1010. Cast<UObjectProperty>(NewProperty)->PropertyClass = Cast<UObjectProperty>(*It)->PropertyClass;
  1011. }
  1012. else if( It->IsA(UNameProperty::StaticClass()) )
  1013. {
  1014. NewProperty = new(TopFunction,It->GetName(),RF_Public)UNameProperty;
  1015. }
  1016. else if( It->IsA(UStrProperty::StaticClass()) )
  1017. {
  1018. NewProperty = new(TopFunction,It->GetName(),RF_Public)UStrProperty;
  1019. }
  1020. else if( It->IsA(UStructProperty::StaticClass()) )
  1021. {
  1022. NewProperty = new(TopFunction,It->GetName(),RF_Public)UStructProperty;
  1023. Cast<UStructProperty>(NewProperty)->Struct = Cast<UStructProperty>(*It)->Struct;
  1024. }
  1025. else appErrorf( TEXT("Unknown property type %s"), It->GetClass()->GetName() );
  1026. NewProperty->ArrayDim = It->ArrayDim;
  1027. NewProperty->PropertyFlags = It->PropertyFlags;
  1028. *PrevLink = NewProperty;
  1029. PrevLink = &(*PrevLink)->Next;
  1030. }
  1031.  
  1032. // Finish up.
  1033. PopNest( NEST_Function, TEXT("Ignores") );
  1034. goto FoundIgnore;
  1035. }
  1036. }
  1037. }
  1038. appThrowf( TEXT("'Ignores': '%s' is not a function"), IgnoreFunction.Identifier );
  1039. FoundIgnore:;
  1040. }
  1041. else
  1042. {
  1043. // Ignore a probe function.
  1044. UState* State = CastChecked<UState>( TopNode );
  1045. State->IgnoreMask &= ~((QWORD)1 << (IgnoreFunction.TokenName.GetIndex() - NAME_PROBEMIN));
  1046. }
  1047.  
  1048. // More?
  1049. if( !MatchSymbol(TEXT(",")) )
  1050. break;
  1051. }
  1052. }
  1053. else if( Token.Matches(NAME_Replication) )
  1054. {
  1055. // Network replication definition.
  1056. if( TopNest->NestType != NEST_Class )
  1057. appThrowf( TEXT("'Replication' is not allowed here") );
  1058. RequireSymbol( TEXT("{"), TEXT("'Replication'") );
  1059. TopNode->TextPos = InputPos;
  1060. TopNode->Line = InputLine;
  1061. SkipStatements( 1, TEXT("'Replication'") );
  1062.  
  1063. NeedSemicolon=0;
  1064. }
  1065. else if( Token.Matches(TEXT("#")) )
  1066. {
  1067. // Compiler directive.
  1068. CompileDirective();
  1069. NeedSemicolon=0;
  1070. }
  1071. else
  1072. {
  1073. // Not a declaration.
  1074. return 0;
  1075. }
  1076. return 1;
  1077. }
Add Comment
Please, Sign In to add comment