Ver código fonte

Reworked debug scope depth leaving try block calculations. Fixes #328.

woollybah 7 anos atrás
pai
commit
eec048dc21
3 arquivos alterados com 156 adições e 47 exclusões
  1. 43 4
      decl.bmx
  2. 21 21
      parser.bmx
  3. 92 22
      translator.bmx

+ 43 - 4
decl.bmx

@@ -57,6 +57,18 @@ Const SCOPE_CLASS_HEIRARCHY:Int = 2
 Const SCOPE_MODULE:Int = 3
 Const SCOPE_ALL:Int = 4
 
+Const BLOCK_OTHER:Int =     $000
+Const BLOCK_LOOP:Int =      $001
+Const BLOCK_TRY:Int =       $002
+Const BLOCK_CATCH:Int =     $004
+Const BLOCK_FINALLY:Int =   $008
+Const BLOCK_IF:Int =        $010
+Const BLOCK_ELSE:Int =      $020
+Const BLOCK_FUNCTION:Int =  $040
+
+Const BLOCK_TRY_CATCH:Int = BLOCK_TRY | BLOCK_CATCH
+Const BLOCK_IF_ELSE:Int =   BLOCK_IF | BLOCK_ELSE
+
 'Const CALL_CONV_CDECL:Int = 0
 'Const CALL_CONV_STDCALL:Int = 1
 'Const CALL_CONV_DEFAULT:Int = CALL_CONV_CDECL
@@ -1636,12 +1648,12 @@ End Type
 Type TBlockDecl Extends TScopeDecl
 	Field stmts:TList=New TList
 	Field extra:Object
-	Field isFinallyBlock:Int
+	Field blockType:Int
 	
-	Method Create:TBlockDecl( scope:TScopeDecl, generated:Int = False, isFinallyBlock:Int = False )
+	Method Create:TBlockDecl( scope:TScopeDecl, generated:Int = False, blockType:Int = BLOCK_OTHER )
 		Self.scope = scope
 		Self.generated = generated
-		Self.isFinallyBlock = isFinallyBlock
+		Self.blockType = blockType
 		
 		attrs :| (scope.attrs & DECL_NODEBUG)
 		
@@ -1662,6 +1674,7 @@ Type TBlockDecl Extends TScopeDecl
 		End If
 		t.extra = extra
 		t.generated = generated
+		t.blockType = blockType
 		Return t
 	End Method
 
@@ -1706,7 +1719,7 @@ Type TBlockDecl Extends TScopeDecl
 			Function SurroundingFinallyBlock:TBlockDecl(block:TBlockDecl)
 				' get the innermost Finally block surrounding the current statement
 				While block And Not TFuncDecl(block)
-					If block.isFinallyBlock Then Return block
+					If block.blockType = BLOCK_FINALLY Then Return block
 					block = TBlockDecl(block.scope)
 				Wend
 				Return Null
@@ -1727,6 +1740,26 @@ Type TBlockDecl Extends TScopeDecl
 		Next
 	End Method
 
+	Method ToString:String()
+		Select blockType
+			Case BLOCK_OTHER
+				Return "TBlockDecl:Other"
+			Case BLOCK_LOOP
+				Return "TBlockDecl:Loop"
+			Case BLOCK_TRY
+				Return "TBlockDecl:Try"
+			Case BLOCK_CATCH
+				Return "TBlockDecl:Catch"
+			Case BLOCK_FINALLY
+				Return "TBlockDecl:Finally"
+			Case BLOCK_IF
+				Return "TBlockDecl:If"
+			Case BLOCK_ELSE
+				Return "TBlockDecl:Else"
+			Default
+				Return "TBlockDecl:Unknown"
+		End Select
+	End Method
 End Type
 
 Const FUNC_METHOD:Int=   $0001			'mutually exclusive with ctor
@@ -1772,6 +1805,7 @@ Type TFuncDecl Extends TBlockDecl
 			Self.argDecls = New TArgDecl[0]
 		End If
 		Self.attrs=attrs
+		Self.blockType = BLOCK_FUNCTION
 		Return Self
 	End Method
 	
@@ -1797,6 +1831,7 @@ Type TFuncDecl Extends TBlockDecl
 		t.metadata = metadata
 		t.mangled = mangled
 		t.noMangle = noMangle
+		t.blockType = blockType
 		Return  t
 	End Method
 
@@ -3272,6 +3307,10 @@ End Type
 
 Type TTryStmtDecl Extends TBlockDecl
 	Field tryStmt:TTryStmt
