gcsx_compile.cpp 155 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105
  1. /* GCSx
  2. ** COMPILE.CPP
  3. **
  4. ** Bytecode compilation (to pre-link state)
  5. */
  6. /*****************************************************************************
  7. ** Copyright (C) 2003-2006 Janson
  8. **
  9. ** This program is free software; you can redistribute it and/or modify
  10. ** it under the terms of the GNU General Public License as published by
  11. ** the Free Software Foundation; either version 2 of the License, or
  12. ** (at your option) any later version.
  13. **
  14. ** This program is distributed in the hope that it will be useful,
  15. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ** GNU General Public License for more details.
  18. **
  19. ** You should have received a copy of the GNU General Public License
  20. ** along with this program; if not, write to the Free Software
  21. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  22. *****************************************************************************/
  23. #include "all.h"
  24. // Code has been ear-marked for places that must be revisted if certain
  25. // features are later added; search for the following:
  26. // OPERATOR++ (refers to prefix or postfix -- or ++)
  27. // OPERATOR+= (refers to the entire family of similar assignment operators)
  28. // @TODO: all compiler and tokenizer asserts need throw_Compile and need
  29. // catch blocks if memory resources need to be freed (such as Operands)
  30. // @TODO: sub-expression memoization
  31. // @TODO:
  32. // warning if a function definitively never returns and isn't main ('end' doesn't count?)
  33. // some optimizations:
  34. // value left over after an expression (e.g. a bare function) doesn't HAVE to be DISCARD'd yet (can accumulate, but watch out for labels/etc)
  35. // DISCARD followed by PUSH could sometimes be a STORE
  36. // POP followed by equivalent PUSH could be a STORE
  37. // RETurning local[0] doesn't need it to be PUSHed first (just return it and reduce # of entries discarded)
  38. // In fact, returning local[x] could be done as DISCARD, RET instead of PUSH, RET (would be faster)
  39. // JUMP, IFTRUE, IFFALSE, SUBR to a JUMP, RET, or STOP is redundant (SUBR to RET shouldn't happen)
  40. // IFTRUE, IFFALSE followed by a JUMP should be condensed (flipping the condition)
  41. // IFTRUE, IFFALSE, JUMP to the next opcode should be removed
  42. // (remove NOOPs if ever used)
  43. // PUSH of a literal followed by later converting that literal (ex: float a = 5 / b does this)
  44. // DISCARD followed by STOP is unneeded
  45. // PUSH followed by DISCARD should be removed
  46. // defining members for built-in object types
  47. struct ObjectMember {
  48. int objtype;
  49. const char* name;
  50. int index;
  51. DataType membertype;
  52. int readonly;
  53. };
  54. static ObjectMember memberTable[] = {
  55. { SUB_SPRITE, "x", Sprite::PROP_X, { DATA_INT, 0, 0 }, 0 },
  56. { SUB_SPRITE, "y", Sprite::PROP_Y, { DATA_INT, 0, 0 }, 0 },
  57. { SUB_SPRITE, "originx", Sprite::PROP_ORIGIN_X, { DATA_INT, 0, 0 }, 0 },
  58. { SUB_SPRITE, "originy", Sprite::PROP_ORIGIN_Y, { DATA_INT, 0, 0 }, 0 },
  59. { SUB_SPRITE, "priority", Sprite::PROP_PRIORITY, { DATA_INT, 0, 0 }, 1 },
  60. { SUB_ENTITY, "name", Entity::PROP_NAME, { DATA_STR, 0, 0 }, 1 },
  61. { SUB_ENTITY, "sprite", Entity::PROP_SPRITE, { DATA_OBJECT, SUB_SPRITE, 0 }, 0 },
  62. { SUB_ENTITY, "priority", Entity::PROP_PRIORITY, { DATA_INT, 0, 0 }, 1 },
  63. { 0, NULL, 0, {0, 0, 0}, 0 }
  64. };
  65. Compiler::Compiler(const list<string>* src, const World* srcWorld) : stringMap(), main(), localInit(), functions(), strings() { start_func
  66. source = src;
  67. world = srcWorld;
  68. t = NULL;
  69. func = NULL;
  70. vars = NULL;
  71. labels = NULL;
  72. errorCount = 0;
  73. warningCount = 0;
  74. inFunctionScope = 0;
  75. main.stackDepth = 0;
  76. localInit.stackDepth = 0;
  77. functions.stackDepth = 0;
  78. strings.stackDepth = 0;
  79. }
  80. Compiler::~Compiler() { start_func
  81. delete t;
  82. destroyVariableMap(vars);
  83. delete vars;
  84. destroyLabelMap(labels);
  85. delete labels;
  86. }
  87. int Compiler::parseSymbols(FunctionMap* funcMap) { start_func
  88. assert(funcMap);
  89. t = new Tokenizer(source);
  90. func = funcMap;
  91. errorCount = 0;
  92. #ifdef COMPILEASSERT
  93. try {
  94. #endif
  95. doParseSymbols();
  96. #ifdef COMPILEASSERT
  97. }
  98. catch (CompileException& e) {
  99. destroyFunctionMap(funcMap);
  100. errorCount = 1;
  101. }
  102. #endif
  103. func = NULL;
  104. delete t;
  105. t = NULL;
  106. return errorCount;
  107. }
  108. int Compiler::compile(Uint32** bytecode, FunctionMap* funcMap, list<LinkEntry>* links, int scriptId) { start_func
  109. assert(bytecode);
  110. assert(funcMap);
  111. assert(links);
  112. assert(scriptId >= SUB_ENTITY_FIRST);
  113. t = new Tokenizer(source);
  114. func = funcMap;
  115. vars = new VariableMap;
  116. labels = new LabelMap;
  117. scriptType = scriptId;
  118. #ifdef COMPILEASSERT
  119. try {
  120. #endif
  121. doCompile(bytecode, links);
  122. #ifdef COMPILEASSERT
  123. }
  124. catch (CompileException& e) {
  125. t->outputError(e.details);
  126. }
  127. #endif
  128. errorCount = t->numErrors();
  129. warningCount = t->numWarnings();
  130. destroyVariableMap(vars);
  131. delete vars;
  132. destroyLabelMap(labels);
  133. delete labels;
  134. labels = NULL;
  135. vars = NULL;
  136. func = NULL;
  137. delete t;
  138. t = NULL;
  139. return errorCount;
  140. }
  141. void Compiler::doParseSymbols() { start_func
  142. assert(func);
  143. assert(t);
  144. int type;
  145. string token;
  146. // Ensure error output is off
  147. t->silentErrors();
  148. // Scan for functions, format- (parens much match if present)
  149. // [datatype] identifier [(] [datatype identifier [, datatype identifier ...]] [)] {
  150. // Also scan for scopes, format-
  151. // state identifier {
  152. // Will also handle certain # configuration commands
  153. // Any other commands or entire blocks are ignored
  154. DataType datatype;
  155. datatype.baseType = 0;
  156. int keywState = 0;
  157. string state;
  158. string ident;
  159. while (t->peekToken(type, token)) {
  160. int doSkip = 0;
  161. if (isDataType(type)) {
  162. // Note datatype and loop for next token
  163. datatype = parseDataType();
  164. if (keywState) doSkip = 1;
  165. }
  166. else if (type == TOKEN_IDENTIFIER) {
  167. ident = token;
  168. t->skipToken();
  169. if (keywState) {
  170. // Next token MUST be brace
  171. t->peekToken(type, token);
  172. if (type == TOKEN_OPEN_BRACE) {
  173. state = ident + "::";
  174. t->skipToken();
  175. }
  176. // Anything that doesn't follow the above format is just ignored
  177. // (main compile will remark on errors)
  178. keywState = 0;
  179. }
  180. else if (datatype.baseType) {
  181. vector<Parameter> plist;
  182. if (parseParameterList(plist)) {
  183. // Next token MUST be brace
  184. t->peekToken(type, token);
  185. if (type == TOKEN_OPEN_BRACE) {
  186. // Build function struct
  187. Function newFunc;
  188. newFunc.returntype = datatype;
  189. newFunc.returntype.flags &= ~(DATA_CONST | DATA_LOCAL | DATA_GLOBAL | DATA_PRIVATE | DATA_PUBLIC);
  190. newFunc.offset = -1;
  191. newFunc.numparam = plist.size();
  192. if (newFunc.numparam) {
  193. // Compile list of parameter types
  194. DataType* where = newFunc.parameters = new DataType[newFunc.numparam];
  195. for (vector<Parameter>::iterator pos = plist.begin(); pos != plist.end(); ++pos) {
  196. *where++ = (*pos).type;
  197. }
  198. }
  199. else newFunc.parameters = NULL;
  200. // Build function name
  201. ident = state + ident;
  202. // Store in map (overwrites previous if found)
  203. addFunctionMap(func, ident) = newFunc;
  204. // Don't skip token- we need to see { to skip function block
  205. }
  206. }
  207. // Anything that doesn't follow the above format is just ignored
  208. // (main compile will remark on errors)
  209. doSkip = 1;
  210. }
  211. else {
  212. doSkip = 1;
  213. }
  214. }
  215. else if (type == KEYW_STATE) {
  216. // Loop for next token
  217. keywState = 1;
  218. t->skipToken();
  219. if (datatype.baseType) doSkip = 1;
  220. }
  221. else if (type == TOKEN_CLOSE_BRACE) {
  222. state = blankString;
  223. t->skipToken();
  224. datatype.baseType = 0;
  225. keywState = 0;
  226. }
  227. else {
  228. doSkip = 1;
  229. }
  230. if (doSkip) {
  231. // Loop until end of line, skipping over blocks
  232. int blockLevel = 0;
  233. while (t->nextToken(type, token)) {
  234. if (type == TOKEN_OPEN_BRACE) ++blockLevel;
  235. if (type == TOKEN_CLOSE_BRACE) --blockLevel;
  236. if (((type == TOKEN_ENDLINE) || (type == TOKEN_CLOSE_BRACE)) &&
  237. (blockLevel == 0)) break;
  238. }
  239. datatype.baseType = 0;
  240. keywState = 0;
  241. }
  242. }
  243. }
  244. int Compiler::isDataType(int tokenType) { start_func
  245. if ((tokenType == KEYW_ARRAY) || (tokenType == KEYW_HASH) ||
  246. (tokenType == KEYW_INT) || (tokenType == KEYW_STR) ||
  247. (tokenType == KEYW_FLOAT) || (tokenType == KEYW_VAR) ||
  248. (tokenType == KEYW_GLOBAL) || (tokenType == KEYW_LOCAL) ||
  249. (tokenType == KEYW_CONST) || (tokenType == KEYW_VOID) ||
  250. (tokenType == KEYW_PRIVATE) || (tokenType == KEYW_PUBLIC) ||
  251. (tokenType == KEYW_OBJ_ENTITY) || (tokenType == KEYW_OBJ_SPRITE) ||
  252. (tokenType == KEYW_OBJ_SCENE) || (tokenType == TOKEN_STRINGTYPE))
  253. return 1;
  254. return 0;
  255. }
  256. DataType Compiler::parseDataType() { start_func
  257. DataType datatype;
  258. datatype.baseType = 0;
  259. datatype.flags = 0;
  260. datatype.subType = 0;
  261. int type;
  262. string token;
  263. while ((t->peekToken(type, token)) && (isDataType(type))) {
  264. t->skipToken();
  265. int base = 0, sub = 0, varConflict = 0, objConflict = 0;
  266. int flag = 0, flagConflict = 0;
  267. switch (type) {
  268. case KEYW_ARRAY:
  269. flag = DATA_ARRAY;
  270. flagConflict = DATA_HASH | DATA_CONST;
  271. break;
  272. case KEYW_HASH:
  273. flag = DATA_HASH;
  274. flagConflict = DATA_ARRAY | DATA_CONST;
  275. break;
  276. case KEYW_CONST:
  277. flag = DATA_CONST;
  278. flagConflict = DATA_HASH | DATA_CONST;
  279. varConflict = 1;
  280. objConflict = 1;
  281. break;
  282. case KEYW_VOID:
  283. base = DATA_VOID;
  284. flagConflict = DATA_HASH | DATA_ARRAY | DATA_CONST | DATA_LOCAL | DATA_GLOBAL;
  285. break;
  286. case KEYW_VAR:
  287. base = DATA_VAR;
  288. flagConflict = DATA_CONST;
  289. break;
  290. case KEYW_STR:
  291. base = DATA_STR;
  292. break;
  293. case KEYW_FLOAT:
  294. base = DATA_FLOAT;
  295. break;
  296. case KEYW_INT:
  297. base = DATA_INT;
  298. break;
  299. case KEYW_OBJ_ENTITY:
  300. // obj_entity doesn't conflict with script type
  301. if ((datatype.baseType == DATA_ENTITY) && (datatype.subType))
  302. datatype.baseType = 0;
  303. base = DATA_ENTITY;
  304. sub = 0;
  305. flagConflict = DATA_CONST;
  306. break;
  307. case KEYW_OBJ_SPRITE:
  308. base = DATA_OBJECT;
  309. sub = SUB_SPRITE;
  310. flagConflict = DATA_CONST;
  311. break;
  312. case KEYW_OBJ_SCENE:
  313. base = DATA_OBJECT;
  314. sub = SUB_SCENE;
  315. flagConflict = DATA_CONST;
  316. break;
  317. case KEYW_LOCAL:
  318. flag = DATA_LOCAL;
  319. flagConflict = DATA_GLOBAL;
  320. break;
  321. case KEYW_GLOBAL:
  322. flag = DATA_GLOBAL;
  323. flagConflict = DATA_LOCAL | DATA_PUBLIC | DATA_PRIVATE;
  324. break;
  325. case KEYW_PRIVATE:
  326. flag = DATA_PRIVATE;
  327. flagConflict = DATA_PUBLIC | DATA_GLOBAL;
  328. break;
  329. case KEYW_PUBLIC:
  330. flag = DATA_PUBLIC;
  331. flagConflict = DATA_PRIVATE | DATA_GLOBAL;
  332. break;
  333. case TOKEN_STRINGTYPE: {
  334. // script type doesn't conflict with obj_entity
  335. if ((datatype.baseType == DATA_ENTITY) && (datatype.subType == 0))
  336. datatype.baseType = 0;
  337. Script* found = world->findScriptCode(token);
  338. if (found) {
  339. sub = found->getId();
  340. }
  341. else {
  342. t->outputError("Unknown script type '%s' (no script by that name)", token.c_str());
  343. // RESOLUTION: fake sub type
  344. sub = SUB_ENTITY_FIRST;
  345. }
  346. base = DATA_ENTITY;
  347. break;
  348. }
  349. }
  350. if ((varConflict && datatype.baseType == DATA_VAR) ||
  351. (objConflict && (datatype.baseType == DATA_OBJECT || datatype.baseType == DATA_ENTITY))) {
  352. t->outputError("Conflicting datatype '%s' (two or more given types cannot be used together)", token.c_str());
  353. // RESOLUTION: ignore conflicting datatype
  354. }
  355. else {
  356. if (base) {
  357. if (datatype.baseType == base) {
  358. t->outputWarning("Duplicated datatype '%s' (datatype is listed twice)", token.c_str());
  359. // RESOLUTION: ignore duplicated datatype
  360. }
  361. else if (datatype.baseType) {
  362. t->outputError("Conflicting datatype '%s' (two or more given types cannot be used together)", token.c_str());
  363. // RESOLUTION: ignore conflicting datatype
  364. }
  365. else {
  366. datatype.baseType = base;
  367. datatype.subType = sub;
  368. }
  369. }
  370. if (datatype.flags & flag) {
  371. t->outputWarning("Duplicated datatype '%s' (datatype is listed twice)", token.c_str());
  372. // RESOLUTION: ignore duplicated datatype
  373. }
  374. else if (datatype.flags & flagConflict) {
  375. t->outputError("Conflicting datatype '%s' (two or more given types cannot be used together)", token.c_str());
  376. // RESOLUTION: ignore conflicting datatype
  377. }
  378. else {
  379. datatype.flags |= flag;
  380. }
  381. }
  382. }
  383. if (!datatype.baseType) {
  384. t->outputError("No base datatype given (must specify 'int', 'str', 'float', etc.)");
  385. // RESOLUTION: assume int
  386. datatype.baseType = DATA_INT;
  387. }
  388. return datatype;
  389. }
  390. int Compiler::parseParameterList(vector<Parameter>& list) { start_func
  391. int type;
  392. string token;
  393. assert(list.empty());
  394. // Optional paren
  395. int paren = 0;
  396. t->peekToken(type, token);
  397. if (type == TOKEN_OPEN_PAREN) {
  398. paren = 1;
  399. t->skipToken();
  400. t->peekToken(type, token);
  401. }
  402. // parameters?
  403. if (isDataType(type)) {
  404. for (;;) {
  405. // (already peeked, above, or at end of loop below)
  406. DataType vartype = parseDataType();
  407. checkDataType(vartype, 1, 1, 1, 1);
  408. t->peekToken(type, token);
  409. if (type != TOKEN_IDENTIFIER) {
  410. t->outputError("Expected parameter identifier here");
  411. // RESOLUTION: parameter list unusable
  412. return 0;
  413. }
  414. // Matches a function?
  415. FunctionMap::iterator flist = func->find(token.c_str());
  416. if (flist != func->end()) {
  417. t->outputError("Function '%s' already exists in this script (parameter variables and functions cannot share names)", token.c_str());
  418. // RESOLUTION: define parameter anyways
  419. }
  420. // Matches a built-in?
  421. for (int pos = 0; memberTable[pos].objtype; ++pos) {
  422. if ((memberTable[pos].objtype == SUB_ENTITY) &&
  423. (token == memberTable[pos].name)) {
  424. t->outputError("'%s' is a built-in entity member (parameter variables cannot override built-in members)", token.c_str());
  425. // RESOLUTION: define parameter anyways
  426. }
  427. }
  428. // All parameters are marked as local
  429. vartype.flags |= DATA_LOCAL;
  430. Parameter param = { vartype, token };
  431. list.push_back(param);
  432. t->skipToken();
  433. t->peekToken(type, token);
  434. if (type == TOKEN_COMMA) {
  435. t->skipToken();
  436. t->peekToken(type, token);
  437. if (!isDataType(type)) {
  438. t->outputError("Expected parameter here (datatype, then identifier)");
  439. // RESOLUTION: assume no more parameters
  440. break;
  441. }
  442. }
  443. else break;
  444. }
  445. }
  446. // End paren? (already peeked previously)
  447. if (type == TOKEN_CLOSE_PAREN) {
  448. t->skipToken();
  449. if (!paren) {
  450. t->outputError("Missing open parenthesis to match closing parenthesis");
  451. // RESOLUTION: pretend paren was there
  452. }
  453. }
  454. else if (paren) {
  455. t->outputError("Missing closing parenthesis to match open parenthesis");
  456. // RESOLUTION: pretend paren was there
  457. }
  458. return (list.empty() && (!paren)) ? -1 : 1;
  459. }
  460. void Compiler::doCompile(Uint32** bytecode, list<LinkEntry>* links) { start_func
  461. assert(bytecode);
  462. assert(func);
  463. assert(t);
  464. assert(vars);
  465. assert(labels);
  466. assert(links);
  467. // First, dealloc any existing bytecode
  468. if (*bytecode) {
  469. delete[] *bytecode;
  470. *bytecode = NULL;
  471. }
  472. // All areas should already be clear
  473. compileAssert(main.code.empty());
  474. compileAssert(main.links.empty());
  475. compileAssert(main.stackDepth == 0);
  476. compileAssert(localInit.code.empty());
  477. compileAssert(localInit.links.empty());
  478. compileAssert(localInit.stackDepth == 0);
  479. compileAssert(functions.code.empty());
  480. compileAssert(functions.links.empty());
  481. compileAssert(functions.stackDepth == 0);
  482. compileAssert(strings.code.empty());
  483. compileAssert(strings.links.empty());
  484. compileAssert(strings.stackDepth == 0);
  485. compileAssert(workspaces.empty());
  486. compileAssert(stringMap.empty());
  487. // Initially adding code to main
  488. pushWorkspace(&main);
  489. scope = -1; // lowest scope will be 0
  490. inFunctionScope = 0;
  491. Ended junk;
  492. compileBlock(junk);
  493. compileAssert(scope == -1);
  494. compileAssert(inFunctionScope == 0);
  495. // Get sizes
  496. int sizeI = localInit.code.size();
  497. int sizeIM = sizeI + main.code.size();
  498. int sizeIMF = sizeIM + functions.code.size();
  499. int sizeIMFS = sizeIMF + strings.code.size();
  500. // Final links adjustment-
  501. // link local strings/functions
  502. // move others to final link table
  503. // (localInit probably won't have links, but it could happen with future improvements)
  504. links->clear();
  505. completeLinkage(links, localInit, 0, sizeIMF, sizeIM);
  506. completeLinkage(links, main, sizeI, sizeIMF - sizeI, sizeIM - sizeI);
  507. completeLinkage(links, functions, sizeIM, sizeIMF - sizeIM, 0);
  508. compileAssert(strings.links.empty());
  509. // Move code back to bytecode
  510. Uint32* work = new Uint32[2 + sizeIMFS];
  511. *bytecode = work;
  512. *work++ = sizeIMFS;
  513. *work++ = sizeIMF;
  514. vector<Uint32>::iterator pos;
  515. vector<Uint32>::iterator end = localInit.code.end();
  516. for (pos = localInit.code.begin(); pos != end; ++pos) *work++ = *pos;
  517. end = main.code.end();
  518. for (pos = main.code.begin(); pos != end; ++pos) *work++ = *pos;
  519. end = functions.code.end();
  520. for (pos = functions.code.begin(); pos != end; ++pos) *work++ = *pos;
  521. end = strings.code.end();
  522. for (pos = strings.code.begin(); pos != end; ++pos) *work++ = *pos;
  523. // Clean up
  524. main.code.clear();
  525. compileAssert(main.links.empty());
  526. compileAssert(main.stackDepth == 0);
  527. localInit.code.clear();
  528. compileAssert(localInit.links.empty());
  529. localInit.stackDepth = 0;
  530. functions.code.clear();
  531. compileAssert(functions.links.empty());
  532. compileAssert(functions.stackDepth == 0);
  533. strings.code.clear();
  534. compileAssert(strings.links.empty());
  535. compileAssert(strings.stackDepth == 0);
  536. workspaces.pop_back();
  537. compileAssert(workspaces.empty());
  538. // We clear one at a time to ensure we can delete hash keys at the right times
  539. StringMap::iterator smpos = stringMap.begin();
  540. while (smpos != stringMap.end()) {
  541. const char* toDel = (*smpos).first;
  542. stringMap.erase(smpos);
  543. delete[] toDel;
  544. smpos = stringMap.begin();
  545. }
  546. }
  547. void Compiler::completeLinkage(list<LinkEntry>* links, Codespace& code, int linkOffset, int strOffset, int funcOffset) { start_func
  548. list<LinkEntry>::iterator pos = code.links.begin();
  549. list<LinkEntry>::iterator end = code.links.end();
  550. for (; pos != end; ++pos) {
  551. if ((*pos).type == LinkEntry::LINK_STRING) {
  552. code.code[(*pos).offset] += strOffset - (*pos).offset;
  553. }
  554. else if ((*pos).type == LinkEntry::LINK_FUNCTION) {
  555. FunctionMap::iterator flist = func->find((*pos).name.c_str());
  556. compileAssert(flist != func->end());
  557. compileAssert((*flist).second.offset >= 0);
  558. code.code[(*pos).offset] += (*flist).second.offset + funcOffset - (*pos).offset;
  559. }
  560. else {
  561. compileAssert((*pos).type != LinkEntry::LINK_LOOP_CONTINUE);
  562. compileAssert((*pos).type != LinkEntry::LINK_LOOP_END);
  563. (*pos).offset += linkOffset;
  564. links->push_back(*pos);
  565. }
  566. }
  567. code.links.clear();
  568. }
  569. void Compiler::compileBlock(Ended& ended, const vector<Parameter>* parameters, DataType* returnType) { start_func
  570. int type;
  571. string token;
  572. int braceBlock = 0;
  573. // Skip remainder of command (until end line or open brace)
  574. int skipCmd = 0;
  575. int exitBlock = 0;
  576. int detectEndOfCommand;
  577. // stackDepth upon entering this code block, so we can discard all NEW vars
  578. int entryStackDepth = ws->stackDepth;
  579. int paramStackDepth = entryStackDepth;
  580. Label* loopLabel = NULL;
  581. string loopLabelName;
  582. int justDidLoopLabel = 0;
  583. ++scope;
  584. enum {
  585. // least-to-most restrictive-
  586. // combining two values (if/else) results in higher scope, lower 'how' if scope tied
  587. ENDED_NONE = 0,
  588. ENDED_CONTINUE = 1, // continue- full stop until it's loop boundary
  589. ENDED_BREAK = 2, // break- full stop until it's loop boundary, also skips do{} ending condition
  590. ENDED_RESTART = 3, // restart- full stop until it's loop boundary, becomes full stop if a do{} loop
  591. ENDED_RETURN = 4, // return/end/infinite loop- full stop (scope set to 0 to always 'lose')
  592. };
  593. // If set, we've returned/stopped, any remaining code is redundant and might get discarded
  594. ended.how = ENDED_NONE;
  595. // For loops, scope of inner loop block that it applies to
  596. ended.scope = scope + 2; // Default to 'highest' scope, so this always 'wins'
  597. // Scope of farthest-out potentially-infinite-loop to break
  598. ended.breakInfinite = scope + 2; // Default to breaking nothing
  599. // Define parameters and function start?
  600. if (parameters) {
  601. for (vector<Parameter>::const_iterator pos = parameters->begin(); pos != parameters->end(); ++pos) {
  602. defineVariable((*pos).type, (*pos).name, 1);
  603. }
  604. // reserve spot for code return pointer
  605. ++ws->stackDepth;
  606. paramStackDepth = ws->stackDepth;
  607. inFunctionScope = scope;
  608. funcEntryStackDepth = entryStackDepth;
  609. funcParamStackDepth = paramStackDepth;
  610. }
  611. if (scope == 0) {
  612. // (local variable initialization will go right before our workspace)
  613. postCmd(OP_INIT);
  614. }
  615. else {
  616. // Beyond top scope, a block can be a single cmd or { block }
  617. // Discard any stray endline
  618. t->peekToken(type, token);
  619. if (type == TOKEN_ENDLINE) {
  620. t->skipToken();
  621. t->peekToken(type, token);
  622. }
  623. // Does our block start with a brace?
  624. if (type == TOKEN_OPEN_BRACE) {
  625. t->skipToken();
  626. braceBlock = 1;
  627. }
  628. }
  629. while (t->peekToken(type, token)) {
  630. detectEndOfCommand = 0;
  631. // Loop label only persists for one token
  632. if (justDidLoopLabel)
  633. justDidLoopLabel = 0;
  634. else {
  635. loopLabel = NULL;
  636. loopLabelName = blankString;
  637. }
  638. // Skipping stuff?
  639. if ((skipCmd) && (type != TOKEN_OPEN_BRACE)) {
  640. if (type == TOKEN_ENDLINE) skipCmd = 0;
  641. t->skipToken();
  642. // that was our one command, if not a brace block
  643. if ((!braceBlock) && (scope)) break;
  644. // next command
  645. continue;
  646. }
  647. skipCmd = 0;
  648. // Ended code? Something other than a closing brace?
  649. if ((ended.how) && (type != TOKEN_CLOSE_BRACE)) {
  650. t->outputWarning("Unreachable code (previous code will prevent this code from ever being executed)");
  651. // RESOLUTION: skip everything until our closing brace, but leave that
  652. int blockLevel = 0;
  653. while (t->peekToken(type, token)) {
  654. if (type == TOKEN_OPEN_BRACE) ++blockLevel;
  655. if (type == TOKEN_CLOSE_BRACE) --blockLevel;
  656. if (blockLevel < 0) break;
  657. t->skipToken();
  658. }
  659. continue;
  660. }
  661. // As a general rule, nothing is left on the stack between full commands
  662. // except for new local variables. Temporaries that must stay on the stack
  663. // must either be right before starting a new block, or be assigned
  664. // an internal temporary local variable; this may change if we determine
  665. // leaving temporaries on the stack can be safe in some situations
  666. // Detect datatypes first, outside of switch
  667. if (isDataType(type)) {
  668. // Datatype for definition
  669. DataType datatype = parseDataType();
  670. // Next MUST be identifier
  671. t->peekToken(type, token);
  672. if (type != TOKEN_IDENTIFIER) {
  673. t->outputError("Expected identifier after datatype (appears to be a function or variable definition)");
  674. // RESOLUTION: ignore rest of command
  675. skipCmd = 1;
  676. }
  677. else {
  678. // Identifier
  679. string ident = token;
  680. t->skipToken();
  681. // Parameters?
  682. vector<Parameter> plist;
  683. int paramResult = parseParameterList(plist);
  684. // Function definition, variable definition, or error?
  685. t->peekToken(type, token);
  686. if ((paramResult) && (type == TOKEN_OPEN_BRACE)) {
  687. // Error-check datatype
  688. checkDataType(datatype, 1, 1, 0, 0);
  689. if (scope) {
  690. t->outputError("Functions must be defined outside all other code blocks");
  691. // RESOLUTION: open brace will just be treated as a scope block now
  692. }
  693. else {
  694. // PARSE: FUNCTION DEFINITION
  695. // Starts at open-brace (denotes block)
  696. // Note position in list
  697. FunctionMap::iterator flist = func->find(ident.c_str());
  698. // (if not found, we shouldn't probably be here, but
  699. // might happen in some situations with symbol preparser)
  700. if (flist != func->end()) {
  701. if ((*flist).second.offset >= 0)
  702. t->outputError("Function '%s' defined twice (you can only create one function with a given name)", ident.c_str());
  703. // RESOLUTION: code gets added, but never referenced
  704. else
  705. // Store offset in function list
  706. (*flist).second.offset = functions.code.size();
  707. }
  708. VariableMap::iterator vlist = vars->find(ident.c_str());
  709. if (vlist != vars->end()) {
  710. t->outputError("Variable '%s' already exists in this script (variables and functions cannot share names)", ident.c_str());
  711. // RESOLUTION: define function anyways
  712. }
  713. for (int pos = 0; memberTable[pos].objtype; ++pos) {
  714. if ((memberTable[pos].objtype == SUB_ENTITY) &&
  715. (ident == memberTable[pos].name)) {
  716. t->outputError("'%s' is a built-in entity member (functions cannot override built-in members)", ident.c_str());
  717. // RESOLUTION: define function anyways
  718. }
  719. }
  720. // Parse function block
  721. compileAssert(ws == &main);
  722. pushWorkspace(&functions);
  723. Ended junk;
  724. compileBlock(junk, &plist, &datatype);
  725. popWorkspace();
  726. compileAssert(functions.stackDepth == 0);
  727. }
  728. }
  729. else if ((paramResult < 0) && ((type == TOKEN_ENDLINE) || (type == OPER_ASSIGN))) {
  730. // Error-check datatype
  731. checkDataType(datatype, 0, 0, 0, 1);
  732. // PARSE: VARIABLE DEFINITION
  733. const Variable& v = defineVariable(datatype, ident);
  734. if (type == OPER_ASSIGN) {
  735. // PARSE: VARIABLE ASSIGNMENT
  736. // (discard =)
  737. t->skipToken();
  738. Operand var = variableToOperand(v);
  739. parseAssignment(var, v.datatype);
  740. // Should be end of command now
  741. t->peekToken(type, token);
  742. }
  743. detectEndOfCommand = 1;
  744. }
  745. else {
  746. // Errors
  747. if (paramResult > 0)
  748. t->outputError("Expected open brace (appears to be a function definition)");
  749. else if (paramResult < 0)
  750. t->outputError("Expected open brace, assignment, or end-of-command (appears to be a function or variable definition)");
  751. // (if 0, parseParameterList already output an error)
  752. // RESOLUTION: ignore rest of command
  753. skipCmd = 1;
  754. }
  755. }
  756. }
  757. else {
  758. switch (type) {
  759. // These types can all start an expression, although currently
  760. // expressions starting with these are gauranteed to be 'wrong'
  761. // in that at least a portion will have no side-effects and should
  762. // produce a warning. Future operators may make these more useful
  763. // so they are here now.
  764. case TOKEN_INTEGER:
  765. case TOKEN_HEX:
  766. case TOKEN_DECIMAL:
  767. case KEYW_TRUE:
  768. case KEYW_FALSE:
  769. case KEYW_QUERY:
  770. case OPER_PLUS:
  771. case OPER_MINUS:
  772. case OPER_B_NOT:
  773. case OPER_L_NOT:
  774. case KEYW_NOTHING:
  775. // These tokens can actually start a useful 'standalone' expression.
  776. case KEYW_ALL:
  777. case KEYW_ALL_OTHER:
  778. case KEYW_THIS:
  779. case KEYW_SOURCE:
  780. case KEYW_DEFAULT:
  781. case TOKEN_STRING:
  782. case TOKEN_OPEN_PAREN:
  783. case TOKEN_IDENTIFIER: {
  784. // Label?
  785. if (type == TOKEN_IDENTIFIER) {
  786. t->bookmarkStore(1);
  787. t->skipToken();
  788. string nextToken;
  789. if ((t->nextToken(type, nextToken)) && (type == TOKEN_LABEL)) {
  790. // Process label token
  791. t->bookmarkCancel(1);
  792. Label newLabel;
  793. newLabel.scope = scope;
  794. newLabel.offset = ws->code.size();
  795. newLabel.isLoop = 0;
  796. newLabel.stackDepth = ws->stackDepth;
  797. // Store label
  798. list<Label>& found = addLabelMap(labels, token);
  799. found.push_back(newLabel);
  800. // (in case a loop is next)
  801. loopLabel = &found.back();
  802. loopLabelName = token;
  803. justDidLoopLabel = 1;
  804. // Use up end-of-command IF present (doesn't count)
  805. t->peekToken(type, token);
  806. if (type == TOKEN_ENDLINE) t->skipToken();
  807. break;
  808. }
  809. else {
  810. t->bookmarkReturn(1);
  811. t->bookmarkCancel(1);
  812. }
  813. }
  814. // Variable assignment, function call, scope, message send, etc.
  815. // All of these are handled via expressions
  816. Operand o = parseExpression(0, 0);
  817. if (!O_IS_SIDEFX(o) && !O_IS_VOID(o))
  818. t->outputWarning("Part or all of expression has no effect (no side effects and result is not used)");
  819. destroyOperand(o);
  820. // Should be end of command now
  821. t->peekToken(type, token);
  822. detectEndOfCommand = 1;
  823. break;
  824. }
  825. case TOKEN_OPEN_BRACE: {
  826. // Build a sub-block of code starting at brace
  827. compileBlock(ended, NULL, returnType);
  828. break;
  829. }
  830. case TOKEN_CLOSE_BRACE: {
  831. t->skipToken();
  832. if (scope == 0) {
  833. t->outputError("Unexpected close brace (does not match an open brace)");
  834. // RESOLUTION: just skip the brace
  835. }
  836. else {
  837. // Done with block
  838. exitBlock = 1;
  839. }
  840. break;
  841. }
  842. case KEYW_RETURN: {
  843. t->skipToken();
  844. // Returning anything?
  845. Operand o;
  846. createEmpty(o);
  847. t->peekToken(type, token);
  848. if ((type != TOKEN_ENDLINE) && (type != TOKEN_OPEN_BRACE)) {
  849. o = parseExpression();
  850. t->peekToken(type, token);
  851. }
  852. processReturn(o, returnType);
  853. ended.how = ENDED_RETURN;
  854. ended.scope = 0;
  855. detectEndOfCommand = 1;
  856. break;
  857. }
  858. case KEYW_END: {
  859. t->skipToken();
  860. // @TODO: don't show warning if main was used
  861. if (inFunctionScope)
  862. t->outputWarning("'end' inside of a function halts any suspended functions as well- did you mean 'return'?");
  863. postCmd(OP_STOP);
  864. ended.how = ENDED_RETURN;
  865. ended.scope = 0;
  866. t->peekToken(type, token);
  867. detectEndOfCommand = 1;
  868. break;
  869. }
  870. case KEYW_IF: {
  871. t->skipToken();
  872. // If-condition
  873. Operand o = parseExpression(2);
  874. if (!o.mode) {
  875. skipCmd = 1;
  876. break;
  877. }
  878. // If cmd
  879. int alwaysJumps, neverJumps;
  880. int offset = postCmdIf(0, 0, o, alwaysJumps, neverJumps);
  881. // Build a sub-block of code starting here
  882. int codeStart = ws->code.size();
  883. Ended endedIf;
  884. compileBlock(endedIf, NULL, returnType);
  885. // Adjust offset to skip new block
  886. if (offset >= 0) ws->code[offset] += ws->code.size() - codeStart;
  887. // else clause? (will automatically chain additional ifs)
  888. t->peekToken(type, token);
  889. if (type == KEYW_ELSE) {
  890. t->skipToken();
  891. // Add to 'if' block a jump to skip past 'else' block IF didn't end
  892. if (endedIf.how)
  893. offset = -1;
  894. else {
  895. // original 'if' jump needs to go 2 spaces further
  896. if (offset >= 0) ws->code[offset] += 2;
  897. // Offset of new 'if' jump (at end of 'if')
  898. offset = ws->code.size() + 1; // (remember where operand is)
  899. // By default, skips to next opcode
  900. postCmdI(OP_JUMP, 0);
  901. }
  902. // 'else' sub-block of code starting here
  903. int codeStart = ws->code.size();
  904. Ended endedElse;
  905. compileBlock(endedElse, NULL, returnType);
  906. // Adjust jump at end of 'if' to skip this block
  907. if (offset >= 0) ws->code[offset] += ws->code.size() - codeStart;
  908. // If both if and else clauses ended, we ended
  909. // Take highest scope
  910. if (endedElse.scope > endedIf.scope) {
  911. ended.how = endedElse.how;
  912. ended.scope = endedElse.scope;
  913. }
  914. else if (endedIf.scope > endedElse.scope) {
  915. ended.how = endedIf.how;
  916. ended.scope = endedIf.scope;
  917. }
  918. else {
  919. // Scope equal, take smallest 'how'
  920. ended.how = min(endedIf.how, endedElse.how);
  921. ended.scope = endedIf.scope; // (same as Else)
  922. }
  923. ended.breakInfinite = min(endedIf.breakInfinite, endedElse.breakInfinite);
  924. }
  925. // @TODO: we could, if we know if was always-true or always-false,
  926. // fill endedHow/Scope more aggressively
  927. // @TODO: discard code entirely if always-true or always-false?
  928. break;
  929. }
  930. case KEYW_ELSE: {
  931. t->outputError("'else' can only appear after an 'if' command or block (did you forget braces around your 'if' blocks?)");
  932. // RESOLUTION: ignore rest of command
  933. skipCmd = 1;
  934. break;
  935. }
  936. case KEYW_DO:
  937. case KEYW_UNTIL:
  938. case KEYW_WHILE: {
  939. t->skipToken();
  940. int loopOffset = ws->code.size();
  941. int continuePos = loopOffset;
  942. int condOffset = -1;
  943. int infiniteLoop = 0; // <= 0 means no, here (-1 means a break gaurantees no infinite)
  944. //int neverLoops = 0;
  945. int skipJumpBack = 0;
  946. // Label marking loop- set scope to sub-block's scope so it
  947. // conveniently deletes it for us; use existing label if any
  948. Label newLabel;
  949. Label* myLabel = loopLabel ? loopLabel : &newLabel;
  950. myLabel->scope = scope + 1;
  951. myLabel->offset = loopOffset; // For 'restart'; 'continue'/'break' linked later
  952. myLabel->isLoop = 1;
  953. myLabel->stackDepth = ws->stackDepth;
  954. // Pre-condition?
  955. if (type != KEYW_DO) {
  956. // Loop condition
  957. Operand o = parseExpression(2);
  958. if (!o.mode) {
  959. skipCmd = 1;
  960. break;
  961. }
  962. // Loop 'if'
  963. int alwaysJumps, neverJumps;
  964. condOffset = postCmdIf(type == KEYW_WHILE ? 0 : 1, 0, o, alwaysJumps, neverJumps);
  965. // (must have same stackdepth now)
  966. compileAssert(myLabel->stackDepth == ws->stackDepth);
  967. // ('restart' position is now here)
  968. myLabel->offset = ws->code.size();
  969. // Special cases
  970. if (alwaysJumps) {
  971. //neverLoops = 1;
  972. t->outputWarning("Code within loop will never execute (loop condition is false and is checked before loop)");
  973. // @TODO: discard code entirely?
  974. }
  975. else if (neverJumps)
  976. infiniteLoop = 1;
  977. }
  978. // Store label if new
  979. if (!loopLabel) {
  980. list<Label>& found = addLabelMap(labels, loopLabelName);
  981. found.push_back(newLabel);
  982. }
  983. // Build a sub-block of code starting here
  984. int codeStart = ws->code.size();
  985. compileBlock(ended, NULL, returnType);
  986. // Handle ended.how now
  987. if (ended.how == ENDED_RETURN) {
  988. // Return- a 'do' loop or infinite loop- prevails
  989. // otherwise- discarded
  990. if ((type != KEYW_DO) && (!infiniteLoop)) {
  991. ended.how = ENDED_NONE;
  992. ended.scope = scope + 2;
  993. }
  994. }
  995. else if (ended.scope > scope) {
  996. // Relates to our scope
  997. // Restart- a 'do' loop- becomes _RETURN (set later) as it's infinite now
  998. if ((ended.how == ENDED_RESTART) && (type == KEYW_DO))
  999. infiniteLoop = 1;
  1000. else if (ended.how > ENDED_NONE) {
  1001. // User handled all loop control for us (doesn't apply to DO loops)
  1002. skipJumpBack = 1;
  1003. // Break- a 'do' loop- final condition is useless,
  1004. // but code afterwards is executed as normal
  1005. if ((ended.how == ENDED_BREAK) && (type == KEYW_DO)) {
  1006. t->outputWarning("Loop condition will never get checked (loop always exits before reaching condition at end)");
  1007. // @TODO: discard code for loop condition?
  1008. }
  1009. ended.how = ENDED_NONE;
  1010. ended.scope = scope + 2;
  1011. }
  1012. }
  1013. if (ended.breakInfinite <= scope) {
  1014. // Breaks thru infinite loops
  1015. infiniteLoop = -1;
  1016. // All types continue downward to proper scope
  1017. }
  1018. // (must have same stackdepth now)
  1019. compileAssert(myLabel->stackDepth == ws->stackDepth);
  1020. // Loop expression still needed? (do loop)
  1021. if (type == KEYW_DO) {
  1022. if (ended.how) {
  1023. t->outputWarning("Loop condition will never get checked (loop always repeats or exits before reaching condition at end)");
  1024. // @TODO: discard code for loop condition?
  1025. }
  1026. t->peekToken(type, token);
  1027. if ((type != KEYW_WHILE) && (type != KEYW_UNTIL)) {
  1028. t->outputError("Unexpected token '%s'- expected 'while' or 'until'", token.c_str());
  1029. // RESOLUTION: treat as new command; block is now just a scope-block that may have used loop controls
  1030. ended.how = ENDED_NONE;
  1031. ended.scope = scope + 2;
  1032. break;
  1033. }
  1034. // Loop condition
  1035. continuePos = ws->code.size();
  1036. t->skipToken();
  1037. Operand o = parseExpression(2);
  1038. if (!o.mode) {
  1039. skipCmd = 1;
  1040. break;
  1041. }
  1042. // Loop 'if'
  1043. int alwaysJumps, neverJumps;
  1044. postCmdIf(type == KEYW_WHILE ? 1 : 0, loopOffset - ws->code.size(), o, alwaysJumps, neverJumps);
  1045. if ((alwaysJumps) && (infiniteLoop == 0))
  1046. infiniteLoop = 1;
  1047. // (must have same stackdepth now)
  1048. compileAssert(myLabel->stackDepth == ws->stackDepth);
  1049. t->peekToken(type, token);
  1050. detectEndOfCommand = 1;
  1051. }
  1052. else {
  1053. // Unconditional loop, back to expression, if loop wasn't aborted/looped already
  1054. // (-2 to account for opcode we're about to use)
  1055. if (!skipJumpBack)
  1056. postCmdI(OP_JUMP, loopOffset - ws->code.size() - 2);
  1057. // Adjust loop jump to skip this block and jump cmd
  1058. if (condOffset >= 0) ws->code[condOffset] += ws->code.size() - codeStart;
  1059. }
  1060. int endPos = ws->code.size();
  1061. if (infiniteLoop > 0) {
  1062. // No warnings, they will be given elsewhere if needed (always-true condition)
  1063. // as an infinite-loop containing an actual return cmd is reasonable
  1064. ended.how = ENDED_RETURN;
  1065. ended.scope = 0;
  1066. }
  1067. // Finally, handle any links from within loop
  1068. list<LinkEntry>::iterator end = ws->links.end();
  1069. list<LinkEntry>::iterator edit;
  1070. for (list<LinkEntry>::iterator pos = ws->links.begin(); pos != end; ) {
  1071. edit = pos;
  1072. ++pos;
  1073. if (((*edit).type == LinkEntry::LINK_LOOP_CONTINUE) ||
  1074. ((*edit).type == LinkEntry::LINK_LOOP_END)) {
  1075. if (((*edit).name == blankString) || ((*edit).name == loopLabelName)) {
  1076. ws->code[(*edit).offset] +=
  1077. (((*edit).type == LinkEntry::LINK_LOOP_CONTINUE) ? continuePos : endPos)
  1078. - (*edit).offset;
  1079. ws->links.erase(edit);
  1080. }
  1081. }
  1082. }
  1083. break;
  1084. }
  1085. case KEYW_BREAK:
  1086. case KEYW_CONTINUE:
  1087. case KEYW_RESTART: {
  1088. t->skipToken();
  1089. // Identifier or anonymous loop?
  1090. int nextType;
  1091. string loopName;
  1092. t->peekToken(nextType, loopName);
  1093. if (nextType == TOKEN_IDENTIFIER) {
  1094. t->skipToken();
  1095. }
  1096. else {
  1097. loopName = blankString;
  1098. }
  1099. // Find label
  1100. LabelMap::iterator llist = labels->find(loopName.c_str());
  1101. if (llist == labels->end()) {
  1102. if (loopName == blankString)
  1103. t->outputError("Must use '%s' from within a loop", token.c_str());
  1104. else
  1105. t->outputError("No label matching '%s' found ('%s' can only be used with labels that immediately precede a loop command such as 'do' or 'for')", loopName.c_str(), token.c_str());
  1106. // RESOLUTION: skip any remaining command even though there shouldn't be any
  1107. skipCmd = 1;
  1108. break;
  1109. }
  1110. // Get label
  1111. Label& label = (*llist).second.back();
  1112. if (!label.isLoop) {
  1113. t->outputError("Label '%s' does not mark a loop ('%s' can only be used with labels that immediately precede a loop command such as 'do' or 'for')", loopName.c_str(), token.c_str());
  1114. // RESOLUTION: skip any remaining command even though there shouldn't be any
  1115. skipCmd = 1;
  1116. break;
  1117. }
  1118. // Ensure stack depth matches (shouldn't be lower- just higher)
  1119. compileAssert(label.stackDepth <= ws->stackDepth);
  1120. if (label.stackDepth < ws->stackDepth) {
  1121. // @TODO: Use OP_DISCARDL when we know all entries are int/float
  1122. postCmdI(OP_DISCARD, ws->stackDepth - label.stackDepth);
  1123. }
  1124. // Jump to label
  1125. if (type == KEYW_RESTART) {
  1126. // (-2 for opcode we're adding)
  1127. postCmdI(OP_JUMP, label.offset - ws->code.size() - 2);
  1128. ended.how = ENDED_RESTART;
  1129. }
  1130. else {
  1131. compileAssert((type == KEYW_BREAK) || (type == KEYW_CONTINUE));
  1132. prepLinker(type == KEYW_CONTINUE, loopName);
  1133. // -1 = offset of operand from next instruction, added into final label offset
  1134. postCmdI(OP_JUMP, -1);
  1135. ended.how = (type == KEYW_CONTINUE ? ENDED_CONTINUE : ENDED_BREAK);
  1136. }
  1137. ended.scope = label.scope;
  1138. // Breaks any infinites up to but not including this loop
  1139. ended.breakInfinite = label.scope;
  1140. // Breaks our loop too if a break
  1141. if (type == KEYW_BREAK) --ended.breakInfinite;
  1142. t->peekToken(type, token);
  1143. detectEndOfCommand = 1;
  1144. break;
  1145. }
  1146. case KEYW_DEBUG: {
  1147. t->skipToken();
  1148. // Debug output
  1149. Operand o = parseExpression(1);
  1150. if (!o.mode) {
  1151. skipCmd = 1;
  1152. break;
  1153. }
  1154. // Source already has conversion flag set if necessary, but it needs to
  1155. // be a 'copy' flag
  1156. if (!OM_IS_LITERAL(o.mode)) {
  1157. if (OM_IS_CONVERT(o.mode))
  1158. o.mode = (OperMode)(o.mode | OM_COPY);
  1159. }
  1160. // Source also needs to be const; define string literals
  1161. if (o.mode == OM_STR)
  1162. defineString(o);
  1163. if (OM_IS_STR(o.mode))
  1164. o.mode = (OperMode)(OM_STR_CONST | (o.mode & ~OM_BASETYPE));
  1165. // Finally, source could be a pop; temporaries should never be variants
  1166. if (O_IS_TEMP(o)) {
  1167. compileAssert(!OM_IS_ENTRY(o.mode));
  1168. compileAssert(o.data.i == 0);
  1169. o.mode = (OperMode)((o.mode & ~OM_LOCATION) | OM_POP);
  1170. }
  1171. postCmdRaw(OP_DEBUG, &o);
  1172. if (OM_IS_POP(o.mode))
  1173. --ws->stackDepth;
  1174. t->peekToken(type, token);
  1175. detectEndOfCommand = 1;
  1176. break;
  1177. }
  1178. case KEYW_IDLE: {
  1179. t->skipToken();
  1180. postCmd(OP_IDLE);
  1181. t->peekToken(type, token);
  1182. detectEndOfCommand = 1;
  1183. break;
  1184. }
  1185. case TOKEN_CONFIG:
  1186. case KEYW_EXTEND:
  1187. case KEYW_IMPORT:
  1188. case KEYW_WITH:
  1189. // @TODO:
  1190. case KEYW_FOR:
  1191. case KEYW_FOREACH:
  1192. case KEYW_REPEAT:
  1193. // @TODO: Just specialized while() loops
  1194. case KEYW_STATE:
  1195. case KEYW_REPLY: { // @TODO: may have to peek past current block
  1196. // @TODO:
  1197. t->outputError("Not currently supported: '%s'", token.c_str());
  1198. skipCmd = 1;
  1199. break;
  1200. }
  1201. case TOKEN_ENDLINE: {
  1202. // Compilation should never see one of these
  1203. compileAssert(0);
  1204. break;
  1205. }
  1206. default: {
  1207. t->outputError("Unexpected token '%s'", token.c_str());
  1208. // RESOLUTION: ignore rest of command
  1209. skipCmd = 1;
  1210. break;
  1211. }
  1212. }
  1213. }
  1214. if (detectEndOfCommand) {
  1215. if (type == TOKEN_ENDLINE) {
  1216. t->skipToken();
  1217. }
  1218. else if (type != TOKEN_OPEN_BRACE) {
  1219. t->outputError("Expected end-of-command");
  1220. skipCmd = 1;
  1221. }
  1222. }
  1223. if (exitBlock) break;
  1224. // Did one command, done with non-brace block
  1225. // Unless skipping command, then let that happen first
  1226. if ((!braceBlock) && (scope) && (!skipCmd)) break;
  1227. }
  1228. // Missing closing brace?
  1229. if ((braceBlock) && (!exitBlock))
  1230. t->outputError("Missing closing brace");
  1231. // RESOLUTION: assume brace is there
  1232. // Remove variables created during this scope
  1233. VariableMap::iterator edit;
  1234. for (VariableMap::iterator pos = vars->begin(); pos != vars->end(); ) {
  1235. edit = pos;
  1236. ++pos;
  1237. compileAssert(!(*edit).second.empty());
  1238. Variable& check = (*edit).second.back();
  1239. if (check.scope == scope) {
  1240. // This var was created by us- remove it
  1241. if ((check.datatype.baseType == DATA_STR) &&
  1242. (check.datatype.flags == DATA_CONST))
  1243. delete[] check.val.constS;
  1244. (*edit).second.pop_back();
  1245. if ((*edit).second.empty()) {
  1246. // No more vars matching this name- delete
  1247. const char* toKill = (*edit).first;
  1248. vars->erase(edit);
  1249. delete[] toKill;
  1250. }
  1251. else {
  1252. // Should never be two vars same name same scope
  1253. compileAssert((*edit).second.back().scope != scope);
  1254. }
  1255. }
  1256. }
  1257. // Remove labels created during this scope
  1258. LabelMap::iterator editL;
  1259. for (LabelMap::iterator posL = labels->begin(); posL != labels->end(); ) {
  1260. editL = posL;
  1261. ++posL;
  1262. compileAssert(!(*editL).second.empty());
  1263. Label& check = (*editL).second.back();
  1264. if (check.scope == scope) {
  1265. // This label was created by us- remove it
  1266. (*editL).second.pop_back();
  1267. if ((*editL).second.empty()) {
  1268. // No more labels matching this name- delete
  1269. const char* toKill = (*editL).first;
  1270. labels->erase(editL);
  1271. delete[] toKill;
  1272. }
  1273. else {
  1274. // Should never be two labels same name same scope
  1275. compileAssert((*editL).second.back().scope != scope);
  1276. }
  1277. }
  1278. }
  1279. // Main scope has a "stop"
  1280. if (scope == 0) {
  1281. if (!ended.how) postCmd(OP_STOP);
  1282. ended.how = ENDED_RETURN;
  1283. ended.scope = 0;
  1284. }
  1285. compileAssert(ws->stackDepth >= paramStackDepth);
  1286. if (!ended.how) {
  1287. // If end of function, return
  1288. if (parameters) {
  1289. Operand o;
  1290. createEmpty(o);
  1291. processReturn(o, returnType);
  1292. }
  1293. else {
  1294. // Pop local variables
  1295. if (ws->stackDepth > entryStackDepth) {
  1296. // @TODO: Use OP_DISCARDL when we know all entries are int/float
  1297. postCmdI(OP_DISCARD, ws->stackDepth - entryStackDepth);
  1298. }
  1299. }
  1300. }
  1301. // local variables have now been discarded
  1302. ws->stackDepth = entryStackDepth;
  1303. if (inFunctionScope == scope) inFunctionScope = 0;
  1304. --scope;
  1305. }
  1306. void Compiler::processReturn(Operand& o, DataType* returnType) { start_func
  1307. // Not in function?
  1308. if (!inFunctionScope) {
  1309. // (no need to destroy operand, OP_STOP clears stack)
  1310. if (o.mode)
  1311. t->outputError("Attempting to return value outside of function ('return' outside of a function is equivalent to 'end' and cannot return a value)");
  1312. else
  1313. t->outputWarning("'return' outside of a function is equivalent to 'end'");
  1314. postCmd(OP_STOP);
  1315. }
  1316. else {
  1317. // warn if return value when void
  1318. if ((returnType == NULL) || (returnType->baseType == DATA_VOID)) {
  1319. if (o.mode != OM_NONE) {
  1320. t->outputError("Attempting to return value within 'void' function ('void' functions cannot return a value)");
  1321. // RESOLUTION: destroy operand
  1322. destroyOperand(o);
  1323. }
  1324. // No return value to pop
  1325. postCmdII(OP_RETVOID, ws->stackDepth - funcParamStackDepth,
  1326. // (-1 for assumed code return pointer)
  1327. funcParamStackDepth - funcEntryStackDepth - 1);
  1328. }
  1329. // if nothing to return, return blank, and warn if NOT void
  1330. else {
  1331. if (o.mode == OM_NONE) {
  1332. t->outputWarning("Return without value (function was not declared as 'void' and therefore should return a value)");
  1333. generateBlank(*returnType);
  1334. ++ws->stackDepth;
  1335. }
  1336. else {
  1337. convertToMatch(o, *returnType, "return type");
  1338. // return values can be references
  1339. convertToTemp(o, 0, 1);
  1340. compileAssert(o.data.i == 0);
  1341. // Finish any pending conversions on o-
  1342. // Anything that was a var was converted by convertToTemp, so
  1343. // if it's still pending conversion, we can safely do it in place
  1344. if (OM_IS_CONVERT(o.mode))
  1345. postCmdRaw(OP_CONVERT, &o);
  1346. }
  1347. // Returned value is assumed to be popped
  1348. // (subtract now for popped return value)
  1349. postCmdII(OP_RET, --ws->stackDepth - funcParamStackDepth,
  1350. // (-1 for assumed code return pointer)
  1351. funcParamStackDepth - funcEntryStackDepth - 1);
  1352. }
  1353. }
  1354. }
  1355. void Compiler::createEmpty(Operand& o) { start_func
  1356. o.mode = OM_NONE;
  1357. o.data.i = 0;
  1358. o.subType = 0;
  1359. o.flags = 0;
  1360. o.ref.global = NULL;
  1361. o.arrayType = 0;
  1362. }
  1363. void Compiler::createInt(Operand& o, Sint32 value) { start_func
  1364. o.mode = OM_INT;
  1365. o.data.i = value;
  1366. o.subType = 0;
  1367. o.flags = 0;
  1368. o.ref.global = NULL;
  1369. o.arrayType = 0;
  1370. }
  1371. void Compiler::createFloat(Operand& o, BCfloat value) { start_func
  1372. o.mode = OM_FLOAT;
  1373. o.data.f = value;
  1374. o.subType = 0;
  1375. o.flags = 0;
  1376. o.ref.global = NULL;
  1377. o.arrayType = 0;
  1378. }
  1379. void Compiler::appendWorkspaces(Codespace* dest, const Codespace* src) { start_func
  1380. int size = dest->code.size();
  1381. list<LinkEntry>::const_iterator end = src->links.end();
  1382. for (list<LinkEntry>::const_iterator pos = src->links.begin(); pos != end; ++pos) {
  1383. dest->links.push_back(*pos);
  1384. dest->links.back().offset += size;
  1385. }
  1386. dest->code.insert(dest->code.end(), src->code.begin(), src->code.end());
  1387. }
  1388. void Compiler::checkDataType(DataType& type, int noConst, int noScope, int noVisibility, int noVoid) { start_func
  1389. if ((noConst) && (type.flags & DATA_CONST)) {
  1390. t->outputError("Cannot use const datatype here");
  1391. // RESOLUTION: drop invalid datatype
  1392. type.flags &= ~DATA_CONST;
  1393. }
  1394. if ((noScope) && (type.flags & DATA_LOCAL)) {
  1395. t->outputError("Cannot use datatype scopes ('local') here");
  1396. // RESOLUTION: drop invalid datatype
  1397. type.flags &= ~DATA_LOCAL;
  1398. }
  1399. if ((noScope) && (type.flags & DATA_GLOBAL)) {
  1400. t->outputError("Cannot use datatype scopes ('global') here");
  1401. // RESOLUTION: drop invalid datatype
  1402. type.flags &= ~DATA_GLOBAL;
  1403. }
  1404. if ((noVisibility) && (type.flags & DATA_PRIVATE)) {
  1405. t->outputError("Cannot use visibility modifiers ('private') here");
  1406. // RESOLUTION: drop invalid datatype
  1407. type.flags &= ~DATA_PRIVATE;
  1408. }
  1409. if ((noVisibility) && (type.flags & DATA_PUBLIC)) {
  1410. t->outputError("Cannot use visibility modifiers ('public') here");
  1411. // RESOLUTION: drop invalid datatype
  1412. type.flags &= ~DATA_PUBLIC;
  1413. }
  1414. if ((noVoid) && (type.baseType == DATA_VOID)) {
  1415. t->outputError("Cannot use 'void' datatype here");
  1416. // RESOLUTION: change to variant
  1417. type.baseType = DATA_VAR;
  1418. }
  1419. }
  1420. Compiler::Operand Compiler::parseFunction(const Function& function, const string& funcName) { start_func
  1421. // @TODO: only supports local functions so far (no global/built-in/sends/queries)
  1422. int paramNum = 0;
  1423. int type;
  1424. string token;
  1425. // Optional paren
  1426. int paren = 0;
  1427. t->peekToken(type, token);
  1428. if (type == TOKEN_OPEN_PAREN) {
  1429. paren = 1;
  1430. t->skipToken();
  1431. t->peekToken(type, token);
  1432. }
  1433. // Parameters? these tokens MOSTLY match those in parseoperand-
  1434. // Exceptions- don't recognize +, - as starting an operand if no parens
  1435. if ((type == TOKEN_INTEGER) || (type == TOKEN_HEX) || (type == TOKEN_DECIMAL) ||
  1436. (type == TOKEN_STRING) || (type == KEYW_TRUE) || (type == KEYW_FALSE) ||
  1437. (type == KEYW_QUERY) || (type == TOKEN_IDENTIFIER) || (type == KEYW_ALL) ||
  1438. (type == KEYW_ALL_OTHER) || (type == KEYW_THIS) || (type == KEYW_SOURCE) ||
  1439. (type == KEYW_DEFAULT) || (type == OPER_B_NOT) || (type == OPER_L_NOT) ||
  1440. (type == KEYW_NOTHING) ||
  1441. ((paren) && ((type == OPER_PLUS) || (type == OPER_MINUS)))) {
  1442. // Parse operands from here on
  1443. do {
  1444. Operand o = parseExpression();
  1445. if (!o.mode) break;
  1446. // Convert to proper operand type
  1447. // (can't convert if no more param types known)
  1448. if (paramNum < function.numparam)
  1449. convertToMatch(o, function.parameters[paramNum], "parameter");
  1450. ++paramNum;
  1451. // (parameters can be references)
  1452. convertToTemp(o, 0, 1);
  1453. // (above ensures any string has been deleted)
  1454. // Finish any pending conversions on o-
  1455. // Anything that was a var was converted by convertToTemp, so
  1456. // if it's still pending conversion, we can safely do it in place
  1457. if (OM_IS_CONVERT(o.mode))
  1458. postCmdRaw(OP_CONVERT, &o);
  1459. // Another parameter?
  1460. t->peekToken(type, token);
  1461. if (type == TOKEN_COMMA) t->skipToken();
  1462. } while (type == TOKEN_COMMA);
  1463. }
  1464. // Incorrect number of parameters?
  1465. if (paramNum != function.numparam) {
  1466. t->outputError("Incorrect number of parameters to function (%d were given; %d were expected)", paramNum, function.numparam);
  1467. // RESOLUTION: continue on; code is of course unusable
  1468. }
  1469. // End paren? (already peeked previously)
  1470. if (paren) {
  1471. if (type == TOKEN_CLOSE_PAREN)
  1472. t->skipToken();
  1473. else
  1474. t->outputError("Missing closing parenthesis to match open parenthesis");
  1475. // RESOLUTION: pretend paren was there
  1476. }
  1477. // Parameters are on stack now
  1478. prepLinker(funcName);
  1479. // -1 = offset of operand compared to next opcode; added into final function offset
  1480. postCmdI(OP_SUBR, -1);
  1481. // "Pop" parameters, push return value if any
  1482. if (function.returntype.baseType == DATA_VOID) {
  1483. ws->stackDepth -= paramNum;
  1484. Operand o;
  1485. createInt(o, 0);
  1486. o.flags = Operand::OF_IS_VOID;
  1487. return o;
  1488. }
  1489. else {
  1490. ws->stackDepth -= paramNum - 1;
  1491. // Return value is on stack now, type is known
  1492. Operand o = dataTypeToOperand(function.returntype);
  1493. o.mode = (OperMode)(o.mode | OM_STACK);
  1494. return o;
  1495. }
  1496. }
  1497. Compiler::Operand Compiler::dataTypeToOperand(DataType dt) { start_func
  1498. Operand o;
  1499. o.flags = 0;
  1500. o.data.i = 0;
  1501. o.ref.global = NULL;
  1502. o.mode = (OperMode)dt.baseType;
  1503. if (dt.baseType == DATA_VAR)
  1504. o.mode = OM_ENTRY;
  1505. if ((o.mode == OM_ENTITY) || (o.mode == OM_OBJECT))
  1506. o.subType = dt.subType;
  1507. if (dt.flags & DATA_ARRAY) {
  1508. o.arrayType = o.mode;
  1509. o.mode = OM_ARRAY;
  1510. }
  1511. else if (dt.flags & DATA_HASH) {
  1512. o.arrayType = o.mode;
  1513. o.mode = OM_HASH;
  1514. }
  1515. o.mode = (OperMode)(o.mode | OM_NO_CONVERT);
  1516. return o;
  1517. }
  1518. int Compiler::findFunction(const string& name, Function& function) const { start_func
  1519. // find matching local function
  1520. FunctionMap::iterator flist = func->find(name.c_str());
  1521. if (flist == func->end()) {
  1522. // @TODO: also need to check global functions and built-ins
  1523. return 0;
  1524. }
  1525. // @TODO: optimize self/tail recursion?
  1526. function = (*flist).second;
  1527. return 1;
  1528. }
  1529. void Compiler::convertToMatch(Operand& o, DataType datatype, const char* errorTarget) { start_func
  1530. compileAssert(!OM_IS_NONE(o.mode));
  1531. // Ensure data types match- convert or error if needed
  1532. // Check array/hash first because target could be var hash/array
  1533. if ((datatype.flags & DATA_ARRAY) || (datatype.flags & DATA_HASH)) {
  1534. string defined = "array";
  1535. int isType = OM_IS_ARRAY(o.mode);
  1536. if (datatype.flags & DATA_HASH) {
  1537. defined = "hash";
  1538. isType = OM_IS_HASH(o.mode);
  1539. }
  1540. if (isType) {
  1541. if ((o.arrayType != datatype.baseType) && (o.arrayType != DATA_VAR) && (datatype.baseType != DATA_VAR)) {
  1542. t->outputError("Incorrect %s type- does not match %s", defined.c_str(), errorTarget);
  1543. }
  1544. else if ((o.arrayType == DATA_ENTITY) && (datatype.baseType == DATA_ENTITY)) {
  1545. // Ensure same subtype or converting to no type
  1546. if ((o.subType != datatype.subType) && (datatype.subType))
  1547. t->outputError("Incorrect %s type- script type does not match %s", defined.c_str(), errorTarget);
  1548. }
  1549. else if ((o.arrayType == DATA_OBJECT) && (datatype.baseType == DATA_OBJECT)) {
  1550. // Ensure same subtype
  1551. if (o.subType != datatype.subType)
  1552. t->outputError("Incorrect %s type- object type does not match %s", defined.c_str(), errorTarget);
  1553. }
  1554. }
  1555. else if (!OM_IS_ENTRY(o.mode)) {
  1556. t->outputError("Incorrect data type- %s must be assigned %s", errorTarget, defined.c_str());
  1557. }
  1558. // RESOLUTION: converts anyways
  1559. if (datatype.flags & DATA_ARRAY) convertToArray(o, datatype);
  1560. else convertToHash(o, datatype);
  1561. }
  1562. // Anything else, no need to convert to var
  1563. else if (datatype.baseType != DATA_VAR) {
  1564. if (datatype.baseType == DATA_INT) {
  1565. if (!OM_IS_INT(o.mode) && !OM_IS_FLOAT(o.mode) && !OM_IS_ENTRY(o.mode))
  1566. t->outputError("Cannot automatically convert to integer here");
  1567. // RESOLUTION: converts anyways
  1568. convertToInt(o);
  1569. }
  1570. else if (datatype.baseType == DATA_FLOAT) {
  1571. if (!OM_IS_INT(o.mode) && !OM_IS_FLOAT(o.mode) && !OM_IS_ENTRY(o.mode))
  1572. t->outputError("Cannot automatically convert to floating point here");
  1573. // RESOLUTION: converts anyways
  1574. convertToFloat(o);
  1575. }
  1576. else if (datatype.baseType == DATA_STR) {
  1577. if (!OM_IS_INT(o.mode) && !OM_IS_FLOAT(o.mode) && !OM_IS_STR(o.mode) && !OM_IS_ENTRY(o.mode))
  1578. t->outputError("Cannot automatically convert to string here");
  1579. // RESOLUTION: converts anyways
  1580. convertToStr(o);
  1581. }
  1582. else if (datatype.baseType == DATA_ENTITY) {
  1583. if (OM_IS_LITERAL(o.mode)) {
  1584. if ((o.mode != OM_ALL) && (o.mode != OM_ALL_OTHER) &&
  1585. (o.mode != OM_NOTHING) && (o.mode != OM_THIS))
  1586. t->outputError("Cannot automatically convert to entity object here");
  1587. }
  1588. else {
  1589. if ((o.mode & OM_BASETYPE) != DATA_ENTITY)
  1590. t->outputError("Cannot automatically convert to entity object here");
  1591. // Ensure same subtype or converting to no type
  1592. else if ((o.subType != datatype.subType) && (datatype.subType))
  1593. t->outputError("Incorrect script type- does not match %s", errorTarget);
  1594. }
  1595. // RESOLUTION: converts anyways
  1596. convertToObject(o, datatype);
  1597. }
  1598. else {
  1599. // All other object types
  1600. assert(datatype.baseType == DATA_OBJECT);
  1601. if (OM_IS_LITERAL(o.mode)) {
  1602. if (o.mode != OM_NOTHING)
  1603. t->outputError("Cannot automatically convert to object type here");
  1604. }
  1605. else {
  1606. if ((o.mode & OM_BASETYPE) != DATA_OBJECT)
  1607. t->outputError("Cannot automatically convert to object type here");
  1608. // Ensure same subtype
  1609. else if (o.subType != datatype.subType)
  1610. t->outputError("Incorrect object type- does not match %s", errorTarget);
  1611. }
  1612. // RESOLUTION: converts anyways
  1613. convertToObject(o, datatype);
  1614. }
  1615. }
  1616. }
  1617. void Compiler::parseAssignment(Operand& var, DataType varType, const Variable* varToCount, int memberPos) { start_func
  1618. // @TODO: calculate directly into variable instead of temporary?
  1619. // (only if no possibility of variable self-referenced in expression)
  1620. // use same algorithm as for a = a + 1 below
  1621. // @TODO: optimize a = a + 1 (etc.) by preparsing and counting uses of a; then
  1622. // during expression parsing, the last time you encounter it, you can now modify
  1623. // it directly; for non-scoped vars, you must count function calls as a possible 'use'.
  1624. // Mark this in operand somehow, and treat it as an equal to a temporary in many places (be careful of type matching)
  1625. // OPERATOR++ and inline-assignment potentially affect this algorithm.
  1626. // This optimization must be ignored if OPERATOR+= is being used.
  1627. // @TODO: prevent use of variable in it's own initialization
  1628. // (just don't define it before calling this?)
  1629. // @TODO: a = b + 1 should be (store b into a, += 1) not (push b, += 1, pop into a)
  1630. // if preparse above finds NO uses of variable, then first time something would be pushed,
  1631. // store into variable instead and then use that as a temporary (only if type matches)
  1632. // @TODO: doesn't work with . (as . isn't coded yet) or probably with 'as'
  1633. // Preparse the expression for uses of variable, or functions that MIGHT affect variable
  1634. // This count allows us to optimize the expression once all other uses of the variable
  1635. // are out of the way by doing further operations directly within the variable
  1636. /*
  1637. int bknum = t->getBookmarkName();
  1638. t->bookmarkStore(bknum);
  1639. t->silentErrors(1);
  1640. Operand counted = parseExpression(0, 1, NULL, 100, &var);
  1641. t->silentErrors(0);
  1642. if (varToCount) {
  1643. t->bookmarkCancel(bknum);
  1644. return;
  1645. }
  1646. t->bookmarkReturn(bknum);
  1647. debugWrite("Found %d instances of %s", counted.data.i, var.name);
  1648. */
  1649. // The easy part- parse the expression
  1650. Operand o = parseExpression();
  1651. if (!o.mode) return;
  1652. compileAssert(!OM_IS_POP(o.mode));
  1653. compileAssert(!OM_IS_COPY(o.mode));
  1654. // @TODO: should error if storing to a const
  1655. convertToMatch(o, varType, "variable");
  1656. // Permutations:
  1657. // known into known, same type
  1658. // known (conversion needed) into known, same type
  1659. // known into variant (convert variant)
  1660. // known (conversion needed) into variant (convert variant)
  1661. // variant into variant
  1662. // Default to object, as that covers multiple types and literals
  1663. Opcode opc = OP_STOREo;
  1664. if (memberPos >= 0) {
  1665. assert(!OM_IS_ENTRY(o.mode));
  1666. if (OM_IS_ENTITY(var.mode)) opc = OP_SETe;
  1667. else {
  1668. compileAssert(OM_IS_OBJECT(var.mode));
  1669. opc = OP_SETo;
  1670. }
  1671. }
  1672. else if (OM_IS_STR(o.mode)) opc = OP_STOREs;
  1673. else if (OM_IS_FLOAT(o.mode)) opc = OP_STOREf;
  1674. else if (OM_IS_INT(o.mode)) opc = OP_STORE;
  1675. else if (OM_IS_ARRAY(o.mode)) opc = OP_STOREa;
  1676. else if (OM_IS_HASH(o.mode)) opc = OP_STOREh;
  1677. else if (!OM_IS_LITERAL(o.mode)) {
  1678. if (OM_IS_ENTRY(o.mode)) {
  1679. compileAssert(varType.baseType == DATA_VAR);
  1680. // @TODO: ensure storev does ALL ref/deref needed, conversions, and copying new array/hash
  1681. opc = OP_STOREv;
  1682. }
  1683. }
  1684. // Dest is set to 'no convert' which is correct unless storing to a variant
  1685. // from a non-variant
  1686. if ((varType.baseType == DATA_VAR) && (opc != OP_STOREv))
  1687. var.mode = (OperMode)(var.mode & ~OM_NO_CONVERT);
  1688. // Source already has conversion flag set if necessary, but it needs to
  1689. // be a 'copy' flag
  1690. if (!OM_IS_LITERAL(o.mode)) {
  1691. if (OM_IS_CONVERT(o.mode))
  1692. o.mode = (OperMode)(o.mode | OM_COPY);
  1693. // Force a copy if non-unique array/hash
  1694. else if (OM_IS_KNOWN(o.mode) && (OM_IS_ARRAY(o.mode) || OM_IS_HASH(o.mode)) && !O_IS_COPY(o) && (opc != OP_STOREv))
  1695. o.mode = (OperMode)((o.mode & ~OM_FLAGS) | OM_COPY);
  1696. }
  1697. // Source also needs to be const; define string literals
  1698. if (o.mode == OM_STR)
  1699. defineString(o);
  1700. if (OM_IS_STR(o.mode))
  1701. o.mode = (OperMode)(OM_STR_CONST | (o.mode & ~OM_BASETYPE));
  1702. // Finally, source could be a pop; temporaries should never be variants
  1703. if (O_IS_TEMP(o)) {
  1704. compileAssert(!OM_IS_ENTRY(o.mode));
  1705. compileAssert(o.data.i == 0);
  1706. o.mode = (OperMode)((o.mode & ~OM_LOCATION) | OM_POP);
  1707. }
  1708. // 'var' goes after 'o' in case both are POPs- popping happens in right order
  1709. if ((opc == OP_SETo) || (opc == OP_SETe)) {
  1710. // Specialized versions
  1711. if (OM_IS_FLOAT(o.mode)) opc = (opc == OP_SETo) ? OP_SETof : OP_SETef;
  1712. else if (OM_IS_INT(o.mode)) opc = (opc == OP_SETo) ? OP_SEToi : OP_SETei;
  1713. Operand b;
  1714. createInt(b, memberPos);
  1715. postCmdRaw(opc, &o, &var, &b);
  1716. }
  1717. else
  1718. postCmdRaw(opc, &o, &var);
  1719. var.mode = (OperMode)(var.mode | OM_NO_CONVERT);
  1720. if (OM_IS_POP(o.mode))
  1721. --ws->stackDepth;
  1722. }
  1723. Compiler::Operand Compiler::variableToOperand(const Variable& var) { start_func
  1724. Operand result;
  1725. if (var.datatype.flags & DATA_CONST) {
  1726. // Constants
  1727. result.arrayType = 0;
  1728. result.flags = 0;
  1729. result.subType = 0;
  1730. result.mode = (OperMode)var.datatype.baseType;
  1731. result.ref.global = NULL;
  1732. if (var.datatype.baseType == DATA_INT) {
  1733. result.data.i = var.val.constI;
  1734. }
  1735. else if (var.datatype.baseType == DATA_FLOAT) {
  1736. result.data.f = var.val.constF;
  1737. }
  1738. else {
  1739. compileAssert(var.datatype.baseType == DATA_STR);
  1740. result.data.i = 0;
  1741. result.ref.strLiteral = new string(var.val.constS);
  1742. }
  1743. }
  1744. else {
  1745. result = dataTypeToOperand(var.datatype);
  1746. result.flags |= Operand::OF_IS_VAR;
  1747. if (var.scope == 0) {
  1748. result.mode = (OperMode)(result.mode | OM_LOCAL);
  1749. result.data.i = var.val.offs;
  1750. }
  1751. else if (var.scope > 0) {
  1752. result.mode = (OperMode)(result.mode | OM_STACK);
  1753. result.data.i = var.val.offs + ws->stackDepth;
  1754. }
  1755. else {
  1756. result.mode = (OperMode)(result.mode | OM_GLOBAL);
  1757. result.ref.global = &var;
  1758. result.data.i = var.val.offs;
  1759. }
  1760. }
  1761. return result;
  1762. }
  1763. int Compiler::convertToTemp(Operand& o, int partialConvert, int refOK) { start_func
  1764. int redoString = 0;
  1765. if (partialConvert) compileAssert(OM_IS_LITERAL(o.mode));
  1766. if (!O_IS_TEMP(o)) {
  1767. // Create temporary via PUSH
  1768. if (o.mode == OM_STR) {
  1769. if (partialConvert) {
  1770. redoString = 1;
  1771. // We NEED to be sure this is zero because we finish conversion
  1772. // later via an addition to the operand created
  1773. compileAssert(o.data.i == 0);
  1774. }
  1775. else defineString(o);
  1776. }
  1777. Operand copyOfO = o;
  1778. postCmdPush(copyOfO, refOK);
  1779. ++ws->stackDepth;
  1780. // Modify operand to match new position
  1781. o.flags = 0;
  1782. if (o.mode != OM_STR) o.ref.global = NULL;
  1783. if (!refOK) o.flags = Operand::OF_IS_COPY;
  1784. o.mode = (OperMode)((o.mode & ~OM_LOCATION) | OM_STACK);
  1785. if (OM_IS_CONVERT(o.mode)) o.mode = (OperMode)((o.mode & ~OM_FLAGS) | OM_NO_CONVERT);
  1786. if (!partialConvert) o.data.i = 0;
  1787. }
  1788. return redoString;
  1789. }
  1790. void Compiler::convertToInt(Operand& o) { start_func
  1791. compileAssert(o.mode);
  1792. compileAssert(!OM_IS_COPY(o.mode));
  1793. compileAssert(!OM_IS_CONST(o.mode));
  1794. compileAssert(!OM_IS_POP(o.mode));
  1795. // Already int
  1796. if (OM_IS_INT(o.mode)) return;
  1797. // Main possibilities-
  1798. // Literal- convert to another literal
  1799. // Otherwise- mark as 'needed conversion'
  1800. if (OM_IS_LITERAL(o.mode)) {
  1801. if (o.mode == OM_FLOAT) {
  1802. o.data.i = (Sint32)o.data.f;
  1803. }
  1804. else if (o.mode == OM_STR) {
  1805. o.data.i = strToInt(*o.ref.strLiteral);
  1806. delete o.ref.strLiteral;
  1807. o.ref.strLiteral = NULL;
  1808. }
  1809. else {
  1810. o.data.i = 0;
  1811. o.subType = 0;
  1812. o.arrayType = 0;
  1813. }
  1814. o.mode = OM_INT;
  1815. return;
  1816. }
  1817. // (clears no_convert flag also)
  1818. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_INT);
  1819. }
  1820. void Compiler::convertToFloat(Operand& o) { start_func
  1821. compileAssert(o.mode);
  1822. compileAssert(!OM_IS_COPY(o.mode));
  1823. compileAssert(!OM_IS_CONST(o.mode));
  1824. compileAssert(!OM_IS_POP(o.mode));
  1825. // Already float
  1826. if (OM_IS_FLOAT(o.mode)) return;
  1827. // Main possibilities-
  1828. // Literal- convert to another literal
  1829. // Otherwise- mark as 'needed conversion'
  1830. if (OM_IS_LITERAL(o.mode)) {
  1831. if (o.mode == OM_INT) {
  1832. o.data.f = (BCfloat)o.data.i;
  1833. }
  1834. else if (o.mode == OM_STR) {
  1835. o.data.f = strToFloat(*o.ref.strLiteral);
  1836. delete o.ref.strLiteral;
  1837. o.ref.strLiteral = NULL;
  1838. }
  1839. else {
  1840. o.data.f = 0.0;
  1841. o.subType = 0;
  1842. o.arrayType = 0;
  1843. }
  1844. o.mode = OM_FLOAT;
  1845. return;
  1846. }
  1847. // (clears no_convert flag also)
  1848. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_FLOAT);
  1849. }
  1850. void Compiler::convertToStr(Operand& o) { start_func
  1851. compileAssert(o.mode);
  1852. compileAssert(!OM_IS_COPY(o.mode));
  1853. compileAssert(!OM_IS_CONST(o.mode));
  1854. compileAssert(!OM_IS_POP(o.mode));
  1855. // Already string
  1856. if (OM_IS_STR(o.mode)) return;
  1857. // Main possibilities-
  1858. // Literal- convert to another literal
  1859. // Otherwise- mark as 'needed conversion'
  1860. if (OM_IS_LITERAL(o.mode)) {
  1861. o.data.i = 0;
  1862. if (o.mode == OM_INT) {
  1863. o.ref.strLiteral = new string(intToStr(o.data.i));
  1864. }
  1865. else if (o.mode == OM_FLOAT) {
  1866. o.ref.strLiteral = new string(floatToStr(o.data.f));
  1867. }
  1868. else {
  1869. o.ref.strLiteral = new string(blankString);
  1870. o.subType = 0;
  1871. o.arrayType = 0;
  1872. }
  1873. o.mode = OM_STR;
  1874. return;
  1875. }
  1876. // (clears no_convert flag also)
  1877. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_STR);
  1878. }
  1879. void Compiler::convertToEntity(Operand& o, DataType type) { start_func
  1880. compileAssert(o.mode);
  1881. compileAssert(!OM_IS_COPY(o.mode));
  1882. compileAssert(!OM_IS_CONST(o.mode));
  1883. compileAssert(!OM_IS_POP(o.mode));
  1884. compileAssert(type.baseType == DATA_ENTITY);
  1885. // Already entity- check for proper type
  1886. if (OM_IS_ENTITY(o.mode) && !OM_IS_LITERAL(o.mode)) {
  1887. // any type matches no-subtype
  1888. if (!type.subType) return;
  1889. // Otherwise type must match exactly
  1890. if (type.subType == o.subType) return;
  1891. // Type failed to match- will mark for conversion later
  1892. }
  1893. // Main possibilities-
  1894. // Literal- convert to another literal
  1895. // Otherwise- mark as 'needed conversion'
  1896. if (OM_IS_LITERAL(o.mode)) {
  1897. // Certain literals are ok
  1898. if ((o.mode == OM_ALL) || (o.mode == OM_ALL_OTHER) || (o.mode == OM_NOTHING)) {
  1899. o.subType = type.subType;
  1900. return;
  1901. }
  1902. if ((o.mode == OM_THIS) && ((type.subType == scriptType) || (!type.subType)))
  1903. return;
  1904. if (o.mode == OM_STR) {
  1905. delete o.ref.strLiteral;
  1906. o.ref.strLiteral = NULL;
  1907. }
  1908. // Create a 'nothing' entity
  1909. o.mode = OM_NOTHING;
  1910. o.arrayType = 0;
  1911. o.subType = type.subType;
  1912. o.data.i = 0;
  1913. o.flags = 0;
  1914. return;
  1915. }
  1916. // (clears no_convert flag also)
  1917. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_ENTITY);
  1918. o.subType = type.subType;
  1919. }
  1920. void Compiler::convertToObject(Operand& o, DataType type) { start_func
  1921. compileAssert(o.mode);
  1922. compileAssert(!OM_IS_COPY(o.mode));
  1923. compileAssert(!OM_IS_CONST(o.mode));
  1924. compileAssert(!OM_IS_POP(o.mode));
  1925. compileAssert(type.baseType == DATA_OBJECT);
  1926. compileAssert(type.subType);
  1927. // Already object- check for proper type
  1928. if (OM_IS_OBJECT(o.mode) && !OM_IS_LITERAL(o.mode)) {
  1929. // Type must match exactly
  1930. if (type.subType == o.subType) return;
  1931. // Type failed to match- will mark for conversion later
  1932. }
  1933. // Main possibilities-
  1934. // Literal- convert to another literal
  1935. // Otherwise- mark as 'needed conversion'
  1936. if (OM_IS_LITERAL(o.mode)) {
  1937. // Certain literals are ok
  1938. if (o.mode == OM_NOTHING) {
  1939. o.subType = type.subType;
  1940. return;
  1941. }
  1942. if (o.mode == OM_STR) {
  1943. delete o.ref.strLiteral;
  1944. o.ref.strLiteral = NULL;
  1945. }
  1946. // Create a 'nothing' object
  1947. o.mode = OM_NOTHING;
  1948. o.arrayType = 0;
  1949. o.subType = type.subType;
  1950. o.data.i = 0;
  1951. o.flags = 0;
  1952. return;
  1953. }
  1954. // (clears no_convert flag also)
  1955. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_OBJECT);
  1956. o.subType = type.subType;
  1957. }
  1958. void Compiler::convertToArray(Operand& o, DataType type) { start_func
  1959. // @TODO: remember that when this is used, a simple copy bit won't
  1960. // complete a specific array type conversion- just promise it's an
  1961. // array of SOME type; you must specifically use a conversion opcode
  1962. // or assume you are pulling a variant out. WE CAN CHANGE THIS by
  1963. // pushing array+subtype whenever conversion/copy operands are used
  1964. assert(0);
  1965. compileAssert(o.mode);
  1966. compileAssert(!OM_IS_COPY(o.mode));
  1967. compileAssert(!OM_IS_CONST(o.mode));
  1968. compileAssert(!OM_IS_POP(o.mode));
  1969. compileAssert(type.flags & DATA_ARRAY);
  1970. // Already array- check for proper type
  1971. if (OM_IS_ARRAY(o.mode)) {
  1972. // any type matches variant type
  1973. if (type.baseType == DATA_VAR) return;
  1974. // Otherwise type must match exactly
  1975. if (o.arrayType == type.baseType) {
  1976. if ((type.baseType != DATA_ENTITY) && (type.baseType != DATA_OBJECT)) return;
  1977. // Match subtype exactly for entities/objects
  1978. if (type.subType == o.subType) return;
  1979. }
  1980. // Type failed to match- will mark for conversion later
  1981. }
  1982. // Main possibilities-
  1983. // Literal- convert to another literal
  1984. // Otherwise- mark as 'needed conversion'
  1985. if (OM_IS_LITERAL(o.mode)) {
  1986. if (o.mode == OM_STR) {
  1987. delete o.ref.strLiteral;
  1988. o.ref.strLiteral = NULL;
  1989. }
  1990. // Create a new array- if variant type, create an INT array
  1991. o.mode = (OperMode)(OM_ARRAY | OM_STACK | OM_NO_CONVERT);
  1992. o.arrayType = type.baseType;
  1993. o.subType = 0;
  1994. o.data.i = 0;
  1995. o.flags = Operand::OF_IS_COPY;
  1996. if (type.baseType == DATA_VAR) {
  1997. postCmdII(OP_CREATEa, DATA_INT, 0);
  1998. o.arrayType = DATA_INT;
  1999. }
  2000. else {
  2001. postCmdII(OP_CREATEa, type.baseType,
  2002. (type.baseType == DATA_ENTITY ||
  2003. type.baseType == DATA_OBJECT) ? type.subType : 0);
  2004. }
  2005. return;
  2006. }
  2007. // (clears no_convert flag also)
  2008. // If was a copy before, would still be; if not, is not, so don't change flags
  2009. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_ARRAY);
  2010. o.subType = type.subType;
  2011. o.arrayType = type.baseType;
  2012. if (type.baseType == DATA_VAR) o.arrayType = OM_INT;
  2013. }
  2014. void Compiler::convertToHash(Operand& o, DataType type) { start_func
  2015. // @TODO: remember that when this is used, a simple copy bit won't
  2016. // complete a specific hash type conversion- just promise it's an
  2017. // array of SOME time; you must specifically use a conversion opcode
  2018. // or assume you are pulling a variant out. WE CAN CHANGE THIS by
  2019. // pushing hash+subtype whenever conversion/copy operands are used
  2020. assert(0);
  2021. compileAssert(o.mode);
  2022. compileAssert(!OM_IS_COPY(o.mode));
  2023. compileAssert(!OM_IS_CONST(o.mode));
  2024. compileAssert(!OM_IS_POP(o.mode));
  2025. compileAssert(type.flags & DATA_HASH);
  2026. // Already hash- check for proper type
  2027. if (OM_IS_HASH(o.mode)) {
  2028. // any type matches variant type
  2029. if (type.baseType == DATA_VAR) return;
  2030. // Otherwise type must match exactly
  2031. if (o.arrayType == type.baseType) {
  2032. if ((type.baseType != DATA_ENTITY) && (type.baseType != DATA_OBJECT)) return;
  2033. // Match subtype exactly for entities/objects
  2034. if (type.subType == o.subType) return;
  2035. }
  2036. // Type failed to match- will mark for conversion later
  2037. }
  2038. // Main possibilities-
  2039. // Literal- convert to another literal
  2040. // Otherwise- mark as 'needed conversion'
  2041. if (OM_IS_LITERAL(o.mode)) {
  2042. if (o.mode == OM_STR) {
  2043. delete o.ref.strLiteral;
  2044. o.ref.strLiteral = NULL;
  2045. }
  2046. // Create a new hash- if variant type, create an INT hash
  2047. o.mode = (OperMode)(OM_HASH | OM_STACK | OM_NO_CONVERT);
  2048. o.arrayType = type.baseType;
  2049. o.subType = 0;
  2050. o.data.i = 0;
  2051. o.flags = Operand::OF_IS_COPY;
  2052. if (type.baseType == DATA_VAR) {
  2053. postCmdII(OP_CREATEh, DATA_INT, 0);
  2054. o.arrayType = DATA_INT;
  2055. }
  2056. else {
  2057. postCmdII(OP_CREATEh, type.baseType,
  2058. (type.baseType == DATA_ENTITY ||
  2059. type.baseType == DATA_OBJECT) ? type.subType : 0);
  2060. }
  2061. return;
  2062. }
  2063. // (clears no_convert flag also)
  2064. // If was a copy before, would still be; if not, is not, so don't change flags
  2065. o.mode = (OperMode)((o.mode & OM_LOCATION) | OM_HASH);
  2066. o.subType = type.subType;
  2067. o.arrayType = type.baseType;
  2068. if (type.baseType == DATA_VAR) o.arrayType = OM_INT;
  2069. }
  2070. void Compiler::destroyOperand(Operand& o) { start_func
  2071. compileAssert(!OM_IS_POP(o.mode));
  2072. if (!o.mode)
  2073. return;
  2074. if (o.mode == OM_STR) {
  2075. delete o.ref.strLiteral;
  2076. o.ref.strLiteral = NULL;
  2077. }
  2078. if (O_IS_TEMP(o)) {
  2079. compileAssert(o.data.i == 0);
  2080. if (OM_IS_INT(o.mode) || OM_IS_FLOAT(o.mode)) postCmdI(OP_DISCARDL, 1);
  2081. else postCmdI(OP_DISCARD, 1);
  2082. --ws->stackDepth;
  2083. }
  2084. }
  2085. int Compiler::precedence(int oper) { start_func
  2086. // (for error states)
  2087. if (oper == 0) return 0;
  2088. compileAssert(oper & TOKEN_OPERATOR);
  2089. switch (oper) {
  2090. case OPER_MEMBER: // (presumed to have lowest precedence)
  2091. case OPER_AS:
  2092. return 2;
  2093. case OPER_B_NOT:
  2094. case OPER_L_NOT:
  2095. return 3;
  2096. case OPER_MULT:
  2097. case OPER_DIV:
  2098. case OPER_MOD:
  2099. return 4;
  2100. case OPER_PLUS:
  2101. case OPER_MINUS:
  2102. return 5;
  2103. case OPER_LSHIFT:
  2104. case OPER_RSHIFT:
  2105. return 6;
  2106. case OPER_B_AND:
  2107. case OPER_B_OR:
  2108. case OPER_B_XOR:
  2109. return 7;
  2110. case OPER_CONCAT:
  2111. return 8;
  2112. case OPER_LT:
  2113. case OPER_LE:
  2114. case OPER_GT:
  2115. case OPER_GE:
  2116. return 9;
  2117. case OPER_EQ:
  2118. case OPER_NE:
  2119. case OPER_IS:
  2120. return 10;
  2121. case OPER_L_AND:
  2122. case OPER_L_OR:
  2123. case OPER_L_XOR:
  2124. return 11;
  2125. case OPER_ASSIGN:
  2126. return 12;
  2127. }
  2128. compileAssert(0);
  2129. return 1;
  2130. }
  2131. Compiler::Operand Compiler::parseExpression(int warnAssign, int usingValue, Operand* firstOperand, int stopPrecedence, const Variable* varToCount) { start_func
  2132. int type;
  2133. string token;
  2134. Operand a;
  2135. if (firstOperand) a = *firstOperand;
  2136. else a = parseOperand(warnAssign, usingValue, varToCount);
  2137. if (a.mode == 0) {
  2138. return a;
  2139. }
  2140. t->peekToken(type, token);
  2141. while (1) {
  2142. size_t aFinishLiteralAt = 0;
  2143. size_t aFinishLiteralSize = 0;
  2144. int aFinishString = 0;
  2145. if (type & TOKEN_OPERATOR) {
  2146. if (O_IS_VOID(a)) {
  2147. t->outputError("Function does not return a value (function returns 'void' and cannot be used within an expression)");
  2148. // RESOLUTION: proceed with int constant
  2149. a.flags &= ~Operand::OF_IS_VOID;
  2150. }
  2151. if (type == OPER_IS) {
  2152. // Second operand can be a datatype or scriptname
  2153. // @TODO:
  2154. t->outputError("Not currently supported: '%s'", token.c_str());
  2155. }
  2156. else if (type == OPER_AS) {
  2157. // Second operand must be a datatype or scriptname
  2158. // @TODO:
  2159. t->outputError("Not currently supported: '%s'", token.c_str());
  2160. }
  2161. else if ((type == OPER_B_NOT) || (type == OPER_L_NOT)) {
  2162. t->outputError("Unexpected operator '%s' (this operator only takes one operand and should not appear between two values)", token.c_str());
  2163. // RESOLUTION: Start expression anew at this unary operator for (hopefully) proper expression parsing
  2164. return parseExpression(warnAssign, usingValue, NULL, stopPrecedence, varToCount);
  2165. }
  2166. else if (type == OPER_ASSIGN) {
  2167. // Should've been handled in operand parsing
  2168. t->outputError("Cannot assign here- can only assign to a variable or subscripted variable");
  2169. // RESOLUTION: treat like == in order to proceed
  2170. type = OPER_EQ;
  2171. }
  2172. // Anything else- proceed normally
  2173. // Non-commutative non-reversible operators (- / % << >> #) require the
  2174. // first operand to be a temporary. We hold off on defining strings as
  2175. // we may cancel this if a and b end up being constants
  2176. // (= . 'as' 'is' are non-commutative but not applicable here)
  2177. if (((type == OPER_MINUS) || (type == OPER_DIV) || (type == OPER_MOD) ||
  2178. (type == OPER_LSHIFT) || (type == OPER_RSHIFT) || (type == OPER_CONCAT)) &&
  2179. !varToCount) {
  2180. if (OM_IS_LITERAL(a.mode)) aFinishLiteralAt = ws->code.size();
  2181. aFinishString = convertToTemp(a, aFinishLiteralAt);
  2182. aFinishLiteralSize = ws->code.size();
  2183. }
  2184. // Do type-check for . operator now, to prevent repeated checks later
  2185. if (type == OPER_MEMBER) {
  2186. if (!OM_IS_ENTRY(a.mode) && !OM_IS_STR(a.mode) && a.mode != OM_ALL &&
  2187. a.mode != OM_ALL_OTHER && a.mode != OM_THIS &&
  2188. (OM_IS_LITERAL(a.mode) || (!OM_IS_ENTITY(a.mode) && !OM_IS_OBJECT(a.mode)))) {
  2189. t->outputError("Left operand to . must be an entity or object or something that can be used as one");
  2190. // RESOLUTION: continue at next operand
  2191. t->skipToken();
  2192. return parseOperand(warnAssign, usingValue, varToCount);
  2193. }
  2194. }
  2195. }
  2196. else {
  2197. // Not an error- no recognized operator means a single operand- just return it
  2198. return a;
  2199. }
  2200. t->skipToken();
  2201. // The first non-. operator means we're now "using" return values.
  2202. if (type != OPER_MEMBER) usingValue = 1;
  2203. Operand b = parseOperand(warnAssign, usingValue, varToCount, type == OPER_MEMBER ? &a : NULL);
  2204. if (b.mode == 0)
  2205. return a;
  2206. // If parseOperand did all the work of the OPER_MEMBER, then a.mode will be 0 now
  2207. // Now peek ahead for another operator
  2208. int nextType;
  2209. string nextToken;
  2210. t->peekToken(nextType, nextToken);
  2211. // @TODO: future optimization, if operator is same and is
  2212. // commutative/associative (+, *) and is more likely to be const+const,
  2213. // yield precedence to help precalculate constants
  2214. // Compare precedence
  2215. if ((nextType & TOKEN_OPERATOR) && (type != OPER_MEMBER) &&
  2216. (precedence(type) > precedence(nextType))) {
  2217. // Next expression has precedence for now
  2218. b = parseExpression(warnAssign, 1, &b, precedence(type), varToCount);
  2219. if (b.mode == 0) {
  2220. // Even though an error condition, we need to finish temporarization
  2221. if (aFinishLiteralAt) {
  2222. compileAssert(!varToCount);
  2223. if (aFinishString) {
  2224. a.mode = OM_STR;
  2225. defineString(a);
  2226. a.mode = (OperMode)(OM_STR | OM_STACK | OM_NO_CONVERT);
  2227. // We know that a string push would've been 2 ints total
  2228. ws->code[aFinishLiteralAt + 1] += a.data.i;
  2229. }
  2230. a.data.i = 0;
  2231. }
  2232. return a;
  2233. }
  2234. // (peek again)
  2235. t->peekToken(nextType, nextToken);
  2236. }
  2237. // Now we have precedence.
  2238. // If a was a temporarized literal...
  2239. if (aFinishLiteralAt) {
  2240. compileAssert(!varToCount);
  2241. // We have to finish OR cancel temporarization of a
  2242. if (OM_IS_LITERAL(b.mode)) {
  2243. // Cancel- nothing else should have been placed on stack!
  2244. compileAssert(ws->code.size() == aFinishLiteralSize);
  2245. // We can't be positive that exactly 2 ints were added to bytecode,
  2246. // so calculate difference and remove that much
  2247. while (aFinishLiteralSize != aFinishLiteralAt) {
  2248. ws->code.pop_back();
  2249. --aFinishLiteralSize;
  2250. }
  2251. --ws->stackDepth;
  2252. a.flags = 0;
  2253. // Clears location and OM_NO_CONVERT
  2254. a.mode = (OperMode)(a.mode & OM_BASETYPE);
  2255. }
  2256. else {
  2257. // Finish
  2258. if (aFinishString) {
  2259. a.mode = OM_STR;
  2260. defineString(a);
  2261. a.mode = (OperMode)(OM_STR | OM_STACK | OM_NO_CONVERT);
  2262. // We know that a string push would've been 2 ints total
  2263. ws->code[aFinishLiteralAt + 1] += a.data.i;
  2264. }
  2265. a.data.i = 0;
  2266. }
  2267. }
  2268. // Operation
  2269. if (a.mode == 0)
  2270. a = b;
  2271. else if (varToCount)
  2272. a.data.i += b.data.i;
  2273. else
  2274. a = parseOperation(type, token, a, b);
  2275. // Loop back for more? Don't loop back if next operator
  2276. // has worse precedence than our caller
  2277. if ((nextType & TOKEN_OPERATOR) &&
  2278. (stopPrecedence > precedence(nextType))) {
  2279. type = nextType;
  2280. token = nextToken;
  2281. continue;
  2282. }
  2283. // Done
  2284. return a;
  2285. }
  2286. }
  2287. Compiler::Operand Compiler::parseOperand(int warnAssign, int usingValue, const Variable* varToCount, Operand* memberOf) { start_func
  2288. int type;
  2289. string token;
  2290. Operand result;
  2291. createEmpty(result);
  2292. int skippedToken = 0;
  2293. if (t->peekToken(type, token)) {
  2294. // REMEMBER WHEN ADDING NEW OPERAND TOKENS THAT THESE NEED
  2295. // TO BE ADDED TO PARSEFUNCTION() AS INITIATING TOKENS ALSO
  2296. // AND ALSO TO MAIN COMPILEBLOCK() LOOP AS EXPRESSION TOKENS
  2297. switch (type) {
  2298. case TOKEN_INTEGER: {
  2299. if (varToCount) { createInt(result, 0); break; }
  2300. result.data.i = strToInt(token);
  2301. result.mode = OM_INT;
  2302. break;
  2303. }
  2304. case TOKEN_HEX: {
  2305. if (varToCount) { createInt(result, 0); break; }
  2306. result.data.i = strtol(token.c_str(), NULL, 0);
  2307. result.mode = OM_INT;
  2308. break;
  2309. }
  2310. case TOKEN_DECIMAL: {
  2311. if (varToCount) { createInt(result, 0); break; }
  2312. result.data.f = strToFloat(token);
  2313. result.mode = OM_FLOAT;
  2314. break;
  2315. }
  2316. case TOKEN_STRING: {
  2317. if (varToCount) { createInt(result, 0); break; }
  2318. result.data.i = 0;
  2319. result.ref.strLiteral = new string(token);
  2320. result.mode = OM_STR;
  2321. break;
  2322. }
  2323. // @TTODO: Consolidate these constants?
  2324. case KEYW_TRUE: {
  2325. if (varToCount) { createInt(result, 0); break; }
  2326. result.data.i = 1;
  2327. result.mode = OM_INT;
  2328. break;
  2329. }
  2330. case KEYW_FALSE: {
  2331. if (varToCount) { createInt(result, 0); break; }
  2332. result.data.i = 0;
  2333. result.mode = OM_INT;
  2334. break;
  2335. }
  2336. case KEYW_QUERY: {
  2337. if (varToCount) { createInt(result, 0); break; }
  2338. result.data.i = -1;
  2339. result.mode = OM_INT;
  2340. break;
  2341. }
  2342. case KEYW_ALL: {
  2343. if (varToCount) { createInt(result, 0); break; }
  2344. result.data.i = 0;
  2345. result.mode = OM_ALL;
  2346. result.subType = 0;
  2347. break;
  2348. }
  2349. case KEYW_ALL_OTHER: {
  2350. if (varToCount) { createInt(result, 0); break; }
  2351. result.data.i = 0;
  2352. result.mode = OM_ALL_OTHER;
  2353. result.subType = 0;
  2354. break;
  2355. }
  2356. case KEYW_NOTHING: {
  2357. if (varToCount) { createInt(result, 0); break; }
  2358. result.data.i = 0;
  2359. result.mode = OM_NOTHING;
  2360. result.subType = 0;
  2361. break;
  2362. }
  2363. case KEYW_THIS: {
  2364. if (varToCount) { createInt(result, 0); break; }
  2365. result.data.i = 0;
  2366. result.mode = OM_THIS;
  2367. result.subType = scriptType;
  2368. break;
  2369. }
  2370. case TOKEN_IDENTIFIER: {
  2371. // function call/message send or variable
  2372. t->skipToken();
  2373. skippedToken = 1;
  2374. // @TODO: no scope or subscript for now
  2375. // @TODO: varToCount not supported for this portion entirely
  2376. // member variable or function
  2377. int searchFor = 0;
  2378. Operand assumeThis;
  2379. if (memberOf) {
  2380. if (OM_IS_LITERAL(memberOf->mode) || OM_IS_STR(memberOf->mode)) {
  2381. searchFor = SUB_ENTITY;
  2382. }
  2383. else if (OM_IS_OBJECT(memberOf->mode)) {
  2384. searchFor = memberOf->subType;
  2385. }
  2386. else if (OM_IS_ENTITY(memberOf->mode)) {
  2387. searchFor = SUB_ENTITY;
  2388. }
  2389. else compileAssert(0);
  2390. }
  2391. else {
  2392. // Basically "this." is presumed
  2393. searchFor = SUB_ENTITY;
  2394. assumeThis.data.i = 0;
  2395. assumeThis.mode = OM_THIS;
  2396. assumeThis.subType = scriptType;
  2397. memberOf = &assumeThis;
  2398. }
  2399. // Search for matching built-in member
  2400. for (int pos = 0; memberTable[pos].objtype; ++pos) {
  2401. if ((memberTable[pos].objtype == searchFor) &&
  2402. (token == memberTable[pos].name)) {
  2403. // Ensure copy, not convert, for object pointer
  2404. if (!OM_IS_LITERAL(memberOf->mode) && OM_IS_CONVERT(memberOf->mode))
  2405. memberOf->mode = (OperMode)(memberOf->mode | OM_COPY);
  2406. // Use pop mode if appropriate
  2407. if (O_IS_TEMP(*memberOf)) {
  2408. compileAssert(memberOf->data.i == 0);
  2409. memberOf->mode = (OperMode)((memberOf->mode & ~OM_LOCATION) | OM_POP);
  2410. }
  2411. // Member found- assign or read?
  2412. if ((t->peekToken(type, token)) && (type == OPER_ASSIGN)) {
  2413. if (memberTable[pos].readonly)
  2414. t->outputError("Member '%s' is read-only (cannot assign a value to it)", token.c_str());
  2415. // RESOLUTION: assign anyways
  2416. if (warnAssign)
  2417. t->outputWarning("Assignment as a condition- did you mean '==' to compare? (surround assignment in extra parenthesis to suppress warning)");
  2418. t->skipToken();
  2419. // @TODO: Ensure handles all/all_other/string as memberOf
  2420. parseAssignment(*memberOf, memberTable[pos].membertype, NULL, memberTable[pos].index);
  2421. // @TODO: if we're usingValue, should be a OP_REFe instead of OP_SETe
  2422. // and skip OM_POP earlier; this irrelevant value is only valid if we aren't
  2423. compileAssert(!usingValue);
  2424. createInt(result, 0);
  2425. result.flags |= Operand::OF_IS_SIDEFX;
  2426. // If popped, adjust stack
  2427. if (OM_IS_POP(memberOf->mode))
  2428. --ws->stackDepth;
  2429. }
  2430. else {
  2431. Operand b, c;
  2432. createInt(b, memberTable[pos].index);
  2433. // Prep result now, as we use it's datatype
  2434. result = dataTypeToOperand(memberTable[pos].membertype);
  2435. result.mode = (OperMode)(result.mode | OM_STACK);
  2436. result.data.i = 0;
  2437. // Need a StackEntry datatype
  2438. createInt(c, result.mode & OM_BASETYPE);
  2439. // @TODO: Ensure handles all/all_other/string as memberOf
  2440. postCmdRaw(searchFor == SUB_ENTITY ? OP_GETe : OP_GETo, memberOf, &b, &c);
  2441. // If popped, it was replaced with newly created value;
  2442. // if not popped, we have a new value on the stack
  2443. if (!OM_IS_POP(memberOf->mode))
  2444. ++ws->stackDepth;
  2445. }
  2446. // (this tells caller that we handled the OPER_MEMBER
  2447. memberOf->mode = OM_NONE;
  2448. return result;
  2449. }
  2450. }
  2451. // Objects only have these specific members, so we're done
  2452. if (searchFor != SUB_ENTITY) {
  2453. t->outputError("Unrecognized identifier '%s'- no object member by that name", token.c_str());
  2454. // RESOLUTION: discarded token
  2455. break;
  2456. }
  2457. // Special handing for this. (may be presumed)
  2458. if (memberOf->mode == OM_THIS) {
  2459. // find matching function
  2460. Function f;
  2461. if (findFunction(token, f)) {
  2462. // (only vartocount if var isn't scoped)
  2463. if (varToCount) { createInt(result, (varToCount->scope <= 0) ? 1 : 0); break; }
  2464. result = parseFunction(f, token);
  2465. result.flags |= Operand::OF_IS_SIDEFX;
  2466. if ((usingValue) && (O_IS_VOID(result))) {
  2467. t->outputError("Function does not return a value (function returns 'void' and cannot be used within an expression)");
  2468. // RESOLUTION: proceed with int constant
  2469. result.flags &= ~Operand::OF_IS_VOID;
  2470. }
  2471. break;
  2472. }
  2473. // find matching variable
  2474. VariableMap::iterator vlist = vars->find(token.c_str());
  2475. if (vlist == vars->end()) {
  2476. // One last possibility- message send, only if we "presumed" this.
  2477. if (memberOf == &result) {
  2478. // @TODO: make this auto-conversion an option
  2479. string nextToken;
  2480. if ((t->peekToken(type, nextToken)) && (type == OPER_MEMBER)) {
  2481. if (varToCount) { createInt(result, 0); break; }
  2482. // Convert identifier to string and continue
  2483. result.data.i = 0;
  2484. result.ref.strLiteral = new string(token);
  2485. result.mode = OM_STR;
  2486. break;
  2487. }
  2488. }
  2489. t->outputError("Unrecognized identifier '%s'- no variable or function by that name", token.c_str());
  2490. // RESOLUTION: discarded token
  2491. break;
  2492. }
  2493. Variable& v = (*vlist).second.back();
  2494. // If assignment coming up, perform that now
  2495. if ((t->peekToken(type, token)) && (type == OPER_ASSIGN)) {
  2496. if (warnAssign)
  2497. t->outputWarning("Assignment as a condition- did you mean '==' to compare? (surround assignment in extra parenthesis to suppress warning)");
  2498. t->skipToken();
  2499. result = variableToOperand(v);
  2500. parseAssignment(result, v.datatype, varToCount);
  2501. // @TODO: optimize by getting operand from parseAssignment instead of
  2502. // turning variable into operand, when appropriate? (careful with arrays
  2503. // and hashes, they might need to become refs; careful with variants or
  2504. // type changes; careful with temporaries that would have been popped now;
  2505. // might also be affected by the optimization algorithm for a=a+1?)
  2506. result.flags |= Operand::OF_IS_SIDEFX;
  2507. }
  2508. else if (!varToCount) {
  2509. result = variableToOperand(v);
  2510. }
  2511. if (varToCount) { createInt(result, (&v == varToCount) ? 1 : 0); break; }
  2512. }
  2513. // Now it's either another entity, or an entity literal/string/etc.
  2514. else {
  2515. // @TODO: Ensure handles all/all_other/string
  2516. // @TODO: Search for user-defined variable or function
  2517. compileAssert(0);
  2518. }
  2519. break;
  2520. }
  2521. case KEYW_SOURCE:
  2522. case KEYW_DEFAULT: // (needs to basically follow identifier section, expecting a :: next)
  2523. case OPER_PLUS:
  2524. case OPER_MINUS:
  2525. case OPER_B_NOT:
  2526. case OPER_L_NOT: {
  2527. // @TODO: L_NOT can be optimized if last operation on an operand before
  2528. // an if-clause or sometimes before an expression consisting of other
  2529. // logical/comparison operators
  2530. // @TODO: (how to handle precedence for opers? just recurse to parseoperand; watch for void)
  2531. if (varToCount) { createInt(result, 0); break; }
  2532. t->outputError("Not currently supported: '%s'", token.c_str());
  2533. break;
  2534. }
  2535. case TOKEN_OPEN_PAREN: {
  2536. // Another expression within parenthesis
  2537. t->skipToken();
  2538. result = parseExpression(warnAssign > 0 ? warnAssign - 1 : warnAssign, usingValue, NULL, 100, varToCount);
  2539. t->peekToken(type, token);
  2540. if (type == TOKEN_CLOSE_PAREN) {
  2541. t->skipToken();
  2542. }
  2543. else {
  2544. t->outputError("Missing closing parenthesis");
  2545. // RESOLUTION: pretend paren was present
  2546. }
  2547. return result;
  2548. }
  2549. case TOKEN_ENDLINE: {
  2550. t->outputError("Unexpected end-of-line (expected value or expression)", token.c_str());
  2551. // RESOLUTION: token will get processed by higher routines
  2552. break;
  2553. }
  2554. default: {
  2555. t->outputError("Unexpected token '%s' (expected value or expression)", token.c_str());
  2556. // RESOLUTION: token will get processed by higher routines
  2557. break;
  2558. }
  2559. }
  2560. }
  2561. if (result.mode == 0) {
  2562. // Error state
  2563. result.data.i = 0;
  2564. }
  2565. else if (!skippedToken) {
  2566. t->skipToken();
  2567. }
  2568. return result;
  2569. }
  2570. Compiler::Operand Compiler::parseOperation(int oper, const string& operToken, Operand& a, Operand& b) { start_func
  2571. compileAssert(oper & TOKEN_OPERATOR);
  2572. compileAssert(a.mode);
  2573. compileAssert(!OM_IS_COPY(a.mode));
  2574. compileAssert(!OM_IS_CONST(a.mode));
  2575. compileAssert(!OM_IS_POP(a.mode));
  2576. compileAssert(!OM_IS_POINTER(a.mode));
  2577. compileAssert(b.mode);
  2578. compileAssert(!OM_IS_COPY(b.mode));
  2579. compileAssert(!OM_IS_CONST(b.mode));
  2580. compileAssert(!OM_IS_POP(b.mode));
  2581. compileAssert(!OM_IS_POINTER(b.mode));
  2582. // Categorize operator- 4) string 3) math, 2) bit/mod, 1) logic, 0) equality
  2583. int otype = 0;
  2584. if ((oper == OPER_L_AND) || (oper == OPER_L_OR) || (oper == OPER_L_XOR))
  2585. otype = 1;
  2586. else if ((oper == OPER_LSHIFT) || (oper == OPER_RSHIFT) ||
  2587. (oper == OPER_B_AND) || (oper == OPER_B_OR) ||
  2588. (oper == OPER_B_XOR) || (oper == OPER_MOD))
  2589. otype = 2;
  2590. else if ((oper == OPER_PLUS) || (oper == OPER_MINUS) ||
  2591. (oper == OPER_MULT) || (oper == OPER_DIV))
  2592. otype = 3;
  2593. else if (oper == OPER_CONCAT)
  2594. otype = 4;
  2595. // @TODO: convert var operands if unambiguous e.g. bit/mod, convert to int
  2596. // General error: no hash or array or variant operands except for logical operators
  2597. if (otype != 1) {
  2598. if (OM_IS_ENTRY(a.mode)) {
  2599. t->outputError("Left operand to '%s' cannot be a variant (convert to a non-variant first)", operToken.c_str());
  2600. // RESOLUTION: continue with (hopefully) non-variant operand
  2601. return b;
  2602. }
  2603. if (OM_IS_ENTRY(b.mode)) {
  2604. t->outputError("Right operand to '%s' cannot be a variant (convert to a non-variant first)", operToken.c_str());
  2605. // RESOLUTION: continue with non-variant operand
  2606. return a;
  2607. }
  2608. if (OM_IS_ARRAY(a.mode)) {
  2609. t->outputError("Left operand to '%s' cannot be an array (use [ and ] to select a value from the array)", operToken.c_str());
  2610. // RESOLUTION: continue with (hopefully) non-array operand
  2611. return b;
  2612. }
  2613. if (OM_IS_ARRAY(b.mode)) {
  2614. t->outputError("Right operand to '%s' cannot be a array (use [ and ] to select a value from the array)", operToken.c_str());
  2615. // RESOLUTION: continue with non-array operand
  2616. return a;
  2617. }
  2618. if (OM_IS_HASH(a.mode)) {
  2619. t->outputError("Left operand to '%s' cannot be a hash (use [ and ] to select a value from the hash)", operToken.c_str());
  2620. // RESOLUTION: continue with (hopefully) non-hash operand
  2621. return b;
  2622. }
  2623. if (OM_IS_HASH(b.mode)) {
  2624. t->outputError("Right operand to '%s' cannot be a hash (use [ and ] to select a value from the hash)", operToken.c_str());
  2625. // RESOLUTION: continue with non-hash operand
  2626. return a;
  2627. }
  2628. }
  2629. // General error: no string operands except for logical/comparison/string operators
  2630. if ((otype > 1) && (otype < 4)) {
  2631. if (OM_IS_STR(a.mode)) {
  2632. t->outputError("Left operand to '%s' cannot be a string (convert to a number first)", operToken.c_str());
  2633. // RESOLUTION: continue with (hopefully) non-string operand
  2634. if (a.mode == OM_STR) delete a.ref.strLiteral;
  2635. return b;
  2636. }
  2637. if (OM_IS_STR(b.mode)) {
  2638. t->outputError("Right operand to '%s' cannot be a string (convert to a number first)", operToken.c_str());
  2639. // RESOLUTION: continue with non-string operand
  2640. if (b.mode == OM_STR) delete b.ref.strLiteral;
  2641. return a;
  2642. }
  2643. }
  2644. // General error: no object/"odd literal" except for logical/comparison operators
  2645. if (otype > 1) {
  2646. if (a.mode == OM_ALL || a.mode == OM_ALL_OTHER || a.mode == OM_NOTHING || a.mode == OM_THIS ||
  2647. OM_IS_OBJECT(a.mode) || OM_IS_ENTITY(a.mode)) {
  2648. t->outputError("Left operand to '%s' cannot be an entity or object", operToken.c_str());
  2649. // RESOLUTION: continue with (hopefully) non-object operand
  2650. return b;
  2651. }
  2652. if (b.mode == OM_ALL || b.mode == OM_ALL_OTHER || b.mode == OM_NOTHING || b.mode == OM_THIS ||
  2653. OM_IS_OBJECT(b.mode) || OM_IS_ENTITY(b.mode)) {
  2654. t->outputError("Right operand to '%s' cannot be an entity or object", operToken.c_str());
  2655. // RESOLUTION: continue with non-object operand
  2656. return a;
  2657. }
  2658. }
  2659. else if (otype == 0) {
  2660. // object-type operands are allowed here but must be compatible types
  2661. if (a.mode == OM_ALL || a.mode == OM_ALL_OTHER || a.mode == OM_NOTHING || a.mode == OM_THIS ||
  2662. b.mode == OM_ALL || b.mode == OM_ALL_OTHER || b.mode == OM_NOTHING || b.mode == OM_THIS ||
  2663. OM_IS_OBJECT(a.mode) || OM_IS_ENTITY(a.mode) ||
  2664. OM_IS_OBJECT(b.mode) || OM_IS_ENTITY(b.mode)) {
  2665. // Literals are basically of type OM_ENTITY except for 'nothing'
  2666. int aType = a.mode & OM_BASETYPE;
  2667. int aSub = a.subType;
  2668. int bType = b.mode & OM_BASETYPE;
  2669. int bSub = b.subType;
  2670. if (OM_IS_LITERAL(a.mode)) {
  2671. if (a.mode == OM_ALL || a.mode == OM_ALL_OTHER) {
  2672. t->outputError("Cannot use multi-object literals ('all', 'all_other') in comparison", operToken.c_str());
  2673. // RESOLUTION: just continue with other operand for simplicity
  2674. return b;
  2675. }
  2676. if ((a.mode == OM_NOTHING) && (!OM_IS_LITERAL(b.mode))) {
  2677. aType = bType;
  2678. aSub = bSub;
  2679. }
  2680. else aType = OM_ENTITY;
  2681. }
  2682. if (OM_IS_LITERAL(b.mode)) {
  2683. if (b.mode == OM_ALL || b.mode == OM_ALL_OTHER) {
  2684. t->outputError("Cannot use multi-object literals ('all', 'all_other') in comparison", operToken.c_str());
  2685. // RESOLUTION: just continue with other operand for simplicity
  2686. return a;
  2687. }
  2688. if ((b.mode == OM_NOTHING) && (!OM_IS_LITERAL(b.mode))) {
  2689. bType = aType;
  2690. bSub = aSub;
  2691. }
  2692. else bType = OM_ENTITY;
  2693. }
  2694. // Ensure both are same type
  2695. if (aType != bType) {
  2696. t->outputError("Cannot compare object to non-object or entity to non-entity using '%s' operator", operToken.c_str());
  2697. // RESOLUTION: just continue with first operand for simplicity
  2698. return a;
  2699. }
  2700. // Now ensure subtype matches exactly or is non-type vs type
  2701. if ((aSub != bSub) && (aSub) && (bSub)) {
  2702. t->outputError("Object or script types are not compatible for '%s' operator", operToken.c_str());
  2703. // RESOLUTION: just continue with first operand for simplicity
  2704. return a;
  2705. }
  2706. }
  2707. }
  2708. // Now we know the operands are valid modes- i/s/f, a/h/o for logicals only, l/s/g/ind/convert unverified
  2709. // Perform standard conversions
  2710. // One problem could occur- if b is a temporary and a converts to a temporary now,
  2711. // a will be on stack top, so a/b and operation needs reversing
  2712. // this won't ever occur with non-commutative operations because those
  2713. // will already have converted a to a temporary
  2714. int watchForSwap = O_IS_TEMP(b) && !O_IS_TEMP(a);
  2715. if (otype == 4) {
  2716. // String- upgrade to string always
  2717. if (!OM_IS_STR(a.mode))
  2718. convertToStr(a);
  2719. if (!OM_IS_STR(b.mode))
  2720. convertToStr(b);
  2721. }
  2722. if (otype == 0) {
  2723. // Equality- upgrade to string
  2724. if (OM_IS_STR(a.mode) && !OM_IS_STR(b.mode))
  2725. convertToStr(b);
  2726. if (OM_IS_STR(b.mode) && !OM_IS_STR(a.mode))
  2727. convertToStr(a);
  2728. }
  2729. if ((otype == 3) || (otype == 0)) {
  2730. // Math or equality- upgrade to float
  2731. if (OM_IS_FLOAT(a.mode) && !OM_IS_FLOAT(b.mode))
  2732. convertToFloat(b);
  2733. if (OM_IS_FLOAT(b.mode) && !OM_IS_FLOAT(a.mode))
  2734. convertToFloat(a);
  2735. }
  2736. if (otype == 2) {
  2737. // Bit/Mod- downgrade to integer
  2738. if (!OM_IS_INT(a.mode))
  2739. convertToInt(a);
  2740. if (!OM_IS_INT(b.mode))
  2741. convertToInt(b);
  2742. }
  2743. // This will be true if we need inverse operation now
  2744. watchForSwap = watchForSwap && O_IS_TEMP(a);
  2745. if (watchForSwap) swap(a, b);
  2746. // Triggers common routines for most basic operators
  2747. // Common routines do not support hash/array operands (logical operators)
  2748. int doCommon = 0;
  2749. int isCommutative = 1;
  2750. int hasInverse = 0; // Can we swap operands using a different opcode? (equalities mostly)
  2751. int pushesResult = !otype; // Equality operators push a new result
  2752. Opcode forInt, forFloat, forStr, forObj;
  2753. Opcode swapInt, swapFloat, swapStr, swapObj;
  2754. switch (oper) {
  2755. case OPER_PLUS: {
  2756. // Const+const
  2757. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2758. // (both are the same due to earlier upgrades)
  2759. if (OM_IS_FLOAT(a.mode))
  2760. a.data.f += b.data.f;
  2761. else
  2762. a.data.i += b.data.i;
  2763. }
  2764. else {
  2765. doCommon = 1;
  2766. forInt = OP_ADD;
  2767. forFloat = OP_ADDf;
  2768. }
  2769. break;
  2770. }
  2771. case OPER_MULT: {
  2772. // Const*const
  2773. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2774. if (OM_IS_FLOAT(a.mode))
  2775. a.data.f *= b.data.f;
  2776. else
  2777. a.data.i *= b.data.i;
  2778. }
  2779. else {
  2780. doCommon = 1;
  2781. forInt = OP_MULT;
  2782. forFloat = OP_MULTf;
  2783. }
  2784. break;
  2785. }
  2786. case OPER_MINUS: {
  2787. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2788. if (OM_IS_FLOAT(a.mode))
  2789. a.data.f -= b.data.f;
  2790. else
  2791. a.data.i -= b.data.i;
  2792. }
  2793. else {
  2794. doCommon = 1;
  2795. isCommutative = 0;
  2796. forInt = OP_SUB;
  2797. forFloat = OP_SUBf;
  2798. }
  2799. break;
  2800. }
  2801. case OPER_DIV: {
  2802. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2803. if (OM_IS_FLOAT(a.mode)) {
  2804. if (b.data.f == 0.0) {
  2805. t->outputError("Divide by zero");
  2806. // RESOLUTION: result is zero
  2807. a.data.f = 0.0;
  2808. }
  2809. else {
  2810. a.data.f /= b.data.f;
  2811. }
  2812. }
  2813. else {
  2814. if (b.data.i == 0) {
  2815. t->outputError("Divide by zero");
  2816. // RESOLUTION: result is zero
  2817. a.data.i = 0;
  2818. }
  2819. else {
  2820. a.data.i /= b.data.i;
  2821. }
  2822. }
  2823. }
  2824. else {
  2825. doCommon = 1;
  2826. isCommutative = 0;
  2827. forInt = OP_DIV;
  2828. forFloat = OP_DIVf;
  2829. }
  2830. break;
  2831. }
  2832. case OPER_MOD: {
  2833. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2834. if (b.data.i == 0) {
  2835. t->outputError("Divide by zero");
  2836. // RESOLUTION: result is zero
  2837. a.data.i = 0;
  2838. }
  2839. else {
  2840. a.data.i %= b.data.i;
  2841. }
  2842. }
  2843. else {
  2844. doCommon = 1;
  2845. isCommutative = 0;
  2846. forInt = OP_MOD;
  2847. }
  2848. break;
  2849. }
  2850. case OPER_LSHIFT: {
  2851. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2852. a.data.i <<= b.data.i;
  2853. }
  2854. else {
  2855. doCommon = 1;
  2856. isCommutative = 0;
  2857. forInt = OP_SHIFTL;
  2858. }
  2859. break;
  2860. }
  2861. case OPER_RSHIFT: {
  2862. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2863. a.data.i >>= b.data.i;
  2864. }
  2865. else {
  2866. doCommon = 1;
  2867. isCommutative = 0;
  2868. forInt = OP_SHIFTR;
  2869. }
  2870. break;
  2871. }
  2872. case OPER_B_AND: {
  2873. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2874. a.data.i &= b.data.i;
  2875. }
  2876. else {
  2877. doCommon = 1;
  2878. forInt = OP_AND;
  2879. }
  2880. break;
  2881. }
  2882. case OPER_B_OR: {
  2883. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2884. a.data.i |= b.data.i;
  2885. }
  2886. else {
  2887. doCommon = 1;
  2888. forInt = OP_OR;
  2889. }
  2890. break;
  2891. }
  2892. case OPER_B_XOR: {
  2893. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2894. a.data.i ^= b.data.i;
  2895. }
  2896. else {
  2897. doCommon = 1;
  2898. forInt = OP_XOR;
  2899. }
  2900. break;
  2901. }
  2902. case OPER_CONCAT: {
  2903. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2904. compileAssert(a.ref.strLiteral);
  2905. compileAssert(b.ref.strLiteral);
  2906. *a.ref.strLiteral += *b.ref.strLiteral;
  2907. }
  2908. else {
  2909. doCommon = 1;
  2910. isCommutative = 0;
  2911. forStr = OP_CONCAT;
  2912. }
  2913. break;
  2914. }
  2915. case OPER_EQ: {
  2916. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2917. if (OM_IS_STR(a.mode)) {
  2918. compileAssert(a.ref.strLiteral);
  2919. compileAssert(b.ref.strLiteral);
  2920. a.data.i = (myStricmp(a.ref.strLiteral->c_str(), b.ref.strLiteral->c_str()) == 0);
  2921. delete a.ref.strLiteral;
  2922. a.ref.strLiteral = NULL;
  2923. }
  2924. else if (OM_IS_FLOAT(a.mode))
  2925. a.data.i = (a.data.f == b.data.f);
  2926. // Only going to be a combination of this/empty
  2927. else if ((a.mode == OM_THIS) || (a.mode == OM_NOTHING))
  2928. a.data.i = (a.mode == b.mode);
  2929. else
  2930. a.data.i = (a.data.i == b.data.i);
  2931. compileAssert(a.flags == 0);
  2932. a.mode = OM_INT;
  2933. }
  2934. else {
  2935. doCommon = 1;
  2936. forInt = OP_EQ;
  2937. forFloat = OP_EQf;
  2938. forStr = OP_EQs;
  2939. forObj = OP_EQo;
  2940. }
  2941. break;
  2942. }
  2943. case OPER_LE: {
  2944. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2945. if (OM_IS_STR(a.mode)) {
  2946. compileAssert(a.ref.strLiteral);
  2947. compileAssert(b.ref.strLiteral);
  2948. a.data.i = (myStricmp(a.ref.strLiteral->c_str(), b.ref.strLiteral->c_str()) <= 0);
  2949. delete a.ref.strLiteral;
  2950. a.ref.strLiteral = NULL;
  2951. }
  2952. else if (OM_IS_FLOAT(a.mode))
  2953. a.data.i = (a.data.f <= b.data.f);
  2954. // Only going to be a combination of this/empty
  2955. else if ((a.mode == OM_THIS) || (a.mode == OM_NOTHING))
  2956. a.data.i = (a.mode == b.mode);
  2957. else
  2958. a.data.i = (a.data.i <= b.data.i);
  2959. compileAssert(a.flags == 0);
  2960. a.mode = OM_INT;
  2961. }
  2962. else {
  2963. doCommon = 1;
  2964. isCommutative = 0;
  2965. hasInverse = 1;
  2966. forInt = OP_LE;
  2967. forFloat = OP_LEf;
  2968. forStr = OP_LEs;
  2969. forObj = OP_EQo;
  2970. swapInt = OP_GE;
  2971. swapFloat = OP_GEf;
  2972. swapStr = OP_GEs;
  2973. swapObj = OP_EQo;
  2974. }
  2975. break;
  2976. }
  2977. case OPER_GT: {
  2978. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  2979. if (OM_IS_STR(a.mode)) {
  2980. compileAssert(a.ref.strLiteral);
  2981. compileAssert(b.ref.strLiteral);
  2982. a.data.i = (myStricmp(a.ref.strLiteral->c_str(), b.ref.strLiteral->c_str()) > 0);
  2983. delete a.ref.strLiteral;
  2984. a.ref.strLiteral = NULL;
  2985. }
  2986. else if (OM_IS_FLOAT(a.mode))
  2987. a.data.i = (a.data.f > b.data.f);
  2988. // Only going to be a combination of this/empty
  2989. else if ((a.mode == OM_THIS) || (a.mode == OM_NOTHING))
  2990. a.data.i = (a.mode != b.mode);
  2991. else
  2992. a.data.i = (a.data.i > b.data.i);
  2993. compileAssert(a.flags == 0);
  2994. a.mode = OM_INT;
  2995. }
  2996. else {
  2997. doCommon = 1;
  2998. isCommutative = 0;
  2999. hasInverse = 1;
  3000. forInt = OP_GT;
  3001. forFloat = OP_GTf;
  3002. forStr = OP_GTs;
  3003. forObj = OP_NEo;
  3004. swapInt = OP_LT;
  3005. swapFloat = OP_LTf;
  3006. swapStr = OP_LTs;
  3007. swapObj = OP_NEo;
  3008. }
  3009. break;
  3010. }
  3011. case OPER_GE: {
  3012. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  3013. if (OM_IS_STR(a.mode)) {
  3014. compileAssert(a.ref.strLiteral);
  3015. compileAssert(b.ref.strLiteral);
  3016. a.data.i = (myStricmp(a.ref.strLiteral->c_str(), b.ref.strLiteral->c_str()) >= 0);
  3017. delete a.ref.strLiteral;
  3018. a.ref.strLiteral = NULL;
  3019. }
  3020. else if (OM_IS_FLOAT(a.mode))
  3021. a.data.i = (a.data.f >= b.data.f);
  3022. // Only going to be a combination of this/empty
  3023. else if ((a.mode == OM_THIS) || (a.mode == OM_NOTHING))
  3024. a.data.i = (a.mode == b.mode);
  3025. else
  3026. a.data.i = (a.data.i >= b.data.i);
  3027. compileAssert(a.flags == 0);
  3028. a.mode = OM_INT;
  3029. }
  3030. else {
  3031. doCommon = 1;
  3032. isCommutative = 0;
  3033. hasInverse = 1;
  3034. forInt = OP_GE;
  3035. forFloat = OP_GEf;
  3036. forStr = OP_GEs;
  3037. forObj = OP_EQo;
  3038. swapInt = OP_LE;
  3039. swapFloat = OP_LEf;
  3040. swapStr = OP_LEs;
  3041. swapObj = OP_EQo;
  3042. }
  3043. break;
  3044. }
  3045. case OPER_LT: {
  3046. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  3047. if (OM_IS_STR(a.mode)) {
  3048. compileAssert(a.ref.strLiteral);
  3049. compileAssert(b.ref.strLiteral);
  3050. a.data.i = (myStricmp(a.ref.strLiteral->c_str(), b.ref.strLiteral->c_str()) < 0);
  3051. delete a.ref.strLiteral;
  3052. a.ref.strLiteral = NULL;
  3053. }
  3054. else if (OM_IS_FLOAT(a.mode))
  3055. a.data.i = (a.data.f < b.data.f);
  3056. // Only going to be a combination of this/empty
  3057. else if ((a.mode == OM_THIS) || (a.mode == OM_NOTHING))
  3058. a.data.i = (a.mode != b.mode);
  3059. else
  3060. a.data.i = (a.data.i < b.data.i);
  3061. compileAssert(a.flags == 0);
  3062. a.mode = OM_INT;
  3063. }
  3064. else {
  3065. doCommon = 1;
  3066. isCommutative = 0;
  3067. hasInverse = 1;
  3068. forInt = OP_LT;
  3069. forFloat = OP_LTf;
  3070. forStr = OP_LTs;
  3071. forObj = OP_NEo;
  3072. swapInt = OP_GT;
  3073. swapFloat = OP_GTf;
  3074. swapStr = OP_GTs;
  3075. swapObj = OP_NEo;
  3076. }
  3077. break;
  3078. }
  3079. case OPER_NE: {
  3080. if (OM_IS_LITERAL(a.mode) && OM_IS_LITERAL(b.mode)) {
  3081. if (OM_IS_STR(a.mode)) {
  3082. compileAssert(a.ref.strLiteral);
  3083. compileAssert(b.ref.strLiteral);
  3084. a.data.i = (myStricmp(a.ref.strLiteral->c_str(), b.ref.strLiteral->c_str()) != 0);
  3085. delete a.ref.strLiteral;
  3086. a.ref.strLiteral = NULL;
  3087. }
  3088. else if (OM_IS_FLOAT(a.mode))
  3089. a.data.i = (a.data.f != b.data.f);
  3090. // Only going to be a combination of this/empty
  3091. else if ((a.mode == OM_THIS) || (a.mode == OM_NOTHING))
  3092. a.data.i = (a.mode != b.mode);
  3093. else
  3094. a.data.i = (a.data.i != b.data.i);
  3095. compileAssert(a.flags == 0);
  3096. a.mode = OM_INT;
  3097. }
  3098. else {
  3099. doCommon = 1;
  3100. forInt = OP_NE;
  3101. forFloat = OP_NEf;
  3102. forStr = OP_NEs;
  3103. forObj = OP_NEo;
  3104. }
  3105. break;
  3106. }
  3107. case OPER_L_AND:
  3108. case OPER_L_XOR:
  3109. case OPER_L_OR: {
  3110. // @TODO: (for now will just return first operand)
  3111. // commutative, so no need to check watchForSwap
  3112. // Also note that operands may have disparate types, be 'this'/'nothing'/'all'/'all_other',
  3113. // or even be variants!
  3114. // @TODO: short-circuiting if enabled
  3115. t->outputError("Not currently supported: '%s'", operToken.c_str());
  3116. break;
  3117. }
  3118. default: {
  3119. // (should never get past other operations)
  3120. compileAssert(0);
  3121. break;
  3122. }
  3123. }
  3124. // Common operator routine
  3125. if (doCommon) {
  3126. // Push-result commands must be swappable
  3127. if (pushesResult) compileAssert(isCommutative || hasInverse);
  3128. // Presumes temporaries are on top of stack
  3129. compileAssert(!O_IS_TEMP(a) || (a.data.i == 0));
  3130. compileAssert(!O_IS_TEMP(b) || (b.data.i == 0));
  3131. // If both items are temporaries, "move" first item down to it's true position
  3132. if (O_IS_TEMP(a) && O_IS_TEMP(b)) ++a.data.i;
  3133. // Different handling based on whether we overwrite first operand
  3134. if (pushesResult) {
  3135. // Just confirm first item isn't the literal; any other combination is valid
  3136. if (OM_IS_LITERAL(a.mode)) {
  3137. // Literal goes in second position
  3138. swap(a, b);
  3139. // must use the inverse operation if exists
  3140. if (hasInverse) watchForSwap = !watchForSwap;
  3141. }
  3142. }
  3143. else {
  3144. // (*for non-commutative operations, first should already be temporary*)
  3145. if (!isCommutative) compileAssert(O_IS_TEMP(a));
  3146. // One item MUST be a temporary (ideally, first item)
  3147. if (!O_IS_TEMP(a) && !O_IS_TEMP(b)) {
  3148. // Create temporary via PUSH- no reference allowed
  3149. convertToTemp(a);
  3150. // This moves other stack entry down if it's a stack var or temporary
  3151. if (OM_IS_STACK(b.mode)) {
  3152. ++b.data.i;
  3153. }
  3154. }
  3155. // Possibilities now: var + temp, temp + temp, temp + literal
  3156. // First item must be a temporary
  3157. // (*never occurs if this is a commutative operation or both are temps*)
  3158. if (!O_IS_TEMP(a)) swap(a, b);
  3159. // First item should also be a copy (we know it's a temporary)
  3160. // HOWEVER as we can never have arrays, hashes, variants here it's moot
  3161. compileAssert(!(OM_IS_ARRAY(a.mode) || OM_IS_HASH(a.mode) || OM_IS_ENTRY(a.mode)));
  3162. }
  3163. // Handle COPYness now, before doing POP
  3164. if (pushesResult && !OM_IS_LITERAL(a.mode) && OM_IS_CONVERT(a.mode))
  3165. a.mode = (OperMode)(a.mode | OM_COPY);
  3166. if (!OM_IS_LITERAL(b.mode) && OM_IS_CONVERT(b.mode))
  3167. b.mode = (OperMode)(b.mode | OM_COPY);
  3168. // If second item is a temporary, convert to a POP
  3169. // (*ok since this isn't hash/array*)
  3170. if (O_IS_TEMP(b)) {
  3171. compileAssert(b.data.i == 0);
  3172. b.mode = (OperMode)((b.mode & ~OM_LOCATION) | OM_POP);
  3173. }
  3174. // If first item is a temporary and we push result, convert that to a POP too
  3175. if (pushesResult && O_IS_TEMP(a)) {
  3176. a.mode = (OperMode)((a.mode & ~OM_LOCATION) | OM_POP);
  3177. // If was further down on the stack...
  3178. if (a.data.i == 1) {
  3179. // ...b is also a temporary that's been converted
  3180. compileAssert(OM_IS_POP(b.mode));
  3181. compileAssert(b.data.i == 0);
  3182. // a and b will get popped in reverse order, so we
  3183. // must use the inverse operation if exists
  3184. if (hasInverse) watchForSwap = !watchForSwap;
  3185. }
  3186. }
  3187. // Need to swap to inverse operation?
  3188. if (watchForSwap) {
  3189. if (hasInverse) {
  3190. forStr = swapStr;
  3191. forFloat = swapFloat;
  3192. forInt = swapInt;
  3193. forObj = swapObj;
  3194. }
  3195. else compileAssert(isCommutative);
  3196. }
  3197. // Post command (we know a/b aren't variants)
  3198. // Define strings
  3199. if (a.mode == OM_STR) defineString(a);
  3200. if (b.mode == OM_STR) defineString(b);
  3201. if (OM_IS_STR(a.mode)) {
  3202. compileAssert(OM_IS_STR(b.mode));
  3203. // Handle CONSTness
  3204. if (pushesResult) a.mode = (OperMode)(OM_STR_CONST | (a.mode & ~OM_BASETYPE));
  3205. b.mode = (OperMode)(OM_STR_CONST | (b.mode & ~OM_BASETYPE));
  3206. postCmdRaw(forStr, &a, &b);
  3207. }
  3208. else if (OM_IS_INT(a.mode)) {
  3209. compileAssert(OM_IS_INT(b.mode));
  3210. postCmdRaw(forInt, &a, &b);
  3211. }
  3212. else if (OM_IS_FLOAT(a.mode)) {
  3213. compileAssert(OM_IS_FLOAT(b.mode));
  3214. postCmdRaw(forFloat, &a, &b);
  3215. }
  3216. else {
  3217. compileAssert(OM_IS_ENTITY(a.mode) || OM_IS_OBJECT(a.mode) || a.mode == OM_THIS || a.mode == OM_NOTHING);
  3218. compileAssert(OM_IS_ENTITY(b.mode) || OM_IS_OBJECT(b.mode) || b.mode == OM_THIS || b.mode == OM_NOTHING);
  3219. postCmdRaw(forObj, &a, &b);
  3220. }
  3221. // (move item back up if popped; also adjust stack depth)
  3222. if (OM_IS_POP(b.mode)) {
  3223. --ws->stackDepth;
  3224. if (O_IS_TEMP(a)) --a.data.i;
  3225. }
  3226. if (OM_IS_POP(a.mode))
  3227. --ws->stackDepth;
  3228. // New result? (always an int- logical ops)
  3229. if (pushesResult) {
  3230. // a.ref.strLiteral is already NULL if there was anything (defineString() above)
  3231. ++ws->stackDepth;
  3232. createInt(a, 0);
  3233. a.mode = (OperMode)(OM_INT | OM_STACK | OM_NO_CONVERT);
  3234. }
  3235. else {
  3236. // Otherwise, mark result with new status- we know it's the right type now
  3237. a.mode = (OperMode)((a.mode & ~OM_FLAGS) | OM_NO_CONVERT);
  3238. // (would set OF_IS_COPY except we know it's not an array or hash in this code)
  3239. }
  3240. }
  3241. else {
  3242. destroyOperand(b);
  3243. }
  3244. // None of these operations have useful side effects. (@TODO: this won't be true for OPER_MEMBER)
  3245. a.flags &= ~Operand::OF_IS_SIDEFX;
  3246. return a;
  3247. }
  3248. const Variable& Compiler::defineVariable(DataType type, const string& name, int isParam) { start_func
  3249. // Possibilities-
  3250. // global var
  3251. // local var in outer scope (local to entire script)
  3252. // local var inner scope (local to block)
  3253. // local var function parameter
  3254. // global const
  3255. // local const outer scope
  3256. // local const inner scope
  3257. Variable var;
  3258. // Global / local / scoped
  3259. var.datatype = type;
  3260. var.datatype.flags &= ~(DATA_LOCAL | DATA_GLOBAL | DATA_CONST);
  3261. if (type.flags & DATA_GLOBAL) {
  3262. var.scope = -1;
  3263. }
  3264. else {
  3265. var.scope = scope;
  3266. }
  3267. // Const
  3268. if (type.flags & DATA_CONST) {
  3269. compileAssert(!isParam);
  3270. // @TODO: assign actual value once expression parsing is complete
  3271. if (type.baseType == DATA_INT)
  3272. var.val.constI = 0;
  3273. else if (type.baseType == DATA_FLOAT)
  3274. var.val.constF = 0.0;
  3275. else {
  3276. char* newCC = new char[1];
  3277. newCC[0] = 0;
  3278. var.val.constS = newCC;
  3279. }
  3280. // @TODO: Global consts need go into links to verify against each other during linking
  3281. }
  3282. // Non-globals
  3283. else if (var.scope >= 0) {
  3284. // inner scope- next stack item
  3285. if (var.scope > 0) {
  3286. // adjust for preexisting stack depth
  3287. // and adjust current stack depth
  3288. var.val.offs = -(++ws->stackDepth);
  3289. }
  3290. else {
  3291. compileAssert(!isParam);
  3292. // Take up next init spot
  3293. var.val.offs = localInit.stackDepth++;
  3294. // Code only goes to init for outer scope
  3295. pushWorkspace(&localInit);
  3296. }
  3297. if (!isParam) {
  3298. // @TODO: original assignment, if not outer scope, should be done instead
  3299. // even outer scope assignments can be done if at top of script and simple
  3300. generateBlank(type);
  3301. }
  3302. if (var.scope == 0) popWorkspace();
  3303. }
  3304. // Global will get added to link table whenever used
  3305. else {
  3306. compileAssert(!isParam);
  3307. var.val.offs = 0;
  3308. }
  3309. // Matches a function?
  3310. FunctionMap::iterator flist = func->find(name.c_str());
  3311. if (flist != func->end()) {
  3312. t->outputError("Function '%s' already exists in this script (variables and functions cannot share names)", name.c_str());
  3313. // RESOLUTION: define variable anyways
  3314. }
  3315. // Matches a built-in?
  3316. for (int pos = 0; memberTable[pos].objtype; ++pos) {
  3317. if ((memberTable[pos].objtype == SUB_ENTITY) &&
  3318. (name == memberTable[pos].name)) {
  3319. t->outputError("'%s' is a built-in entity member (variables cannot override built-in members)", name.c_str());
  3320. // RESOLUTION: define variable anyways
  3321. }
  3322. }
  3323. // @TODO: error if already defined at this scope
  3324. list<Variable>& found = addVariableMap(vars, name, var.name);
  3325. // Globals go to the "back" of the line (overridden by any existing locals)
  3326. if (var.scope < 0) {
  3327. found.push_front(var);
  3328. return found.front();
  3329. }
  3330. // Everything else overrides any prior variable of the same name
  3331. found.push_back(var);
  3332. return found.back();
  3333. }
  3334. void Compiler::generateBlank(DataType& type) { start_func
  3335. if (type.flags & (DATA_ARRAY | DATA_HASH))
  3336. postCmdII((type.flags & DATA_ARRAY) ? OP_CREATEa : OP_CREATEh,
  3337. type.baseType == DATA_VAR ? DATA_INT : type.baseType,
  3338. (type.baseType == DATA_ENTITY || type.baseType == DATA_OBJECT) ? type.subType : 0);
  3339. else if (type.baseType == DATA_FLOAT)
  3340. postCmdF(OP_PUSHf, 0.0);
  3341. else if (type.baseType == DATA_STR)
  3342. postCmdS(OP_PUSHs, defineString(blankString));
  3343. else if (type.baseType == DATA_ENTITY)
  3344. postCmd(OP_CREATEe);
  3345. else if (type.baseType == DATA_OBJECT)
  3346. postCmd(OP_CREATEo);
  3347. else {
  3348. compileAssert((type.baseType == DATA_VAR) || (type.baseType == DATA_INT));
  3349. // (default for variants is integer 0)
  3350. postCmdI(OP_PUSH, 0);
  3351. }
  3352. }
  3353. void Compiler::defineString(Operand& o) { start_func
  3354. compileAssert(o.mode == OM_STR);
  3355. if (o.ref.strLiteral) {
  3356. o.data.i = defineString(*o.ref.strLiteral);
  3357. delete o.ref.strLiteral;
  3358. o.ref.strLiteral = NULL;
  3359. }
  3360. }
  3361. int Compiler::defineString(const string& str) { start_func
  3362. // Existing element?
  3363. StringMap::iterator found = stringMap.find(str.c_str());
  3364. if (found != stringMap.end()) {
  3365. // Use existing string
  3366. return (*found).second;
  3367. }
  3368. // New string will go at end
  3369. int offset = strings.code.size();
  3370. // Translating a string to 32-bit ints in this manner (and untranslating
  3371. // by using a char* ptr later) should be platform-neutral.
  3372. // Turn into an array of 32-bit ints; includes a byte for terminating NUL
  3373. int length = (str.size() + sizeof(Uint32)) / sizeof(Uint32);
  3374. Uint32* uiCopy = new Uint32[length];
  3375. memcpy(uiCopy, str.c_str(), str.size() + 1);
  3376. // Push onto strings
  3377. strings.code.reserve(offset + length);
  3378. for (int pos = 0; pos < length; ++pos)
  3379. strings.code.push_back(uiCopy[pos]);
  3380. // Remember offset for reuse
  3381. stringMap[newCpCopy(str.c_str())] = offset;
  3382. delete[] uiCopy;
  3383. return offset;
  3384. }
  3385. void Compiler::prepLinker(const Variable* var, int toData) { start_func
  3386. compileAssert(var);
  3387. compileAssert(var->scope < 0);
  3388. LinkEntry prepLink;
  3389. prepLink.type = toData ? LinkEntry::LINK_GLOBAL : LinkEntry::LINK_GLOBALVAR;
  3390. prepLink.offset = ws->code.size();
  3391. prepLink.scope = blankString;
  3392. prepLink.name = var->name;
  3393. prepLink.wart = dataTypeToWart(var->datatype);
  3394. ws->links.push_back(prepLink);
  3395. }
  3396. void Compiler::prepLinker(const string& funcName) { start_func
  3397. LinkEntry prepLink;
  3398. prepLink.type = LinkEntry::LINK_FUNCTION;
  3399. prepLink.offset = ws->code.size() + 1;
  3400. prepLink.scope = blankString;
  3401. prepLink.name = funcName;
  3402. prepLink.wart = blankString;
  3403. ws->links.push_back(prepLink);
  3404. }
  3405. void Compiler::prepLinker(int isContinue, const string& loopName) { start_func
  3406. LinkEntry prepLink;
  3407. prepLink.type = isContinue ? LinkEntry::LINK_LOOP_CONTINUE : LinkEntry::LINK_LOOP_END;
  3408. prepLink.offset = ws->code.size() + 1;
  3409. prepLink.scope = blankString;
  3410. prepLink.name = loopName;
  3411. prepLink.wart = blankString;
  3412. ws->links.push_back(prepLink);
  3413. }
  3414. void Compiler::prepLinker() { start_func
  3415. LinkEntry prepLink;
  3416. prepLink.type = LinkEntry::LINK_STRING;
  3417. prepLink.offset = ws->code.size();
  3418. prepLink.scope = blankString;
  3419. prepLink.name = blankString;
  3420. prepLink.wart = blankString;
  3421. ws->links.push_back(prepLink);
  3422. }
  3423. int Compiler::postCmdRaw(Opcode opc, Operand* o1, Operand* o2, Operand* o3) { start_func
  3424. Operand* opers[3] = { o1, o2, o3 };
  3425. Uint8 oms[3] = { o1 ? o1->mode : OM_NONE,
  3426. o2 ? o2->mode : OM_NONE,
  3427. o3 ? o3->mode : OM_NONE };
  3428. // Must be OM_STR_CONST by now
  3429. compileAssert(oms[0] != OM_STR);
  3430. compileAssert(oms[1] != OM_STR);
  3431. compileAssert(oms[2] != OM_STR);
  3432. #ifdef COMPILEASSERT
  3433. // Checks for valid opcode/mode combinations
  3434. checkOpcode(opc, oms[0], oms[1], oms[2]);
  3435. #endif
  3436. // Create opcode/mode combination
  3437. Uint32 opcFinal = (((((oms[2] << 8) | oms[1]) << 8) | oms[0]) << 8) | opc;
  3438. // Always store opcode
  3439. ws->code.push_back(opcFinal);
  3440. int used = 1;
  3441. // Operands
  3442. for (int pos = 0; pos < 3; ++pos) {
  3443. // (skip empty operands)
  3444. if (oms[pos]) {
  3445. compileAssert(opers[pos]);
  3446. // @TODO: array/hash conversion/copy should add type+subtype! (see convertToArray)
  3447. // Adding subtype- any conversion or copy to entity or object (verify not literal)
  3448. // OR all/all_other literals
  3449. if ((((oms[pos] & OM_BASETYPE) == OM_ENTITY || (oms[pos] & OM_BASETYPE) == OM_OBJECT) &&
  3450. (oms[pos] & OM_FLAGS) != OM_NO_CONVERT && (oms[pos] & OM_FLAGS) != OM_INDIRECT &&
  3451. (oms[pos] & OM_BASETYPE) != oms[pos])
  3452. || oms[pos] == OM_ALL || oms[pos] == OM_ALL_OTHER) {
  3453. ws->code.push_back(opers[pos]->subType);
  3454. ++used;
  3455. }
  3456. // Special literals, pop- nothing more
  3457. if (((oms[pos] >= OM_ALL) && (oms[pos] < OM_POINTER)) || OM_IS_POP(oms[pos]))
  3458. continue;
  3459. // Linking globals
  3460. if (OM_IS_GLOBAL(oms[pos])) {
  3461. prepLinker(opers[pos]->ref.global);
  3462. assert(opers[pos]->data.p == NULL);
  3463. }
  3464. // Linking static strings
  3465. // After linking, this will be-
  3466. // String offset within strings
  3467. // +Offset of string section
  3468. // -Offset of operand itself
  3469. if (oms[pos] == OM_STR_CONST) {
  3470. prepLinker();
  3471. ws->code.push_back(opers[pos]->data.i);
  3472. ++used;
  3473. }
  3474. // Pushing float
  3475. else if (oms[pos] == OM_FLOAT) {
  3476. Uint32 buffer[bcFloatSize];
  3477. memset(buffer, 0, sizeof(buffer[bcFloatSize]));
  3478. *(BCfloat*)(&buffer) = opers[pos]->data.f;
  3479. for (int pos = 0; pos < bcFloatSize; ++pos)
  3480. ws->code.push_back(buffer[pos]);
  3481. used += bcFloatSize;
  3482. }
  3483. // Pushing pointer
  3484. else if (OM_IS_POINTER(oms[pos]) || OM_IS_GLOBAL(oms[pos])) {
  3485. Uint32 buffer[vPtrSize];
  3486. memset(buffer, 0, sizeof(buffer[vPtrSize]));
  3487. *(void**)(&buffer) = opers[pos]->data.p;
  3488. for (int pos = 0; pos < bcFloatSize; ++pos)
  3489. ws->code.push_back(buffer[pos]);
  3490. used += vPtrSize;
  3491. }
  3492. /* @TODO: may optimize things to have stack refs be + 1
  3493. // Pushing stack
  3494. else if (OM_IS_STACK(oms[pos])) {
  3495. ws->code.push_back(opers[pos]->data.i + 1);
  3496. ++used;
  3497. }
  3498. */
  3499. // Pushing int
  3500. else {
  3501. ws->code.push_back(opers[pos]->data.i);
  3502. ++used;
  3503. }
  3504. }
  3505. }
  3506. // Display?
  3507. if (debugLevel() & DEBUG_BYTECODE) {
  3508. int start = ws->code.size() - used;
  3509. Uint32* temp = new Uint32[used];
  3510. for (int copy = 0; copy < used; ++copy) {
  3511. temp[copy] = ws->code[start + copy];
  3512. }
  3513. string line;
  3514. debugBytecode(line, temp);
  3515. debugWrite("%s", line.c_str());
  3516. delete[] temp;
  3517. }
  3518. return used;
  3519. }
  3520. void Compiler::postCmd(Opcode opc) { start_func
  3521. postCmdRaw(opc);
  3522. }
  3523. void Compiler::postCmdI(Opcode opc, Sint32 int1) { start_func
  3524. Operand o;
  3525. createInt(o, int1);
  3526. postCmdRaw(opc, &o);
  3527. }
  3528. void Compiler::postCmdII(Opcode opc, Sint32 int1, Sint32 int2) { start_func
  3529. Operand o1;
  3530. Operand o2;
  3531. createInt(o1, int1);
  3532. createInt(o2, int2);
  3533. postCmdRaw(opc, &o1, &o2);
  3534. }
  3535. void Compiler::postCmdF(Opcode opc, BCfloat float1) { start_func
  3536. Operand o;
  3537. createFloat(o, float1);
  3538. postCmdRaw(opc, &o);
  3539. }
  3540. void Compiler::postCmdS(Opcode opc, Sint32 str1) { start_func
  3541. Operand o;
  3542. createInt(o, str1);
  3543. o.mode = OM_STR_CONST;
  3544. postCmdRaw(opc, &o);
  3545. }
  3546. void Compiler::postCmdPush(Operand& oper, int refOK) { start_func
  3547. compileAssert(oper.mode);
  3548. compileAssert(!OM_IS_COPY(oper.mode));
  3549. compileAssert(!OM_IS_CONST(oper.mode));
  3550. compileAssert(!OM_IS_POP(oper.mode));
  3551. compileAssert(!OM_IS_POINTER(oper.mode));
  3552. Opcode opc = OP_PUSHo;
  3553. // TODO: ensure pushv does ALL ref/deref needed, conversions, and copying new array/hash
  3554. if (OM_IS_ENTRY(oper.mode)) opc = OP_PUSHv;
  3555. else if (OM_IS_ARRAY(oper.mode)) opc = OP_PUSHa;
  3556. else if (OM_IS_HASH(oper.mode)) opc = OP_PUSHh;
  3557. else if (OM_IS_INT(oper.mode)) opc = OP_PUSH;
  3558. else if (OM_IS_FLOAT(oper.mode)) opc = OP_PUSHf;
  3559. else if (OM_IS_STR(oper.mode)) opc = OP_PUSHs;
  3560. if (!OM_IS_LITERAL(oper.mode)) {
  3561. // Source already has conversion flag set if necessary, but it needs to
  3562. // be a 'copy' flag
  3563. if (OM_IS_CONVERT(oper.mode))
  3564. oper.mode = (OperMode)(oper.mode | OM_COPY);
  3565. // Force a copy if non-unique array/hash and no refs allowed
  3566. // (known flag precludes this from being an indirect, too)
  3567. else if (!refOK && OM_IS_KNOWN(oper.mode) && (OM_IS_ARRAY(oper.mode) || OM_IS_HASH(oper.mode)) && !O_IS_COPY(oper) && (opc != OP_PUSHv))
  3568. oper.mode = (OperMode)((oper.mode & ~OM_FLAGS) | OM_COPY);
  3569. }
  3570. // Source also needs to be const
  3571. if (OM_IS_STR(oper.mode))
  3572. oper.mode = (OperMode)(OM_STR_CONST | (oper.mode & ~OM_BASETYPE));
  3573. postCmdRaw(opc, &oper);
  3574. }
  3575. int Compiler::postCmdIf(int ifTrue, Sint32 offset, Operand& o, int& alwaysJumps, int& neverJumps) { start_func
  3576. compileAssert(o.mode);
  3577. compileAssert(!OM_IS_COPY(o.mode));
  3578. compileAssert(!OM_IS_CONST(o.mode));
  3579. compileAssert(!OM_IS_POP(o.mode));
  3580. compileAssert(!OM_IS_POINTER(o.mode));
  3581. int curPos = ws->code.size();
  3582. int result = -1;
  3583. int alwaysTrue = 0;
  3584. // If item is literal, always true or false
  3585. if (OM_IS_LITERAL(o.mode)) {
  3586. if (OM_IS_INT(o.mode)) alwaysTrue = o.data.i;
  3587. else if (OM_IS_FLOAT(o.mode)) alwaysTrue = (o.data.f != 0.0);
  3588. else if (OM_IS_STR(o.mode)) {
  3589. compileAssert(o.ref.strLiteral);
  3590. alwaysTrue = (*o.ref.strLiteral != blankString);
  3591. }
  3592. // 'nothing' is always false
  3593. else if (o.mode == OM_NOTHING) alwaysTrue = 0;
  3594. // All other 'literals' are true
  3595. else alwaysTrue = 1;
  3596. if (alwaysTrue) {
  3597. t->outputWarning("Condition is always true");
  3598. }
  3599. // If always false...
  3600. else {
  3601. t->outputWarning("Condition is always false");
  3602. // Reverse condition
  3603. alwaysTrue = 1;
  3604. ifTrue = !ifTrue;
  3605. }
  3606. }
  3607. alwaysJumps = 0;
  3608. neverJumps = 0;
  3609. if (alwaysTrue) {
  3610. destroyOperand(o);
  3611. if (ifTrue) {
  3612. alwaysJumps = 1;
  3613. // 2 = adjusted by size of opcode we're about to add
  3614. if (offset < 0) offset -= ws->code.size() - curPos + 2;
  3615. result = ws->code.size() + 1; // 1 = position of offset operand
  3616. postCmdI(OP_JUMP, offset);
  3617. }
  3618. else {
  3619. neverJumps = 1;
  3620. }
  3621. return result;
  3622. }
  3623. // Default to object, as that covers a lot of types
  3624. Opcode opc = ifTrue ? OP_IFTRUEo : OP_IFFALSEo;
  3625. if (OM_IS_STR(o.mode)) opc = ifTrue ? OP_IFTRUEs : OP_IFFALSEs;
  3626. else if (OM_IS_FLOAT(o.mode)) opc = ifTrue ? OP_IFTRUEf : OP_IFFALSEf;
  3627. else if (OM_IS_INT(o.mode)) opc = ifTrue ? OP_IFTRUE : OP_IFFALSE;
  3628. else if (OM_IS_ARRAY(o.mode)) opc = ifTrue ? OP_IFTRUEa : OP_IFFALSEa;
  3629. else if (OM_IS_HASH(o.mode)) opc = ifTrue ? OP_IFTRUEh : OP_IFFALSEh;
  3630. else if (OM_IS_ENTRY(o.mode)) opc = ifTrue ? OP_IFTRUEv : OP_IFFALSEv;
  3631. // Source already has conversion flag set if necessary, but it needs to
  3632. // be a 'copy' flag; we already know it's not a literal.
  3633. if (OM_IS_CONVERT(o.mode))
  3634. o.mode = (OperMode)(o.mode | OM_COPY);
  3635. // Source also needs to be const; define string literals
  3636. if (OM_IS_STR(o.mode))
  3637. o.mode = (OperMode)(OM_STR_CONST | (o.mode & ~OM_BASETYPE));
  3638. // Finally, source could be a pop; temporaries should never be variants
  3639. if (O_IS_TEMP(o)) {
  3640. compileAssert(!OM_IS_ENTRY(o.mode));
  3641. compileAssert(o.data.i == 0);
  3642. o.mode = (OperMode)((o.mode & ~OM_LOCATION) | OM_POP);
  3643. }
  3644. // Post command
  3645. if (offset < 0) offset -= ws->code.size() - curPos;
  3646. Operand jump;
  3647. createInt(jump, offset);
  3648. int dist = postCmdRaw(opc, &o, &jump);
  3649. // We KNOW that the last operand, the jump, is 1 byte, so we can
  3650. // deduce the position of the jump
  3651. result = ws->code.size() - 1;
  3652. // We need to adjust the jump, if it was negative, to cover the
  3653. // size of the op.
  3654. if (offset < 0) ws->code[result] -= dist;
  3655. // (adjust stack depth if popped)
  3656. if (OM_IS_POP(o.mode))
  3657. --ws->stackDepth;
  3658. return result;
  3659. }