branch: externals/phps-mode commit 258551c02a3ab6b30c5f04e925a75b9da31f0a50 Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
More work on bookkeeping generation via SDT --- phps-mode-ast-bookkeeping.el | 1077 +----------------------------------------- phps-mode-parser-sdt.el | 48 +- 2 files changed, 48 insertions(+), 1077 deletions(-) diff --git a/phps-mode-ast-bookkeeping.el b/phps-mode-ast-bookkeeping.el index e4fd2b2b9e..6bf8875c65 100644 --- a/phps-mode-ast-bookkeeping.el +++ b/phps-mode-ast-bookkeeping.el @@ -249,1081 +249,8 @@ (defun phps-mode-ast-bookkeeping--generate (&optional tree) "Generate AST for current buffer or optionally for TREE." - (let ((bookkeeping (make-hash-table :test 'equal)) - (bookkeeping-stack (if tree tree phps-mode-ast--tree)) - (bookkeeping-objects) - (inline-function-count 0) - (arrow-function-count 0) - (defined-count 0) - (global-namespace)) - (while bookkeeping-stack - (let ((item-raw (pop bookkeeping-stack)) - (item) - (scope)) - (if (listp (car item-raw)) - (progn - (setq - scope - (car item-raw)) - (setq - item - (car (cdr item-raw)))) - (setq - item - item-raw)) - - ;; Set global namespace (if any) - (when global-namespace - (let ((had-scope-p scope)) - (when had-scope-p - (setq scope (reverse scope))) - (push - (list 'type 'namespace 'name global-namespace) - scope) - (when had-scope-p - (setq scope (reverse scope))))) - - (let ((type (plist-get item 'ast-type))) - (cond - - ((equal type 'simple-variable) - (let* ((object-name (plist-get item 'name)) - (object-start (plist-get item 'start)) - (object-end (plist-get item 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-name - t)) - (object - (list - object-start - object-end)) - (defined-p 0) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (when (gethash id bookkeeping) - (setq - defined-p - 1))) - - ;; Is it a super-global variable? - (when - (gethash - (plist-get item 'name) - phps-mode-ast-bookkeeping--superglobal-variable-p) - (setq - defined-p - 1)) - (puthash - object - defined-p - bookkeeping))) - - ((equal type 'static-variables-statement) - (when-let ((variables (reverse (plist-get item 'static-var-list)))) - (dolist (variable variables) - (let* ((object-name (plist-get variable 'name)) - (object-start (plist-get variable 'start)) - (object-end (plist-get variable 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-name)) - (object - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - object - 1 - bookkeeping))))) - - ((equal type 'function) - (let ((name (plist-get item 'name)) - (sub-scope scope)) - (push `(type function name ,name) sub-scope) - (when-let ((parameter-list (plist-get item 'parameter-list))) - (dolist (parameter parameter-list) - (let* ((object-name (plist-get parameter 'name)) - (object-start (plist-get parameter 'start)) - (object-end (plist-get parameter 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name)) - (object - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - object - 1 - bookkeeping)))) - - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,sub-scope ,child) bookkeeping-stack))))) - - ((equal type 'return-statement) - (when-let ((expr (reverse (plist-get item 'optional-expr)))) - (dolist (e expr) - (push `(,scope ,e) bookkeeping-stack)))) - - ((equal type 'method) - (let ((name (plist-get item 'name)) - (sub-scope scope) - (parent-is-interface) - (is-static)) - (push `(type function name ,name) sub-scope) - - (when-let ((modifiers (plist-get item 'modifiers))) - (dolist (modifier modifiers) - (when (equal modifier 'static) - (setq - is-static - t)))) - - (when (equal (plist-get (car scope) 'type) 'interface) - (setq parent-is-interface t)) - - (unless (or - is-static - parent-is-interface) - (let ((this-ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - "$this"))) - (dolist (this-id this-ids) - (puthash - this-id - 1 - bookkeeping)))) - - (when-let ((parameter-list (plist-get item 'parameter-list))) - (dolist (parameter parameter-list) - (let* ((object-name (plist-get parameter 'name)) - (object-start (plist-get parameter 'start)) - (object-end (plist-get parameter 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name)) - (object - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - object - 1 - bookkeeping)))) - - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,sub-scope ,child) bookkeeping-stack))))) - - ((equal type 'namespace) - (let ((name (plist-get item 'name)) - (sub-scope scope)) - (push `(type namespace name ,name) sub-scope) - (if-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,sub-scope ,child) bookkeeping-stack)) - (setq global-namespace name)))) - - ((equal type 'class) - (let ((name (plist-get item 'name)) - (sub-scope scope)) - (push `(type class name ,name) sub-scope) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,sub-scope ,child) bookkeeping-stack))))) - - ((equal type 'interface) - (let ((name (plist-get item 'name)) - (sub-scope scope)) - (push `(type interface name ,name) sub-scope) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,sub-scope ,child) bookkeeping-stack))))) - - ((equal type 'if) - (let* ((conditions (reverse (plist-get item 'condition))) - (condition-stack conditions) - (found-defined-scope) - (sub-scope scope)) - (while condition-stack - (let ((condition (pop condition-stack))) - (when-let ((condition-type (plist-get condition 'ast-type))) - (cond - - ((or (equal condition-type 'boolean-and-expression) - (equal condition-type 'boolean-or-expression)) - (let ((as (reverse (plist-get condition 'a))) - (bs (reverse (plist-get condition 'b)))) - (dolist (b bs) - (push b condition-stack)) - (dolist (a as) - (push a condition-stack)))) - - ((equal condition-type 'isset-variables) - (let ((sub-scope scope)) - (unless found-defined-scope - (setq defined-count (1+ defined-count)) - (setq found-defined-scope t)) - (push `(type defined name ,defined-count) sub-scope) - (let ((isset-variables (plist-get condition 'variables))) - (dolist (isset-variable isset-variables) - (let ((ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - (plist-get isset-variable 'name)))) - (dolist (id ids) - (puthash - id - 1 - bookkeeping))))))) - - ((and - (equal condition-type 'negated-expression) - (equal (plist-get (plist-get condition 'expression) 'ast-type) 'empty-expression)) - (let ((sub-scope scope)) - (unless found-defined-scope - (setq defined-count (1+ defined-count)) - (setq found-defined-scope t)) - (push `(type defined name ,defined-count) sub-scope) - (let ((not-empty-variables (plist-get (plist-get condition 'expression) 'variables))) - (dolist (not-empty-variable not-empty-variables) - (let ((ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - (plist-get not-empty-variable 'name)))) - (dolist (id ids) - (puthash - id - 1 - bookkeeping))))))) - - )))) - (when found-defined-scope - (push `(type defined name ,defined-count) sub-scope)) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,sub-scope, child) bookkeeping-stack))) - (when conditions - (dolist (condition conditions) - (push `(,sub-scope ,condition) bookkeeping-stack))))) - - ((equal type 'isset-variables) - (let ((isset-variables (reverse (plist-get item 'variables)))) - (dolist (isset-variable isset-variables) - (push `(,scope ,isset-variable) bookkeeping-stack)))) - - ((equal type 'empty-expression) - (let ((not-empty-variables (reverse (plist-get item 'variables)))) - (dolist (not-empty-variable not-empty-variables) - (push `(,scope ,not-empty-variable) bookkeeping-stack)))) - - ((equal type 'foreach) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((value (plist-get item 'value))) - (if (equal (plist-get value 'ast-type) 'foreach-referenced-variable) - (push - (list - scope - (list - 'ast-type - 'assign-variable - 'key - (plist-get value 'variable))) - bookkeeping-stack) - (push - (list - scope - (list - 'ast-type - 'assign-variable - 'key - value)) - bookkeeping-stack))) - (when-let ((key (plist-get item 'key))) - (push - (list - scope - (list - 'ast-type - 'assign-variable - 'key - key)) - bookkeeping-stack)) - (when-let ((expression (reverse (plist-get item 'expression)))) - (dolist (expr expression) - (push `(,scope ,expr) bookkeeping-stack)))) - - ((equal type 'for) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((children (reverse (plist-get item 'incremental)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((children (reverse (plist-get item 'test)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((children (reverse (plist-get item 'initial)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack)))) - - ((equal type 'while) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((conditions (reverse (plist-get item 'condition)))) - (dolist (condition conditions) - (push `(,scope ,condition) bookkeeping-stack)))) - - ((equal type 'do-while) - (when-let ((conditions (reverse (plist-get item 'condition)))) - (dolist (condition conditions) - (push `(,scope ,condition) bookkeeping-stack))) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack)))) - - ((equal type 'assign-property-variable) - (let* ((object-key (plist-get item 'key)) - (object-start (plist-get item 'start)) - (object-end (plist-get item 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-key)) - (object - (list - object-start - object-end)) - (defined 1) - (bookkeeping-object - (list - 'type type - 'name object-key - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (when-let ((predefined (gethash id bookkeeping))) - (setq - defined - (1+ predefined)))) - (dolist (id ids) - (puthash - id - defined - bookkeeping)) - (puthash - object - defined - bookkeeping))) - - ;; Infix expressions - ((or - (equal type 'boolean-or-expression) - (equal type 'boolean-and-expression) - (equal type 'logical-or-expression) - (equal type 'logical-and-expression) - (equal type 'logical-xor-expression) - (equal type 'bitwise-or-expression) - (equal type 'bitwise-and-expression) - (equal type 'bitwise-xor-expression) - (equal type 'concat-expression) - (equal type 'addition-expression) - (equal type 'subtraction-expression) - (equal type 'multiplication-expression) - (equal type 'exponentiation-expression) - (equal type 'division-expression) - (equal type 'modulo-expression) - (equal type 'bitwise-shift-left-expression) - (equal type 'bitwise-shift-right-expression)) - (when-let ((bs (reverse (plist-get item 'b)))) - (dolist (b bs) - (push `(,scope ,b) bookkeeping-stack))) - (when-let ((as (reverse (plist-get item 'a)))) - (dolist (a as) - (push `(,scope ,a) bookkeeping-stack)))) - - ((equal type 'global-statement) - (when-let ((global-var-list (reverse (plist-get item 'global-var-list)))) - (dolist (global-var global-var-list) - (push - (list - scope - (list - 'ast-type - 'assign-variable - 'key - global-var)) - bookkeeping-stack)))) - - ((equal type 'assign-variables-from-array) - (when-let ((keys (reverse (plist-get item 'keys)))) - (dolist (key keys) - (push - (list - scope - (list - 'ast-type - 'assign-variable - 'key - key)) - bookkeeping-stack)))) - - ((and - (equal type 'assign-variable) - (plist-get (plist-get item 'key) 'name)) - (let* ((object-name (plist-get (plist-get item 'key) 'name)) - (object-start (plist-get (plist-get item 'key) 'start)) - (object-end (plist-get (plist-get item 'key) 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-name)) - (object - (list - object-start - object-end)) - (defined 1) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (when-let ((predefined (gethash id bookkeeping))) - (setq - defined - (1+ predefined)))) - (dolist (id ids) - (puthash - id - defined - bookkeeping)) - (puthash - object - defined - bookkeeping) - (when-let ((exps (plist-get item 'value))) - (when (listp exps) - (dolist (exp exps) - (push `(,scope ,exp) bookkeeping-stack)))))) - - ((equal type 'property) - (let ((subject (plist-get item 'subject)) - (static-p) - (sub-scope scope)) - (when-let ((modifiers (plist-get item 'modifiers))) - (dolist (modifier modifiers) - (when (equal modifier 'static) - (setq - static-p - t)))) - (when static-p - (push '(type static) sub-scope)) - (if (stringp subject) - (let ((ids)) - (setq - ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - subject)) - (let* ((object-name subject) - (object-start (plist-get item 'start)) - (object-end (plist-get item 'end)) - (object - (list - object-start - object-end)) - (defined 1) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (when-let ((predefined (gethash id bookkeeping))) - (setq - defined - (1+ predefined)))) - (dolist (id ids) - (puthash - id - defined - bookkeeping)) - (puthash - object - defined - bookkeeping))) - (push `(,sub-scope ,subject) bookkeeping-stack)))) - - ((equal type 'function-call) - (when-let ((arguments (plist-get item 'argument-list))) - (dolist (argument arguments) - (push `(,scope ,argument) bookkeeping-stack)))) - - ((equal type 'increment-variable) - (push `(,scope ,(plist-get item 'variable)) bookkeeping-stack)) - - ((equal type 'negated-expression) - (push `(,scope ,(plist-get item 'expression)) bookkeeping-stack)) - - ((equal type 'try) - (when-let ((children (reverse (plist-get item 'inner-statement-list)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((children (reverse (plist-get item 'catch-list)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack))) - (when-let ((children (reverse (plist-get item 'finally-statement)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack)))) - - ((equal type 'catch) - (when-let ((optional-variable - (plist-get item 'optional-variable))) - (let* ((object-name optional-variable) - (object-start (plist-get item 'optional-variable-start)) - (object-end (plist-get item 'optional-variable-end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-name)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - (list - object-start - object-end) - 1 - bookkeeping))) - (when-let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (push `(,scope ,child) bookkeeping-stack)))) - - ((equal type 'array-object-dereferencable) - (let* ((subject (plist-get item 'subject)) - (downcase-subject-name (downcase (plist-get subject 'name))) - (property-name (plist-get item 'property-name))) - - (when downcase-subject-name - (cond - - ((string= downcase-subject-name "$this") - (puthash - (list - (plist-get subject 'start) - (plist-get subject 'end)) - 1 - bookkeeping) - ;; When current scope is arrow function - ;; we should go up in scope until we get out of - ;; arrow functions scope - (let ((sub-scope scope) - (head-scope) - (is-arrow-function-scope t)) - (while (and - sub-scope - is-arrow-function-scope) - (setq - head-scope - (car sub-scope)) - (setq - sub-scope - (cdr sub-scope)) - (unless (equal - (plist-get head-scope 'type) - 'arrow-function) - (setq is-arrow-function-scope nil))) - (let* ((object-name (concat "$" property-name)) - (object-start (plist-get item 'property-start)) - (object-end (plist-get item 'property-end)) - (predefined) - (variable-ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name - t)) - (symbol-id - (phps-mode-ast-bookkeeping--generate-symbol-scope-string - sub-scope - property-name)) - (bookkeeping-object2 - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (when (gethash symbol-id bookkeeping) - (setq - predefined - t)) - (dolist (variable-id variable-ids) - (when (gethash variable-id bookkeeping) - (setq - predefined - t))) - (if predefined - (puthash - bookkeeping-object2 - 1 - bookkeeping) - (puthash - bookkeeping-object2 - 0 - bookkeeping))))) - - (t - (let* ((object-name (plist-get subject 'name)) - (object-start (plist-get subject 'start)) - (object-end (plist-get subject 'end)) - (variable-ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-name - t)) - (predefined 0) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (dolist (variable-id variable-ids) - (when (gethash - variable-id - bookkeeping) - (setq - predefined - 1))) - (puthash - (list - object-start - object-end) - predefined - bookkeeping))) - - )))) - - ((equal type 'variable) - (let* ((subject (plist-get item 'array-object-dereferencable)) - (downcase-subject-name (downcase (plist-get subject 'name))) - (property-name (plist-get item 'property-name))) - - (when downcase-subject-name - (cond - - ((string= downcase-subject-name "$this") - (puthash - (list - (plist-get subject 'start) - (plist-get subject 'end)) - 1 - bookkeeping) - ;; When current scope is arrow function - ;; we should go up in scope until we get out of - ;; arrow functions scope - (let ((sub-scope scope) - (head-scope) - (is-arrow-function-scope t)) - (while (and - sub-scope - is-arrow-function-scope) - (setq - head-scope - (car sub-scope)) - (setq - sub-scope - (cdr sub-scope)) - (unless (equal - (plist-get head-scope 'type) - 'arrow-function) - (setq is-arrow-function-scope nil))) - (let* ((object-name (concat "$" property-name)) - (object-start (plist-get item 'property-start)) - (object-end (plist-get item 'property-end)) - (predefined) - (variable-ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name - t)) - (symbol-id - (phps-mode-ast-bookkeeping--generate-symbol-scope-string - sub-scope - property-name)) - (bookkeeping-object2 - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (when (gethash symbol-id bookkeeping) - (setq - predefined - t)) - (dolist (variable-id variable-ids) - (when (gethash variable-id bookkeeping) - (setq - predefined - t))) - (if predefined - (puthash - bookkeeping-object2 - 1 - bookkeeping) - (puthash - bookkeeping-object2 - 0 - bookkeeping))))) - - (t - (let* ((object-name (plist-get subject 'name)) - (object-start (plist-get subject 'start)) - (object-end (plist-get subject 'end)) - (variable-ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - scope - object-name - t)) - (predefined 0) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (dolist (variable-id variable-ids) - (when (gethash - variable-id - bookkeeping) - (setq - predefined - 1))) - (puthash - (list - object-start - object-end) - predefined - bookkeeping))) - - )))) - - ((equal type 'static-member) - (let* ((parent-class (plist-get item 'class)) - (downcased-parent-class (downcase parent-class)) - (member (plist-get item 'member)) - (member-type (plist-get member 'ast-type))) - - (cond - - ((or (string= downcased-parent-class "self") - (string= downcased-parent-class "static")) - - (cond - - ((equal member-type 'simple-variable) - ;; When current scope is arrow function - ;; we should go up in scope until we get out of - ;; arrow functions scope - (let ((sub-scope scope) - (head-scope) - (is-arrow-function-scope t)) - (while (and - sub-scope - is-arrow-function-scope) - (setq - head-scope - (car sub-scope)) - (setq - sub-scope - (cdr sub-scope)) - (unless (equal - (plist-get head-scope 'type) - 'arrow-function) - (setq is-arrow-function-scope nil))) - (push '(type static) sub-scope) - (let* ((object-name (plist-get member 'name)) - (object-start (plist-get member 'start)) - (object-end (plist-get member 'end)) - (predefined) - (variable-ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name - t)) - (bookkeeping-object2 - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (dolist (variable-id variable-ids) - (when (gethash variable-id bookkeeping) - (setq - predefined - t))) - (if predefined - (puthash - bookkeeping-object2 - 1 - bookkeeping) - (puthash - bookkeeping-object2 - 0 - bookkeeping))))) - - ) - - )))) - - ((equal type 'static-inline-function) - (push `(,scope ,(plist-get item 'inline-function)) bookkeeping-stack)) - - ((equal type 'echo-statement) - (let ((children (reverse (plist-get item 'children)))) - (dolist (child children) - (when (listp child) - (push `(,scope ,child) bookkeeping-stack))))) - - ((equal type 'arrow-function) - (let ((sub-scope scope)) - (setq arrow-function-count (1+ arrow-function-count)) - (push `(type arrow-function name ,arrow-function-count) sub-scope) - (when-let ((expr (reverse (plist-get item 'expr)))) - (dolist (e expr) - (push `(,sub-scope ,e) bookkeeping-stack))) - (when-let ((parameter-list (plist-get item 'parameter-list))) - (dolist (parameter parameter-list) - (let* ((object-name (plist-get parameter 'name)) - (object-start (plist-get parameter 'start)) - (object-end (plist-get parameter 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name)) - (object - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - object - 1 - bookkeeping)))))) - - ((equal type 'inline-function) - (let ((sub-scope scope)) - (setq inline-function-count (1+ inline-function-count)) - (push `(type inline-function name ,inline-function-count) sub-scope) - (when-let ((inner-statement-list (reverse (plist-get item 'inner-statement-list)))) - (dolist (inner-statement inner-statement-list) - (push `(,sub-scope ,inner-statement) bookkeeping-stack))) - (when-let ((parameter-list (plist-get item 'parameter-list))) - (dolist (parameter parameter-list) - (let ((ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - (plist-get parameter 'name))) - (object - (list - (plist-get parameter 'start) - (plist-get parameter 'end)))) - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - object - 1 - bookkeeping)))) - (when-let ((lexical-vars (plist-get item 'lexical-vars))) - (dolist (lexical-var lexical-vars) - (let* ((object-name (plist-get lexical-var 'name)) - (object-start (plist-get lexical-var 'start)) - (object-end (plist-get lexical-var 'end)) - (ids - (phps-mode-ast-bookkeeping--generate-variable-scope-string - sub-scope - object-name)) - (object - (list - object-start - object-end)) - (bookkeeping-object - (list - 'type type - 'name object-name - 'scope scope - 'start object-start - 'end object-end))) - (push - bookkeeping-object - bookkeeping-objects) - - (dolist (id ids) - (puthash - id - 1 - bookkeeping)) - (puthash - object - 1 - bookkeeping)))))) - - )))) - (setq - phps-mode-ast-bookkeeping--index - bookkeeping) - (setq - phps-mode-ast-bookkeeping--object-index - bookkeeping-objects) - - ;; (message "\nBookkeeping\n:%S\n" bookkeeping) - phps-mode-ast-bookkeeping--index)) + (setq phps-mode-ast-bookkeeping--index phps-mode-parser-sdt-bookkeeping) + phps-mode-ast-bookkeeping--index) (provide 'phps-mode-ast-bookkeeping) diff --git a/phps-mode-parser-sdt.el b/phps-mode-parser-sdt.el index 265bba60e9..c4c3f52583 100644 --- a/phps-mode-parser-sdt.el +++ b/phps-mode-parser-sdt.el @@ -591,6 +591,11 @@ (make-hash-table :test 'equal) "Bookkeeping") +(defvar-local + phps-mode-parser-sdt-bookkeeping-namespace + "" + "Current bookkeeping namespace.") + ;; SDT starts here ;; 0 ((start) (top_statement_list)) @@ -3158,7 +3163,7 @@ (lambda(args terminals) `( ast-type - expr-assign-variable + expr-assign-variable-by-expr variable ,(nth 0 args) expr @@ -5052,7 +5057,46 @@ ;; 515 ((simple_variable) (T_VARIABLE)) (puthash 515 - (lambda(args _terminals) + (lambda(args terminals) + (let ((namespaced-variable + (format + "%s id %s" + phps-mode-parser-sdt-bookkeeping-namespace + args))) + + ;; Bookkeep whether we hit or miss the variable + (if (gethash + namespaced-variable + phps-mode-parser-sdt-bookkeeping) + (puthash + (list + (car (cdr terminals)) + (cdr (cdr terminals))) + 1 + phps-mode-parser-sdt-bookkeeping) + (puthash + (list + (car (cdr terminals)) + (cdr (cdr terminals))) + 0 + phps-mode-parser-sdt-bookkeeping)) + + ;; Declare variable + (unless (gethash + namespaced-variable + phps-mode-parser-sdt-bookkeeping) + + ;; TODO Should not declare in this production + (puthash + namespaced-variable + 1 + phps-mode-parser-sdt-bookkeeping) + (message "Declared variable") + ) + ;; Flag whether we hit or missed variable in the bookkeeping here + ) + (message "args: %S" args) + (message "terminals: %S" terminals) `( ast-type simple-variable-variable