JavaScriptCompilerWithBreakpointSupport.st
author Claus Gittinger <cg@exept.de>
Fri, 21 Feb 2020 20:48:14 +0100
changeset 1231 b7d945ef967a
parent 1228 bb43112baac3
permissions -rw-r--r--
#REFACTORING by exept class: JavaScriptParser changed: #forStatement class: JavaScriptParser class added: #forOfAllowed comment/format in: #forInAllowed

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 2013 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libjavascript' }"

"{ NameSpace: Smalltalk }"

JavaScriptCompiler subclass:#JavaScriptCompilerWithBreakpointSupport
	instanceVariableNames:'breakpoints'
	classVariableNames:''
	poolDictionaries:''
	category:'Languages-JavaScript-Compiling & Parsing'
!

!JavaScriptCompilerWithBreakpointSupport class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 2013 by eXept Software AG
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    I'm an experimental compiler class that supports breakpoints. 
    Once tested, the code might be merged to JavaScriptCompiler.

    [author:]
        code stolen from BytecodeCompilerWithBreakpointSupport

    [instance variables:]

    [class variables:]

    [see also:]

"
! !

!JavaScriptCompilerWithBreakpointSupport methodsFor:'adding breakpoint'!

possiblyWrapABreakPointAround:aBlock
    "refactored Jan's original code; changed to not wrap an already wrapped expression"

    | expr bpnt tokenPositionBefore tokenLineNrBefore |

    breakpoints isEmptyOrNil ifTrue:[ ^ aBlock value].

    tokenPositionBefore := tokenPosition ? source position.
    tokenLineNrBefore := tokenLineNr.

    expr := aBlock value.
    expr startPosition notNil ifTrue:[
        tokenPositionBefore := expr startPosition.
        tokenLineNrBefore := expr lineNumber.
    ].

    "/ find the very first breakpoint, which is right after the
    "/ current line start, and remove it from the breakpoints collection,
    "/ incl. all before. This removes breakpoints on empty lines or inside strings etc.
    [
        breakpoints notEmpty
        and:[
            (breakpoints first position notNil and:[breakpoints first position <= tokenPositionBefore])
            or:[ (breakpoints first position isNil and:[breakpoints first line <= (tokenLineNrBefore ? 0)]) ]
        ]
    ] whileTrue:[
        bpnt := breakpoints removeFirst
    ].

    bpnt isNil ifTrue:[^ expr].
    (expr isBreakPointNode 
     and:[expr lineNumber <= bpnt line]) ifTrue:[
        ^ expr
    ].
    tokenPositionBefore = tokenPosition ifTrue:[
        "/ nothing scanned - happens with unaryExpression which does not find anything,
        "/ but returns due to a ')' or ']' token.
        ^ expr
    ].

    bpnt isReached:true.

    "/ Transcript show:'adding breakpoint '; show:bpnt; show:' before: '; showCR:expr.

    ^ BreakpointNode new
        breakpoint:bpnt;
        expression:expr;
        lineNumber:(bpnt line ? tokenLineNrBefore);
        yourself

    "Created: / 05-07-2011 / 21:11:19 / cg"
    "Modified: / 30-01-2020 / 14:59:48 / Stefan Vogel"
!

possiblyWrapABreakPointBefore:aBlock
    "refactored Jan's original code; changed to not wrap an already wrapped expression"

    | stat bpnt tokenPositionBefore tokenLineNrBefore |

    breakpoints isEmptyOrNil ifTrue:[ ^ aBlock value].

    tokenPositionBefore := tokenPosition ? source position.
    tokenLineNrBefore := tokenLineNr.

    "/ find the very first breakpoint, which is right after the
    "/ current line start, and remove it from the breakpoints collection,
    "/ incl. all before. This removes breakpoints on empty lines or inside strings etc.
    [
        breakpoints notEmpty
        and:[breakpoints first position < tokenPositionBefore]
    ] whileTrue:[
        bpnt := breakpoints removeFirst
    ].

    stat := aBlock value.
    bpnt isNil ifTrue:[^stat].
    stat isNil ifTrue:[^stat].

    ((stat isKindOf:JavaScriptParser::StatementBlockNode)
        and:[stat statements first isBreakPointNode]) ifTrue:[^stat].

    tokenPositionBefore = tokenPosition ifTrue:[
        "/ nothing scanned - happens with unaryExpression which does not find anything,
        "/ but returns due to a ')' or ']' token.
        ^stat
    ].

    bpnt isReached:true.

    "/ Transcript show:'adding breakpoint '; show:bpnt; show:' before: '; showCR:expr.

    ^ JavaScriptParser::StatementBlockNode new
        statements:{
                BreakpointNode new
                    breakpoint: bpnt;
                    expression: nil;
                    lineNumber:(bpnt line ? tokenLineNrBefore);
                    yourself
                .
                stat
        }

    "Created: / 22-07-2013 / 15:42:08 / cg"
