Skip to content

Commit

Permalink
Merge pull request #133 from countvajhula/fixes-in-primitives-and-del…
Browse files Browse the repository at this point in the history
…etion

Fixes in primitives and deletion
  • Loading branch information
countvajhula authored Jun 14, 2024
2 parents 23c01d5 + 77c50df commit bab9c37
Show file tree
Hide file tree
Showing 14 changed files with 232 additions and 130 deletions.
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ As of Jan 2023, there is "alpha" support for non-Lisp languages via ``tree-sitte
<img src="https://user-images.githubusercontent.com/401668/59328521-6db96280-8ca1-11e9-8b32-24574a0af676.png" alt="Screenshot" title="Screenshot" style="cursor:default;"/>
</p>

.. [1] As long as, from a theoretical perspective, the intended traversal can be accomplished using a `finite automaton <https://en.wikipedia.org/wiki/Deterministic_finite_automaton>`_. More complex traversals can be implemented (such as "leap branch"), but not as easily. Symex may be made Turing-complete at some point in the future, if there is interest in a feature that cannot be implemented in the DSL in its current form.
.. [1] As long as, from a theoretical perspective, the intended traversal can be accomplished using a `pushdown automaton <https://en.wikipedia.org/wiki/Pushdown_automaton>`_. That is, Symex is more expressive than regular expressions but less expressive than Lisp itself.
Installation
============
Expand Down
2 changes: 1 addition & 1 deletion symex-computations.el
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ computation (each of the 'expressed' type) to yield the final result
"The act procedure of the COMPUTATION."
(nth 7 computation))

(defun symex-compute-results (a b computation)
(defun symex-compose-computation (a b computation)
"Compose traversal results according to COMPUTATION.
Combine the result of a traversal computation A with the accumulated
Expand Down
5 changes: 5 additions & 0 deletions symex-custom.el
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
:type 'boolean
:group 'symex)

(defcustom symex-toggle-blink-cursor t
"Whether to disable cursor blinking while in Symex state."
:type 'boolean
:group 'symex)

(defcustom symex-remember-branch-positions-p t
"Whether movement in the vertical direction should remember branch positions."
:type 'boolean
Expand Down
6 changes: 3 additions & 3 deletions symex-dsl.el
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,9 @@ TRAVERSAL - the traversal to perform. This could be any traversal. If
no traversal is specified, then the traversal is treated as the zero
move, making this a pure side effect."
`(symex-make-effect (lambda () ,effect)
(if ,traversal
(symex-traversal ,traversal)
symex--move-zero)))
,(if traversal
`(symex-traversal ,traversal)
symex--move-zero)))

;; TODO: support args here like lambda / defun (i.e. as a list in the
;; binding form -- not passed in but syntactically inserted)
Expand Down
8 changes: 4 additions & 4 deletions symex-evaluator.el
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,10 @@ Optional argument COMPUTATION currently unused."
(funcall (symex--computation-perceive computation)
symex--move-zero))))
(when executed-move
(symex-compute-results result
(funcall (symex--computation-perceive computation)
executed-move)
computation))))
(symex-compose-computation result
(funcall (symex--computation-perceive computation)
executed-move)
computation))))

(defun symex-execute-maneuver (maneuver computation result)
"Attempt to execute a given MANEUVER.
Expand Down
2 changes: 2 additions & 0 deletions symex-misc.el
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ ORIG-FN applied to ARGS is the invocation being advised."
(unless (member evil-next-state '(emacslike normallike))
;; these are "internal" state transitions, used in e.g. symex-evaluate
(deactivate-mark)
(when symex--original-blink-cursor-state
(blink-cursor-mode 1))
(when symex-refocus-p
(symex--restore-scroll-margin))
(symex--primitive-exit)))
Expand Down
48 changes: 34 additions & 14 deletions symex-primitives-lisp.el
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,12 @@
(defvar symex--re-blank-line "^[[:space:]]*$"
"A blank line, either empty or containing only whitespace.")

(defvar symex--re-whitespace "[[:space:]|\n]*"
(defvar symex--re-whitespace "[[:space:]|\n]+"
"Whitespace that may extend over many lines.")

(defvar symex--re-optional-whitespace "[[:space:]|\n]*"
"Optional whitespace that may extend over many lines.")

(defvar symex--re-symex-line "^[[:space:]]*[^;[:space:]\n]"
"A line that isn't blank and isn't a comment line.")

Expand Down Expand Up @@ -211,6 +214,10 @@
(cond ((looking-at "\\s(") (forward-list 1) (backward-char 1))
((looking-at "\\s)") (forward-char 1) (backward-list 1))))

(defun symex-whitespace-p ()
"Check if we're looking at whitespace."
(looking-at-p symex--re-whitespace))

(defun symex-comment-line-p ()
"Check if we're currently at the start of a comment line."
(save-excursion
Expand Down Expand Up @@ -241,7 +248,7 @@
"Check if we're looking at an empty list."
(looking-at-p
(concat symex--re-left
symex--re-whitespace
symex--re-optional-whitespace
symex--re-right)))

(defun symex-empty-string-p ()
Expand All @@ -254,10 +261,10 @@
(defun symex-inside-empty-form-p ()
"Check if point is inside an empty form."
(and (looking-back (concat symex--re-left
symex--re-whitespace)
symex--re-optional-whitespace)
(line-beginning-position))
(looking-at-p
(concat symex--re-whitespace
(concat symex--re-optional-whitespace
symex--re-right))))

(defun symex--racket-syntax-object-p ()
Expand Down Expand Up @@ -404,18 +411,31 @@ symexes, returns the end point of the last one found.
Note that this mutates point - it should not be called directly."
(if (= count 0)
(point)
(condition-case nil
(forward-sexp)
(error (point)))
(symex-lisp--get-end-point-helper (1- count))))

(defun symex-lisp--get-end-point (count)
(let ((at-end (condition-case nil
(progn (forward-sexp)
nil)
(error t))))
(if at-end
(error "Out of range!")
(symex-lisp--get-end-point-helper (1- count))))))

(defun symex-lisp--get-end-point (count &optional include-whitespace)
"Get the point value after COUNT symexes.
If the containing expression terminates earlier than COUNT
symexes, returns the end point of the last one found."
symexes, returns the end point of the last one found.
If include-whitespace is non-nil, this returns the end point
including trailing whitespace at the end of the last symex."
(save-excursion
(symex-lisp--get-end-point-helper count)))
(let ((endpoint (symex-lisp--get-end-point-helper count)))
(if include-whitespace
(progn (goto-char endpoint)
(if (and (not (eobp))
(symex-whitespace-p))
(1+ endpoint)
endpoint))
endpoint))))

