translator.bmx 58 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204
  1. ' Copyright (c) 2013-2025 Bruce A Henderson
  2. '
  3. ' Based on the public domain Monkey "trans" by Mark Sibly
  4. '
  5. ' This software is provided 'as-is', without any express or implied
  6. ' warranty. In no event will the authors be held liable for any damages
  7. ' arising from the use of this software.
  8. '
  9. ' Permission is granted to anyone to use this software for any purpose,
  10. ' including commercial applications, and to alter it and redistribute it
  11. ' freely, subject to the following restrictions:
  12. '
  13. ' 1. The origin of this software must not be misrepresented; you must not
  14. ' claim that you wrote the original software. If you use this software
  15. ' in a product, an acknowledgment in the product documentation would be
  16. ' appreciated but is not required.
  17. '
  18. ' 2. Altered source versions must be plainly marked as such, and must not be
  19. ' misrepresented as being the original software.
  20. '
  21. ' 3. This notice may not be removed or altered from any source
  22. ' distribution.
  23. '
  24. Global _trans:TTranslator
  25. Type TTranslator
  26. Field _app:TAppDecl
  27. Field outputFiles:TMap = New TMap
  28. Field indent$
  29. Field LINES:TStringList'=New TStringList
  30. Field unreachable:Int,broken:Int
  31. Field contLabelId:Int
  32. Field exitLabelId:Int
  33. 'Munging needs a big cleanup!
  34. Field globalMungScope:TMap = New TMap
  35. Field mungScope:TMap=New TMap'<TDecl>
  36. Field mungStack:TStackList=New TStackList'< StringMap<TDecl> >
  37. Field funcMungs:TMap=New TMap'<FuncDeclList>
  38. Field customVarStack:TStackList = New TStackList
  39. Field varStack:TStackList = New TStackList
  40. Field tryStack:TStackList = New TStackList
  41. Field loopTryStack:TStackList = New TStackList
  42. Field mungedScopes:TMap=New TMap'<StringSet>
  43. 'Field funcMungs:TFuncDeclList=New TFuncDeclList
  44. 'Field mungedFuncs:TMap=New Map
  45. Field localScopeStack:TStackList = New TStackList
  46. Field localScope:TStackList = New TStackList
  47. Field ind:Int
  48. Field debugOut:String
  49. Field processingReturnStatement:Int
  50. Field coverageFileInfo:TMap = New TMap
  51. Field coverageFunctionFileInfo:TMap = New TMap
  52. Method PushVarScope()
  53. varStack.Push customVarStack
  54. customVarStack = New TStackList
  55. End Method
  56. Method PopVarScope()
  57. customVarStack=TStackList(varStack.Pop())
  58. End Method
  59. Method PushLoopLocalStack(stmt:Object)
  60. ind :+ 1
  61. If DEBUG Then
  62. Emit "// --> STACK = " + ind
  63. End If
  64. localScope.Push stmt
  65. End Method
  66. Method PopLoopLocalStack()
  67. If DEBUG Then
  68. Emit "// <-- STACK = " + ind
  69. End If
  70. ind :- 1
  71. If ind < 0 Then
  72. InternalErr "TTranslator.PopLoopLocalStack"
  73. End If
  74. localScope.Pop
  75. End Method
  76. Method LoopLocalScopeDepth:Int(findStmt:TStmt)
  77. Local count:Int = 0
  78. For Local stmt:Object = EachIn localScope
  79. If TBlockDecl(stmt) = Null Then
  80. If findStmt And TTryBreakCheck(stmt) And findStmt <> TTryBreakCheck(stmt).stmt Then
  81. Continue
  82. End If
  83. Exit
  84. End If
  85. count :+ 1
  86. Next
  87. Return count
  88. End Method
  89. Method DumpLocalScope:Int()
  90. Print "DumpLocalScope:"
  91. For Local stmt:Object = EachIn localScope
  92. Print " " + stmt.ToString()
  93. Next
  94. End Method
  95. Method GetTopLocalLoop:TTryBreakCheck(findStmt:TStmt)
  96. For Local tbc:TTryBreakCheck = EachIn localScope
  97. If findStmt And findStmt <> tbc.stmt Then
  98. Continue
  99. End If
  100. Return tbc
  101. Next
  102. End Method
  103. Method PushLoopTryStack(stmt:Object)
  104. If loopTryStack.Length() = 0 Then
  105. ' Try statements can only be applied here to loops
  106. If TTryStmt(stmt) = Null Then
  107. loopTryStack.Push stmt
  108. End If
  109. Else
  110. loopTryStack.Push stmt
  111. End If
  112. End Method
  113. Method TryDownToBlockScopeCount:Int(endBlockType:Int)
  114. Local lastTry:Int
  115. Local firstBlock:Int
  116. Local count:Int
  117. For Local stmt:Object = EachIn localScope
  118. If TBlockDecl(stmt) Then
  119. If TBlockDecl(stmt).blockType & BLOCK_TRY_CATCH Then
  120. lastTry = count
  121. Else If TBlockDecl(stmt).blockType = endBlockType Then
  122. firstBlock = count
  123. Exit
  124. End If
  125. End If
  126. If TTryBreakCheck(stmt) Then
  127. Continue
  128. End If
  129. count :+ 1
  130. Next
  131. Return firstBlock - lastTry
  132. End Method
  133. Method PopLoopTryStack()
  134. loopTryStack.Pop
  135. End Method
  136. Method LoopTryDepth:Int(findStmt:TStmt)
  137. Local count:Int = 0
  138. For Local stmt:Object = EachIn loopTryStack
  139. If TTryStmt(stmt) = Null Then
  140. If findStmt And findStmt <> stmt Then
  141. Continue
  142. End If
  143. Exit
  144. End If
  145. count :+ 1
  146. Next
  147. Return count
  148. End Method
  149. Method LoopTryStmts:TTryStmt[](findStmt:TStmt)
  150. Local stmts:TTryStmt[]
  151. For Local stmt:Object = EachIn loopTryStack
  152. If TTryStmt(stmt) Then
  153. stmts :+ [TTryStmt(stmt)]
  154. Else
  155. If findStmt And findStmt <> stmt Then
  156. Continue
  157. End If
  158. Exit
  159. End If
  160. Next
  161. Return stmts
  162. End Method
  163. Method GetTopLoop:TTryBreakCheck(findStmt:TStmt)
  164. For Local tbc:TTryBreakCheck = EachIn loopTryStack
  165. If findStmt And findStmt <> tbc.stmt Then
  166. Continue
  167. End If
  168. Return tbc
  169. Next
  170. End Method
  171. Function TransManglePointer$( ty:TType )
  172. Local p:String
  173. If ty
  174. If ty._flags & TType.T_VAR Then
  175. p:+ "v"
  176. End If
  177. If ty._flags & TType.T_PTR Then
  178. p:+ "p"
  179. Else If ty._flags & TType.T_PTRPTR Then
  180. p:+ "pp"
  181. Else If ty._flags & TType.T_PTRPTRPTR Then
  182. p:+ "ppp"
  183. End If
  184. End If
  185. Return p
  186. End Function
  187. ' Function TransMangleType:String(ty:TType)
  188. ' Local p:String = TransManglePointer(ty)
  189. ' If TVoidType( ty ) Return "v"
  190. ' If TByteType( ty ) Return p + "b"
  191. ' If TShortType( ty ) Return p + "s"
  192. ' If TIntType( ty ) Return p + "i"
  193. ' If TUIntType( ty ) Return p + "u"
  194. ' If TFloatType( ty ) Return p + "f"
  195. ' If TDoubleType( ty ) Return p + "d"
  196. ' If TLongType( ty ) Return p + "l"
  197. ' If TULongType( ty ) Return p + "y"
  198. ' If TSizeTType( ty ) Return p + "z"
  199. ' If TFloat64Type( ty ) Return p + "h"
  200. ' If TFloat128Type( ty ) Return p + "k"
  201. ' If TInt128Type( ty ) Return p + "j"
  202. ' If TDouble128Type( ty ) Return p + "m"
  203. ' If TStringType( ty ) Return p + "S"
  204. ' If TWParamType( ty ) Return p + "W"
  205. ' If TLParamType( ty ) Return p + "L"
  206. ' If TLongIntType( ty ) Return p + "g"
  207. ' If TULongIntType( ty ) Return p + "G"
  208. ' If TArrayType( ty ) Then
  209. ' Return p + "a" + TransMangleType(TArrayType( ty ).elemType)
  210. ' End If
  211. ' If TObjectType( ty ) Then
  212. ' If Not TObjectType( ty ).classdecl.IsExtern()
  213. ' Local t:String = p + "T" + TObjectType( ty ).classDecl.ident
  214. ' ' handle case where class is also a template instance... and so on
  215. ' If TClassDecl(TObjectType(ty).classDecl) And TClassDecl(TObjectType(ty).classDecl).instArgs Then
  216. ' For Local ity:TType = EachIn TClassDecl(TObjectType(ty).classDecl).instArgs
  217. ' t :+ TransMangleType(ity)
  218. ' Next
  219. ' End If
  220. ' Return t
  221. ' Else
  222. ' If TObjectType( ty ).classdecl.IsInterface() Then
  223. ' Return p + "I" + TObjectType(ty).classDecl.ident
  224. ' ElseIf TObjectType( ty ).classdecl.IsStruct() Then
  225. ' Return p + "R" + TObjectType(ty).classDecl.ident
  226. ' Else
  227. ' Return p + "E" + TObjectType(ty).classDecl.ident
  228. ' End If
  229. ' End If
  230. ' End If
  231. ' If TFunctionPtrType( ty ) Then
  232. ' Local func:TFuncDecl = TFunctionPtrType( ty ).func
  233. ' Local s:String = "F" + MangleMethodArgs(func)
  234. ' ' For Local i:Int = 0 Until func.argDecls.length
  235. ' ' s :+ TransMangleType(func.argDecls[i].ty)
  236. ' ' Next
  237. ' Return s + "_" + TransMangleType(func.retType) + "_"
  238. ' End If
  239. ' If TEnumType( ty ) Return p + "e" + TEnumType( ty ).decl.ident
  240. ' Err "Unsupported type for name mangling : " + ty.ToString()
  241. ' End Function
  242. ' New internal, buffer-based worker
  243. Function TransMangleTypeToBuf(ty:TType, buf:TStringBuffer)
  244. Local p:String = TransManglePointer(ty)
  245. ' NOTE: Void does not get the pointer prefix (same behavior as original)
  246. If TVoidType(ty) Then
  247. buf.Append("v")
  248. Return
  249. End If
  250. If TByteType(ty) Then buf.Append(p).Append("b"); Return
  251. If TShortType(ty) Then buf.Append(p).Append("s"); Return
  252. If TIntType(ty) Then buf.Append(p).Append("i"); Return
  253. If TUIntType(ty) Then buf.Append(p).Append("u"); Return
  254. If TFloatType(ty) Then buf.Append(p).Append("f"); Return
  255. If TDoubleType(ty) Then buf.Append(p).Append("d"); Return
  256. If TLongType(ty) Then buf.Append(p).Append("l"); Return
  257. If TULongType(ty) Then buf.Append(p).Append("y"); Return
  258. If TSizeTType(ty) Then buf.Append(p).Append("z"); Return
  259. If TFloat64Type(ty) Then buf.Append(p).Append("h"); Return
  260. If TFloat128Type(ty) Then buf.Append(p).Append("k"); Return
  261. If TInt128Type(ty) Then buf.Append(p).Append("j"); Return
  262. If TDouble128Type(ty) Then buf.Append(p).Append("m"); Return
  263. If TStringType(ty) Then buf.Append(p).Append("S"); Return
  264. If TWParamType(ty) Then buf.Append(p).Append("W"); Return
  265. If TLParamType(ty) Then buf.Append(p).Append("L"); Return
  266. If TLongIntType(ty) Then buf.Append(p).Append("g"); Return
  267. If TULongIntType(ty) Then buf.Append(p).Append("G"); Return
  268. If TArrayType(ty) Then
  269. buf.Append(p).Append("a")
  270. TransMangleTypeToBuf(TArrayType(ty).elemType, buf)
  271. Return
  272. End If
  273. If TObjectType(ty) Then
  274. Local o:TObjectType = TObjectType(ty)
  275. If Not o.classDecl.IsExtern() Then
  276. buf.Append(p).Append("T").Append(o.classDecl.ident)
  277. ' If class is a template instance, append its instantiation argument manglings
  278. If TClassDecl(o.classDecl) And TClassDecl(o.classDecl).instArgs Then
  279. For Local ity:TType = EachIn TClassDecl(o.classDecl).instArgs
  280. TransMangleTypeToBuf(ity, buf)
  281. Next
  282. End If
  283. Return
  284. Else
  285. If o.classDecl.IsInterface() Then
  286. buf.Append(p).Append("I").Append(o.classDecl.ident)
  287. ElseIf o.classDecl.IsStruct() Then
  288. buf.Append(p).Append("R").Append(o.classDecl.ident)
  289. Else
  290. buf.Append(p).Append("E").Append(o.classDecl.ident)
  291. End If
  292. Return
  293. End If
  294. End If
  295. If TFunctionPtrType(ty) Then
  296. Local func:TFuncDecl = TFunctionPtrType(ty).func
  297. buf.Append("F").Append(MangleMethodArgs(func)).Append("_")
  298. TransMangleTypeToBuf(func.retType, buf)
  299. buf.Append("_")
  300. Return
  301. End If
  302. If TEnumType(ty) Then
  303. buf.Append(p).Append("e").Append(TEnumType(ty).decl.ident)
  304. Return
  305. End If
  306. Err "Unsupported type for name mangling : " + ty.ToString()
  307. End Function
  308. ' Backwards-compatible wrapper that still returns a String.
  309. Function TransMangleType:String(ty:TType)
  310. Local sb:TStringBuffer = New TStringBuffer
  311. TransMangleTypeToBuf(ty, sb)
  312. Return sb.ToString()
  313. End Function
  314. Method MangleMethod:String(fdecl:TFuncDecl)
  315. If (fdecl.IsMethod() And Not fdecl.ClassScope().IsStruct())Or fdecl.IsCtor() Then
  316. Return MangleMethodArgs(fdecl)
  317. Else
  318. Return MangleMethodRetType(fdecl) + MangleMethodArgs(fdecl)
  319. End If
  320. End Method
  321. Method MangleMethodRetType:String(fdecl:TFuncDecl)
  322. If fdecl.retType Then
  323. Return "_" + TransMangleType(fdecl.retType)
  324. Else
  325. Return "_v"
  326. End If
  327. End Method
  328. Function MangleMethodArgs:String(fdecl:TFuncDecl)
  329. Local s:TStringBuffer = New TStringBuffer
  330. For Local arg:TArgDecl = EachIn fdecl.argDecls
  331. If Not s.Length() Then
  332. s.Append( "_" )
  333. End If
  334. ' s.Append( TransMangleType(arg.ty) )
  335. TransMangleTypeToBuf(arg.ty, s)
  336. Next
  337. Return s.ToString()
  338. End Function
  339. Method equalsTorFunc:Int(classDecl:TClassDecl, func:TFuncDecl)
  340. If func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
  341. Return True
  342. End If
  343. Return False
  344. End Method
  345. Method equalsBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
  346. If func.equalsBuiltIn > -1 Then
  347. Return func.equalsBuiltIn
  348. End If
  349. If checked Or func.IdentLower() = "tostring" Or func.IdentLower() = "compare" Or func.IdentLower() = "sendmessage" Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Or func.IdentLower() = "hashcode" Then
  350. If classDecl.munged = "bbObjectClass" Then
  351. For Local decl:TFuncDecl = EachIn classDecl.Decls()
  352. If Not decl.IsSemanted() Then
  353. decl.Semant
  354. End If
  355. If decl.IdentLower() = func.IdentLower() Then
  356. Local res:Int = decl.EqualsFunc(func)
  357. If res Then
  358. func.equalsBuiltIn = True
  359. End If
  360. Return res
  361. End If
  362. Next
  363. End If
  364. If classDecl.superClass Then
  365. Return equalsBuiltInFunc(classDecl.superClass, func, True)
  366. End If
  367. End If
  368. func.equalsBuiltIn = False
  369. Return False
  370. End Method
  371. Method equalsIfcBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
  372. If checked Or func.IdentLower() = "delete" Then
  373. If classDecl.munged = "bbObjectClass" Then
  374. For Local decl:TFuncDecl = EachIn classDecl.Decls()
  375. If Not decl.IsSemanted() Then
  376. decl.Semant
  377. End If
  378. If decl.IdentLower() = func.IdentLower() Then
  379. Return decl.EqualsFunc(func)
  380. End If
  381. Next
  382. End If
  383. If classDecl.superClass Then
  384. Return equalsIfcBuiltInFunc(classDecl.superClass, func, True)
  385. End If
  386. End If
  387. Return False
  388. End Method
  389. Method MungFuncDecl( fdecl:TFuncDecl )
  390. If fdecl.munged Return
  391. Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
  392. If funcs
  393. For Local tdecl:TFuncDecl=EachIn funcs
  394. If fdecl.EqualsArgs( tdecl, True ) And fdecl.scope = tdecl.scope
  395. fdecl.munged=tdecl.munged
  396. Return
  397. EndIf
  398. Next
  399. Else
  400. funcs=New TFuncDeclList
  401. funcMungs.Insert fdecl.ident,funcs
  402. EndIf
  403. If fdecl.scope Then
  404. Local id:String = fdecl.ident
  405. If fdecl.attrs & FUNC_OPERATOR Then
  406. id = MungSymbol(id)
  407. End If
  408. fdecl.munged = fdecl.ParentScope().munged + "_" + id
  409. If Not equalsBuiltInFunc(fdecl.classScope(), fdecl) And Not fdecl.noMangle Then
  410. fdecl.munged :+ MangleMethod(fdecl)
  411. End If
  412. ' fields are lowercase with underscore prefix.
  413. ' a function pointer with FUNC_METHOD is a field function pointer.
  414. 'If TFieldDecl(fdecl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
  415. ' munged = "_" + munged.ToLower()
  416. 'End If
  417. Else
  418. fdecl.munged="bb_"+fdecl.ident
  419. End If
  420. funcs.AddLast fdecl
  421. End Method
  422. Method MungSymbol:String(sym:String)
  423. Select sym
  424. Case "*"
  425. Return "_mul"
  426. Case "/"
  427. Return "_div"
  428. Case "+"
  429. Return "_add"
  430. Case "-"
  431. Return "_sub"
  432. Case "&"
  433. Return "_and"
  434. Case "|"
  435. Return "_or"
  436. Case "~~"
  437. Return "_xor"
  438. Case "^"
  439. Return "_pow"
  440. Case ":*"
  441. Return "_muleq"
  442. Case ":/"
  443. Return "_diveq"
  444. Case ":+"
  445. Return "_addeq"
  446. Case ":-"
  447. Return "_subeq"
  448. Case ":&"
  449. Return "_andeq"
  450. Case ":|"
  451. Return "_oreq"
  452. Case ":~~"
  453. Return "_xoreq"
  454. Case ":^"
  455. Return "_poweq"
  456. Case "<"
  457. Return "_lt"
  458. Case "<="
  459. Return "_le"
  460. Case ">"
  461. Return "_gt"
  462. Case ">="
  463. Return "_ge"
  464. Case "="
  465. Return "_eq"
  466. Case "<>"
  467. Return "_ne"
  468. Case "mod"
  469. Return "_mod"
  470. Case "shl"
  471. Return "_shl"
  472. Case "shr"
  473. Return "_shr"
  474. Case ":mod"
  475. Return "_modeq"
  476. Case ":shl"
  477. Return "_shleq"
  478. Case ":shr"
  479. Return "_shreq"
  480. Case "[]"
  481. Return "_iget"
  482. Case "[]="
  483. Return "_iset"
  484. End Select
  485. Err "?? unknown symbol ?? : " + sym
  486. End Method
  487. Method MungDecl( decl:TDecl, addIfNotInScope:Int = False )
  488. If decl.munged Then
  489. ' ensure function args get into local scope correctly.
  490. If addIfNotInScope Then
  491. If Not mungScope.Contains( decl.munged ) Then
  492. mungScope.Insert(decl.munged, decl)
  493. End If
  494. End If
  495. Return
  496. End If
  497. Local fdecl:TFuncDecl=TFuncDecl( decl )
  498. ' apply mangling to methods and New (ctors)
  499. ' but don't apply mangling to function pointers
  500. If fdecl And fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
  501. MungFuncDecl( fdecl )
  502. Return
  503. End If
  504. Local id$=decl.ident
  505. Local munged:String
  506. 'this lot just makes output a bit more readable...
  507. ' Select ENV_LANG
  508. ' Case "js"
  509. ' If TModuleDecl( decl.scope ) Or TGlobalDecl( decl ) Or (fdecl And Not fdecl.IsMethod())
  510. ' munged=decl.ModuleScope().munged+"_"+id
  511. ' EndIf
  512. ' Case "as"
  513. ' If TModuleDecl( decl.scope )
  514. ' munged=decl.ModuleScope().munged+"_"+id
  515. ' EndIf
  516. ' Case "cs"
  517. ' If TClassDecl( decl )
  518. ' munged=decl.ModuleScope().munged+"_"+id
  519. ' EndIf
  520. ' Case "java"
  521. ' If TClassDecl( decl )
  522. ' munged=decl.ModuleScope().munged+"_"+id
  523. ' EndIf
  524. ' Case "cpp"
  525. If Not munged And TFuncDecl(decl) And TFuncDecl(decl).exported Then
  526. munged = id
  527. Else
  528. If TModuleDecl( decl.scope ) Or (TGlobalDecl(decl) And TModuleDecl(TGlobalDecl(decl).mscope))
  529. If TClassDecl(decl) And TClassDecl(decl).instArgs Then
  530. munged = "gimpl" + "_" + id
  531. Else
  532. munged=decl.ModuleScope().munged+"_"+id
  533. End If
  534. If TClassDecl(decl) And TClassDecl(decl).instArgs Then
  535. For Local ty:TType = EachIn TClassDecl(decl).instArgs
  536. munged :+ TransMangleType(ty)
  537. Next
  538. End If
  539. EndIf
  540. If TModuleDecl( decl )
  541. munged=decl.ModuleScope().munged+"_"+id
  542. EndIf
  543. End If
  544. ' End Select
  545. 'DebugStop
  546. If Not munged
  547. If TLocalDecl( decl )
  548. munged="bbt_"+id
  549. Else If TLoopLabelDecl(decl)
  550. munged = "_" + TLoopLabelDecl(decl).realIdent
  551. Else
  552. If decl.scope Then
  553. If TClassDecl(decl) And TClassDecl(decl).instArgs Then
  554. Local m:TStringBuffer = New TStringBuffer
  555. m.Append("gimpl").Append("_").Append(id)
  556. For Local ty:TType = EachIn TClassDecl(decl).instArgs
  557. ' m.Append(TransMangleType(ty))
  558. TransMangleTypeToBuf(ty, m)
  559. Next
  560. munged = m.ToString()
  561. Else
  562. munged = decl.scope.munged + "_" + id
  563. End If
  564. ' fields are lowercase with underscore prefix.
  565. ' a function pointer with FUNC_METHOD is a field function pointer.
  566. If TFieldDecl(decl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
  567. munged = "_" + munged.ToLower()
  568. End If
  569. Else
  570. munged="bb_"+id
  571. End If
  572. EndIf
  573. EndIf
  574. 'sanitize non-mung-able characters
  575. munged = TStringHelper.Sanitize(munged)
  576. Local scopeSearch:Int = 0
  577. If fdecl And Not fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
  578. scopeSearch = 1
  579. End If
  580. 'add an increasing number to identifier if already used
  581. If MungScopeContains( munged, scopeSearch )
  582. If TFuncDecl(decl) And TFuncDecl(decl).exported Then
  583. Err "Cannot export duplicate identifiers : " + decl.ident
  584. End If
  585. Local i:Int=1
  586. Repeat
  587. i:+1
  588. Until Not MungScopeContains( munged + i, scopeSearch )
  589. munged :+ i
  590. EndIf
  591. mungScope.Insert(munged, decl)
  592. If scopeSearch Then
  593. globalMungScope.Insert(munged, decl)
  594. End If
  595. decl.munged=munged
  596. ' a function pointers' real function is stored in "func" - need to set its munged to match the parent.
  597. If TValDecl(decl) Then
  598. If TFunctionPtrType(TValDecl(decl).ty) Then
  599. TFunctionPtrType(TValDecl(decl).ty).func.munged = munged
  600. End If
  601. End If
  602. End Method
  603. Method MungScopeContains:Int( munged:String, scopeSearch:Int )
  604. If Not scopeSearch Then
  605. Return mungScope.Contains( munged )
  606. End If
  607. Return globalMungScope.Contains( munged )
  608. End Method
  609. Rem
  610. Method MungDecl( decl:TDecl )
  611. If decl.munged Return
  612. Local fdecl:TFuncDecl=TFuncDecl( decl )
  613. If fdecl And fdecl.IsMethod() Then
  614. ' DebugStop
  615. MungFuncDecl( fdecl )
  616. Return
  617. End If
  618. Local id:String=decl.ident,munged$,scope$
  619. If TLocalDecl( decl )
  620. scope="$"
  621. munged="t_"+id
  622. Else If TClassDecl( decl )
  623. scope=""
  624. munged="c_"+id
  625. Else If TModuleDecl( decl )
  626. scope=""
  627. munged="bb_"+id
  628. Else If TClassDecl( decl.scope )
  629. scope=decl.scope.munged
  630. munged="m_"+id
  631. Else If TModuleDecl( decl.scope )
  632. 'If ENV_LANG="cs" Or ENV_LANG="java"
  633. ' scope=decl.scope.munged
  634. ' munged="g_"+id
  635. 'Else
  636. scope=""
  637. munged=decl.scope.munged+"_"+id
  638. 'EndIf
  639. Else
  640. InternalErr
  641. EndIf
  642. Local set:TMap=TMap(mungedScopes.ValueForKey( scope ))
  643. If set
  644. If set.Contains( munged.ToLower() )
  645. Local id:Int=1
  646. Repeat
  647. id :+ 1
  648. Local t$=munged+id
  649. If set.Contains( t.ToLower() ) Continue
  650. munged=t
  651. Exit
  652. Forever
  653. End If
  654. Else
  655. If scope="$"
  656. Print "OOPS2"
  657. InternalErr
  658. EndIf
  659. set=New TMap
  660. mungedScopes.Insert scope,set
  661. End If
  662. set.Insert munged.ToLower(), ""
  663. decl.munged=munged
  664. End Method
  665. End Rem
  666. Method Bra$( str$ )
  667. If str.StartsWith( "(" ) And str.EndsWith( ")" )
  668. Local n:Int=1
  669. For Local i:Int=1 Until str.Length-1
  670. Select str[i]
  671. Case Asc("(")
  672. n:+1
  673. Case Asc(")")
  674. n:-1
  675. If Not n Return "("+str+")"
  676. End Select
  677. Next
  678. If n=1 Return str
  679. ' If str.FindLast("(")<str.Find(")") Return str
  680. EndIf
  681. Return "("+str+")"
  682. End Method
  683. 'Utility C/C++ style...
  684. Method Enquote$( str$ )
  685. Return LangEnquote( str )
  686. End Method
  687. Method EscapeChars:String(str:String)
  688. If str Then
  689. Local found:Int = False
  690. For Local i:Int = 0 Until str.length
  691. If str[i] > 127 Then
  692. found = True
  693. Exit
  694. End If
  695. Next
  696. If Not found Then
  697. Return str
  698. End If
  699. Local s:String
  700. For Local i:Int = 0 Until str.length
  701. Local char:Int = str[i]
  702. If char < 128 Then
  703. s :+ Chr(char)
  704. Else
  705. s :+ "~~" + char + "~~"
  706. End If
  707. Next
  708. Return s
  709. End If
  710. End Method
  711. Method TransUnaryOp$( op$ )
  712. Select op
  713. Case "+" Return "+"
  714. Case "-" Return "-"
  715. Case "~~" Return op
  716. Case "not" Return "!"
  717. End Select
  718. InternalErr "TTranslator.TransUnaryOp"
  719. End Method
  720. Method TransBinaryOp$( op$,rhs$ )
  721. 'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
  722. op = mapSymbol(op)
  723. Select op
  724. Case "+","-"
  725. If rhs.StartsWith( op ) Return op+" "
  726. Return op
  727. Case "*","/" Return op
  728. Case "shl" Return "<<"
  729. Case "shr" Return ">>"
  730. Case "sar" Return ">>"
  731. Case "mod" Return " % "
  732. Case "and" Return " && "
  733. Case "or" Return " || "
  734. Case "=" Return "=="
  735. Case "<>" Return "!="
  736. Case "<","<=",">",">=" Return op
  737. Case "=<" Return "<="
  738. Case "=>" Return ">="
  739. Case "&","|" Return op
  740. Case "~~" Return "^"
  741. Case "<<", ">>" Return Op
  742. Case "%" Return Op
  743. End Select
  744. InternalErr "TTranslator.TransBinaryOp"
  745. End Method
  746. Method TransAssignOp$( op$ )
  747. op = mapSymbol(op)
  748. Select op
  749. Case ":mod" Return "%="
  750. Case ":shl" Return "<<="
  751. Case ":shr" Return ">>="
  752. Case ":sar" Return ">>="
  753. End Select
  754. Return op
  755. End Method
  756. Method ExprPri:Int( expr:TExpr )
  757. '
  758. '1=primary,
  759. '2=postfix
  760. '3=prefix
  761. '
  762. If TNewObjectExpr( expr )
  763. Return 3
  764. Else If TUnaryExpr( expr )
  765. Select TUnaryExpr( expr ).op
  766. Case "+","-","~~","not" Return 3
  767. End Select
  768. InternalErr "TTranslator.ExprPri"
  769. Else If TBinaryExpr( expr )
  770. Select TBinaryExpr( expr ).op
  771. Case "^" Return 4
  772. Case "*","/","mod","%" Return 5
  773. Case "+","-" Return 6
  774. Case "shl","shr", "sar","<<", ">>" Return 7
  775. Case "<","<=",">",">=", "=<", "=>" Return 8
  776. Case "=","<>" Return 9
  777. Case "&" Return 10
  778. Case "~~" Return 11
  779. Case "|" Return 12
  780. Case "and" Return 13
  781. Case "or" Return 14
  782. End Select
  783. InternalErr "TTranslator.ExprPri"
  784. EndIf
  785. Return 2
  786. End Method
  787. Method TransSubExpr$( expr:TExpr,pri:Int=2 )
  788. Local t_expr$=expr.Trans()
  789. 'If expr.exprType._flags & TTYPE.T_VAR Then
  790. ' t_expr = Bra("*" + t_expr)
  791. 'End If
  792. If ExprPri( expr )>pri t_expr=Bra( t_expr )
  793. Return t_expr
  794. End Method
  795. Method TransExprNS$( expr:TExpr )
  796. If TVarExpr( expr ) Return expr.Trans()
  797. If TConstExpr( expr ) Return expr.Trans()
  798. Return CreateLocal( expr )
  799. End Method
  800. Method CreateLocal$( expr:TExpr, init:Int = True, vol:Int = True )
  801. Local tmp:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr, True, , vol )
  802. MungDecl tmp
  803. Emit TransLocalDecl( tmp,expr, True, init )+";"
  804. EmitCoverage(_errInfo)
  805. EmitGDBDebug(_errInfo)
  806. Return tmp.munged
  807. End Method
  808. '***** Utility *****
  809. Method TransLocalDecl$( decl:TLocalDecl,init:TExpr, declare:Int = False, outputInit:Int = True ) Abstract
  810. Method TransGlobalDecl$( gdecl:TGlobalDecl ) Abstract
  811. Method EmitPushErr()
  812. End Method
  813. Method EmitSetErr( errInfo$ )
  814. End Method
  815. Method EmitPopErr()
  816. End Method
  817. '***** Declarations *****
  818. Method TransGlobal$( decl:TGlobalDecl ) Abstract
  819. Method TransField$( decl:TFieldDecl,lhs:TExpr ) Abstract
  820. Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr, sup:Int = False, scope:TScopeDecl = Null ) Abstract
  821. Method TransSuperFunc$( decl:TFuncDecl,args:TExpr[], scope:TScopeDecl ) Abstract
  822. '***** Expressions *****
  823. Method TransConstExpr$( expr:TConstExpr ) Abstract
  824. Method TransNewObjectExpr$( expr:TNewObjectExpr ) Abstract
  825. Method TransNewArrayExpr$( expr:TNewArrayExpr ) Abstract
  826. Method TransSelfExpr$( expr:TSelfExpr ) Abstract
  827. Method TransCastExpr$( expr:TCastExpr ) Abstract
  828. Method TransUnaryExpr$( expr:TUnaryExpr ) Abstract
  829. Method TransBinaryExpr$( expr:TBinaryExpr ) Abstract
  830. Method TransIndexExpr$( expr:TIndexExpr ) Abstract
  831. Method TransSliceExpr$( expr:TSliceExpr ) Abstract
  832. Method TransArrayExpr$( expr:TArrayExpr ) Abstract
  833. Method TransArraySizeExpr$ ( expr:TArraySizeExpr ) Abstract
  834. Method TransIntrinsicExpr$( decl:TDecl,expr:TExpr,args:TExpr[]=Null ) Abstract
  835. Method TransArgs$( args:TExpr[],decl:TFuncDecl, objParam:String = Null, objectNew:Int = False ) Abstract
  836. Method EmitDebugEnterScope(block:TBlockDecl) Abstract
  837. Method EmitLocalDeclarations(decl:TScopeDecl, v:TValDecl = Null) Abstract
  838. Method TransType$( ty:TType, ident:String, fpReturnTypeFunctionArgs:String = Null, fpReturnTypeClassFunc:Int = False) Abstract
  839. Method TransObject:String(decl:TScopeDecl, this:Int = False) Abstract
  840. Method BeginLocalScope()
  841. mungStack.Push mungScope
  842. mungScope:TMap=New TMap'<TDecl>
  843. ' mungedScopes.Insert "$",New TMap
  844. If opt_debug Then
  845. localScopeStack.Push localScope
  846. localScope = New TStackList
  847. End If
  848. End Method
  849. Method EndLocalScope()
  850. mungScope=TMap(mungStack.Pop())
  851. ' mungedScopes.Insert "$",Null
  852. If opt_debug Then
  853. localScope = TStackList(localScopeStack.Pop())
  854. End If
  855. End Method
  856. Rem
  857. Method MungMethodDecl( fdecl:TFuncDecl )
  858. If fdecl.munged Return
  859. If fdecl.overrides
  860. MungMethodDecl fdecl.overrides
  861. fdecl.munged=fdecl.overrides.munged
  862. Return
  863. EndIf
  864. Local funcs:=funcMungs.Get( fdecl.ident )
  865. If funcs
  866. For Local tdecl:=EachIn funcs
  867. If fdecl.EqualsArgs( tdecl )
  868. fdecl.munged=tdecl.munged
  869. Return
  870. EndIf
  871. Next
  872. Else
  873. funcs=New FuncDeclList
  874. funcMungs.Set fdecl.ident,funcs
  875. EndIf
  876. Local id:=fdecl.ident
  877. If mungedFuncs.Contains( id )
  878. Local n:=1
  879. Repeat
  880. n+=1
  881. id=fdecl.ident+String(n)
  882. Until Not mungedFuncs.Contains( id )
  883. EndIf
  884. mungedFuncs.Set id,fdecl
  885. fdecl.munged="p_"+id
  886. funcs.AddLast fdecl
  887. End
  888. End Rem
  889. '***** Simple statements *****
  890. 'Expressions
  891. Method TransStmtExpr$( expr:TStmtExpr )
  892. Local t$=expr.stmt.Trans()
  893. If t Emit t+";"
  894. Return expr.expr.Trans()
  895. End Method
  896. Method TransTemplateCast$( ty:TType,src:TType,expr$ )
  897. Return expr
  898. End Method
  899. Method TransVarExpr$( expr:TVarExpr )
  900. Local decl:TVarDecl=TVarDecl( expr.decl.actual )
  901. If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null )
  902. If TLocalDecl( decl ) Then
  903. If decl.ty._flags & TType.T_VAR Then
  904. Return "*" + decl.munged
  905. Else
  906. Return decl.munged
  907. End If
  908. End If
  909. If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),Null )
  910. If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
  911. InternalErr "TTranslator.TransVarExpr"
  912. End Method
  913. Method TransMemberVarExpr$( expr:TMemberVarExpr )
  914. Local decl:TVarDecl=TVarDecl( expr.decl.actual )
  915. If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr )
  916. If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),expr.expr )
  917. If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
  918. InternalErr "TTranslator.TransMemberVarExpr"
  919. End Method
  920. Method TransInvokeExpr$( expr:TInvokeExpr )
  921. Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
  922. If Not decl.munged Then
  923. MungDecl decl
  924. End If
  925. 'If (decl.attrs & FUNC_PTR) And (decl.attrs & FUNC_INIT) And Not expr.InvokedWithBraces Return decl.munged
  926. 'If ((decl.attrs & FUNC_PTR) Or (expr.decl.attrs & FUNC_PTR)) And Not expr.InvokedWithBraces Return decl.munged
  927. 'If Not expr.InvokedWithBraces And expr.IsRhs Return decl.munged
  928. ' if the call was a statement (even one written without parentheses), then invokedWithBraces is true
  929. ' so no complicated checks are needed here; if invokedWithBraces is false, this is definitely not a call
  930. If Not expr.InvokedWithBraces Then Return decl.munged
  931. If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null,expr.args )
  932. If processingReturnStatement = 1 Then
  933. If decl Then
  934. processingReturnStatement :+ 1
  935. Return CreateLocal(expr)
  936. End If
  937. Else
  938. Return TransFunc( TFuncDecl(decl),expr.args,Null )
  939. End If
  940. InternalErr "TTranslator.TransInvokeExpr"
  941. End Method
  942. Method TransInvokeMemberExpr$( expr:TInvokeMemberExpr )
  943. Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
  944. If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr,expr.args )
  945. If processingReturnStatement = 1 Then
  946. If decl Then
  947. processingReturnStatement :+ 1
  948. Return CreateLocal(expr)
  949. End If
  950. Else
  951. Return TransFunc( TFuncDecl(decl),expr.args,expr.expr )
  952. End If
  953. InternalErr "TTranslator.TransInvokeMemberExpr"
  954. End Method
  955. Method TransInvokeSuperExpr$( expr:TInvokeSuperExpr )
  956. Local decl:TFuncDecl=TFuncDecl( expr.origFuncDecl.actual ),t$
  957. If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr )
  958. If processingReturnStatement = 1 Then
  959. If decl Then
  960. processingReturnStatement :+ 1
  961. Return CreateLocal(expr)
  962. End If
  963. Else
  964. If decl Return TransSuperFunc( TFuncDecl( expr.funcDecl ),expr.args, expr.classScope )
  965. End If
  966. InternalErr "TTranslator.TransInvokeSuperExpr"
  967. End Method
  968. Method TransFuncCallExpr:String( expr:TFuncCallExpr )
  969. If TIndexExpr(expr.expr) And TArrayType(TIndexExpr(expr.expr).expr.exprType) And TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType) Then
  970. Local decl:TDecl = TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType).func.actual
  971. decl.Semant()
  972. expr.args=expr.CastArgs( expr.args,TFuncDecl(decl) )
  973. Return expr.expr.Trans() + TransArgs(expr.args, TFuncDecl(decl))
  974. End If
  975. ' hmmm, complicated - a function returning and invoking a function pointer...
  976. If TInvokeExpr(expr.expr) And TFunctionPtrType(TInvokeExpr(expr.expr).exprType) Then
  977. Local decl:TDecl = TFunctionPtrType(TInvokeExpr(expr.expr).exprType).func.actual
  978. decl.Semant()
  979. expr.args=expr.CastArgs( expr.args,TFuncDecl(decl) )
  980. Return expr.expr.Trans() + TransArgs(expr.args, TFuncDecl(decl))
  981. End If
  982. If TInvokeMemberExpr(expr.expr) Then
  983. Local decl:TFuncDecl = TFuncDecl(TInvokeMemberExpr(expr.expr).decl.actual)
  984. decl.Semant()
  985. Return expr.expr.Trans()
  986. End If
  987. InternalErr "TTranslator.TransFuncCallExpr"
  988. End Method
  989. Method TransExprStmt$( stmt:TExprStmt )
  990. Return stmt.expr.TransStmt()
  991. End Method
  992. Method TransAssignStmt$( stmt:TAssignStmt )
  993. If stmt.rhs Return stmt.lhs.TransVar()+TransAssignOp(stmt.op)+stmt.rhs.Trans()
  994. Return stmt.lhs.Trans()
  995. End Method
  996. Method TransReturnStmt$( stmt:TReturnStmt )
  997. Local t:TStringBuffer = New TStringBuffer(128)
  998. t.Append( "return" )
  999. unreachable=True
  1000. If stmt.expr Then
  1001. If TObjectType(stmt.expr.exprType) And TNullDecl(TObjectType(stmt.expr.exprType).classDecl) Then
  1002. If IsPointerType(stmt.fRetType, 0, TType.T_POINTER) Or IsNumericType(stmt.fRetType) Then
  1003. t.Append( " 0" )
  1004. End If
  1005. If TStringType(stmt.fRetType) Then
  1006. t.Append( " &bbEmptyString" )
  1007. End If
  1008. If TArrayType(stmt.fRetType) Then
  1009. t.Append( " &bbEmptyArray" )
  1010. End If
  1011. Else
  1012. If TObjectType(stmt.expr.exprType) And TObjectType(stmt.expr.exprType).classDecl.IsStruct() And TConstExpr(stmt.expr) And Not TConstExpr(stmt.expr).value Then
  1013. Local lvar:String = CreateLocal(stmt.expr)
  1014. t.Append( " " ).Append( lvar )
  1015. Else
  1016. Local s:String
  1017. ' cast to function return type
  1018. If TObjectType(stmt.fRetType) And Not TObjectType(stmt.fRetType).classDecl.IsStruct() Then
  1019. s :+ Bra(TransType(stmt.fRetType, ""))
  1020. End If
  1021. s :+ stmt.expr.Trans()
  1022. ' we have some temp variables that need to be freed before we can return
  1023. ' put the results into a new variable, and return that.
  1024. If customVarStack.Count() > 0 Then
  1025. If Not TFunctionPtrType( stmt.expr.exprType ) Then
  1026. Emit TransType(stmt.expr.exprType, "rt_") + " rt_ = " + s + ";"
  1027. Else
  1028. Emit TransType(stmt.expr.exprType, "rt_") + " = " + s + ";"
  1029. End If
  1030. t.Append( " rt_" )
  1031. Else
  1032. t.Append( " " ).Append( s )
  1033. End If
  1034. End If
  1035. End If
  1036. End If
  1037. FreeVarsIfRequired()
  1038. ' if this is a Delete() method, we need to call the dtor first
  1039. Local funcScope:TFuncDecl = _env.FuncScope()
  1040. If funcScope And funcScope.IdentLower() = "delete" Then
  1041. Local classScope:TClassDecl = funcScope.ClassScope()
  1042. If classScope Then
  1043. EmitClassDeclDeleteDtor(classScope)
  1044. End If
  1045. End If
  1046. Return t.ToString()
  1047. End Method
  1048. Method NextExitId:Int(bc:TTryBreakCheck)
  1049. If Not bc.exitId Then
  1050. exitLabelId :+ 1
  1051. bc.exitId = exitLabelId
  1052. End If
  1053. Return bc.exitId
  1054. End Method
  1055. Method NextContId:Int(bc:TTryBreakCheck)
  1056. If Not bc.contId Then
  1057. contLabelId :+ 1
  1058. bc.contId = contLabelId
  1059. End If
  1060. Return bc.contId
  1061. End Method
  1062. Method TransContinueStmt$( stmt:TContinueStmt )
  1063. Local returnStr:String
  1064. Local contLoop:TStmt
  1065. ' if we are continuing with a loop label, we'll need to find it in the stack
  1066. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1067. contLoop = TLoopLabelExpr(stmt.label).loop
  1068. End If
  1069. ' get Try statements in the stack in this loop
  1070. Local tryStmts:TTryStmt[] = LoopTryStmts(contLoop)
  1071. Local count:Int = tryStmts.length
  1072. Local nowUnreachable:Int = False
  1073. If count > 0 Then
  1074. Local bc:TTryBreakCheck = GetTopLoop(contLoop)
  1075. If bc Then
  1076. NextContId(bc)
  1077. For Local i:Int = 0 Until count
  1078. Emit "bbExLeave();"
  1079. If opt_debug Then Emit "bbOnDebugPopExState();"
  1080. ' in debug we also roll back scope from first Try in scope down to the loop scope itself
  1081. If opt_debug And (i = count - 1) And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1082. Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_LOOP)
  1083. For Local n:Int = 0 Until loopCount
  1084. Emit "bbOnDebugLeaveScope();"
  1085. Next
  1086. End If
  1087. If tryStmts[i].finallyStmt Then
  1088. Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("continue")
  1089. MungDecl returnLabelDecl
  1090. EmitFinallyJmp tryStmts[i].finallyStmt, returnLabelDecl
  1091. Emit TransLabel(returnLabelDecl)
  1092. End If
  1093. Next
  1094. Emit "goto " + TransLabelCont(bc, False)
  1095. Else
  1096. InternalErr "TTranslator.TransContinueStmt"
  1097. End If
  1098. Else
  1099. ' For debug builds, we need to rollback the local scope stack correctly
  1100. count = 0
  1101. If opt_debug And TLoopStmt(contLoop) And Not TLoopStmt(contLoop).block.IsNoDebug() Then
  1102. count = LoopLocalScopeDepth(contLoop)
  1103. End If
  1104. If count > 0 Then
  1105. Local bc:TTryBreakCheck = GetTopLocalLoop(contLoop)
  1106. If bc Then
  1107. NextContId(bc)
  1108. For Local i:Int = 0 Until count
  1109. Emit "bbOnDebugLeaveScope();"
  1110. Next
  1111. Emit "goto " + TransLabelCont(bc, False)
  1112. Else
  1113. InternalErr "TTranslator.TransContinueStmt"
  1114. End If
  1115. Else
  1116. If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1117. count = LoopLocalScopeDepth(Null)
  1118. End If
  1119. For Local i:Int = 0 Until count
  1120. Emit "bbOnDebugLeaveScope();"
  1121. Next
  1122. ' No Try statements in the stack here..
  1123. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1124. Emit "goto " + TransLoopLabelCont(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
  1125. Else
  1126. returnStr = "continue"
  1127. End If
  1128. End If
  1129. End If
  1130. unreachable = True
  1131. Return returnStr
  1132. End Method
  1133. Method TransBreakStmt$( stmt:TBreakStmt )
  1134. Local returnStr:String
  1135. Local brkLoop:TStmt
  1136. ' if we are exiting with a loop label, we'll need to find it in the stack
  1137. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1138. brkLoop = TLoopLabelExpr(stmt.label).loop
  1139. End If
  1140. ' get Try statements in the stack in this loop
  1141. Local tryStmts:TTryStmt[] = LoopTryStmts(brkLoop)
  1142. Local count:Int = tryStmts.length
  1143. Local nowUnreachable:Int = False
  1144. If count > 0 Then
  1145. Local bc:TTryBreakCheck = GetTopLoop(brkLoop)
  1146. If bc Then
  1147. NextExitId(bc)
  1148. For Local i:Int = 0 Until count
  1149. Emit "bbExLeave();"
  1150. If opt_debug Then Emit "bbOnDebugPopExState();"
  1151. ' in debug we also roll back scope from first Try in scope down to the loop scope itself
  1152. If opt_debug And (i = count - 1) And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1153. Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_LOOP)
  1154. For Local n:Int = 0 Until loopCount
  1155. Emit "bbOnDebugLeaveScope();"
  1156. Next
  1157. End If
  1158. If tryStmts[i].finallyStmt Then
  1159. Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("break")
  1160. MungDecl returnLabelDecl
  1161. EmitFinallyJmp tryStmts[i].finallyStmt, returnLabelDecl
  1162. Emit TransLabel(returnLabelDecl)
  1163. End If
  1164. Next
  1165. Emit "goto " + TransLabelExit(bc, False)
  1166. Else
  1167. InternalErr "TTranslator.TransBreakStmt"
  1168. End If
  1169. Else
  1170. ' For debug builds, we need to rollback the local scope stack correctly
  1171. count = 0
  1172. If opt_debug And TLoopStmt(brkLoop) And Not TLoopStmt(brkLoop).block.IsNoDebug() Then
  1173. count = LoopLocalScopeDepth(brkLoop)
  1174. End If
  1175. If count > 0 Then
  1176. Local bc:TTryBreakCheck = GetTopLocalLoop(brkLoop)
  1177. If bc Then
  1178. NextExitId(bc)
  1179. For Local i:Int = 0 Until count
  1180. Emit "bbOnDebugLeaveScope();"
  1181. Next
  1182. Emit "goto " + TransLabelExit(bc, False)
  1183. Else
  1184. InternalErr "TTranslator.TransBreakStmt"
  1185. End If
  1186. Else
  1187. If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1188. count = LoopLocalScopeDepth(Null)
  1189. End If
  1190. For Local i:Int = 0 Until count
  1191. Emit "bbOnDebugLeaveScope();"
  1192. Next
  1193. ' No Try statements in the stack here..
  1194. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1195. Emit "goto " + TransLoopLabelExit(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
  1196. Else
  1197. returnStr = "break"
  1198. End If
  1199. End If
  1200. End If
  1201. unreachable = True
  1202. broken :+ 1
  1203. Return returnStr
  1204. End Method
  1205. Method TransTryStmt$( stmt:TTryStmt )
  1206. End Method
  1207. Method EmitFinallyJmp(stmt:TFinallyStmt, returnLabel:TLoopLabelDecl) Abstract
  1208. Method TransThrowStmt$( stmt:TThrowStmt )
  1209. End Method
  1210. Method TransBuiltinExpr$( expr:TBuiltinExpr )
  1211. If TAscExpr(expr) Return TransAscExpr(TAscExpr(expr))
  1212. If TChrExpr(expr) Return TransChrExpr(TChrExpr(expr))
  1213. If TLenExpr(expr) Return TransLenExpr(TLenExpr(expr))
  1214. If TSizeOfExpr(expr) Return TransSizeOfExpr(TSizeOfExpr(expr))
  1215. If TStackAllocExpr(expr) Return TransStackAllocExpr(TStackAllocExpr(expr))
  1216. If TFieldOffsetExpr(expr) Return TransFieldOffsetExpr(TFieldOffsetExpr(expr))
  1217. Err "TODO : TransBuiltinExpr()"
  1218. End Method
  1219. Method TransAscExpr:String(expr:TAscExpr)
  1220. End Method
  1221. Method TransChrExpr:String(expr:TChrExpr)
  1222. End Method
  1223. Method TransLenExpr:String(expr:TLenExpr)
  1224. End Method
  1225. Method TransSizeOfExpr:String(expr:TSizeOfExpr)
  1226. End Method
  1227. Method TransStackAllocExpr:String(expr:TStackAllocExpr)
  1228. End Method
  1229. Method TransFieldOffsetExpr:String(expr:TFieldOffsetExpr)
  1230. End Method
  1231. Method TransIdentTypeExpr:String(expr:TIdentTypeExpr) Abstract
  1232. Method TransLabelCont:String(bc:TTryBreakCheck, jmp:Int = True)
  1233. If jmp Then
  1234. Return "_contjmp" + bc.contId + ": ;"
  1235. Else
  1236. Return "_contjmp" + bc.contId + ";"
  1237. End If
  1238. End Method
  1239. Method TransLabelExit:String(bc:TTryBreakCheck, jmp:Int = True)
  1240. If jmp Then
  1241. Return "_exitjmp" + bc.exitId + ": ;"
  1242. Else
  1243. Return "_exitjmp" + bc.exitId + ";"
  1244. End If
  1245. End Method
  1246. Method TransLoopLabelCont:String(id:String, jmp:Int = True)
  1247. If jmp Then
  1248. Return "_loopcont_" + id.ToLower() + ": ;"
  1249. Else
  1250. Return "_loopcont_" + id.ToLower() + ";"
  1251. End If
  1252. End Method
  1253. Method TransLoopLabelExit:String(id:String, jmp:Int = True)
  1254. If jmp Then
  1255. Return "_loopexit_" + id.ToLower() + ": ;"
  1256. Else
  1257. Return "_loopexit_" + id.ToLower() + ";"
  1258. End If
  1259. End Method
  1260. Method TransLabel:String(labelDecl:TLoopLabelDecl)
  1261. Return labelDecl.munged + ":;"
  1262. End Method
  1263. '***** Block statements - all very C like! *****
  1264. Method Emit( t$, useIndent:Int = True )
  1265. If Not t Return
  1266. If useIndent
  1267. If t.StartsWith( "}" )
  1268. indent=indent[..indent.Length-1]
  1269. EndIf
  1270. End If
  1271. LINES.AddLast indent+t
  1272. 'code+=indent+t+"~n"
  1273. If useIndent
  1274. If t.EndsWith( "{" )
  1275. indent:+"~t"
  1276. EndIf
  1277. End If
  1278. End Method
  1279. Method JoinLines$( file:String )
  1280. Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
  1281. If _lines Then
  1282. Local code$=_lines.Join( "~n" )
  1283. _lines.Clear
  1284. Return code
  1285. End If
  1286. End Method
  1287. 'returns and resets unreachable status
  1288. Method EmitBlock:Int( block:TBlockDecl )
  1289. Local stmtCount:Int
  1290. 'DebugStop
  1291. 'If ENV_CONFIG="debug"
  1292. ' If TFuncDecl( block ) EmitPushErr
  1293. 'EndIf
  1294. PushEnv block
  1295. ' enter scope
  1296. If opt_debug And Not block.IsNoDebug() And Not block.generated Then
  1297. PushLoopLocalStack(block)
  1298. EmitDebugEnterScope(block)
  1299. End If
  1300. For Local stmt:TStmt=EachIn block.stmts
  1301. _errInfo=stmt.errInfo
  1302. If unreachable
  1303. ' Statements following cannot be reached - maybe we have Returned, etc
  1304. ' So don't process any more for this block - they won't be generated now!
  1305. Exit
  1306. EndIf
  1307. Rem
  1308. If ENV_CONFIG="debug"
  1309. Local rs:TReturnStmt=TReturnStmt( stmt )
  1310. If rs
  1311. If rs.expr
  1312. EmitSetErr stmt.errInfo
  1313. Local t_expr$=TransExprNS( rs.expr )
  1314. EmitPopErr
  1315. Emit "return "+t_expr+";"
  1316. Else
  1317. EmitPopErr
  1318. Emit "return;"
  1319. EndIf
  1320. unreachable=True
  1321. Continue
  1322. EndIf
  1323. EmitSetErr stmt.errInfo
  1324. EndIf
  1325. End Rem
  1326. If opt_debug And Not block.IsNoDebug() Then
  1327. ' only for user-made code
  1328. If Not stmt.generated Then
  1329. EmitDebugStmtErrInfo(stmt.errInfo, stmtCount)
  1330. stmtCount :+ 1
  1331. End If
  1332. End If
  1333. EmitCoverage(stmt)
  1334. EmitGDBDebug(stmt)
  1335. If TReturnStmt(stmt) And Not tryStack.IsEmpty() Then
  1336. processingReturnStatement = 1
  1337. End If
  1338. Local t$=stmt.Trans()
  1339. processingReturnStatement = 0
  1340. If TReturnStmt(stmt) Then
  1341. Local stackSize:Int = tryStack.Count()
  1342. Local count:Int
  1343. If stackSize Then
  1344. For Local tryStmt:TTryStmt = EachIn tryStack
  1345. Emit "bbExLeave();"
  1346. If opt_debug Then Emit "bbOnDebugPopExState();"
  1347. ' in debug we need to roll back scope from first Try in scope down to the function scope
  1348. If opt_debug And (count = stackSize - 1) And Not block.IsNoDebug() Then
  1349. Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_FUNCTION)
  1350. For Local n:Int = 0 Until loopCount
  1351. Emit "bbOnDebugLeaveScope();"
  1352. Next
  1353. End If
  1354. If tryStmt.finallyStmt Then
  1355. Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("return")
  1356. MungDecl returnLabelDecl
  1357. EmitFinallyJmp tryStmt.finallyStmt, returnLabelDecl
  1358. Emit TransLabel(returnLabelDecl)
  1359. End If
  1360. count :+ 1
  1361. Next
  1362. Else
  1363. If opt_debug And Not block.IsNoDebug() Then
  1364. For Local b:TBlockDecl = EachIn localScope
  1365. Emit "bbOnDebugLeaveScope();"
  1366. Next
  1367. End If
  1368. End If
  1369. End If
  1370. If t Emit t+";"
  1371. If DEBUG And debugOut Then
  1372. Emit debugOut
  1373. debugOut = Null
  1374. End If
  1375. Local v:String = String(customVarStack.Pop())
  1376. While v
  1377. Emit "bbMemFree" + Bra(v) + ";"
  1378. v = String(customVarStack.Pop())
  1379. Wend
  1380. Next
  1381. If opt_debug And Not block.IsNoDebug() And Not block.generated Then
  1382. PopLoopLocalStack()
  1383. If Not unreachable Then
  1384. Emit "bbOnDebugLeaveScope();"
  1385. End If
  1386. End If
  1387. Local r:Int=unreachable
  1388. unreachable=False
  1389. PopEnv
  1390. Return r
  1391. End Method
  1392. Method TransDeclStmt$( stmt:TDeclStmt, declare:Int = False )
  1393. Local decl:TLocalDecl=TLocalDecl( stmt.decl )
  1394. If decl
  1395. MungDecl decl
  1396. ' only generate local declarations once.
  1397. If decl.generated Then
  1398. If Not decl.done Then
  1399. decl.done = True
  1400. Else
  1401. Return ""
  1402. End If
  1403. End If
  1404. Return TransLocalDecl( decl,decl.init, decl.generated Or declare )
  1405. EndIf
  1406. Local cdecl:TConstDecl=TConstDecl( stmt.decl )
  1407. If cdecl
  1408. Return Null
  1409. EndIf
  1410. Local gdecl:TGlobalDecl=TGlobalDecl( stmt.decl )
  1411. If gdecl Then
  1412. MungDecl gdecl
  1413. If gdecl.inited Return Null
  1414. Return TransGlobalDecl( gdecl )
  1415. End If
  1416. InternalErr "TTranslator.TransDeclStmt"
  1417. End Method
  1418. Method TransIfStmt$( stmt:TIfStmt )
  1419. If TConstExpr( stmt.expr )
  1420. If TConstExpr( stmt.expr ).value
  1421. Emit "{"
  1422. EmitLocalDeclarations(stmt.thenBlock)
  1423. If EmitBlock( stmt.thenBlock ) unreachable=True
  1424. Emit "}"
  1425. Else If stmt.elseBlock And stmt.elseBlock.stmts.First()
  1426. Emit "{"
  1427. EmitLocalDeclarations(stmt.elseBlock)
  1428. If EmitBlock( stmt.elseBlock ) unreachable=True
  1429. Emit "}"
  1430. EndIf
  1431. Else If stmt.elseBlock And stmt.elseBlock.stmts.First()
  1432. Emit "if"+Bra( stmt.expr.Trans() )+"{"
  1433. EmitLocalDeclarations(stmt.thenBlock)
  1434. FreeVarsIfRequired(False)
  1435. PushVarScope
  1436. Local unr:Int=EmitBlock( stmt.thenBlock )
  1437. PopVarScope
  1438. Emit "}else{"
  1439. EmitLocalDeclarations(stmt.elseBlock)
  1440. FreeVarsIfRequired
  1441. Local unr2:Int=EmitBlock( stmt.elseBlock )
  1442. Emit "}"
  1443. If unr And unr2 unreachable=True
  1444. Else
  1445. ' Emit "if"+ Bra(TransCondition(stmt.expr)) + "{"
  1446. ' If TVarExpr(stmt.expr) Then
  1447. ' If TObjectType(TVarExpr(stmt.expr).exprType) Then
  1448. ' Emit "if"+Bra( stmt.expr.Trans() + "!= &bbNullObject") + "{"
  1449. ' Else If TStringType(TVarExpr(stmt.expr).exprType) Then
  1450. ' Emit "if"+Bra( stmt.expr.Trans() + "!= &bbEmptyString") + "{"
  1451. ' Else
  1452. ' Emit "if"+Bra( stmt.expr.Trans() )+"{"
  1453. ' End If
  1454. ' Else
  1455. Emit "if"+Bra( stmt.expr.Trans() )+"{"
  1456. FreeVarsIfRequired(False)
  1457. ' End If
  1458. EmitLocalDeclarations(stmt.thenBlock)
  1459. PushVarScope
  1460. Local unr:Int=EmitBlock( stmt.thenBlock )
  1461. PopVarScope
  1462. Emit "}"
  1463. FreeVarsIfRequired
  1464. EndIf
  1465. End Method
  1466. Method FreeVarsIfRequired(removeFromStack:Int = True)
  1467. If removeFromStack
  1468. Local v:String = String(customVarStack.Pop())
  1469. While v
  1470. Emit "bbMemFree" + Bra(v) + ";"
  1471. v = String(customVarStack.Pop())
  1472. Wend
  1473. Else
  1474. For Local v:String = EachIn customVarStack
  1475. Emit "bbMemFree" + Bra(v) + ";"
  1476. Next
  1477. End If
  1478. End Method
  1479. ' Method TransCondition:String(expr:TExpr)
  1480. ' If TVarExpr(expr) Then
  1481. ' If TObjectType(TVarExpr(expr).exprType) Then
  1482. ' Return Bra( expr.Trans() + "!= &bbNullObject")
  1483. ' Else If TStringType(TVarExpr(expr).exprType) Then
  1484. ' Return Bra( expr.Trans() + "!= &bbEmptyString")
  1485. ' Else
  1486. ' Return Bra( expr.Trans() )
  1487. ' End If
  1488. ' Else
  1489. ' Return Bra( expr.Trans() )
  1490. ' End If
  1491. ' End Method
  1492. Method TransWhileStmt$( stmt:TWhileStmt )
  1493. Local nbroken:Int=broken
  1494. Emit "while"+Bra( stmt.expr.Trans() )+"{"
  1495. Local check:TTryBreakCheck = New TTryBreakCheck
  1496. check.stmt = stmt
  1497. PushLoopTryStack(check)
  1498. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1499. PushLoopLocalStack(check)
  1500. End If
  1501. EmitLocalDeclarations(stmt.block)
  1502. Local unr:Int=EmitBlock( stmt.block )
  1503. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1504. PopLoopLocalStack
  1505. End If
  1506. PopLoopTryStack
  1507. If check.contId Then
  1508. Emit TransLabelCont(check)
  1509. End If
  1510. If stmt.loopLabel Then
  1511. MungDecl stmt.loopLabel
  1512. Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
  1513. End If
  1514. Emit "}"
  1515. If check.exitId Then
  1516. Emit TransLabelExit(check)
  1517. End If
  1518. If stmt.loopLabel Then
  1519. Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
  1520. End If
  1521. If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
  1522. broken=nbroken
  1523. End Method
  1524. Method TransRepeatStmt$( stmt:TRepeatStmt )
  1525. Local nbroken:Int=broken
  1526. SetOutputTemp()
  1527. Emit "do{"
  1528. Local check:TTryBreakCheck = New TTryBreakCheck
  1529. check.stmt = stmt
  1530. PushLoopTryStack(check)
  1531. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1532. PushLoopLocalStack(check)
  1533. End If
  1534. EmitLocalDeclarations(stmt.block)
  1535. Local unr:Int=EmitBlock( stmt.block )
  1536. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1537. PopLoopLocalStack
  1538. End If
  1539. PopLoopTryStack
  1540. If check.contId Then
  1541. Emit TransLabelCont(check)
  1542. End If
  1543. If stmt.loopLabel Then
  1544. MungDecl stmt.loopLabel
  1545. Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
  1546. End If
  1547. SetOutput("source")
  1548. Local s:String = "}while(!"+Bra( stmt.expr.Trans() )+");"
  1549. SetOutputTemp(True)
  1550. Emit s
  1551. If check.exitId Then
  1552. Emit TransLabelExit(check)
  1553. End If
  1554. If stmt.loopLabel Then
  1555. Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
  1556. End If
  1557. If broken=nbroken And TConstExpr( stmt.expr ) And Not TConstExpr( stmt.expr ).value unreachable=True
  1558. broken=nbroken
  1559. End Method
  1560. Method TransForStmt$( stmt:TForStmt )
  1561. Local nbroken:Int=broken
  1562. Local init$
  1563. Local decl:Int
  1564. Local vdecl:TValDecl
  1565. If TDeclStmt(stmt.init) Then
  1566. decl = True
  1567. Emit "{"
  1568. Emit TransDeclStmt(TDeclStmt(stmt.init), True) + ";"
  1569. 'init = TDeclStmt(stmt.init).decl.munged
  1570. vdecl = TValDecl(TDeclStmt(stmt.init).decl)
  1571. Else
  1572. init=stmt.init.Trans()
  1573. End If
  1574. Local expr$=stmt.expr.Trans()
  1575. Local incr$=stmt.incr.Trans()
  1576. Emit "for("+init+";"+expr+";"+incr+"){"
  1577. Local check:TTryBreakCheck = New TTryBreakCheck
  1578. check.stmt = stmt
  1579. PushLoopTryStack(check)
  1580. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1581. PushLoopLocalStack(check)
  1582. End If
  1583. EmitLocalDeclarations(stmt.block, vdecl)
  1584. Local unr:Int=EmitBlock( stmt.block )
  1585. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1586. PopLoopLocalStack
  1587. End If
  1588. PopLoopTryStack
  1589. If check.contId Then
  1590. Emit TransLabelCont(check)
  1591. End If
  1592. If stmt.loopLabel Then
  1593. MungDecl stmt.loopLabel
  1594. Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
  1595. End If
  1596. Emit "}"
  1597. If decl Then
  1598. Emit "}"
  1599. End If
  1600. If check.exitId Then
  1601. Emit TransLabelExit(check)
  1602. End If
  1603. If stmt.loopLabel Then
  1604. Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
  1605. End If
  1606. If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
  1607. broken=nbroken
  1608. End Method
  1609. Method TransAssertStmt$( stmt:TAssertStmt ) Abstract
  1610. Method TransEndStmt$( stmt:TEndStmt ) Abstract
  1611. Method TransReleaseStmt$( stmt:TReleaseStmt ) Abstract
  1612. Method TransRestoreDataStmt$( stmt:TRestoreDataStmt ) Abstract
  1613. Method TransReadDataStmt$( stmt:TReadDataStmt ) Abstract
  1614. Method TransNativeStmt$( stmt:TNativeStmt) Abstract
  1615. 'module
  1616. Method TransApp( app:TAppDecl ) Abstract
  1617. Rem
  1618. Method MungOverrides( cdecl:TClassDecl )
  1619. For Local decl:=Eachin cdecl.Semanted
  1620. Local fdecl:=TFuncDecl( decl )
  1621. If fdecl And fdecl.overrides
  1622. If Not fdecl.overrides.munged InternalErr
  1623. fdecl.munged=fdecl.overrides.munged
  1624. mungScope.Insert fdecl.munged,fdecl
  1625. Endif
  1626. Next
  1627. End
  1628. End Rem
  1629. Method PostProcess$( source$ )
  1630. Return source
  1631. End Method
  1632. Method SetOutput( file:String )
  1633. Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
  1634. If Not _lines Then
  1635. _lines = New TStringList
  1636. outputFiles.Insert(file, _lines)
  1637. End If
  1638. LINES = _lines
  1639. End Method
  1640. Method SetOutputTemp( fin:Int = False )
  1641. Global tmpLevel:Int = 0
  1642. If Not fin Then
  1643. tmpLevel :+ 1
  1644. Local _lines:TStringList = New TStringList
  1645. outputFiles.Insert("tmp" + tmpLevel, _lines)
  1646. LINES = _lines
  1647. Else
  1648. Local _lines:TStringList = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
  1649. tmpLevel :- 1
  1650. If Not tmpLevel Then
  1651. SetOutput("source")
  1652. Else
  1653. LINES = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
  1654. End If
  1655. If _lines Then
  1656. For Local line:String = EachIn _lines
  1657. LINES.AddLast(line)
  1658. Next
  1659. End If
  1660. End If
  1661. End Method
  1662. Method DebugPrint(text:String, func:String = Null, trans:Int = False)
  1663. Global count:Int
  1664. Global lastFunc:String
  1665. If func Then
  1666. lastFunc = func
  1667. End If
  1668. Local s:String = "fprintf(stderr," + "~q" + lastFunc + " : " + count + " :: " + text + "\n~q)" + ";fflush(stderr);"
  1669. If trans Then
  1670. debugOut :+ indent + s + "~n"
  1671. Else
  1672. Emit s
  1673. End If
  1674. count :+ 1
  1675. End Method
  1676. Method DebugString(s:String, func:String = Null, trans:Int = False)
  1677. ' bbNullObject test
  1678. If trans Then
  1679. debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
  1680. Else
  1681. Emit "if (" + s + "==&bbNullObject) {"
  1682. End If
  1683. DebugPrint("Invalid Null String : " + s, func, trans)
  1684. If trans Then
  1685. debugOut :+ indent + "}~n"
  1686. Else
  1687. Emit "}"
  1688. End If
  1689. End Method
  1690. Method DebugArray(s:String, func:String = Null, trans:Int = False)
  1691. ' bbNullObject test
  1692. If trans Then
  1693. debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
  1694. Else
  1695. Emit "if (" + s + "==&bbNullObject) {"
  1696. End If
  1697. DebugPrint("Invalid Null Array : " + s, func, trans)
  1698. If trans Then
  1699. debugOut :+ indent + "}~n"
  1700. Else
  1701. Emit "}"
  1702. End If
  1703. End Method
  1704. Method DebugObject(ty:TType, id:String, func:String = Null, trans:Int = False)
  1705. If TObjectType(ty) Or TStringType(ty) Or TArrayType(ty) Then
  1706. ' null test
  1707. If trans Then
  1708. debugOut :+ indent + "if (" + id + "==NULL) {~n"
  1709. Else
  1710. Emit "if (" + id + "==NULL) {"
  1711. End If
  1712. DebugPrint("Null Pointer : " + id, func, trans)
  1713. If trans Then
  1714. If ABORT_ON_NULL Then
  1715. debugOut :+ indent + "abort();~n"
  1716. End If
  1717. debugOut :+ indent + "}~n"
  1718. Else
  1719. If ABORT_ON_NULL Then
  1720. Emit "abort();~n"
  1721. End If
  1722. Emit "}"
  1723. End If
  1724. End If
  1725. If TStringType(ty) Then
  1726. DebugString(id, func, trans)
  1727. Else If TArrayType(ty) Then
  1728. DebugArray(id, func, trans)
  1729. End If
  1730. End Method
  1731. Method EmitDebugStmtErrInfo(info:String, count:Int)
  1732. ' extract from info
  1733. info = info[1..info.length-1]
  1734. Local infoArray:String[] = info.Split(";")
  1735. Local dbg:String = "struct BBDebugStm __stmt_" + count + " = {"
  1736. dbg :+ GenHash(infoArray[0]) + ", "
  1737. dbg :+ infoArray[1] + ", "
  1738. dbg :+ infoArray[2] + "};"
  1739. Emit dbg
  1740. Emit "bbOnDebugEnterStm(&__stmt_" + count + ");"
  1741. End Method
  1742. Method EmitGDBDebug(obj:Object)
  1743. If opt_gdbdebug Then
  1744. If TStmt(obj) Then
  1745. Local stmt:TStmt = TStmt(obj)
  1746. Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
  1747. If Not stmt.generated Then
  1748. Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
  1749. End If
  1750. Else If TDecl(obj) Then
  1751. Local decl:TDecl = TDecl(obj)
  1752. Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
  1753. Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
  1754. Else If String(obj) Then
  1755. Local errInfo:String = String(obj)
  1756. Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
  1757. Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
  1758. End If
  1759. End If
  1760. End Method
  1761. Method EmitCoverage(obj:Object)
  1762. If opt_coverage Then
  1763. If TStmt(obj) Then
  1764. Local stmt:TStmt = TStmt(obj)
  1765. Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
  1766. If Not stmt.generated Then
  1767. GenerateCoverageLine(infoArray)
  1768. End If
  1769. Else If TDecl(obj) Then
  1770. Local decl:TDecl = TDecl(obj)
  1771. Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
  1772. GenerateCoverageLine(infoArray)
  1773. Else If String(obj) Then
  1774. Local errInfo:String = String(obj)
  1775. Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
  1776. GenerateCoverageLine(infoArray)
  1777. End If
  1778. End If
  1779. End Method
  1780. Method GenerateCoverageLine(infoArray:String[])
  1781. Emit "bbCoverageUpdateLineInfo(" + Enquote(infoArray[0]) + ", " + infoArray[1] + ");"
  1782. Local filename:String = infoArray[0]
  1783. Local line:Int = Int(infoArray[1])
  1784. Local lineInfo:TCoverageLineInfo = TCoverageLineInfo(coverageFileInfo.ValueForKey(filename))
  1785. If Not lineInfo Then
  1786. lineInfo = New TCoverageLineInfo
  1787. lineInfo.lines = New Int[0]
  1788. coverageFileInfo.Insert(filename, lineInfo)
  1789. End If
  1790. ' Don't add duplicate lines
  1791. If Not lineInfo.lines.Length Or lineInfo.lines[lineInfo.lines.Length-1] <> line Then
  1792. lineInfo.lines :+ [line]
  1793. End If
  1794. End Method
  1795. Method EmitCoverageFunction(decl:TFuncDecl)
  1796. If opt_coverage Then
  1797. Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
  1798. GenerateCoverageFunctionLine(infoArray, decl.ident)
  1799. End If
  1800. End Method
  1801. Method GenerateCoverageFunctionLine(infoArray:String[], name:String)
  1802. Emit "bbCoverageUpdateFunctionLineInfo(" + Enquote(infoArray[0]) + ", " + Enquote(name) + ", " + infoArray[1] + ");"
  1803. Local filename:String = infoArray[0]
  1804. Local line:Int = Int(infoArray[1])
  1805. Local funcInfo:TCoverageFunctionLineInfo = TCoverageFunctionLineInfo(coverageFunctionFileInfo.ValueForKey(filename))
  1806. If Not funcInfo Then
  1807. funcInfo = New TCoverageFunctionLineInfo
  1808. coverageFunctionFileInfo.Insert(filename, funcInfo)
  1809. End If
  1810. Local func:TCoverageFunctionInfo = New TCoverageFunctionInfo
  1811. func.name = name
  1812. func.line = line
  1813. funcInfo.funcs :+ [func]
  1814. End Method
  1815. Method EmitClassDeclDeleteDtor( classDecl:TClassDecl )
  1816. End Method
  1817. End Type
  1818. Type TCoverageLineInfo
  1819. Field lines:Int[]
  1820. End Type
  1821. Type TCoverageFunctionLineInfo
  1822. Field funcs:TCoverageFunctionInfo[]
  1823. End Type
  1824. Type TCoverageFunctionInfo
  1825. Field name:String
  1826. Field line:Int
  1827. End Type
  1828. Type TTryBreakCheck
  1829. Field contId:Int
  1830. Field exitId:Int
  1831. Field stmt:TStmt
  1832. Method ToString:String()
  1833. Return "TTryBreakCheck"
  1834. End Method
  1835. End Type