| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204 |
- ' Copyright (c) 2013-2025 Bruce A Henderson
- '
- ' Based on the public domain Monkey "trans" by Mark Sibly
- '
- ' This software is provided 'as-is', without any express or implied
- ' warranty. In no event will the authors be held liable for any damages
- ' arising from the use of this software.
- '
- ' Permission is granted to anyone to use this software for any purpose,
- ' including commercial applications, and to alter it and redistribute it
- ' freely, subject to the following restrictions:
- '
- ' 1. The origin of this software must not be misrepresented; you must not
- ' claim that you wrote the original software. If you use this software
- ' in a product, an acknowledgment in the product documentation would be
- ' appreciated but is not required.
- '
- ' 2. Altered source versions must be plainly marked as such, and must not be
- ' misrepresented as being the original software.
- '
- ' 3. This notice may not be removed or altered from any source
- ' distribution.
- '
- Global _trans:TTranslator
- Type TTranslator
- Field _app:TAppDecl
- Field outputFiles:TMap = New TMap
- Field indent$
- Field LINES:TStringList'=New TStringList
- Field unreachable:Int,broken:Int
-
- Field contLabelId:Int
- Field exitLabelId:Int
-
- 'Munging needs a big cleanup!
-
- Field globalMungScope:TMap = New TMap
- Field mungScope:TMap=New TMap'<TDecl>
- Field mungStack:TStackList=New TStackList'< StringMap<TDecl> >
- Field funcMungs:TMap=New TMap'<FuncDeclList>
- Field customVarStack:TStackList = New TStackList
- Field varStack:TStackList = New TStackList
- Field tryStack:TStackList = New TStackList
- Field loopTryStack:TStackList = New TStackList
- Field mungedScopes:TMap=New TMap'<StringSet>
- 'Field funcMungs:TFuncDeclList=New TFuncDeclList
- 'Field mungedFuncs:TMap=New Map
- Field localScopeStack:TStackList = New TStackList
- Field localScope:TStackList = New TStackList
- Field ind:Int
- Field debugOut:String
-
- Field processingReturnStatement:Int
- Field coverageFileInfo:TMap = New TMap
- Field coverageFunctionFileInfo:TMap = New TMap
- Method PushVarScope()
- varStack.Push customVarStack
- customVarStack = New TStackList
- End Method
-
- Method PopVarScope()
- customVarStack=TStackList(varStack.Pop())
- End Method
-
- Method PushLoopLocalStack(stmt:Object)
- ind :+ 1
- If DEBUG Then
- Emit "// --> STACK = " + ind
- End If
- localScope.Push stmt
- End Method
- Method PopLoopLocalStack()
- If DEBUG Then
- Emit "// <-- STACK = " + ind
- End If
- ind :- 1
- If ind < 0 Then
- InternalErr "TTranslator.PopLoopLocalStack"
- End If
- localScope.Pop
- End Method
- Method LoopLocalScopeDepth:Int(findStmt:TStmt)
- Local count:Int = 0
- For Local stmt:Object = EachIn localScope
- If TBlockDecl(stmt) = Null Then
- If findStmt And TTryBreakCheck(stmt) And findStmt <> TTryBreakCheck(stmt).stmt Then
- Continue
- End If
- Exit
- End If
- count :+ 1
- Next
-
- Return count
- End Method
- Method DumpLocalScope:Int()
- Print "DumpLocalScope:"
- For Local stmt:Object = EachIn localScope
- Print " " + stmt.ToString()
- Next
- End Method
-
- Method GetTopLocalLoop:TTryBreakCheck(findStmt:TStmt)
- For Local tbc:TTryBreakCheck = EachIn localScope
- If findStmt And findStmt <> tbc.stmt Then
- Continue
- End If
- Return tbc
- Next
- End Method
- Method PushLoopTryStack(stmt:Object)
- If loopTryStack.Length() = 0 Then
- ' Try statements can only be applied here to loops
- If TTryStmt(stmt) = Null Then
- loopTryStack.Push stmt
- End If
- Else
- loopTryStack.Push stmt
- End If
- End Method
-
- Method TryDownToBlockScopeCount:Int(endBlockType:Int)
- Local lastTry:Int
- Local firstBlock:Int
- Local count:Int
- For Local stmt:Object = EachIn localScope
- If TBlockDecl(stmt) Then
- If TBlockDecl(stmt).blockType & BLOCK_TRY_CATCH Then
- lastTry = count
- Else If TBlockDecl(stmt).blockType = endBlockType Then
- firstBlock = count
- Exit
- End If
- End If
-
- If TTryBreakCheck(stmt) Then
- Continue
- End If
-
- count :+ 1
- Next
-
- Return firstBlock - lastTry
- End Method
- Method PopLoopTryStack()
- loopTryStack.Pop
- End Method
-
- Method LoopTryDepth:Int(findStmt:TStmt)
- Local count:Int = 0
-
- For Local stmt:Object = EachIn loopTryStack
- If TTryStmt(stmt) = Null Then
- If findStmt And findStmt <> stmt Then
- Continue
- End If
-
- Exit
- End If
- count :+ 1
- Next
-
- Return count
- End Method
- Method LoopTryStmts:TTryStmt[](findStmt:TStmt)
- Local stmts:TTryStmt[]
-
- For Local stmt:Object = EachIn loopTryStack
- If TTryStmt(stmt) Then
- stmts :+ [TTryStmt(stmt)]
- Else
- If findStmt And findStmt <> stmt Then
- Continue
- End If
-
- Exit
- End If
- Next
-
- Return stmts
- End Method
-
- Method GetTopLoop:TTryBreakCheck(findStmt:TStmt)
- For Local tbc:TTryBreakCheck = EachIn loopTryStack
- If findStmt And findStmt <> tbc.stmt Then
- Continue
- End If
- Return tbc
- Next
- End Method
- Function TransManglePointer$( ty:TType )
- Local p:String
-
- If ty
- If ty._flags & TType.T_VAR Then
- p:+ "v"
- End If
- If ty._flags & TType.T_PTR Then
- p:+ "p"
- Else If ty._flags & TType.T_PTRPTR Then
- p:+ "pp"
- Else If ty._flags & TType.T_PTRPTRPTR Then
- p:+ "ppp"
- End If
- End If
-
- Return p
- End Function
- ' Function TransMangleType:String(ty:TType)
- ' Local p:String = TransManglePointer(ty)
- ' If TVoidType( ty ) Return "v"
- ' If TByteType( ty ) Return p + "b"
- ' If TShortType( ty ) Return p + "s"
- ' If TIntType( ty ) Return p + "i"
- ' If TUIntType( ty ) Return p + "u"
- ' If TFloatType( ty ) Return p + "f"
- ' If TDoubleType( ty ) Return p + "d"
- ' If TLongType( ty ) Return p + "l"
- ' If TULongType( ty ) Return p + "y"
- ' If TSizeTType( ty ) Return p + "z"
- ' If TFloat64Type( ty ) Return p + "h"
- ' If TFloat128Type( ty ) Return p + "k"
- ' If TInt128Type( ty ) Return p + "j"
- ' If TDouble128Type( ty ) Return p + "m"
- ' If TStringType( ty ) Return p + "S"
- ' If TWParamType( ty ) Return p + "W"
- ' If TLParamType( ty ) Return p + "L"
- ' If TLongIntType( ty ) Return p + "g"
- ' If TULongIntType( ty ) Return p + "G"
- ' If TArrayType( ty ) Then
- ' Return p + "a" + TransMangleType(TArrayType( ty ).elemType)
- ' End If
- ' If TObjectType( ty ) Then
- ' If Not TObjectType( ty ).classdecl.IsExtern()
- ' Local t:String = p + "T" + TObjectType( ty ).classDecl.ident
-
- ' ' handle case where class is also a template instance... and so on
- ' If TClassDecl(TObjectType(ty).classDecl) And TClassDecl(TObjectType(ty).classDecl).instArgs Then
- ' For Local ity:TType = EachIn TClassDecl(TObjectType(ty).classDecl).instArgs
- ' t :+ TransMangleType(ity)
- ' Next
- ' End If
- ' Return t
- ' Else
- ' If TObjectType( ty ).classdecl.IsInterface() Then
- ' Return p + "I" + TObjectType(ty).classDecl.ident
- ' ElseIf TObjectType( ty ).classdecl.IsStruct() Then
- ' Return p + "R" + TObjectType(ty).classDecl.ident
- ' Else
- ' Return p + "E" + TObjectType(ty).classDecl.ident
- ' End If
- ' End If
- ' End If
- ' If TFunctionPtrType( ty ) Then
- ' Local func:TFuncDecl = TFunctionPtrType( ty ).func
- ' Local s:String = "F" + MangleMethodArgs(func)
- ' ' For Local i:Int = 0 Until func.argDecls.length
- ' ' s :+ TransMangleType(func.argDecls[i].ty)
- ' ' Next
- ' Return s + "_" + TransMangleType(func.retType) + "_"
- ' End If
- ' If TEnumType( ty ) Return p + "e" + TEnumType( ty ).decl.ident
-
- ' Err "Unsupported type for name mangling : " + ty.ToString()
- ' End Function
- ' New internal, buffer-based worker
- Function TransMangleTypeToBuf(ty:TType, buf:TStringBuffer)
- Local p:String = TransManglePointer(ty)
- ' NOTE: Void does not get the pointer prefix (same behavior as original)
- If TVoidType(ty) Then
- buf.Append("v")
- Return
- End If
- If TByteType(ty) Then buf.Append(p).Append("b"); Return
- If TShortType(ty) Then buf.Append(p).Append("s"); Return
- If TIntType(ty) Then buf.Append(p).Append("i"); Return
- If TUIntType(ty) Then buf.Append(p).Append("u"); Return
- If TFloatType(ty) Then buf.Append(p).Append("f"); Return
- If TDoubleType(ty) Then buf.Append(p).Append("d"); Return
- If TLongType(ty) Then buf.Append(p).Append("l"); Return
- If TULongType(ty) Then buf.Append(p).Append("y"); Return
- If TSizeTType(ty) Then buf.Append(p).Append("z"); Return
- If TFloat64Type(ty) Then buf.Append(p).Append("h"); Return
- If TFloat128Type(ty) Then buf.Append(p).Append("k"); Return
- If TInt128Type(ty) Then buf.Append(p).Append("j"); Return
- If TDouble128Type(ty) Then buf.Append(p).Append("m"); Return
- If TStringType(ty) Then buf.Append(p).Append("S"); Return
- If TWParamType(ty) Then buf.Append(p).Append("W"); Return
- If TLParamType(ty) Then buf.Append(p).Append("L"); Return
- If TLongIntType(ty) Then buf.Append(p).Append("g"); Return
- If TULongIntType(ty) Then buf.Append(p).Append("G"); Return
- If TArrayType(ty) Then
- buf.Append(p).Append("a")
- TransMangleTypeToBuf(TArrayType(ty).elemType, buf)
- Return
- End If
- If TObjectType(ty) Then
- Local o:TObjectType = TObjectType(ty)
- If Not o.classDecl.IsExtern() Then
- buf.Append(p).Append("T").Append(o.classDecl.ident)
- ' If class is a template instance, append its instantiation argument manglings
- If TClassDecl(o.classDecl) And TClassDecl(o.classDecl).instArgs Then
- For Local ity:TType = EachIn TClassDecl(o.classDecl).instArgs
- TransMangleTypeToBuf(ity, buf)
- Next
- End If
- Return
- Else
- If o.classDecl.IsInterface() Then
- buf.Append(p).Append("I").Append(o.classDecl.ident)
- ElseIf o.classDecl.IsStruct() Then
- buf.Append(p).Append("R").Append(o.classDecl.ident)
- Else
- buf.Append(p).Append("E").Append(o.classDecl.ident)
- End If
- Return
- End If
- End If
- If TFunctionPtrType(ty) Then
- Local func:TFuncDecl = TFunctionPtrType(ty).func
- buf.Append("F").Append(MangleMethodArgs(func)).Append("_")
- TransMangleTypeToBuf(func.retType, buf)
- buf.Append("_")
- Return
- End If
- If TEnumType(ty) Then
- buf.Append(p).Append("e").Append(TEnumType(ty).decl.ident)
- Return
- End If
- Err "Unsupported type for name mangling : " + ty.ToString()
- End Function
- ' Backwards-compatible wrapper that still returns a String.
- Function TransMangleType:String(ty:TType)
- Local sb:TStringBuffer = New TStringBuffer
- TransMangleTypeToBuf(ty, sb)
- Return sb.ToString()
- End Function
- Method MangleMethod:String(fdecl:TFuncDecl)
- If (fdecl.IsMethod() And Not fdecl.ClassScope().IsStruct())Or fdecl.IsCtor() Then
- Return MangleMethodArgs(fdecl)
- Else
- Return MangleMethodRetType(fdecl) + MangleMethodArgs(fdecl)
- End If
- End Method
-
- Method MangleMethodRetType:String(fdecl:TFuncDecl)
- If fdecl.retType Then
- Return "_" + TransMangleType(fdecl.retType)
- Else
- Return "_v"
- End If
- End Method
-
- Function MangleMethodArgs:String(fdecl:TFuncDecl)
- Local s:TStringBuffer = New TStringBuffer
- For Local arg:TArgDecl = EachIn fdecl.argDecls
- If Not s.Length() Then
- s.Append( "_" )
- End If
- ' s.Append( TransMangleType(arg.ty) )
- TransMangleTypeToBuf(arg.ty, s)
- Next
- Return s.ToString()
- End Function
- Method equalsTorFunc:Int(classDecl:TClassDecl, func:TFuncDecl)
- If func.IdentLower() = "new" Or func.IdentLower() = "delete" Then
- Return True
- End If
- Return False
- End Method
- Method equalsBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
- If func.equalsBuiltIn > -1 Then
- Return func.equalsBuiltIn
- End If
-
- If checked Or func.IdentLower() = "tostring" Or func.IdentLower() = "compare" Or func.IdentLower() = "sendmessage" Or func.IdentLower() = "new" Or func.IdentLower() = "delete" Or func.IdentLower() = "hashcode" Then
- If classDecl.munged = "bbObjectClass" Then
- For Local decl:TFuncDecl = EachIn classDecl.Decls()
- If Not decl.IsSemanted() Then
- decl.Semant
- End If
- If decl.IdentLower() = func.IdentLower() Then
- Local res:Int = decl.EqualsFunc(func)
- If res Then
- func.equalsBuiltIn = True
- End If
- Return res
- End If
- Next
- End If
- If classDecl.superClass Then
- Return equalsBuiltInFunc(classDecl.superClass, func, True)
- End If
- End If
- func.equalsBuiltIn = False
- Return False
- End Method
- Method equalsIfcBuiltInFunc:Int(classDecl:TClassDecl, func:TFuncDecl, checked:Int = False)
- If checked Or func.IdentLower() = "delete" Then
- If classDecl.munged = "bbObjectClass" Then
- For Local decl:TFuncDecl = EachIn classDecl.Decls()
- If Not decl.IsSemanted() Then
- decl.Semant
- End If
- If decl.IdentLower() = func.IdentLower() Then
- Return decl.EqualsFunc(func)
- End If
- Next
- End If
- If classDecl.superClass Then
- Return equalsIfcBuiltInFunc(classDecl.superClass, func, True)
- End If
- End If
- Return False
- End Method
- Method MungFuncDecl( fdecl:TFuncDecl )
- If fdecl.munged Return
-
- Local funcs:TFuncDeclList=TFuncDeclList(funcMungs.ValueForKey( fdecl.ident ))
- If funcs
- For Local tdecl:TFuncDecl=EachIn funcs
- If fdecl.EqualsArgs( tdecl, True ) And fdecl.scope = tdecl.scope
- fdecl.munged=tdecl.munged
- Return
- EndIf
- Next
- Else
- funcs=New TFuncDeclList
- funcMungs.Insert fdecl.ident,funcs
- EndIf
- If fdecl.scope Then
- Local id:String = fdecl.ident
- If fdecl.attrs & FUNC_OPERATOR Then
- id = MungSymbol(id)
- End If
-
- fdecl.munged = fdecl.ParentScope().munged + "_" + id
-
- If Not equalsBuiltInFunc(fdecl.classScope(), fdecl) And Not fdecl.noMangle Then
- fdecl.munged :+ MangleMethod(fdecl)
- End If
-
- ' fields are lowercase with underscore prefix.
- ' a function pointer with FUNC_METHOD is a field function pointer.
- 'If TFieldDecl(fdecl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
- ' munged = "_" + munged.ToLower()
- 'End If
- Else
- fdecl.munged="bb_"+fdecl.ident
- End If
-
- funcs.AddLast fdecl
- End Method
-
- Method MungSymbol:String(sym:String)
- Select sym
- Case "*"
- Return "_mul"
- Case "/"
- Return "_div"
- Case "+"
- Return "_add"
- Case "-"
- Return "_sub"
- Case "&"
- Return "_and"
- Case "|"
- Return "_or"
- Case "~~"
- Return "_xor"
- Case "^"
- Return "_pow"
- Case ":*"
- Return "_muleq"
- Case ":/"
- Return "_diveq"
- Case ":+"
- Return "_addeq"
- Case ":-"
- Return "_subeq"
- Case ":&"
- Return "_andeq"
- Case ":|"
- Return "_oreq"
- Case ":~~"
- Return "_xoreq"
- Case ":^"
- Return "_poweq"
- Case "<"
- Return "_lt"
- Case "<="
- Return "_le"
- Case ">"
- Return "_gt"
- Case ">="
- Return "_ge"
- Case "="
- Return "_eq"
- Case "<>"
- Return "_ne"
- Case "mod"
- Return "_mod"
- Case "shl"
- Return "_shl"
- Case "shr"
- Return "_shr"
- Case ":mod"
- Return "_modeq"
- Case ":shl"
- Return "_shleq"
- Case ":shr"
- Return "_shreq"
- Case "[]"
- Return "_iget"
- Case "[]="
- Return "_iset"
- End Select
- Err "?? unknown symbol ?? : " + sym
- End Method
-
- Method MungDecl( decl:TDecl, addIfNotInScope:Int = False )
- If decl.munged Then
- ' ensure function args get into local scope correctly.
- If addIfNotInScope Then
- If Not mungScope.Contains( decl.munged ) Then
- mungScope.Insert(decl.munged, decl)
- End If
- End If
- Return
- End If
- Local fdecl:TFuncDecl=TFuncDecl( decl )
-
- ' apply mangling to methods and New (ctors)
- ' but don't apply mangling to function pointers
- If fdecl And fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
- MungFuncDecl( fdecl )
- Return
- End If
-
- Local id$=decl.ident
- Local munged:String
-
- 'this lot just makes output a bit more readable...
- ' Select ENV_LANG
- ' Case "js"
- ' If TModuleDecl( decl.scope ) Or TGlobalDecl( decl ) Or (fdecl And Not fdecl.IsMethod())
- ' munged=decl.ModuleScope().munged+"_"+id
- ' EndIf
- ' Case "as"
- ' If TModuleDecl( decl.scope )
- ' munged=decl.ModuleScope().munged+"_"+id
- ' EndIf
- ' Case "cs"
- ' If TClassDecl( decl )
- ' munged=decl.ModuleScope().munged+"_"+id
- ' EndIf
- ' Case "java"
- ' If TClassDecl( decl )
- ' munged=decl.ModuleScope().munged+"_"+id
- ' EndIf
- ' Case "cpp"
- If Not munged And TFuncDecl(decl) And TFuncDecl(decl).exported Then
- munged = id
- Else
- If TModuleDecl( decl.scope ) Or (TGlobalDecl(decl) And TModuleDecl(TGlobalDecl(decl).mscope))
- If TClassDecl(decl) And TClassDecl(decl).instArgs Then
- munged = "gimpl" + "_" + id
- Else
- munged=decl.ModuleScope().munged+"_"+id
- End If
-
- If TClassDecl(decl) And TClassDecl(decl).instArgs Then
- For Local ty:TType = EachIn TClassDecl(decl).instArgs
- munged :+ TransMangleType(ty)
- Next
- End If
- EndIf
- If TModuleDecl( decl )
- munged=decl.ModuleScope().munged+"_"+id
- EndIf
- End If
- ' End Select
- 'DebugStop
- If Not munged
- If TLocalDecl( decl )
- munged="bbt_"+id
- Else If TLoopLabelDecl(decl)
- munged = "_" + TLoopLabelDecl(decl).realIdent
- Else
- If decl.scope Then
- If TClassDecl(decl) And TClassDecl(decl).instArgs Then
- Local m:TStringBuffer = New TStringBuffer
- m.Append("gimpl").Append("_").Append(id)
- For Local ty:TType = EachIn TClassDecl(decl).instArgs
- ' m.Append(TransMangleType(ty))
- TransMangleTypeToBuf(ty, m)
- Next
- munged = m.ToString()
- Else
- munged = decl.scope.munged + "_" + id
- End If
-
- ' fields are lowercase with underscore prefix.
- ' a function pointer with FUNC_METHOD is a field function pointer.
- If TFieldDecl(decl) Or (TFuncDecl(decl) And (decl.attrs & FUNC_METHOD) And (decl.attrs & FUNC_PTR)) Then
- munged = "_" + munged.ToLower()
- End If
- Else
- munged="bb_"+id
- End If
- EndIf
- EndIf
- 'sanitize non-mung-able characters
- munged = TStringHelper.Sanitize(munged)
- Local scopeSearch:Int = 0
- If fdecl And Not fdecl.ClassScope() And Not (fdecl.attrs & FUNC_PTR)
- scopeSearch = 1
- End If
- 'add an increasing number to identifier if already used
- If MungScopeContains( munged, scopeSearch )
- If TFuncDecl(decl) And TFuncDecl(decl).exported Then
- Err "Cannot export duplicate identifiers : " + decl.ident
- End If
-
- Local i:Int=1
- Repeat
- i:+1
- Until Not MungScopeContains( munged + i, scopeSearch )
- munged :+ i
- EndIf
- mungScope.Insert(munged, decl)
- If scopeSearch Then
- globalMungScope.Insert(munged, decl)
- End If
- decl.munged=munged
-
- ' a function pointers' real function is stored in "func" - need to set its munged to match the parent.
- If TValDecl(decl) Then
- If TFunctionPtrType(TValDecl(decl).ty) Then
- TFunctionPtrType(TValDecl(decl).ty).func.munged = munged
- End If
- End If
-
- End Method
-
- Method MungScopeContains:Int( munged:String, scopeSearch:Int )
- If Not scopeSearch Then
- Return mungScope.Contains( munged )
- End If
-
- Return globalMungScope.Contains( munged )
- End Method
- Rem
- Method MungDecl( decl:TDecl )
- If decl.munged Return
- Local fdecl:TFuncDecl=TFuncDecl( decl )
- If fdecl And fdecl.IsMethod() Then
- ' DebugStop
- MungFuncDecl( fdecl )
- Return
- End If
-
- Local id:String=decl.ident,munged$,scope$
-
- If TLocalDecl( decl )
- scope="$"
- munged="t_"+id
- Else If TClassDecl( decl )
- scope=""
- munged="c_"+id
- Else If TModuleDecl( decl )
- scope=""
- munged="bb_"+id
- Else If TClassDecl( decl.scope )
- scope=decl.scope.munged
- munged="m_"+id
- Else If TModuleDecl( decl.scope )
- 'If ENV_LANG="cs" Or ENV_LANG="java"
- ' scope=decl.scope.munged
- ' munged="g_"+id
- 'Else
- scope=""
- munged=decl.scope.munged+"_"+id
- 'EndIf
- Else
- InternalErr
- EndIf
-
- Local set:TMap=TMap(mungedScopes.ValueForKey( scope ))
- If set
- If set.Contains( munged.ToLower() )
- Local id:Int=1
- Repeat
- id :+ 1
- Local t$=munged+id
- If set.Contains( t.ToLower() ) Continue
- munged=t
- Exit
- Forever
- End If
- Else
- If scope="$"
- Print "OOPS2"
- InternalErr
- EndIf
- set=New TMap
- mungedScopes.Insert scope,set
- End If
- set.Insert munged.ToLower(), ""
- decl.munged=munged
- End Method
- End Rem
-
- Method Bra$( str$ )
- If str.StartsWith( "(" ) And str.EndsWith( ")" )
- Local n:Int=1
- For Local i:Int=1 Until str.Length-1
- Select str[i]
- Case Asc("(")
- n:+1
- Case Asc(")")
- n:-1
- If Not n Return "("+str+")"
- End Select
- Next
- If n=1 Return str
- ' If str.FindLast("(")<str.Find(")") Return str
- EndIf
- Return "("+str+")"
- End Method
-
- 'Utility C/C++ style...
- Method Enquote$( str$ )
- Return LangEnquote( str )
- End Method
-
- Method EscapeChars:String(str:String)
- If str Then
- Local found:Int = False
- For Local i:Int = 0 Until str.length
- If str[i] > 127 Then
- found = True
- Exit
- End If
- Next
-
- If Not found Then
- Return str
- End If
-
- Local s:String
-
- For Local i:Int = 0 Until str.length
- Local char:Int = str[i]
-
- If char < 128 Then
- s :+ Chr(char)
- Else
- s :+ "~~" + char + "~~"
- End If
- Next
-
- Return s
- End If
- End Method
- Method TransUnaryOp$( op$ )
- Select op
- Case "+" Return "+"
- Case "-" Return "-"
- Case "~~" Return op
- Case "not" Return "!"
- End Select
- InternalErr "TTranslator.TransUnaryOp"
- End Method
-
- Method TransBinaryOp$( op$,rhs$ )
- 'DebugLog "TransBinaryOp '" + op + "' : '" + rhs + "'"
- op = mapSymbol(op)
- Select op
- Case "+","-"
- If rhs.StartsWith( op ) Return op+" "
- Return op
- Case "*","/" Return op
- Case "shl" Return "<<"
- Case "shr" Return ">>"
- Case "sar" Return ">>"
- Case "mod" Return " % "
- Case "and" Return " && "
- Case "or" Return " || "
- Case "=" Return "=="
- Case "<>" Return "!="
- Case "<","<=",">",">=" Return op
- Case "=<" Return "<="
- Case "=>" Return ">="
- Case "&","|" Return op
- Case "~~" Return "^"
- Case "<<", ">>" Return Op
- Case "%" Return Op
- End Select
- InternalErr "TTranslator.TransBinaryOp"
- End Method
-
- Method TransAssignOp$( op$ )
- op = mapSymbol(op)
- Select op
- Case ":mod" Return "%="
- Case ":shl" Return "<<="
- Case ":shr" Return ">>="
- Case ":sar" Return ">>="
- End Select
- Return op
- End Method
-
- Method ExprPri:Int( expr:TExpr )
- '
- '1=primary,
- '2=postfix
- '3=prefix
- '
- If TNewObjectExpr( expr )
- Return 3
- Else If TUnaryExpr( expr )
- Select TUnaryExpr( expr ).op
- Case "+","-","~~","not" Return 3
- End Select
- InternalErr "TTranslator.ExprPri"
- Else If TBinaryExpr( expr )
- Select TBinaryExpr( expr ).op
- Case "^" Return 4
- Case "*","/","mod","%" Return 5
- Case "+","-" Return 6
- Case "shl","shr", "sar","<<", ">>" Return 7
- Case "<","<=",">",">=", "=<", "=>" Return 8
- Case "=","<>" Return 9
- Case "&" Return 10
- Case "~~" Return 11
- Case "|" Return 12
- Case "and" Return 13
- Case "or" Return 14
- End Select
- InternalErr "TTranslator.ExprPri"
- EndIf
- Return 2
- End Method
-
- Method TransSubExpr$( expr:TExpr,pri:Int=2 )
- Local t_expr$=expr.Trans()
- 'If expr.exprType._flags & TTYPE.T_VAR Then
- ' t_expr = Bra("*" + t_expr)
- 'End If
- If ExprPri( expr )>pri t_expr=Bra( t_expr )
- Return t_expr
- End Method
-
- Method TransExprNS$( expr:TExpr )
- If TVarExpr( expr ) Return expr.Trans()
- If TConstExpr( expr ) Return expr.Trans()
- Return CreateLocal( expr )
- End Method
-
- Method CreateLocal$( expr:TExpr, init:Int = True, vol:Int = True )
- Local tmp:TLocalDecl=New TLocalDecl.Create( "",expr.exprType,expr, True, , vol )
- MungDecl tmp
- Emit TransLocalDecl( tmp,expr, True, init )+";"
- EmitCoverage(_errInfo)
- EmitGDBDebug(_errInfo)
-
- Return tmp.munged
- End Method
- '***** Utility *****
- Method TransLocalDecl$( decl:TLocalDecl,init:TExpr, declare:Int = False, outputInit:Int = True ) Abstract
- Method TransGlobalDecl$( gdecl:TGlobalDecl ) Abstract
-
- Method EmitPushErr()
- End Method
-
- Method EmitSetErr( errInfo$ )
- End Method
-
- Method EmitPopErr()
- End Method
-
- '***** Declarations *****
-
- Method TransGlobal$( decl:TGlobalDecl ) Abstract
-
- Method TransField$( decl:TFieldDecl,lhs:TExpr ) Abstract
-
- Method TransFunc$( decl:TFuncDecl,args:TExpr[],lhs:TExpr, sup:Int = False, scope:TScopeDecl = Null ) Abstract
-
- Method TransSuperFunc$( decl:TFuncDecl,args:TExpr[], scope:TScopeDecl ) Abstract
-
-
- '***** Expressions *****
-
- Method TransConstExpr$( expr:TConstExpr ) Abstract
-
- Method TransNewObjectExpr$( expr:TNewObjectExpr ) Abstract
-
- Method TransNewArrayExpr$( expr:TNewArrayExpr ) Abstract
-
- Method TransSelfExpr$( expr:TSelfExpr ) Abstract
-
- Method TransCastExpr$( expr:TCastExpr ) Abstract
-
- Method TransUnaryExpr$( expr:TUnaryExpr ) Abstract
-
- Method TransBinaryExpr$( expr:TBinaryExpr ) Abstract
-
- Method TransIndexExpr$( expr:TIndexExpr ) Abstract
-
- Method TransSliceExpr$( expr:TSliceExpr ) Abstract
-
- Method TransArrayExpr$( expr:TArrayExpr ) Abstract
-
- Method TransArraySizeExpr$ ( expr:TArraySizeExpr ) Abstract
-
- Method TransIntrinsicExpr$( decl:TDecl,expr:TExpr,args:TExpr[]=Null ) Abstract
-
- Method TransArgs$( args:TExpr[],decl:TFuncDecl, objParam:String = Null, objectNew:Int = False ) Abstract
- Method EmitDebugEnterScope(block:TBlockDecl) Abstract
-
- Method EmitLocalDeclarations(decl:TScopeDecl, v:TValDecl = Null) Abstract
-
- Method TransType$( ty:TType, ident:String, fpReturnTypeFunctionArgs:String = Null, fpReturnTypeClassFunc:Int = False) Abstract
- Method TransObject:String(decl:TScopeDecl, this:Int = False) Abstract
-
- Method BeginLocalScope()
- mungStack.Push mungScope
- mungScope:TMap=New TMap'<TDecl>
- ' mungedScopes.Insert "$",New TMap
-
- If opt_debug Then
- localScopeStack.Push localScope
- localScope = New TStackList
- End If
- End Method
-
- Method EndLocalScope()
- mungScope=TMap(mungStack.Pop())
- ' mungedScopes.Insert "$",Null
- If opt_debug Then
- localScope = TStackList(localScopeStack.Pop())
- End If
- End Method
- Rem
- Method MungMethodDecl( fdecl:TFuncDecl )
- If fdecl.munged Return
-
- If fdecl.overrides
- MungMethodDecl fdecl.overrides
- fdecl.munged=fdecl.overrides.munged
- Return
- EndIf
-
- Local funcs:=funcMungs.Get( fdecl.ident )
- If funcs
- For Local tdecl:=EachIn funcs
- If fdecl.EqualsArgs( tdecl )
- fdecl.munged=tdecl.munged
- Return
- EndIf
- Next
- Else
- funcs=New FuncDeclList
- funcMungs.Set fdecl.ident,funcs
- EndIf
-
- Local id:=fdecl.ident
- If mungedFuncs.Contains( id )
- Local n:=1
- Repeat
- n+=1
- id=fdecl.ident+String(n)
- Until Not mungedFuncs.Contains( id )
- EndIf
-
- mungedFuncs.Set id,fdecl
- fdecl.munged="p_"+id
- funcs.AddLast fdecl
- End
- End Rem
- '***** Simple statements *****
-
- 'Expressions
- Method TransStmtExpr$( expr:TStmtExpr )
- Local t$=expr.stmt.Trans()
- If t Emit t+";"
- Return expr.expr.Trans()
- End Method
-
- Method TransTemplateCast$( ty:TType,src:TType,expr$ )
- Return expr
- End Method
-
- Method TransVarExpr$( expr:TVarExpr )
- Local decl:TVarDecl=TVarDecl( expr.decl.actual )
- If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null )
-
- If TLocalDecl( decl ) Then
- If decl.ty._flags & TType.T_VAR Then
- Return "*" + decl.munged
- Else
- Return decl.munged
- End If
- End If
-
- If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),Null )
-
- If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
-
- InternalErr "TTranslator.TransVarExpr"
- End Method
-
- Method TransMemberVarExpr$( expr:TMemberVarExpr )
- Local decl:TVarDecl=TVarDecl( expr.decl.actual )
-
- If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr )
-
- If TFieldDecl( decl ) Return TransField( TFieldDecl( decl ),expr.expr )
- If TGlobalDecl( decl ) Return TransGlobal( TGlobalDecl( decl ) )
- InternalErr "TTranslator.TransMemberVarExpr"
- End Method
-
- Method TransInvokeExpr$( expr:TInvokeExpr )
- Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
- If Not decl.munged Then
- MungDecl decl
- End If
-
- 'If (decl.attrs & FUNC_PTR) And (decl.attrs & FUNC_INIT) And Not expr.InvokedWithBraces Return decl.munged
-
- 'If ((decl.attrs & FUNC_PTR) Or (expr.decl.attrs & FUNC_PTR)) And Not expr.InvokedWithBraces Return decl.munged
-
- 'If Not expr.InvokedWithBraces And expr.IsRhs Return decl.munged
-
- ' if the call was a statement (even one written without parentheses), then invokedWithBraces is true
- ' so no complicated checks are needed here; if invokedWithBraces is false, this is definitely not a call
- If Not expr.InvokedWithBraces Then Return decl.munged
-
- If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,Null,expr.args )
-
- If processingReturnStatement = 1 Then
- If decl Then
- processingReturnStatement :+ 1
- Return CreateLocal(expr)
- End If
- Else
- Return TransFunc( TFuncDecl(decl),expr.args,Null )
- End If
-
- InternalErr "TTranslator.TransInvokeExpr"
- End Method
-
- Method TransInvokeMemberExpr$( expr:TInvokeMemberExpr )
- Local decl:TFuncDecl=TFuncDecl( expr.decl.actual ),t$
- If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr.expr,expr.args )
-
- If processingReturnStatement = 1 Then
- If decl Then
- processingReturnStatement :+ 1
- Return CreateLocal(expr)
- End If
- Else
- Return TransFunc( TFuncDecl(decl),expr.args,expr.expr )
- End If
-
- InternalErr "TTranslator.TransInvokeMemberExpr"
- End Method
-
- Method TransInvokeSuperExpr$( expr:TInvokeSuperExpr )
- Local decl:TFuncDecl=TFuncDecl( expr.origFuncDecl.actual ),t$
- If decl.munged.StartsWith( "$" ) Return TransIntrinsicExpr( decl,expr )
-
- If processingReturnStatement = 1 Then
- If decl Then
- processingReturnStatement :+ 1
- Return CreateLocal(expr)
- End If
- Else
- If decl Return TransSuperFunc( TFuncDecl( expr.funcDecl ),expr.args, expr.classScope )
- End If
-
- InternalErr "TTranslator.TransInvokeSuperExpr"
- End Method
-
- Method TransFuncCallExpr:String( expr:TFuncCallExpr )
- If TIndexExpr(expr.expr) And TArrayType(TIndexExpr(expr.expr).expr.exprType) And TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType) Then
- Local decl:TDecl = TFunctionPtrType(TArrayType(TIndexExpr(expr.expr).expr.exprType).elemType).func.actual
- decl.Semant()
- expr.args=expr.CastArgs( expr.args,TFuncDecl(decl) )
- Return expr.expr.Trans() + TransArgs(expr.args, TFuncDecl(decl))
- End If
- ' hmmm, complicated - a function returning and invoking a function pointer...
- If TInvokeExpr(expr.expr) And TFunctionPtrType(TInvokeExpr(expr.expr).exprType) Then
- Local decl:TDecl = TFunctionPtrType(TInvokeExpr(expr.expr).exprType).func.actual
- decl.Semant()
- expr.args=expr.CastArgs( expr.args,TFuncDecl(decl) )
- Return expr.expr.Trans() + TransArgs(expr.args, TFuncDecl(decl))
- End If
- If TInvokeMemberExpr(expr.expr) Then
- Local decl:TFuncDecl = TFuncDecl(TInvokeMemberExpr(expr.expr).decl.actual)
- decl.Semant()
- Return expr.expr.Trans()
- End If
-
- InternalErr "TTranslator.TransFuncCallExpr"
- End Method
-
- Method TransExprStmt$( stmt:TExprStmt )
- Return stmt.expr.TransStmt()
- End Method
-
- Method TransAssignStmt$( stmt:TAssignStmt )
- If stmt.rhs Return stmt.lhs.TransVar()+TransAssignOp(stmt.op)+stmt.rhs.Trans()
- Return stmt.lhs.Trans()
- End Method
-
- Method TransReturnStmt$( stmt:TReturnStmt )
- Local t:TStringBuffer = New TStringBuffer(128)
- t.Append( "return" )
- unreachable=True
- If stmt.expr Then
- If TObjectType(stmt.expr.exprType) And TNullDecl(TObjectType(stmt.expr.exprType).classDecl) Then
- If IsPointerType(stmt.fRetType, 0, TType.T_POINTER) Or IsNumericType(stmt.fRetType) Then
- t.Append( " 0" )
- End If
- If TStringType(stmt.fRetType) Then
- t.Append( " &bbEmptyString" )
- End If
- If TArrayType(stmt.fRetType) Then
- t.Append( " &bbEmptyArray" )
- End If
- Else
-
- If TObjectType(stmt.expr.exprType) And TObjectType(stmt.expr.exprType).classDecl.IsStruct() And TConstExpr(stmt.expr) And Not TConstExpr(stmt.expr).value Then
- Local lvar:String = CreateLocal(stmt.expr)
- t.Append( " " ).Append( lvar )
- Else
- Local s:String
-
- ' cast to function return type
- If TObjectType(stmt.fRetType) And Not TObjectType(stmt.fRetType).classDecl.IsStruct() Then
- s :+ Bra(TransType(stmt.fRetType, ""))
- End If
- s :+ stmt.expr.Trans()
-
- ' we have some temp variables that need to be freed before we can return
- ' put the results into a new variable, and return that.
- If customVarStack.Count() > 0 Then
- If Not TFunctionPtrType( stmt.expr.exprType ) Then
- Emit TransType(stmt.expr.exprType, "rt_") + " rt_ = " + s + ";"
- Else
- Emit TransType(stmt.expr.exprType, "rt_") + " = " + s + ";"
- End If
- t.Append( " rt_" )
- Else
- t.Append( " " ).Append( s )
- End If
- End If
- End If
-
- End If
- FreeVarsIfRequired()
-
- ' if this is a Delete() method, we need to call the dtor first
- Local funcScope:TFuncDecl = _env.FuncScope()
- If funcScope And funcScope.IdentLower() = "delete" Then
- Local classScope:TClassDecl = funcScope.ClassScope()
- If classScope Then
- EmitClassDeclDeleteDtor(classScope)
- End If
- End If
-
- Return t.ToString()
- End Method
-
- Method NextExitId:Int(bc:TTryBreakCheck)
- If Not bc.exitId Then
- exitLabelId :+ 1
- bc.exitId = exitLabelId
- End If
-
- Return bc.exitId
- End Method
- Method NextContId:Int(bc:TTryBreakCheck)
- If Not bc.contId Then
- contLabelId :+ 1
- bc.contId = contLabelId
- End If
-
- Return bc.contId
- End Method
-
- Method TransContinueStmt$( stmt:TContinueStmt )
- Local returnStr:String
-
- Local contLoop:TStmt
- ' if we are continuing with a loop label, we'll need to find it in the stack
- If stmt.label And TLoopLabelExpr(stmt.label) Then
- contLoop = TLoopLabelExpr(stmt.label).loop
- End If
- ' get Try statements in the stack in this loop
- Local tryStmts:TTryStmt[] = LoopTryStmts(contLoop)
- Local count:Int = tryStmts.length
- Local nowUnreachable:Int = False
- If count > 0 Then
- Local bc:TTryBreakCheck = GetTopLoop(contLoop)
- If bc Then
- NextContId(bc)
- For Local i:Int = 0 Until count
- Emit "bbExLeave();"
- If opt_debug Then Emit "bbOnDebugPopExState();"
-
- ' in debug we also roll back scope from first Try in scope down to the loop scope itself
- If opt_debug And (i = count - 1) And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
- Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_LOOP)
- For Local n:Int = 0 Until loopCount
- Emit "bbOnDebugLeaveScope();"
- Next
- End If
- If tryStmts[i].finallyStmt Then
- Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("continue")
- MungDecl returnLabelDecl
- EmitFinallyJmp tryStmts[i].finallyStmt, returnLabelDecl
- Emit TransLabel(returnLabelDecl)
- End If
- Next
- Emit "goto " + TransLabelCont(bc, False)
- Else
- InternalErr "TTranslator.TransContinueStmt"
- End If
- Else
- ' For debug builds, we need to rollback the local scope stack correctly
- count = 0
-
- If opt_debug And TLoopStmt(contLoop) And Not TLoopStmt(contLoop).block.IsNoDebug() Then
- count = LoopLocalScopeDepth(contLoop)
- End If
-
- If count > 0 Then
- Local bc:TTryBreakCheck = GetTopLocalLoop(contLoop)
- If bc Then
- NextContId(bc)
- For Local i:Int = 0 Until count
- Emit "bbOnDebugLeaveScope();"
- Next
- Emit "goto " + TransLabelCont(bc, False)
- Else
- InternalErr "TTranslator.TransContinueStmt"
- End If
- Else
- If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
- count = LoopLocalScopeDepth(Null)
- End If
- For Local i:Int = 0 Until count
- Emit "bbOnDebugLeaveScope();"
- Next
-
- ' No Try statements in the stack here..
- If stmt.label And TLoopLabelExpr(stmt.label) Then
- Emit "goto " + TransLoopLabelCont(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
- Else
- returnStr = "continue"
- End If
- End If
- End If
-
- unreachable = True
- Return returnStr
- End Method
-
- Method TransBreakStmt$( stmt:TBreakStmt )
- Local returnStr:String
-
- Local brkLoop:TStmt
- ' if we are exiting with a loop label, we'll need to find it in the stack
- If stmt.label And TLoopLabelExpr(stmt.label) Then
- brkLoop = TLoopLabelExpr(stmt.label).loop
- End If
- ' get Try statements in the stack in this loop
- Local tryStmts:TTryStmt[] = LoopTryStmts(brkLoop)
- Local count:Int = tryStmts.length
- Local nowUnreachable:Int = False
- If count > 0 Then
- Local bc:TTryBreakCheck = GetTopLoop(brkLoop)
- If bc Then
- NextExitId(bc)
- For Local i:Int = 0 Until count
- Emit "bbExLeave();"
- If opt_debug Then Emit "bbOnDebugPopExState();"
-
- ' in debug we also roll back scope from first Try in scope down to the loop scope itself
- If opt_debug And (i = count - 1) And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
- Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_LOOP)
- For Local n:Int = 0 Until loopCount
- Emit "bbOnDebugLeaveScope();"
- Next
- End If
-
- If tryStmts[i].finallyStmt Then
- Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("break")
- MungDecl returnLabelDecl
- EmitFinallyJmp tryStmts[i].finallyStmt, returnLabelDecl
- Emit TransLabel(returnLabelDecl)
- End If
- Next
- Emit "goto " + TransLabelExit(bc, False)
- Else
- InternalErr "TTranslator.TransBreakStmt"
- End If
- Else
- ' For debug builds, we need to rollback the local scope stack correctly
- count = 0
-
- If opt_debug And TLoopStmt(brkLoop) And Not TLoopStmt(brkLoop).block.IsNoDebug() Then
- count = LoopLocalScopeDepth(brkLoop)
- End If
-
- If count > 0 Then
- Local bc:TTryBreakCheck = GetTopLocalLoop(brkLoop)
- If bc Then
- NextExitId(bc)
- For Local i:Int = 0 Until count
- Emit "bbOnDebugLeaveScope();"
- Next
- Emit "goto " + TransLabelExit(bc, False)
- Else
- InternalErr "TTranslator.TransBreakStmt"
- End If
- Else
- If opt_debug And stmt.loop And Not stmt.loop.block.IsNoDebug() Then
- count = LoopLocalScopeDepth(Null)
- End If
- For Local i:Int = 0 Until count
- Emit "bbOnDebugLeaveScope();"
- Next
-
- ' No Try statements in the stack here..
- If stmt.label And TLoopLabelExpr(stmt.label) Then
- Emit "goto " + TransLoopLabelExit(TLoopLabelExpr(stmt.label).loop.loopLabel.realIdent, False)
- Else
- returnStr = "break"
- End If
- End If
- End If
-
- unreachable = True
- broken :+ 1
- Return returnStr
- End Method
-
- Method TransTryStmt$( stmt:TTryStmt )
- End Method
-
- Method EmitFinallyJmp(stmt:TFinallyStmt, returnLabel:TLoopLabelDecl) Abstract
-
- Method TransThrowStmt$( stmt:TThrowStmt )
- End Method
- Method TransBuiltinExpr$( expr:TBuiltinExpr )
- If TAscExpr(expr) Return TransAscExpr(TAscExpr(expr))
- If TChrExpr(expr) Return TransChrExpr(TChrExpr(expr))
- If TLenExpr(expr) Return TransLenExpr(TLenExpr(expr))
- If TSizeOfExpr(expr) Return TransSizeOfExpr(TSizeOfExpr(expr))
- If TStackAllocExpr(expr) Return TransStackAllocExpr(TStackAllocExpr(expr))
- If TFieldOffsetExpr(expr) Return TransFieldOffsetExpr(TFieldOffsetExpr(expr))
- Err "TODO : TransBuiltinExpr()"
- End Method
-
- Method TransAscExpr:String(expr:TAscExpr)
- End Method
- Method TransChrExpr:String(expr:TChrExpr)
- End Method
- Method TransLenExpr:String(expr:TLenExpr)
- End Method
- Method TransSizeOfExpr:String(expr:TSizeOfExpr)
- End Method
- Method TransStackAllocExpr:String(expr:TStackAllocExpr)
- End Method
- Method TransFieldOffsetExpr:String(expr:TFieldOffsetExpr)
- End Method
-
- Method TransIdentTypeExpr:String(expr:TIdentTypeExpr) Abstract
-
- Method TransLabelCont:String(bc:TTryBreakCheck, jmp:Int = True)
- If jmp Then
- Return "_contjmp" + bc.contId + ": ;"
- Else
- Return "_contjmp" + bc.contId + ";"
- End If
- End Method
-
- Method TransLabelExit:String(bc:TTryBreakCheck, jmp:Int = True)
- If jmp Then
- Return "_exitjmp" + bc.exitId + ": ;"
- Else
- Return "_exitjmp" + bc.exitId + ";"
- End If
- End Method
- Method TransLoopLabelCont:String(id:String, jmp:Int = True)
- If jmp Then
- Return "_loopcont_" + id.ToLower() + ": ;"
- Else
- Return "_loopcont_" + id.ToLower() + ";"
- End If
- End Method
- Method TransLoopLabelExit:String(id:String, jmp:Int = True)
- If jmp Then
- Return "_loopexit_" + id.ToLower() + ": ;"
- Else
- Return "_loopexit_" + id.ToLower() + ";"
- End If
- End Method
-
- Method TransLabel:String(labelDecl:TLoopLabelDecl)
- Return labelDecl.munged + ":;"
- End Method
- '***** Block statements - all very C like! *****
-
- Method Emit( t$, useIndent:Int = True )
- If Not t Return
- If useIndent
- If t.StartsWith( "}" )
- indent=indent[..indent.Length-1]
- EndIf
- End If
- LINES.AddLast indent+t
- 'code+=indent+t+"~n"
- If useIndent
- If t.EndsWith( "{" )
- indent:+"~t"
- EndIf
- End If
- End Method
-
- Method JoinLines$( file:String )
- Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
-
- If _lines Then
- Local code$=_lines.Join( "~n" )
- _lines.Clear
- Return code
- End If
- End Method
-
- 'returns and resets unreachable status
- Method EmitBlock:Int( block:TBlockDecl )
- Local stmtCount:Int
- 'DebugStop
- 'If ENV_CONFIG="debug"
- ' If TFuncDecl( block ) EmitPushErr
- 'EndIf
- PushEnv block
-
- ' enter scope
- If opt_debug And Not block.IsNoDebug() And Not block.generated Then
- PushLoopLocalStack(block)
- EmitDebugEnterScope(block)
- End If
- For Local stmt:TStmt=EachIn block.stmts
-
- _errInfo=stmt.errInfo
-
- If unreachable
- ' Statements following cannot be reached - maybe we have Returned, etc
- ' So don't process any more for this block - they won't be generated now!
- Exit
- EndIf
- Rem
- If ENV_CONFIG="debug"
- Local rs:TReturnStmt=TReturnStmt( stmt )
- If rs
- If rs.expr
- EmitSetErr stmt.errInfo
- Local t_expr$=TransExprNS( rs.expr )
- EmitPopErr
- Emit "return "+t_expr+";"
- Else
- EmitPopErr
- Emit "return;"
- EndIf
- unreachable=True
- Continue
- EndIf
- EmitSetErr stmt.errInfo
- EndIf
- End Rem
- If opt_debug And Not block.IsNoDebug() Then
- ' only for user-made code
- If Not stmt.generated Then
- EmitDebugStmtErrInfo(stmt.errInfo, stmtCount)
- stmtCount :+ 1
- End If
-
- End If
- EmitCoverage(stmt)
- EmitGDBDebug(stmt)
-
- If TReturnStmt(stmt) And Not tryStack.IsEmpty() Then
- processingReturnStatement = 1
- End If
-
- Local t$=stmt.Trans()
-
- processingReturnStatement = 0
-
- If TReturnStmt(stmt) Then
- Local stackSize:Int = tryStack.Count()
- Local count:Int
-
- If stackSize Then
- For Local tryStmt:TTryStmt = EachIn tryStack
- Emit "bbExLeave();"
- If opt_debug Then Emit "bbOnDebugPopExState();"
-
- ' in debug we need to roll back scope from first Try in scope down to the function scope
- If opt_debug And (count = stackSize - 1) And Not block.IsNoDebug() Then
- Local loopCount:Int = TryDownToBlockScopeCount(BLOCK_FUNCTION)
- For Local n:Int = 0 Until loopCount
- Emit "bbOnDebugLeaveScope();"
- Next
- End If
-
- If tryStmt.finallyStmt Then
- Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("return")
- MungDecl returnLabelDecl
- EmitFinallyJmp tryStmt.finallyStmt, returnLabelDecl
- Emit TransLabel(returnLabelDecl)
- End If
-
- count :+ 1
- Next
- Else
- If opt_debug And Not block.IsNoDebug() Then
- For Local b:TBlockDecl = EachIn localScope
- Emit "bbOnDebugLeaveScope();"
- Next
- End If
- End If
- End If
-
- If t Emit t+";"
- If DEBUG And debugOut Then
- Emit debugOut
- debugOut = Null
- End If
-
- Local v:String = String(customVarStack.Pop())
- While v
- Emit "bbMemFree" + Bra(v) + ";"
- v = String(customVarStack.Pop())
- Wend
-
- Next
- If opt_debug And Not block.IsNoDebug() And Not block.generated Then
- PopLoopLocalStack()
- If Not unreachable Then
- Emit "bbOnDebugLeaveScope();"
- End If
- End If
- Local r:Int=unreachable
- unreachable=False
- PopEnv
- Return r
- End Method
-
- Method TransDeclStmt$( stmt:TDeclStmt, declare:Int = False )
- Local decl:TLocalDecl=TLocalDecl( stmt.decl )
- If decl
- MungDecl decl
- ' only generate local declarations once.
- If decl.generated Then
- If Not decl.done Then
- decl.done = True
- Else
- Return ""
- End If
- End If
- Return TransLocalDecl( decl,decl.init, decl.generated Or declare )
- EndIf
- Local cdecl:TConstDecl=TConstDecl( stmt.decl )
- If cdecl
- Return Null
- EndIf
- Local gdecl:TGlobalDecl=TGlobalDecl( stmt.decl )
- If gdecl Then
- MungDecl gdecl
- If gdecl.inited Return Null
- Return TransGlobalDecl( gdecl )
- End If
- InternalErr "TTranslator.TransDeclStmt"
- End Method
-
- Method TransIfStmt$( stmt:TIfStmt )
- If TConstExpr( stmt.expr )
- If TConstExpr( stmt.expr ).value
- Emit "{"
- EmitLocalDeclarations(stmt.thenBlock)
- If EmitBlock( stmt.thenBlock ) unreachable=True
- Emit "}"
- Else If stmt.elseBlock And stmt.elseBlock.stmts.First()
- Emit "{"
- EmitLocalDeclarations(stmt.elseBlock)
- If EmitBlock( stmt.elseBlock ) unreachable=True
- Emit "}"
- EndIf
- Else If stmt.elseBlock And stmt.elseBlock.stmts.First()
- Emit "if"+Bra( stmt.expr.Trans() )+"{"
- EmitLocalDeclarations(stmt.thenBlock)
- FreeVarsIfRequired(False)
- PushVarScope
- Local unr:Int=EmitBlock( stmt.thenBlock )
- PopVarScope
- Emit "}else{"
- EmitLocalDeclarations(stmt.elseBlock)
- FreeVarsIfRequired
- Local unr2:Int=EmitBlock( stmt.elseBlock )
- Emit "}"
- If unr And unr2 unreachable=True
- Else
- ' Emit "if"+ Bra(TransCondition(stmt.expr)) + "{"
- ' If TVarExpr(stmt.expr) Then
- ' If TObjectType(TVarExpr(stmt.expr).exprType) Then
- ' Emit "if"+Bra( stmt.expr.Trans() + "!= &bbNullObject") + "{"
- ' Else If TStringType(TVarExpr(stmt.expr).exprType) Then
- ' Emit "if"+Bra( stmt.expr.Trans() + "!= &bbEmptyString") + "{"
- ' Else
- ' Emit "if"+Bra( stmt.expr.Trans() )+"{"
- ' End If
- ' Else
- Emit "if"+Bra( stmt.expr.Trans() )+"{"
- FreeVarsIfRequired(False)
- ' End If
- EmitLocalDeclarations(stmt.thenBlock)
- PushVarScope
- Local unr:Int=EmitBlock( stmt.thenBlock )
- PopVarScope
- Emit "}"
- FreeVarsIfRequired
- EndIf
- End Method
-
- Method FreeVarsIfRequired(removeFromStack:Int = True)
- If removeFromStack
- Local v:String = String(customVarStack.Pop())
- While v
- Emit "bbMemFree" + Bra(v) + ";"
- v = String(customVarStack.Pop())
- Wend
- Else
- For Local v:String = EachIn customVarStack
- Emit "bbMemFree" + Bra(v) + ";"
- Next
- End If
- End Method
-
- ' Method TransCondition:String(expr:TExpr)
- ' If TVarExpr(expr) Then
- ' If TObjectType(TVarExpr(expr).exprType) Then
- ' Return Bra( expr.Trans() + "!= &bbNullObject")
- ' Else If TStringType(TVarExpr(expr).exprType) Then
- ' Return Bra( expr.Trans() + "!= &bbEmptyString")
- ' Else
- ' Return Bra( expr.Trans() )
- ' End If
- ' Else
- ' Return Bra( expr.Trans() )
- ' End If
- ' End Method
-
- Method TransWhileStmt$( stmt:TWhileStmt )
- Local nbroken:Int=broken
- Emit "while"+Bra( stmt.expr.Trans() )+"{"
-
- Local check:TTryBreakCheck = New TTryBreakCheck
- check.stmt = stmt
- PushLoopTryStack(check)
- If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
- PushLoopLocalStack(check)
- End If
- EmitLocalDeclarations(stmt.block)
- Local unr:Int=EmitBlock( stmt.block )
- If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
- PopLoopLocalStack
- End If
- PopLoopTryStack
-
- If check.contId Then
- Emit TransLabelCont(check)
- End If
- If stmt.loopLabel Then
- MungDecl stmt.loopLabel
- Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
- End If
-
- Emit "}"
- If check.exitId Then
- Emit TransLabelExit(check)
- End If
- If stmt.loopLabel Then
- Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
- End If
-
- If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
- broken=nbroken
- End Method
- Method TransRepeatStmt$( stmt:TRepeatStmt )
- Local nbroken:Int=broken
- SetOutputTemp()
- Emit "do{"
-
- Local check:TTryBreakCheck = New TTryBreakCheck
- check.stmt = stmt
- PushLoopTryStack(check)
- If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
- PushLoopLocalStack(check)
- End If
- EmitLocalDeclarations(stmt.block)
- Local unr:Int=EmitBlock( stmt.block )
- If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
- PopLoopLocalStack
- End If
- PopLoopTryStack
- If check.contId Then
- Emit TransLabelCont(check)
- End If
- If stmt.loopLabel Then
- MungDecl stmt.loopLabel
- Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
- End If
-
- SetOutput("source")
- Local s:String = "}while(!"+Bra( stmt.expr.Trans() )+");"
-
- SetOutputTemp(True)
-
- Emit s
- If check.exitId Then
- Emit TransLabelExit(check)
- End If
- If stmt.loopLabel Then
- Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
- End If
- If broken=nbroken And TConstExpr( stmt.expr ) And Not TConstExpr( stmt.expr ).value unreachable=True
- broken=nbroken
- End Method
- Method TransForStmt$( stmt:TForStmt )
- Local nbroken:Int=broken
- Local init$
- Local decl:Int
- Local vdecl:TValDecl
- If TDeclStmt(stmt.init) Then
- decl = True
- Emit "{"
- Emit TransDeclStmt(TDeclStmt(stmt.init), True) + ";"
- 'init = TDeclStmt(stmt.init).decl.munged
- vdecl = TValDecl(TDeclStmt(stmt.init).decl)
- Else
- init=stmt.init.Trans()
- End If
- Local expr$=stmt.expr.Trans()
- Local incr$=stmt.incr.Trans()
- Emit "for("+init+";"+expr+";"+incr+"){"
- Local check:TTryBreakCheck = New TTryBreakCheck
- check.stmt = stmt
- PushLoopTryStack(check)
- If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
- PushLoopLocalStack(check)
- End If
- EmitLocalDeclarations(stmt.block, vdecl)
- Local unr:Int=EmitBlock( stmt.block )
- If opt_debug And Not stmt.block.IsNoDebug() And Not stmt.block.generated Then
- PopLoopLocalStack
- End If
- PopLoopTryStack
-
- If check.contId Then
- Emit TransLabelCont(check)
- End If
- If stmt.loopLabel Then
- MungDecl stmt.loopLabel
- Emit TransLoopLabelCont(stmt.loopLabel.realIdent, True)
- End If
-
- Emit "}"
-
- If decl Then
- Emit "}"
- End If
- If check.exitId Then
- Emit TransLabelExit(check)
- End If
- If stmt.loopLabel Then
- Emit TransLoopLabelExit(stmt.loopLabel.realIdent, True)
- End If
-
- If broken=nbroken And TConstExpr( stmt.expr ) And TConstExpr( stmt.expr ).value unreachable=True
- broken=nbroken
- End Method
- Method TransAssertStmt$( stmt:TAssertStmt ) Abstract
- Method TransEndStmt$( stmt:TEndStmt ) Abstract
- Method TransReleaseStmt$( stmt:TReleaseStmt ) Abstract
- Method TransRestoreDataStmt$( stmt:TRestoreDataStmt ) Abstract
- Method TransReadDataStmt$( stmt:TReadDataStmt ) Abstract
-
- Method TransNativeStmt$( stmt:TNativeStmt) Abstract
- 'module
- Method TransApp( app:TAppDecl ) Abstract
- Rem
- Method MungOverrides( cdecl:TClassDecl )
- For Local decl:=Eachin cdecl.Semanted
- Local fdecl:=TFuncDecl( decl )
- If fdecl And fdecl.overrides
- If Not fdecl.overrides.munged InternalErr
- fdecl.munged=fdecl.overrides.munged
- mungScope.Insert fdecl.munged,fdecl
- Endif
- Next
- End
- End Rem
-
- Method PostProcess$( source$ )
- Return source
- End Method
-
- Method SetOutput( file:String )
- Local _lines:TStringList = TStringList(outputFiles.ValueForKey(file))
-
- If Not _lines Then
- _lines = New TStringList
- outputFiles.Insert(file, _lines)
- End If
-
- LINES = _lines
-
- End Method
- Method SetOutputTemp( fin:Int = False )
- Global tmpLevel:Int = 0
-
- If Not fin Then
- tmpLevel :+ 1
- Local _lines:TStringList = New TStringList
- outputFiles.Insert("tmp" + tmpLevel, _lines)
-
- LINES = _lines
- Else
- Local _lines:TStringList = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
-
- tmpLevel :- 1
-
- If Not tmpLevel Then
- SetOutput("source")
- Else
- LINES = TStringList(outputFiles.ValueForKey("tmp" + tmpLevel))
- End If
-
- If _lines Then
- For Local line:String = EachIn _lines
- LINES.AddLast(line)
- Next
- End If
-
- End If
- End Method
- Method DebugPrint(text:String, func:String = Null, trans:Int = False)
- Global count:Int
- Global lastFunc:String
-
- If func Then
- lastFunc = func
- End If
-
- Local s:String = "fprintf(stderr," + "~q" + lastFunc + " : " + count + " :: " + text + "\n~q)" + ";fflush(stderr);"
-
- If trans Then
- debugOut :+ indent + s + "~n"
- Else
- Emit s
- End If
- count :+ 1
- End Method
-
- Method DebugString(s:String, func:String = Null, trans:Int = False)
- ' bbNullObject test
- If trans Then
- debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
- Else
- Emit "if (" + s + "==&bbNullObject) {"
- End If
- DebugPrint("Invalid Null String : " + s, func, trans)
- If trans Then
- debugOut :+ indent + "}~n"
- Else
- Emit "}"
- End If
- End Method
- Method DebugArray(s:String, func:String = Null, trans:Int = False)
- ' bbNullObject test
- If trans Then
- debugOut :+ indent + "if (" + s + "==&bbNullObject) {~n"
- Else
- Emit "if (" + s + "==&bbNullObject) {"
- End If
- DebugPrint("Invalid Null Array : " + s, func, trans)
- If trans Then
- debugOut :+ indent + "}~n"
- Else
- Emit "}"
- End If
- End Method
- Method DebugObject(ty:TType, id:String, func:String = Null, trans:Int = False)
- If TObjectType(ty) Or TStringType(ty) Or TArrayType(ty) Then
- ' null test
- If trans Then
- debugOut :+ indent + "if (" + id + "==NULL) {~n"
- Else
- Emit "if (" + id + "==NULL) {"
- End If
- DebugPrint("Null Pointer : " + id, func, trans)
- If trans Then
- If ABORT_ON_NULL Then
- debugOut :+ indent + "abort();~n"
- End If
- debugOut :+ indent + "}~n"
- Else
- If ABORT_ON_NULL Then
- Emit "abort();~n"
- End If
- Emit "}"
- End If
- End If
-
- If TStringType(ty) Then
- DebugString(id, func, trans)
- Else If TArrayType(ty) Then
- DebugArray(id, func, trans)
- End If
- End Method
-
- Method EmitDebugStmtErrInfo(info:String, count:Int)
- ' extract from info
- info = info[1..info.length-1]
- Local infoArray:String[] = info.Split(";")
- Local dbg:String = "struct BBDebugStm __stmt_" + count + " = {"
- dbg :+ GenHash(infoArray[0]) + ", "
- dbg :+ infoArray[1] + ", "
- dbg :+ infoArray[2] + "};"
- Emit dbg
- Emit "bbOnDebugEnterStm(&__stmt_" + count + ");"
- End Method
-
- Method EmitGDBDebug(obj:Object)
- If opt_gdbdebug Then
- If TStmt(obj) Then
- Local stmt:TStmt = TStmt(obj)
- Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
- If Not stmt.generated Then
- Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
- End If
- Else If TDecl(obj) Then
- Local decl:TDecl = TDecl(obj)
- Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
- Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
- Else If String(obj) Then
- Local errInfo:String = String(obj)
- Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
- Emit "#line " + infoArray[1] + " " + Enquote(infoArray[0])
- End If
- End If
- End Method
- Method EmitCoverage(obj:Object)
- If opt_coverage Then
- If TStmt(obj) Then
- Local stmt:TStmt = TStmt(obj)
- Local infoArray:String[] = stmt.errInfo[1..stmt.errInfo.length-1].Split(";")
- If Not stmt.generated Then
- GenerateCoverageLine(infoArray)
- End If
- Else If TDecl(obj) Then
- Local decl:TDecl = TDecl(obj)
- Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
- GenerateCoverageLine(infoArray)
- Else If String(obj) Then
- Local errInfo:String = String(obj)
- Local infoArray:String[] = errInfo[1..errInfo.length-1].Split(";")
- GenerateCoverageLine(infoArray)
- End If
- End If
- End Method
- Method GenerateCoverageLine(infoArray:String[])
- Emit "bbCoverageUpdateLineInfo(" + Enquote(infoArray[0]) + ", " + infoArray[1] + ");"
- Local filename:String = infoArray[0]
- Local line:Int = Int(infoArray[1])
- Local lineInfo:TCoverageLineInfo = TCoverageLineInfo(coverageFileInfo.ValueForKey(filename))
- If Not lineInfo Then
- lineInfo = New TCoverageLineInfo
- lineInfo.lines = New Int[0]
- coverageFileInfo.Insert(filename, lineInfo)
- End If
- ' Don't add duplicate lines
- If Not lineInfo.lines.Length Or lineInfo.lines[lineInfo.lines.Length-1] <> line Then
- lineInfo.lines :+ [line]
- End If
- End Method
- Method EmitCoverageFunction(decl:TFuncDecl)
- If opt_coverage Then
- Local infoArray:String[] = decl.errInfo[1..decl.errInfo.length-1].Split(";")
- GenerateCoverageFunctionLine(infoArray, decl.ident)
- End If
- End Method
- Method GenerateCoverageFunctionLine(infoArray:String[], name:String)
- Emit "bbCoverageUpdateFunctionLineInfo(" + Enquote(infoArray[0]) + ", " + Enquote(name) + ", " + infoArray[1] + ");"
- Local filename:String = infoArray[0]
- Local line:Int = Int(infoArray[1])
- Local funcInfo:TCoverageFunctionLineInfo = TCoverageFunctionLineInfo(coverageFunctionFileInfo.ValueForKey(filename))
- If Not funcInfo Then
- funcInfo = New TCoverageFunctionLineInfo
- coverageFunctionFileInfo.Insert(filename, funcInfo)
- End If
- Local func:TCoverageFunctionInfo = New TCoverageFunctionInfo
- func.name = name
- func.line = line
- funcInfo.funcs :+ [func]
- End Method
- Method EmitClassDeclDeleteDtor( classDecl:TClassDecl )
- End Method
-
- End Type
- Type TCoverageLineInfo
- Field lines:Int[]
- End Type
- Type TCoverageFunctionLineInfo
- Field funcs:TCoverageFunctionInfo[]
- End Type
- Type TCoverageFunctionInfo
- Field name:String
- Field line:Int
- End Type
- Type TTryBreakCheck
- Field contId:Int
- Field exitId:Int
- Field stmt:TStmt
-
- Method ToString:String()
- Return "TTryBreakCheck"
- End Method
- End Type
|