(defun symex-lisp--point-height-offset ()
"Compute the height offset of the current symex.
Expand Down Expand Up @@ -636,7 +656,7 @@ line."
(symex--previous-line-empty-p))
(symex--join-to-next)
;; don't leave an empty line where the symex was
(symex--kill-whole-line)))
(symex--delete-whole-line)))
((or (save-excursion (evil-last-non-blank) ; (<>$
(symex-left-p)))
(symex--join-to-next))
Expand Down Expand Up @@ -666,7 +686,7 @@ line."
(error nil))
(symex--join-to-match symex--re-right))))))))
((symex-right-p) (fixup-whitespace)) ; abc <>)
(t (symex--join-to-non-whitespace))))
(t nil)))

;;; Utilities

Expand Down
51 changes: 28 additions & 23 deletions symex-primitives.el
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ This is a low-level utility that simply removes the indicated text
from the buffer."
(let ((last-command nil) ; see symex-yank re: last-command
(start (point))
(end (symex--get-end-point count)))
(end (symex--get-end-point count t)))
(when (> end start)
(kill-region start end)
t)))
Expand Down Expand Up @@ -250,26 +250,24 @@ from the buffer."
WHAT could be `this`, `next`, or `previous`."
(let ((result))
(cond ((eq 'this what)
(setq result (symex-remove 1)))
((eq 'previous what)
(when (symex--previous-p)
;; not sure how reliable `save-excursion` is when
;; the buffer is being mutated. If we encounter
;; any issues we could try `symex--save-point-excursion`
;; or otherwise, note the bounds of the mutated region
;; and manually preserve point where we need it, or
;; if necessary, preserve point structurally by using
;; a primitive version of `symex-index`.
(symex-save-excursion
(symex--go-backward)
(setq result (symex-remove 1)))))
((eq 'next what)
(when (symex--next-p)
(save-excursion
(symex--go-forward)
(setq result (symex-remove 1)))))
(t (error "Invalid argument for primitive delete!")))
(condition-case nil
(cond ((eq 'this what)
(setq result (symex-remove 1)))
((eq 'previous what)
(when (symex--previous-p)
(symex--go-backward)
(setq result (symex-remove 1))))
((eq 'next what)
(when (symex--next-p)
(save-excursion
(symex--go-forward)
(setq result (symex-remove 1)))))
(t (error "Invalid argument for primitive delete!")))
;; if unable to delete, return nil instead of
;; raising an error. nil is used in the evaluator
;; to mean failed, so the traversal would stop there
;; as expected.
(error nil))
result))

(defun symex-prim-paste (where)
Expand Down Expand Up @@ -327,14 +325,21 @@ difference from the lowest such level."
(symex-ts--get-starting-point)
(symex-lisp--get-starting-point)))

(defun symex--get-end-point (count)
(defun symex--get-end-point (count &optional include-whitespace)
"Get the point value after COUNT symexes.
If the containing expression terminates earlier than COUNT
symexes, returns the end point of the last one found."
(if (symex-tree-sitter-p)
;; TODO: implement include-whitespace for ts
(symex-ts--get-end-point count)
(symex-lisp--get-end-point count)))
(symex-lisp--get-end-point count include-whitespace)))

(defun symex--get-bounds (count &optional include-whitespace)
"Get the start and end points of COUNT symexes."
(let ((start (symex--get-starting-point))
(end (symex--get-end-point count include-whitespace)))
(cons start end)))

(defun symex-select-end (count)
"Select endpoint of symex nearest to point."
Expand Down
Loading

0 comments on commit bab9c37

Please sign in to comment.