CE Expression.cpp 142 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Edit{
  5. /******************************************************************************/
  6. // TODO:
  7. // parse #pragma pack and setup Symbol::class_pack
  8. // call ctors/def_values for global vars and dtors at the end
  9. // a && b && c conditional execute support (add destructors to conditional destructor list)
  10. // a || b || c conditional execute support (add destructors to conditional destructor list)
  11. // a ? b : c conditional execute support (add destructors to conditional destructor list)
  12. // reuse stack size, when destroying locals, reuse their stack memory (use 'chunks' struct Chunk{Bool used; Int offset, length;}), only for release mode (so debug will keep variable values for preview)
  13. // test 'goto' for "can't jump to block after ctor/dtor var"
  14. // enum value calculation (into 'Symbol::raw_offset' ?)
  15. // support auto-cast for calculate "CChar *s=Str();"
  16. // TODO:
  17. // compile errors for parsing data types, read var funcs, etc.
  18. // do not allow custom operators that operate on basic types only
  19. // do not allow class static operators
  20. // do not allow default parameters for operators
  21. // () [] operators can be only class non-static operators
  22. // verify correct amount of parameters for operators (remember that class non-static require 1 less)
  23. // verify uniqueness of symbol names
  24. // pointer to reference is illegal
  25. // array of references are illegal
  26. // if one func param has default value specified, then all following params also must have a default value
  27. // do not allow 2 same bases for a class (allow if different in templates: "class Ext : Str, Str {}" BAD, "class Ext : Memc<Int>, Memc<Str> {}" GOOD)
  28. // do not allow virtual for global or class static funcs
  29. // TODO:
  30. // do following optimizations (add MODIF_ARITHMETIC to functions? to allow following optimizations also to classes):
  31. // "a+b" -> "a+=b" if 'a' is a temporary
  32. // "a+=1" -> "++a" if 'a' is a basic type (pointer only if size==1)
  33. // "a=b+c" -> don't create temporary "$temp=b+c" and store it "a=$temp" but already do "a=b+c" (only if 'a' and '$temp' are of the same type, and basic type? remember that operator+ uses $temp::ctor(b+c))
  34. // "x*0" -> if 'x' is basic type then set whole expr as known
  35. // skip "1*x", "x*1", "x/1", "0+x", "x+0", "x-0", "x<<0", "x>>0", .. (same for *= /= += -= <<= >>=) if 'x' is basic type (however keep */+- if operation changes type int->flt/dbl, flt->dbl)
  36. // set known for 'const' expressions of basic type
  37. // "a+-b" -> "a-b" if 'a' and 'b' are basic type
  38. // "!!x" -> "x" (only if 'x' is bool or result is used for 'if/for/while', and '!' is not overloaded operator)
  39. // "- - a" (not "--a"), "~~a" -> "a" if 'a' is basic type
  40. // "x++" "x--" if result is unused then replace with "++x" "--x"
  41. // "x*=2" -> "x<<=1" .. (watch out for negative values - only for unsigned ints?)
  42. // "x/=2" -> "x>>=1" .. (watch out for negative values - only for unsigned ints?)
  43. // "1 && x" -> "x", "0 || x" -> "x" (only if 'x' is bool or result is used for 'if/for/while')
  44. // TODO:
  45. // do not allow compiling when class belongs to one of its base classes
  46. // do not allow compiling when class belongs to one of class types of its member
  47. // error for const vars that don't have default value specified (ignore case when there is a default constructor, like "const Str S;")
  48. // error for references that don't have default value specified
  49. // do not allow modifying of values or calling non-const methods, or passing this to func/operator params of non const pointer/ref, for const methods "void func()const"
  50. // where to set src_template_i to -1 ?
  51. // mutable, explicit support
  52. // when detecting cast currently templates will always return ok/conv/ctor match, but the case of "func(TYPE a, TYPE b)" and "func(Image(), Str())" is ignored, when passing different types to the same template, so when assuming to test cast match, make local copy of the TYPE value/type, so all remaining parameters will have the same value/type
  53. // allocate class static vars in global heap, call ctors/dtors , (watch out for template classes <TYPE> class X {static TYPE obj;})
  54. // allocate func static vars in global heap, call ctors (on first func/space/block enter), dtors if initialized on app exit, (watch out for template functions <TYPE> void func() {static TYPE obj;})
  55. // do some global variable initialization order sorting (basing on dependencies)
  56. // initializing variables with default values (globals, statics, members), include arrays "type x[]={..};"
  57. // operator new delete
  58. // friend (classes, funcs, etc)
  59. // dynamic cast, rtti, virtual functions
  60. // pointers to class members and methods
  61. // pointers to non-static functions (as variables)
  62. /******************************************************************************/
  63. // CAST MATCH
  64. /******************************************************************************/
  65. static CAST_MATCH CastMatch(VAR_TYPE src, VAR_TYPE dest) // treat CHAR,ENUM as both signed/unsigned
  66. {
  67. if(src==dest && src!=VAR_ENUM && src!=VAR_NONE)return CAST_MAX;
  68. switch(dest)
  69. {
  70. case VAR_BOOL:
  71. if(src==VAR_BYTE || src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_CHAR8 || src==VAR_CHAR16 || src==VAR_FLT || src==VAR_DBL || src==VAR_ENUM)return CAST_CONV;
  72. break;
  73. case VAR_BYTE:
  74. if(src==VAR_BOOL || src==VAR_CHAR8)return CAST_CONV;
  75. if(src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_CHAR16 || src==VAR_FLT || src==VAR_DBL || src==VAR_ENUM)return CAST_CONV;
  76. break;
  77. case VAR_SBYTE:
  78. if(src==VAR_BOOL || src==VAR_CHAR8)return CAST_CONV;
  79. if(src==VAR_BYTE || src==VAR_SHORT || src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_CHAR16 || src==VAR_FLT || src==VAR_DBL || src==VAR_ENUM)return CAST_CONV;
  80. break;
  81. case VAR_SHORT:
  82. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_SBYTE || src==VAR_CHAR8 || src==VAR_CHAR16)return CAST_CONV;
  83. if(src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_FLT || src==VAR_DBL || src==VAR_ENUM)return CAST_CONV;
  84. break;
  85. case VAR_USHORT:
  86. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_CHAR8 || src==VAR_CHAR16)return CAST_CONV;
  87. if(src==VAR_SBYTE || src==VAR_SHORT || src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_FLT || src==VAR_DBL || src==VAR_ENUM)return CAST_CONV;
  88. break;
  89. case VAR_INT:
  90. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT || src==VAR_CHAR8 || src==VAR_CHAR16 || src==VAR_ENUM)return CAST_CONV;
  91. if(src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_FLT || src==VAR_DBL)return CAST_CONV;
  92. break;
  93. case VAR_UINT:
  94. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_USHORT || src==VAR_CHAR8 || src==VAR_CHAR16 || src==VAR_ENUM)return CAST_CONV;
  95. if(src==VAR_SBYTE || src==VAR_SHORT || src==VAR_INT || src==VAR_LONG || src==VAR_ULONG || src==VAR_FLT || src==VAR_DBL)return CAST_CONV;
  96. break;
  97. case VAR_LONG:
  98. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_CHAR8 || src==VAR_CHAR16 || src==VAR_ENUM)return CAST_CONV;
  99. if(src==VAR_ULONG || src==VAR_FLT || src==VAR_DBL)return CAST_CONV;
  100. break;
  101. case VAR_ULONG:
  102. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_USHORT || src==VAR_UINT || src==VAR_CHAR8 || src==VAR_CHAR16 || src==VAR_ENUM)return CAST_CONV;
  103. if(src==VAR_SBYTE || src==VAR_SHORT || src==VAR_INT || src==VAR_LONG || src==VAR_FLT || src==VAR_DBL)return CAST_CONV;
  104. break;
  105. case VAR_CHAR8:
  106. if(src==VAR_BYTE || src==VAR_SBYTE )return CAST_CONV;
  107. if(src==VAR_SHORT || src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_CHAR16)return CAST_CONV;
  108. break;
  109. case VAR_CHAR16:
  110. if(src==VAR_CHAR8 || src==VAR_BYTE || src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT)return CAST_CONV;
  111. if(src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG )return CAST_CONV;
  112. break;
  113. case VAR_FLT:
  114. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT)return CAST_CONV;
  115. if(src==VAR_INT || src==VAR_UINT || src==VAR_LONG || src==VAR_ULONG || src==VAR_DBL )return CAST_CONV;
  116. break;
  117. case VAR_DBL:
  118. if(src==VAR_BOOL || src==VAR_BYTE || src==VAR_SBYTE || src==VAR_SHORT || src==VAR_USHORT || src==VAR_INT || src==VAR_UINT || src==VAR_FLT)return CAST_CONV;
  119. if(src==VAR_LONG || src==VAR_ULONG)return CAST_CONV;
  120. break;
  121. }
  122. return CAST_NONE;
  123. }
  124. static CAST_MATCH CastMatchConst(CAST_MATCH cast)
  125. {
  126. switch(cast)
  127. {
  128. default : return cast;
  129. case CAST_CTOR: return CAST_CTOR_CONST;
  130. case CAST_CONV: return CAST_CONV_CONST;
  131. case CAST_MAX : return CAST_MAX_CONST ;
  132. }
  133. }
  134. /******************************************************************************/
  135. // EXPRESSION
  136. /******************************************************************************/
  137. static void ConvertPtrToUIntPtr(Symbol::Modif &symbol) {symbol.clear(true); symbol=TypeSymbol((PtrSize==4) ? VAR_UINT : VAR_ULONG);} // treat pointers as unsigned's - this is needed for comparing pointers
  138. void Expr::calculateKnown(Expr &op, Expr &a, Compiler &compiler)
  139. {
  140. if(known() && symbol)
  141. {
  142. if(op=='!')setBorrowed(a.asBool(compiler) ? u"false" : u"true");else
  143. if(op=='~')switch(symbol->var_type)
  144. {
  145. case VAR_INT : setCustom(S + ~a.asInt (compiler)); break;
  146. case VAR_UINT : setCustom(S + ~a.asUInt (compiler)); break;
  147. case VAR_LONG : setCustom(S + ~a.asLong (compiler)); break;
  148. case VAR_ULONG: setCustom(S + ~a.asULong(compiler)); break;
  149. }else
  150. if(op=='-')switch(symbol->var_type)
  151. {
  152. case VAR_INT : setCustom(S + -a.asInt (compiler)); break;
  153. case VAR_LONG: setCustom(S + -a.asLong(compiler)); break;
  154. case VAR_FLT : setCustom(S + -a.asDbl (compiler)); break; // use Dbl to increase precision
  155. case VAR_DBL : setCustom(S + -a.asDbl (compiler)); break;
  156. }else
  157. compiler.msgs.New().error("Uknown operator", op.origin);
  158. }
  159. }
  160. void Expr::calculateKnown(Expr &op, Expr &a, Expr &b, Compiler &compiler)
  161. {
  162. if(known() && symbol && a.symbol && b.symbol)
  163. {
  164. if(op=="&&")setBorrowed(((a.known() && !a.asBool(compiler) || b.known() && !b.asBool(compiler)) ? false : (a.asBool(compiler) && b.asBool(compiler))) ? u"true" : u"false");else // if at least one is false then the result is false
  165. if(op=="||")setBorrowed(((a.known() && a.asBool(compiler) || b.known() && b.asBool(compiler)) ? true : (a.asBool(compiler) || b.asBool(compiler))) ? u"true" : u"false");else // if at least one is true then the result is true
  166. if(op=="^^")setBorrowed((a.asBool(compiler) != b.asBool(compiler)) ? u"true" : u"false");else
  167. if(op=="==")
  168. {
  169. Bool r=false;
  170. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )r=(a.asDbl (compiler) == b.asDbl (compiler));else
  171. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)r=(a.asULong(compiler) == b.asULong(compiler));else r=(a.asULong(compiler) == b.asLong(compiler));}else
  172. {if(b.symbol->var_type==VAR_ULONG)r=(a.asLong (compiler) == b.asULong(compiler));else r=(a.asLong (compiler) == b.asLong(compiler));}
  173. setBorrowed(r ? u"true" : u"false");
  174. }else
  175. if(op=="!=")
  176. {
  177. Bool r=false;
  178. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )r=(a.asDbl (compiler) != b.asDbl (compiler));else
  179. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)r=(a.asULong(compiler) != b.asULong(compiler));else r=(a.asULong(compiler) != b.asLong(compiler));}else
  180. {if(b.symbol->var_type==VAR_ULONG)r=(a.asLong (compiler) != b.asULong(compiler));else r=(a.asLong (compiler) != b.asLong(compiler));}
  181. setBorrowed(r ? u"true" : u"false");
  182. }else
  183. if(op=="<=")
  184. {
  185. Bool r=false;
  186. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )r=(a.asDbl (compiler) <= b.asDbl (compiler));else
  187. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)r=(a.asULong(compiler) <= b.asULong(compiler));else r=(a.asULong(compiler) <= b.asLong(compiler));}else
  188. {if(b.symbol->var_type==VAR_ULONG)r=(a.asLong (compiler) <= b.asULong(compiler));else r=(a.asLong (compiler) <= b.asLong(compiler));}
  189. setBorrowed(r ? u"true" : u"false");
  190. }else
  191. if(op==">=")
  192. {
  193. Bool r=false;
  194. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )r=(a.asDbl (compiler) >= b.asDbl (compiler));else
  195. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)r=(a.asULong(compiler) >= b.asULong(compiler));else r=(a.asULong(compiler) >= b.asLong(compiler));}else
  196. {if(b.symbol->var_type==VAR_ULONG)r=(a.asLong (compiler) >= b.asULong(compiler));else r=(a.asLong (compiler) >= b.asLong(compiler));}
  197. setBorrowed(r ? u"true" : u"false");
  198. }else
  199. if(op=='<')
  200. {
  201. Bool r=false;
  202. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )r=(a.asDbl (compiler) < b.asDbl (compiler));else
  203. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)r=(a.asULong(compiler) < b.asULong(compiler));else r=(a.asULong(compiler) < b.asLong(compiler));}else
  204. {if(b.symbol->var_type==VAR_ULONG)r=(a.asLong (compiler) < b.asULong(compiler));else r=(a.asLong (compiler) < b.asLong(compiler));}
  205. setBorrowed(r ? u"true" : u"false");
  206. }else
  207. if(op=='>')
  208. {
  209. Bool r=false;
  210. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )r=(a.asDbl (compiler) > b.asDbl (compiler));else
  211. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)r=(a.asULong(compiler) > b.asULong(compiler));else r=(a.asULong(compiler) > b.asLong(compiler));}else
  212. {if(b.symbol->var_type==VAR_ULONG)r=(a.asLong (compiler) > b.asULong(compiler));else r=(a.asLong (compiler) > b.asLong(compiler));}
  213. setBorrowed(r ? u"true" : u"false");
  214. }else
  215. if(op=='*')
  216. {
  217. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )setCustom(S+(a.asDbl (compiler) * b.asDbl (compiler)));else
  218. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) * b.asULong(compiler)));else setCustom(S+(a.asULong(compiler) * b.asLong(compiler)));}else
  219. {if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asLong (compiler) * b.asULong(compiler)));else setCustom(S+(a.asLong (compiler) * b.asLong(compiler)));}
  220. }else
  221. if(op=='/')
  222. {
  223. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )setCustom(S+(a.asDbl(compiler) / b.asDbl(compiler)));else
  224. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG){ULong v=b.asULong(compiler); if(v)setCustom(S+(a.asULong(compiler) / v));else compiler.msgs.New().error("Division by zero", b.origin);}else {Long v=b.asLong(compiler); if(v)setCustom(S+(a.asULong(compiler) / v));else compiler.msgs.New().error("Division by zero", b.origin);}}else
  225. {if(b.symbol->var_type==VAR_ULONG){ULong v=b.asULong(compiler); if(v)setCustom(S+(a.asLong (compiler) / v));else compiler.msgs.New().error("Division by zero", b.origin);}else {Long v=b.asLong(compiler); if(v)setCustom(S+(a.asLong (compiler) / v));else compiler.msgs.New().error("Division by zero", b.origin);}}
  226. }else
  227. if(op=='%')
  228. {
  229. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG){ULong v=b.asULong(compiler); if(v)setCustom(S+(a.asULong(compiler) % v));else compiler.msgs.New().error("Modulo by zero", b.origin);}else {Long v=b.asLong(compiler); if(v)setCustom(S+(a.asULong(compiler) % v));else compiler.msgs.New().error("Modulo by zero", b.origin);}}else
  230. {if(b.symbol->var_type==VAR_ULONG){ULong v=b.asULong(compiler); if(v)setCustom(S+(a.asLong (compiler) % v));else compiler.msgs.New().error("Modulo by zero", b.origin);}else {Long v=b.asLong(compiler); if(v)setCustom(S+(a.asLong (compiler) % v));else compiler.msgs.New().error("Modulo by zero", b.origin);}}
  231. }else
  232. if(op=='+')
  233. {
  234. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )setCustom(S+(a.asDbl (compiler) + b.asDbl (compiler)));else
  235. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) + b.asULong(compiler)));else setCustom(S+(a.asULong(compiler) + b.asLong(compiler)));}else
  236. {if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asLong (compiler) + b.asULong(compiler)));else setCustom(S+(a.asLong (compiler) + b.asLong(compiler)));}
  237. }else
  238. if(op=='-')
  239. {
  240. if(RealType(a.symbol->var_type) || RealType(b.symbol->var_type) )setCustom(S+(a.asDbl (compiler) - b.asDbl (compiler)));else
  241. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) - b.asULong(compiler)));else setCustom(S+(a.asULong(compiler) - b.asLong(compiler)));}else
  242. {if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asLong (compiler) - b.asULong(compiler)));else setCustom(S+(a.asLong (compiler) - b.asLong(compiler)));}
  243. }else
  244. if(op=="<<")
  245. {
  246. if(a.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) << b.asInt(compiler)));
  247. else setCustom(S+(a.asLong (compiler) << b.asInt(compiler)));
  248. }else
  249. if(op==">>")
  250. {
  251. if(a.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) >> b.asInt(compiler)));
  252. else setCustom(S+(a.asLong (compiler) >> b.asInt(compiler)));
  253. }else
  254. if(op=='&')
  255. {
  256. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) & b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asULong(compiler) & b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asULong(compiler) & b.asUInt(compiler)));else setCustom(S+(a.asULong(compiler) & b.asInt(compiler)));}else
  257. if(a.symbol->var_type==VAR_LONG ){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asLong (compiler) & b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asLong (compiler) & b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asLong (compiler) & b.asUInt(compiler)));else setCustom(S+(a.asLong (compiler) & b.asInt(compiler)));}else
  258. if(a.symbol->var_type==VAR_UINT ){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asUInt (compiler) & b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asUInt (compiler) & b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asUInt (compiler) & b.asUInt(compiler)));else setCustom(S+(a.asUInt (compiler) & b.asInt(compiler)));}else
  259. {if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asInt (compiler) & b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asInt (compiler) & b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asInt (compiler) & b.asUInt(compiler)));else setCustom(S+(a.asInt (compiler) & b.asInt(compiler)));}
  260. }else
  261. if(op=='^')
  262. {
  263. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) ^ b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asULong(compiler) ^ b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asULong(compiler) ^ b.asUInt(compiler)));else setCustom(S+(a.asULong(compiler) ^ b.asInt(compiler)));}else
  264. if(a.symbol->var_type==VAR_LONG ){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asLong (compiler) ^ b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asLong (compiler) ^ b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asLong (compiler) ^ b.asUInt(compiler)));else setCustom(S+(a.asLong (compiler) ^ b.asInt(compiler)));}else
  265. if(a.symbol->var_type==VAR_UINT ){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asUInt (compiler) ^ b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asUInt (compiler) ^ b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asUInt (compiler) ^ b.asUInt(compiler)));else setCustom(S+(a.asUInt (compiler) ^ b.asInt(compiler)));}else
  266. {if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asInt (compiler) ^ b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asInt (compiler) ^ b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asInt (compiler) ^ b.asUInt(compiler)));else setCustom(S+(a.asInt (compiler) ^ b.asInt(compiler)));}
  267. }else
  268. if(op=='|')
  269. {
  270. if(a.symbol->var_type==VAR_ULONG){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asULong(compiler) | b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asULong(compiler) | b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asULong(compiler) | b.asUInt(compiler)));else setCustom(S+(a.asULong(compiler) | b.asInt(compiler)));}else
  271. if(a.symbol->var_type==VAR_LONG ){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asLong (compiler) | b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asLong (compiler) | b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asLong (compiler) | b.asUInt(compiler)));else setCustom(S+(a.asLong (compiler) | b.asInt(compiler)));}else
  272. if(a.symbol->var_type==VAR_UINT ){if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asUInt (compiler) | b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asUInt (compiler) | b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asUInt (compiler) | b.asUInt(compiler)));else setCustom(S+(a.asUInt (compiler) | b.asInt(compiler)));}else
  273. {if(b.symbol->var_type==VAR_ULONG)setCustom(S+(a.asInt (compiler) | b.asULong(compiler)));else if(b.symbol->var_type==VAR_LONG)setCustom(S+(a.asInt (compiler) | b.asLong(compiler)));else if(b.symbol->var_type==VAR_UINT)setCustom(S+(a.asInt (compiler) | b.asUInt(compiler)));else setCustom(S+(a.asInt (compiler) | b.asInt(compiler)));}
  274. }else
  275. if(op=='=')
  276. {
  277. if(a.symbol.isPtr()){if(b=="null")setBorrowed(u"null");else setCustom(S+b.asULong(compiler));}else
  278. if(RealType(a.symbol->var_type) )setCustom(S+b.asDbl (compiler));else
  279. if(a.symbol->var_type==VAR_ULONG)setCustom(S+b.asULong(compiler));else
  280. setCustom(S+b.asLong (compiler));
  281. }else
  282. /*if(op=="*=" || op=="/=" || op=="%=" || op=="+=" || op=="-=" || op=="<<=" || op==">>=" || op=="&=" || op=="|=" || op=="^=")
  283. {
  284. }else*/
  285. compiler.msgs.New().error("Uknown operator", op.origin);
  286. }
  287. }
  288. CAST_MATCH Expr::calculate(Compiler &compiler)
  289. {
  290. if(func.elms()==1)
  291. {
  292. Expr &func=T.func[0];
  293. origin =func.origin;
  294. final |=func.final;
  295. instance=true; // functions/operators/constructors always return an instance
  296. // check for built-in operators functions
  297. if(func=="sizeof")
  298. {
  299. setBasic(VAR_INT);
  300. if(compiler.strict && func.params.elms()!=1){compiler.msgs.New().error(S+"Invalid number of parameters to '"+func+'\'', origin); return CAST_NONE;}
  301. if(func.params.elms()>=1){Expr &a=func.params[0]; mem.setKnown(); setCustom(S+a.symbol.rawSize(false));}
  302. return CAST_MAX;
  303. }else
  304. if(func=="typeid")
  305. {
  306. setPtr(); return CAST_MAX;
  307. }else
  308. if(func=="dynamic_cast" || func=="static_cast" || func=="const_cast" || func=="reinterpret_cast")
  309. {
  310. if(compiler.strict)
  311. {
  312. if(func.symbol.templates.elms()!=1){compiler.msgs.New().error(S+"Invalid number of template parameters to '"+func+'\'', origin); return CAST_NONE;}
  313. if(func.params. elms()!=1){compiler.msgs.New().error(S+"Invalid number of parameters to '" +func+'\'', origin); return CAST_NONE;}
  314. Expr &src =func.params[0];
  315. Symbol::Modif &dest=func.symbol.templates[0]; if(!dest){compiler.msgs.New().error(S+"Unknown template parameter", origin); return CAST_NONE;}
  316. if(func=="dynamic_cast")
  317. {
  318. if(dest.ptr_level==1 && !(dest.modifiers&Symbol::MODIF_REF) && !dest.array_dims.elms() // C++ allows 'dynamic_cast' only when target is TYPE* or TYPE&
  319. || dest.ptr_level==0 && (dest.modifiers&Symbol::MODIF_REF) && !dest.array_dims.elms())
  320. {
  321. if(src.symbol.ptr_level==dest.ptr_level && !src.symbol.array_dims.elms())
  322. {
  323. temporary=(dest.ptr_level ? true : src.temporary); symbol=dest; if(dest.ptr_level)symbol.setConst(); return CAST_MAX; // yes it is a temporary - C++ compiling failed on "struct A{virtual ~A(){}}; struct B:A{virtual ~B(){}}; A *a=null; &CAST(B,a);"
  324. }
  325. compiler.msgs.New().error(S+"Can't perform 'dynamic_cast' from: "+src.symbol.modifName(true, true, false)+", to: "+dest.modifName(true, true, false), origin); return CAST_NONE;
  326. }
  327. compiler.msgs.New().error(S+"Target for 'dynamic_cast' must be a pointer or a reference", origin); return CAST_NONE;
  328. }else
  329. {
  330. temporary=true; symbol=dest; symbol.setConst(); return CAST_MAX;
  331. }
  332. }else
  333. {
  334. if(func.symbol.templates.elms()>=1) // set 'dest'
  335. {
  336. Symbol::Modif &dest=func.symbol.templates[0];
  337. if(dest){symbol=dest; return CAST_MAX;}
  338. }
  339. if(func.params.elms()>=1) // set 'src'
  340. {
  341. Expr &src=func.params[0];
  342. symbol=src.symbol; return CAST_MAX;
  343. }
  344. return CAST_NONE;
  345. }
  346. }else
  347. if(func._operator && func!="()") // there is no built-in "operator()"
  348. {
  349. if(func.params.elms()==1) // unary [] *x, &x, !x, ~x, +x, -x, ++x, --x, x++, x--
  350. {
  351. if(func=="[]") // parent[a], C++ supports only non-static [] operators
  352. {
  353. Expr &a=func.params[0];
  354. if(func.parent.elms()!=1){compiler.msgs.New().error("Invalid object for the [] operator", origin); return CAST_NONE;}
  355. if(compiler.strict)if(!a.symbol.isObj() || !a.symbol || !OffsetType(a.symbol->var_type)){compiler.msgs.New().error("Invalid index for the [] operator", a.origin); return CAST_NONE;}
  356. Expr &parent=func.parent[0];
  357. if(!parent.symbol.isObj())
  358. {
  359. if(!parent.indirection(compiler))return CAST_NONE; // do "TYPE a[]; *a;"
  360. temporary=parent.temporary; symbol=parent.symbol;
  361. if(a.known())
  362. {
  363. memFrom(parent.mem, compiler);
  364. memOffset(a.asLong(compiler)*parent.symbol.rawSize(false));
  365. func.func_call=GetIgnoreCall();
  366. }else
  367. {
  368. symbol.modifiers|=Symbol::MODIF_REF;
  369. memNew(false, compiler);
  370. func.func_call_mask=FC_PARENT|FC_RESULT;
  371. func.func_call =GetOffsetCall(a.symbol);
  372. if(!func.func_call){if(!compiler.quiet)compiler.msgs.New().error("No function/operator found able to process command", origin); return CAST_NONE;} // if didn't found the function then it means this call is impossible
  373. // create extra param specifying size of the object (do this after all codes accessing 'a', because this will change memory address of 'a')
  374. Expr &raw_size=func.params.New(); raw_size.setBasic(VAR_INT); raw_size.mem.setKnown(); raw_size.setCustom(S+parent.symbol.rawSize(false));
  375. }
  376. return CAST_MAX;
  377. }else
  378. if(parent.basicType()){compiler.msgs.New().error("Invalid object for the [] operator", origin); return CAST_NONE;}
  379. }else
  380. if(func.params[0].basicType())
  381. {
  382. indirection_address_of:
  383. Expr &a=func.params[0];
  384. if(func=='*') // verified Obj, Ptr, Array
  385. {
  386. if(a.symbol.isObj() && compiler.strict){compiler.msgs.New().error("Invalid * operator", origin); return CAST_NONE;} // in C++ "int a[2]; *a;" is correct!
  387. temporary=false; symbol=a.symbol; symbol.setConst(false); // remove const from pointer, 'temporary' IS false because this "int a[1]; &(*a);" compiles on C++
  388. if(a.symbol.isArray())
  389. {
  390. if(symbol.array_dims.elms())symbol.array_dims.removeLast();else if(symbol.ptr_level>0)symbol.ptr_level--;
  391. memFrom(a.mem, compiler);
  392. func.func_call=GetIgnoreCall();
  393. }else // use REF for arrays too ? (consider REF array and non-REF array)
  394. {
  395. if(a.func.elms()) // "*(&x)" -> "x"
  396. {
  397. Expr &a_func=a.func[0];
  398. if( a_func.func_call==GetAddressOfCall() && a_func.params.elms()==1)
  399. {
  400. Expr temp; Swap(temp, a_func.params[0]); Swap(temp, T); return CAST_MAX;
  401. }
  402. }
  403. FlagEnable(symbol.modifiers, Symbol::MODIF_REF); // treat this expression as reference (because this was a pointer, and we still operate on Ptr address)
  404. if(symbol.array_dims.elms())symbol.array_dims.removeLast();else if(symbol.ptr_level>0)symbol.ptr_level--;
  405. if(a.symbol.modifiers&Symbol::MODIF_REF) // if param was a reference too, then we need to create a temporary local variable
  406. {
  407. memNew(false, compiler);
  408. func.func_call_mask=FC_RESULT;
  409. func.func_call =GetIndirectionCall();
  410. }else // we have direct access to the param Ptr, so reuse it
  411. {
  412. memFrom(a.mem, compiler);
  413. if(parent.elms()!=0){compiler.msgs.New().error("Parent should be empty in indirection", origin); return CAST_NONE;}
  414. Swap(parent.New(), a); // move the original pointer to parent so func is not needed
  415. T.func.del(); // delete the function
  416. }
  417. }
  418. return CAST_MAX;
  419. }else
  420. if(func=='&') // verified Obj, Ptr, Array
  421. {
  422. if(a.temporary && a.basicType() && compiler.strict){compiler.msgs.New().error("Can't take address of a temporary", origin); return CAST_NONE;}
  423. if(a.func.elms()) // "&(*x)" -> "x"
  424. {
  425. Expr &a_func=a.func[0];
  426. if( a_func.func_call==GetIndirectionCall() && a_func.params.elms()==1)
  427. {
  428. Expr temp; Swap(temp, a_func.params[0]); Swap(temp, T); return CAST_MAX;
  429. }
  430. }
  431. temporary=true; symbol=a.symbol; // make the address a 'temporary'
  432. FlagDisable(symbol.modifiers, Symbol::MODIF_REF); // clear any reference modifier
  433. if(symbol.array_dims.elms())symbol.array_dims.add(Symbol::DIM_PTR);else symbol.ptr_level++;
  434. symbol.setConst(); // set const to the pointer
  435. memNew(false, compiler);
  436. func.func_call_mask=FC_RESULT;
  437. func.func_call =GetAddressOfCall();
  438. return CAST_MAX;
  439. }else
  440. if(func=='!') // verified Obj, Ptr, Array
  441. {
  442. setBasic(VAR_BOOL); memNew(a.known(), compiler); calculateKnown(func, a, compiler);
  443. Symbol::Modif src=a.symbol;
  444. if(src.isPtr())ConvertPtrToUIntPtr(src); // treat ptr as int
  445. if(src.isObj() && src)src=TypeSymbol(SameSizeType(src->var_type));
  446. func.func_call_mask=FC_RESULT;
  447. func.func_call =FindFuncCall(NativeOperatorName(func, symbol, src));
  448. return CAST_MAX;
  449. }else
  450. if(func=='~') // verified Obj, Ptr, Array
  451. {
  452. setBasic(ComplementResult(a.symbol ? a.symbol->varType() : VAR_NONE)); memNew(a.known(), compiler); calculateKnown(func, a, compiler);
  453. Symbol::Modif src=a.symbol; if(src.isObj() && src)src=TypeSymbol(SameSizeSignType(src->var_type));
  454. func.func_call_mask=FC_RESULT;
  455. func.func_call =FindFuncCall(NativeOperatorName(func, symbol, src));
  456. return CAST_MAX;
  457. }else
  458. if(func=='+') // verified Obj, Ptr, Array
  459. {
  460. Expr temp; // use temporary because 'a' belongs to 'T'
  461. Swap(temp, a);
  462. Swap(temp, T);
  463. return CAST_MAX;
  464. }else
  465. if(func=='-') // verified Obj, Ptr, Array
  466. {
  467. setBasic(NegativeResult(a.symbol ? a.symbol->varType() : VAR_NONE)); memNew(a.known(), compiler); calculateKnown(func, a, compiler);
  468. Symbol::Modif src=a.symbol; if(src.isObj() && src)src=TypeSymbol(SameSizeSignType(src->var_type));
  469. func.func_call_mask=FC_RESULT;
  470. func.func_call =FindFuncCall(NativeOperatorName(func, symbol, src));
  471. return CAST_MAX;
  472. }else
  473. if(func=="++" || func=="--") // verified Obj, Ptr, Array
  474. {
  475. if(a.symbol.isConst() && compiler.strict){compiler.msgs.New().error("Can't modify a const value", origin); return CAST_NONE;}
  476. if(func.l_to_r) // x++, x--
  477. {
  478. // TODO: add support
  479. temporary=true; symbol=a.symbol; symbol.setConst();
  480. if(compiler.strict){compiler.msgs.New().error("This operator is not yet supported, try using ++x or --x", origin); return CAST_NONE;}
  481. }else // ++x, --x
  482. {
  483. temporary=a.temporary; symbol=a.symbol; memFrom(a.mem, compiler); // use the same memory layout as 'a' because these operators do not return any other address
  484. Symbol::Modif src=a.symbol;
  485. func.func_call_mask=0;
  486. if(src.isPtr())
  487. {
  488. if(src.array_dims.elms())src.array_dims.removeLast();else src.ptr_level--; // remove the ptr
  489. Int size=src.rawSize(false); // get the size of under the pointer "byte *x" would be 1, while "byte **x" would be PtrSize
  490. if( size<=0 && compiler.strict){compiler.msgs.New().error("Unknown pointer size", origin); return CAST_NONE;}
  491. if( size> 0)switch(size)
  492. {
  493. case 1: ConvertPtrToUIntPtr(src); goto inc_dec_1;
  494. case 2:
  495. case 4:
  496. case 8: func.func_call=FindFuncCall(S+((func=="++") ? "inc ptr " : "dec ptr ")+size); break;
  497. default:
  498. {
  499. Expr &by=func.params.New(); by.origin=origin; by.setBasic(VAR_INT); by.mem.setKnown(); by.setCustom(S+size);
  500. func.func_call=FindFuncCall((func=="++") ? "inc ptr n" : "dec ptr n");
  501. }break;
  502. }
  503. }else
  504. {
  505. inc_dec_1:
  506. if(src.isObj() && src)src=TypeSymbol(SameSizeType(src->var_type));
  507. Symbol::Modif result; result=TypeSymbol(VAR_VOID);
  508. func.func_call=FindFuncCall(NativeOperatorName(func, result, src));
  509. }
  510. }
  511. return CAST_MAX;
  512. }else
  513. {
  514. compiler.msgs.New().error("Invalid unary operator", origin); return CAST_NONE;
  515. }
  516. }
  517. }else
  518. if(func.params.elms()==2) // binary * / % + - << >> < > <= >= == != === !!= & ^ | && ^^ || = *= /= %= += -= <<= >>= &= |= ^= ,
  519. {
  520. Expr &a=func.params[0], &b=func.params[1];
  521. // cast to conditionals
  522. if(func=="&&" || func=="||" || func=="^^")
  523. {
  524. if(!a.castToConditional() && compiler.strict){compiler.msgs.New().error("Can't cast to bool", a.origin); return CAST_NONE;}
  525. if(!b.castToConditional() && compiler.strict){compiler.msgs.New().error("Can't cast to bool", b.origin); return CAST_NONE;}
  526. }
  527. if(func==',') // a, b
  528. {
  529. temporary=b.temporary; symbol=b.symbol; memFrom(b.mem, compiler); set(b); return CAST_MAX;
  530. }else
  531. if(a.basicType() && b.basicType())
  532. {
  533. if(func=="==" || func=="===" || func=="!=" || func=="!!=" || func=='<' || func=='>' || func=="<=" || func==">=" || func=="&&" || func=="^^" || func=="||") // verified Obj, Ptr, Array
  534. {
  535. setBasic(VAR_BOOL);
  536. if(func=="&&")memNew(a.known() && !a.asBool(compiler) || b.known() && !b.asBool(compiler), compiler);else // if at least one is false
  537. if(func=="||")memNew(a.known() && a.asBool(compiler) || b.known() && b.asBool(compiler), compiler);else // if at least one is true
  538. memNew(a.known() && b.known() , compiler);
  539. calculateKnown(func, a, b, compiler);
  540. Symbol::Modif pa=a.symbol, pb=b.symbol;
  541. // adjust pointers
  542. if(func=="&&" || func=="^^" || func=="||")
  543. {
  544. if(pa.isPtr())ConvertPtrToUIntPtr(pa);
  545. if(pb.isPtr())ConvertPtrToUIntPtr(pb);
  546. }else // "==", "===", "!=", "!!=", "<", ">", "<=", ">="
  547. if(!pa.isObj() && !pb.isObj()) // ptr or array
  548. {
  549. Bool a_is_void_ptr=a.symbol.isVoidPtr(),
  550. b_is_void_ptr=b.symbol.isVoidPtr();
  551. if(pa.isPtr() && pb.isPtr() && (pa.same(pb, false, false) || pa=="null" || pb=="null" || a_is_void_ptr || b_is_void_ptr))
  552. {
  553. ConvertPtrToUIntPtr(pa);
  554. ConvertPtrToUIntPtr(pb);
  555. }else
  556. {
  557. // TODO: test for "class Base {} class Ext : Image, Base, Sound {} {Base *b; Ext *e; b==e;}" - WORKS OK in C++, Watch out for different offsets !! (don't forget about possible vfunc_table)
  558. // if(pa && pa->hasBase(pb..) || pb && pb->hasBase(pa..)) and compare if base's are the 'same' use 'same' func 'Base<int>' vs 'Ext' which has 'Base<float>'
  559. /*if(pa pb .isPtr())
  560. {
  561. }else // array
  562. {
  563. }*/
  564. if(compiler.strict){compiler.msgs.New().error("Can't compare pointers of different types", origin); return CAST_NONE;}
  565. }
  566. }
  567. if(func=="&&" || func=="^^" || func=="||")
  568. {
  569. if(pa.isObj() && pa)pa=TypeSymbol(SameSizeType(pa->var_type));
  570. if(pb.isObj() && pb)pb=TypeSymbol(SameSizeType(pb->var_type));
  571. }else
  572. {
  573. if(pa.isObj() && pa)pa=TypeSymbol(SameSizeSignType(pa->var_type));
  574. if(pb.isObj() && pb)pb=TypeSymbol(SameSizeSignType(pb->var_type));
  575. }
  576. func.func_call_mask=FC_RESULT;
  577. func.func_call =FindFuncCall(NativeOperatorName(func, symbol, pa, pb));
  578. return CAST_MAX;
  579. }else
  580. if(func=='=' || func=="*=" || func=="/=" || func=="%=" || func=="+=" || func=="-=" || func=="<<=" || func==">>=" || func=="&=" || func=="|=" || func=="^=") // verified Obj, Ptr, Array
  581. {
  582. if(a.symbol.isConst() && compiler.strict){if(!compiler.quiet)compiler.msgs.New().error("Can't modify a const value", origin); return CAST_NONE;}
  583. Bool array_to_ptr=false;
  584. if(a.symbol.isPtr() && b.symbol.isArray()) // convert "TYPE b[]" -> "TYPE *b"
  585. {
  586. if(!b.addressOf(compiler))return CAST_NONE; if(b.symbol.array_dims.elms()<2)return CAST_NONE;
  587. // 'b' is now pointer to array "TYPE (*b)[]", which needs to be converted to "TYPE *b" (ptr_level, array_dims[0..last-2]=*, array_dims[last-1]!=PTR, array_dims.last=PTR) -> (ptr_level, array_dims[0..last-2]=*, array_dims.last=PTR)
  588. UInt start=(b.symbol.const_level & ((1<<(b.symbol.ptr_level+b.symbol.array_dims.elms()-1))-1)); // get const level of (ptr_level, array_dims[0..last-2])
  589. // skip const level of ( array_dims[ last-1])
  590. Bool end =b.symbol.isConst(); // get const level of ( array_dims[ last ])
  591. if(b.symbol.array_dims.elms()!=2)b.symbol.array_dims.remove(b.symbol.array_dims.elms()-2, true); // remove element before last
  592. { // in case there are 2 array_dims then they are {"!=PTR, PTR"}, removing first would result in {"PTR"}, which should be represented as ptr_level and not array_dims
  593. b.symbol.ptr_level++;
  594. b.symbol.array_dims.clear();
  595. }
  596. b.symbol.const_level=start; b.symbol.setConst(end); // set new const levels
  597. array_to_ptr=true;
  598. }
  599. Bool same=a.symbol.same(b.symbol, false, false); // this is needed to test for the same enum's and pointers (enum's are not included in the 'CastMatch' function)
  600. CAST_MATCH cast=(same ? CAST_MAX : CastMatch(a.symbol ? a.symbol->varType() : VAR_NONE, b.symbol ? b.symbol->varType() : VAR_NONE));
  601. temporary=a.temporary; symbol=a.symbol;
  602. if(a.known() && b.known() && a.basicType() && func=='=')mem.setKnown();else memFrom(a.mem, compiler); // allow setting known only if both 'a' and 'b' are known (this is used in casting 'CastTo' when converting constants, however do not set known if 'a' is not a known constant, because it would cause skipping of setting the value in the compiler) otherwise use the same memory layout as 'a' because these operators do not return any other address
  603. calculateKnown(func, a, b, compiler);
  604. Symbol::Modif result, pa=a.symbol, pb=b.symbol; result=TypeSymbol(VAR_VOID);
  605. if(pa.isPtr())
  606. {
  607. if(func=="+=" || func=="-=")
  608. {
  609. if(compiler.strict)if(!pb.isObj() || !pb || !OffsetType(pb->var_type)){compiler.msgs.New().error(S+"Invalid offset for the "+func+" operator", b.origin); return CAST_NONE;}
  610. if(pa.array_dims.elms())pa.array_dims.removeLast();else pa.ptr_level--; // remove the ptr
  611. Int size=pa.rawSize(false); // get the size of under the pointer "byte *x" would be 1, while "byte **x" would be PtrSize
  612. if( size<=0 && compiler.strict){compiler.msgs.New().error("Unknown pointer size", origin); return CAST_NONE;}
  613. if( size==1) // "byte *p;" (can use integer += -=)
  614. {
  615. ConvertPtrToUIntPtr(pa);
  616. }else
  617. if(b.known()) // "TYPE *p; p+=const;" (can use integer += -= by "const*SIZE(TYPE)")
  618. {
  619. ConvertPtrToUIntPtr(pa);
  620. Long total=b.asLong(compiler)*size;
  621. b.setBasic((Int(total)!=total) ? VAR_LONG : VAR_INT); b.setCustom(S+total);
  622. }else
  623. {
  624. func.func_call_mask=0;
  625. func.func_call =GetAddPtrCall(pb);
  626. if(!func.func_call){if(!compiler.quiet)compiler.msgs.New().error("No function/operator found able to process command", origin); return CAST_NONE;} // if didn't found the function then it means this call is impossible
  627. // create extra param specifying size of the object (do this after all codes accessing func.params, because this will change memory address of func.params)
  628. Expr &raw_size=func.params.New(); raw_size.setBasic(VAR_INT); raw_size.mem.setKnown(); raw_size.setCustom(S+((func=="+=") ? size : -size));
  629. return CAST_MAX;
  630. }
  631. }else
  632. if(func=='=' && pb.isPtr())
  633. {
  634. Bool a_is_void_ptr=pa.isVoidPtr();
  635. if( a_is_void_ptr || same || pb=="null")
  636. {
  637. if(pb!="null" && compiler.strict)
  638. {
  639. pb.setConst(false); // disable last const, since "void *a; void *const b; a=b;" is OK
  640. if(a_is_void_ptr)pb.const_level=(pb.const_level!=0); // 'a' can be Ptr or CPtr, in that case set const_level to 'b' only to 1st bit
  641. if(LostConst(pb.const_level, pa.const_level) && compiler.strict){if(compiler.quiet)return CAST_NONE; compiler.msgs.New().error("Lost const", origin);}
  642. }
  643. ConvertPtrToUIntPtr(pa);
  644. ConvertPtrToUIntPtr(pb);
  645. if(!same)cast=CAST_CONV; // if the pointers are not the same, but we still can convert them, then set conversion priority (otherwise this could be CAST_NONE through 'CastMatch')
  646. if(array_to_ptr && compiler.unmappedLocal(b.mem)) // if 'b' pointer was created using 'addressOf'
  647. {
  648. b.mem=a.mem; // set target of 'addressOf' to 'a' pointer
  649. func.func_call=GetIgnoreCall();
  650. return cast;
  651. }
  652. }else
  653. {
  654. // TODO: do the same base checks as above in "==" operators
  655. // include LostConst(pb.const_level, pa.const_level))
  656. // include "cast=.."
  657. if(compiler.strict){if(!compiler.quiet)compiler.msgs.New().error("Can't set pointer to a different type", origin); return CAST_NONE;}
  658. }
  659. }
  660. }
  661. if(pa.isObj() && pa)pa=TypeSymbol( SameSizeSignBoolType(pa->var_type));
  662. if(pb.isObj() && pb)pb=TypeSymbol((pa && pa->var_type==VAR_BOOL && func=='=') ? SameSizeSignBoolType(pb->var_type) : SameSizeSignType(pb->var_type));
  663. func.func_call_mask=0;
  664. func.func_call =FindFuncCall(NativeOperatorName(func, result, pa, pb));
  665. if(!func.func_call){if(!compiler.quiet)compiler.msgs.New().error("No function/operator found able to process command", origin); return CAST_NONE;} // if didn't found the function then it means this call is impossible
  666. return cast;
  667. }else
  668. if(func=='*' || func=='/' || func=='%' || func=='+' || func=='-' || func=="<<" || func==">>" || func=='&' || func=='^' || func=='|') // verified Obj, Ptr, Array
  669. {
  670. if(a.symbol.isPtr())
  671. {
  672. if(func=='-' && b.symbol.isPtr()) // ptr-ptr (pointer difference)
  673. {
  674. if(!a.symbol.same(b.symbol, false, false) && compiler.strict){compiler.msgs.New().error("Can't perform pointer difference on different type of pointers", origin); return CAST_NONE;}
  675. Symbol::Modif pa=a.symbol; if(pa.array_dims.elms())pa.array_dims.removeLast();else if(pa.ptr_level>0)pa.ptr_level--;
  676. Int size=pa.rawSize(false); if(size<=0 && compiler.strict){compiler.msgs.New().error("Can't perform pointer difference on zero sized pointers", origin); return CAST_NONE;}
  677. setBasic((PtrSize==4) ? VAR_INT : VAR_LONG); // result must be UIntPtr
  678. memNew(false, compiler);
  679. func.func_call_mask=FC_RESULT;
  680. func.func_call =GetPtrDiffCall();
  681. // create extra param specifying size of the object (do this after all codes accessing func.params, because this will change memory address of func.params)
  682. Expr &raw_size=func.params.New(); raw_size.setBasic(VAR_INT); raw_size.mem.setKnown(); raw_size.setCustom(S+size);
  683. return CAST_MAX;
  684. }else
  685. if(func=='+' || func=='-') // ptr+int, ptr-int (pointer offset)
  686. {
  687. if(compiler.strict)if(!b.symbol.isObj() || !b.symbol || !OffsetType(b.symbol->var_type)){compiler.msgs.New().error(S+"Invalid offset for the "+func+" operator", b.origin); return CAST_NONE;}
  688. Symbol::Modif pa=a.symbol; if(pa.array_dims.elms())pa.array_dims.removeLast();else if(pa.ptr_level>0)pa.ptr_level--;
  689. Int size=pa.rawSize(false); if(size<=0 && compiler.strict){compiler.msgs.New().error("Unknown pointer size", origin); return CAST_NONE;}
  690. symbol=a.symbol; symbol.setConst(true); temporary=true; memNew(false, compiler);
  691. func.func_call_mask=FC_RESULT;
  692. func.func_call =GetPtrAddCall(b.symbol);
  693. if(!func.func_call){if(!compiler.quiet)compiler.msgs.New().error("No function/operator found able to process command", origin); return CAST_NONE;} // if didn't found the function then it means this call is impossible
  694. // create extra param specifying size of the object (do this after all codes accessing func.params, because this will change memory address of func.params)
  695. Expr &raw_size=func.params.New(); raw_size.setBasic(VAR_INT); raw_size.mem.setKnown(); raw_size.setCustom(S+((func=='+') ? size : -size));
  696. return CAST_MAX;
  697. }
  698. }else
  699. if(a.symbol && a.symbol.isObj() && b.symbol && b.symbol.isObj())
  700. {
  701. Symbol::Modif pa, pb;
  702. pa=TypeSymbol(SameSizeSignType(a.symbol->var_type));
  703. pb=TypeSymbol(SameSizeSignType(b.symbol->var_type));
  704. VAR_TYPE type=VAR_NONE;
  705. if(func=='*' )type= MulResult(pa->var_type, pb->var_type);else
  706. if(func=='/' )type= DivResult(pa->var_type, pb->var_type);else
  707. if(func=='%' )type= ModResult(pa->var_type, pb->var_type);else
  708. if(func=='+' )type= AddResult(pa->var_type, pb->var_type);else
  709. if(func=='-' )type= SubResult(pa->var_type, pb->var_type);else
  710. if(func=="<<" )type= ShiftLeftResult(pa->var_type, pb->var_type);else
  711. if(func==">>" )type=ShiftRightResult(pa->var_type, pb->var_type);else
  712. if(func=='&' || func=='^' || func=='|')type= BitResult(pa->var_type, pb->var_type);
  713. setBasic(type); memNew(a.known() && b.known(), compiler); calculateKnown(func, a, b, compiler);
  714. func.func_call_mask=FC_RESULT;
  715. func.func_call =FindFuncCall(NativeOperatorName(func, symbol, pa, pb));
  716. return CAST_MAX;
  717. }
  718. }else
  719. {
  720. compiler.msgs.New().error("Invalid binary operator", origin); return CAST_NONE;
  721. }
  722. }
  723. }else
  724. if(func.params.elms()==3) // ternary
  725. {
  726. Expr &a=func.params[0], &b=func.params[1], &c=func.params[2];
  727. if(func=='?') // a ? b : c
  728. {
  729. if(!a.known()){b.setConditional(); c.setConditional();}
  730. // TODO:
  731. // a must be of bool type (allow casting)
  732. // b must be of similar type to c (allow converting/casting)
  733. //temporary=b.temporary;
  734. symbol=b.symbol;
  735. //known=(a.known ? (a.asBool() ? b.known : c.known) : false);
  736. return CAST_MAX;
  737. }else
  738. {
  739. compiler.msgs.New().error("Invalid ternary operator", origin); return CAST_NONE;
  740. }
  741. }else
  742. {
  743. compiler.msgs.New().error("Invalid parameter number for operator", origin); return CAST_NONE;
  744. }
  745. }
  746. // TODO: check for function template specification "func<Image>(..)" and include it for AddMatches
  747. // TODO: check if calling non-const function for const parent/object
  748. // TODO: check for constructors / functions / custom operators
  749. Bool ignore_first =false, // used for detecting templates from function parameters "func(TYPE x)" func(Image()) -> TYPE=Image, ignore first param when having "a+b" operator when defined as class operator "class A{operator+(A b);}, in such case list of params is "a,b" but func/operator has "b" and we should ignore the 'a' param
  750. allow_mem_reuse=false; // if allow func.mem reuse for the result if available, this is used if we're calling class constructor and we already know the destination memory for the result
  751. Memc<FuncMatch> matches;
  752. if(func.symbol && (func.symbol->modifiers&Symbol::MODIF_DATA_TYPE)) // constructor/cast
  753. {
  754. if(!func.instance)
  755. {
  756. if(func.symbol.modifiers&Symbol::MODIF_REF) // reinterpret cast "(TYPE&)x"
  757. {
  758. symbol=func.symbol;
  759. if(func.params.elms()!=1 && compiler.strict){compiler.msgs.New().error(S+"Invalid number of parameters for cast to "+func, origin); return CAST_NONE;}
  760. if(func.params.elms()>=1)
  761. {
  762. Expr &a=func.params[0];
  763. if(a.known() && compiler.strict){compiler.msgs.New().error(S+"Can't perform cast on a known constant", origin); return CAST_NONE;}
  764. temporary=a.temporary; memFrom(a.mem, compiler); FlagSet(symbol.modifiers, Symbol::MODIF_REF, FlagTest(a.symbol.modifiers, Symbol::MODIF_REF)); // discard reference from the func, and keep it from the original 'a' parameter
  765. }
  766. return CAST_MAX;
  767. }else
  768. if(func.basicType()) // cast
  769. {
  770. if(func.params.elms()!=1 && compiler.strict){compiler.msgs.New().error(S+"Invalid number of parameters for cast to "+func, origin); return CAST_NONE;}
  771. // TODO: add support
  772. if(func.params.elms()>=1){Expr &a=func.params[0];}
  773. temporary=true; symbol=func.symbol; symbol.setConst(); return CAST_MAX;
  774. }else
  775. if(func.symbol->type==Symbol::CLASS) // class constructor
  776. {
  777. allow_mem_reuse=true;
  778. if(Symbol *ctor=FindChild(*func.symbol, func.symbol(), null, false)()) // get ctor func list
  779. if(ctor->type==Symbol::FUNC_LIST)
  780. AddMatches(matches, ctor->funcs, func.l_to_r, func.params.data(), func.params.elms(), func.symbol.templates, compiler); // add matches for all ctors
  781. }
  782. }
  783. }else
  784. if(func.symbol && func.symbol->type==Symbol::FUNC_LIST) // function (global func, class static method, class non-static method)
  785. {
  786. AddMatches(matches, func.symbol->funcs, func.l_to_r, func.params.data(), func.params.elms(), func.symbol.templates, compiler);
  787. }else
  788. if(func.symbol && func.symbol->type==Symbol::FUNC) // if a ready function was already provided (global func, class static method, class non-static method)
  789. {
  790. AddMatch(matches, func.symbol(), func.l_to_r, func.params.data(), func.params.elms(), func.symbol.templates, compiler);
  791. }else
  792. if(func._operator) // custom operator ("parent[param]", "parent(param)" - both can be class non-static method only) (global "operator(obj, param)", or class non-static "Class::operator(param)")
  793. {
  794. if(func=="()" || func=="[]") // "parent[param]", "parent(param)"
  795. {
  796. if(func.parent.elms()!=1){compiler.msgs.New().error(S+"Invalid object for the "+func+" operator", origin); return CAST_NONE;}
  797. Expr &parent=func.parent[0];
  798. if(!parent.instance || !parent.symbol || parent.symbol->type!=Symbol::CLASS){compiler.msgs.New().error(S+"Invalid object for the "+func+" operator", origin); return CAST_NONE;}
  799. Str func_name=SymbolToPath(S+"operator"+func);
  800. if(Symbol *op=FindChild(func_name, parent.symbol())())if(op->type==Symbol::FUNC_LIST)AddMatches(matches, op->funcs, func.l_to_r, func.params.data(), func.params.elms(), func.symbol.templates, compiler); // add class non-static operators "parent[params]", "parent(params)"
  801. }else
  802. if(func.params.elms()>=1) // global "operator(obj, param)" or class non-static "Class::operator(param)"
  803. {
  804. Str func_name=SymbolToPath(S+"operator"+func);
  805. ignore_first=true; // allow for potential ignoring of the first parameter
  806. if(Symbol *global_op=FindChild(func_name, null )())if(global_op->type==Symbol::FUNC_LIST)AddMatches(matches, global_op->funcs, func.l_to_r, func.params.data() , func.params.elms() , func.symbol.templates, compiler ); // add global operators " op(obj, params)"
  807. if(func.params.elms()>=1 && func.params[0].symbol && func.params[0].symbol.isObj())if(Symbol * class_op=FindChild(func_name, func.params[0].symbol())())if( class_op->type==Symbol::FUNC_LIST)AddMatches(matches, class_op->funcs, func.l_to_r, func.params.data()+1, func.params.elms()-1, func.symbol.templates, compiler, true); // add class non-static operators "Class::op( params)", add extra match, because 'this' already fits perfectly, and unlike matching line above it is not included in param list so it doesn't benefit from full match and we must add this manually
  808. if(!matches.elms() && func.params.elms()==1) // if there are no matches
  809. {
  810. // continue with built-in operators
  811. if(func=='*' || func=='&')goto indirection_address_of;
  812. }
  813. }
  814. }else
  815. {
  816. compiler.msgs.New().error("Invalid token", origin); return CAST_NONE;
  817. }
  818. if(matches.elms())
  819. {
  820. // remove double functions (definition/declaration)
  821. REPA(matches){Symbol *a=matches[i].func; REPD(j, i)if(a->sameFunc(*matches[j].func)){matches.remove((a->modifiers&Symbol::MODIF_FUNC_BODY) ? i : j, true); break;}} // remove the one with function body (because it doesn't have default parameters listed, and full class path)
  822. Symbol *f=matches.sort(CompareLowest).first().func;
  823. func.symbol=func.symbol_origin=f; // change function symbol from FUNC_LIST to the actual FUNC (do this before calling 'castParentToSymbolClass')
  824. if(f && f->source && f->source->ee_header) // check if this is EE function
  825. if(func.func_call=FindFuncCall(FuncName(*f))) // if this function was found on the list
  826. func.func_call_mask=((f->hasResult() ? FC_RESULT : 0) | (f->isClassNonStaticFunc() ? FC_PARENT : 0)); // setup call mask (use 'f' when checking for hasResult and not T.symbol.value!=void because 'f' was used during creation of the func list, and all functions there, never have templates)
  827. if(matches.elms()>=2 && matches[0].lowest_match==matches[1].lowest_match && compiler.strict) // check if there are multiple functions with same match
  828. {
  829. if(!compiler.quiet)
  830. {
  831. Str s=S+"Multiple function candidates found for "+f->fullCppName()+'(';
  832. FREPA(func.params)
  833. {
  834. if(i)s+=", ";
  835. s+=func.params[i].symbol.modifName(true, true, false);
  836. }
  837. s+=')';
  838. Message &msg=compiler.msgs.New().error(s, origin);
  839. FREPA(matches)if(matches[i].lowest_match==matches[0].lowest_match)if(Symbol *func=matches[i].func)
  840. {
  841. msg.children.New().set(func->definition(), func);
  842. }
  843. }
  844. return CAST_NONE;
  845. }
  846. if(matches[0].lowest_match<=CAST_NONE && compiler.strict) // check if the call is do-able
  847. {
  848. if(!compiler.quiet)compiler.msgs.New().error(S+"Invalid parameters for function call "+f->definition(), origin);
  849. return CAST_NONE;
  850. }
  851. // check if this is class non-static operator Class::op(params) which needs to move the 1st param as the parent
  852. if(ignore_first && f->isClassNonStaticFunc())
  853. {
  854. if(func.parent.elms()!=0 || func.params.elms()<=0){compiler.msgs.New().error(S+"Can't adjust class non-static operator", origin); return CAST_NONE;}
  855. Swap(func.parent.New(), func.params[0]); func.params.remove(0, true); // move the 1st param as the parent and remove from params list
  856. }
  857. // add default parameters
  858. if(compiler.strict)FREP(f->realParams())if(!InRange(i, func.params)) // order is important
  859. {
  860. Symbol *defaul=f->params[i]();
  861. if(defaul->modifiers&Symbol::MODIF_DEF_VALUE) // add param from default value
  862. {
  863. if(!defaul->source || compiler.compileTokens(defaul->def_val_range.x, defaul->def_val_range.y, func.params.New(), &defaul->source->tokens)!=COMPILE_FULL)
  864. {if(!compiler.quiet)compiler.msgs.New().error(S+"Error compiling expression for default value", defaul); return CAST_NONE;}
  865. }else
  866. {
  867. if(!compiler.quiet)compiler.msgs.New().error(S+"Missing parameters for function call", origin); return CAST_NONE;
  868. break; // stop on first which does not have default value
  869. }
  870. }
  871. // verify number of parameters
  872. if(f->realParams()!=func.params.elms() && compiler.strict){compiler.msgs.New().error(S+"Invalid number of parameters for function call", origin); return CAST_NONE;}
  873. // detect unknown template typenames from parameters, for example "TYPE func(TYPE x)" check every parameter if it's a TYPENAME and then set it according to parameter type, "func(Str())" would set 'TYPE' to 'Str' and "func(&Str())" would set 'TYPE' to 'Str*'
  874. FREP(f->realParams())if(f->params[i]->value && f->params[i]->value->type==Symbol::TYPENAME && InRange(i, func.params))
  875. {
  876. Expr &src=func.params[i];
  877. if(src.symbol)
  878. {
  879. Symbol::Modif &t=func.symbol.templates.New();
  880. t=src.symbol;
  881. t.src_template=f->params[i]->value;
  882. // TODO: what about const_level, array_dims, templates ?
  883. t.ptr_level -=f->params[i]->value.ptr_level; // yes it should be '-' because for "TYPE func(TYPE *x); func(&TYPE());" : func.param[0].ptr_level==1, param[0].ptr_level==1
  884. }
  885. }
  886. // detect unknown template typenames from function specification "func<TYPE>();"
  887. // TODO: check if this is not in conflict with above (template setting, however this should be more important)
  888. FREPA(func.symbol.templates)
  889. {
  890. Symbol::Modif &tmplt=func.symbol.templates[i]; // get all acquired template infos
  891. if(InRange(tmplt.src_template_i, f->templates.elms())) // if we've set 'src_template_i' lately, check if it should belong to obtained function
  892. tmplt.src_template=f->templates[tmplt.src_template_i]; // set that template
  893. tmplt.src_template_i=-1;
  894. }
  895. // verify if func is non-static and we have a good object/parent for it (do this after we have gathered all templates)
  896. // TODO: if there is any non-instance in the parent then disable virtual function calls (do this earlier as at this stage non-instance parents could have been removed in earlier call to 'castParentToSymbolClass')
  897. if(compiler.strict && !func.castParentToSymbolClass(compiler))return CAST_NONE; // do this after setting 'func.symbol_origin'
  898. // cast parameters if needed (do this after getting all templates)
  899. if(compiler.strict)FREP(f->realParams())if(InRange(i, func.params))if(!func.params[i].castTo(f->params[i](), func.symbol.templates, compiler)){compiler.msgs.New().error("Can't cast", func.params[i].origin); return CAST_NONE;}
  900. symbol.templates=func.symbol.templates; // copy templates obtained from the function to the result
  901. toSymbol(f, true);
  902. if(!(symbol.modifiers&Symbol::MODIF_REF)) // for functions that don't return references
  903. {
  904. temporary=true;
  905. if(basicType())symbol.setConst(); // this is C++ behavior (can't modify returned basic types)
  906. }
  907. if(allow_mem_reuse && func.mem.type)memFrom(func.mem, compiler);else memNew(false, compiler); // set memory layout for the result
  908. // once we have the result we need to setup the parent/object/this for the constructors to be the same as the result
  909. if(compiler.strict && (f->modifiers&Symbol::MODIF_CTOR))
  910. {
  911. if(func.parent.elms()!=0){compiler.msgs.New().error("Constructor parent should be empty", origin); return CAST_NONE;}
  912. copyThis(func.parent.New());
  913. }
  914. return CAST_MAX;
  915. }else
  916. {
  917. if(!compiler.quiet)compiler.msgs.New().error("No function/operator found able to process command", origin); return CAST_NONE;
  918. }
  919. }
  920. compiler.msgs.New().error("Invalid token", origin); return CAST_NONE;
  921. }
  922. Expr& Func(Memc<Expr> &expr, Int func_i, Int params, Compiler &compiler) // calculate function call, which starts at 'expr[func_i]' (which specifies function or operator) followed by list of 'params' parameters, result will be put into expr[func_i] while previous func/operator and params will be moved from the 'expr' array into the result (as members Expr::func,params)
  923. {
  924. if(!InRange(func_i, expr) || params<0 || params>=expr.elms()-func_i)Exit("Func out of range");
  925. Expr temp, // create element that will store the result
  926. &temp_func=temp.func.New(); // create func
  927. Swap(temp_func, expr[func_i]); // move 'func' from 'expr' into 'temp.func'
  928. temp_func.params.setNum(params); FREP(params)Swap(temp_func.params[i], expr[func_i+1+i]); // move 'params' from 'expr' into 'temp.func.params'
  929. CAST_MATCH cast=temp.calculate(compiler);
  930. // delete members because they will no longer be needed, this is to release memory and also avoid stack overflow, because the calculation tree can get very big for very long expressions such as "int x[]={0,1,2,3,4,..};"
  931. temp.parent.del();
  932. temp.func .del();
  933. temp.params.del();
  934. expr.removeNum(func_i+1, params, true); // remove params from 'expr' !! this call may change memory addresses !!
  935. Expr &result=expr[func_i]; // set reference after removing params
  936. Swap(temp, result);
  937. return result;
  938. }
  939. /******************************************************************************/
  940. Expr& Template(Memc<Expr> &expr, Int templ_i, Int params)
  941. {
  942. if(!InRange(templ_i, expr) || params<0 || params>=expr.elms()-templ_i)Exit("Template out of range");
  943. Expr &templ=expr[templ_i];
  944. FREP(params)
  945. {
  946. Expr &param=expr[templ_i+1+i];
  947. Symbol::Modif &dest =templ.symbol.templates.New();
  948. dest=param.symbol;
  949. if(templ.symbol)
  950. {
  951. if(templ.symbol->type==Symbol::FUNC_LIST)dest.src_template_i=i;else // we operate on FUNC_LIST so we don't know which exactly function we're going to call (as there can be "<TYPE> func(int a, TYPE b)", "<TYPE> func(float a, TYPE b)" , so instead of storing 'src_template' store its index 'src_template_i'
  952. if(InRange(i, templ.symbol->templates) )dest.src_template =templ.symbol->templates[i];
  953. }
  954. }
  955. REP(params)expr.remove(templ_i+1, true); // remove 'params' from 'expr' container !! after this call 'templ' can no longer be accessed !! (because memory addresses may changed)
  956. return expr[templ_i]; // don't use old reference (because memory addresses may changed)
  957. }
  958. /******************************************************************************/
  959. Bool Expr::possibleInstanceOrDataTypeOrNativeFunc( ) {return _operator==false;} // this function is used to disallow (prefix operator "this ++x") or ("this (x)" to "this x") - disallow: "int ++x" but allow: "return ++x" (currently 'return' and other similar keywords are assumed to be not set in Expr, so just ignore them)
  960. Bool Expr::knownFinal (Bool allow_func_lists) {return final && symbol && (allow_func_lists ? true : symbol->type!=Symbol::FUNC_LIST);}
  961. Bool Expr::instanceChild ( ) {if(parent.elms())return parent[0].firstInstance()!=null; return false;} // if any of parents is an instance then this expr is a child and not full object
  962. Bool Expr::fullTemporary ( ) {return temporary && !instanceChild();}
  963. Expr* Expr::firstInstance ( ) {for(Expr *expr=this; expr; expr=expr->parent.data())if(expr->instance)return expr; return null;}
  964. /******************************************************************************/
  965. Bool Expr::asBool(Compiler &compiler)
  966. {
  967. if(known())
  968. {
  969. // built-in constants
  970. if(T=="null" )return false;
  971. if(T=="false")return false;
  972. if(T=="true" )return true ;
  973. // pointers
  974. if(symbol.isPtr())return TextULong(asStr())!=0;
  975. // values
  976. if(symbol.isObj() && symbol)switch(symbol->var_type)
  977. {
  978. case VAR_CHAR8 :
  979. case VAR_CHAR16: return asChar(compiler)!=0;
  980. case VAR_FLT:
  981. case VAR_DBL: return TextDbl(asStr())!=0;
  982. case VAR_NULL: return false;
  983. default: return TextULong(asStr())!=0;
  984. }
  985. }
  986. return false;
  987. }
  988. Int Expr::asInt(Compiler &compiler)
  989. {
  990. if(known())
  991. {
  992. // built-in constants
  993. if(T=="null" )return 0;
  994. if(T=="false")return 0;
  995. if(T=="true" )return 1;
  996. // pointers
  997. if(symbol.isPtr())return TextInt(asStr());
  998. // values
  999. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1000. {
  1001. case VAR_CHAR8 :
  1002. case VAR_CHAR16: return (UShort)asChar(compiler);
  1003. case VAR_FLT:
  1004. case VAR_DBL: return TextInt(asStr());
  1005. case VAR_NULL: return 0;
  1006. default: return TextInt(asStr());
  1007. }
  1008. }
  1009. return 0;
  1010. }
  1011. UInt Expr::asUInt(Compiler &compiler)
  1012. {
  1013. if(known())
  1014. {
  1015. // built-in constants
  1016. if(T=="null" )return 0;
  1017. if(T=="false")return 0;
  1018. if(T=="true" )return 1;
  1019. // pointers
  1020. if(symbol.isPtr())return TextUInt(asStr());
  1021. // values
  1022. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1023. {
  1024. case VAR_CHAR8 :
  1025. case VAR_CHAR16: return (UShort)asChar(compiler);
  1026. case VAR_FLT:
  1027. case VAR_DBL: return TextUInt(asStr());
  1028. case VAR_NULL: return 0;
  1029. default: return TextUInt(asStr());
  1030. }
  1031. }
  1032. return 0;
  1033. }
  1034. Long Expr::asLong(Compiler &compiler)
  1035. {
  1036. if(known())
  1037. {
  1038. // built-in constants
  1039. if(T=="null" )return 0;
  1040. if(T=="false")return 0;
  1041. if(T=="true" )return 1;
  1042. // pointers
  1043. if(symbol.isPtr())return TextLong(asStr());
  1044. // values
  1045. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1046. {
  1047. case VAR_CHAR8 :
  1048. case VAR_CHAR16: return (UShort)asChar(compiler);
  1049. case VAR_FLT:
  1050. case VAR_DBL: return TextLong(asStr());
  1051. case VAR_NULL: return 0;
  1052. default: return TextLong(asStr());
  1053. }
  1054. }
  1055. return 0;
  1056. }
  1057. ULong Expr::asULong(Compiler &compiler)
  1058. {
  1059. if(known())
  1060. {
  1061. // built-in constants
  1062. if(T=="null" )return 0;
  1063. if(T=="false")return 0;
  1064. if(T=="true" )return 1;
  1065. // pointers
  1066. if(symbol.isPtr())return TextULong(asStr());
  1067. // values
  1068. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1069. {
  1070. case VAR_CHAR8 :
  1071. case VAR_CHAR16: return (UShort)asChar(compiler);
  1072. case VAR_FLT:
  1073. case VAR_DBL: return TextULong(asStr());
  1074. case VAR_NULL: return 0;
  1075. default: return TextULong(asStr());
  1076. }
  1077. }
  1078. return 0;
  1079. }
  1080. Flt Expr::asFlt(Compiler &compiler)
  1081. {
  1082. if(known())
  1083. {
  1084. // built-in constants
  1085. if(T=="null" )return 0.0f;
  1086. if(T=="false")return 0.0f;
  1087. if(T=="true" )return 1.0f;
  1088. // pointers
  1089. if(symbol.isPtr())return TextFlt(asStr());
  1090. // values
  1091. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1092. {
  1093. case VAR_CHAR8 :
  1094. case VAR_CHAR16: return (UShort)asChar(compiler);
  1095. case VAR_FLT:
  1096. case VAR_DBL: return TextFlt(asStr());
  1097. case VAR_NULL: return 0.0f;
  1098. default: return TextFlt(asStr());
  1099. }
  1100. }
  1101. return 0.0f;
  1102. }
  1103. Dbl Expr::asDbl(Compiler &compiler)
  1104. {
  1105. if(known())
  1106. {
  1107. // built-in constants
  1108. if(T=="null" )return 0.0;
  1109. if(T=="false")return 0.0;
  1110. if(T=="true" )return 1.0;
  1111. // pointers
  1112. if(symbol.isPtr())return TextDbl(asStr());
  1113. // values
  1114. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1115. {
  1116. case VAR_CHAR8 :
  1117. case VAR_CHAR16: return (UShort)asChar(compiler);
  1118. case VAR_FLT:
  1119. case VAR_DBL: return TextDbl(asStr());
  1120. case VAR_NULL: return 0.0;
  1121. default: return TextDbl(asStr());
  1122. }
  1123. }
  1124. return 0.0;
  1125. }
  1126. Char CppChar(C Str &s, Int &i, Token *token, Compiler &compiler)
  1127. {
  1128. if(s[i]=='\\')switch(s[(++i)++])
  1129. {
  1130. default : compiler.msgs.New().error(S+"Unrecognized '"+s[i-1]+"' character escape sequence", token); return '\0';
  1131. case 'n' : return '\n';
  1132. case 't' : return '\t';
  1133. case 'v' : return '\v';
  1134. case 'b' : return '\b';
  1135. case 'r' : return '\r';
  1136. case 'f' : return '\f';
  1137. case 'a' : return '\a';
  1138. case '\\': return '\\';
  1139. case '?' : return '\?';
  1140. case '\'': return '\'';
  1141. case '"' : return '\"';
  1142. case '0' : return '\0';
  1143. case 'x' :
  1144. {
  1145. UInt u=0; for(; i<s.length(); i++)
  1146. {
  1147. Int v=CharInt(s[i]);
  1148. if( v>=0)u=u*16+v;else break;
  1149. }
  1150. return (Char)u;
  1151. }break;
  1152. }
  1153. return s[i++];
  1154. }
  1155. Char Expr::asChar(Compiler &compiler)
  1156. {
  1157. if(known())
  1158. {
  1159. // built-in constants
  1160. if(T=="null" )return '\0';
  1161. if(T=="false")return '\0';
  1162. if(T=="true" )return '\1';
  1163. // pointers
  1164. if(symbol.isPtr())return (Char)TextInt(asStr());
  1165. // values
  1166. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1167. {
  1168. case VAR_CHAR8 :
  1169. case VAR_CHAR16:
  1170. {
  1171. Str s=T;
  1172. if((s[0]=='8' || s[0]=='u' || s[0]=='U' || s[0]=='L') && s[1]=='\'' && s.last()=='\'')s.remove(0); // eat 8,u,U,L from 8"..", u"..", U"..", L".."
  1173. if(s[0]=='\'' && s.last()=='\'')s.removeLast().remove(0); // eat '' from '..'
  1174. Int i=0; return CppChar(s, i, origin, compiler);
  1175. }break;
  1176. case VAR_FLT:
  1177. case VAR_DBL: return (Char)TextInt(asStr());
  1178. case VAR_NULL: return '\0';
  1179. default: return (Char)TextInt(asStr());
  1180. }
  1181. }
  1182. return '\0';
  1183. }
  1184. Memc<Char> Expr::asText(Compiler &compiler)
  1185. {
  1186. Str s=T;
  1187. if((s[0]=='8' || s[0]=='u' || s[0]=='U' || s[0]=='L') && s[1]=='"' && s.last()=='"')s.remove(0); // eat 8,u,U,L from 8"..", u"..", U"..", L".."
  1188. if(s[0]=='"' && s.last()=='"')s.removeLast().remove(0); // eat "" from ".."
  1189. Memc<Char> out; for(Int i=0; i<s.length(); )out.add(CppChar(s, i, origin, compiler)); out.add('\0');
  1190. return out;
  1191. }
  1192. U64 Expr::asRaw(Compiler &compiler)
  1193. {
  1194. if(known() && is())
  1195. {
  1196. // pointers
  1197. if(symbol.isPtr())return asLong(compiler);
  1198. // values
  1199. if(symbol.isObj() && symbol)switch(symbol->var_type)
  1200. {
  1201. case VAR_BOOL : return asBool(compiler);
  1202. case VAR_BYTE :
  1203. case VAR_SBYTE :
  1204. case VAR_SHORT :
  1205. case VAR_USHORT:
  1206. case VAR_INT :
  1207. case VAR_UINT :
  1208. case VAR_ENUM : return asInt(compiler);
  1209. case VAR_LONG :
  1210. case VAR_ULONG : return asLong(compiler);
  1211. case VAR_CHAR8 : return (Byte )asChar8(compiler);
  1212. case VAR_CHAR16: return (UShort)asChar (compiler);
  1213. case VAR_FLT: {Flt f=asFlt(compiler); return (U32&)f;}
  1214. case VAR_DBL: {Dbl d=asDbl(compiler); return (U64&)d;}
  1215. }
  1216. }
  1217. compiler.msgs.New().error("Expression value is not known and can't be converted to raw memory"); return 0;
  1218. }
  1219. /******************************************************************************/
  1220. Expr& Expr::setOperator(CChar *op)
  1221. {
  1222. symbol.clear(true);
  1223. setBorrowed(op);
  1224. _operator=true;
  1225. instance=false;
  1226. setPriority();
  1227. return T;
  1228. }
  1229. Expr& Expr::setBasic(VAR_TYPE type)
  1230. {
  1231. symbol.clear(true); toSymbol(TypeSymbol(type));
  1232. symbol.const_level=1;
  1233. _operator =false;
  1234. instance =true;
  1235. temporary=true;
  1236. return T;
  1237. }
  1238. Expr& Expr::setPtr()
  1239. {
  1240. symbol.clear(true); toSymbol(Symbols("ptr"));
  1241. symbol.const_level=1|2;
  1242. _operator =false;
  1243. instance =true;
  1244. temporary=true;
  1245. return T;
  1246. }
  1247. /******************************************************************************/
  1248. Expr& Expr::toSymbol(Symbol *symbol, Bool func_call) // this function moves from current symbol (usually a parent) to 'symbol' (usually a child), keeping templates (templates are kept because in "<TYPE> class X {TYPE x;}" if we're moving from parent "X<int> obj; obj.x" then 'obj' (parent) has the template information and proceeding to 'x' symbol (child) we will still know its template and thus its type)
  1249. {
  1250. T.symbol.clear(false); // keep templates
  1251. T.symbol =symbol;
  1252. T.symbol_origin=symbol;
  1253. if(!final)T.symbol.proceedToFinal(&T.symbol.templates, func_call); // for final we are interested only in the root 'symbol' (not its value) for example when we want to use jump-to-definition on function we want to calculate which FUNC is that
  1254. if(T.symbol)AddBaseTemplates(T.symbol.templates, *T.symbol); // after getting the final value we need to add base templates for its class (new templates may override previous values)
  1255. //if(T.symbol)BStr::setBorrowed(*T.symbol); adjust the name for debug purpose - DON'T DO THIS because it will destroy constants: "abc" 'a' 123 etc. !
  1256. if(symbol_origin) // check 'T.symbol_origin' and not 'T.symbol', because for example 'T.symbol_origin' operates on root (like variable) while 'T.symbol' is already set to target type (such as type/class of variable)
  1257. {
  1258. if(symbol_origin->type==Symbol::VAR // variable, for example 'x' in "int x"
  1259. || symbol_origin->type==Symbol::FUNC || symbol_origin->type==Symbol::FUNC_LIST // functions are also instances, because in C++ they can be casted to pointers for example, this is correct!
  1260. || symbol_origin->type==Symbol::ENUM_ELM)T.instance=true; // enum element is also an instance (just like constant integer '1')
  1261. if(symbol_origin->type==Symbol::ENUM_ELM){T.temporary=true; T.symbol.const_level|=1; mem.setKnown();}
  1262. }
  1263. return T;
  1264. }
  1265. /******************************************************************************/
  1266. void Expr::setPriority()
  1267. {
  1268. l_to_r=true;
  1269. if(_operator)
  1270. {
  1271. #define UNARY_PRIORITY 17
  1272. if(T=='.' || T=="->" || T=="::")priority=19;else
  1273. if(T=='(' || T==')' || T=='[' || T==']' || T==TMPL_B || T==TMPL_E || T=="++" || T=="--")priority=18;else
  1274. if(T=='~' || T=='!'/* || T=='*' || T=='&' || T=="+" || T=="-"*/){priority=UNARY_PRIORITY; l_to_r=false;}else
  1275. if(T==".*" || T=="->*")priority=16;else
  1276. if(T=='*' || T=='/' || T=='%')priority=15;else
  1277. if(T=='+' || T=='-' )priority=14;else
  1278. if(T=="<<" || T==">>" )priority=13;else
  1279. if(T=='<' || T=='>' || T=="<=" || T==">=" )priority=12;else
  1280. if(T=="==" || T=="!=" || T=="===" || T=="!!=")priority=11;else
  1281. if(T=='&' )priority=10;else
  1282. if(T=='^' )priority= 9;else
  1283. if(T=='|' )priority= 8;else
  1284. if(T=="&&")priority= 7;else
  1285. if(T=="^^")priority= 6;else
  1286. if(T=="||")priority= 5;else
  1287. if(T=='?' || T==':'){priority=4; l_to_r=false;}else
  1288. if(T=='=' || T=="*=" || T=="/=" || T=="%=" || T=="+=" || T=="-=" || T=="<<=" || T==">>=" || T=="&=" || T=="|=" || T=="^="){priority=3; l_to_r=false;}else
  1289. if(T==',' )priority= 2;else
  1290. priority=1;
  1291. }else priority=0;
  1292. }
  1293. /******************************************************************************/
  1294. void Expr::setConditional()
  1295. {
  1296. conditional=true;
  1297. REPAO(parent).setConditional();
  1298. REPAO(func ).setConditional();
  1299. REPAO(params).setConditional();
  1300. }
  1301. void Expr::setBlockScope(Compiler &compiler, Bool force_heap)
  1302. {
  1303. if(mem.type==Memory::LOCAL && InRange(mem.index, compiler.locals))
  1304. {
  1305. Local &local=compiler.locals[mem.index];
  1306. local.block_scope=true;
  1307. if(force_heap && !local.force_heap)
  1308. {
  1309. local.force_heap =true;
  1310. local.stack_offset=-1; // unuse the stack
  1311. }
  1312. }
  1313. }
  1314. /******************************************************************************/
  1315. void Expr::memAuto(Compiler &compiler)
  1316. {
  1317. if(symbol_origin && symbol_origin->isVar())
  1318. {
  1319. if(mem.type)compiler.msgs.New().error("Expression already had memory layout set", origin);
  1320. if(symbol_origin->modifiers&Symbol::MODIF_FUNC_PARAM) // function parameter
  1321. {
  1322. mem.setParam(*symbol_origin);
  1323. }else
  1324. if(symbol_origin->func()) // symbol belongs to a function - it's a local variable in a function
  1325. {
  1326. if(symbol_origin->modifiers&Symbol::MODIF_STATIC) // static variable inside function body
  1327. {
  1328. // TODO: support function static variables
  1329. }else // non-static variable inside function body
  1330. {
  1331. if(!InRange(symbol_origin->raw_offset, compiler.locals)) // if the symbol was not yet initialized in the 'locals'
  1332. symbol_origin->raw_offset=compiler.newLocal(symbol, true, origin); // set local variable type to the final symbol of this 'Expr' and NOT 'symbol_origin' (and set the returned index of the local variable)
  1333. mem.setLocal(*symbol_origin);
  1334. }
  1335. }else
  1336. if(symbol_origin->isGlobalOrStatic()) // global or class static variable
  1337. {
  1338. mem.setGlobal(*symbol_origin);
  1339. }else
  1340. {
  1341. // class non-static members (this.member, obj.member), don't set this here because we don't know the class object for the member
  1342. }
  1343. }
  1344. }
  1345. void Expr::memNew(Bool known, Compiler &compiler)
  1346. {
  1347. if(mem.type)compiler.msgs.New().error("Expression already had memory layout set", origin);
  1348. if(known)mem.setKnown();else mem.setLocal(compiler.newLocal(symbol, false, origin));
  1349. }
  1350. void Expr::memFrom(Memory &mem, Compiler &compiler)
  1351. {
  1352. if(T.mem.type)compiler.msgs.New().error("Expression already had memory layout set", origin);
  1353. T.mem=mem;
  1354. }
  1355. void Expr::memOffset(Long offset)
  1356. {
  1357. mem.addOffset(offset, FlagTest(symbol.modifiers, Symbol::MODIF_REF));
  1358. }
  1359. /******************************************************************************/
  1360. static void CastTo(Expr &expr, Symbol::Modif &dest, CAST_MATCH &max_cast, Expr &max_result, Compiler &compiler, RecTest &rt=ConstCast(RecTest())) // function which recursively updates the cast
  1361. {
  1362. IntLock lock(rt); if(rt)return;
  1363. Symbol::Modif &src=expr.symbol;
  1364. if(src && dest)
  1365. {
  1366. //Bool is_null=(src=="null"), good_null=(is_null && dest.isPtr());
  1367. UInt src_const_level=src .const_level; FlagDisable( src_const_level, 1<<(src .ptr_level+src .array_dims.elms())); // disable top const
  1368. UInt dest_const_level=dest.const_level; FlagDisable(dest_const_level, 1<<(dest.ptr_level+dest.array_dims.elms())); // disable top const
  1369. Bool same=src .same(dest, false, false);
  1370. // check for reference able to modify source
  1371. if((dest.modifiers&Symbol::MODIF_REF) && !dest.isConst()) // if expecting non-const reference - "TYPE&" or "TYPE *const *const * &" then proceed only if the 'src' is the same
  1372. {
  1373. if(same && !LostConst(src.const_level, dest.const_level))
  1374. {
  1375. max_cast =((src.const_level==dest.const_level) ? CAST_MAX : CAST_MAX_CONST);
  1376. max_result=expr;
  1377. return; // we won't get any better cast
  1378. }
  1379. goto try_base; // do not try operator=, constructor and auto-cast, but go directly to base testing
  1380. }
  1381. // check for same type
  1382. if(same)
  1383. if(!LostConst(src.const_level, dest.const_level) // identical
  1384. || !LostConst(src_const_level, dest_const_level) && src.basicType()) // allow "const int -> int" and "int *const-> int *"
  1385. {
  1386. max_cast =((src.const_level==dest.const_level) ? CAST_MAX : CAST_MAX_CONST);
  1387. max_result=expr;
  1388. return; // we won't get any better cast
  1389. }
  1390. // allow conversion
  1391. // try calling 'dest' constructor
  1392. if(dest.basicType()) // try operator = (this will automatically calculate known value)
  1393. {
  1394. // =(expr_dest, expr_src) -> expr_dest=expr_src
  1395. Expr result, &func=result.func.New(); func.origin=expr.origin; func.setOperator(u"="); func.params.setNum(2); // allocate parameters up-front so New will not change address of references
  1396. Expr &expr_dest=func.params[0], &expr_src=func.params[1];
  1397. // setup 'expr_src'
  1398. expr_src=expr; // expr_src is the original (so copy the original 'expr' into 'expr_src')
  1399. // setup 'expr_dest'
  1400. expr_dest.origin =expr_src.origin;
  1401. expr_dest.instance =expr_src.instance;
  1402. expr_dest.temporary=expr_src.temporary;
  1403. expr_dest.symbol =dest; expr_dest.symbol.setConst(false); FlagDisable(expr_dest.symbol.modifiers, Symbol::MODIF_REF); // disable main const to enable setting the value, and disable reference because we're still setting to a temporary local variable (or known const) which then later will be passed to the reference
  1404. expr_dest.memNew(expr_src.known(), compiler); // if source is known then dest will be known as well, if not then we need to store it in locals
  1405. // compile the 'operator='
  1406. Bool quiet=compiler.quiet, allow_cast=compiler.allow_cast; compiler.quiet=true; compiler.allow_cast=false; // make sure error messages are not generated
  1407. CAST_MATCH cast=result.calculate(compiler);
  1408. compiler.quiet=quiet; compiler.allow_cast=allow_cast; // restore quiet and allow cast
  1409. if(src.const_level!=dest.const_level)cast=CastMatchConst(cast); // adjust const if needed (do this here and not inside 'calculate' because there the 'expr_dest' has const disabled in order to allow setting the value)
  1410. if(cast>max_cast){max_cast=cast; Swap(max_result, result); if(max_cast>=CAST_MAX_CONST)return;} // 'Swap' can be used because 'result' is local variable
  1411. }else // try class constructor
  1412. if(dest.isObj() && compiler.allow_cast)
  1413. {
  1414. // class Test { Test(Str str); Test(int x); }; void func(Test t); - func(0.0f) is GOOD, but func("") is BAD (here only direct match, or basic type conversions are allowed)
  1415. Expr result, &func=result.func.New(); func.origin=expr.origin;
  1416. func.symbol=dest;
  1417. func.symbol.setConst(false); // disable const so it can be modified for further purpose
  1418. FlagDisable(func.symbol.modifiers, Symbol::MODIF_REF); // disable reference (we're calling ctor)
  1419. func.params.New()=expr; // this is the original expression
  1420. Bool quiet=compiler.quiet, allow_cast=compiler.allow_cast; compiler.quiet=true; compiler.allow_cast=false; // make sure error messages are not generated
  1421. CAST_MATCH cast=result.calculate(compiler); MIN(cast, CAST_CTOR);
  1422. compiler.quiet=quiet; compiler.allow_cast=allow_cast; // restore quiet and allow cast
  1423. if(cast>max_cast){max_cast=cast; Swap(max_result, result);} // 'Swap' can be used because 'result' is local variable
  1424. }
  1425. //expr.copyCtor
  1426. /*if(Symbol *ctor=FindChild(*dest, dest(), null, false)())
  1427. if(ctor->type==Symbol::FUNC_LIST)
  1428. REPA(ctor->funcs)
  1429. {
  1430. Symbol *func=ctor->funcs[i]();
  1431. if(func->params.elms()==1 || (func->params.elms()>=2 && (func->params[1]->modifiers&Symbol::MODIF_DEF_VALUE))) // if can be called by using only 1 parameter only (can accept 2 or more but all must have default values specified)
  1432. {
  1433. if(func->modifiers&Symbol::MODIF_FUNC_BODY)REPAD(j, ctor->funcs)if(i!=j && func->sameFunc(*ctor->funcs[j]))goto skip_func; // skip same functions with bodies (they have different templates and no default parameters)
  1434. {
  1435. Symbol::Modif param; param=func->params[0]; param.proceedToFinal(&dest.templates);
  1436. //if(param.same(src, false, false
  1437. //Symbol::Modif param; param=func->params[0]; param.proceedToFinal(&templates); // dest.templates?
  1438. // CAST_CTOR
  1439. //if(param.same(dest, false, false) // if has constructor for source
  1440. //|| (param && param->type==Symbol::TYPENAME) // if this is unknown template
  1441. // )return CAST_OK;
  1442. /*Bool identical=(!LostConst(src.const_level, param.const_level) && src.same(param, false, false));
  1443. if( identical)return CAST_MAX;
  1444. if((param.modifiers&Symbol::MODIF_REF) && !param.isConst()) // if expecting non-const reference - "TYPE&" or "TYPE *const *const * &" then proceed only if the 'src' is the same
  1445. {
  1446. return identical ? CAST_MAX : CAST_NONE;
  1447. }*
  1448. }
  1449. skip_func:;
  1450. }
  1451. }*/
  1452. // try calling auto-cast
  1453. if(src.isObj() && !src.basicType() && compiler.allow_cast)
  1454. {
  1455. if(Symbol *auto_cast=FindChild("operator cast", src(), null, false)())
  1456. if(auto_cast->type==Symbol::FUNC_LIST)
  1457. REPA(auto_cast->funcs)
  1458. {
  1459. Symbol *func=auto_cast->funcs[i]();
  1460. if(func->modifiers&Symbol::MODIF_FUNC_BODY)REPAD(j, auto_cast->funcs)if(i!=j && func->sameFunc(*auto_cast->funcs[j]))goto skip_auto_cast; // skip same functions with bodies (they have different templates and no default parameters)
  1461. {
  1462. //Symbol::Modif auto_cast; auto_cast=func; auto_cast.proceedToFinal(&templates); // src.templates?
  1463. //if(auto_cast)
  1464. {
  1465. //MAX(cast, CastMatch(auto_cast->var_type, auto_cast.ptr_level, to, templates )-1);
  1466. //MAX(cast, CastMatch(auto_cast , to, templates, rt)-1);
  1467. }
  1468. }
  1469. skip_auto_cast:;
  1470. }
  1471. }
  1472. // check if any base class has better casting to the target
  1473. // TODO: check if bases can be accessed (private, protected ..)
  1474. // TODO: what if src is a pointer, can this still be used? perhaps only first base can be used, and only if it's at zero memory offset (watch out for 1st base non-virtual, but some other base or parent being virtual, in such case base would be offsetted by vfunc ptr)
  1475. try_base:
  1476. if(max_cast<CAST_MAX_CONST)REPA(src->base)
  1477. {
  1478. Expr base=expr; base.proceedToBase(i); // operate on temporary value so that 'expr' remains unmodified
  1479. CastTo(base, dest, max_cast, max_result, compiler, rt); if(max_cast>=CAST_MAX_CONST)return;
  1480. }
  1481. }
  1482. }
  1483. static Bool CastToBase(Expr &expr, Symbol::Modif &dest, Expr &out, RecTest &rt=ConstCast(RecTest()))
  1484. {
  1485. IntLock lock(rt); if(rt)return false;
  1486. Symbol::Modif &src=expr.symbol;
  1487. if(src.same(dest, false, false)){if(&out!=&expr)out=expr; return true;}
  1488. // TODO: what if src is a pointer, can this still be used? perhaps only first base can be used, and only if it's at zero memory offset (watch out for 1st base non-virtual, but some other base or parent being virtual, in such case base would be offsetted by vfunc ptr)
  1489. if(src)REPA(src->base)
  1490. {
  1491. // TODO: check if bases can be accessed (private, protected ..)
  1492. Expr base=expr; base.proceedToBase(i); // operate on temporary value so that 'expr' remains unmodified
  1493. if(CastToBase(base, dest, out, rt))return true;
  1494. }
  1495. return false;
  1496. }
  1497. Bool Expr::castToBase(Symbol::Modif &dest)
  1498. {
  1499. return CastToBase(T, dest, T);
  1500. }
  1501. Bool Expr::castTo(Symbol::Modif &dest, Compiler &compiler) // try to convert 'this' to 'dest' by ('dest' ctor from 'this', or use 'this' auto-cast operator)
  1502. {
  1503. if(!instance)return false; // can't convert from non-instance
  1504. if(!(dest.modifiers&Symbol::MODIF_REF) && dest.isPtr() && T=="null")return true; // no conversion needed (test this in case "operator=" may not set "null" value in the result)
  1505. /*TODO: link templates? template_src.. (what about T.symbol.templates and dest.templates), template_src is already used in 'same' function
  1506. Memc<Symbol::Modif> linked_templates=templates; // if target accepts templates, and we know those templates (they are listed in 'templates', then add target template as known)
  1507. // for example target is "Memc<Int>" or "<TYPE> Memc<TYPE>" or "<TYPE> TYPE" ?
  1508. // TODO: should this be "dest->value.templates" or "to_final.templates" ?
  1509. FREPA(to_final.templates)
  1510. {
  1511. Symbol::Modif &dest=to_final.templates[i];
  1512. REPA(linked_templates)
  1513. {
  1514. Symbol::Modif &src=linked_templates[i];
  1515. if(dest==src.src_template)
  1516. {
  1517. src.src_template=dest.src_template;
  1518. break;
  1519. }
  1520. }
  1521. }*/
  1522. CAST_MATCH cast=CAST_NONE; Expr result;
  1523. CastTo(T, dest, cast, result, compiler);
  1524. if(cast>CAST_NONE){Swap(T, result); return true;}
  1525. return false;
  1526. }
  1527. Bool Expr::castTo(Symbol *dest, Memc<Symbol::Modif> &templates, Compiler &compiler)
  1528. {
  1529. Symbol::Modif final; final=dest; final.templates=templates; final.proceedToFinal(&final.templates); return castTo(final, compiler); // copy templates in the modif and do proceedToFinal so "TYPE<TYPE2>" can be replaced with "Memc<Str>" (meaning, template class can be replaced with the target, and its templates can be as well, in other words keep the templates in modif.templates so we can pass "Memc<Str>" with "Str" in the templates)
  1530. }
  1531. CAST_MATCH Expr::canBeCastedTo(Symbol *dest, Memc<Symbol::Modif> &templates, Compiler &compiler)
  1532. {
  1533. Symbol::Modif final; final=dest; final.templates=templates; final.proceedToFinal(&final.templates);
  1534. if(!(final.modifiers&Symbol::MODIF_REF) && final.isPtr() && T=="null")return CAST_MAX;
  1535. if(!compiler.strict && final && final->type==Symbol::TYPENAME)return CAST_CONV; // if dest is template then it can always be used
  1536. CAST_MATCH cast=CAST_NONE; Expr result; CastTo(T, final, cast, result, compiler); return cast;
  1537. }
  1538. Bool Expr::castToConditional()
  1539. {
  1540. if(symbol.isPtr())return true;
  1541. if(symbol.isObj() && symbol)
  1542. {
  1543. switch(symbol->var_type)
  1544. {
  1545. case VAR_VOID : return false; // can't be casted
  1546. case VAR_BOOL : // all of these types have their 'goto' commands defined in the func list
  1547. case VAR_BYTE :
  1548. case VAR_SBYTE :
  1549. case VAR_SHORT :
  1550. case VAR_USHORT:
  1551. case VAR_INT :
  1552. case VAR_UINT :
  1553. case VAR_LONG :
  1554. case VAR_ULONG :
  1555. case VAR_FLT :
  1556. case VAR_DBL :
  1557. case VAR_CHAR8 :
  1558. case VAR_CHAR16:
  1559. case VAR_ENUM : return true;
  1560. case VAR_NONE : // possible object
  1561. {
  1562. // TODO: add support for casting to bool (use some universal function used in other parts too)
  1563. }break;
  1564. }
  1565. }
  1566. return false;
  1567. }
  1568. Bool Expr::castParentToSymbolClass(Compiler &compiler)
  1569. {
  1570. if(symbol_origin && symbol_origin->isClassNonStaticMember()) // expects 'this'
  1571. {
  1572. if(symbol_origin->modifiers&Symbol::MODIF_CTOR){parent.del(); return true;} // constructors can be called without specifying the parent
  1573. // move all non-instance parents to temporary, sample data: "obj.Base::this" will move "obj.Base" to temp
  1574. Expr parent_path;
  1575. if(parent.elms() && !parent[0].instance)
  1576. {
  1577. Swap(parent[0], parent_path); parent.clear(); // move all parents to the temp
  1578. if(Expr *instance=parent_path.firstInstance()) // get first instance in temp parent path
  1579. Swap(parent.New(), *instance); // put the instance into this.parent, this may leave the top parent_path as empty expression
  1580. }
  1581. // get the object
  1582. Expr *parent_instance=parent.data();
  1583. // if no instance is specified then use 'this'
  1584. if(!parent_instance)
  1585. if(origin && origin->parent)
  1586. if(Symbol *caller_func=origin->parent->func())
  1587. if(caller_func->isClassNonStaticFunc())
  1588. if(Symbol *caller_class=caller_func->Class())
  1589. {
  1590. parent_instance=&parent.New();
  1591. if(!parent_instance->setThis(caller_func, origin, compiler))return false;
  1592. }
  1593. // verify the obtained instance
  1594. if(!parent_instance || !parent_instance->instance){compiler.msgs.New().error(S+"Can't access class non-static member without specifying the class object", origin); return false;}
  1595. if( parent_instance->symbol.array_dims.elms() ){compiler.msgs.New().error(S+"Can't access class non-static member from an array" , origin); return false;}
  1596. if( parent_instance->symbol.ptr_level>1 ){compiler.msgs.New().error(S+"Can't access class non-static member from deep pointer" , origin); return false;}
  1597. if( parent_instance->symbol.ptr_level>0 )if(!parent_instance->indirection(compiler))return false;
  1598. // follow the parent path (this is needed in case of "Class::Base1::Str" and "Class::Base2::Str"
  1599. Memc<Symbol::Modif*> parents; for(Expr *cur=&parent_path; cur; cur=cur->parent.data())if(cur->symbol && cur->symbol->type==Symbol::CLASS)parents.add(&cur->symbol); // parents are now listed in C++ reversed order "empty_instance::base::class::namespace"
  1600. REPA(parents)parent_instance->castToBase(*parents[i]); // process in reversed order to process in normal C++ order (first namespace, then class, then bases)
  1601. // now we have the object, so verify that the 'symbol_origin' can be called from it
  1602. Symbol *parent_symbol=parent_instance->symbol();
  1603. Bool allow_self =true;
  1604. if(parent_symbol && parent_symbol->type==Symbol::KEYWORD && (*parent_symbol=="super" || *parent_symbol=="__super"))
  1605. {
  1606. allow_self=false;
  1607. if(parent_instance->parent.elms())
  1608. {
  1609. parent_symbol=parent_instance->parent[0].symbol();
  1610. }else
  1611. {
  1612. parent_symbol=((origin && origin->parent) ? origin->parent->Class() : null);
  1613. }
  1614. }
  1615. if(!symbol_origin->isMemberOf(parent_symbol, symbol.templates, origin ? origin->parent : null, true, false, allow_self, true)){compiler.msgs.New().error(S+"Can't access class non-static member from specified object", origin); return false;}
  1616. // cast parent to class made from "symbol_origin->Class" with templates extracted from "this.templates"
  1617. Symbol::Modif cast; cast=symbol_origin->Class(); cast.templates=symbol.templates;
  1618. if(!parent_instance->castToBase(cast)){compiler.msgs.New().error("Can't cast object from its class to class of the member", parent_instance->origin ? parent_instance->origin : origin); return false;}
  1619. // setup memory layout for the member
  1620. if(symbol_origin->isVar())
  1621. {
  1622. if(!parent_instance || !parent_instance->symbol){compiler.msgs.New().error(S+"Something went wrong during member object calculation", origin); return COMPILE_FAILED;}
  1623. Bool found; Int member_offset=parent_instance->symbol->memberOffset(symbol_origin, &found, &symbol.templates);
  1624. if( !found){compiler.msgs.New().error(S+"Member not found in class", origin); return COMPILE_FAILED;}
  1625. mem=parent_instance->mem;
  1626. mem.addOffset(member_offset, FlagTest(parent_instance->symbol.modifiers, Symbol::MODIF_REF)); // here 'this.ref' should be ignored for 'memOffset' and only 'parent.ref' should be checked
  1627. if(parent_instance->symbol.modifiers&Symbol::MODIF_REF)
  1628. {
  1629. if(symbol.modifiers&Symbol::MODIF_REF)
  1630. {
  1631. // if child is reference and parent is reference then create new local variable that will hold the address of the target child
  1632. // TODO:
  1633. compiler.msgs.New().error("ref to ref not yet supported", origin);
  1634. }else
  1635. {
  1636. symbol.modifiers|=Symbol::MODIF_REF; // parent is reference so it means we're still accessing the member through reference
  1637. }
  1638. }
  1639. }
  1640. }
  1641. return true; // success
  1642. }
  1643. /******************************************************************************/
  1644. Bool Expr::addressOf(Compiler &compiler) // this function performs address-of on self
  1645. {
  1646. Expr result, &func=result.func.New(); func.origin=origin; func.setOperator(u"&"); Swap(T, func.params.New());
  1647. Swap(result, T);
  1648. return calculate(compiler)>CAST_NONE;
  1649. }
  1650. Bool Expr::indirection(Compiler &compiler) // this function performs indirection on self
  1651. {
  1652. Expr result, &func=result.func.New(); func.origin=origin; func.setOperator(u"*"); Swap(T, func.params.New());
  1653. Swap(result, T);
  1654. return calculate(compiler)>CAST_NONE;
  1655. }
  1656. Bool Expr::copyCtor(Compiler &compiler)
  1657. {
  1658. Expr result, &func=result.func.New(); func.origin=origin;
  1659. if(symbol.basicType() && !symbol.isArray()) // operator=
  1660. {
  1661. func.setOperator(u"=");
  1662. func.params.setNum(2); // create params up-front so their memory is already allocated
  1663. Expr &a=func.params[0], &b=func.params[1]; // "a=b"
  1664. Swap(T, b);
  1665. b.copyThis(a);
  1666. a.temporary=true;
  1667. a.symbol.setConst(false); // disable const so it can be modified for further purpose
  1668. FlagDisable(a.symbol.modifiers, Symbol::MODIF_REF); // disable reference (we're copying to value and not reference)
  1669. a.mem.clear();
  1670. a.memNew(b.known(), compiler);
  1671. }else // class ctor call
  1672. if(!symbol.basicType() && symbol.isObj())
  1673. {
  1674. func.symbol=symbol;
  1675. func.symbol.setConst(false); // disable const so it can be modified for further purpose
  1676. FlagDisable(func.symbol.modifiers, Symbol::MODIF_REF); // disable reference (we're calling ctor)
  1677. Expr &a=func.params.New();
  1678. Swap(T, a);
  1679. func.memNew(false, compiler);
  1680. }else
  1681. {
  1682. compiler.msgs.New().error("Can't copy object", origin); return false;
  1683. }
  1684. Swap(result, T);
  1685. return calculate(compiler)>CAST_NONE;
  1686. }
  1687. void Expr::proceedToBase(Int base_index) // this function moves self to T.parent, and sets self as the child
  1688. {
  1689. if(symbol && InRange(base_index, symbol->base))
  1690. {
  1691. Symbol::Modif base=symbol->base[base_index]; base.proceedToFinal(&symbol.templates);
  1692. base.modifiers =symbol. modifiers; // keep modifiers (especially MODIF_REF) so that if parent is reference then the base is a reference too
  1693. base. ptr_level=symbol. ptr_level; // normally ptr_level should be zero, however keeping original value helps with auto-complete
  1694. base.const_level=symbol.const_level; // normally ptr_level should be zero, however keeping original value helps with auto-complete
  1695. base.array_dims =symbol.array_dims ; // normally ptr_level should be zero, however keeping original value helps with auto-complete
  1696. Expr child; copyThis(child); // copy all params to child (except parent, func, params)
  1697. Swap(child.parent.New(), T); // swap this with child.parent
  1698. Swap(child , T); // swap this with child
  1699. // now we operate on the child
  1700. BStr::clear(); // clear its value as we don't know it
  1701. memOffset(symbol->baseOffset(base_index));
  1702. symbol=base; // set child symbol
  1703. }
  1704. }
  1705. /******************************************************************************/
  1706. Bool Expr::setThis(Symbol *caller, Token *origin, Compiler &compiler)
  1707. {
  1708. BStr::setBorrowed(u"this");
  1709. T.symbol.clear(true);
  1710. T.origin=origin;
  1711. if(caller)
  1712. if(Symbol *func=caller->func())
  1713. if(func->isClassNonStaticFunc())
  1714. {
  1715. toSymbol(func->Class());
  1716. instance=true; symbol.const_level=FlagTest(func->modifiers, Symbol::MODIF_FUNC_CONST); // if the function is const "void func()const" then mark the data as const
  1717. mem.setThis();
  1718. }
  1719. if(!symbol)compiler.msgs.New().error(S+"'this' can be used only in non-static class methods", origin);
  1720. return symbol!=null;
  1721. }
  1722. void Expr::create(Token &src, Compiler &compiler, Bool final)
  1723. {
  1724. BStr &bs=T; bs=src;
  1725. T.symbol.clear(true);
  1726. T.final = final;
  1727. T.origin=&src;
  1728. switch(src.type)
  1729. {
  1730. case TOKEN_CHAR8 : setBasic(VAR_CHAR8 ); mem.setKnown(); break;
  1731. case TOKEN_CHAR16: setBasic(VAR_CHAR16); mem.setKnown(); break;
  1732. case TOKEN_TEXT8 : setBasic(VAR_CHAR8 ); temporary=false; symbol.const_level=1|2; symbol.array_dims.add(Symbol::DIM_UNKNOWN); break; // convert "" text8 to 'char8[]' (include null-terminating character, make the characters and the array pointer itself both constants "1|2")
  1733. case TOKEN_TEXT16: setBasic(VAR_CHAR16); temporary=false; symbol.const_level=1|2; symbol.array_dims.add(Symbol::DIM_UNKNOWN); break; // convert "" text to 'char []' (include null-terminating character, make the characters and the array pointer itself both constants "1|2")
  1734. case TOKEN_NUMBER:
  1735. {
  1736. VAR_TYPE type=VAR_NONE; REPA(bs)if(bs[i]=='.'){type=((bs.last()=='d') ? VAR_DBL : VAR_FLT); break;} // detect if real type
  1737. if(!type) // detect int type
  1738. {
  1739. ULong u=TextULong(asStr()); // the text never has any '-' so read as ulong
  1740. if( u<= INT_MAX )type=VAR_INT ;else
  1741. if( u<=UINT_MAX )type=VAR_UINT ;else
  1742. if( u<=0x7FFFFFFFFFFFFFFFull)type=VAR_LONG ;else // ULL = UNSIGNED LONG LONG
  1743. type=VAR_ULONG;
  1744. }
  1745. setBasic(type); mem.setKnown();
  1746. }break;
  1747. case TOKEN_OPERATOR: _operator=true; separator=(src=='.' || src=="->" || src=="::"); setPriority(); break;
  1748. default:
  1749. {
  1750. // check special symbols
  1751. if(src=="this" ){if(setThis(src.parent, &src, compiler))addressOf(compiler);}else
  1752. if(src=="true" ){setBasic(VAR_BOOL); mem.setKnown();}else
  1753. if(src=="false"){setBasic(VAR_BOOL); mem.setKnown();}else
  1754. if(src=="null" ){setBasic(VAR_NULL); mem.setKnown(); symbol.const_level=2; symbol.ptr_level=1;}else // make the pointer as constant (not the data to which it points to), always fit as KNOWN because 'null' is always zero
  1755. {
  1756. // TODO: detect enum value (set to BStr as Int)
  1757. toSymbol(src.symbol());
  1758. memAuto (compiler ); // set mem after setting the symbol
  1759. }
  1760. }break;
  1761. }
  1762. }
  1763. /******************************************************************************/
  1764. void Expr::copyThis(Expr &dest)
  1765. {
  1766. dest.set(T);
  1767. dest.instance=T.instance;
  1768. dest.final=T.final;
  1769. dest._operator=T._operator;
  1770. dest.separator=T.separator;
  1771. dest.l_to_r=T.l_to_r;
  1772. dest.temporary=T.temporary;
  1773. dest.conditional=T.conditional;
  1774. dest.func_call_mask=T.func_call_mask;
  1775. dest.priority=T.priority;
  1776. dest.symbol=T.symbol;
  1777. dest.symbol_origin=T.symbol_origin;
  1778. dest.origin=T.origin;
  1779. dest.func_call=T.func_call;
  1780. dest.mem=T.mem;
  1781. }
  1782. /******************************************************************************/
  1783. // FUNCTION MATCH
  1784. /******************************************************************************/
  1785. void FuncMatch::create(Symbol *func, Expr *param, Int params, Memc<Symbol::Modif> &templates, Compiler &compiler, Bool extra_match)
  1786. {
  1787. T.func=func;
  1788. average_match=(extra_match ? CAST_MAX+1 : CAST_NONE);
  1789. lowest_match=CAST_MAX;
  1790. FREP(Max(func->realParams(), params))
  1791. {
  1792. if(InRange(i, func->realParams()))
  1793. {
  1794. if(InRange(i, params)) // check match for param
  1795. {
  1796. Int param_match=param[i].canBeCastedTo(func->params[i](), templates, compiler);
  1797. // TODO: for lowest_match disallow casting to non-const "TYPE &" if src is not compatible
  1798. average_match+=param_match+1;
  1799. MIN(lowest_match, param_match);
  1800. }else
  1801. if(func->params[i]->modifiers&Symbol::MODIF_DEF_VALUE) // custom param is not specified but there is default value in the function param
  1802. {
  1803. // don't modify
  1804. }else // we haven't specified required param
  1805. {
  1806. average_match-=CAST_MAX+1;
  1807. lowest_match =CAST_NONE;
  1808. }
  1809. }else // we've specified a parameter too much (doesn't fit in func param list)
  1810. {
  1811. average_match-=CAST_MAX+1;
  1812. lowest_match =CAST_NONE;
  1813. }
  1814. }
  1815. }
  1816. void AddMatch(Memc<FuncMatch> &matches, Symbol *func, Bool l_to_r, Expr *param, Int params, Memc<Symbol::Modif> &templates, Compiler &compiler, Bool extra_match)
  1817. {
  1818. if(func && func->valid)
  1819. {
  1820. if(Symbol *parent=func->parent()) // func FUNC has "29386481" name, so check the FUNC_LIST parent
  1821. {
  1822. if(*parent=="operator*"
  1823. || *parent=="operator&"
  1824. || *parent=="operator+"
  1825. || *parent=="operator-")
  1826. {
  1827. if(func->params.elms()!=params)return; // above funcs/operators can be both unary/binary, so make additional check for the number of parameters (this is to avoid situations of for example "Rect rect; &rect" when wanting to get the address of the object using unary '&', but there is custom binary operator '&' of Rect&Rect format)
  1828. }else
  1829. if(*parent=="operator++"
  1830. || *parent=="operator--")
  1831. {
  1832. // OP | l_to_r | params (dummy "int" param)
  1833. // x++ | 1 | 1
  1834. // x-- | 1 | 1
  1835. // ++x | 0 | 0
  1836. // --x | 0 | 0
  1837. if(func->params.elms()!=Int(l_to_r))return;
  1838. }
  1839. }
  1840. matches.New().create(func, param, params, templates, compiler, extra_match);
  1841. }
  1842. }
  1843. void AddMatches(Memc<FuncMatch> &matches, Memc<SymbolPtr> &funcs, Bool l_to_r, Expr *param, Int params, Memc<Symbol::Modif> &templates, Compiler &compiler, Bool extra_match)
  1844. {
  1845. FREPA(funcs)AddMatch(matches, funcs[i](), l_to_r, param, params, templates, compiler, extra_match);
  1846. }
  1847. /******************************************************************************/
  1848. // COMPILER
  1849. /******************************************************************************
  1850. SAMPLE EXPRESSIONS:
  1851. S.
  1852. (S+S).
  1853. Map<Image,Data>.
  1854. Mems< Map<Image,Data> >.
  1855. Image x[20];
  1856. x[0].
  1857. func<temp>().
  1858. D.mode(320, 240).hdr(true).
  1859. TEMPLATE:
  1860. x.
  1861. x[].
  1862. x().
  1863. x<..>.
  1864. x<..>().
  1865. x[]().
  1866. (..).
  1867. OPERATORS:
  1868. UNARY : ~x !x x++ x-- ++x --x
  1869. *x &x +x -x (must be checked if token before *&+- operators isn't a value)
  1870. x(..) x[..] type(x)
  1871. (type)x
  1872. BINARY : a+b a.b a->b a::b a,b ..
  1873. TERNARY: a ? b : c
  1874. SORTED BY PRIORITY:
  1875. . -> ::
  1876. () [] <T T> x++ x--
  1877. ~ ! * & + - ++x --x (here '*' and '&' are indirection and address-of, and '+' and '-' are unary operators like "+x" or "-x")
  1878. (type) (cast)
  1879. .* ->*
  1880. * / %
  1881. + -
  1882. << >>
  1883. < > <= >=
  1884. == != === !!=
  1885. &
  1886. ^
  1887. |
  1888. &&
  1889. ^^
  1890. ||
  1891. "a ? b : c"
  1892. = *= /= %= += -= <<= >>= &= |= ^=
  1893. ,
  1894. TERNARY DESCRIPTION:
  1895. "a ? b ? c : d : e" == "a ? (b ? c : d) : e"
  1896. "a ? b : c ? d : e" == "a ? b : (c ? d : e)"
  1897. Expression templates are setup as follow:
  1898. 1. all root expressions ("ROOT.", ".ROOT.", "ROOT.NOT_ROOT") have all 'class_base_templates' from current class "space->Class()" (NOT_ROOT cannot have 'class_base_templates' because later when merging symbols "parent.child" child 'class_base_templates' would have overriden parent templates (which are in form 1.class_base_templates, 2.value base templates), and it would be 1.class_base_templates, 2.value base templates, 3.class_base_templates)
  1899. 2. then all expressions have their templates overriden by value class base templates
  1900. /******************************************************************************/
  1901. COMPILE_RESULT Compiler::compileExpr(Memc<Expr> &expr, Symbol *space, Expr &out)
  1902. {
  1903. IntLock lock(recursive); if(recursive>16){msgs.New().error("Compiler recursive loop", expr.elms() ? expr.first().origin : null); return COMPILE_FAILED;} // this can happen if calculating "int func(int par=func())" or "int f(int par=g()); int g(int par=f());"
  1904. Str temp;
  1905. Symbol *Class=(space ? space->Class() : null);
  1906. // merge < < and > > into << and >> (this can be done because at this stage all < > templates should be converted to TMPL_B and TMPL_E)
  1907. FREPA(expr)if(InRange(i+1, expr))if(expr[i]=='<' && expr[i+1]=='<'
  1908. || expr[i]=='>' && expr[i+1]=='>')
  1909. if(expr[i]()+1==expr[i+1]()) // if text pointers are after each other
  1910. {
  1911. expr[i].final|=expr[i+1].final;
  1912. expr[i].extend();
  1913. expr[i].setPriority();
  1914. expr.remove(i+1, true);
  1915. }
  1916. Memc<Symbol::Modif> class_base_templates;
  1917. if(Class)AddBaseTemplates(class_base_templates, *Class);
  1918. // setup templates and verify that already detected symbols indeed can be accessed
  1919. FREPA(expr)
  1920. {
  1921. Expr &e=expr[i], *prev=(InRange(i-1, expr) ? &expr[i-1] : null);
  1922. if(!(prev && prev->separator)) // if not preceeded by separator (check only root symbols, sub-symbols will be checked in the '.' merging)
  1923. {
  1924. FREPA(class_base_templates)e.symbol.templates.NewAt(i)=class_base_templates[i]; // set only for expressions not preceeded by separator (later below needs to be called for ".ROOT" too), add in this order because 'class_base_templates' need to be placed at start, to be least important
  1925. if(strict && e.symbol_origin && !e.symbol_origin->canBeAccessedFrom(space, space, false, ProjectUsings)){msgs.New().error("Symbol can't be accessed from current space", e.origin); return COMPILE_FAILED;} // this needs to be checked here because later access is checked only on detecting of unknown yet symbols
  1926. if(strict && !e.castParentToSymbolClass(T))return COMPILE_FAILED; // this will make sure that "member_var" have "this." parent set
  1927. }
  1928. }
  1929. // processing loop
  1930. for(; expr.elms(); )
  1931. {
  1932. Bool changed=false;
  1933. if(final>=0)REPA(expr)if(expr[i].knownFinal(allow_func_lists)){Swap(out, expr[i]); return COMPILE_FULL;}
  1934. // detect symbols
  1935. FREPA(expr)
  1936. {
  1937. Expr &e=expr[i];
  1938. if( !e.symbol) // not yet detected
  1939. {
  1940. if(!e._operator) // starts with name
  1941. {
  1942. Expr *prev=(InRange(i-1, expr) ? &expr[i-1] : null);
  1943. if( !(prev && prev->separator)) // if not preceeded by separator
  1944. {
  1945. if(Symbol *s=FindSymbol(temp=e, space, ProjectUsings)())
  1946. {
  1947. changed=true; e.toSymbol(s); if(e.knownFinal(allow_func_lists)){Swap(out, e); return COMPILE_FULL;}
  1948. if(strict && !e.symbol_origin->canBeAccessedFrom(space, space, false, ProjectUsings)){msgs.New().error("Symbol can't be accessed from current space", e.origin); return COMPILE_FAILED;}
  1949. e.memAuto(T); // set mem after setting the symbol
  1950. }
  1951. }
  1952. }else
  1953. if(e.separator) // encountered separator (this can be symbol with parent "obj.member" or global namespace "::EE::SomeFunc", this can also be object with base class specification "obj.Base<Str>::func")
  1954. {
  1955. Expr *prev =(InRange(i-1, expr) ? &expr[i-1] : null),
  1956. *prev2=(InRange(i-2, expr) ? &expr[i-2] : null);
  1957. if( !(prev && (*prev==']' || *prev==TMPL_E || (!prev->_operator && !prev->symbol)))) // don't process if it's ). ]. >. ?. (? = unknown symbol), however allow ")." if it's a cast "(TYPE).EE.SomeFunc" - perform additional checks below
  1958. if( !(prev2 && prev2->separator)) // if not preceeded by operator
  1959. {
  1960. if(prev && *prev==')') // test if we're preceeded by cast "(TYPE).x"
  1961. {
  1962. Expr *prev3=(InRange(i-3, expr) ? &expr[i-3] : null); // (
  1963. if(!(prev3 && *prev3=='(' && prev2 && prev2->symbol && (prev2->symbol->modifiers&Symbol::MODIF_DATA_TYPE) && !prev2->instance))continue; // if it's not a cast then continue the loop
  1964. }
  1965. if(prev && prev->instance && prev->symbol && prev->symbol.isObj() && e=="->") // check for overloaded -> operator
  1966. {
  1967. // TODO:
  1968. if(Symbol *s=FindChild("operator->", prev->symbol(), &prev->symbol.templates)())if(s->type==Symbol::FUNC_LIST && s->funcs.elms())
  1969. {
  1970. prev->final|=e.final;
  1971. prev->toSymbol(s->funcs[0](), true); MAX(--prev->symbol.ptr_level, 0); if(prev->knownFinal(allow_func_lists)){Swap(out, *prev); return COMPILE_FULL;}
  1972. e.setOperator(u"."); // replace "obj->" with "obj."
  1973. changed=true;
  1974. continue;
  1975. }
  1976. }
  1977. if(InRange(i+1, expr))
  1978. {
  1979. Expr &next=expr[i+1];
  1980. Symbol *s =next.symbol_origin;
  1981. Bool prev_is_parent=(prev && prev->symbol);
  1982. if(!s)
  1983. {
  1984. Bool allow_self=true;
  1985. Symbol *parent =(prev_is_parent ? prev->symbol() : null);
  1986. if(prev && (*prev=="super" || *prev=="__super")) // we're referring to an element of a base class (when checking against "super" name, use Expr::BStr and not the symbol, because symbol may point to the target class already)
  1987. {
  1988. Expr *prev_parent=prev->parent.data();
  1989. parent=(prev_parent ? prev_parent->symbol() : Class); // this can be "obj.super::method()", "super::method"
  1990. allow_self=false;
  1991. }
  1992. s=FindChild(temp=next, parent, prev_is_parent ? &prev->symbol.templates : null, true, allow_self)();
  1993. if(!s) // if not found
  1994. if(prev_is_parent && prev->symbol->type==Symbol::CLASS && *prev->symbol==temp())s=prev->symbol();else // check "X::X"
  1995. if(Equal(temp, "super", true) || Equal(temp, "__super", true) )s=Symbols("super");
  1996. }
  1997. if(s)
  1998. {
  1999. if(prev_is_parent)
  2000. {
  2001. {FREPA(prev->symbol.templates)next.symbol.templates.NewAt(i)=prev->symbol.templates[i];} // inherit all template informations from the parent (in correct order)
  2002. Swap(next.parent.New(), expr[i-1]); // store 'parent' into 'child' "parent.child"
  2003. }
  2004. next.final|=e.final; next.toSymbol(s); if(next.knownFinal(allow_func_lists)){Swap(out, next); return COMPILE_FULL;}
  2005. if(!prev_is_parent)FREPA(class_base_templates)next.symbol.templates.NewAt(i)=class_base_templates[i]; // we need to call this here for ".ROOT" cases, check above similar usage of 'class_base_templates'
  2006. // setup memory layout (don't setup mem for class specification ".Class" or "obj.Base<Str>::member" because as in example 'next' "Base" may be followed by template "Str", and since there can be multiple bases "Base<Str>, Base<Int>" then don't proceed to child yet)
  2007. if(strict)
  2008. {
  2009. if( next=="this"){msgs.New().error("Keyword can't be used as a child", next.origin); return COMPILE_FAILED;}
  2010. if(!prev_is_parent && !next.symbol_origin->canBeAccessedFrom(null, space, true, ProjectUsings)){msgs.New().error("Symbol can't be accessed from current space", next.origin); return COMPILE_FAILED;}
  2011. if(!next.castParentToSymbolClass(T))return COMPILE_FAILED;
  2012. if(!next.symbol_origin->isClassNonStaticMember() && !next.mem.type)next.memAuto(T); // global, class static, memAuto can be used
  2013. }
  2014. // remove expressions
  2015. expr.remove(i , true); // remove "."
  2016. if(prev_is_parent)expr.remove(i-1, true); // remove "parent" / 'prev'
  2017. changed=true;
  2018. }
  2019. }
  2020. }
  2021. }
  2022. }
  2023. }
  2024. // unary postfix operators
  2025. FREPA(expr)
  2026. {
  2027. Expr &op=expr[i];
  2028. if(op._operator)
  2029. if(op=="++" || op=="--") // x++ x--
  2030. if(InRange(i-1, expr))
  2031. {
  2032. Expr &value=expr[i-1];
  2033. if( value.instance)
  2034. {
  2035. Expr *prev=(InRange(i-2, expr) ? &expr[i-2] : null);
  2036. if( !(prev && prev->separator)) // if not preceeded by separator
  2037. {
  2038. Swap(op, value); // put operator as first
  2039. Expr &result=Func(expr, i-1, 1, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2040. changed=true;
  2041. }
  2042. }
  2043. }
  2044. }
  2045. // unary prefix operators
  2046. FREPA(expr)
  2047. {
  2048. Expr &op=expr[i];
  2049. if(op._operator)
  2050. if(op=='~' || op=='!' || op=='*' || op=='&' || op=='+' || op=='-' || op=="++" || op=="--") // ~x, !x, *x, &x, +x, -x, ++x, --x
  2051. if(InRange(i+1, expr))
  2052. {
  2053. // use custom priority and associativity because some operators are placed in different groups (*&+- and ++ --)
  2054. Int priority=UNARY_PRIORITY;
  2055. Bool l_to_r =false ;
  2056. Expr &value = expr[i+1],
  2057. *next_op =(InRange(i+2, expr) ? &expr[i+2] : null),
  2058. *prev_op =(InRange(i-1, expr) ? &expr[i-1] : null);
  2059. if(value.instance && !(prev_op && prev_op->possibleInstanceOrDataTypeOrNativeFunc())) // can't be preceeded by an instance (disallow: "int ++x" but allow: "return ++x")
  2060. if(!prev_op || ((l_to_r ? prev_op->priority< priority : prev_op->priority<=priority) || *prev_op=='{' || *prev_op=='(' || *prev_op=='[' || *prev_op==TMPL_B || *prev_op==')')) // allow special case of ')' which is checked later
  2061. if(!next_op || ((l_to_r ? next_op->priority<=priority : next_op->priority< priority) || *next_op=='}' || *next_op==')' || *next_op==']' || *next_op==TMPL_E))
  2062. {
  2063. if(prev_op && *prev_op==')') // test if we're preceeded by cast "(TYPE)&x"
  2064. {
  2065. Expr *type =(InRange(i-2, expr) ? &expr[i-2] : null), // TYPE
  2066. *prev_op2=(InRange(i-3, expr) ? &expr[i-3] : null); // (
  2067. if(!(prev_op2 && *prev_op2=='(' && type && type->symbol && (type->symbol->modifiers&Symbol::MODIF_DATA_TYPE) && !type->instance))continue; // if it's not a cast then continue the loop
  2068. }
  2069. // adjust operator parameters
  2070. op.l_to_r =l_to_r ;
  2071. op.priority=priority;
  2072. Expr &result=Func(expr, i, 1, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2073. changed=true;
  2074. }
  2075. }
  2076. }
  2077. // binary operators
  2078. FREPA(expr)
  2079. {
  2080. Expr &op=expr[i];
  2081. if(op._operator)
  2082. if(op=='*' || op=='/' || op=='%' || op=='+' || op=='-' || op=="<<" || op==">>" || op=='<' || op=='>' || op=="<=" || op==">=" || op=="==" || op=="!=" || op=="===" || op=="!!="
  2083. || op=='&' || op=='^' || op=='|' || op=="&&" || op=="^^" || op=="||"
  2084. || op=='=' || op=="*=" || op=="/=" || op=="%=" || op=="+=" || op=="-=" || op=="<<=" || op==">>=" || op=="&=" || op=="|=" || op=="^=")
  2085. if(InRange(i-1, expr)
  2086. && InRange(i+1, expr))
  2087. {
  2088. Expr &a = expr[i-1],
  2089. &b = expr[i+1],
  2090. *next_op=(InRange(i+2, expr) ? &expr[i+2] : null),
  2091. *prev_op=(InRange(i-2, expr) ? &expr[i-2] : null);
  2092. if(a.instance && b.instance)
  2093. if(!prev_op || ((op.l_to_r ? prev_op->priority< op.priority : prev_op->priority<=op.priority) || *prev_op=='{' || *prev_op=='(' || *prev_op=='[' || *prev_op==TMPL_B))
  2094. if(!next_op || ((op.l_to_r ? next_op->priority<=op.priority : next_op->priority< op.priority) || *next_op=='}' || *next_op==')' || *next_op==']' || *next_op==TMPL_E))
  2095. {
  2096. Swap(op, a); // put operator as first
  2097. Expr &result=Func(expr, i-1, 2, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2098. changed=true;
  2099. }
  2100. }
  2101. }
  2102. // ternary operators "a ? b : c"
  2103. FREPA(expr)
  2104. {
  2105. Expr &op=expr[i];
  2106. if( op=='?' && InRange(i-1, expr) && InRange(i+3, expr))
  2107. {
  2108. if(expr[i-1].instance && // a
  2109. // ?
  2110. expr[i+1].instance && // b
  2111. expr[i+2]==':' && // :
  2112. expr[i+3].instance) // c
  2113. {
  2114. Expr *prev_op=(InRange(i-2, expr) ? &expr[i-2] : null),
  2115. *next_op=(InRange(i+4, expr) ? &expr[i+4] : null);
  2116. if(!prev_op || ((op.l_to_r ? prev_op->priority< op.priority : prev_op->priority<=op.priority) || *prev_op=='{' || *prev_op=='(' || *prev_op=='[' || *prev_op==TMPL_B))
  2117. if(!next_op || ((op.l_to_r ? next_op->priority<=op.priority : next_op->priority< op.priority) || *next_op=='}' || *next_op==')' || *next_op==']' || *next_op==TMPL_E))
  2118. {
  2119. Swap(expr[i], expr[i-1]); // put operator as first, now it's "? a b : c"
  2120. expr.remove(i+2, true ); // remove ':' operatior , now it's "? a b c"
  2121. Expr &result=Func(expr, i-1, 3, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2122. changed=true;
  2123. }
  2124. }
  2125. }
  2126. }
  2127. // convert "(x)" to "x", only if not preceeded by TOKEN_CODE|TOKEN_KEYWORD, like int(x) || f(x) || f<T>(x) || f()() || f[]()
  2128. FREPA(expr)
  2129. {
  2130. if(expr[i ]=='(' && InRange(i+2, expr)
  2131. && expr[i+2]==')')
  2132. {
  2133. Expr *prev=(InRange(i-1, expr) ? &expr[i-1] : null);
  2134. if( !(prev && (prev->possibleInstanceOrDataTypeOrNativeFunc() || *prev==')' || *prev==']' || *prev==TMPL_E)))
  2135. {
  2136. Expr &type=expr[i+1], *next=(InRange(i+3, expr) ? &expr[i+3] : null);
  2137. if(type.symbol && (type.symbol->modifiers&Symbol::MODIF_DATA_TYPE) && !type.instance && next) // if it's actually a cast "(TYPE)x"
  2138. {
  2139. Expr *next2=(InRange(i+4, expr) ? &expr[i+4] : null);
  2140. if(next->instance)
  2141. {
  2142. if(!(next2 && (next2->separator || *next2=='(' || *next2=='[' || *next2==TMPL_B))) // don't cast yet when it's "(TYPE)x.", "(TYPE)x(", "(TYPE)x[", "(TYPE)x<"
  2143. {
  2144. type.instance=true;
  2145. expr.remove(i , true); // remove '('
  2146. expr.remove(i+1, true); // remove ')'
  2147. expr.remove(i+1, true); // remove src
  2148. changed=true;
  2149. }
  2150. }else
  2151. if(!strict && *next=='.' && !next2) // if not using strict T and we have "(TYPE)." and nothing afterwards (next2==null) then most probably we're just evaluating the symbol for '.' dot adjustment, so just remove the "(TYPE)" part to allow proper detection of the '.' as the "::" for the global namespace in the 'adjustDot' function (see more info there)
  2152. {
  2153. expr.remove(i, true); // remove '('
  2154. expr.remove(i, true); // remove TYPE
  2155. expr.remove(i, true); // remove ')'
  2156. changed=true;
  2157. }
  2158. }else
  2159. {
  2160. expr.remove(i , true); // remove '('
  2161. expr.remove(i+1, true); // remove ')'
  2162. changed=true;
  2163. }
  2164. }
  2165. }
  2166. }
  2167. // [] operators, like x[i]
  2168. FREPA(expr)
  2169. {
  2170. if(expr[i ]=='[' && InRange(i+2, expr)
  2171. && expr[i+2]==']' && InRange(i-1, expr))
  2172. {
  2173. Expr &value=expr[i-1];
  2174. if( value.instance)
  2175. {
  2176. Expr *prev=(InRange(i-2, expr) ? &expr[i-2] : null);
  2177. if( !(prev && prev->separator)) // if not preceeded by separator
  2178. {
  2179. expr[i].symbol.templates=expr[i-1].symbol.templates; // let "[]" operator have all 'x' object templates
  2180. Swap(expr[i-1], expr[i].parent.New()); // move the 'x' into [.parent
  2181. expr.remove(i-1, true); // remove the empty 'x', now it's "[ i ]"
  2182. expr[i-1].final|=expr[i+1].final; // ].final to [.final
  2183. expr[i-1].setBorrowed(u"[]"); // set [ into []
  2184. expr.remove(i+1, true); // remove ], now it's "[] i"
  2185. Expr &result=Func(expr, i-1, 1, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2186. changed=true;
  2187. }
  2188. }
  2189. }
  2190. }
  2191. // cast modifiers: (TYPE*), (TYPE&), (TYPE*&), (TYPE *const), (const TYPE), (const TYPE *const), (const TYPE<A,B>.B), (const .TYPE.A), ..
  2192. FREPA(expr)
  2193. {
  2194. Expr &type=expr[i];
  2195. if(type.symbol && (type.symbol->modifiers&Symbol::MODIF_DATA_TYPE) && !type.instance)
  2196. {
  2197. Expr *prev=(InRange(i-1, expr) ? &expr[i-1] : null);
  2198. if( !(prev && prev->separator)) // if not preceeded by separator
  2199. {
  2200. if(InRange(i+1, expr)) // check for "TYPE*", "TYPE&", "TYPE const"
  2201. {
  2202. Expr &modif=expr[i+1];
  2203. if(modif=='&' ){type.symbol. modifiers|=Symbol::MODIF_REF; expr.remove(i+1, true); changed=true;}else
  2204. if(modif=='*' ){type.symbol. ptr_level++; expr.remove(i+1, true); changed=true;}else
  2205. if(modif=="const"){type.symbol.const_level|=(1<<type.symbol.ptr_level); expr.remove(i+1, true); changed=true;}
  2206. }
  2207. if(prev && *prev=="const") // check for "const TYPE"
  2208. {
  2209. Expr *next=(InRange(i+1, expr) ? &expr[i+1] : null);
  2210. if( !(next && (next->separator || *next==TMPL_B))) // if not followed by separator or template
  2211. {
  2212. type.symbol.const_level|=1; expr.remove(i-1, true); changed=true; // add const to TYPE, remove 'const' expr
  2213. }
  2214. }
  2215. }
  2216. }
  2217. }
  2218. // templates like "A<X>", "A<X,Y>" (valid parameters are non-operators)
  2219. FREPA(expr)
  2220. {
  2221. if(expr[i]==TMPL_B && InRange(i-1, expr)) // 'i' points to '<'
  2222. {
  2223. Expr &templ=expr[i-1];
  2224. if( templ.symbol) // can be symbol of data type or function or native function
  2225. {
  2226. Expr *prev=(InRange(i-2, expr) ? &expr[i-2] : null);
  2227. if( !(prev && prev->separator)) // if not preceeded by separator
  2228. {
  2229. for(Int j=i+1, last_elm=-1; j<expr.elms(); j++) // last_elm: -1=start, 0=parameter, 1=comma(,)
  2230. {
  2231. Expr &param=expr[j];
  2232. if( param==',') // comma
  2233. {
  2234. if(last_elm==1) // if last element was comma
  2235. {
  2236. if(strict){msgs.New().error("Unexpected ','", param.origin); return COMPILE_FAILED;}
  2237. expr.NewAt(j++); // insert empty expression between last and current comma - ',', ' ', ',' and increase the 'j' index so we don't process the same comma again in next step
  2238. }else last_elm=1; // set last element to comma
  2239. }else
  2240. if(param==TMPL_E) // end
  2241. {
  2242. if(last_elm==1) // if last element was comma
  2243. {
  2244. if(strict){msgs.New().error("Unexpected ','", param.origin); return COMPILE_FAILED;}
  2245. expr.NewAt(j++); // insert empty expression between last comma and current '>' - ',', ' ', '>' and increase the 'j' index so it will still point to the '>'
  2246. }
  2247. // 'j' points to '>'
  2248. Expr &templ=expr[i-1]; // set 'templ' reference again because 'expr' addresses may have changed
  2249. templ.final|=expr[i].final; expr.remove(i, true); j--; // remove '<'
  2250. templ.final|=expr[j].final; expr.remove(j, true); j--; // remove '>'
  2251. for(Int k=j; k>=i; k--)if(expr[k]==','){templ.final|=expr[k].final; expr.remove(k, true); j--;} // remove ','
  2252. Int params=j-i+1;
  2253. Expr &result=Template(expr, i-1, params); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2254. changed=true;
  2255. break;
  2256. }else
  2257. if(!param._operator) // parameter
  2258. {
  2259. if(last_elm==0)break; // if last element was parameter then it means both parameters haven't been merged yet
  2260. last_elm=0; // set last element to parameter
  2261. }else
  2262. {
  2263. break; // invalid parameter
  2264. }
  2265. }
  2266. }
  2267. }
  2268. }
  2269. }
  2270. // function calls, constructors/casting, operator(), native-functions, like: f(x), f(a,b,c), int(x), Vec2(0,1), D.staticFunc(0), object(0), sizeof(..) (valid parameters are instances)
  2271. FREPA(expr)
  2272. {
  2273. if(expr[i]=='(' && InRange(i-1, expr)) // 'i' points to '('
  2274. {
  2275. Expr &func=expr[i-1];
  2276. if(func.instance // function or object for operator()
  2277. || (func.symbol && ((func.symbol->modifiers&Symbol::MODIF_DATA_TYPE) // constructor
  2278. || func.symbol->isNativeFunc()))) // native func
  2279. {
  2280. Bool size_of=(func=="sizeof");
  2281. Expr *prev=(InRange(i-2, expr) ? &expr[i-2] : null);
  2282. if( !(prev && prev->separator)) // if not preceeded by separator, needed because "D.mode(320,240)" could result into "D.D" if "mode(320,240)" would be computed before "D.mode"
  2283. {
  2284. for(Int j=i+1, last_elm=-1; j<expr.elms(); j++) // last_elm: -1=start, 0=parameter, 1=comma(,)
  2285. {
  2286. Expr &param=expr[j];
  2287. if( param==',') // comma
  2288. {
  2289. if(last_elm==1) // if last element was comma
  2290. {
  2291. if(strict){msgs.New().error("Unexpected ','", param.origin); return COMPILE_FAILED;}
  2292. expr.NewAt(j++); // insert empty expression between last and current comma - ',', ' ', ',' and increase the 'j' index so we don't process the same comma again in next step
  2293. }else last_elm=1; // set last element to comma
  2294. }else
  2295. if(param==')') // end
  2296. {
  2297. if(last_elm==1) // if last element was comma
  2298. {
  2299. if(strict){msgs.New().error("Unexpected ','", param.origin); return COMPILE_FAILED;}
  2300. expr.NewAt(j++); // insert empty expression between last comma and current ')' - ',', ' ', ')' and increase the 'j' index so it will still point to the ')'
  2301. }
  2302. // 'j' points to ')'
  2303. Expr &func=expr[i-1]; // set 'func' reference again because 'expr' addresses may have changed
  2304. func.final|=expr[i].final; expr.remove(i, true); j--; // remove '('
  2305. func.final|=expr[j].final; expr.remove(j, true); j--; // remove ')'
  2306. for(Int k=j; k>=i; k--)if(expr[k]==','){func.final|=expr[k].final; expr.remove(k, true); j--;} // remove ','
  2307. // check for operator()
  2308. if(func.instance && func.symbol && func.symbol->type!=Symbol::FUNC && func.symbol->type!=Symbol::FUNC_LIST && !func.symbol->isNativeFunc()) // if 'x' in "x(..)" is an object, then this is operator() call
  2309. {
  2310. Expr op; op.setOperator(u"()"); op.symbol.templates=func.symbol.templates; // let "()" operator have all 'x' object templates
  2311. Swap(func, op.parent.New()); // move 'func' (object ) into "op.parent"
  2312. Swap(func, op ); // move 'op' (operator) into 'expr' array at 'func' position
  2313. }
  2314. Int params=j-i+1;
  2315. Expr &result=Func(expr, i-1, params, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2316. changed=true;
  2317. break;
  2318. }else
  2319. if(param.instance || (size_of && param.symbol && (param.symbol->modifiers&Symbol::MODIF_DATA_TYPE))) // parameter (must be instance, however sizeof can accept data types as well)
  2320. {
  2321. if(last_elm==0)break; // if last element was parameter then it means both parameters haven't been merged yet
  2322. last_elm=0; // set last element to parameter
  2323. }else
  2324. {
  2325. break; // invalid parameter
  2326. }
  2327. }
  2328. }
  2329. }
  2330. }
  2331. }
  2332. // process binary comma ',' operators as last to avoid confusions with commas for function/template parameters "func(a,b)", "<a,b>" which would change into "func(b)", "<b>"
  2333. if(!changed)
  2334. FREPA(expr)
  2335. {
  2336. Expr &op=expr[i];
  2337. if(op._operator)
  2338. if(op==',')
  2339. if(InRange(i-1, expr)
  2340. && InRange(i+1, expr))
  2341. {
  2342. Expr &a = expr[i-1],
  2343. &b = expr[i+1],
  2344. *next_op=(InRange(i+2, expr) ? &expr[i+2] : null),
  2345. *prev_op=(InRange(i-2, expr) ? &expr[i-2] : null);
  2346. if(a.instance && b.instance)
  2347. if(!prev_op || ((op.l_to_r ? prev_op->priority< op.priority : prev_op->priority<=op.priority) || *prev_op=='{' || *prev_op=='(' || *prev_op=='[' /*|| *prev_op==TMPL_B*/)) // don't allow inside templates "<a,b>"
  2348. if(!next_op || ((op.l_to_r ? next_op->priority<=op.priority : next_op->priority< op.priority) || *next_op=='}' || *next_op==')' || *next_op==']' /*|| *next_op==TMPL_E*/))
  2349. {
  2350. if(prev_op && *prev_op=='(' && InRange(i-3, expr))
  2351. {
  2352. Expr &func=expr[i-3];
  2353. if(func.possibleInstanceOrDataTypeOrNativeFunc() || func==')' || func==']' || func==TMPL_E)continue; // disallow "func(a,b", "x()(a,b", "x[i](a,b", "func<t>(a,b"
  2354. }
  2355. // C++ comma operator "a,b" results in "return" of 2nd expression "b"
  2356. Swap(expr[i-1], expr[i]); // put operator as first, now it's ", a b"
  2357. Expr &result=Func(expr, i-1, 2, T); if(result.knownFinal(allow_func_lists)){Swap(out, result); return COMPILE_FULL;}
  2358. changed=true;
  2359. }
  2360. }
  2361. }
  2362. // end
  2363. if(!changed)break;
  2364. }
  2365. // return
  2366. if(expr.elms() && expr.last().separator && !strict) // if we were calculating "something x." then remove last separator (expressions which include the last separator are needed in case of "(TYPE*)obj." expressions, see comments in 'adjustDot' functions)
  2367. {
  2368. if(expr.elms()>=2)expr[expr.elms()-2].final|=expr.last().final; // merge final from last separator to expr before
  2369. expr.removeLast(); // remove last separator
  2370. }
  2371. if(final>=0) // if final was requested
  2372. {
  2373. REPA(expr)if(expr[i].final)
  2374. {
  2375. Swap(out, expr[i]);
  2376. return out.knownFinal(allow_func_lists) ? COMPILE_FULL : COMPILE_PARTIAL;
  2377. }
  2378. return COMPILE_FAILED;
  2379. }
  2380. if(expr.elms())
  2381. {
  2382. Swap(out, expr.last());
  2383. return (expr.elms()==1) ? COMPILE_FULL : COMPILE_PARTIAL;
  2384. }
  2385. return COMPILE_FAILED;
  2386. }
  2387. COMPILE_RESULT Compiler::compileTokens(Int from, Int to, Expr &out, Memc<Token*> *tokens)
  2388. {
  2389. Memc<Expr > expr;
  2390. Memc<Token*> &t=(tokens ? *tokens : T.tokens);
  2391. return appendTokens(expr, from, to, tokens) ? compileExpr(expr, t[from]->parent, out) : COMPILE_FAILED;
  2392. }
  2393. Bool Compiler::appendTokens(Memc<Expr> &expr, Int from, Int to, Memc<Token*> *tokens)
  2394. {
  2395. Memc<Token*> &t=(tokens ? *tokens : T.tokens);
  2396. if(InRange(from, t)
  2397. && InRange(to , t))
  2398. {
  2399. for(Int i=from; i<=to; i++)expr.New().create(*t[i], T, i==final);
  2400. return true;
  2401. }
  2402. return false;
  2403. }
  2404. /******************************************************************************/
  2405. }}
  2406. /******************************************************************************/