+	
+	Method ToString:String()
+		Return "TTryStmtDecl"
+	End Method
 End Type
 
 Const MODULE_STRICT:Int=1

+ 21 - 21
parser.bmx

@@ -110,8 +110,8 @@ Type TForEachinStmt Extends TLoopStmt
 					expr=New TBinaryCompareExpr.Create( "=",expr, New TNullExpr.Create(TType.nullObjectType))
 
 					' then continue
-					Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope )
-					Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope )
+					Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_IF )
+					Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_ELSE )
 					cont = New TContinueStmt
 					thenBlock.AddStmt cont
 
@@ -144,8 +144,8 @@ Type TForEachinStmt Extends TLoopStmt
 					expr=New TBinaryCompareExpr.Create( "=",varExpr, New TNullExpr.Create(TType.nullObjectType))
 
 					' then continue
-					Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope )
-					Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope )
+					Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_IF )
+					Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, , BLOCK_ELSE )
 					cont = New TContinueStmt
 					thenBlock.AddStmt cont
 
@@ -165,7 +165,7 @@ Type TForEachinStmt Extends TLoopStmt
 
 			Local whileStmt:TWhileStmt=New TWhileStmt.Create( cmpExpr,block,loopLabel, True )
 
-			block=New TBlockDecl.Create( block.scope, True )
+			block=New TBlockDecl.Create( block.scope, True, BLOCK_LOOP )
 			block.AddStmt New TDeclStmt.Create( exprTmp, True )
 			block.AddStmt New TDeclStmt.Create( indexTmp, True )
 			block.AddStmt whileStmt
@@ -233,8 +233,8 @@ Type TForEachinStmt Extends TLoopStmt
 				expr=New TBinaryCompareExpr.Create( "=",expr, New TNullExpr.Create(TType.nullObjectType))
 
 				' then continue
-				Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True )
-				Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True )
+				Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_IF )
+				Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, True, BLOCK_ELSE )
 				cont = New TContinueStmt.Create(Null, True)
 				thenBlock.AddStmt cont
 
@@ -262,8 +262,8 @@ Type TForEachinStmt Extends TLoopStmt
 				Local expr:TExpr=New TBinaryCompareExpr.Create( "=",varExpr, New TNullExpr.Create(TType.nullObjectType))
 
 				' then continue
-				Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope )
-				Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope )
+				Local thenBlock:TBlockDecl=New TBlockDecl.Create( block.scope, ,BLOCK_IF )
+				Local elseBlock:TBlockDecl=New TBlockDecl.Create( block.scope, ,BLOCK_ELSE )
 				cont = New TContinueStmt
 				thenBlock.AddStmt cont
 
@@ -276,7 +276,7 @@ Type TForEachinStmt Extends TLoopStmt
 
 			Local whileStmt:TWhileStmt=New TWhileStmt.Create( hasNextExpr,block, loopLabel, True )
 
-			block=New TBlockDecl.Create( block.scope, True )
+			block=New TBlockDecl.Create( block.scope, True, BLOCK_LOOP )
 			If tmpDecl Then
 				block.AddStmt tmpDecl
 			End If
@@ -1653,8 +1653,8 @@ End Rem
 		CParse "then"
 
 		'create empty blocks for then/else
-		Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block )
-		Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block )
+		Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, ,BLOCK_IF )
+		Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, ,BLOCK_ELSE )
 
 		'define if the current if is a "singleline if"
 		'"singleline ifs" are not allowed to contain "endif" "end if"
@@ -1794,7 +1794,7 @@ End Rem
 		Parse "while"
 
 		Local expr:TExpr=ParseExpr()
-		Local block:TBlockDecl=New TBlockDecl.Create( _block )
+		Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
 
 		PushBlock block
 		While Not CParse( "wend" ) And Not CParse( "endwhile" )
@@ -1826,7 +1826,7 @@ End Rem
 
 		Parse "repeat"
 
-		Local block:TBlockDecl=New TBlockDecl.Create( _block )
+		Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
 
 		PushBlock block
 		While _toke<>"until" And _toke<>"forever"
@@ -1881,7 +1881,7 @@ End Rem
 
 		If CParse( "eachin" )
 			Local expr:TExpr=ParseExpr()
-			Local block:TBlockDecl=New TBlockDecl.Create( _block )
+			Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
 
 			PushBlock block
 			While Not CParse( "next" )
