translator.bmx 54 KB

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