Script_Compiler.cpp 71 KB

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