@@ -1936,7 +1936,7 @@ End Rem
 			incr=New TAssignStmt.Create( "=",varExpr,New TBinaryMathExpr.Create( "+",varExpr,New TCastExpr.Create( varty,stp,1 ) ) )
 		EndIf
 
-		Local block:TBlockDecl=New TBlockDecl.Create( _block )
+		Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_LOOP )
 
 		PushBlock block
 		While Not CParse( "next" )
@@ -2037,7 +2037,7 @@ End Rem
 		
 		PushBlock tryStmtDecl
 
-		Local block:TBlockDecl=New TBlockDecl.Create( tryStmtDecl )
+		Local block:TBlockDecl=New TBlockDecl.Create( tryStmtDecl, , BLOCK_TRY )
 		Local catches:TList=New TList
 		Local finallyStmt:TFinallyStmt = Null
 
@@ -2057,13 +2057,13 @@ End Rem
 					Wend
 				End If
 				Local init:TLocalDecl=New TLocalDecl.Create( id,ty,Null,0 )
-				Local block:TBlockDecl=New TBlockDecl.Create( _block )
+				Local block:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_CATCH )
 				catches.AddLast(New TCatchStmt.Create( init,block ))
 				PopBlock
 				PushBlock block
 			Else If CParse("finally") Then
 				If finallyStmt Then Err "Try statement cannot have more than one Finally block."
-				Local block:TBlockDecl = New TBlockDecl.Create(_block, , True)
+				Local block:TBlockDecl = New TBlockDecl.Create(_block, , BLOCK_FINALLY)
 				finallyStmt = New TFinallyStmt.Create(block)
 				PopBlock
 				PushBlock block
@@ -2162,8 +2162,8 @@ End Rem
 					EndIf
 				Until Not CParse(",")
 
-				Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block )
-				Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block )
+				Local thenBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_IF )
+				Local elseBlock:TBlockDecl=New TBlockDecl.Create( _block, , BLOCK_ELSE )
 
 				Local ifstmt:TIfStmt=New TIfStmt.Create( comp,thenBlock,elseBlock )
 				block.AddStmt ifstmt

+ 92 - 22
translator.bmx

@@ -1,4 +1,4 @@
-' Copyright (c) 2013-2018 Bruce A Henderson
+' Copyright (c) 2013-2018 Bruce A Henderson
 '
 ' Based on the public domain Monkey "trans" by Mark Sibly
 '
@@ -103,6 +103,13 @@ Type TTranslator
 		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
@@ -122,6 +129,30 @@ Type TTranslator
 			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
@@ -380,8 +411,8 @@ Type TTranslator
 				Return "_or"
 			Case "~~"
 				Return "_xor"
-			Case "^"
-				Return "_pow"
+			Case "^"
+				Return "_pow"
 			Case ":*"
 				Return "_muleq"
 			Case ":/"
@@ -396,8 +427,8 @@ Type TTranslator
 				Return "_oreq"
 			Case ":~~"
 				Return "_xoreq"
-			Case ":^"
-				Return "_poweq"
+			Case ":^"
+				Return "_poweq"
 			Case "<"
 				Return "_lt"
 			Case "<="
@@ -1114,6 +1145,17 @@ End Rem
 				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
@@ -1184,6 +1226,17 @@ End Rem
 				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
@@ -1409,25 +1462,39 @@ End Rem
 			
 			processingReturnStatement = 0
 			
-			If opt_debug And Not block.IsNoDebug() Then
-				If TReturnStmt(stmt) Then
-					For Local b:TBlockDecl = EachIn localScope
-						Emit "bbOnDebugLeaveScope();"
-					Next
-				End If
-			End If
-			
 			If TReturnStmt(stmt) Then
-				For Local tryStmt:TTryStmt = EachIn tryStack
-					Emit "bbExLeave();"
-					If opt_debug Then Emit "bbOnDebugPopExState();"
-					If tryStmt.finallyStmt Then
-						Local returnLabelDecl:TLoopLabelDecl = New TLoopLabelDecl.Create("return")
-						MungDecl returnLabelDecl
-						EmitFinallyJmp tryStmt.finallyStmt, returnLabelDecl
-						Emit TransLabel(returnLabelDecl)
+				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
-				Next
+				End If
 			End If
 			
 			If t Emit t+";"
@@ -1910,4 +1977,7 @@ Type TTryBreakCheck
 
 	Field stmt:TStmt
 	
+	Method ToString:String()
+		Return "TTryBreakCheck"
+	End Method
 End Type