]> gitweb.factorcode.org Git - factor.git/blob - misc/fuel/fuel-eval.el
0e84e60ec813c07332cc7088e44d0e432788add7
[factor.git] / misc / fuel / fuel-eval.el
1 ;;; fuel-eval.el --- evaluating Factor expressions
2
3 ;; Copyright (C) 2008, 2009  Jose Antonio Ortega Ruiz
4 ;; See http://factorcode.org/license.txt for BSD license.
5
6 ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
7 ;; Keywords: languages
8 ;; Start date: Tue Dec 02, 2008
9
10 ;;; Commentary:
11
12 ;; Protocols for sending evaluations to the Factor listener.
13
14 ;;; Code:
15
16 (require 'fuel-connection)
17 (require 'fuel-log)
18 (require 'fuel-base)
19 (require 'factor-mode)
20
21 (require 'cl-lib)
22
23 \f
24 ;;; Simple sexp-based representation of factor code
25
26 (defun factor (sexp)
27   (cond ((null sexp) "f")
28         ((eq sexp t) "t")
29         ((or (stringp sexp) (numberp sexp)) (format "%S" sexp))
30         ((vectorp sexp) (factor (cons :quotation (append sexp nil))))
31         ((listp sexp)
32          (cl-case (car sexp)
33            (:array (factor--seq 'V{ '} (cdr sexp)))
34            (:seq (factor--seq '{ '} (cdr sexp)))
35            (:tuple (factor--seq 'T{ '} (cdr sexp)))
36            (:quote (format "\\ %s" (factor `(:factor ,(cadr sexp)))))
37            (:quotation (factor--seq '\[ '\] (cdr sexp)))
38            (:using (factor `(USING: ,@(cdr sexp) :end)))
39            (:factor (format "%s" (mapconcat 'identity (cdr sexp) " ")))
40            (:fuel (factor--fuel-factor (cons :rs (cdr sexp))))
41            (:fuel* (factor--fuel-factor (cons :nrs (cdr sexp))))
42            (t (mapconcat 'factor sexp " "))))
43         ((keywordp sexp)
44          (factor (cl-case sexp
45                    (:rs 'fuel-eval-restartable)
46                    (:nrs 'fuel-eval-non-restartable)
47                    (:in (or (factor-current-vocab) "fuel"))
48                    (:usings `(:array ,@(factor-usings)))
49                    (:get 'fuel-eval-set-result)
50                    (:end '\;)
51                    (t `(:factor ,(symbol-name sexp))))))
52         ((symbolp sexp) (symbol-name sexp))))
53
54 (defsubst factor--seq (begin end forms)
55   (format "%s %s %s" begin (if forms (factor forms) "") end))
56
57 (defsubst factor--fuel-factor (sexp)
58   (factor `(,(factor--fuel-restart (nth 0 sexp))
59             ,(factor--fuel-lines (nth 1 sexp))
60             ,(factor--fuel-in (nth 2 sexp))
61             ,(factor--fuel-usings (nth 3 sexp))
62             fuel-eval-in-context)))
63
64 (defsubst factor--fuel-restart (rs)
65   (unless (member rs '(:rs :nrs))
66     (error "Invalid restart spec (%s)" rs))
67   rs)
68
69 (defsubst factor--fuel-lines (lst)
70   (cons :array (mapcar 'factor lst)))
71
72 (defsubst factor--fuel-in (in)
73   (cond ((or (eq in :in) (null in)) :in)
74         ((eq in 'f) 'f)
75         ((eq in 't) "fuel")
76         ((stringp in) in)
77         (t (error "Invalid 'in' (%s)" in))))
78
79 (defsubst factor--fuel-usings (usings)
80   (cond ((or (null usings) (eq usings :usings)) :usings)
81         ((eq usings t) nil)
82         ((listp usings) `(:array ,@usings))
83         (t (error "Invalid 'usings' (%s)" usings))))
84
85 \f
86 ;;; Code sending:
87
88 (defvar fuel-eval--default-proc-function nil)
89 (defsubst fuel-eval--default-proc ()
90   (and fuel-eval--default-proc-function
91        (funcall fuel-eval--default-proc-function)))
92
93 (defvar fuel-eval--proc nil)
94
95 (defvar fuel-eval--sync-retort nil)
96
97 (defun fuel-eval--send/wait (code &optional timeout buffer)
98   (setq fuel-eval--sync-retort nil)
99   (fuel-con--send-string/wait (or fuel-eval--proc (fuel-eval--default-proc))
100                               (if (stringp code) code (factor code))
101                               #'(lambda (s)
102                                  (setq fuel-eval--sync-retort
103                                        (fuel-eval--parse-retort s)))
104                               timeout
105                               buffer)
106   fuel-eval--sync-retort)
107
108 (defun fuel-eval--send (code cont &optional buffer)
109   (fuel-con--send-string (or fuel-eval--proc (fuel-eval--default-proc))
110                          (if (stringp code) code (factor code))
111                          `(lambda (s) (,cont (fuel-eval--parse-retort s)))
112                          buffer))
113
114 \f
115 ;;; Retort and retort-error datatypes:
116
117 (defsubst fuel-eval--retort-make (err result &optional output)
118   (list err result output))
119
120 (defsubst fuel-eval--retort-error (ret) (nth 0 ret))
121 (defsubst fuel-eval--retort-result (ret) (nth 1 ret))
122 (defsubst fuel-eval--retort-output (ret) (nth 2 ret))
123
124 (defun fuel-eval--retort-result-safe (ret)
125   "Retort result or throws an error if the retort error is set."
126   (let ((err (fuel-eval--retort-error ret)))
127     (when err (error "%s" err))
128     (fuel-eval--retort-result ret)))
129
130 (defsubst fuel-eval--retort-p (ret)
131   (and (listp ret) (= 3 (length ret))))
132
133 (defun fuel-eval--parse-retort (ret)
134   (fuel-log--info "RETORT: %S" ret)
135   (if (fuel-eval--retort-p ret)
136       ret
137     (list ret nil nil)))
138
139 (defsubst fuel-eval--error-name (err) (car err))
140
141 (defun fuel-eval--error-name-p (err name)
142   (unless (null err)
143     (or (and (eq (fuel-eval--error-name err) name) err)
144         (assoc name err))))
145
146 (defsubst fuel-eval--error-restarts (err)
147   (alist-get :restarts (or (fuel-eval--error-name-p err 'condition)
148                            (fuel-eval--error-name-p err 'lexer-error))))
149
150 (defsubst fuel-eval--error-file (err)
151   (nth 1 (fuel-eval--error-name-p err 'source-file-error)))
152
153 (defsubst fuel-eval--error-lexer-p (err)
154   (or (fuel-eval--error-name-p err 'lexer-error)
155       (fuel-eval--error-name-p (fuel-eval--error-name-p err 'source-file-error)
156                                'lexer-error)))
157
158 (defsubst fuel-eval--error-line/column (err)
159   (let ((err (fuel-eval--error-lexer-p err)))
160     (cons (nth 1 err) (nth 2 err))))
161
162 (defsubst fuel-eval--error-line-text (err)
163   (nth 3 (fuel-eval--error-lexer-p err)))
164
165 \f
166 (provide 'fuel-eval)
167 ;;; fuel-eval.el ends here