!

removeMissedBreakpointsBefore:aPosition
    [
        breakpoints notEmpty
        and:[breakpoints first position < aPosition]
    ] whileTrue:[
        breakpoints removeFirst
    ].

    "Created: / 05-07-2011 / 23:13:25 / cg"
! !

!JavaScriptCompilerWithBreakpointSupport methodsFor:'parsing-expressions'!

addExpression
    |node|

    node := super addExpression.
    breakpoints isEmptyOrNil ifTrue:[ ^ node].
    ^ self possiblyWrapABreakPointAround:[node]

    "Created: / 22-07-2013 / 15:36:03 / cg"
!

block
    |blockNode|

    self removeMissedBreakpointsBefore:source position.
    blockNode := super block.
    self removeMissedBreakpointsBefore:blockNode endPosition+2.
    ^ blockNode

    "Created: / 05-07-2011 / 22:56:19 / cg"
!

expression
    |node|

    node := super expression.
    breakpoints isEmptyOrNil ifTrue:[ ^ node].
    ^ self possiblyWrapABreakPointAround:[node]

    "Created: / 16-06-2011 / 14:58:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 05-07-2011 / 21:11:38 / cg"
!

primaryExpression
    |node|

    node := super primaryExpression.
    breakpoints isEmptyOrNil ifTrue:[ ^ node].
    ^ self possiblyWrapABreakPointAround:[node]

    "Created: / 22-07-2013 / 15:37:04 / cg"
!

unaryExpression
    |node|

    node := super unaryExpression.
    breakpoints isEmptyOrNil ifTrue:[ ^ node].
    ^ self possiblyWrapABreakPointAround:[node]

    "Created: / 05-07-2011 / 23:08:54 / cg"
! !

!JavaScriptCompilerWithBreakpointSupport methodsFor:'parsing-statements'!

statement
    |node|

    node := super statement.
    breakpoints isEmptyOrNil ifTrue:[ ^ node].
    ^ self possiblyWrapABreakPointBefore:[node]

    "Created: / 22-07-2013 / 15:42:53 / cg"
! !

!JavaScriptCompilerWithBreakpointSupport methodsFor:'private'!

breakpoints:aCollection
    self assert:(aCollection conform:[:bpnt | bpnt line notNil]).
    self assert:(aCollection conform:[:bpnt | bpnt position notNil or:[bpnt line notNil]]).
    breakpoints := aCollection copy 
                        sort:[:a :b|
                            (a position notNil and:[b position notNil]) ifTrue:[
                                a position < b position
                            ] ifFalse:[
                                a line < b line
                            ]
                        ].

    "Created: / 16-06-2011 / 14:35:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Created: / 05-07-2011 / 21:37:28 / cg"
    "Modified: / 20-02-2019 / 18:53:14 / Claus Gittinger"
!

methodClass
    ^ methodClass ? JavaScriptFunctionWithBreakpoints

    "Created: / 22-07-2013 / 15:53:54 / cg"
!

notifying: anObject
    super notifying: anObject.
    anObject notNil ifTrue:[
        breakpoints isNil ifTrue:[
            self breakpoints:(anObject perform: #breakpoints ifNotUnderstood:#()).
        ]
    ]

    "Created: / 16-06-2011 / 14:35:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 05-07-2011 / 21:48:37 / cg"
! !

!JavaScriptCompilerWithBreakpointSupport class methodsFor:'documentation'!

version
    ^ '$Header$'
!

version_CVS
    ^ '$Header$'
! !