From 6b4de4bcb32c1f67a65ec0d7e06daaf9918eac0a Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 18 Aug 2022 16:17:30 +0200 Subject: [PATCH 01/43] updating ASTInterpreter and visitors according to nez API for TemporaryVariable and ArgumentVariable --- DebuggableASTInterpreter/DASTInterpreter.class.st | 5 +++++ .../DASTPostOrderTreeVisitor.class.st | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/DebuggableASTInterpreter/DASTInterpreter.class.st b/DebuggableASTInterpreter/DASTInterpreter.class.st index d0970dd..bff841c 100644 --- a/DebuggableASTInterpreter/DASTInterpreter.class.st +++ b/DebuggableASTInterpreter/DASTInterpreter.class.st @@ -310,6 +310,11 @@ DASTInterpreter >> visitArgumentNode: aRBArgumentNode [ self stackPush: (currentContext findVariable: aRBArgumentNode name) ] +{ #category : #visiting } +DASTInterpreter >> visitArgumentVariableNode: aRBVariableNode [ + self visitVariableNode: aRBVariableNode . +] + { #category : #visiting } DASTInterpreter >> visitArrayNode: aRBArrayNode [ | literals size arrayMirror | diff --git a/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st b/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st index 75436db..1716250 100644 --- a/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st +++ b/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st @@ -37,6 +37,12 @@ DASTPostOrderTreeVisitor >> visitArgumentNode: aRBArgumentNode [ ^ stack push: aRBArgumentNode ] +{ #category : #visiting } +DASTPostOrderTreeVisitor >> visitArgumentVariableNode: aRBVariableNode [ + + stack push: aRBVariableNode +] + { #category : #visiting } DASTPostOrderTreeVisitor >> visitArrayNode: aRBArrayNode [ stack push: aRBArrayNode. @@ -138,6 +144,12 @@ DASTPostOrderTreeVisitor >> visitTemporaryNode: aRBTemporaryNode [ stack push: aRBTemporaryNode ] +{ #category : #visiting } +DASTPostOrderTreeVisitor >> visitTemporaryVariableNode: aRBVariableNode [ + + stack push: aRBVariableNode +] + { #category : #visiting } DASTPostOrderTreeVisitor >> visitThisContextNode: aRBThisContextNode [ stack push: aRBThisContextNode From 474dbd3c6efa8a550d614b3e05cbdc87de81f56e Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 30 Aug 2022 12:08:04 +0200 Subject: [PATCH 02/43] updating ASTInterpreter and ASTPostOrderTreeVisitor according to new AST Visitor API --- .../DASTInterpreter.class.st | 27 +++++++++++++++++ .../DASTPostOrderTreeVisitor.class.st | 29 ++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/DebuggableASTInterpreter/DASTInterpreter.class.st b/DebuggableASTInterpreter/DASTInterpreter.class.st index bff841c..2efd49c 100644 --- a/DebuggableASTInterpreter/DASTInterpreter.class.st +++ b/DebuggableASTInterpreter/DASTInterpreter.class.st @@ -347,6 +347,12 @@ DASTInterpreter >> visitCascadeNode: aRBCascadeNode [ self flag: 'I do nothing'. ] +{ #category : #visiting } +DASTInterpreter >> visitClassVariableNode: aNode [ + + ^ self visitLiteralVariableNode: aNode +] + { #category : #visiting } DASTInterpreter >> visitGlobalNode: aRBGlobalNode [ @@ -354,6 +360,12 @@ DASTInterpreter >> visitGlobalNode: aRBGlobalNode [ ] +{ #category : #visiting } +DASTInterpreter >> visitGlobalVariableNode: aNode [ + + ^ self visitLiteralVariableNode: aNode +] + { #category : #visiting } DASTInterpreter >> visitInstanceVariableNode: aRBInstanceVariableNode [ self stackPush: (self readInstanceVariableNamed: aRBInstanceVariableNode name) @@ -379,6 +391,21 @@ DASTInterpreter >> visitLiteralValueNode: aRBLiteralValueNode [ self visitLiteralNode: aRBLiteralValueNode ] +{ #category : #visiting } +DASTInterpreter >> visitLiteralVariableNode: aNode [ + "to be backward compatible, we visit for Gloabls here (there used to be no difference)" + + ^ self visitGlobalNode: aNode +] + +{ #category : #visiting } +DASTInterpreter >> visitLocalVariableNode: aNode [ + + "call visitTemporaryNode: for backward compatibility" + + ^ self visitTemporaryNode: aNode +] + { #category : #visiting } DASTInterpreter >> visitMessageNode: aRBMessageNode [ | arguments receiver method newContext | diff --git a/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st b/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st index 1716250..4e8af2e 100644 --- a/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st +++ b/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st @@ -67,11 +67,23 @@ DASTPostOrderTreeVisitor >> visitCascadeNode: aRBCascadeNode [ aRBCascadeNode children reverse do: [ :e | e acceptVisitor: self ] ] +{ #category : #visiting } +DASTPostOrderTreeVisitor >> visitClassVariableNode: aNode [ + + ^ self visitLiteralVariableNode: aNode +] + { #category : #visiting } DASTPostOrderTreeVisitor >> visitGlobalNode: aRBGlobalNode [ stack push: aRBGlobalNode ] +{ #category : #visiting } +DASTPostOrderTreeVisitor >> visitGlobalVariableNode: aNode [ + + ^ self visitLiteralVariableNode: aNode +] + { #category : #visiting } DASTPostOrderTreeVisitor >> visitInstanceVariableNode: aRBInstanceVariableNode [ stack push: aRBInstanceVariableNode @@ -95,6 +107,21 @@ DASTPostOrderTreeVisitor >> visitLiteralValueNode: aRBLiteralValueNode [ ^ self visitLiteralNode: aRBLiteralValueNode ] +{ #category : #visiting } +DASTPostOrderTreeVisitor >> visitLiteralVariableNode: aNode [ + "to be backward compatible, we visit for Gloabls here (there used to be no difference)" + + ^ self visitGlobalNode: aNode +] + +{ #category : #visiting } +DASTPostOrderTreeVisitor >> visitLocalVariableNode: aNode [ + + "call visitTemporaryNode: for backward compatibility" + + ^ self visitTemporaryNode: aNode +] + { #category : #visiting } DASTPostOrderTreeVisitor >> visitMessageNode: aRBMessageNode [ @@ -139,7 +166,7 @@ DASTPostOrderTreeVisitor >> visitSuperNode: aRBSuperNode [ ^ stack push: aRBSuperNode ] -{ #category : #'as yet unclassified' } +{ #category : #visiting } DASTPostOrderTreeVisitor >> visitTemporaryNode: aRBTemporaryNode [ stack push: aRBTemporaryNode ] From 91d5689100516379577dcfb0bfb45da09d3e488e Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 6 Sep 2022 16:45:29 +0200 Subject: [PATCH 03/43] removing deprecated spec-debugger dependency + adding espell dependency to the baseline --- ...aselineOfDebuggableASTInterpreter.class.st | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st b/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st index 442f871..803bc35 100644 --- a/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st +++ b/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st @@ -8,27 +8,28 @@ Class { BaselineOfDebuggableASTInterpreter >> baseline: spec [ - spec - for: #common - do: [ - "Dependencies" - spec - baseline: 'SpecDebugger' - with: [ spec repository: 'github://dupriezt/Spec-Debugger' ]. - spec - baseline: 'Ghost' - with: [ spec repository: 'gitlab://gitlab.inria.fr:RMOD/Ghost' ]. - - "Packages" - spec - package: 'DebuggableASTInterpreter'; - package: 'DebuggableASTDebugger' with: [ spec requires: #('DebuggableASTInterpreter' 'SpecDebugger') ]; - package: 'DebuggableASTInterpreterOverlays' with: [ spec requires: #('DebuggableASTDebugger' 'Ghost') ]]. + spec for: #common do: [ "Dependencies" + spec + baseline: 'Espell' + with: [ spec repository: 'github://guillep/espell' ]. + spec + baseline: 'Ghost' + with: [ spec repository: 'gitlab://gitlab.inria.fr:RMOD/Ghost' ]. + + "Packages" + spec + package: 'DebuggableASTInterpreter' + with: [ spec requires: #( 'Espell' ) ]; + package: 'DebuggableASTDebugger' + with: [ spec requires: #( 'DebuggableASTInterpreter' ) ]; + package: 'DebuggableASTInterpreterOverlays' + with: [ spec requires: #( 'DebuggableASTDebugger' + 'Ghost' ) ] ]. - "Groups" - spec - group: 'default' with: #('Model'); - group: 'Model' with: #('DebuggableASTInterpreter'); - group: 'Debugger' with: #('DebuggableASTDebugger'); - group: 'Overlay' with: #('DebuggableASTInterpreterOverlays') + "Groups" + spec + group: 'default' with: #( 'Model' ); + group: 'Model' with: #( 'DebuggableASTInterpreter' ); + group: 'Debugger' with: #( 'DebuggableASTDebugger' ); + group: 'Overlay' with: #( 'DebuggableASTInterpreterOverlays' ) ] From 21444f567e2f7ef93876ec40cb87243c15f00149 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 23 Sep 2022 11:05:23 +0200 Subject: [PATCH 04/43] synch with RMODINRIA/DebuggableASTInterpreter --- ...aselineOfDebuggableASTInterpreter.class.st | 21 +++++-------------- .../DASTInterpreter.class.st | 13 ++++++------ .../DASTPostOrderTreeVisitor.class.st | 14 ++++++------- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st b/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st index 803bc35..deeab82 100644 --- a/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st +++ b/BaselineOfDebuggableASTInterpreter/BaselineOfDebuggableASTInterpreter.class.st @@ -8,28 +8,17 @@ Class { BaselineOfDebuggableASTInterpreter >> baseline: spec [ - spec for: #common do: [ "Dependencies" - spec - baseline: 'Espell' - with: [ spec repository: 'github://guillep/espell' ]. - spec - baseline: 'Ghost' - with: [ spec repository: 'gitlab://gitlab.inria.fr:RMOD/Ghost' ]. + spec for: #common do: [ "Packages" spec - package: 'DebuggableASTInterpreter' - with: [ spec requires: #( 'Espell' ) ]; - package: 'DebuggableASTDebugger' - with: [ spec requires: #( 'DebuggableASTInterpreter' ) ]; - package: 'DebuggableASTInterpreterOverlays' - with: [ spec requires: #( 'DebuggableASTDebugger' - 'Ghost' ) ] ]. + package: 'DebuggableASTInterpreter'; + package: 'DebuggableASTDebugger' with: [ + spec requires: #( 'DebuggableASTInterpreter' ) ] ]. "Groups" spec group: 'default' with: #( 'Model' ); group: 'Model' with: #( 'DebuggableASTInterpreter' ); - group: 'Debugger' with: #( 'DebuggableASTDebugger' ); - group: 'Overlay' with: #( 'DebuggableASTInterpreterOverlays' ) + group: 'Debugger' with: #( 'DebuggableASTDebugger' ) ] diff --git a/DebuggableASTInterpreter/DASTInterpreter.class.st b/DebuggableASTInterpreter/DASTInterpreter.class.st index 2abbed5..8d9365d 100644 --- a/DebuggableASTInterpreter/DASTInterpreter.class.st +++ b/DebuggableASTInterpreter/DASTInterpreter.class.st @@ -311,8 +311,9 @@ DASTInterpreter >> visitArgumentNode: aRBArgumentNode [ ] { #category : #visiting } -DASTInterpreter >> visitArgumentVariableNode: aRBVariableNode [ - self visitVariableNode: aRBVariableNode . +DASTInterpreter >> visitArgumentVariableNode: aRBVariableNode [ + + ^ self visitTemporaryNode: aRBVariableNode ] { #category : #visiting } @@ -348,9 +349,9 @@ DASTInterpreter >> visitCascadeNode: aRBCascadeNode [ ] { #category : #visiting } -DASTInterpreter >> visitClassVariableNode: aNode [ +DASTInterpreter >> visitClassVariableNode: aRBVariableNode [ - ^ self visitLiteralVariableNode: aNode + ^ self visitGlobalNode: aRBVariableNode ] { #category : #visiting } @@ -361,9 +362,9 @@ DASTInterpreter >> visitGlobalNode: aRBGlobalNode [ ] { #category : #visiting } -DASTInterpreter >> visitGlobalVariableNode: aNode [ +DASTInterpreter >> visitGlobalVariableNode: aRBVariableNode [ - ^ self visitLiteralVariableNode: aNode + ^ self visitGlobalNode: aRBVariableNode ] { #category : #visiting } diff --git a/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st b/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st index 4e8af2e..acc1791 100644 --- a/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st +++ b/DebuggableASTInterpreter/DASTPostOrderTreeVisitor.class.st @@ -40,7 +40,7 @@ DASTPostOrderTreeVisitor >> visitArgumentNode: aRBArgumentNode [ { #category : #visiting } DASTPostOrderTreeVisitor >> visitArgumentVariableNode: aRBVariableNode [ - stack push: aRBVariableNode + ^ self visitTemporaryNode: aRBVariableNode ] { #category : #visiting } @@ -68,9 +68,9 @@ DASTPostOrderTreeVisitor >> visitCascadeNode: aRBCascadeNode [ ] { #category : #visiting } -DASTPostOrderTreeVisitor >> visitClassVariableNode: aNode [ +DASTPostOrderTreeVisitor >> visitClassVariableNode: aRBVariableNode [ - ^ self visitLiteralVariableNode: aNode + ^ self visitGlobalNode: aRBVariableNode ] { #category : #visiting } @@ -79,9 +79,9 @@ DASTPostOrderTreeVisitor >> visitGlobalNode: aRBGlobalNode [ ] { #category : #visiting } -DASTPostOrderTreeVisitor >> visitGlobalVariableNode: aNode [ +DASTPostOrderTreeVisitor >> visitGlobalVariableNode: aRBVariableNode [ - ^ self visitLiteralVariableNode: aNode + ^ self visitGlobalNode: aRBVariableNode ] { #category : #visiting } @@ -172,9 +172,9 @@ DASTPostOrderTreeVisitor >> visitTemporaryNode: aRBTemporaryNode [ ] { #category : #visiting } -DASTPostOrderTreeVisitor >> visitTemporaryVariableNode: aRBVariableNode [ +DASTPostOrderTreeVisitor >> visitTemporaryVariableNode: aRBVariableNode [ - stack push: aRBVariableNode + ^ self visitTemporaryNode: aRBVariableNode ] { #category : #visiting } From d2987ba38bb6e4d3b3013e3648f6a7d74c6821ad Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 4 Nov 2022 15:06:17 +0100 Subject: [PATCH 05/43] implementing asContext for rootContext --- DebuggableASTInterpreter/DASTContext.class.st | 6 ++ .../DASTContextRootSmalltalk.class.st | 6 ++ .../DASTContextTests.class.st | 57 ++++++++++++++++++- 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index fda8aa6..7c2c2d3 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -95,6 +95,12 @@ DASTContext >> allTemps [ self subclassResponsibility ] +{ #category : #converting } +DASTContext >> asContext [ + + self subclassResponsibility +] + { #category : #'API-lookup' } DASTContext >> assignVariable: name value: value [ "Temporary variables assignment" diff --git a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st index 8112060..f2cd80f 100644 --- a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st +++ b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st @@ -18,6 +18,12 @@ DASTContextRootSmalltalk >> allTemps [ ^ #() ] +{ #category : #converting } +DASTContextRootSmalltalk >> asContext [ + + ^ nil +] + { #category : #accessing } DASTContextRootSmalltalk >> assignVariable: name value: value [ (self findVariable: name) diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index b658604..f48615a 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -2,17 +2,72 @@ Class { #name : #DASTContextTests, #superclass : #TestCase, #instVars : [ - 'context' + 'context', + 'aCompiledMethod', + 'aReceiver', + 'aSender', + 'anArgument', + 'aMethodContext', + 'pharoContext', + 'interpreterRoot', + 'rootContext', + 'interpreterMethod', + 'methodContext', + 'interpreterBlock', + 'blockContext' ], #category : #'DebuggableASTInterpreter-Tests' } +{ #category : #helpers } +DASTContextTests >> helperAddingPoints [ + + ^ (2@2) + (3 @ 3) +] + +{ #category : #helpers } +DASTContextTests >> helperCallingHelperAddingPoints [ + + ^ self helperAddingPoints +] + +{ #category : #running } +DASTContextTests >> setUp [ + + super setUp. + + "Put here a common initialization logic for tests" + interpreterRoot := DASTInterpreter new. + interpreterRoot initializeWithProgram: (RBParser parseExpression: '1'). + rootContext := interpreterRoot currentContext rootContext. + + interpreterMethod := DASTInterpreter new. + interpreterMethod initializeWithProgram: + (RBParser parseExpression: '1'). + methodContext := interpreterMethod currentContext. + + interpreterBlock := DASTInterpreter new. + interpreterBlock initializeWithProgram: (RBParser parseExpression: '1'). + blockContext := interpreterBlock currentContext +] + { #category : #tests } DASTContextTests >> testContextInitialization [ context := DASTContext new. self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTRootContextAsContext [ + + | bcContext | + self assert: rootContext sender isNil. + + bcContext := rootContext asContext. + + self assert: bcContext isNil +] + { #category : #stack } DASTContextTests >> testStackPopEmpty [ | stack | From 1f84fee85507740d64e8afd9082cfc8054b6891f Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 7 Nov 2022 09:59:03 +0100 Subject: [PATCH 06/43] adding test so that asContext and its senders keep same receiver, arguments for senders --- DebuggableASTInterpreter/DASTContext.class.st | 17 ++++- .../DASTContextTests.class.st | 75 +++++++++++++++---- .../DASTInterpreterClassForTests.class.st | 12 +++ .../DASTMethodContext.class.st | 6 ++ 4 files changed, 93 insertions(+), 17 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 7c2c2d3..9239061 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -95,10 +95,25 @@ DASTContext >> allTemps [ self subclassResponsibility ] +{ #category : #accessing } +DASTContext >> arguments [ + + ^ { } asOrderedCollection +] + { #category : #converting } DASTContext >> asContext [ - self subclassResponsibility + | newContext | + newContext := Context + sender: self sender asContext + receiver: self receiver + method: self method + arguments: self arguments. + + "We need to change pc and to think about that later ..." + "self pc: ." + ^ newContext ] { #category : #'API-lookup' } diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index f48615a..865be06 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -19,18 +19,6 @@ Class { #category : #'DebuggableASTInterpreter-Tests' } -{ #category : #helpers } -DASTContextTests >> helperAddingPoints [ - - ^ (2@2) + (3 @ 3) -] - -{ #category : #helpers } -DASTContextTests >> helperCallingHelperAddingPoints [ - - ^ self helperAddingPoints -] - { #category : #running } DASTContextTests >> setUp [ @@ -38,16 +26,29 @@ DASTContextTests >> setUp [ "Put here a common initialization logic for tests" interpreterRoot := DASTInterpreter new. - interpreterRoot initializeWithProgram: (RBParser parseExpression: '1'). + interpreterRoot initializeWithProgram: + (RBParser parseExpression: '1'). rootContext := interpreterRoot currentContext rootContext. interpreterMethod := DASTInterpreter new. - interpreterMethod initializeWithProgram: - (RBParser parseExpression: '1'). + interpreterMethod initializeWithProgram: (RBParser parseExpression: + 'DASTInterpreterClassForTests new helperCallingHelperAddingPoints: 2@2 with: 3@3 '). + interpreterMethod + stepOver; + stepOver; + stepOver; + stepOver; + stepInto; + stepOver; + stepOver; + stepOver; + stepInto. + "stop at the beginning of helperMethodAddingPoints context" methodContext := interpreterMethod currentContext. interpreterBlock := DASTInterpreter new. - interpreterBlock initializeWithProgram: (RBParser parseExpression: '1'). + interpreterBlock initializeWithProgram: + (RBParser parseExpression: '1'). blockContext := interpreterBlock currentContext ] @@ -57,6 +58,48 @@ DASTContextTests >> testContextInitialization [ self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTMethodContextAsContextKeepsSameReceiverSenderAndArguments [ + + | arguments receiver bcContext | + bcContext := methodContext asContext. + + "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" + [ bcContext ] whileNotNil: [ + receiver := methodContext receiver. + arguments := methodContext arguments. + + self + assert: bcContext receiver identicalTo: receiver; + assertCollection: bcContext arguments hasSameElements: arguments. + + bcContext := bcContext sender. + methodContext := methodContext sender ] +] + +{ #category : #tests } +DASTContextTests >> testDASTMethodContextAsContextKeepsSameStack [ + + | bcContext stack | + interpreterMethod + stepOver; + stepOver. + bcContext := methodContext asContext. + + "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" + [ bcContext ] whileNotNil: [ + stack := methodContext stack. + + self + assert: bcContext stackPtr + equals: stack size + methodContext allTemps size. + 1 to: stack size do: [ :each | + self assert: stack pop identicalTo: bcContext pop ]. + + bcContext := bcContext sender. + methodContext := methodContext sender ] +] + { #category : #tests } DASTContextTests >> testDASTRootContextAsContext [ diff --git a/DebuggableASTInterpreter/DASTInterpreterClassForTests.class.st b/DebuggableASTInterpreter/DASTInterpreterClassForTests.class.st index 84c2816..63ab57d 100644 --- a/DebuggableASTInterpreter/DASTInterpreterClassForTests.class.st +++ b/DebuggableASTInterpreter/DASTInterpreterClassForTests.class.st @@ -81,6 +81,18 @@ DASTInterpreterClassForTests >> getVariableDeclaredInMethod [ ^ a ] +{ #category : #helpers } +DASTInterpreterClassForTests >> helperAddingPoints: point1 with: point2 [ + + ^ point1 + point2 +] + +{ #category : #helpers } +DASTInterpreterClassForTests >> helperCallingHelperAddingPoints: point1 with: point2 [ + + ^ self helperAddingPoints: point1 with: point2 +] + { #category : #tests } DASTInterpreterClassForTests >> initialize [ |x| diff --git a/DebuggableASTInterpreter/DASTMethodContext.class.st b/DebuggableASTInterpreter/DASTMethodContext.class.st index 08c4e64..5dfec68 100644 --- a/DebuggableASTInterpreter/DASTMethodContext.class.st +++ b/DebuggableASTInterpreter/DASTMethodContext.class.st @@ -19,6 +19,12 @@ DASTMethodContext >> allTemps [ ^ self variablesDict associations ] +{ #category : #accessing } +DASTMethodContext >> arguments [ + + ^ (self method ast arguments collect: [ :each | each name ]) collect: [ :each | (self findLocalVariable: each) value ] +] + { #category : #'API-lookup' } DASTMethodContext >> findLocalVariable: aName [ ^ variablesDict From 9f415b3c6b4cf1a073d48969eb1405b1384f1e2d Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 7 Nov 2022 10:42:02 +0100 Subject: [PATCH 07/43] applying node -> pc equivalence in asContext --- DebuggableASTInterpreter/DASTContext.class.st | 8 +++-- .../DASTContextTests.class.st | 29 ++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 9239061..4e26c5f 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -104,15 +104,19 @@ DASTContext >> arguments [ { #category : #converting } DASTContext >> asContext [ - | newContext | + | newContext nextNode nextPC nextNodes | newContext := Context sender: self sender asContext receiver: self receiver method: self method arguments: self arguments. + nextNodes := self nodes copy. "We need to change pc and to think about that later ..." - "self pc: ." + [ nextPC ] whileNil: [ + nextNode := nextNodes pop. + nextPC := self methodOrBlock nodeAST firstPcForNode: nextNode ]. + newContext pc: nextPC. ^ newContext ] diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index 865be06..a9d8d81 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -58,6 +58,31 @@ DASTContextTests >> testContextInitialization [ self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTMethodContextAsContextKeepsSameEquivalentPc [ + + | bcContext nextNode nodes | + interpreterMethod + stepOver; + stepOver. + bcContext := methodContext asContext. + + "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" + [ bcContext ] whileNotNil: [ + nodes := methodContext nodes copy. + nextNode := nodes pop. + [ methodContext methodOrBlock nodeAST firstPcForNode: nextNode ] + whileNil: [ nextNode := nodes pop ]. + + self + assert: bcContext pc + equals: + (methodContext methodOrBlock nodeAST firstPcForNode: nextNode). + + bcContext := bcContext sender. + methodContext := methodContext sender ] +] + { #category : #tests } DASTContextTests >> testDASTMethodContextAsContextKeepsSameReceiverSenderAndArguments [ @@ -74,7 +99,9 @@ DASTContextTests >> testDASTMethodContextAsContextKeepsSameReceiverSenderAndArgu assertCollection: bcContext arguments hasSameElements: arguments. bcContext := bcContext sender. - methodContext := methodContext sender ] + methodContext := methodContext sender ]. + + self assert: methodContext isRoot ] { #category : #tests } From 058026fffcc3ef2225692da9e114e202a3e905e1 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 7 Nov 2022 13:13:12 +0100 Subject: [PATCH 08/43] adding test to check that asContext creates a context that gives the same result when resumed. It works but raises an exception "CannotReturn" afterwards and I don't know why --- DebuggableASTInterpreter/DASTContext.class.st | 7 +++++- .../DASTContextTests.class.st | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 4e26c5f..7a1551b 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -112,11 +112,16 @@ DASTContext >> asContext [ arguments: self arguments. nextNodes := self nodes copy. - "We need to change pc and to think about that later ..." + "We need to change pc" [ nextPC ] whileNil: [ nextNode := nextNodes pop. nextPC := self methodOrBlock nodeAST firstPcForNode: nextNode ]. newContext pc: nextPC. + + "We need to rebuild the stack" + newContext stackp: 0. + (self allTemps collect: [ :each | each value ]) , self stack do: [ + :each | newContext push: each ]. ^ newContext ] diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index a9d8d81..d2e11ef 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -42,6 +42,10 @@ DASTContextTests >> setUp [ stepOver; stepOver; stepOver; + stepInto; + stepOver; + stepOver; + stepOver; stepInto. "stop at the beginning of helperMethodAddingPoints context" methodContext := interpreterMethod currentContext. @@ -58,6 +62,26 @@ DASTContextTests >> testContextInitialization [ self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTMethodContextAsContextHasSameResult [ + + | bcContext process result | + interpreterMethod + stepOver; + stepOver. + bcContext := methodContext asContext. + process := Process + forContext: bcContext + priority: Processor userInterruptPriority. + + result := interpreterMethod evaluate. + + process completeTo: bcContext sender. + self assert: process suspendedContext top equals: result. + + self shouldnt: [ process resume ] raise: [ Exception ] +] + { #category : #tests } DASTContextTests >> testDASTMethodContextAsContextKeepsSameEquivalentPc [ From aa8d199360d9017d2d577f734476e91f49314ce6 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:00:15 +0100 Subject: [PATCH 09/43] making sure that DASTBlockContext asContext keeps same receiver; senders, arguments and closure --- DebuggableASTInterpreter/DASTBlock.class.st | 12 ++++++ DebuggableASTInterpreter/DASTClosure.class.st | 12 ++++++ DebuggableASTInterpreter/DASTContext.class.st | 12 +++--- .../DASTContextRootSmalltalk.class.st | 6 +++ .../DASTContextTests.class.st | 42 +++++++++++++++++-- DebuggableASTInterpreter/DASTMethod.class.st | 6 +++ 6 files changed, 82 insertions(+), 8 deletions(-) diff --git a/DebuggableASTInterpreter/DASTBlock.class.st b/DebuggableASTInterpreter/DASTBlock.class.st index 358c19a..bbebccc 100644 --- a/DebuggableASTInterpreter/DASTBlock.class.st +++ b/DebuggableASTInterpreter/DASTBlock.class.st @@ -29,6 +29,18 @@ DASTBlock >> bodyOffset [ ^ self outerContext methodOrBlock bodyOffset ] +{ #category : #accessing } +DASTBlock >> closure [ + + ^ self nodeAST evaluate +] + +{ #category : #accessing } +DASTBlock >> compiledCode [ + + ^ self closure compiledBlock +] + { #category : #accessing } DASTBlock >> ensure: aBlock [ "Evaluate a termination block after evaluating the receiver, regardless of diff --git a/DebuggableASTInterpreter/DASTClosure.class.st b/DebuggableASTInterpreter/DASTClosure.class.st index bd9e263..a4d8e4e 100644 --- a/DebuggableASTInterpreter/DASTClosure.class.st +++ b/DebuggableASTInterpreter/DASTClosure.class.st @@ -34,6 +34,18 @@ DASTClosure >> body [ ^ nodeAST body ] +{ #category : #accessing } +DASTClosure >> closure [ + + ^ nil +] + +{ #category : #accessing } +DASTClosure >> compiledCode [ + + self subclassResponsibility +] + { #category : #initialization } DASTClosure >> initializeWith: aRBNode [ diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 7a1551b..f84af4f 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -98,18 +98,20 @@ DASTContext >> allTemps [ { #category : #accessing } DASTContext >> arguments [ - ^ { } asOrderedCollection + ^ (self methodOrBlock nodeAST arguments collect: [ :each | each name ]) + collect: [ :each | (self findLocalVariable: each) value ] ] { #category : #converting } DASTContext >> asContext [ | newContext nextNode nextPC nextNodes | - newContext := Context - sender: self sender asContext + newContext := (Context newForMethod: self method) + setSender: self sender asContext receiver: self receiver - method: self method - arguments: self arguments. + method: self methodOrBlock compiledCode + closure: self methodOrBlock closure + startpc: self methodOrBlock compiledCode initialPC. nextNodes := self nodes copy. "We need to change pc" diff --git a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st index f2cd80f..7e980de 100644 --- a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st +++ b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st @@ -18,6 +18,12 @@ DASTContextRootSmalltalk >> allTemps [ ^ #() ] +{ #category : #accessing } +DASTContextRootSmalltalk >> arguments [ + + ^ { } asOrderedCollection +] + { #category : #converting } DASTContextRootSmalltalk >> asContext [ diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index d2e11ef..2545c48 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -51,8 +51,18 @@ DASTContextTests >> setUp [ methodContext := interpreterMethod currentContext. interpreterBlock := DASTInterpreter new. - interpreterBlock initializeWithProgram: - (RBParser parseExpression: '1'). + interpreterBlock initializeWithProgram: (RBParser parseExpression: + '[ :each | [:point | point + (5 @ 8) ] value: each @ each ] value: 4'). + "stop at the beginning of the embedded block context" + interpreterBlock + stepOver; + stepOver; + stepInto; + stepOver; + stepOver; + stepOver; + stepOver; + stepInto. blockContext := interpreterBlock currentContext ] @@ -62,6 +72,30 @@ DASTContextTests >> testContextInitialization [ self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTBlockContextAsContextKeepsSameReceiverSenderAndArguments [ + + | arguments receiver bcContext bcMethod dastMethod | + bcContext := blockContext asContext. + + "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" + [ bcContext ] whileNotNil: [ + receiver := blockContext receiver. + arguments := blockContext arguments. + bcMethod := bcContext method. + dastMethod := blockContext methodOrBlock compiledCode. + self + assert: bcContext receiver identicalTo: receiver; + assertCollection: bcContext arguments hasSameElements: arguments; + assert: bcContext method sourceCode + equals: blockContext methodOrBlock compiledCode sourceCode. + + bcContext := bcContext sender. + blockContext := blockContext sender ]. + + self assert: blockContext isRoot +] + { #category : #tests } DASTContextTests >> testDASTMethodContextAsContextHasSameResult [ @@ -120,7 +154,9 @@ DASTContextTests >> testDASTMethodContextAsContextKeepsSameReceiverSenderAndArgu self assert: bcContext receiver identicalTo: receiver; - assertCollection: bcContext arguments hasSameElements: arguments. + assertCollection: bcContext arguments hasSameElements: arguments; + assert: bcContext method + identicalTo: methodContext methodOrBlock compiledCode. bcContext := bcContext sender. methodContext := methodContext sender ]. diff --git a/DebuggableASTInterpreter/DASTMethod.class.st b/DebuggableASTInterpreter/DASTMethod.class.st index aa8ade0..52373eb 100644 --- a/DebuggableASTInterpreter/DASTMethod.class.st +++ b/DebuggableASTInterpreter/DASTMethod.class.st @@ -13,6 +13,12 @@ DASTMethod >> bodyOffset [ ^ self selectorFormatted size "+ (self isNoMethod ifTrue: [ 1 ] ifFalse: [ 0 ])" ] +{ #category : #accessing } +DASTMethod >> compiledCode [ + + ^ self nodeAST compiledMethod +] + { #category : #accessing } DASTMethod >> evaluatePrimitive [ ^ evaluatePrimitive ifNil: [ evaluatePrimitive := true ] From e04a8c53d94ec524f71c52df3f5305ac0a251519 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:42:27 +0100 Subject: [PATCH 10/43] testing DASTBlockContext>>#asContext keeps same stack and PC equivalence --- DebuggableASTInterpreter/DASTContext.class.st | 30 +++++++---- .../DASTContextRootSmalltalk.class.st | 8 +++ .../DASTContextTests.class.st | 50 +++++++++++++++++++ 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index f84af4f..00218ac 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -106,12 +106,7 @@ DASTContext >> arguments [ DASTContext >> asContext [ | newContext nextNode nextPC nextNodes | - newContext := (Context newForMethod: self method) - setSender: self sender asContext - receiver: self receiver - method: self methodOrBlock compiledCode - closure: self methodOrBlock closure - startpc: self methodOrBlock compiledCode initialPC. + newContext := self privAsContext. nextNodes := self nodes copy. "We need to change pc" @@ -121,9 +116,7 @@ DASTContext >> asContext [ newContext pc: nextPC. "We need to rebuild the stack" - newContext stackp: 0. - (self allTemps collect: [ :each | each value ]) , self stack do: [ - :each | newContext push: each ]. + self privCopyStackInContext: newContext. ^ newContext ] @@ -630,6 +623,25 @@ DASTContext >> printOn: aStream [ ] +{ #category : #converting } +DASTContext >> privAsContext [ + + ^ (Context newForMethod: self method) + setSender: self sender asContext + receiver: self receiver + method: self methodOrBlock compiledCode + closure: self methodOrBlock closure + startpc: self methodOrBlock compiledCode initialPC +] + +{ #category : #converting } +DASTContext >> privCopyStackInContext: newContext [ + + newContext stackp: 0. + (self variablesDict associations collect: [ :each | each value ]) + , self stack do: [ :each | newContext push: each ] +] + { #category : #accessing } DASTContext >> receiver [ ^ receiver diff --git a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st index 7e980de..2db9c6f 100644 --- a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st +++ b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st @@ -75,6 +75,14 @@ DASTContextRootSmalltalk >> methodClass [ ^ nil ] +{ #category : #converting } +DASTContextRootSmalltalk >> privCopyStackInContext: newContext [ + + "nothing to copy when self isRoot" + + +] + { #category : #'gt-extension' } DASTContextRootSmalltalk >> sourceCode [ ^ '' diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index 2545c48..f39b8e9 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -72,6 +72,32 @@ DASTContextTests >> testContextInitialization [ self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTBlockContextAsContextKeepsSameEquivalentPc [ + + | bcContext nextNode nodes | + interpreterBlock + stepOver; + stepOver; + stepOver. + bcContext := blockContext asContext. + + "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" + [ bcContext ] whileNotNil: [ + nodes := blockContext nodes copy. + nextNode := nodes pop. + [ blockContext methodOrBlock nodeAST firstPcForNode: nextNode ] + whileNil: [ nextNode := nodes pop ]. + + self + assert: bcContext pc + equals: + (blockContext methodOrBlock nodeAST firstPcForNode: nextNode). + + bcContext := bcContext sender. + blockContext := blockContext sender ] +] + { #category : #tests } DASTContextTests >> testDASTBlockContextAsContextKeepsSameReceiverSenderAndArguments [ @@ -96,6 +122,30 @@ DASTContextTests >> testDASTBlockContextAsContextKeepsSameReceiverSenderAndArgum self assert: blockContext isRoot ] +{ #category : #tests } +DASTContextTests >> testDASTBlockContextAsContextKeepsSameStack [ + + | bcContext stack | + interpreterBlock + stepOver; + stepOver; + stepOver. + bcContext := blockContext asContext. + + "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" + [ bcContext ] whileNotNil: [ + stack := blockContext stack. + + self + assert: bcContext stackPtr + equals: stack size + blockContext variablesDict size. + 1 to: stack size do: [ :each | + self assert: stack pop identicalTo: bcContext pop ]. + + bcContext := bcContext sender. + blockContext := blockContext sender ] +] + { #category : #tests } DASTContextTests >> testDASTMethodContextAsContextHasSameResult [ From e03328dc4a14b75dfc000cdbb66d6900bcee585b Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 7 Nov 2022 15:46:10 +0100 Subject: [PATCH 11/43] testing that DASTBlockContext>>#asContext has same result as the block context itself. Just like with DASTMethodContext, it works but it raises a Context>>#cannotReturn: --- .../DASTContextTests.class.st | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index f39b8e9..2fb8678 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -72,6 +72,27 @@ DASTContextTests >> testContextInitialization [ self assert: context executedNodes isEmpty ] +{ #category : #tests } +DASTContextTests >> testDASTBlockContextAsContextHasSameResult [ + + | bcContext process result | + interpreterBlock + stepOver; + stepOver; + stepOver. + bcContext := blockContext asContext. + process := Process + forContext: bcContext + priority: Processor userInterruptPriority. + + result := interpreterBlock evaluate. + + process completeTo: bcContext sender. + self assert: process suspendedContext top equals: result. + + self shouldnt: [ process resume ] raise: [ Exception ] +] + { #category : #tests } DASTContextTests >> testDASTBlockContextAsContextKeepsSameEquivalentPc [ From 4d8af2ec3a2321697f46a9e6886dc0b6c2b9bff2 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 15 Nov 2022 15:23:21 +0100 Subject: [PATCH 12/43] ajout d'un rootContext qui termine le processus lors de la traduction DASTContext -> Context --- .../DASTContextRootSmalltalk.class.st | 2 +- .../DASTContextTests.class.st | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st index 2db9c6f..128e0ef 100644 --- a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st +++ b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st @@ -27,7 +27,7 @@ DASTContextRootSmalltalk >> arguments [ { #category : #converting } DASTContextRootSmalltalk >> asContext [ - ^ nil + ^ [ Processor terminateRealActive] asContext ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index 2fb8678..e3c068b 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -104,7 +104,7 @@ DASTContextTests >> testDASTBlockContextAsContextKeepsSameEquivalentPc [ bcContext := blockContext asContext. "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" - [ bcContext ] whileNotNil: [ + [ blockContext isRoot ] whileFalse: [ nodes := blockContext nodes copy. nextNode := nodes pop. [ blockContext methodOrBlock nodeAST firstPcForNode: nextNode ] @@ -126,7 +126,7 @@ DASTContextTests >> testDASTBlockContextAsContextKeepsSameReceiverSenderAndArgum bcContext := blockContext asContext. "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" - [ bcContext ] whileNotNil: [ + [ blockContext isRoot ] whileFalse: [ receiver := blockContext receiver. arguments := blockContext arguments. bcMethod := bcContext method. @@ -197,7 +197,7 @@ DASTContextTests >> testDASTMethodContextAsContextKeepsSameEquivalentPc [ bcContext := methodContext asContext. "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" - [ bcContext ] whileNotNil: [ + [ methodContext isRoot ] whileFalse: [ nodes := methodContext nodes copy. nextNode := nodes pop. [ methodContext methodOrBlock nodeAST firstPcForNode: nextNode ] @@ -219,7 +219,7 @@ DASTContextTests >> testDASTMethodContextAsContextKeepsSameReceiverSenderAndArgu bcContext := methodContext asContext. "We check that bcContext and its senders have the same receiver and arguments the DASTContext and its senders" - [ bcContext ] whileNotNil: [ + [ methodContext isRoot ] whileFalse: [ receiver := methodContext receiver. arguments := methodContext arguments. @@ -261,12 +261,17 @@ DASTContextTests >> testDASTMethodContextAsContextKeepsSameStack [ { #category : #tests } DASTContextTests >> testDASTRootContextAsContext [ - | bcContext | + | bcContext process | self assert: rootContext sender isNil. bcContext := rootContext asContext. - self assert: bcContext isNil + process := Process + forContext: bcContext + priority: Processor userInterruptPriority. + self shouldnt: [ process resume ] raise: [ Exception ]. + + self assert: process isTerminated ] { #category : #stack } From 389f616730ebc8d86ceba9f595bcb91bfc862fbb Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 25 Nov 2022 14:12:12 +0100 Subject: [PATCH 13/43] experiment Context -> DASTContext --- DebuggableASTInterpreter/Context.extension.st | 28 ++++++++++++++++ DebuggableASTInterpreter/DASTContext.class.st | 1 + .../DASTContextSwitchTests.class.st | 33 +++++++++++++++++++ .../DASTContextTests.class.st | 2 +- .../DASTInterpreter.class.st | 33 +++++++------------ .../StDebuggerObjectForTests.extension.st | 9 +++++ .../UndefinedObject.extension.st | 11 +++++++ 7 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 DebuggableASTInterpreter/Context.extension.st create mode 100644 DebuggableASTInterpreter/DASTContextSwitchTests.class.st create mode 100644 DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st create mode 100644 DebuggableASTInterpreter/UndefinedObject.extension.st diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st new file mode 100644 index 0000000..cc2b2ef --- /dev/null +++ b/DebuggableASTInterpreter/Context.extension.st @@ -0,0 +1,28 @@ +Extension { #name : #Context } + +{ #category : #'*DebuggableASTInterpreter' } +Context >> asDASTContextInterpretedBy: aDASTInterpreter [ + + | dastCtx | + dastCtx := DASTContext + newWithSender: + (sender asDASTContextInterpretedBy: aDASTInterpreter) + receiver: (sender ifNil: [closureOrNil] ifNotNil:[receiver]) + messageNode: (sender + ifNil: [ + closureOrNil ifNotNil: [ + RBMessageNode + receiver: RBValueNode new + selector: #value ] ] + ifNotNil: [ + sender sourceNodeExecuted ]) + evaluator: aDASTInterpreter evaluator. + ^ dastCtx +] + +{ #category : #'*DebuggableASTInterpreter' } +Context >> nodeForCurrentPC [ + + ^ self method ast sourceNodeForPC: pc + +] diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 00218ac..c0f6c54 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -110,6 +110,7 @@ DASTContext >> asContext [ nextNodes := self nodes copy. "We need to change pc" + nextPC := nil. [ nextPC ] whileNil: [ nextNode := nextNodes pop. nextPC := self methodOrBlock nodeAST firstPcForNode: nextNode ]. diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st new file mode 100644 index 0000000..f3aa43d --- /dev/null +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -0,0 +1,33 @@ +Class { + #name : #DASTContextSwitchTests, + #superclass : #TestCase, + #instVars : [ + 'context' + ], + #category : #'DebuggableASTInterpreter-Tests' +} + +{ #category : #running } +DASTContextSwitchTests >> setUp [ + | debuggerObjectForTest | + super setUp. + debuggerObjectForTest := StDebuggerObjectForTests new. + context := [ debuggerObjectForTest methodWithTempsAssignments ] asContext. + 2 timesRepeat: [ context := context step ] + + "Put here a common initialization logic for tests" +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitch [ + | dastContext | + 4 timesRepeat: [ context := context step ]. + self assert: ((context lookupTempVar: #a) readInContext: context) equals: 40. + self assert: ((context lookupTempVar: #b) readInContext: context) equals: 2. + + self halt. + dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. + self halt + + +] diff --git a/DebuggableASTInterpreter/DASTContextTests.class.st b/DebuggableASTInterpreter/DASTContextTests.class.st index e3c068b..6903394 100644 --- a/DebuggableASTInterpreter/DASTContextTests.class.st +++ b/DebuggableASTInterpreter/DASTContextTests.class.st @@ -269,7 +269,7 @@ DASTContextTests >> testDASTRootContextAsContext [ process := Process forContext: bcContext priority: Processor userInterruptPriority. - self shouldnt: [ process resume ] raise: [ Exception ]. + self shouldnt: [ process resume ] raise: [ BlockCannotReturn ]. self assert: process isTerminated ] diff --git a/DebuggableASTInterpreter/DASTInterpreter.class.st b/DebuggableASTInterpreter/DASTInterpreter.class.st index 7ccb093..71de9c6 100644 --- a/DebuggableASTInterpreter/DASTInterpreter.class.st +++ b/DebuggableASTInterpreter/DASTInterpreter.class.st @@ -14,6 +14,16 @@ Class { #category : #'DebuggableASTInterpreter-Core' } +{ #category : #'as yet unclassified' } +DASTInterpreter class >> startFromContext: aContext [ + + | interpreter | + interpreter := self new. + + ^ interpreter initializeWithContext: + (aContext asDASTContextInterpretedBy: interpreter) +] + { #category : #accessing } DASTInterpreter >> astCache: aCollection [ astCache := aCollection @@ -113,29 +123,8 @@ DASTInterpreter >> increasePC [ DASTInterpreter >> initializeWithContext: aDASTContext [ "initialize the interpreter to resume the execution from the context got as argument" - | visitor nodes rootContext aRBNode aCollection| -self halt. - astCache := IdentityDictionary new. programCounter := 0. - visitor := DASTPostOrderTreeVisitor new. - - (aRBNode methodNode body addReturn; yourself) acceptVisitor: visitor. - nodes := visitor stack. - rootContext := DASTContextRootSmalltalk new - evaluator: self evaluator; - yourself. - "ugly method necessary because we are putting the root expression of the AST inside a return and sending it the message value" - self flag: 'update next call'. - " Set the first method (noMethod) context evaluation. The receiver is nil " - currentContext := DASTMethodContext new - receiver: self evaluator nilObject; - parent: rootContext; - methodOrBlock: (DASTMethod new initializeWith: nodes last methodNode evaluator: self evaluator); - nodes: nodes; - sender: rootContext; - temps: aCollection; - evaluator: self evaluator; - yourself. + self currentContext: aDASTContext ] diff --git a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st new file mode 100644 index 0000000..f05031d --- /dev/null +++ b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st @@ -0,0 +1,9 @@ +Extension { #name : #StDebuggerObjectForTests } + +{ #category : #'*DebuggableASTInterpreter' } +StDebuggerObjectForTests >> methodWithTempsAssignments [ + |a b| + a := 40. + b := 2. + ^a + b +] diff --git a/DebuggableASTInterpreter/UndefinedObject.extension.st b/DebuggableASTInterpreter/UndefinedObject.extension.st new file mode 100644 index 0000000..a7215e2 --- /dev/null +++ b/DebuggableASTInterpreter/UndefinedObject.extension.st @@ -0,0 +1,11 @@ +Extension { #name : #UndefinedObject } + +{ #category : #'*DebuggableASTInterpreter' } +UndefinedObject >> asDASTContextInterpretedBy: aDastInterpreter [ + ^ DASTContextRootSmalltalk new +] + +{ #category : #'*DebuggableASTInterpreter' } +UndefinedObject >> nodeForCurrentPC [ + ^ nil +] From 6aea1e8c898549ca5b0af170ae660766f46974f2 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 30 Jan 2023 10:57:20 +0100 Subject: [PATCH 14/43] bytecode to DAST interpreter switch + small DAST debugger prototype --- DebuggableASTDebugger/DASTDebugger.class.st | 84 +++++++++++++++++++ DebuggableASTInterpreter/Context.extension.st | 36 ++++---- .../DASTBlockContext.class.st | 6 ++ DebuggableASTInterpreter/DASTContext.class.st | 8 +- .../DASTContextSwitchTests.class.st | 10 ++- .../DASTMethodContext.class.st | 5 ++ .../StDebuggerObjectForTests.extension.st | 9 +- 7 files changed, 134 insertions(+), 24 deletions(-) create mode 100644 DebuggableASTDebugger/DASTDebugger.class.st diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st new file mode 100644 index 0000000..b0d5de4 --- /dev/null +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -0,0 +1,84 @@ +Class { + #name : #DASTDebugger, + #superclass : #SpPresenter, + #traits : 'TDebugger', + #classTraits : 'TDebugger classTrait', + #instVars : [ + 'stack', + 'code', + 'interpreter', + 'toolBar', + 'simulatorSession' + ], + #category : #DebuggableASTDebugger +} + +{ #category : #'instance creation' } +DASTDebugger class >> debugSession: aDebugSession [ + + | dast | + dast := self basicNew. + dast simulatorSession: aDebugSession. + dast interpreter: + (DASTInterpreter startFromContext: aDebugSession interruptedContext). + dast initialize. + dast open +] + +{ #category : #accessing } +DASTDebugger >> clear [ + simulatorSession terminate +] + +{ #category : #initialization } +DASTDebugger >> initializePresenters [ + + code := self newCode. + stack := self newList + transmitDo: [ :ctx | self updateCodeFromContext: ctx ]; + yourself. + toolBar := self newToolbar + addItem: (SpToolbarButtonPresenter new + label: 'Step'; + icon: (self iconNamed: #smallOk); + action: [ self stepInterpreter ]; + yourself); + yourself. + self updateStack +] + +{ #category : #accessing } +DASTDebugger >> simulatorSession: anObject [ + + simulatorSession := anObject +] + +{ #category : #'as yet unclassified' } +DASTDebugger >> stepInterpreter [ + + + interpreter stepInto. + self updateStack +] + +{ #category : #'presenter - code' } +DASTDebugger >> updateCodeFromContext: aDASTContext [ + + aDASTContext ifNil: [ ^ nil ]. + code text: aDASTContext sourceCode. + code beForContext: aDASTContext. + code removeAllTextSegmentDecorations. + + code addTextSegmentDecoration: (SpTextPresenterDecorator forHighlight + interval: (aDASTContext currentNode start to: aDASTContext currentNode stop + 1); + yourself). + +] + +{ #category : #'as yet unclassified' } +DASTDebugger >> updateStack [ + + stack + items: interpreter contextsStack; + selectFirst +] diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index cc2b2ef..0860b7d 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -3,20 +3,28 @@ Extension { #name : #Context } { #category : #'*DebuggableASTInterpreter' } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ - | dastCtx | - dastCtx := DASTContext - newWithSender: - (sender asDASTContextInterpretedBy: aDASTInterpreter) - receiver: (sender ifNil: [closureOrNil] ifNotNil:[receiver]) - messageNode: (sender - ifNil: [ - closureOrNil ifNotNil: [ - RBMessageNode - receiver: RBValueNode new - selector: #value ] ] - ifNotNil: [ - sender sourceNodeExecuted ]) - evaluator: aDASTInterpreter evaluator. + | dastCtx bindings | + bindings := Dictionary new. + self tempNames do: [ :tempName | + bindings at: tempName put: (self tempNamed: tempName) ]. + dastCtx := [ + (DASTContext + newWithSender: + (sender asDASTContextInterpretedBy: aDASTInterpreter) + receiver: + (sender ifNil: [ closureOrNil ] ifNotNil: [ receiver ]) + messageNode: (sender + ifNil: [ + closureOrNil ifNotNil: [ + RBMessageNode + receiver: RBValueNode new + selector: #value ] ] + ifNotNil: [ sender sourceNodeExecuted ]) + evaluator: aDASTInterpreter evaluator) + temps: bindings associations; + yourself ] + on: Exception + do: [ :exc | ^ DASTContextRootSmalltalk new ]. ^ dastCtx ] diff --git a/DebuggableASTInterpreter/DASTBlockContext.class.st b/DebuggableASTInterpreter/DASTBlockContext.class.st index 8c44987..9c2397b 100644 --- a/DebuggableASTInterpreter/DASTBlockContext.class.st +++ b/DebuggableASTInterpreter/DASTBlockContext.class.st @@ -20,6 +20,12 @@ DASTBlockContext >> allTemps [ sender allTemps ] +{ #category : #testing } +DASTBlockContext >> belongsToDoIt [ + self flag: 'wrong imoplementation, to fix'. + ^false +] + { #category : #initialization } DASTBlockContext >> contextTag [ ^ closure outerContext diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index c0f6c54..49b5cd0 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -613,14 +613,14 @@ DASTContext >> parent: aDASTContext [ { #category : #accessing } DASTContext >> printOn: aStream [ - "aStream + aStream cr; nextPutAll: (receiver ifNotNil: [ receiver asString ] ifNil: [ 'nil' ]); nextPutAll: ' <- '; - nextPutAll: (closure ifNotNil: [ closure selector asString ] ifNil: ['nil'])." - + nextPutAll: (closure ifNotNil: [ closure selector asString ] ifNil: ['nil']). + " aStream - nextPutAll: 'DAST Context standard' + nextPutAll: 'DAST Context standard'" ] diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index f3aa43d..7abab5c 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -18,6 +18,13 @@ DASTContextSwitchTests >> setUp [ "Put here a common initialization logic for tests" ] +{ #category : #running } +DASTContextSwitchTests >> tearDown [ + context terminate. + super tearDown. + +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitch [ | dastContext | @@ -25,9 +32,8 @@ DASTContextSwitchTests >> testInterpreterSwitch [ self assert: ((context lookupTempVar: #a) readInContext: context) equals: 40. self assert: ((context lookupTempVar: #b) readInContext: context) equals: 2. - self halt. dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. - self halt +" self assert: (dastContext findLocalVariable: #a) value equals: 40" ] diff --git a/DebuggableASTInterpreter/DASTMethodContext.class.st b/DebuggableASTInterpreter/DASTMethodContext.class.st index 5dfec68..3e336d0 100644 --- a/DebuggableASTInterpreter/DASTMethodContext.class.st +++ b/DebuggableASTInterpreter/DASTMethodContext.class.st @@ -25,6 +25,11 @@ DASTMethodContext >> arguments [ ^ (self method ast arguments collect: [ :each | each name ]) collect: [ :each | (self findLocalVariable: each) value ] ] +{ #category : #testing } +DASTMethodContext >> belongsToDoIt [ + ^false +] + { #category : #'API-lookup' } DASTMethodContext >> findLocalVariable: aName [ ^ variablesDict diff --git a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st index f05031d..d44b9df 100644 --- a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st +++ b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st @@ -2,8 +2,9 @@ Extension { #name : #StDebuggerObjectForTests } { #category : #'*DebuggableASTInterpreter' } StDebuggerObjectForTests >> methodWithTempsAssignments [ - |a b| - a := 40. - b := 2. - ^a + b + + | a b | + a := 40. + b := 2. + ^ a + b ] From 2651f8c98cfce738490995fd7776a907343b5ac4 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 30 Jan 2023 10:57:20 +0100 Subject: [PATCH 15/43] bytecode to DAST interpreter switch + small DAST debugger prototype Co-Authored-By: Steven Costiou <26929529+StevenCostiou@users.noreply.github.com> --- DebuggableASTDebugger/DASTDebugger.class.st | 84 +++++++++++++++++++ DebuggableASTInterpreter/Context.extension.st | 36 ++++---- .../DASTBlockContext.class.st | 6 ++ DebuggableASTInterpreter/DASTContext.class.st | 8 +- .../DASTContextSwitchTests.class.st | 10 ++- .../DASTMethodContext.class.st | 5 ++ .../StDebuggerObjectForTests.extension.st | 9 +- 7 files changed, 134 insertions(+), 24 deletions(-) create mode 100644 DebuggableASTDebugger/DASTDebugger.class.st diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st new file mode 100644 index 0000000..b0d5de4 --- /dev/null +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -0,0 +1,84 @@ +Class { + #name : #DASTDebugger, + #superclass : #SpPresenter, + #traits : 'TDebugger', + #classTraits : 'TDebugger classTrait', + #instVars : [ + 'stack', + 'code', + 'interpreter', + 'toolBar', + 'simulatorSession' + ], + #category : #DebuggableASTDebugger +} + +{ #category : #'instance creation' } +DASTDebugger class >> debugSession: aDebugSession [ + + | dast | + dast := self basicNew. + dast simulatorSession: aDebugSession. + dast interpreter: + (DASTInterpreter startFromContext: aDebugSession interruptedContext). + dast initialize. + dast open +] + +{ #category : #accessing } +DASTDebugger >> clear [ + simulatorSession terminate +] + +{ #category : #initialization } +DASTDebugger >> initializePresenters [ + + code := self newCode. + stack := self newList + transmitDo: [ :ctx | self updateCodeFromContext: ctx ]; + yourself. + toolBar := self newToolbar + addItem: (SpToolbarButtonPresenter new + label: 'Step'; + icon: (self iconNamed: #smallOk); + action: [ self stepInterpreter ]; + yourself); + yourself. + self updateStack +] + +{ #category : #accessing } +DASTDebugger >> simulatorSession: anObject [ + + simulatorSession := anObject +] + +{ #category : #'as yet unclassified' } +DASTDebugger >> stepInterpreter [ + + + interpreter stepInto. + self updateStack +] + +{ #category : #'presenter - code' } +DASTDebugger >> updateCodeFromContext: aDASTContext [ + + aDASTContext ifNil: [ ^ nil ]. + code text: aDASTContext sourceCode. + code beForContext: aDASTContext. + code removeAllTextSegmentDecorations. + + code addTextSegmentDecoration: (SpTextPresenterDecorator forHighlight + interval: (aDASTContext currentNode start to: aDASTContext currentNode stop + 1); + yourself). + +] + +{ #category : #'as yet unclassified' } +DASTDebugger >> updateStack [ + + stack + items: interpreter contextsStack; + selectFirst +] diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index cc2b2ef..0860b7d 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -3,20 +3,28 @@ Extension { #name : #Context } { #category : #'*DebuggableASTInterpreter' } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ - | dastCtx | - dastCtx := DASTContext - newWithSender: - (sender asDASTContextInterpretedBy: aDASTInterpreter) - receiver: (sender ifNil: [closureOrNil] ifNotNil:[receiver]) - messageNode: (sender - ifNil: [ - closureOrNil ifNotNil: [ - RBMessageNode - receiver: RBValueNode new - selector: #value ] ] - ifNotNil: [ - sender sourceNodeExecuted ]) - evaluator: aDASTInterpreter evaluator. + | dastCtx bindings | + bindings := Dictionary new. + self tempNames do: [ :tempName | + bindings at: tempName put: (self tempNamed: tempName) ]. + dastCtx := [ + (DASTContext + newWithSender: + (sender asDASTContextInterpretedBy: aDASTInterpreter) + receiver: + (sender ifNil: [ closureOrNil ] ifNotNil: [ receiver ]) + messageNode: (sender + ifNil: [ + closureOrNil ifNotNil: [ + RBMessageNode + receiver: RBValueNode new + selector: #value ] ] + ifNotNil: [ sender sourceNodeExecuted ]) + evaluator: aDASTInterpreter evaluator) + temps: bindings associations; + yourself ] + on: Exception + do: [ :exc | ^ DASTContextRootSmalltalk new ]. ^ dastCtx ] diff --git a/DebuggableASTInterpreter/DASTBlockContext.class.st b/DebuggableASTInterpreter/DASTBlockContext.class.st index 8c44987..9c2397b 100644 --- a/DebuggableASTInterpreter/DASTBlockContext.class.st +++ b/DebuggableASTInterpreter/DASTBlockContext.class.st @@ -20,6 +20,12 @@ DASTBlockContext >> allTemps [ sender allTemps ] +{ #category : #testing } +DASTBlockContext >> belongsToDoIt [ + self flag: 'wrong imoplementation, to fix'. + ^false +] + { #category : #initialization } DASTBlockContext >> contextTag [ ^ closure outerContext diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index c0f6c54..49b5cd0 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -613,14 +613,14 @@ DASTContext >> parent: aDASTContext [ { #category : #accessing } DASTContext >> printOn: aStream [ - "aStream + aStream cr; nextPutAll: (receiver ifNotNil: [ receiver asString ] ifNil: [ 'nil' ]); nextPutAll: ' <- '; - nextPutAll: (closure ifNotNil: [ closure selector asString ] ifNil: ['nil'])." - + nextPutAll: (closure ifNotNil: [ closure selector asString ] ifNil: ['nil']). + " aStream - nextPutAll: 'DAST Context standard' + nextPutAll: 'DAST Context standard'" ] diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index f3aa43d..7abab5c 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -18,6 +18,13 @@ DASTContextSwitchTests >> setUp [ "Put here a common initialization logic for tests" ] +{ #category : #running } +DASTContextSwitchTests >> tearDown [ + context terminate. + super tearDown. + +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitch [ | dastContext | @@ -25,9 +32,8 @@ DASTContextSwitchTests >> testInterpreterSwitch [ self assert: ((context lookupTempVar: #a) readInContext: context) equals: 40. self assert: ((context lookupTempVar: #b) readInContext: context) equals: 2. - self halt. dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. - self halt +" self assert: (dastContext findLocalVariable: #a) value equals: 40" ] diff --git a/DebuggableASTInterpreter/DASTMethodContext.class.st b/DebuggableASTInterpreter/DASTMethodContext.class.st index 5dfec68..3e336d0 100644 --- a/DebuggableASTInterpreter/DASTMethodContext.class.st +++ b/DebuggableASTInterpreter/DASTMethodContext.class.st @@ -25,6 +25,11 @@ DASTMethodContext >> arguments [ ^ (self method ast arguments collect: [ :each | each name ]) collect: [ :each | (self findLocalVariable: each) value ] ] +{ #category : #testing } +DASTMethodContext >> belongsToDoIt [ + ^false +] + { #category : #'API-lookup' } DASTMethodContext >> findLocalVariable: aName [ ^ variablesDict diff --git a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st index f05031d..d44b9df 100644 --- a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st +++ b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st @@ -2,8 +2,9 @@ Extension { #name : #StDebuggerObjectForTests } { #category : #'*DebuggableASTInterpreter' } StDebuggerObjectForTests >> methodWithTempsAssignments [ - |a b| - a := 40. - b := 2. - ^a + b + + | a b | + a := 40. + b := 2. + ^ a + b ] From 1f8d45ebc626c8347984a0941d466f61be4a7a22 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 30 Jan 2023 13:38:55 +0100 Subject: [PATCH 16/43] Adding a no method class to perform a semantic analysis only when the method is a DoIt --- DebuggableASTInterpreter/DASTClosure.class.st | 4 +-- DebuggableASTInterpreter/DASTContext.class.st | 32 ++++++++++--------- .../DASTContextSwitchTests.class.st | 19 +++++++---- DebuggableASTInterpreter/DASTMethod.class.st | 2 +- .../DASTNoMethod.class.st | 18 +++++++++++ .../StDebuggerObjectForTests.extension.st | 4 +-- 6 files changed, 51 insertions(+), 28 deletions(-) create mode 100644 DebuggableASTInterpreter/DASTNoMethod.class.st diff --git a/DebuggableASTInterpreter/DASTClosure.class.st b/DebuggableASTInterpreter/DASTClosure.class.st index a4d8e4e..223f59d 100644 --- a/DebuggableASTInterpreter/DASTClosure.class.st +++ b/DebuggableASTInterpreter/DASTClosure.class.st @@ -88,9 +88,7 @@ DASTClosure >> nodeAST: aRBNode [ sourceCode := aRBNode sourceCode. nodeAST := aRBNode. - numArgs := nodeAST arguments size. - - nodeAST doSemanticAnalysis + numArgs := nodeAST arguments size ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 49b5cd0..d15e1e9 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -31,25 +31,27 @@ Class { { #category : #instantiation } DASTContext class >> newNoMethodContextWithProgram: aRBNode temps: aCollection evaluator: anEvaluator [ "special context for the first call" + | nodes rootContext noMethod | - nodes := DASTPostOrderTreeVisitor new flattenedNodesFrom: aRBNode. - - rootContext := DASTContextRootSmalltalk new - evaluator: anEvaluator; - yourself. - - noMethod := (DASTMethod new initializeWith: nodes last methodNode evaluator: anEvaluator). + + rootContext := DASTContextRootSmalltalk new + evaluator: anEvaluator; + yourself. + + noMethod := DASTNoMethod new + initializeWith: nodes last methodNode + evaluator: anEvaluator. " Set the first method (noMethod) context evaluation. The receiver is nil " ^ DASTMethodContext new - receiver: anEvaluator nilObject; - parent: rootContext; - methodOrBlock: noMethod; - nodes: nodes; - sender: rootContext; - temps: aCollection; - evaluator: anEvaluator; - yourself. + receiver: anEvaluator nilObject; + parent: rootContext; + methodOrBlock: noMethod; + nodes: nodes; + sender: rootContext; + temps: aCollection; + evaluator: anEvaluator; + yourself ] { #category : #instantiation } diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 7abab5c..0160456 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -27,13 +27,18 @@ DASTContextSwitchTests >> tearDown [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitch [ + | dastContext | 4 timesRepeat: [ context := context step ]. - self assert: ((context lookupTempVar: #a) readInContext: context) equals: 40. - self assert: ((context lookupTempVar: #b) readInContext: context) equals: 2. - - dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. -" self assert: (dastContext findLocalVariable: #a) value equals: 40" - - + self + assert: ((context lookupTempVar: #a) readInContext: context) + equals: 40. + self + assert: ((context lookupTempVar: #b) readInContext: context) + equals: 2. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + self assert: (dastContext findLocalVariable: #a) value equals: 40. + self assert: (dastContext findLocalVariable: #b) value equals: 2 ] diff --git a/DebuggableASTInterpreter/DASTMethod.class.st b/DebuggableASTInterpreter/DASTMethod.class.st index 52373eb..e2dced2 100644 --- a/DebuggableASTInterpreter/DASTMethod.class.st +++ b/DebuggableASTInterpreter/DASTMethod.class.st @@ -87,7 +87,7 @@ DASTMethod >> isNamedPrimitive [ { #category : #testing } DASTMethod >> isNoMethod [ - ^ self selector = #noMethod + ^ self selector = #DoIt ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTNoMethod.class.st b/DebuggableASTInterpreter/DASTNoMethod.class.st new file mode 100644 index 0000000..634de8f --- /dev/null +++ b/DebuggableASTInterpreter/DASTNoMethod.class.st @@ -0,0 +1,18 @@ +Class { + #name : #DASTNoMethod, + #superclass : #DASTMethod, + #category : #'DebuggableASTInterpreter-Closures' +} + +{ #category : #testing } +DASTNoMethod >> isNoMethod [ + + ^ true +] + +{ #category : #accessing } +DASTNoMethod >> nodeAST: aRBNode [ + + super nodeAST: aRBNode. + nodeAST doSemanticAnalysis +] diff --git a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st index d44b9df..98133cc 100644 --- a/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st +++ b/DebuggableASTInterpreter/StDebuggerObjectForTests.extension.st @@ -4,7 +4,7 @@ Extension { #name : #StDebuggerObjectForTests } StDebuggerObjectForTests >> methodWithTempsAssignments [ | a b | - a := 40. + a := 40. b := 2. - ^ a + b + ^ a + b ] From ee28860e8f1a5510c0bfc828150b2085e2672e6f Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 30 Jan 2023 14:19:27 +0100 Subject: [PATCH 17/43] adding buttons to DAST debugger + recovering lost changes --- DebuggableASTDebugger/DASTDebugger.class.st | 84 +++++++++++++++++++-- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st index b0d5de4..b14d5ff 100644 --- a/DebuggableASTDebugger/DASTDebugger.class.st +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -25,11 +25,53 @@ DASTDebugger class >> debugSession: aDebugSession [ dast open ] +{ #category : #initialization } +DASTDebugger >> buildToolbar [ + + ^ self newToolbar + addItem: (SpToolbarButtonPresenter new + label: 'Proceed'; + icon: (self iconNamed: #glamorousSpawn); + action: [ self proceed ]; + yourself); + addItem: (SpToolbarButtonPresenter new + label: 'Step'; + icon: (self iconNamed: #down); + action: [ self stepInterpreter ]; + yourself); + addItem: (SpToolbarButtonPresenter new + label: 'Step over'; + icon: (self iconNamed: #forward); + action: [ self stepOver ]; + yourself); + addItem: (SpToolbarButtonPresenter new + label: 'Step through'; + icon: (self iconNamed: #glamorousThrough); + action: [ self stepThrough ]; + yourself); + addItem: (SpToolbarButtonPresenter new + label: 'Restart'; + icon: (self iconNamed: #glamorousRestart); + action: [ self restart ]; + yourself); + yourself +] + { #category : #accessing } DASTDebugger >> clear [ simulatorSession terminate ] +{ #category : #layout } +DASTDebugger >> defaultLayout [ + + ^ SpBoxLayout newVertical + add: stack; + add: toolBar expand: false; + add: code; + yourself +] + { #category : #initialization } DASTDebugger >> initializePresenters [ @@ -37,13 +79,27 @@ DASTDebugger >> initializePresenters [ stack := self newList transmitDo: [ :ctx | self updateCodeFromContext: ctx ]; yourself. - toolBar := self newToolbar - addItem: (SpToolbarButtonPresenter new - label: 'Step'; - icon: (self iconNamed: #smallOk); - action: [ self stepInterpreter ]; - yourself); - yourself. + toolBar := self buildToolbar. + self updateStack +] + +{ #category : #accessing } +DASTDebugger >> interpreter: aDASTInterpreter [ + + interpreter := aDASTInterpreter +] + +{ #category : #menu } +DASTDebugger >> proceed [ + + interpreter evaluate. + self updateStack +] + +{ #category : #menu } +DASTDebugger >> restart [ + + interpreter restart: stack selectedItem. self updateStack ] @@ -61,6 +117,20 @@ DASTDebugger >> stepInterpreter [ self updateStack ] +{ #category : #'debug - stepping' } +DASTDebugger >> stepOver [ + + interpreter stepOver. + self updateStack +] + +{ #category : #actions } +DASTDebugger >> stepThrough [ + + interpreter stepThrough. + self updateStack +] + { #category : #'presenter - code' } DASTDebugger >> updateCodeFromContext: aDASTContext [ From 53410cef342dcdf1e31a8847021e472b8df39320 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 3 Feb 2023 09:52:07 +0100 Subject: [PATCH 18/43] test interpreter switch binding conservations --- .../DASTContextSwitchTests.class.st | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 0160456..f79e464 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -26,7 +26,7 @@ DASTContextSwitchTests >> tearDown [ ] { #category : #tests } -DASTContextSwitchTests >> testInterpreterSwitch [ +DASTContextSwitchTests >> testInterpreterSwitchKeepsBindings [ | dastContext | 4 timesRepeat: [ context := context step ]. @@ -42,3 +42,21 @@ DASTContextSwitchTests >> testInterpreterSwitch [ self assert: (dastContext findLocalVariable: #a) value equals: 40. self assert: (dastContext findLocalVariable: #b) value equals: 2 ] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchKeepsBindingsRecursively [ + + | dastContext tempNames | + 4 timesRepeat: [ context := context step ]. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + tempNames := context tempNames. + tempNames do: [ :temp | + self + assert: ((context lookupTempVar: temp) readInContext: context) + identicalTo: (dastContext findLocalVariable: temp) value ]. + context := context sender. + dastContext := dastContext sender ] +] From 79f21bf0705c2394fa07187a22b8e829e62fa876 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 3 Feb 2023 15:16:42 +0100 Subject: [PATCH 19/43] test interpreter switch keeps receiver unchanged + next nodesis the one mapped to current PC --- DebuggableASTInterpreter/Context.extension.st | 14 ++-- .../DASTContextSwitchTests.class.st | 77 +++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index 0860b7d..a882dd2 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -3,19 +3,20 @@ Extension { #name : #Context } { #category : #'*DebuggableASTInterpreter' } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ - | dastCtx bindings | + | dastCtx bindings aimedNode | + "set current node and executed node stack and next nodes stack" bindings := Dictionary new. - self tempNames do: [ :tempName | + self tempNames do: [ :tempName | bindings at: tempName put: (self tempNamed: tempName) ]. - dastCtx := [ + dastCtx := [ (DASTContext newWithSender: (sender asDASTContextInterpretedBy: aDASTInterpreter) receiver: (sender ifNil: [ closureOrNil ] ifNotNil: [ receiver ]) messageNode: (sender - ifNil: [ - closureOrNil ifNotNil: [ + ifNil: [ + closureOrNil ifNotNil: [ RBMessageNode receiver: RBValueNode new selector: #value ] ] @@ -25,6 +26,9 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ yourself ] on: Exception do: [ :exc | ^ DASTContextRootSmalltalk new ]. + aimedNode := self compiledCode sourceNodeForPC: self pc. + [ aimedNode == dastCtx nodes top ] whileFalse: [ + dastCtx executedNodes push: dastCtx nodes pop ]. ^ dastCtx ] diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index f79e464..64faee2 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -60,3 +60,80 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsBindingsRecursively [ context := context sender. dastContext := dastContext sender ] ] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiver [ + + | dastContext | + 4 timesRepeat: [ context := context step ]. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + self assert: context receiver identicalTo: dastContext receiver +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ + + | dastContext | + 4 timesRepeat: [ context := context step ]. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + self assert: context receiver identicalTo: dastContext receiver. + context := context sender. + dastContext := dastContext sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchReceiverRemainsUnchanged [ + + | dastContext instVars oldInstVarValues newInstVarValues | + 4 timesRepeat: [ context := context step ]. + + instVars := context receiver class allInstVarNames. + oldInstVarValues := instVars collect: [ :inst | + context receiver instVarNamed: inst ]. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + newInstVarValues := instVars collect: [ :inst | + dastContext receiver instVarNamed: inst ]. + + oldInstVarValues withIndexDo: [ :each :index | + self assert: each identicalTo: (newInstVarValues at: index) ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPC [ + + | dastContext pc node | + 4 timesRepeat: [ context := context step ]. + + pc := context pc. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + node := context compiledCode sourceNodeForPC: context pc. + + self assert: dastContext nodes top identicalTo: node +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPCRecursively [ + + | dastContext pcs node | + 4 timesRepeat: [ context := context step ]. + + pcs := context stack collect: [ :ctx | ctx pc ]. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + node := context compiledCode sourceNodeForPC: context pc. + + self assert: dastContext nodes top identicalTo: node. + context := context sender. + dastContext := dastContext sender ] +] From 3e5c7412e03814a4a0195754f43329141ec115c8 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 3 Feb 2023 16:30:10 +0100 Subject: [PATCH 20/43] adding failing tests --- DebuggableASTInterpreter/Context.extension.st | 23 +++++++++----- .../DASTContextSwitchTests.class.st | 30 +++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index a882dd2..6caef99 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -13,19 +13,28 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ newWithSender: (sender asDASTContextInterpretedBy: aDASTInterpreter) receiver: - (sender ifNil: [ closureOrNil ] ifNotNil: [ receiver ]) + (sender + ifNil: [ closureOrNil "compiledBlock" ] + ifNotNil: [ receiver ]) messageNode: (sender - ifNil: [ - closureOrNil ifNotNil: [ - RBMessageNode - receiver: RBValueNode new - selector: #value ] ] + ifNil: [ "closureOrNil ifNotNil: [" "]" + RBMessageNode + receiver: RBLiteralValueNode new + selector: #value ] ifNotNil: [ sender sourceNodeExecuted ]) evaluator: aDASTInterpreter evaluator) temps: bindings associations; yourself ] on: Exception - do: [ :exc | ^ DASTContextRootSmalltalk new ]. + do: [ :exc | + UIManager inform: exc printString. + ^ DASTContextRootSmalltalk new + currentNode: + (RBMessageNode + receiver: RBLiteralValueNode new + selector: #value); + yourself ]. + aimedNode := self compiledCode sourceNodeForPC: self pc. [ aimedNode == dastCtx nodes top ] whileFalse: [ dastCtx executedNodes push: dastCtx nodes pop ]. diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 64faee2..3ba3876 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -25,6 +25,20 @@ DASTContextSwitchTests >> tearDown [ ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchCurrentNodeIsLastExecutedNode [ + + | dastContext node | + 4 timesRepeat: [ context := context step ]. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + node := dastContext executedNodes last. + + self assert: dastContext currentNode identicalTo: node +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsBindings [ @@ -86,6 +100,22 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ dastContext := dastContext sender ] ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchMessageNodeIsLastSourceNodeExecutedFromSender [ + + | dastContext pc node | + 4 timesRepeat: [ context := context step ]. + + pc := context pc. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + self deny: dastContext sender isRoot. + node := context sender sourceNodeExecuted. + + self assert: dastContext messageNode identicalTo: node +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchReceiverRemainsUnchanged [ From ebc28cda533f74a91632509a0f161ba8aef2c7fc Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:23:39 +0100 Subject: [PATCH 21/43] adding tests for interpreter switch to ensure that: - the stack remains the same - current node is last executed node - dast context chain is correct (the root is at the right place): this test is not green for now --- DebuggableASTInterpreter/Context.extension.st | 19 +++--- .../DASTBlockContext.class.st | 2 +- .../DASTContextRootSmalltalk.class.st | 6 ++ .../DASTContextSwitchTests.class.st | 65 ++++++++++++++++++- .../DASTMethodContext.class.st | 3 +- 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index 6caef99..584f7f0 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -3,7 +3,7 @@ Extension { #name : #Context } { #category : #'*DebuggableASTInterpreter' } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ - | dastCtx bindings aimedNode | + | dastCtx bindings aimedNode currentNode | "set current node and executed node stack and next nodes stack" bindings := Dictionary new. self tempNames do: [ :tempName | @@ -17,17 +17,17 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ ifNil: [ closureOrNil "compiledBlock" ] ifNotNil: [ receiver ]) messageNode: (sender - ifNil: [ "closureOrNil ifNotNil: [" "]" - RBMessageNode - receiver: RBLiteralValueNode new - selector: #value ] + ifNil: [ + closureOrNil ifNotNil: [ + RBMessageNode + receiver: RBLiteralValueNode new + selector: #value ] ] ifNotNil: [ sender sourceNodeExecuted ]) evaluator: aDASTInterpreter evaluator) temps: bindings associations; yourself ] on: Exception - do: [ :exc | - UIManager inform: exc printString. + do: [ :exc | "UIManager inform: exc printString." ^ DASTContextRootSmalltalk new currentNode: (RBMessageNode @@ -37,7 +37,10 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ aimedNode := self compiledCode sourceNodeForPC: self pc. [ aimedNode == dastCtx nodes top ] whileFalse: [ - dastCtx executedNodes push: dastCtx nodes pop ]. + dastCtx executedNodes push: (currentNode := dastCtx nodes pop) ]. + dastCtx currentNode: currentNode. + (Interval from: self numTemps + 1 to: self stackPtr) do: [ :each | + dastCtx stack push: (self at: each) ]. ^ dastCtx ] diff --git a/DebuggableASTInterpreter/DASTBlockContext.class.st b/DebuggableASTInterpreter/DASTBlockContext.class.st index 9c2397b..4363dc1 100644 --- a/DebuggableASTInterpreter/DASTBlockContext.class.st +++ b/DebuggableASTInterpreter/DASTBlockContext.class.st @@ -55,7 +55,7 @@ DASTBlockContext >> initializeContext [ ifFalse: [ self getClassForLookup ]. " visitor := DASTPostOrderTreeVisitor new. - receiver body acceptVisitor: visitor. + receiver "compiledBlock ast" body acceptVisitor: visitor. nodes := visitor stack. currentNode := nodes top. self methodOrBlock: receiver; diff --git a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st index 128e0ef..1d41386 100644 --- a/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st +++ b/DebuggableASTInterpreter/DASTContextRootSmalltalk.class.st @@ -37,6 +37,12 @@ DASTContextRootSmalltalk >> assignVariable: name value: value [ ^ false ] +{ #category : #testing } +DASTContextRootSmalltalk >> belongsToDoIt [ + + ^ false +] + { #category : #'API-lookup' } DASTContextRootSmalltalk >> findLocalVariable: aName [ ^ nil diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 3ba3876..845c76e 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -100,13 +100,50 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ dastContext := dastContext sender ] ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchKeepsValueStack [ + + | dastContext | + 6 timesRepeat: [ context := context step ]. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + self + assert: dastContext stack size + equals: context stackPtr - context numTemps. + (Interval from: 1 to: dastContext stack size) do: [ :index | + self + assert: (dastContext stack at: index) + identicalTo: (context at: context numTemps + index) ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchKeepsValueStackRecursively [ + + | dastContext | + 6 timesRepeat: [ context := context step ]. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + self + assert: dastContext stack size + equals: context stackPtr - context numTemps. + (Interval from: 1 to: dastContext stack size) do: [ :index | + self + assert: (dastContext stack at: index) + identicalTo: (context at: context numTemps + index) ]. + context := context sender. + dastContext := dastContext sender ] +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchMessageNodeIsLastSourceNodeExecutedFromSender [ - | dastContext pc node | + | dastContext node | 4 timesRepeat: [ context := context step ]. - pc := context pc. dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. @@ -116,6 +153,30 @@ DASTContextSwitchTests >> testInterpreterSwitchMessageNodeIsLastSourceNodeExecut self assert: dastContext messageNode identicalTo: node ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchPutsRootBeforeFirstInterestingContext [ + + | dastContext | + 4 timesRepeat: [ context step ]. + + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + self deny: dastContext isRoot. + self deny: dastContext isBlockContext. + self + assert: dastContext methodOrBlock compiledCode + identicalTo: context compiledCode. + + self deny: dastContext sender isRoot. + self assert: dastContext sender isBlockContext. + self + assert: dastContext sender nodeAST compiledCode + identicalTo: context sender compiledCode. + + self assert: dastContext sender sender isRoot +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchReceiverRemainsUnchanged [ diff --git a/DebuggableASTInterpreter/DASTMethodContext.class.st b/DebuggableASTInterpreter/DASTMethodContext.class.st index 3e336d0..6730783 100644 --- a/DebuggableASTInterpreter/DASTMethodContext.class.st +++ b/DebuggableASTInterpreter/DASTMethodContext.class.st @@ -27,7 +27,8 @@ DASTMethodContext >> arguments [ { #category : #testing } DASTMethodContext >> belongsToDoIt [ - ^false + + ^ self methodOrBlock isNoMethod ] { #category : #'API-lookup' } From 9b812b6dda30b8faba914d075b15ec42b185b8fc Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 6 Feb 2023 13:59:06 +0100 Subject: [PATCH 22/43] fixing some tests --- DebuggableASTInterpreter/Context.extension.st | 33 ++++++++++--------- DebuggableASTInterpreter/DASTBlock.class.st | 2 +- DebuggableASTInterpreter/DASTContext.class.st | 5 +++ .../DASTContextSwitchTests.class.st | 6 ++-- .../DASTMethodContext.class.st | 5 --- 5 files changed, 27 insertions(+), 24 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index 584f7f0..58d1f77 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -3,37 +3,40 @@ Extension { #name : #Context } { #category : #'*DebuggableASTInterpreter' } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ - | dastCtx bindings aimedNode currentNode | + | dastCtx bindings aimedNode currentNode dastSender | "set current node and executed node stack and next nodes stack" bindings := Dictionary new. self tempNames do: [ :tempName | bindings at: tempName put: (self tempNamed: tempName) ]. - dastCtx := [ - (DASTContext + dastCtx := (DASTContext newWithSender: - (sender asDASTContextInterpretedBy: aDASTInterpreter) - receiver: - (sender - ifNil: [ closureOrNil "compiledBlock" ] - ifNotNil: [ receiver ]) + (dastSender := sender asDASTContextInterpretedBy: + aDASTInterpreter) + receiver: (closureOrNil ifNil: [ receiver ] ifNotNil: [ + DASTBlock new + nodeAST: closureOrNil compiledBlock ast; + outerContext: dastSender; + yourself ]) messageNode: (sender ifNil: [ closureOrNil ifNotNil: [ - RBMessageNode - receiver: RBLiteralValueNode new - selector: #value ] ] + RBMessageNode + receiver: RBLiteralValueNode new + selector: #value ] ] ifNotNil: [ sender sourceNodeExecuted ]) evaluator: aDASTInterpreter evaluator) temps: bindings associations; - yourself ] - on: Exception - do: [ :exc | "UIManager inform: exc printString." + "sender + ifNil: [ closureOrNil ] + ifNotNil: [ receiver ] ]""on: Exception + do: [ :exc | ""UIManager inform: exc printString."" ^ DASTContextRootSmalltalk new currentNode: (RBMessageNode receiver: RBLiteralValueNode new selector: #value); - yourself ]. + Missing opener for closer: ] -> yourself ]" + yourself. "[" aimedNode := self compiledCode sourceNodeForPC: self pc. [ aimedNode == dastCtx nodes top ] whileFalse: [ diff --git a/DebuggableASTInterpreter/DASTBlock.class.st b/DebuggableASTInterpreter/DASTBlock.class.st index bbebccc..70f02b2 100644 --- a/DebuggableASTInterpreter/DASTBlock.class.st +++ b/DebuggableASTInterpreter/DASTBlock.class.st @@ -128,7 +128,7 @@ DASTBlock >> outerContext [ { #category : #accessing } DASTBlock >> outerContext: aDASTContext [ outerContext := aDASTContext. - self initializeInterval + "self initializeInterval" ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index d15e1e9..bd12765 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -765,6 +765,11 @@ DASTContext >> tempAt: anIndex [ ^ self variablesDict at: (self variablesDict keys at: anIndex) ] +{ #category : #accessing } +DASTContext >> temps: aCollection [ + aCollection do: [ :assoc | self at: assoc key put: assoc value ] +] + { #category : #'private-exceptions' } DASTContext >> terminate [ "Make myself unresumable." diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 845c76e..e236ba6 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -20,7 +20,7 @@ DASTContextSwitchTests >> setUp [ { #category : #running } DASTContextSwitchTests >> tearDown [ - context terminate. + "context terminate." super tearDown. ] @@ -171,8 +171,8 @@ DASTContextSwitchTests >> testInterpreterSwitchPutsRootBeforeFirstInterestingCon self deny: dastContext sender isRoot. self assert: dastContext sender isBlockContext. self - assert: dastContext sender nodeAST compiledCode - identicalTo: context sender compiledCode. + assert: dastContext sender methodOrBlock + equals: context sender compiledCode ast. self assert: dastContext sender sender isRoot ] diff --git a/DebuggableASTInterpreter/DASTMethodContext.class.st b/DebuggableASTInterpreter/DASTMethodContext.class.st index 6730783..56751d0 100644 --- a/DebuggableASTInterpreter/DASTMethodContext.class.st +++ b/DebuggableASTInterpreter/DASTMethodContext.class.st @@ -133,8 +133,3 @@ DASTMethodContext >> removePrimitiveFromMethod [ self methodOrBlock evaluatePrimitive: false ] - -{ #category : #accessing } -DASTMethodContext >> temps: aCollection [ - aCollection do: [ :assoc | self at: assoc key put: assoc value ] -] From 47b1bb76b64dbf76e8e7e0e0e53a8f9c42f264d6 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 10 Feb 2023 10:11:54 +0100 Subject: [PATCH 23/43] Fixing root test --- DebuggableASTInterpreter/DASTContextSwitchTests.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index e236ba6..5dcc92c 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -171,7 +171,7 @@ DASTContextSwitchTests >> testInterpreterSwitchPutsRootBeforeFirstInterestingCon self deny: dastContext sender isRoot. self assert: dastContext sender isBlockContext. self - assert: dastContext sender methodOrBlock + assert: dastContext sender methodOrBlock nodeAST equals: context sender compiledCode ast. self assert: dastContext sender sender isRoot From 24bff4144f23ffff3494c93e812b58be9291ef0a Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 10 Feb 2023 15:41:47 +0100 Subject: [PATCH 24/43] fiixng debugger opening --- DebuggableASTInterpreter/Context.extension.st | 55 +++++++++---------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index 58d1f77..87bd0ff 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -4,39 +4,34 @@ Extension { #name : #Context } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ | dastCtx bindings aimedNode currentNode dastSender | - "set current node and executed node stack and next nodes stack" bindings := Dictionary new. self tempNames do: [ :tempName | bindings at: tempName put: (self tempNamed: tempName) ]. - dastCtx := (DASTContext - newWithSender: - (dastSender := sender asDASTContextInterpretedBy: - aDASTInterpreter) - receiver: (closureOrNil ifNil: [ receiver ] ifNotNil: [ - DASTBlock new - nodeAST: closureOrNil compiledBlock ast; - outerContext: dastSender; - yourself ]) - messageNode: (sender - ifNil: [ - closureOrNil ifNotNil: [ - RBMessageNode - receiver: RBLiteralValueNode new - selector: #value ] ] - ifNotNil: [ sender sourceNodeExecuted ]) - evaluator: aDASTInterpreter evaluator) - temps: bindings associations; - "sender - ifNil: [ closureOrNil ] - ifNotNil: [ receiver ] ]""on: Exception - do: [ :exc | ""UIManager inform: exc printString."" - ^ DASTContextRootSmalltalk new - currentNode: - (RBMessageNode - receiver: RBLiteralValueNode new - selector: #value); - Missing opener for closer: ] -> yourself ]" - yourself. "[" + dastCtx := self compiledCode isDoIt + ifTrue: [ + DASTContext + newNoMethodContextWithProgram: self compiledCode ast + temps: { } + evaluator: aDASTInterpreter evaluator ] + ifFalse: [ + DASTContext + newWithSender: + (dastSender := sender asDASTContextInterpretedBy: + aDASTInterpreter) + receiver: + (closureOrNil ifNil: [ receiver ] ifNotNil: [ + DASTBlock new + nodeAST: closureOrNil compiledBlock ast; + outerContext: dastSender; + yourself ]) + messageNode: (dastSender isRoot + ifTrue: [ + RBMessageNode + receiver: RBMessageNode new + selector: #value ] + ifFalse: [ sender sourceNodeExecuted ]) + evaluator: aDASTInterpreter evaluator ]. + dastCtx temps: bindings associations. aimedNode := self compiledCode sourceNodeForPC: self pc. [ aimedNode == dastCtx nodes top ] whileFalse: [ From 19c84099c0941b603c50f94e272ecbcd3bd383d8 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 10 Feb 2023 16:00:17 +0100 Subject: [PATCH 25/43] adding a test: performing steps after switching interpreter --- .../DASTContextSwitchTests.class.st | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 5dcc92c..12bc72b 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -197,6 +197,34 @@ DASTContextSwitchTests >> testInterpreterSwitchReceiverRemainsUnchanged [ self assert: each identicalTo: (newInstVarValues at: index) ] ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchStepIsCorrect [ + + | dastContext pc node interpreter | + 4 timesRepeat: [ context := context step ]. + + pc := context pc. + dastContext := context asDASTContextInterpretedBy: + (interpreter := DASTInterpreter new). + node := context compiledCode sourceNodeForPC: context pc. + + interpreter initializeWithContext: dastContext. + + self assert: dastContext nodes top identicalTo: node. + self assert: dastContext canExecute. + self assert: interpreter currentContext identicalTo: dastContext. + + "one step to evaluate a (40), one step to evaluate b (2) and one step to compute the sum" + interpreter + stepInto; + stepInto; + stepInto. + + self assert: dastContext nodes top isReturn. + self assert: dastContext canExecute. + self assert: interpreter currentContext identicalTo: dastContext +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPC [ From 255d9b4e2d676ce78a8d29478c004f858f69256a Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 13 Feb 2023 10:54:59 +0100 Subject: [PATCH 26/43] - adding DAST interpreter tests about inlined code - adding bc -> DAST interpreter switch test about being able to find bindings of variables inside closures that are defined in a context outside of these closures but that doesn't have an equivalent DAST context - skipping the test about receivers remaining the same before and after switch, because I'm not sure of what should be the receiver of a DASTBlockContext --- DebuggableASTInterpreter/Context.extension.st | 7 ++++--- DebuggableASTInterpreter/DASTContext.class.st | 4 +++- .../DASTContextSwitchTests.class.st | 15 +++++++++++++++ .../DASTInterpreterTests.class.st | 17 +++++++++++++++++ .../UndefinedObject.extension.st | 5 +++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index 87bd0ff..05eeacf 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -4,6 +4,7 @@ Extension { #name : #Context } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ | dastCtx bindings aimedNode currentNode dastSender | + bindings := Dictionary new. self tempNames do: [ :tempName | bindings at: tempName put: (self tempNamed: tempName) ]. @@ -26,9 +27,9 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ yourself ]) messageNode: (dastSender isRoot ifTrue: [ - RBMessageNode - receiver: RBMessageNode new - selector: #value ] + RBMessageNode + receiver: (RBLiteralValueNode value: nil) + selector: #value ] ifFalse: [ sender sourceNodeExecuted ]) evaluator: aDASTInterpreter evaluator ]. dastCtx temps: bindings associations. diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index bd12765..c360b4b 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -37,7 +37,9 @@ DASTContext class >> newNoMethodContextWithProgram: aRBNode temps: aCollection e rootContext := DASTContextRootSmalltalk new evaluator: anEvaluator; - yourself. + currentNode: (RBMessageNode + receiver: (RBLiteralValueNode value: nil) + selector: #value) yourself. noMethod := DASTNoMethod new initializeWith: nodes last methodNode diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 12bc72b..e5c641a 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -39,6 +39,20 @@ DASTContextSwitchTests >> testInterpreterSwitchCurrentNodeIsLastExecutedNode [ self assert: dastContext currentNode identicalTo: node ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchEvaluateAfterSwitchCanFindBindingsOfObjectsDefinedOutsideOfClosuresInContextThatDoesNotHaveDASTEquivalent [ + + | dastContext debuggerObjectForTest interpreter | + debuggerObjectForTest := StDebuggerObjectForTests new. + context := [ debuggerObjectForTest methodWithTempsAssignments ] + asContext. + interpreter := DASTInterpreter new. + dastContext := context asDASTContextInterpretedBy: interpreter. + interpreter initializeWithContext: dastContext. + + self assert: interpreter evaluate equals: 42 +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsBindings [ @@ -90,6 +104,7 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiver [ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ | dastContext | + self skip. 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. diff --git a/DebuggableASTInterpreter/DASTInterpreterTests.class.st b/DebuggableASTInterpreter/DASTInterpreterTests.class.st index ee27ea3..7e8dd78 100644 --- a/DebuggableASTInterpreter/DASTInterpreterTests.class.st +++ b/DebuggableASTInterpreter/DASTInterpreterTests.class.st @@ -274,6 +274,14 @@ DASTInterpreterTests >> testIfTrue [ equals: 3 ] +{ #category : #'tests-contexts' } +DASTInterpreterTests >> testIfTrueIfFalse [ + + self + assert: (self evaluateProgram: 'false ifTrue: [ ^3] ifFalse: [ ^2]') + equals: 2 +] + { #category : #'tests-blocks' } DASTInterpreterTests >> testIfTrueThatWritesLocalVar [ @@ -929,6 +937,15 @@ DASTInterpreterTests >> testVarsLocalVariableModifiedInsideWhileTrueAndValueBloc ] +{ #category : #'tests-blocks' } +DASTInterpreterTests >> testWhileTrue [ + + self + assert: (self evaluateProgram: + '|a| a := 0. [ a < 5 ] whileTrue: [a := a + 1 ]. ^ a') + equals: 5 +] + { #category : #'tests-self' } DASTInterpreterTests >> testYourSelfTwice [ diff --git a/DebuggableASTInterpreter/UndefinedObject.extension.st b/DebuggableASTInterpreter/UndefinedObject.extension.st index a7215e2..497cc9b 100644 --- a/DebuggableASTInterpreter/UndefinedObject.extension.st +++ b/DebuggableASTInterpreter/UndefinedObject.extension.st @@ -2,7 +2,12 @@ Extension { #name : #UndefinedObject } { #category : #'*DebuggableASTInterpreter' } UndefinedObject >> asDASTContextInterpretedBy: aDastInterpreter [ + ^ DASTContextRootSmalltalk new + currentNode: (RBMessageNode + receiver: (RBLiteralValueNode value: nil) + selector: #value); + yourself ] { #category : #'*DebuggableASTInterpreter' } From 007328970f25d48f62f5c41bb26e03e98d4f5133 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 16 Feb 2023 09:54:24 +0100 Subject: [PATCH 27/43] tests DAST -> Bytecode (receiver, bindings) + upgrdng DAN --- DebuggableASTInterpreter/DASTContext.class.st | 13 +- .../DASTContextSwitchTests.class.st | 114 +++++++++++++++--- .../DASTInterpreter.class.st | 20 ++- .../DASTNoMethod.class.st | 3 +- 4 files changed, 124 insertions(+), 26 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index c360b4b..1d0a252 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -633,7 +633,9 @@ DASTContext >> privAsContext [ ^ (Context newForMethod: self method) setSender: self sender asContext - receiver: self receiver + receiver: (self receiver isBlock + ifFalse: [ self receiver ] + ifTrue: [ self receiver nodeAST evaluate ]) method: self methodOrBlock compiledCode closure: self methodOrBlock closure startpc: self methodOrBlock compiledCode initialPC @@ -643,8 +645,13 @@ DASTContext >> privAsContext [ DASTContext >> privCopyStackInContext: newContext [ newContext stackp: 0. - (self variablesDict associations collect: [ :each | each value ]) - , self stack do: [ :each | newContext push: each ] + (self variablesDict associations collect: [ :each | + | value | + value := each value. + value isBlock + ifFalse: [ value ] + ifTrue: [ value nodeAST evaluate ] ]) , self stack do: [ :each | + newContext push: each ] ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index e5c641a..a0a2d3e 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -2,19 +2,36 @@ Class { #name : #DASTContextSwitchTests, #superclass : #TestCase, #instVars : [ - 'context' + 'context', + 'dastInterpreter', + 'dastContext' ], #category : #'DebuggableASTInterpreter-Tests' } { #category : #running } DASTContextSwitchTests >> setUp [ + | debuggerObjectForTest | super setUp. + "context initialization" debuggerObjectForTest := StDebuggerObjectForTests new. - context := [ debuggerObjectForTest methodWithTempsAssignments ] asContext. - 2 timesRepeat: [ context := context step ] - + context := [ debuggerObjectForTest methodWithTempsAssignments ] + asContext. + 2 timesRepeat: [ context := context step ]. + + "DASTInterpreter initialization (which initializes DAST contexts)" + dastInterpreter := DASTInterpreter new. + dastInterpreter initializeWithProgram: + (RBParser parseExpression: '| debuggerObjectForTest block | + debuggerObjectForTest := StDebuggerObjectForTests new. + block := [ debuggerObjectForTest methodWithTempsAssignments ]. + block value'). + "We step until we step into StDebuggerObjectForTests>>#methodWithTempsAssignments" + 8 timesRepeat: [ dastInterpreter stepOver ]. + 5 timesRepeat: [ dastInterpreter stepInto ]. + dastContext := dastInterpreter currentContext + "Put here a common initialization logic for tests" ] @@ -25,10 +42,77 @@ DASTContextSwitchTests >> tearDown [ ] +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchKeepsBindings [ + "we step after the node `b := 2 ` of StDebuggerObjectForTests>>#methodWithTempsAssignments has been executed" + + 6 timesRepeat: [ dastInterpreter stepInto ]. + self assert: (dastContext findLocalVariable: #a) value equals: 40. + self assert: (dastContext findLocalVariable: #b) value equals: 2. + + context := dastContext asContext. + + self + assert: ((context lookupTempVar: #a) readInContext: context) + equals: 40. + self + assert: ((context lookupTempVar: #b) readInContext: context) + equals: 2 +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ + "we step after the node `b := 2 ` of StDebuggerObjectForTests>>#methodWithTempsAssignments has been executed" + + "The test fails because the AST of the compiled DoItMethod has a scope with nil indexes for each temp" + + | tempNames dastReceiver | + 6 timesRepeat: [ dastInterpreter stepInto ]. + + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + tempNames := dastContext tempNames. + tempNames do: [ :temp | + dastReceiver := (dastContext findLocalVariable: temp) value. + dastReceiver isBlock + ifFalse: [ + self + assert: ((context lookupTempVar: temp) readInContext: context) + identicalTo: dastReceiver ] + ifTrue: [ + self + assert: (dastContext findLocalVariable: temp) value + identicalTo: dastReceiver nodeAST evaluate ] ]. + context := context sender. + dastContext := dastContext sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchKeepsReceiver [ + + 6 timesRepeat: [ dastInterpreter stepInto ]. + + context := dastContext asContext. + self assert: context receiver identicalTo: dastContext receiver +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchKeepsReceiversRecursively [ + + 6 timesRepeat: [ dastInterpreter stepInto ]. + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + self assert: context receiver identicalTo: dastContext receiver. + context := context sender. + dastContext := dastContext sender ] +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchCurrentNodeIsLastExecutedNode [ - | dastContext node | + | node | 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -42,7 +126,7 @@ DASTContextSwitchTests >> testInterpreterSwitchCurrentNodeIsLastExecutedNode [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchEvaluateAfterSwitchCanFindBindingsOfObjectsDefinedOutsideOfClosuresInContextThatDoesNotHaveDASTEquivalent [ - | dastContext debuggerObjectForTest interpreter | + | debuggerObjectForTest interpreter | debuggerObjectForTest := StDebuggerObjectForTests new. context := [ debuggerObjectForTest methodWithTempsAssignments ] asContext. @@ -56,7 +140,6 @@ DASTContextSwitchTests >> testInterpreterSwitchEvaluateAfterSwitchCanFindBinding { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsBindings [ - | dastContext | 4 timesRepeat: [ context := context step ]. self assert: ((context lookupTempVar: #a) readInContext: context) @@ -74,7 +157,7 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsBindings [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsBindingsRecursively [ - | dastContext tempNames | + | tempNames | 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. @@ -92,7 +175,6 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsBindingsRecursively [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiver [ - | dastContext | 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -103,7 +185,6 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiver [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ - | dastContext | self skip. 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -118,7 +199,6 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsValueStack [ - | dastContext | 6 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -135,7 +215,6 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsValueStack [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsValueStackRecursively [ - | dastContext | 6 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -156,7 +235,7 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsValueStackRecursively [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchMessageNodeIsLastSourceNodeExecutedFromSender [ - | dastContext node | + | node | 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -171,7 +250,6 @@ DASTContextSwitchTests >> testInterpreterSwitchMessageNodeIsLastSourceNodeExecut { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchPutsRootBeforeFirstInterestingContext [ - | dastContext | 4 timesRepeat: [ context step ]. dastContext := context asDASTContextInterpretedBy: @@ -195,7 +273,7 @@ DASTContextSwitchTests >> testInterpreterSwitchPutsRootBeforeFirstInterestingCon { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchReceiverRemainsUnchanged [ - | dastContext instVars oldInstVarValues newInstVarValues | + | instVars oldInstVarValues newInstVarValues | 4 timesRepeat: [ context := context step ]. instVars := context receiver class allInstVarNames. @@ -215,7 +293,7 @@ DASTContextSwitchTests >> testInterpreterSwitchReceiverRemainsUnchanged [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchStepIsCorrect [ - | dastContext pc node interpreter | + | pc node interpreter | 4 timesRepeat: [ context := context step ]. pc := context pc. @@ -243,7 +321,7 @@ DASTContextSwitchTests >> testInterpreterSwitchStepIsCorrect [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPC [ - | dastContext pc node | + | pc node | 4 timesRepeat: [ context := context step ]. pc := context pc. @@ -257,7 +335,7 @@ DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPC [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPCRecursively [ - | dastContext pcs node | + | pcs node | 4 timesRepeat: [ context := context step ]. pcs := context stack collect: [ :ctx | ctx pc ]. diff --git a/DebuggableASTInterpreter/DASTInterpreter.class.st b/DebuggableASTInterpreter/DASTInterpreter.class.st index 71de9c6..742c878 100644 --- a/DebuggableASTInterpreter/DASTInterpreter.class.st +++ b/DebuggableASTInterpreter/DASTInterpreter.class.st @@ -156,11 +156,23 @@ DASTInterpreter >> initializeWithProgram: aRBNode inContext: aDASTContext [ { #category : #initialization } DASTInterpreter >> initializeWithProgram: aRBNode withTemps: aCollection astCache: anIdentityDictionary [ - - astCache := anIdentityDictionary. - programCounter := 0. - currentContext := DASTContext newNoMethodContextWithProgram: aRBNode temps: aCollection evaluator: self evaluator + | compiledMethod doItMethodNode | + astCache := anIdentityDictionary. + programCounter := 0. + "aRBNode methodNode generateWithSource." + + compiledMethod := UndefinedObject compiler + noPattern: true; + compile: aRBNode methodNode source. + doItMethodNode := compiledMethod ast. + "(doItMethodNode + doSemanticAnalysis; + ir)" "generate". + currentContext := DASTContext + newNoMethodContextWithProgram: doItMethodNode body + temps: aCollection + evaluator: self evaluator ] { #category : #testing } diff --git a/DebuggableASTInterpreter/DASTNoMethod.class.st b/DebuggableASTInterpreter/DASTNoMethod.class.st index 634de8f..b5ee4da 100644 --- a/DebuggableASTInterpreter/DASTNoMethod.class.st +++ b/DebuggableASTInterpreter/DASTNoMethod.class.st @@ -14,5 +14,6 @@ DASTNoMethod >> isNoMethod [ DASTNoMethod >> nodeAST: aRBNode [ super nodeAST: aRBNode. - nodeAST doSemanticAnalysis + "Not necessary anymore as the interpreter compiles DoIts properly" + "nodeAST doSemanticAnalysis" ] From 87135100108582cbe1b3e322f742eb762b20a0b4 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 16 Feb 2023 10:55:11 +0100 Subject: [PATCH 28/43] block context receiver fix, DAST->bc --- DebuggableASTInterpreter/DASTContext.class.st | 4 +--- .../DASTContextSwitchTests.class.st | 17 ++++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 1d0a252..dfc98aa 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -633,9 +633,7 @@ DASTContext >> privAsContext [ ^ (Context newForMethod: self method) setSender: self sender asContext - receiver: (self receiver isBlock - ifFalse: [ self receiver ] - ifTrue: [ self receiver nodeAST evaluate ]) + receiver: self receiver method: self methodOrBlock compiledCode closure: self methodOrBlock closure startpc: self methodOrBlock compiledCode initialPC diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index a0a2d3e..54d70ab 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -38,8 +38,11 @@ DASTContextSwitchTests >> setUp [ { #category : #running } DASTContextSwitchTests >> tearDown [ "context terminate." + super tearDown. - + context := nil. + dastContext := nil. + dastInterpreter := nil ] { #category : #tests } @@ -66,7 +69,7 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ "The test fails because the AST of the compiled DoItMethod has a scope with nil indexes for each temp" - | tempNames dastReceiver | + | tempNames dastTemp | 6 timesRepeat: [ dastInterpreter stepInto ]. context := dastContext asContext. @@ -74,16 +77,16 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ [ dastContext isRoot ] whileFalse: [ tempNames := dastContext tempNames. tempNames do: [ :temp | - dastReceiver := (dastContext findLocalVariable: temp) value. - dastReceiver isBlock + dastTemp := (dastContext findLocalVariable: temp) value. + dastTemp isBlock ifFalse: [ self assert: ((context lookupTempVar: temp) readInContext: context) - identicalTo: dastReceiver ] + identicalTo: dastTemp ] ifTrue: [ self - assert: (dastContext findLocalVariable: temp) value - identicalTo: dastReceiver nodeAST evaluate ] ]. + assert: ((context lookupTempVar: temp) readInContext: context) + identicalTo: dastTemp closure ] ]. context := context sender. dastContext := dastContext sender ] ] From e1402e885c2518657e54a4e849d19e37b2e0c1f4 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 16 Feb 2023 16:29:54 +0100 Subject: [PATCH 29/43] fixing number of steps in DAST->bc tests + adding other DAST->bc tests (stack unchanged, receiver state unchanged, correct stepping, termination of process, running process with new context...) The test that checks bindings recursively and stack recursively are yellow for now --- DebuggableASTInterpreter/DASTBlock.class.st | 7 +- .../DASTBlockContext.class.st | 7 +- .../DASTContextSwitchTests.class.st | 194 +++++++++++++++++- 3 files changed, 199 insertions(+), 9 deletions(-) diff --git a/DebuggableASTInterpreter/DASTBlock.class.st b/DebuggableASTInterpreter/DASTBlock.class.st index 70f02b2..78c3a01 100644 --- a/DebuggableASTInterpreter/DASTBlock.class.st +++ b/DebuggableASTInterpreter/DASTBlock.class.st @@ -32,7 +32,12 @@ DASTBlock >> bodyOffset [ { #category : #accessing } DASTBlock >> closure [ - ^ self nodeAST evaluate + ^ "closure ifNil: [ "self nodeAST evaluate + "closure := Smalltalk compiler + source: self sourceCode; + context: self outerContext; + receiver: self outerContext receiver; + evaluate ]" ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTBlockContext.class.st b/DebuggableASTInterpreter/DASTBlockContext.class.st index 4363dc1..132c329 100644 --- a/DebuggableASTInterpreter/DASTBlockContext.class.st +++ b/DebuggableASTInterpreter/DASTBlockContext.class.st @@ -15,9 +15,10 @@ DASTBlockContext >> allInstVars [ { #category : #'accessing - private' } DASTBlockContext >> allTemps [ - ^ self variablesDict associations , - closure outerContext allTemps , - sender allTemps + + self flag: 'I really think that this statement duplicates temps'. + ^ self variablesDict associations , closure outerContext allTemps + , sender allTemps ] { #category : #testing } diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 54d70ab..a10d429 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -45,11 +45,70 @@ DASTContextSwitchTests >> tearDown [ dastInterpreter := nil ] +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchBottomContextMapsToRootAndTerminatesProcess [ + + | process | + 4 timesRepeat: [ dastInterpreter stepInto ]. + + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + dastContext := dastContext sender. + context := context sender ]. + + self assert: context sender isNil. + + process := Process + forContext: context + priority: Processor userInterruptPriority. + + self deny: process isTerminated. + self shouldnt: [ process resume ] raise: BlockCannotReturn. + self assert: process isTerminated +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchCurrentPcIsFirstPcOfTopNodeOnStack [ + + | node | + 4 timesRepeat: [ dastInterpreter stepInto ]. + + context := dastContext asContext. + + node := dastContext nodes top. + + self + assert: context pc + identicalTo: + (dastContext methodOrBlock nodeAST firstPcForNode: node) +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchCurrentPcIsFirstPcOfTopNodeOnStackRecursively [ + + | node | + 4 timesRepeat: [ dastInterpreter stepInto ]. + node := dastContext nodes top. + + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + node := dastContext nodes top. + + self + assert: context pc + identicalTo: + (dastContext methodOrBlock nodeAST firstPcForNode: node). + context := context sender. + dastContext := dastContext sender ] +] + { #category : #tests } DASTContextSwitchTests >> testBytecodeSwitchKeepsBindings [ "we step after the node `b := 2 ` of StDebuggerObjectForTests>>#methodWithTempsAssignments has been executed" - 6 timesRepeat: [ dastInterpreter stepInto ]. + 4 timesRepeat: [ dastInterpreter stepInto ]. self assert: (dastContext findLocalVariable: #a) value equals: 40. self assert: (dastContext findLocalVariable: #b) value equals: 2. @@ -67,10 +126,10 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindings [ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ "we step after the node `b := 2 ` of StDebuggerObjectForTests>>#methodWithTempsAssignments has been executed" - "The test fails because the AST of the compiled DoItMethod has a scope with nil indexes for each temp" + "The test fails because I don't manage to get a compiled block (and thus a block closure) that contains the bindings of variables from the outer context. I suppose there are something to do with the compiler. I tried to compile the block in the DAST outer context but it doesn't work (DNU). I don't know if defining these messages would solve the problem" | tempNames dastTemp | - 6 timesRepeat: [ dastInterpreter stepInto ]. + 4 timesRepeat: [ dastInterpreter stepInto ]. context := dastContext asContext. @@ -94,7 +153,7 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ { #category : #tests } DASTContextSwitchTests >> testBytecodeSwitchKeepsReceiver [ - 6 timesRepeat: [ dastInterpreter stepInto ]. + 4 timesRepeat: [ dastInterpreter stepInto ]. context := dastContext asContext. self assert: context receiver identicalTo: dastContext receiver @@ -103,7 +162,7 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsReceiver [ { #category : #tests } DASTContextSwitchTests >> testBytecodeSwitchKeepsReceiversRecursively [ - 6 timesRepeat: [ dastInterpreter stepInto ]. + 4 timesRepeat: [ dastInterpreter stepInto ]. context := dastContext asContext. [ dastContext isRoot ] whileFalse: [ @@ -112,6 +171,131 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsReceiversRecursively [ dastContext := dastContext sender ] ] +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchKeepsValueStack [ + + | stack | + 4 timesRepeat: [ dastInterpreter stepInto ]. + stack := dastContext stack. + + context := dastContext asContext. + + self + assert: context stackPtr + equals: dastContext allTemps size + stack size. + self assert: dastContext allTemps size equals: context numTemps. + (Interval from: 1 to: stack size) do: [ :index | + self + assert: (dastContext stack at: index) + identicalTo: (context at: context numTemps + index) ]. + (Interval from: 1 to: dastContext allTemps size) do: [ :index | + self + assert: (context at: index) + identicalTo: (dastContext allTemps at: index) value ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchKeepsValueStackRecursively [ + + | stack | + "The test fails because a block context relies on its variable dict to build the new context's stack, instead of allTemps. Maybe (Surely) that my approach of using allTemps is wrong but this block context needs at least a vector of temps from allTemps." + 4 timesRepeat: [ dastInterpreter stepInto ]. + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + stack := dastContext stack. + + self + assert: context stackPtr + equals: dastContext allTemps size + stack size. + self assert: dastContext allTemps size equals: context numTemps. + (Interval from: 1 to: stack size) do: [ :index | + self + assert: (dastContext stack at: index) + identicalTo: (context at: context numTemps + index) ]. + (Interval from: 1 to: dastContext allTemps size) do: [ :index | + self + assert: (context at: index) + identicalTo: (dastContext allTemps at: index) value ]. + dastContext := dastContext sender. + context := context sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchProcessResume [ + + | process | + context := dastContext asContext. + + process := Process + forContext: context + priority: Processor userInterruptPriority. + + [ dastContext isRoot ] whileFalse: [ + context := context sender. + dastContext := dastContext sender ]. + + process completeTo: context. + + self assert: process suspendedContext top equals: 42. + + self deny: process isTerminated. + + self shouldnt: [ process resume ] raise: BlockCannotReturn. + + self assert: process isTerminated +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchReceiverRemainsUnchanged [ + + | instVars oldInstVarValues newInstVarValues | + 4 timesRepeat: [ dastInterpreter stepInto ]. + + instVars := dastContext receiver class allInstVarNames. + oldInstVarValues := instVars collect: [ :inst | + dastContext receiver instVarNamed: inst ]. + + context := dastContext asContext. + + newInstVarValues := instVars collect: [ :inst | + context receiver instVarNamed: inst ]. + + oldInstVarValues withIndexDo: [ :each :index | + self assert: each identicalTo: (newInstVarValues at: index) ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchStepIsCorrect [ + + | pc node process | + 4 timesRepeat: [ dastInterpreter stepInto ]. + + node := dastContext nodes top. + context := dastContext asContext. + pc := dastContext methodOrBlock nodeAST firstPcForNode: node. + + process := Process + forContext: context + priority: Processor userInterruptPriority. + + self assert: process suspendedContext pc identicalTo: pc. + self deny: context isDead. + self assert: process suspendedContext identicalTo: context. + + "one step to evaluate a (40), one step to evaluate b (2) and one step to compute the sum" + process + step; + step; + step. + + self assert: process suspendedContext top equals: 42. + self assert: (process suspendedContext compiledCode sourceNodeForPC: + process suspendedContext pc) isReturn. + self deny: process suspendedContext isDead. + self assert: process suspendedContext identicalTo: context +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchCurrentNodeIsLastExecutedNode [ From 2cdc45c9fe707865336f9d245d0cfe409d0a8d32 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Fri, 17 Feb 2023 10:16:07 +0100 Subject: [PATCH 30/43] fixing bc->DAST receiver recursively test --- DebuggableASTInterpreter/Context.extension.st | 14 +++++++++++--- .../DASTContextSwitchTests.class.st | 1 - 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index 05eeacf..c3d6a49 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -4,7 +4,6 @@ Extension { #name : #Context } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ | dastCtx bindings aimedNode currentNode dastSender | - bindings := Dictionary new. self tempNames do: [ :tempName | bindings at: tempName put: (self tempNamed: tempName) ]. @@ -23,7 +22,12 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ (closureOrNil ifNil: [ receiver ] ifNotNil: [ DASTBlock new nodeAST: closureOrNil compiledBlock ast; - outerContext: dastSender; + outerContext: (dastSender isRoot + ifFalse: [ dastSender ] + ifTrue: [ + self flag: + 'Maybe it is weird that the outer context is a context but I haven''t found a better solution yet.'. + self outerContext ]); yourself ]) messageNode: (dastSender isRoot ifTrue: [ @@ -34,7 +38,11 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ evaluator: aDASTInterpreter evaluator ]. dastCtx temps: bindings associations. - aimedNode := self compiledCode sourceNodeForPC: self pc. + self pc + ifNil: [ + aimedNode := dastCtx nodes first. + dastCtx isDead: true ] + ifNotNil: [ aimedNode := self compiledCode sourceNodeForPC: self pc ]. [ aimedNode == dastCtx nodes top ] whileFalse: [ dastCtx executedNodes push: (currentNode := dastCtx nodes pop) ]. dastCtx currentNode: currentNode. diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index a10d429..5df1ae1 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -372,7 +372,6 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiver [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ - self skip. 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: DASTInterpreter new. From 03fd2e8b48b9a9bcb514b4f534ac3cd87c7bb807 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Mon, 20 Feb 2023 14:25:50 +0100 Subject: [PATCH 31/43] better temp gestion in DASTBlockContext + better creation of FullBlockClosure in DASTBlock Vectors of temps need to be handled for DAST -> bc switch mapping indexes to right temps --- .../DASTBlockContext.extension.st | 14 ++++++++++++++ DebuggableASTInterpreter/DASTBlock.class.st | 10 +++++++--- .../DASTBlockContext.class.st | 8 +++++++- DebuggableASTInterpreter/DASTContext.class.st | 17 ++++++++++++++--- .../DASTContextSwitchTests.class.st | 4 +++- .../DASTMethodContext.class.st | 6 ++++++ 6 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 DebuggableASTDebugger/DASTBlockContext.extension.st diff --git a/DebuggableASTDebugger/DASTBlockContext.extension.st b/DebuggableASTDebugger/DASTBlockContext.extension.st new file mode 100644 index 0000000..23c321d --- /dev/null +++ b/DebuggableASTDebugger/DASTBlockContext.extension.st @@ -0,0 +1,14 @@ +Extension { #name : #DASTBlockContext } + +{ #category : #'*DebuggableASTDebugger' } +DASTBlockContext >> tempNamed: aTempVarName [ + + ^ [ super tempNamed: aTempVarName ] + on: KeyNotFound + do: ([ + self sender + ifNotNil: [ self sender tempNamed: aTempVarName ] + ifNil: [ closure outerContext tempNamed: aTempVarName ] ] + on: KeyNotFound + do: [ closure outerContext tempNamed: aTempVarName ]) +] diff --git a/DebuggableASTInterpreter/DASTBlock.class.st b/DebuggableASTInterpreter/DASTBlock.class.st index 78c3a01..083af15 100644 --- a/DebuggableASTInterpreter/DASTBlock.class.st +++ b/DebuggableASTInterpreter/DASTBlock.class.st @@ -32,8 +32,12 @@ DASTBlock >> bodyOffset [ { #category : #accessing } DASTBlock >> closure [ - ^ "closure ifNil: [ "self nodeAST evaluate - "closure := Smalltalk compiler + ^ FullBlockClosure new + compiledBlock: self nodeAST ir compiledMethod; + receiver: self outerContext receiver; + numArgs: self nodeAST numArgs; + outerContext: self outerContext "closure ifNil: [ ""self nodeAST evaluate" + "closure := Smalltalk compiler source: self sourceCode; context: self outerContext; receiver: self outerContext receiver; @@ -43,7 +47,7 @@ DASTBlock >> closure [ { #category : #accessing } DASTBlock >> compiledCode [ - ^ self closure compiledBlock + ^ self nodeAST ir compiledMethod ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTBlockContext.class.st b/DebuggableASTInterpreter/DASTBlockContext.class.st index 132c329..090ffa7 100644 --- a/DebuggableASTInterpreter/DASTBlockContext.class.st +++ b/DebuggableASTInterpreter/DASTBlockContext.class.st @@ -17,7 +17,7 @@ DASTBlockContext >> allInstVars [ DASTBlockContext >> allTemps [ self flag: 'I really think that this statement duplicates temps'. - ^ self variablesDict associations , closure outerContext allTemps + ^ self variablesDict associations ", closure outerContext allTemps" , sender allTemps ] @@ -64,6 +64,12 @@ DASTBlockContext >> initializeContext [ ] +{ #category : #helpers } +DASTBlockContext >> ir [ + + ^ self methodOrBlock nodeAST ir +] + { #category : #initialization } DASTBlockContext >> isBlockContext [ ^ true diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index dfc98aa..ab0575a 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -466,6 +466,12 @@ DASTContext >> initialize [ tempVarIndex := 0 ] +{ #category : #helpers } +DASTContext >> ir [ + + self subclassResponsibility +] + { #category : #testing } DASTContext >> isBlockContext [ @@ -643,13 +649,18 @@ DASTContext >> privAsContext [ DASTContext >> privCopyStackInContext: newContext [ newContext stackp: 0. - (self variablesDict associations collect: [ :each | + (self ir tempMap associations sorted: [ :assoc1 :assoc2 | + assoc1 value <= assoc2 value ]) do: [ :each | + newContext push: + (self allTemps detect: [ :tempAssoc | tempAssoc key == each key ]) + value ]. + "(self variablesDict associations collect: [ :each | | value | value := each value. value isBlock ifFalse: [ value ] - ifTrue: [ value nodeAST evaluate ] ]) , self stack do: [ :each | - newContext push: each ] + ifTrue: [ value nodeAST evaluate ] ]) ," + self stack do: [ :each | newContext push: each ] ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 5df1ae1..ecf58dd 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -216,7 +216,9 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsValueStackRecursively [ (Interval from: 1 to: dastContext allTemps size) do: [ :index | self assert: (context at: index) - identicalTo: (dastContext allTemps at: index) value ]. + identicalTo: + (dastContext tempNamed: (dastContext allTemps at: index) key) + value ]. dastContext := dastContext sender. context := context sender ] ] diff --git a/DebuggableASTInterpreter/DASTMethodContext.class.st b/DebuggableASTInterpreter/DASTMethodContext.class.st index 56751d0..7f1f9a1 100644 --- a/DebuggableASTInterpreter/DASTMethodContext.class.st +++ b/DebuggableASTInterpreter/DASTMethodContext.class.st @@ -90,6 +90,12 @@ DASTMethodContext >> initializeContext [ ] +{ #category : #helpers } +DASTMethodContext >> ir [ + + ^ self methodOrBlock nodeAST compiledMethod ir +] + { #category : #initialization } DASTMethodContext >> isBlockContext [ ^ false From 818fc050bec94968c689288fda479c229e633588 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 21 Feb 2023 09:39:58 +0100 Subject: [PATCH 32/43] mapping DASTBlock to their pharo outer context. All tests are green --- DebuggableASTDebugger/DASTBlock.extension.st | 7 +++ .../DASTBlockContext.extension.st | 13 ++--- DebuggableASTDebugger/Object.extension.st | 7 +++ DebuggableASTInterpreter/DASTBlock.class.st | 17 ++++++- DebuggableASTInterpreter/DASTContext.class.st | 18 +++++-- .../DASTContextSwitchTests.class.st | 50 +++++++++++++------ 6 files changed, 83 insertions(+), 29 deletions(-) create mode 100644 DebuggableASTDebugger/DASTBlock.extension.st create mode 100644 DebuggableASTDebugger/Object.extension.st diff --git a/DebuggableASTDebugger/DASTBlock.extension.st b/DebuggableASTDebugger/DASTBlock.extension.st new file mode 100644 index 0000000..3528636 --- /dev/null +++ b/DebuggableASTDebugger/DASTBlock.extension.st @@ -0,0 +1,7 @@ +Extension { #name : #DASTBlock } + +{ #category : #'*DebuggableASTDebugger' } +DASTBlock >> dastToBcValue [ + + ^ self closure +] diff --git a/DebuggableASTDebugger/DASTBlockContext.extension.st b/DebuggableASTDebugger/DASTBlockContext.extension.st index 23c321d..653411a 100644 --- a/DebuggableASTDebugger/DASTBlockContext.extension.st +++ b/DebuggableASTDebugger/DASTBlockContext.extension.st @@ -5,10 +5,11 @@ DASTBlockContext >> tempNamed: aTempVarName [ ^ [ super tempNamed: aTempVarName ] on: KeyNotFound - do: ([ - self sender - ifNotNil: [ self sender tempNamed: aTempVarName ] - ifNil: [ closure outerContext tempNamed: aTempVarName ] ] - on: KeyNotFound - do: [ closure outerContext tempNamed: aTempVarName ]) + do: [ + [ + self sender + ifNotNil: [ self sender tempNamed: aTempVarName ] + ifNil: [ closure outerContext tempNamed: aTempVarName ] ] + on: KeyNotFound + do: [ closure outerContext tempNamed: aTempVarName ] ] ] diff --git a/DebuggableASTDebugger/Object.extension.st b/DebuggableASTDebugger/Object.extension.st new file mode 100644 index 0000000..6180434 --- /dev/null +++ b/DebuggableASTDebugger/Object.extension.st @@ -0,0 +1,7 @@ +Extension { #name : #Object } + +{ #category : #'*DebuggableASTDebugger' } +Object >> dastToBcValue [ + + ^ self +] diff --git a/DebuggableASTInterpreter/DASTBlock.class.st b/DebuggableASTInterpreter/DASTBlock.class.st index 083af15..c909baf 100644 --- a/DebuggableASTInterpreter/DASTBlock.class.st +++ b/DebuggableASTInterpreter/DASTBlock.class.st @@ -2,7 +2,8 @@ Class { #name : #DASTBlock, #superclass : #DASTClosure, #instVars : [ - 'interval' + 'interval', + 'pharoOuterContext' ], #category : #'DebuggableASTInterpreter-Closures' } @@ -36,7 +37,7 @@ DASTBlock >> closure [ compiledBlock: self nodeAST ir compiledMethod; receiver: self outerContext receiver; numArgs: self nodeAST numArgs; - outerContext: self outerContext "closure ifNil: [ ""self nodeAST evaluate" + outerContext: self pharoOuterContext "closure ifNil: [ ""self nodeAST evaluate" "closure := Smalltalk compiler source: self sourceCode; context: self outerContext; @@ -140,6 +141,18 @@ DASTBlock >> outerContext: aDASTContext [ "self initializeInterval" ] +{ #category : #accessing } +DASTBlock >> pharoOuterContext [ + + ^ pharoOuterContext +] + +{ #category : #accessing } +DASTBlock >> pharoOuterContext: anObject [ + + pharoOuterContext := anObject +] + { #category : #accessing } DASTBlock >> primitive [ "A block always has code inside, and cannot have a primitive declaration " diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index ab0575a..44207ac 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -456,12 +456,13 @@ DASTContext >> hasSender: context [ { #category : #initialization } DASTContext >> initialize [ + super initialize. stack := DASTStack new. executedNodes := DASTStack new. nodes := DASTStack new. currentNode := nil. - variablesDict := Dictionary new. + variablesDict := OrderedDictionary new. tempVarsNamesIndexes := Dictionary new. tempVarIndex := 0 ] @@ -651,16 +652,23 @@ DASTContext >> privCopyStackInContext: newContext [ newContext stackp: 0. (self ir tempMap associations sorted: [ :assoc1 :assoc2 | assoc1 value <= assoc2 value ]) do: [ :each | - newContext push: - (self allTemps detect: [ :tempAssoc | tempAssoc key == each key ]) - value ]. + | value | + value := (self allTemps detect: [ :tempAssoc | + tempAssoc key == each key ]) value. + value isBlock ifTrue: [ + value pharoOuterContext ifNil: [ + value pharoOuterContext: newContext ] ]. + newContext push: value dastToBcValue ]. "(self variablesDict associations collect: [ :each | | value | value := each value. value isBlock ifFalse: [ value ] ifTrue: [ value nodeAST evaluate ] ]) ," - self stack do: [ :each | newContext push: each ] + self stack do: [ :each | + each isBlock ifTrue: [ + each pharoOuterContext ifNil: [ each pharoOuterContext: newContext ] ]. + newContext push: each dastToBcValue ] ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index ecf58dd..6a23fc6 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -9,6 +9,18 @@ Class { #category : #'DebuggableASTInterpreter-Tests' } +{ #category : #tests } +DASTContextSwitchTests >> assertFullBlock: fullBlock equalsDASTBlock: dastBlock [ + + | closure | + closure := dastBlock closure. + ^ self + assert: fullBlock compiledBlock + identicalTo: closure compiledBlock; + assert: fullBlock outerContext identicalTo: closure outerContext; + assert: fullBlock receiver identicalTo: closure receiver +] + { #category : #running } DASTContextSwitchTests >> setUp [ @@ -134,7 +146,7 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ context := dastContext asContext. [ dastContext isRoot ] whileFalse: [ - tempNames := dastContext tempNames. + tempNames := dastContext allTemps collect: [ :each | each key ]. tempNames do: [ :temp | dastTemp := (dastContext findLocalVariable: temp) value. dastTemp isBlock @@ -143,9 +155,10 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ assert: ((context lookupTempVar: temp) readInContext: context) identicalTo: dastTemp ] ifTrue: [ - self - assert: ((context lookupTempVar: temp) readInContext: context) - identicalTo: dastTemp closure ] ]. + | contextTemp closure | + contextTemp := (context lookupTempVar: temp) readInContext: + context. + self assertFullBlock: contextTemp equalsDASTBlock: dastTemp ] ]. context := context sender. dastContext := dastContext sender ] ] @@ -197,7 +210,7 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsValueStack [ { #category : #tests } DASTContextSwitchTests >> testBytecodeSwitchKeepsValueStackRecursively [ - | stack | + | stack dastElement contextElement | "The test fails because a block context relies on its variable dict to build the new context's stack, instead of allTemps. Maybe (Surely) that my approach of using allTemps is wrong but this block context needs at least a vector of temps from allTemps." 4 timesRepeat: [ dastInterpreter stepInto ]. context := dastContext asContext. @@ -207,18 +220,23 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsValueStackRecursively [ self assert: context stackPtr - equals: dastContext allTemps size + stack size. - self assert: dastContext allTemps size equals: context numTemps. + equals: dastContext ir tempMap size + stack size. + self assert: dastContext ir tempMap size equals: context numTemps. (Interval from: 1 to: stack size) do: [ :index | - self - assert: (dastContext stack at: index) - identicalTo: (context at: context numTemps + index) ]. - (Interval from: 1 to: dastContext allTemps size) do: [ :index | - self - assert: (context at: index) - identicalTo: - (dastContext tempNamed: (dastContext allTemps at: index) key) - value ]. + dastElement := dastContext stack at: index. + contextElement := context at: context numTemps + index. + dastElement isBlock + ifFalse: [ self assert: contextElement identicalTo: dastElement ] + ifTrue: [ + self assertFullBlock: contextElement equalsDASTBlock: dastElement ] ]. + (Interval from: 1 to: dastContext ir tempMap size) do: [ :index | + contextElement := context at: index. + dastElement := (dastContext tempNamed: + (dastContext allTemps at: index) key) value. + dastElement isBlock + ifFalse: [ self assert: contextElement identicalTo: dastElement ] + ifTrue: [ + self assertFullBlock: contextElement equalsDASTBlock: dastElement ] ]. dastContext := dastContext sender. context := context sender ] ] From 0ca9f172ae5fb6cab25020347e6e83195c1c302d Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:21:18 +0100 Subject: [PATCH 33/43] handling DASTBreakpoints --- DebuggableASTDebugger/DASTDebugger.class.st | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st index b14d5ff..a567c48 100644 --- a/DebuggableASTDebugger/DASTDebugger.class.st +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -19,12 +19,27 @@ DASTDebugger class >> debugSession: aDebugSession [ | dast | dast := self basicNew. dast simulatorSession: aDebugSession. + aDebugSession stepInto. + aDebugSession stepInto. dast interpreter: (DASTInterpreter startFromContext: aDebugSession interruptedContext). dast initialize. dast open ] +{ #category : #accessing } +DASTDebugger class >> defaultDebuggerRank [ + + ^ 10 +] + +{ #category : #debugging } +DASTDebugger class >> handlesContext: aContext [ + |handlesContext| + handlesContext := aContext receiver class = DASTBreakpoint. + ^handlesContext +] + { #category : #initialization } DASTDebugger >> buildToolbar [ From 1e652cef8eb4ec49f5d64ccb2a666caeff913646 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:22:02 +0100 Subject: [PATCH 34/43] adding DASTBreakpoint --- DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st | 5 +++++ DebuggableASTDebuggerExperiment/package.st | 1 + 2 files changed, 6 insertions(+) create mode 100644 DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st create mode 100644 DebuggableASTDebuggerExperiment/package.st diff --git a/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st b/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st new file mode 100644 index 0000000..c6b6144 --- /dev/null +++ b/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st @@ -0,0 +1,5 @@ +Class { + #name : #DASTBreakpoint, + #superclass : #Breakpoint, + #category : #DebuggableASTDebuggerExperiment +} diff --git a/DebuggableASTDebuggerExperiment/package.st b/DebuggableASTDebuggerExperiment/package.st new file mode 100644 index 0000000..7184993 --- /dev/null +++ b/DebuggableASTDebuggerExperiment/package.st @@ -0,0 +1 @@ +Package { #name : #DebuggableASTDebuggerExperiment } From 2971bc67667b1b8620a3199c8296568556d769e5 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:22:43 +0100 Subject: [PATCH 35/43] code example DASTBreakpoint --- DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st b/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st index c6b6144..8c6bf64 100644 --- a/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st +++ b/DebuggableASTDebuggerExperiment/DASTBreakpoint.class.st @@ -1,3 +1,10 @@ +" +1/0. +bp := +DASTBreakpoint new node: (StDebuggerObjectForTests>>#instVar) ast. +bp install. +StDebuggerObjectForTests new instVar +" Class { #name : #DASTBreakpoint, #superclass : #Breakpoint, From 749f039a30b2e73964bcd45d3c9d709f7f4b0e9b Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:36:03 +0100 Subject: [PATCH 36/43] Adding possibility to add DAST breakpoints in Calypso --- .../ClyAddDASTBreakpointCommand.class.st | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 DebuggableASTDebuggerExperiment/ClyAddDASTBreakpointCommand.class.st diff --git a/DebuggableASTDebuggerExperiment/ClyAddDASTBreakpointCommand.class.st b/DebuggableASTDebuggerExperiment/ClyAddDASTBreakpointCommand.class.st new file mode 100644 index 0000000..3c02bf9 --- /dev/null +++ b/DebuggableASTDebuggerExperiment/ClyAddDASTBreakpointCommand.class.st @@ -0,0 +1,36 @@ +Class { + #name : #ClyAddDASTBreakpointCommand, + #superclass : #ClyAddStaticBreakpointCommand, + #category : #DebuggableASTDebuggerExperiment +} + +{ #category : #testing } +ClyAddDASTBreakpointCommand class >> canBeExecutedInContext: aBrowserContext [ + + ^ (super canBeExecutedInContext: aBrowserContext) and: [ + aBrowserContext isSelectedItemHasBreakpoint not ] +] + +{ #category : #activation } +ClyAddDASTBreakpointCommand class >> contextMenuOrder [ + + ^1 +] + +{ #category : #testing } +ClyAddDASTBreakpointCommand class >> isAbstract [ + ^self = ClyAddBreakpointCommand +] + +{ #category : #accessing } +ClyAddDASTBreakpointCommand >> defaultMenuItemName [ + ^'DAST breakpoint' +] + +{ #category : #execution } +ClyAddDASTBreakpointCommand >> execute [ + + | breakpoint | + breakpoint := DASTBreakpoint new node: sourceNode. + breakpoint install +] From 8c9af491ec39c3840536a417f543a4fe62f307b6 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Tue, 21 Feb 2023 15:46:17 +0100 Subject: [PATCH 37/43] dast->bc switch with vector of temps --- DebuggableASTInterpreter/DASTContext.class.st | 46 +++- .../DASTContextSwitchTests.class.st | 216 +++++++++++++++++- 2 files changed, 250 insertions(+), 12 deletions(-) diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index 44207ac..e3a359f 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -157,6 +157,17 @@ DASTContext >> at: aByteSymbol put: anObject [ ] +{ #category : #'as yet unclassified' } +DASTContext >> bcValueForAnObject: anObject forContext: newContext [ + + | bcValue | + anObject isBlock ifTrue: [ + anObject pharoOuterContext ifNil: [ + anObject pharoOuterContext: newContext ] ]. + bcValue := anObject dastToBcValue. + ^ bcValue +] + { #category : #testing } DASTContext >> canExecute [ ^ self nodes isNotEmpty and: [ self unhandledException isNil ] @@ -653,12 +664,32 @@ DASTContext >> privCopyStackInContext: newContext [ (self ir tempMap associations sorted: [ :assoc1 :assoc2 | assoc1 value <= assoc2 value ]) do: [ :each | | value | + [ value := (self allTemps detect: [ :tempAssoc | - tempAssoc key == each key ]) value. - value isBlock ifTrue: [ - value pharoOuterContext ifNil: [ - value pharoOuterContext: newContext ] ]. - newContext push: value dastToBcValue ]. + tempAssoc key == each key ]) value ] + on: NotFound + do: [ "newContext sender or newContext outerContext" + [ value := newContext sender tempNamed: each key ] + on: Error + do: [ + | scope tempVector index | + scope := self methodOrBlock nodeAST scope. + self + assert: scope tempVector isEmpty not + description: 'Temp named ' , each key , ' is missing'. + tempVector := scope tempVector. + value := Array new: tempVector size. + index := 1. + tempVector keysDo: [ :key | + value + at: index + put: + (self + bcValueForAnObject: (self tempNamed: key) + forContext: newContext). + index := index + 1 ] ] ]. + newContext push: + (self bcValueForAnObject: value forContext: newContext) ]. "(self variablesDict associations collect: [ :each | | value | value := each value. @@ -666,9 +697,8 @@ DASTContext >> privCopyStackInContext: newContext [ ifFalse: [ value ] ifTrue: [ value nodeAST evaluate ] ]) ," self stack do: [ :each | - each isBlock ifTrue: [ - each pharoOuterContext ifNil: [ each pharoOuterContext: newContext ] ]. - newContext push: each dastToBcValue ] + newContext push: + (self bcValueForAnObject: each forContext: newContext) ] ] { #category : #accessing } diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 6a23fc6..0715da6 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -9,10 +9,12 @@ Class { #category : #'DebuggableASTInterpreter-Tests' } -{ #category : #tests } +{ #category : #'tests - helper' } DASTContextSwitchTests >> assertFullBlock: fullBlock equalsDASTBlock: dastBlock [ | closure | + self assert: fullBlock isClosure. + self assert: dastBlock isBlock. closure := dastBlock closure. ^ self assert: fullBlock compiledBlock @@ -21,6 +23,32 @@ DASTContextSwitchTests >> assertFullBlock: fullBlock equalsDASTBlock: dastBlock assert: fullBlock receiver identicalTo: closure receiver ] +{ #category : #'tests - helper' } +DASTContextSwitchTests >> bcStepUntil: aBlock [ + + aBlock whileTrue: [ context := context step ] +] + +{ #category : #'tests - helper' } +DASTContextSwitchTests >> dastStepUntil: aBlock [ + + aBlock whileTrue: [ dastInterpreter stepInto ]. + dastContext := dastInterpreter currentContext +] + +{ #category : #'tests - helper' } +DASTContextSwitchTests >> interpreterOnMethodWithTempVector [ + + dastInterpreter initializeWithProgram: + (RBParser parseExpression: '| debuggerObjectForTest block a b | + debuggerObjectForTest := StDebuggerObjectForTests new. + a := 0. + block := [ | c | debuggerObjectForTest methodWithTempsAssignments. 1=2 ifTrue: [ block value ]. a := a + 1. b:=0. c:=0 . [ a:= a + 2. c:=c+4. b:=b+3 ] value ]. + ^ block value + b + a'). + + dastContext := dastInterpreter currentContext +] + { #category : #running } DASTContextSwitchTests >> setUp [ @@ -43,8 +71,6 @@ DASTContextSwitchTests >> setUp [ 8 timesRepeat: [ dastInterpreter stepOver ]. 5 timesRepeat: [ dastInterpreter stepInto ]. dastContext := dastInterpreter currentContext - - "Put here a common initialization logic for tests" ] { #category : #running } @@ -155,7 +181,7 @@ DASTContextSwitchTests >> testBytecodeSwitchKeepsBindingsRecursively [ assert: ((context lookupTempVar: temp) readInContext: context) identicalTo: dastTemp ] ifTrue: [ - | contextTemp closure | + | contextTemp | contextTemp := (context lookupTempVar: temp) readInContext: context. self assertFullBlock: contextTemp equalsDASTBlock: dastTemp ] ]. @@ -316,6 +342,188 @@ DASTContextSwitchTests >> testBytecodeSwitchStepIsCorrect [ self assert: process suspendedContext identicalTo: context ] +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchTempVectorBindings [ + + | dastTemp | + self + interpreterOnMethodWithTempVector; + dastStepUntil: [ + (dastInterpreter currentNode isMessage and: [ + dastInterpreter currentNode selector = #+ and: [ + dastInterpreter currentNode arguments last isLiteralNode and: [ + dastInterpreter currentNode arguments last value = 3 ] ] ]) + not ]. + dastContext := dastInterpreter currentContext. + + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + | tempNames | + tempNames := dastContext allTemps collect: [ :each | each key ]. + tempNames do: [ :temp | + dastTemp := (dastContext findLocalVariable: temp) value. + dastTemp isBlock + ifFalse: [ + self + assert: ((context lookupTempVar: temp) readInContext: context) + identicalTo: dastTemp ] + ifTrue: [ + | contextTemp | + contextTemp := (context lookupTempVar: temp) readInContext: + context. + self assertFullBlock: contextTemp equalsDASTBlock: dastTemp ] ]. + + dastContext := dastContext sender. + context := context sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchTempVectorCreation [ + + | astScope temp dastTemp vectorSize | + self + interpreterOnMethodWithTempVector; + dastStepUntil: [ + (dastInterpreter currentNode isMessage and: [ + dastInterpreter currentNode selector = #+ and: [ + dastInterpreter currentNode arguments last isLiteralNode and: [ + dastInterpreter currentNode arguments last value = 3 ] ] ]) + not ]. + dastContext := dastInterpreter currentContext. + + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ "ir := dastContext ir." + astScope := dastContext methodOrBlock nodeAST scope. + astScope tempVector ifNotEmpty: [ + temp := context tempNamed: astScope tempVectorName. + self assert: temp isArray. + vectorSize := 0. + astScope tempVector keysDo: [ :each | + vectorSize := vectorSize + 1. + dastTemp := dastContext tempNamed: each. + dastTemp isBlock + ifFalse: [ + self assert: (temp at: vectorSize) identicalTo: dastTemp ] + ifTrue: [ + self + assertFullBlock: (temp at: vectorSize) + equalsDASTBlock: dastTemp ] ] ]. + + dastContext := dastContext sender. + context := context sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchTempVectorProcessResume [ + + | process | + self + interpreterOnMethodWithTempVector; + dastStepUntil: [ + (dastInterpreter currentNode isMessage and: [ + dastInterpreter currentNode selector = #+ and: [ + dastInterpreter currentNode arguments last isLiteralNode and: [ + dastInterpreter currentNode arguments last value = 3 ] ] ]) + not ]. + dastContext := dastInterpreter currentContext. + + context := dastContext asContext. + + process := Process + forContext: context + priority: Processor userInterruptPriority. + + [ dastContext isRoot ] whileFalse: [ + context := context sender. + dastContext := dastContext sender ]. + + process completeTo: context. + + self assert: process suspendedContext top equals: 9. + + self deny: process isTerminated. + + self shouldnt: [ process resume ] raise: Exception. + + self assert: process isTerminated +] + +{ #category : #tests } +DASTContextSwitchTests >> testBytecodeSwitchTempVectorStack [ + + | stack dastElement contextElement | + self + interpreterOnMethodWithTempVector; + dastStepUntil: [ + (dastInterpreter currentNode isMessage and: [ + dastInterpreter currentNode selector = #+ and: [ + dastInterpreter currentNode arguments last isLiteralNode and: [ + dastInterpreter currentNode arguments last value = 3 ] ] ]) + not ]. + dastContext := dastInterpreter currentContext. + + context := dastContext asContext. + + [ dastContext isRoot ] whileFalse: [ + stack := dastContext stack. + + self + assert: context stackPtr + equals: dastContext ir tempMap size + stack size. + self assert: dastContext ir tempMap size equals: context numTemps. + (Interval from: 1 to: stack size) do: [ :index | + dastElement := dastContext stack at: index. + contextElement := context at: context numTemps + index. + dastElement isBlock + ifFalse: [ self assert: contextElement identicalTo: dastElement ] + ifTrue: [ + self assertFullBlock: contextElement equalsDASTBlock: dastElement ] ]. + (Interval from: 1 to: dastContext ir tempMap size) do: [ :index | + | variableNames | + variableNames := (dastContext ir tempMap associations sorted: [ + :assoc1 + :assoc2 | assoc1 value <= assoc2 value ]) + collect: [ :each | each key ]. + contextElement := context at: index. + (variableNames at: index) = (dastContext allTemps at: index) key + ifTrue: [ + dastElement := (dastContext tempNamed: + (dastContext allTemps at: index) key) value. + dastElement isBlock + ifFalse: [ self assert: contextElement identicalTo: dastElement ] + ifTrue: [ + self + assertFullBlock: contextElement + equalsDASTBlock: dastElement ] ] + ifFalse: [ + | astScope | + astScope := context compiledCode ast scope. + self assert: contextElement isArray. + astScope tempVectorName = (variableNames at: index) + ifTrue: [ + astScope tempVectorVarNames withIndexDo: [ :each :indexVector | + dastElement := (dastContext tempNamed: each) value. + dastElement isBlock + ifFalse: [ + self + assert: (contextElement at: indexVector) + identicalTo: dastElement ] + ifTrue: [ + self + assertFullBlock: (contextElement at: indexVector) + equalsDASTBlock: dastElement ] ] ] + ifFalse: [ + self + assert: contextElement + identicalTo: + (context sender tempNamed: (variableNames at: index)) ] ] ]. + + dastContext := dastContext sender. + context := context sender ] +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchCurrentNodeIsLastExecutedNode [ From 4a023d793fde7d6a321c4afcae9aa982cbab2b7a Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Wed, 22 Feb 2023 13:52:33 +0100 Subject: [PATCH 38/43] bc -> DAST temp vector switch --- .../BlockClosure.extension.st | 10 ++ DebuggableASTDebugger/Context.extension.st | 14 ++ DebuggableASTDebugger/Object.extension.st | 6 + DebuggableASTInterpreter/Context.extension.st | 72 +++++++-- DebuggableASTInterpreter/DASTContext.class.st | 7 + .../DASTContextSwitchTests.class.st | 146 ++++++++++++++++++ 6 files changed, 242 insertions(+), 13 deletions(-) create mode 100644 DebuggableASTDebugger/BlockClosure.extension.st create mode 100644 DebuggableASTDebugger/Context.extension.st diff --git a/DebuggableASTDebugger/BlockClosure.extension.st b/DebuggableASTDebugger/BlockClosure.extension.st new file mode 100644 index 0000000..325b3c2 --- /dev/null +++ b/DebuggableASTDebugger/BlockClosure.extension.st @@ -0,0 +1,10 @@ +Extension { #name : #BlockClosure } + +{ #category : #'*DebuggableASTDebugger' } +BlockClosure >> bcToDASTValue [ + + ^ DASTBlock new + initializeWith: self compiledBlock ast; + pharoOuterContext: self outerContext; + yourself +] diff --git a/DebuggableASTDebugger/Context.extension.st b/DebuggableASTDebugger/Context.extension.st new file mode 100644 index 0000000..2a81c7c --- /dev/null +++ b/DebuggableASTDebugger/Context.extension.st @@ -0,0 +1,14 @@ +Extension { #name : #Context } + +{ #category : #'*DebuggableASTDebugger' } +Context >> dastValueFor: anObject interpretedBy: aDASTInterpreter withClosureToBlockDictionary: closureToDASTBlock [ + + | value | + (closureToDASTBlock includesKey: anObject) ifTrue: [ + ^ closureToDASTBlock at: anObject ]. + value := anObject bcToDASTValue. + value isBlock ifTrue: [ + value outerContext: self. "aDASTInterpreter currentContext" + closureToDASTBlock at: anObject put: value ]. + ^ value +] diff --git a/DebuggableASTDebugger/Object.extension.st b/DebuggableASTDebugger/Object.extension.st index 6180434..1888a29 100644 --- a/DebuggableASTDebugger/Object.extension.st +++ b/DebuggableASTDebugger/Object.extension.st @@ -1,5 +1,11 @@ Extension { #name : #Object } +{ #category : #'*DebuggableASTDebugger' } +Object >> bcToDASTValue [ + + ^ self +] + { #category : #'*DebuggableASTDebugger' } Object >> dastToBcValue [ diff --git a/DebuggableASTInterpreter/Context.extension.st b/DebuggableASTInterpreter/Context.extension.st index c3d6a49..e504154 100644 --- a/DebuggableASTInterpreter/Context.extension.st +++ b/DebuggableASTInterpreter/Context.extension.st @@ -3,10 +3,8 @@ Extension { #name : #Context } { #category : #'*DebuggableASTInterpreter' } Context >> asDASTContextInterpretedBy: aDASTInterpreter [ - | dastCtx bindings aimedNode currentNode dastSender | - bindings := Dictionary new. - self tempNames do: [ :tempName | - bindings at: tempName put: (self tempNamed: tempName) ]. + | dastCtx bindings aimedNode currentNode dastSender closureToDASTBlock tempNames | + closureToDASTBlock := Dictionary new. dastCtx := self compiledCode isDoIt ifTrue: [ DASTContext @@ -18,17 +16,39 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ newWithSender: (dastSender := sender asDASTContextInterpretedBy: aDASTInterpreter) - receiver: - (closureOrNil ifNil: [ receiver ] ifNotNil: [ - DASTBlock new + receiver: (closureOrNil + ifNil: [ + self + dastValueFor: receiver + interpretedBy: aDASTInterpreter + withClosureToBlockDictionary: closureToDASTBlock ] + ifNotNil: [ + | dastBlock | + dastBlock := self + dastValueFor: closureOrNil + interpretedBy: aDASTInterpreter + withClosureToBlockDictionary: + closureToDASTBlock. + (dastBlock outerContext isNil or: [ + dastBlock outerContext isDead not ]) + ifTrue: [ "DASTBlock new nodeAST: closureOrNil compiledBlock ast; outerContext: (dastSender isRoot ifFalse: [ dastSender ] - ifTrue: [ - self flag: - 'Maybe it is weird that the outer context is a context but I haven''t found a better solution yet.'. - self outerContext ]); - yourself ]) + ifTrue: [" + self flag: + 'Maybe it is weird that the outer context is a context but I haven''t found a better solution yet.'. + dastBlock + outerContext: self outerContext; + "]); + yourself + dastBlock + outerContext: + (self outerContext asDASTContextInterpretedBy: + aDASTInterpreter); + yourself ]" + yourself ] + ifFalse: [ dastBlock ] ]) messageNode: (dastSender isRoot ifTrue: [ RBMessageNode @@ -36,6 +56,25 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ selector: #value ] ifFalse: [ sender sourceNodeExecuted ]) evaluator: aDASTInterpreter evaluator ]. + DASTContext bcToDASTContextMap at: self put: dastCtx. + bindings := Dictionary new. + "need to find right set of temp names" + tempNames := (self isBlockContext and: [ + (DASTContext bcToDASTContextMap keys + detect: [ :each | each == self outerContext ] + ifNone: [ nil ]) isNotNil ]) + ifTrue: [ + self tempNames difference: self outerContext tempNames ] + ifFalse: [ self tempNames ]. + tempNames do: [ :tempName | + | contextTemp dastTemp | + contextTemp := self tempNamed: tempName. + dastTemp := self + dastValueFor: contextTemp + interpretedBy: aDASTInterpreter + withClosureToBlockDictionary: closureToDASTBlock. + bindings at: tempName put: dastTemp ]. + dastCtx isDead: self isDead. dastCtx temps: bindings associations. self pc @@ -47,7 +86,14 @@ Context >> asDASTContextInterpretedBy: aDASTInterpreter [ dastCtx executedNodes push: (currentNode := dastCtx nodes pop) ]. dastCtx currentNode: currentNode. (Interval from: self numTemps + 1 to: self stackPtr) do: [ :each | - dastCtx stack push: (self at: each) ]. + dastCtx stack push: (self + dastValueFor: (self at: each) + interpretedBy: aDASTInterpreter + withClosureToBlockDictionary: closureToDASTBlock) ]. + closureToDASTBlock do: [ :each | + each outerContext: (DASTContext bcToDASTContextMap + at: self outerContext + ifAbsent: [ self outerContext ]) ]. ^ dastCtx ] diff --git a/DebuggableASTInterpreter/DASTContext.class.st b/DebuggableASTInterpreter/DASTContext.class.st index e3a359f..38aff3c 100644 --- a/DebuggableASTInterpreter/DASTContext.class.st +++ b/DebuggableASTInterpreter/DASTContext.class.st @@ -23,11 +23,18 @@ Class { 'isDead' ], #classVars : [ + 'BcToDASTContextMap', 'valueToBlockMessages' ], #category : #'DebuggableASTInterpreter-Contexts' } +{ #category : #'as yet unclassified' } +DASTContext class >> bcToDASTContextMap [ + + ^ BcToDASTContextMap ifNil: [ BcToDASTContextMap := WeakIdentityKeyDictionary new ] +] + { #category : #instantiation } DASTContext class >> newNoMethodContextWithProgram: aRBNode temps: aCollection evaluator: anEvaluator [ "special context for the first call" diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index 0715da6..e6783cd 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -29,6 +29,27 @@ DASTContextSwitchTests >> bcStepUntil: aBlock [ aBlock whileTrue: [ context := context step ] ] +{ #category : #'as yet unclassified' } +DASTContextSwitchTests >> contextOnMethodWithTempVector [ + + context := [ + | debuggerObjectForTest block a b | + debuggerObjectForTest := StDebuggerObjectForTests new. + a := 0. + block := [ + | c | + debuggerObjectForTest methodWithTempsAssignments. + 1 = 2 ifTrue: [ block value ]. + a := a + 1. + b := 0. + c := 0. + [ + a := a + 2. + c := c + 4. + b := b + 3 ] value ]. + block value + b + a ] asContext +] + { #category : #'tests - helper' } DASTContextSwitchTests >> dastStepUntil: aBlock [ @@ -599,6 +620,7 @@ DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiver [ { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchKeepsReceiversRecursively [ + "Tests fail because we NEED, in some way, to have an outer context. I need either to put the dead pharo context again OR to transform this dead context to a DAST context" 4 timesRepeat: [ context := context step ]. dastContext := context asDASTContextInterpretedBy: @@ -732,6 +754,130 @@ DASTContextSwitchTests >> testInterpreterSwitchStepIsCorrect [ self assert: interpreter currentContext identicalTo: dastContext ] +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchTempVectorBindings [ + + | dastTemp | + self + contextOnMethodWithTempVector; + bcStepUntil: [ + | node | + node := context compiledCode ast sourceNodeForPC: context pc. + (node isMessage and: [ + node selector = #+ and: [ + node arguments last isLiteralNode and: [ + node arguments last value = 3 ] ] ]) not ]. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + | tempNames | + tempNames := dastContext allTemps collect: [ :each | each key ]. + tempNames do: [ :temp | + dastTemp := (dastContext findLocalVariable: temp) value. + dastTemp isBlock + ifFalse: [ + self + assert: ((context lookupTempVar: temp) readInContext: context) + identicalTo: dastTemp ] + ifTrue: [ + | contextTemp | + contextTemp := (context lookupTempVar: temp) readInContext: + context. + self assertFullBlock: contextTemp equalsDASTBlock: dastTemp ] ]. + + dastContext := dastContext sender. + context := context sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchTempVectorEvaluateAfterSwitch [ + + | interpreter | + self + contextOnMethodWithTempVector; + bcStepUntil: [ + | node | + node := context compiledCode ast sourceNodeForPC: context pc. + (node isMessage and: [ + node selector = #+ and: [ + node arguments last isLiteralNode and: [ + node arguments last value = 3 ] ] ]) not ]. + interpreter := DASTInterpreter new. + dastContext := context asDASTContextInterpretedBy: interpreter. + interpreter initializeWithContext: dastContext. + + self assert: interpreter evaluate equals: 9 +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchTempVectorFlatting [ + + | astScope temp dastTemp vectorSize | + self + contextOnMethodWithTempVector; + bcStepUntil: [ + | node | + node := context compiledCode ast sourceNodeForPC: context pc. + (node isMessage and: [ + node selector = #+ and: [ + node arguments last isLiteralNode and: [ + node arguments last value = 3 ] ] ]) not ]. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + astScope := dastContext methodOrBlock nodeAST scope. + astScope tempVector ifNotEmpty: [ + temp := context tempNamed: astScope tempVectorName. + self assert: temp isArray. + vectorSize := 0. + astScope tempVector keysDo: [ :each | + vectorSize := vectorSize + 1. + dastTemp := dastContext tempNamed: each. + dastTemp isBlock + ifFalse: [ + self assert: (temp at: vectorSize) identicalTo: dastTemp ] + ifTrue: [ + self + assertFullBlock: (temp at: vectorSize) + equalsDASTBlock: dastTemp ] ] ]. + + dastContext := dastContext sender. + context := context sender ] +] + +{ #category : #tests } +DASTContextSwitchTests >> testInterpreterSwitchTempVectorStack [ + + | stack dastElement contextElement | + self + contextOnMethodWithTempVector; + bcStepUntil: [ + | node | + node := context compiledCode ast sourceNodeForPC: context pc. + (node isMessage and: [ + node selector = #+ and: [ + node arguments last isLiteralNode and: [ + node arguments last value = 3 ] ] ]) not ]. + dastContext := context asDASTContextInterpretedBy: + DASTInterpreter new. + + [ dastContext isRoot ] whileFalse: [ + stack := dastContext stack. + + (Interval from: 1 to: stack size) do: [ :index | + dastElement := dastContext stack at: index. + contextElement := context at: context numTemps + index. + dastElement isBlock + ifFalse: [ self assert: contextElement identicalTo: dastElement ] + ifTrue: [ + self assertFullBlock: contextElement equalsDASTBlock: dastElement ] ]. + + dastContext := dastContext sender. + context := context sender ] +] + { #category : #tests } DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPC [ From 9e065ff708922829c366f95f7da78f094fa89424 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Wed, 22 Feb 2023 15:51:32 +0100 Subject: [PATCH 39/43] adding a button to switch to another debugger from the DAST debugger --- DebuggableASTDebugger/DASTDebugger.class.st | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st index a567c48..848e9b6 100644 --- a/DebuggableASTDebugger/DASTDebugger.class.st +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -8,7 +8,8 @@ Class { 'code', 'interpreter', 'toolBar', - 'simulatorSession' + 'simulatorSession', + 'switchButton' ], #category : #DebuggableASTDebugger } @@ -81,7 +82,13 @@ DASTDebugger >> clear [ DASTDebugger >> defaultLayout [ ^ SpBoxLayout newVertical - add: stack; + add: (SpBoxLayout newTopToBottom + add: switchButton + expand: false + fill: false + padding: 5; + add: stack; + yourself); add: toolBar expand: false; add: code; yourself @@ -95,6 +102,7 @@ DASTDebugger >> initializePresenters [ transmitDo: [ :ctx | self updateCodeFromContext: ctx ]; yourself. toolBar := self buildToolbar. + switchButton := self newButton action: [ self switchToOtherDebugger ]. self updateStack ] @@ -146,6 +154,22 @@ DASTDebugger >> stepThrough [ self updateStack ] +{ #category : #initialization } +DASTDebugger >> switchToOtherDebugger [ + + | context process | + context := interpreter currentContext asContext. + process := Process + forContext: context + priority: Processor userInterruptPriority. + (OupsDebugRequest newForContext: context) + label: context compiledCode printString; + process: process; + submit. + self clear. + self window close +] + { #category : #'presenter - code' } DASTDebugger >> updateCodeFromContext: aDASTContext [ From cb07e88209a623fe772e1ea24cec90d735662efb Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 23 Feb 2023 13:59:08 +0100 Subject: [PATCH 40/43] adding SwitchToDAST --- DebuggableASTDebugger/DASTDebugger.class.st | 14 ++++---- .../StDebugger.extension.st | 20 +++++++++++ ...nfigurationCommandTreeBuilder.extension.st | 33 +++++++++++++++++++ .../StSwitchToDASTCommand.class.st | 31 +++++++++++++++++ .../DASTException.class.st | 5 +-- 5 files changed, 93 insertions(+), 10 deletions(-) create mode 100644 DebuggableASTDebuggerExperiment/StDebugger.extension.st create mode 100644 DebuggableASTDebuggerExperiment/StDebuggerConfigurationCommandTreeBuilder.extension.st create mode 100644 DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st index 848e9b6..66c52cd 100644 --- a/DebuggableASTDebugger/DASTDebugger.class.st +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -20,8 +20,10 @@ DASTDebugger class >> debugSession: aDebugSession [ | dast | dast := self basicNew. dast simulatorSession: aDebugSession. - aDebugSession stepInto. - aDebugSession stepInto. + aDebugSession interruptedContext receiver class == DASTBreakpoint + ifTrue: [ + aDebugSession stepInto. + aDebugSession stepInto ]. dast interpreter: (DASTInterpreter startFromContext: aDebugSession interruptedContext). dast initialize. @@ -35,10 +37,10 @@ DASTDebugger class >> defaultDebuggerRank [ ] { #category : #debugging } -DASTDebugger class >> handlesContext: aContext [ - |handlesContext| - handlesContext := aContext receiver class = DASTBreakpoint. - ^handlesContext +DASTDebugger class >> handlesDebugSession: aDebugSession [ + + ^ (super handlesDebugSession: aDebugSession) and: [ + aDebugSession exception class == DASTException ] ] { #category : #initialization } diff --git a/DebuggableASTDebuggerExperiment/StDebugger.extension.st b/DebuggableASTDebuggerExperiment/StDebugger.extension.st new file mode 100644 index 0000000..6747fd7 --- /dev/null +++ b/DebuggableASTDebuggerExperiment/StDebugger.extension.st @@ -0,0 +1,20 @@ +Extension { #name : #StDebugger } + +{ #category : #'*DebuggableASTDebuggerExperiment' } +StDebugger class >> buildDASTCommandsGroupWith: stDebuggerInstance forRoot: aRootGroup [ + + + | configGroup dastConfigGroup | + configGroup := aRootGroup + / StDebuggerConfigurationCommandTreeBuilder groupName. + dastConfigGroup := StDebuggerConfigurationCommandTreeBuilder new + dastConfigurationCommandsGroup. + configGroup register: dastConfigGroup +] + +{ #category : #'*DebuggableASTDebuggerExperiment' } +StDebugger >> programmaticallyClose [ + + programmaticallyClosed := true. + self withWindowDo: #close +] diff --git a/DebuggableASTDebuggerExperiment/StDebuggerConfigurationCommandTreeBuilder.extension.st b/DebuggableASTDebuggerExperiment/StDebuggerConfigurationCommandTreeBuilder.extension.st new file mode 100644 index 0000000..b6ffeac --- /dev/null +++ b/DebuggableASTDebuggerExperiment/StDebuggerConfigurationCommandTreeBuilder.extension.st @@ -0,0 +1,33 @@ +Extension { #name : #StDebuggerConfigurationCommandTreeBuilder } + +{ #category : #'*DebuggableASTDebuggerExperiment' } +StDebuggerConfigurationCommandTreeBuilder >> dastConfigurationCommandsClasses [ + + ^ { StSwitchToDASTCommand } +] + +{ #category : #'*DebuggableASTDebuggerExperiment' } +StDebuggerConfigurationCommandTreeBuilder >> dastConfigurationCommandsGroup [ + + | group | + group := (CmCommandGroup named: self dastConfigurationGroupName) + asSpecGroup. + group beDisplayedAsSubMenu. + group description: self dastConfigurationGroupDescription. + self dastConfigurationCommandsClasses do: [ :c | + group register: + (self buildSpecCommand: c forContext: stDebuggerInstance) ]. + ^ group +] + +{ #category : #'*DebuggableASTDebuggerExperiment' } +StDebuggerConfigurationCommandTreeBuilder >> dastConfigurationGroupDescription [ + + ^ 'Configuration commands to perform actions with DAST interpreter' +] + +{ #category : #'*DebuggableASTDebuggerExperiment' } +StDebuggerConfigurationCommandTreeBuilder >> dastConfigurationGroupName [ + + ^ 'DAST configuration' +] diff --git a/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st b/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st new file mode 100644 index 0000000..0081b8b --- /dev/null +++ b/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st @@ -0,0 +1,31 @@ +Class { + #name : #StSwitchToDASTCommand, + #superclass : #StDebuggerCommand, + #category : #DebuggableASTDebuggerExperiment +} + +{ #category : #initialization } +StSwitchToDASTCommand class >> defaultIconName [ + + ^ #halt +] + +{ #category : #initialization } +StSwitchToDASTCommand class >> defaultShortcut [ + + ^ $d meta , $s meta +] + +{ #category : #execution } +StSwitchToDASTCommand >> execute [ + + | session | + session := self context session. + self context programmaticallyClose. + (OupsDebugRequest newForContext: context) + label: context compiledCode printString; + exception: (DASTException new + signaler: self context session receiver; + yourself); + "DASTDebugger debugSession: session"submit +] diff --git a/DebuggableASTInterpreter/DASTException.class.st b/DebuggableASTInterpreter/DASTException.class.st index f5fc64b..7e51f86 100644 --- a/DebuggableASTInterpreter/DASTException.class.st +++ b/DebuggableASTInterpreter/DASTException.class.st @@ -4,9 +4,6 @@ If I'm signaled, the interpreter evaluation should pause " Class { #name : #DASTException, - #superclass : #Object, - #instVars : [ - 'messageText' - ], + #superclass : #Exception, #category : #'DebuggableASTInterpreter-Exceptions' } From 1fc3d3162e73528618cb13ee3885dcfdfe0de868 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 23 Feb 2023 15:21:53 +0100 Subject: [PATCH 41/43] removing super call --- DebuggableASTDebugger/DASTDebugger.class.st | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DebuggableASTDebugger/DASTDebugger.class.st b/DebuggableASTDebugger/DASTDebugger.class.st index 66c52cd..e222924 100644 --- a/DebuggableASTDebugger/DASTDebugger.class.st +++ b/DebuggableASTDebugger/DASTDebugger.class.st @@ -39,8 +39,8 @@ DASTDebugger class >> defaultDebuggerRank [ { #category : #debugging } DASTDebugger class >> handlesDebugSession: aDebugSession [ - ^ (super handlesDebugSession: aDebugSession) and: [ - aDebugSession exception class == DASTException ] + ^ aDebugSession exception class = DASTException or: [ + aDebugSession interruptedContext receiver class = DASTBreakpoint ] ] { #category : #initialization } From 90cfc37eacbf6b1b79df93a468f384486301b223 Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Thu, 23 Feb 2023 15:36:54 +0100 Subject: [PATCH 42/43] fixing StSwitchToDASTCommand + making DASTException an OupsNullException so that it becomes an exception that is only used to open a DASTDebugger --- .../StSwitchToDASTCommand.class.st | 8 +++----- DebuggableASTInterpreter/DASTException.class.st | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st b/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st index 0081b8b..d815d33 100644 --- a/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st +++ b/DebuggableASTDebuggerExperiment/StSwitchToDASTCommand.class.st @@ -16,16 +16,14 @@ StSwitchToDASTCommand class >> defaultShortcut [ ^ $d meta , $s meta ] -{ #category : #execution } +{ #category : #executing } StSwitchToDASTCommand >> execute [ | session | session := self context session. self context programmaticallyClose. (OupsDebugRequest newForContext: context) - label: context compiledCode printString; - exception: (DASTException new - signaler: self context session receiver; - yourself); + label: session interruptedContext compiledCode printString; + exception: (DASTException fromSignallerContext: session interruptedContext); "DASTDebugger debugSession: session"submit ] diff --git a/DebuggableASTInterpreter/DASTException.class.st b/DebuggableASTInterpreter/DASTException.class.st index 7e51f86..56662dd 100644 --- a/DebuggableASTInterpreter/DASTException.class.st +++ b/DebuggableASTInterpreter/DASTException.class.st @@ -4,6 +4,6 @@ If I'm signaled, the interpreter evaluation should pause " Class { #name : #DASTException, - #superclass : #Exception, + #superclass : #OupsNullException, #category : #'DebuggableASTInterpreter-Exceptions' } From 632ea6d3395ae062f61319ae8cebfeae1b62096d Mon Sep 17 00:00:00 2001 From: adri09070 <97704417+adri09070@users.noreply.github.com> Date: Wed, 15 Mar 2023 10:34:44 +0100 Subject: [PATCH 43/43] test bc->DAST optimized ifs --- .../DASTContextSwitchTests.class.st | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st index e6783cd..cedc63b 100644 --- a/DebuggableASTInterpreter/DASTContextSwitchTests.class.st +++ b/DebuggableASTInterpreter/DASTContextSwitchTests.class.st @@ -909,3 +909,24 @@ DASTContextSwitchTests >> testInterpreterSwitchTopNodeIsNodeMappedToCurrentPCRec context := context sender. dastContext := dastContext sender ] ] + +{ #category : #tests } +DASTContextSwitchTests >> testOptimizedIfsBcToDAST [ + + | interpreter | + context := [ + | a | + a := 0. + 1 = 2 + ifFalse: [ a := a + 1 ] + ifTrue: [ a := a + 2 ]. + a ] asContext. + + 4 timesRepeat: [ context := context step; stepToSendOrReturn ]. + + interpreter := DASTInterpreter new. + dastContext := context asDASTContextInterpretedBy: interpreter. + interpreter initializeWithContext: dastContext. + + self assert: interpreter evaluate equals: 1 +]