123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100 |
- ' Copyright (c) 2013-2024 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:TStack=New TStack'< StringMap<TDecl> >
- Field funcMungs:TMap=New TMap'<FuncDeclList>
- Field customVarStack:TStack = New TStack
- Field varStack:TStack = New TStack
- Field tryStack:TStack = New TStack
- Field loopTryStack:TStack = New TStack
- Field mungedScopes:TMap=New TMap'<StringSet>
- 'Field funcMungs:TFuncDeclList=New TFuncDeclList
- 'Field mungedFuncs:TMap=New Map
- Field localScopeStack:TStack = New TStack
- Field localScope:TStack = New TStack
- 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 TStack
- End Method
-
- Method PopVarScope()
- customVarStack=TStack(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()
- Return p + "T" + TObjectType( ty ).classDecl.ident
- 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
- 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:String
- For Local arg:TArgDecl = EachIn fdecl.argDecls
- If Not s Then
- s = "_"
- End If
- s :+ TransMangleType(arg.ty)
- Next
- Return s
- 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" 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,munged$
-
- '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))
- munged=decl.ModuleScope().munged+"_"+id
-
- 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
- munged = decl.scope.munged + "_" + id
-
- If TClassDecl(decl) And TClassDecl(decl).instArgs Then
- For Local ty:TType = EachIn TClassDecl(decl).instArgs
- munged :+ TransMangleType(ty)
- Next
- 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..i+1]
- Case "("
- n:+1
- Case ")"
- 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 TStack
- End If
- End Method
-
- Method EndLocalScope()
- mungScope=TMap(mungStack.Pop())
- ' mungedScopes.Insert "$",Null
- If opt_debug Then
- localScope = TStack(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$="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:+ " 0"
- End If
- If TStringType(stmt.fRetType) Then
- t:+ " &bbEmptyString"
- End If
- If TArrayType(stmt.fRetType) Then
- t:+ " &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 :+ " " + 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:+ " rt_"
- Else
- t:+" " + 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
- 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.stmts.First()
- Emit "{"
- EmitLocalDeclarations(stmt.elseBlock)
- If EmitBlock( stmt.elseBlock ) unreachable=True
- Emit "}"
- EndIf
- Else If 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
|