import { VIEW_DIRECTIVE_PREFIX } from "../directives" ; export interface SkulptAnalysis { functionCallStack : SkulptScope [ ] ; stepNum : number ; code : '' ; lines : string [ ] ; } export interface SkulptVariable { cur : any ; old : any ; } export interface SkulptScope { variables : { [ key ] : SkulptVariable ; } ; directives : any [ ] ; name : string ; args : string [ ] ; openedPaths : { [ key ] : boolean ; } ; loadedReferences : any ; currentLine : number ; currentColumn : number ; suspensionIdx : number ; scopeIndex : number ; } type { int } const SKULPT_ANALYSIS_DEBUG = 0 ; param suspensions param lastAnalysis param newStepNum returns export const analyseSkulptState = function ( suspensions , lastAnalysis , newStepNum ) : SkulptAnalysis { if ( SKULPT_ANALYSIS_DEBUG === 2 ) { console . log ( '[¥¥¥¥¥¥¥] Building analysis' ) ; console . log ( suspensions ) ; console . log ( lastAnalysis ) ; } let functionCallStack = [ ] ; if ( suspensions ) { let scopeIndex = 0 ; for ( let suspensionIdx = 0 ; suspensionIdx < suspensions . length ; suspensionIdx ++ ) { const suspension = suspensions [ suspensionIdx ] ; if ( ! isProgramSuspension ( suspension ) ) { continue ; } let lastScopeAnalysis = null ; if ( lastAnalysis && lastAnalysis . functionCallStack . length > scopeIndex ) { lastScopeAnalysis = lastAnalysis . functionCallStack [ scopeIndex ] ; } const analysedScope = analyseSkulptScope ( suspension , lastScopeAnalysis , newStepNum , suspensionIdx , scopeIndex ) ; functionCallStack . push ( analysedScope ) ; scopeIndex ++ ; } } const analysis = { ... lastAnalysis , functionCallStack : functionCallStack , stepNum : newStepNum } ; if ( SKULPT_ANALYSIS_DEBUG > 0 ) { console . log ( '[¥¥¥¥¥¥¥] End of building analysis' ) ; console . log ( analysis ) ; } return Object . freeze ( analysis ) ; } ; param { Object } suspension returns { boolean } const isProgramSuspension = function ( suspension ) : boolean { return suspension . hasOwnProperty ( '$lineno' ) ; } ; param suspension param lastAnalysis param newStepNum param suspensionIdx param scopeIndex returns export const analyseSkulptScope = function ( suspension , lastAnalysis , newStepNum , suspensionIdx , scopeIndex ) : SkulptScope { if ( SKULPT_ANALYSIS_DEBUG === 2 ) { console . log ( '////// Analyse scope...' ) ; console . log ( suspension ) ; console . log ( lastAnalysis ) ; } let variables = { } ; let name = suspension . _name ; if ( name === '<module>' ) { name = '' ; } const args = suspension . _argnames ; let suspVariables ; if ( Object . keys ( suspension . $loc ) . length === 0 && suspension . $loc . constructor === Object ) { suspVariables = suspension . $tmps ; } else { suspVariables = suspension . $loc ; } const variableNames = sortArgumentsFirst ( filterInternalVariables ( Object . keys ( suspVariables ) ) , args ) ; for ( let variableName of variableNames ) { let value = suspVariables [ variableName ] ; if ( typeof value === 'function' ) { if ( ! value . prototype || ! value . prototype . tp$name ) { continue ; } value = `<class '${ value . prototype . tp$name }'>` ; } let lastValue = null ; if ( lastAnalysis ) { lastValue = lastAnalysis . variables [ variableName ] ; if ( lastValue ) { lastValue = lastValue . cur ; } else { lastValue = undefined ; } } variables [ Sk . unfixReserved ( variableName ) ] = { cur : value , old : lastValue } ; } const loadedReferences = ( lastAnalysis ) ? { ... lastAnalysis . loadedReferences } : { } ; for ( let reference in suspension . $loaded_references ) { loadedReferences [ reference ] = newStepNum ; } let openedPaths = { } ; if ( lastAnalysis ) { openedPaths = lastAnalysis . openedPaths ; } const analysis = { variables , directives : getDirectiveVariables ( suspVariables ) , name , args , openedPaths , loadedReferences , currentColumn : suspension . $colno , currentLine : suspension . $lineno , suspensionIdx , scopeIndex } ; if ( SKULPT_ANALYSIS_DEBUG === 2 ) { console . log ( '////// End of analyse scope...' ) ; console . log ( analysis ) ; } return analysis ; } ; const variablesBeginWithIgnore = [ '__name__' , '__doc__' , '__package__' , '__file__' , '__class__' , '__refs__' , VIEW_DIRECTIVE_PREFIX , '$compareres' , '$loadgbl' , '$binop' , '$lsubscr' , '$iter' , '$call' , '$loadtuple' , '$items' , '$elem' , '$lattr' ] ; param { Array } variableNames returns { Array } const filterInternalVariables = ( variableNames ) : string [ ] => { return variableNames . filter ( ( name ) => { let ignore = false ; for ( let variableBeginWithIgnore of variablesBeginWithIgnore ) { if ( name . indexOf ( variableBeginWithIgnore ) === 0 ) { return false ; } } return true ; } ) ; } ; const getDirectiveVariables = ( variables ) => { let directiveVariables = [ ] ; for ( let variableName in variables ) { if ( variableName . startsWith ( VIEW_DIRECTIVE_PREFIX ) ) { const directiveName = variableName . substr ( VIEW_DIRECTIVE_PREFIX . length ) ; if ( variables [ variableName ] ) { directiveVariables . push ( directiveName + ' = ' + variables [ variableName ] . v ) ; } } } return directiveVariables ; } ; param { Array } variableNames param { Array } args return { Array } const sortArgumentsFirst = ( variableNames , args ) => { return variableNames . sort ( ( a , b ) => { const aIsArg = ( args && args . indexOf ( a ) !== - 1 ) ; const bIsArg = ( args && args . indexOf ( b ) !== - 1 ) ; if ( aIsArg && ! bIsArg ) { return - 1 ; } else if ( bIsArg && ! aIsArg ) { return 1 ; } return a . localeCompare ( b ) ; } ) ; } ; param { Array } suspensions return { Array } export const getSkulptSuspensionsCopy = function ( suspensions ) { const copies = [ ] ; for ( let suspensionIdx in suspensions ) { const suspension = suspensions [ suspensionIdx ] ; copies [ suspensionIdx ] = { ... suspension } ; } return Object . freeze ( copies ) ; } ; param analysis export const clearLoadedReferences = function ( analysis ) { const clearedAnalysis = { ... analysis , functionCallStack : [ ] } ; for ( let idx = 0 ; idx < analysis . functionCallStack . length ; idx ++ ) { const clearedFunctionCallStack = { ... analysis . functionCallStack [ idx ] , loadedReferences : { } } ; clearedAnalysis . functionCallStack . push ( clearedFunctionCallStack ) ; } return clearedAnalysis ; } ;