translator.bmx 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
  1. ' Copyright (c) 2013-2024 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. 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. 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 Function
  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. Function 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 Function
  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, objectNew:Int = False ) 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. If TInvokeMemberExpr(expr.expr) Then
  893. Local decl:TFuncDecl = TFuncDecl(TInvokeMemberExpr(expr.expr).decl.actual)
  894. decl.Semant()
  895. Return expr.expr.Trans()
  896. End If
  897. InternalErr "TTranslator.TransFuncCallExpr"
  898. End Method
  899. Method TransExprStmt$( stmt:TExprStmt )
  900. Return stmt.expr.TransStmt()
  901. End Method
  902. Method TransAssignStmt$( stmt:TAssignStmt )
  903. If stmt.rhs Return stmt.lhs.TransVar()+TransAssignOp(stmt.op)+stmt.rhs.Trans()
  904. Return stmt.lhs.Trans()
  905. End Method
  906. Method TransReturnStmt$( stmt:TReturnStmt )
  907. Local t$="return"
  908. unreachable=True
  909. If stmt.expr Then
  910. If TObjectType(stmt.expr.exprType) And TNullDecl(TObjectType(stmt.expr.exprType).classDecl) Then
  911. If IsPointerType(stmt.fRetType, 0, TType.T_POINTER) Or IsNumericType(stmt.fRetType) Then
  912. t:+ " 0"
  913. End If
  914. If TStringType(stmt.fRetType) Then
  915. t:+ " &bbEmptyString"
  916. End If
  917. If TArrayType(stmt.fRetType) Then
  918. t:+ " &bbEmptyArray"
  919. End If
  920. Else
  921. If TObjectType(stmt.expr.exprType) And TObjectType(stmt.expr.exprType).classDecl.IsStruct() And TConstExpr(stmt.expr) And Not TConstExpr(stmt.expr).value Then
  922. Local lvar:String = CreateLocal(stmt.expr)
  923. t :+ " " + lvar
  924. Else
  925. Local s:String
  926. ' cast to function return type
  927. If TObjectType(stmt.fRetType) And Not TObjectType(stmt.fRetType).classDecl.IsStruct() Then
  928. s :+ Bra(TransType(stmt.fRetType, ""))
  929. End If
  930. s :+ stmt.expr.Trans()
  931. ' we have some temp variables that need to be freed before we can return
  932. ' put the results into a new variable, and return that.
  933. If customVarStack.Count() > 0 Then
  934. If Not TFunctionPtrType( stmt.expr.exprType ) Then
  935. Emit TransType(stmt.expr.exprType, "rt_") + " rt_ = " + s + ";"
  936. Else
  937. Emit TransType(stmt.expr.exprType, "rt_") + " = " + s + ";"
  938. End If
  939. t:+ " rt_"
  940. Else
  941. t:+" " + s
  942. End If
  943. End If
  944. End If
  945. End If
  946. FreeVarsIfRequired()
  947. ' if this is a Delete() method, we need to call the dtor first
  948. Local funcScope:TFuncDecl = _env.FuncScope()
  949. If funcScope And funcScope.IdentLower() = "delete" Then
  950. Local classScope:TClassDecl = funcScope.ClassScope()
  951. If classScope Then
  952. EmitClassDeclDeleteDtor(classScope)
  953. End If
  954. End If
  955. Return t
  956. End Method
  957. Method NextExitId:Int(bc:TTryBreakCheck)
  958. If Not bc.exitId Then
  959. exitLabelId :+ 1
  960. bc.exitId = exitLabelId
  961. End If
  962. Return bc.exitId
  963. End Method
  964. Method NextContId:Int(bc:TTryBreakCheck)
  965. If Not bc.contId Then
  966. contLabelId :+ 1
  967. bc.contId = contLabelId
  968. End If
  969. Return bc.contId
  970. End Method
  971. Method TransContinueStmt$( stmt:TContinueStmt )
  972. Local returnStr:String
  973. Local contLoop:TStmt
  974. ' if we are continuing with a loop label, we'll need to find it in the stack
  975. If stmt.label And TLoopLabelExpr(stmt.label) Then
  976. contLoop = TLoopLabelExpr(stmt.label).loop
  977. End If
  978. ' get Try statements in the stack in this loop
  979. Local tryStmts:TTryStmt[] = LoopTryStmts(contLoop)
  980. Local count:Int = tryStmts.length
  981. Local nowUnreachable:Int = False
  982. If count > 0 Then
  983. Local bc:TTryBreakCheck = GetTopLoop(contLoop)
  984. If bc Then
  985. NextContId(bc)
  986. For Local i:Int = 0 Until count
  987. Emit "bbExLeave();"
  988. If opt_debug Then Emit "bbOnDebugPopExState();"
  989. ' in debug we also roll back scope from first Try in scope down to the loop scope itself
  990. If opt_debug And (i = count - 1) And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  991. Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_LOOP)
  992. For Local n:Int = 0 Until loopCount
  993. Emit "bbOnDebugLeaveScope();"
  994. Next
  995. End If
  996. If tryStmts[i].finallyStmt Then
  997. Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("continue")
  998. MungDecl returnLabelDecl
  999. EmitFinallyJmp tryStmts[i].finallyStmt, returnLabelDecl
  1000. Emit TransLabel(returnLabelDecl)
  1001. End If
  1002. Next
  1003. Emit "goto " + TransLabelCont(bc, False)
  1004. Else
  1005. InternalErr "TTranslator.TransContinueStmt"
  1006. End If
  1007. Else
  1008. ' For debug builds, we need to rollback the local scope stack correctly
  1009. count = 0
  1010. If opt_debug And TLoopStmt(contLoop) And Not TLoopStmt(contLoop).block.IsNoDebug() Then
  1011. count = LoopLocalScopeDepth(contLoop)
  1012. End If
  1013. If count > 0 Then
  1014. Local bc:TTryBreakCheck = GetTopLocalLoop(contLoop)
  1015. If bc Then
  1016. NextContId(bc)
  1017. For Local i:Int = 0 Until count
  1018. Emit "bbOnDebugLeaveScope();"
  1019. Next
  1020. Emit "goto " + TransLabelCont(bc, False)
  1021. Else
  1022. InternalErr "TTranslator.TransContinueStmt"
  1023. End If
  1024. Else
  1025. If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1026. count = LoopLocalScopeDepth(Null)
  1027. End If
  1028. For Local i:Int = 0 Until count
  1029. Emit "bbOnDebugLeaveScope();"
  1030. Next
  1031. ' No Try statements in the stack here..
  1032. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1033. Emit "goto " + TransLoopLabelCont(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
  1034. Else
  1035. returnStr = "continue"
  1036. End If
  1037. End If
  1038. End If
  1039. unreachable = True
  1040. Return returnStr
  1041. End Method
  1042. Method TransBreakStmt$( stmt:TBreakStmt )
  1043. Local returnStr:String
  1044. Local brkLoop:TStmt
  1045. ' if we are exiting with a loop label, we'll need to find it in the stack
  1046. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1047. brkLoop = TLoopLabelExpr(stmt.label).loop
  1048. End If
  1049. ' get Try statements in the stack in this loop
  1050. Local tryStmts:TTryStmt[] = LoopTryStmts(brkLoop)
  1051. Local count:Int = tryStmts.length
  1052. Local nowUnreachable:Int = False
  1053. If count > 0 Then
  1054. Local bc:TTryBreakCheck = GetTopLoop(brkLoop)
  1055. If bc Then
  1056. NextExitId(bc)
  1057. For Local i:Int = 0 Until count
  1058. Emit "bbExLeave();"
  1059. If opt_debug Then Emit "bbOnDebugPopExState();"
  1060. ' in debug we also roll back scope from first Try in scope down to the loop scope itself
  1061. If opt_debug And (i = count - 1) And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1062. Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_LOOP)
  1063. For Local n:Int = 0 Until loopCount
  1064. Emit "bbOnDebugLeaveScope();"
  1065. Next
  1066. End If
  1067. If tryStmts[i].finallyStmt Then
  1068. Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("break")
  1069. MungDecl returnLabelDecl
  1070. EmitFinallyJmp tryStmts[i].finallyStmt, returnLabelDecl
  1071. Emit TransLabel(returnLabelDecl)
  1072. End If
  1073. Next
  1074. Emit "goto " + TransLabelExit(bc, False)
  1075. Else
  1076. InternalErr "TTranslator.TransBreakStmt"
  1077. End If
  1078. Else
  1079. ' For debug builds, we need to rollback the local scope stack correctly
  1080. count = 0
  1081. If opt_debug And TLoopStmt(brkLoop) And Not TLoopStmt(brkLoop).block.IsNoDebug() Then
  1082. count = LoopLocalScopeDepth(brkLoop)
  1083. End If
  1084. If count > 0 Then
  1085. Local bc:TTryBreakCheck = GetTopLocalLoop(brkLoop)
  1086. If bc Then
  1087. NextExitId(bc)
  1088. For Local i:Int = 0 Until count
  1089. Emit "bbOnDebugLeaveScope();"
  1090. Next
  1091. Emit "goto " + TransLabelExit(bc, False)
  1092. Else
  1093. InternalErr "TTranslator.TransBreakStmt"
  1094. End If
  1095. Else
  1096. If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
  1097. count = LoopLocalScopeDepth(Null)
  1098. End If
  1099. For Local i:Int = 0 Until count
  1100. Emit "bbOnDebugLeaveScope();"
  1101. Next
  1102. ' No Try statements in the stack here..
  1103. If stmt.label And TLoopLabelExpr(stmt.label) Then
  1104. Emit "goto " + TransLoopLabelExit(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
  1105. Else
  1106. returnStr = "break"
  1107. End If
  1108. End If
  1109. End If
  1110. unreachable = True
  1111. broken :+ 1
  1112. Return returnStr
  1113. End Method
  1114. Method TransTryStmt$( stmt:TTryStmt )
  1115. End Method
  1116. Method EmitFinallyJmp(stmt:TFinallyStmt, returnLabel:TLoopLabelDecl) Abstract
  1117. Method TransThrowStmt$( stmt:TThrowStmt )
  1118. End Method
  1119. Method TransBuiltinExpr$( expr:TBuiltinExpr )
  1120. If TAscExpr(expr) Return TransAscExpr(TAscExpr(expr))
  1121. If TChrExpr(expr) Return TransChrExpr(TChrExpr(expr))
  1122. If TLenExpr(expr) Return TransLenExpr(TLenExpr(expr))
  1123. If TSizeOfExpr(expr) Return TransSizeOfExpr(TSizeOfExpr(expr))
  1124. If TStackAllocExpr(expr) Return TransStackAllocExpr(TStackAllocExpr(expr))
  1125. If TFieldOffsetExpr(expr) Return TransFieldOffsetExpr(TFieldOffsetExpr(expr))
  1126. Err "TODO : TransBuiltinExpr()"
  1127. End Method
  1128. Method TransAscExpr:String(expr:TAscExpr)
  1129. End Method
  1130. Method TransChrExpr:String(expr:TChrExpr)
  1131. End Method
  1132. Method TransLenExpr:String(expr:TLenExpr)
  1133. End Method
  1134. Method TransSizeOfExpr:String(expr:TSizeOfExpr)
  1135. End Method
  1136. Method TransStackAllocExpr:String(expr:TStackAllocExpr)
  1137. End Method
  1138. Method TransFieldOffsetExpr:String(expr:TFieldOffsetExpr)
  1139. End Method
  1140. Method TransIdentTypeExpr:String(expr:TIdentTypeExpr) Abstract
  1141. Method TransLabelCont:String(bc:TTryBreakCheck, jmp:Int = True)
  1142. If jmp Then
  1143. Return "_contjmp" + bc.contId + ": ;"
  1144. Else
  1145. Return "_contjmp" + bc.contId + ";"
  1146. End If
  1147. End Method
  1148. Method TransLabelExit:String(bc:TTryBreakCheck, jmp:Int = True)
  1149. If jmp Then
  1150. Return "_exitjmp" + bc.exitId + ": ;"
  1151. Else
  1152. Return "_exitjmp" + bc.exitId + ";"
  1153. End If
  1154. End Method
  1155. Method TransLoopLabelCont:String(id:String, jmp:Int = True)
  1156. If jmp Then
  1157. Return "_loopcont_" + id.ToLower() + ": ;"
  1158. Else
  1159. Return "_loopcont_" + id.ToLower() + ";"
  1160. End If
  1161. End Method
  1162. Method TransLoopLabelExit:String(id:String, jmp:Int = True)
  1163. If jmp Then
  1164. Return "_loopexit_" + id.ToLower() + ": ;"
  1165. Else
  1166. Return "_loopexit_" + id.ToLower() + ";"
  1167. End If
  1168. End Method
  1169. Method TransLabel:String(labelDecl:TLoopLabelDecl)
  1170. Return labelDecl.munged + ":;"
  1171. End Method
  1172. '***** Block statements - all very C like! *****
  1173. Method Emit( t$, useIndent:Int = True )
  1174. If Not t Return
  1175. If useIndent
  1176. If t.StartsWith( "}" )
  1177. indent=indent[..indent.Length-1]
  1178. EndIf
  1179. End If
  1180. LINES.AddLast indent+t
  1181. 'code+=indent+t+"~n"
  1182. If useIndent
  1183. If t.EndsWith( "{" )
  1184. indent:+"~t"
  1185. EndIf
  1186. End If
  1187. End Method
  1188. Method JoinLines$( file:String )
  1189. Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
  1190. If _lines Then
  1191. Local code$=_lines.Join( "~n" )
  1192. _lines.Clear
  1193. Return code
  1194. End If
  1195. End Method
  1196. 'returns and resets unreachable status
  1197. Method EmitBlock:Int( block:TBlockDecl )
  1198. Local stmtCount:Int
  1199. 'DebugStop
  1200. 'If ENV_CONFIG="debug"
  1201. ' If TFuncDecl( block ) EmitPushErr
  1202. 'EndIf
  1203. PushEnv block
  1204. ' enter scope
  1205. If opt_debug And Not block.IsNoDebug() And Not block.generated Then
  1206. PushLoopLocalStack(block)
  1207. EmitDebugEnterScope(block)
  1208. End If
  1209. For Local stmt:TStmt=EachIn block.stmts
  1210. _errInfo=stmt.errInfo
  1211. If unreachable
  1212. ' Statements following cannot be reached - maybe we have Returned, etc
  1213. ' So don't process any more for this block - they won't be generated now!
  1214. Exit
  1215. EndIf
  1216. Rem
  1217. If ENV_CONFIG="debug"
  1218. Local rs:TReturnStmt=TReturnStmt( stmt )
  1219. If rs
  1220. If rs.expr
  1221. EmitSetErr stmt.errInfo
  1222. Local t_expr$=TransExprNS( rs.expr )
  1223. EmitPopErr
  1224. Emit "return "+t_expr+";"
  1225. Else
  1226. EmitPopErr
  1227. Emit "return;"
  1228. EndIf
  1229. unreachable=True
  1230. Continue
  1231. EndIf
  1232. EmitSetErr stmt.errInfo
  1233. EndIf
  1234. End Rem
  1235. If opt_debug And Not block.IsNoDebug() Then
  1236. ' only for user-made code
  1237. If Not stmt.generated Then
  1238. EmitDebugStmtErrInfo(stmt.errInfo, stmtCount)
  1239. stmtCount :+ 1
  1240. End If
  1241. End If
  1242. EmitCoverage(stmt)
  1243. EmitGDBDebug(stmt)
  1244. If TReturnStmt(stmt) And Not tryStack.IsEmpty() Then
  1245. processingReturnStatement = 1
  1246. End If
  1247. Local t$=stmt.Trans()
  1248. processingReturnStatement = 0
  1249. If TReturnStmt(stmt) Then
  1250. Local stackSize:Int = tryStack.Count()
  1251. Local count:Int
  1252. If stackSize Then
  1253. For Local tryStmt:TTryStmt = EachIn tryStack
  1254. Emit "bbExLeave();"
  1255. If opt_debug Then Emit "bbOnDebugPopExState();"
  1256. ' in debug we need to roll back scope from first Try in scope down to the function scope
  1257. If opt_debug And (count = stackSize - 1) And Not block.IsNoDebug() Then
  1258. Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_FUNCTION)
  1259. For Local n:Int = 0 Until loopCount
  1260. Emit "bbOnDebugLeaveScope();"
  1261. Next
  1262. End If
  1263. If tryStmt.finallyStmt Then
  1264. Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("return")
  1265. MungDecl returnLabelDecl
  1266. EmitFinallyJmp tryStmt.finallyStmt, returnLabelDecl
  1267. Emit TransLabel(returnLabelDecl)
  1268. End If
  1269. count :+ 1
  1270. Next
  1271. Else
  1272. If opt_debug And Not block.IsNoDebug() Then
  1273. For Local b:TBlockDecl = EachIn localScope
  1274. Emit "bbOnDebugLeaveScope();"
  1275. Next
  1276. End If
  1277. End If
  1278. End If
  1279. If t Emit t+";"
  1280. If DEBUG And debugOut Then
  1281. Emit debugOut
  1282. debugOut = Null
  1283. End If
  1284. Local v:String = String(customVarStack.Pop())
  1285. While v
  1286. Emit "bbMemFree" + Bra(v) + ";"
  1287. v = String(customVarStack.Pop())
  1288. Wend
  1289. Next
  1290. If opt_debug And Not block.IsNoDebug() And Not block.generated Then
  1291. PopLoopLocalStack()
  1292. If Not unreachable Then
  1293. Emit "bbOnDebugLeaveScope();"
  1294. End If
  1295. End If
  1296. Local r:Int=unreachable
  1297. unreachable=False
  1298. PopEnv
  1299. Return r
  1300. End Method
  1301. Method TransDeclStmt$( stmt:TDeclStmt, declare:Int = False )
  1302. Local decl:TLocalDecl=TLocalDecl( stmt.decl )
  1303. If decl
  1304. MungDecl decl
  1305. ' only generate local declarations once.
  1306. If decl.generated Then
  1307. If Not decl.done Then
  1308. decl.done = True
  1309. Else
  1310. Return ""
  1311. End If
  1312. End If
  1313. Return TransLocalDecl( decl,decl.init, decl.generated Or declare )
  1314. EndIf
  1315. Local cdecl:TConstDecl=TConstDecl( stmt.decl )
  1316. If cdecl
  1317. Return Null
  1318. EndIf
  1319. Local gdecl:TGlobalDecl=TGlobalDecl( stmt.decl )
  1320. If gdecl Then
  1321. MungDecl gdecl
  1322. If gdecl.inited Return Null
  1323. Return TransGlobalDecl( gdecl )
  1324. End If
  1325. InternalErr "TTranslator.TransDeclStmt"
  1326. End Method
  1327. Method TransIfStmt$( stmt:TIfStmt )
  1328. If TConstExpr( stmt.expr )
  1329. If TConstExpr( stmt.expr ).value
  1330. Emit "{"
  1331. EmitLocalDeclarations(stmt.thenBlock)
  1332. If EmitBlock( stmt.thenBlock ) unreachable=True
  1333. Emit "}"
  1334. Else If stmt.elseBlock.stmts.First()
  1335. Emit "{"
  1336. EmitLocalDeclarations(stmt.elseBlock)
  1337. If EmitBlock( stmt.elseBlock ) unreachable=True
  1338. Emit "}"
  1339. EndIf
  1340. Else If stmt.elseBlock.stmts.First()
  1341. Emit "if"+Bra( stmt.expr.Trans() )+"{"
  1342. EmitLocalDeclarations(stmt.thenBlock)
  1343. FreeVarsIfRequired(False)
  1344. PushVarScope
  1345. Local unr:Int=EmitBlock( stmt.thenBlock )
  1346. PopVarScope
  1347. Emit "}else{"
  1348. EmitLocalDeclarations(stmt.elseBlock)
  1349. FreeVarsIfRequired
  1350. Local unr2:Int=EmitBlock( stmt.elseBlock )
  1351. Emit "}"
  1352. If unr And unr2 unreachable=True
  1353. Else
  1354. ' Emit "if"+ Bra(TransCondition(stmt.expr)) + "{"
  1355. ' If TVarExpr(stmt.expr) Then
  1356. ' If TObjectType(TVarExpr(stmt.expr).exprType) Then
  1357. ' Emit "if"+Bra( stmt.expr.Trans() + "!= &bbNullObject") + "{"
  1358. ' Else If TStringType(TVarExpr(stmt.expr).exprType) Then
  1359. ' Emit "if"+Bra( stmt.expr.Trans() + "!= &bbEmptyString") + "{"
  1360. ' Else
  1361. ' Emit "if"+Bra( stmt.expr.Trans() )+"{"
  1362. ' End If
  1363. ' Else
  1364. Emit "if"+Bra( stmt.expr.Trans() )+"{"
  1365. FreeVarsIfRequired(False)
  1366. ' End If
  1367. EmitLocalDeclarations(stmt.thenBlock)
  1368. PushVarScope
  1369. Local unr:Int=EmitBlock( stmt.thenBlock )
  1370. PopVarScope
  1371. Emit "}"
  1372. FreeVarsIfRequired
  1373. EndIf
  1374. End Method
  1375. Method FreeVarsIfRequired(removeFromStack:Int = True)
  1376. If removeFromStack
  1377. Local v:String = String(customVarStack.Pop())
  1378. While v
  1379. Emit "bbMemFree" + Bra(v) + ";"
  1380. v = String(customVarStack.Pop())
  1381. Wend
  1382. Else
  1383. For Local v:String = EachIn customVarStack
  1384. Emit "bbMemFree" + Bra(v) + ";"
  1385. Next
  1386. End If
  1387. End Method
  1388. ' Method TransCondition:String(expr:TExpr)
  1389. ' If TVarExpr(expr) Then
  1390. ' If TObjectType(TVarExpr(expr).exprType) Then
  1391. ' Return Bra( expr.Trans() + "!= &bbNullObject")
  1392. ' Else If TStringType(TVarExpr(expr).exprType) Then
  1393. ' Return Bra( expr.Trans() + "!= &bbEmptyString")
  1394. ' Else
  1395. ' Return Bra( expr.Trans() )
  1396. ' End If
  1397. ' Else
  1398. ' Return Bra( expr.Trans() )
  1399. ' End If
  1400. ' End Method
  1401. Method TransWhileStmt$( stmt:TWhileStmt )
  1402. Local nbroken:Int=broken
  1403. Emit "while"+Bra( stmt.expr.Trans() )+"{"
  1404. Local check:TTryBreakCheck = New TTryBreakCheck
  1405. check.stmt = stmt
  1406. PushLoopTryStack(check)
  1407. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1408. PushLoopLocalStack(check)
  1409. End If
  1410. EmitLocalDeclarations(stmt.block)
  1411. Local unr:Int=EmitBlock( stmt.block )
  1412. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1413. PopLoopLocalStack
  1414. End If
  1415. PopLoopTryStack
  1416. If check.contId Then
  1417. Emit TransLabelCont(check)
  1418. End If
  1419. If stmt.loopLabel Then
  1420. MungDecl stmt.loopLabel
  1421. Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
  1422. End If
  1423. Emit "}"
  1424. If check.exitId Then
  1425. Emit TransLabelExit(check)
  1426. End If
  1427. If stmt.loopLabel Then
  1428. Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
  1429. End If
  1430. If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
  1431. broken=nbroken
  1432. End Method
  1433. Method TransRepeatStmt$( stmt:TRepeatStmt )
  1434. Local nbroken:Int=broken
  1435. SetOutputTemp()
  1436. Emit "do{"
  1437. Local check:TTryBreakCheck = New TTryBreakCheck
  1438. check.stmt = stmt
  1439. PushLoopTryStack(check)
  1440. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1441. PushLoopLocalStack(check)
  1442. End If
  1443. EmitLocalDeclarations(stmt.block)
  1444. Local unr:Int=EmitBlock( stmt.block )
  1445. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1446. PopLoopLocalStack
  1447. End If
  1448. PopLoopTryStack
  1449. If check.contId Then
  1450. Emit TransLabelCont(check)
  1451. End If
  1452. If stmt.loopLabel Then
  1453. MungDecl stmt.loopLabel
  1454. Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
  1455. End If
  1456. SetOutput("source")
  1457. Local s:String = "}while(!"+Bra( stmt.expr.Trans() )+");"
  1458. SetOutputTemp(True)
  1459. Emit s
  1460. If check.exitId Then
  1461. Emit TransLabelExit(check)
  1462. End If
  1463. If stmt.loopLabel Then
  1464. Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
  1465. End If
  1466. If broken=nbroken And TConstExpr( stmt.expr ) And Not TConstExpr( stmt.expr ).value unreachable=True
  1467. broken=nbroken
  1468. End Method
  1469. Method TransForStmt$( stmt:TForStmt )
  1470. Local nbroken:Int=broken
  1471. Local init$
  1472. Local decl:Int
  1473. Local vdecl:TValDecl
  1474. If TDeclStmt(stmt.init) Then
  1475. decl = True
  1476. Emit "{"
  1477. Emit TransDeclStmt(TDeclStmt(stmt.init), True) + ";"
  1478. 'init = TDeclStmt(stmt.init).decl.munged
  1479. vdecl = TValDecl(TDeclStmt(stmt.init).decl)
  1480. Else
  1481. init=stmt.init.Trans()
  1482. End If
  1483. Local expr$=stmt.expr.Trans()
  1484. Local incr$=stmt.incr.Trans()
  1485. Emit "for("+init+";"+expr+";"+incr+"){"
  1486. Local check:TTryBreakCheck = New TTryBreakCheck
  1487. check.stmt = stmt
  1488. PushLoopTryStack(check)
  1489. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1490. PushLoopLocalStack(check)
  1491. End If
  1492. EmitLocalDeclarations(stmt.block, vdecl)
  1493. Local unr:Int=EmitBlock( stmt.block )
  1494. If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
  1495. PopLoopLocalStack
  1496. End If
  1497. PopLoopTryStack
  1498. If check.contId Then
  1499. Emit TransLabelCont(check)
  1500. End If
  1501. If stmt.loopLabel Then
  1502. MungDecl stmt.loopLabel
  1503. Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
  1504. End If
  1505. Emit "}"
  1506. If decl Then
  1507. Emit "}"
  1508. End If
  1509. If check.exitId Then
  1510. Emit TransLabelExit(check)
  1511. End If
  1512. If stmt.loopLabel Then
  1513. Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
  1514. End If
  1515. If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
  1516. broken=nbroken
  1517. End Method
  1518. Method TransAssertStmt$( stmt:TAssertStmt ) Abstract
  1519. Method TransEndStmt$( stmt:TEndStmt ) Abstract
  1520. Method TransReleaseStmt$( stmt:TReleaseStmt ) Abstract
  1521. Method TransRestoreDataStmt$( stmt:TRestoreDataStmt ) Abstract
  1522. Method TransReadDataStmt$( stmt:TReadDataStmt ) Abstract
  1523. Method TransNativeStmt$( stmt:TNativeStmt) Abstract
  1524. 'module
  1525. Method TransApp( app:TAppDecl ) Abstract
  1526. Rem
  1527. Method MungOverrides( cdecl:TClassDecl )
  1528. For Local decl:=Eachin cdecl.Semanted
  1529. Local fdecl:=TFuncDecl( decl )
  1530. If fdecl And fdecl.overrides
  1531. If Not fdecl.overrides.munged InternalErr
  1532. fdecl.munged=fdecl.overrides.munged
  1533. mungScope.Insert fdecl.munged,fdecl
  1534. Endif
  1535. Next
  1536. End
  1537. End Rem
  1538. Method PostProcess$( source$ )
  1539. Return source
  1540. End Method
  1541. Method SetOutput( file:String )
  1542. Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
  1543. If Not _lines Then
  1544. _lines = New TStringList
  1545. outputFiles.Insert(file, _lines)
  1546. End If
  1547. LINES = _lines
  1548. End Method
  1549. Method SetOutputTemp( fin:Int = False )
  1550. Global tmpLevel:Int = 0
  1551. If Not fin Then
  1552. tmpLevel :+ 1
  1553. Local _lines:TStringList = New TStringList
  1554. outputFiles.Insert("tmp" + tmpLevel, _lines)
  1555. LINES = _lines
  1556. Else
  1557. Local _lines:TStringList = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
  1558. tmpLevel :- 1
  1559. If Not tmpLevel Then
  1560. SetOutput("source")
  1561. Else
  1562. LINES = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
  1563. End If
  1564. If _lines Then
  1565. For Local line:String = EachIn _lines
  1566. LINES.AddLast(line)
  1567. Next
  1568. End If
  1569. End If
  1570. End Method
  1571. Method DebugPrint(text:String, func:String = Null, trans:Int = False)
  1572. Global count:Int
  1573. Global lastFunc:String
  1574. If func Then
  1575. lastFunc = func
  1576. End If
  1577. Local s:String = "fprintf(stderr," + "~q" + lastFunc + " : " + count + " :: " + text + "\n~q)" + ";fflush(stderr);"
  1578. If trans Then
  1579. debugOut :+ indent + s + "~n"
  1580. Else
  1581. Emit s
  1582. End If
  1583. count :+ 1
  1584. End Method
  1585. Method DebugString(s:String, func:String = Null, trans:Int = False)
  1586. ' bbNullObject test
  1587. If trans Then
  1588. debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
  1589. Else
  1590. Emit "if (" + s + "==&bbNullObject) {"
  1591. End If
  1592. DebugPrint("Invalid Null String : " + s, func, trans)
  1593. If trans Then
  1594. debugOut :+ indent + "}~n"
  1595. Else
  1596. Emit "}"
  1597. End If
  1598. End Method
  1599. Method DebugArray(s:String, func:String = Null, trans:Int = False)
  1600. ' bbNullObject test
  1601. If trans Then
  1602. debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
  1603. Else
  1604. Emit "if (" + s + "==&bbNullObject) {"
  1605. End If
  1606. DebugPrint("Invalid Null Array : " + s, func, trans)
  1607. If trans Then
  1608. debugOut :+ indent + "}~n"
  1609. Else
  1610. Emit "}"
  1611. End If
  1612. End Method
  1613. Method DebugObject(ty:TType, id:String, func:String = Null, trans:Int = False)
  1614. If TObjectType(ty) Or TStringType(ty) Or TArrayType(ty) Then
  1615. ' null test
  1616. If trans Then
  1617. debugOut :+ indent + "if (" + id + "==NULL) {~n"
  1618. Else
  1619. Emit "if (" + id + "==NULL) {"
  1620. End If
  1621. DebugPrint("Null Pointer : " + id, func, trans)
  1622. If trans Then
  1623. If ABORT_ON_NULL Then
  1624. debugOut :+ indent + "abort();~n"
  1625. End If
  1626. debugOut :+ indent + "}~n"
  1627. Else
  1628. If ABORT_ON_NULL Then
  1629. Emit "abort();~n"
  1630. End If
  1631. Emit "}"
  1632. End If
  1633. End If
  1634. If TStringType(ty) Then
  1635. DebugString(id, func, trans)
  1636. Else If TArrayType(ty) Then
  1637. DebugArray(id, func, trans)
  1638. End If
  1639. End Method
  1640. Method EmitDebugStmtErrInfo(info:String, count:Int)
  1641. ' extract from info
  1642. info = info[1..info.length-1]
  1643. Local infoArray:String[] = info.Split(";")
  1644. Local dbg:String = "struct BBDebugStm __stmt_" + count + " = {"
  1645. dbg :+ GenHash(infoArray[0]) + ", "
  1646. dbg :+ infoArray[1] + ", "
  1647. dbg :+ infoArray[2] + "};"
  1648. Emit dbg
  1649. Emit "bbOnDebugEnterStm(&__stmt_" + count + ");"
  1650. End Method
  1651. Method EmitGDBDebug(obj:Object)
  1652. If opt_gdbdebug Then
  1653. If TStmt(obj) Then
  1654. Local stmt:TStmt = TStmt(obj)
  1655. Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
  1656. If Not stmt.generated Then
  1657. Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
  1658. End If
  1659. Else If TDecl(obj) Then
  1660. Local decl:TDecl = TDecl(obj)
  1661. Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
  1662. Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
  1663. Else If String(obj) Then
  1664. Local errInfo:String = String(obj)
  1665. Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
  1666. Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
  1667. End If
  1668. End If
  1669. End Method
  1670. Method EmitCoverage(obj:Object)
  1671. If opt_coverage Then
  1672. If TStmt(obj) Then
  1673. Local stmt:TStmt = TStmt(obj)
  1674. Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
  1675. If Not stmt.generated Then
  1676. GenerateCoverageLine(infoArray)
  1677. End If
  1678. Else If TDecl(obj) Then
  1679. Local decl:TDecl = TDecl(obj)
  1680. Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
  1681. GenerateCoverageLine(infoArray)
  1682. Else If String(obj) Then
  1683. Local errInfo:String = String(obj)
  1684. Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
  1685. GenerateCoverageLine(infoArray)
  1686. End If
  1687. End If
  1688. End Method
  1689. Method GenerateCoverageLine(infoArray:String[])
  1690. Emit "bbCoverageUpdateLineInfo(" + Enquote(infoArray[0]) + ", " + infoArray[1] + ");"
  1691. Local filename:String = infoArray[0]
  1692. Local line:Int = Int(infoArray[1])
  1693. Local lineInfo:TCoverageLineInfo = TCoverageLineInfo(coverageFileInfo.ValueForKey(filename))
  1694. If Not lineInfo Then
  1695. lineInfo = New TCoverageLineInfo
  1696. lineInfo.lines = New Int[0]
  1697. coverageFileInfo.Insert(filename, lineInfo)
  1698. End If
  1699. ' Don't add duplicate lines
  1700. If Not lineInfo.lines.Length Or lineInfo.lines[lineInfo.lines.Length-1] <> line Then
  1701. lineInfo.lines :+ [line]
  1702. End If
  1703. End Method
  1704. Method EmitCoverageFunction(decl:TFuncDecl)
  1705. If opt_coverage Then
  1706. Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
  1707. GenerateCoverageFunctionLine(infoArray, decl.ident)
  1708. End If
  1709. End Method
  1710. Method GenerateCoverageFunctionLine(infoArray:String[], name:String)
  1711. Emit "bbCoverageUpdateFunctionLineInfo(" + Enquote(infoArray[0]) + ", " + Enquote(name) + ", " + infoArray[1] + ");"
  1712. Local filename:String = infoArray[0]
  1713. Local line:Int = Int(infoArray[1])
  1714. Local funcInfo:TCoverageFunctionLineInfo = TCoverageFunctionLineInfo(coverageFunctionFileInfo.ValueForKey(filename))
  1715. If Not funcInfo Then
  1716. funcInfo = New TCoverageFunctionLineInfo
  1717. coverageFunctionFileInfo.Insert(filename, funcInfo)
  1718. End If
  1719. Local func:TCoverageFunctionInfo = New TCoverageFunctionInfo
  1720. func.name = name
  1721. func.line = line
  1722. funcInfo.funcs :+ [func]
  1723. End Method
  1724. Method EmitClassDeclDeleteDtor( classDecl:TClassDecl )
  1725. End Method
  1726. End Type
  1727. Type TCoverageLineInfo
  1728. Field lines:Int[]
  1729. End Type
  1730. Type TCoverageFunctionLineInfo
  1731. Field funcs:TCoverageFunctionInfo[]
  1732. End Type
  1733. Type TCoverageFunctionInfo
  1734. Field name:String
  1735. Field line:Int
  1736. End Type
  1737. Type TTryBreakCheck
  1738. Field contId:Int
  1739. Field exitId:Int
  1740. Field stmt:TStmt
  1741. Method ToString:String()
  1742. Return "TTryBreakCheck"
  1743. End Method
  1744. End Type