Commit | Line | Data |
---|---|---|
86fbb8ca CD |
1 | ;;; ob-ocaml.el --- org-babel functions for ocaml evaluation |
2 | ||
cbd20947 | 3 | ;; Copyright (C) 2009-2011 Free Software Foundation, Inc. |
86fbb8ca CD |
4 | |
5 | ;; Author: Eric Schulte | |
6 | ;; Keywords: literate programming, reproducible research | |
7 | ;; Homepage: http://orgmode.org | |
3ab2c837 | 8 | ;; Version: 7.7 |
86fbb8ca CD |
9 | |
10 | ;; This file is part of GNU Emacs. | |
11 | ||
12 | ;; GNU Emacs is free software: you can redistribute it and/or modify | |
13 | ;; it under the terms of the GNU General Public License as published by | |
14 | ;; the Free Software Foundation, either version 3 of the License, or | |
15 | ;; (at your option) any later version. | |
16 | ||
17 | ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 | ;; GNU General Public License for more details. | |
21 | ||
22 | ;; You should have received a copy of the GNU General Public License | |
23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | |
24 | ||
25 | ;;; Commentary: | |
26 | ||
27 | ;; Org-Babel support for evaluating ocaml source code. This one will | |
28 | ;; be sort of tricky because ocaml programs must be compiled before | |
29 | ;; they can be run, but ocaml code can also be run through an | |
30 | ;; interactive interpreter. | |
31 | ;; | |
c7015153 | 32 | ;; For now let's only allow evaluation using the ocaml interpreter. |
86fbb8ca CD |
33 | |
34 | ;;; Requirements: | |
35 | ||
36 | ;; - tuareg-mode :: http://www-rocq.inria.fr/~acohen/tuareg/ | |
37 | ||
38 | ;;; Code: | |
39 | (require 'ob) | |
40 | (require 'ob-comint) | |
41 | (require 'comint) | |
42 | (eval-when-compile (require 'cl)) | |
43 | ||
44 | (declare-function tuareg-run-caml "ext:tuareg" ()) | |
45 | (declare-function tuareg-interactive-send-input "ext:tuareg" ()) | |
46 | ||
3ab2c837 | 47 | (defvar org-babel-tangle-lang-exts) |
86fbb8ca CD |
48 | (add-to-list 'org-babel-tangle-lang-exts '("ocaml" . "ml")) |
49 | ||
50 | (defvar org-babel-default-header-args:ocaml '()) | |
51 | ||
52 | (defvar org-babel-ocaml-eoe-indicator "\"org-babel-ocaml-eoe\";;") | |
53 | (defvar org-babel-ocaml-eoe-output "org-babel-ocaml-eoe") | |
54 | ||
86fbb8ca CD |
55 | (defun org-babel-execute:ocaml (body params) |
56 | "Execute a block of Ocaml code with Babel." | |
afe98dfa CD |
57 | (let* ((vars (mapcar #'cdr (org-babel-get-header params :var))) |
58 | (full-body (org-babel-expand-body:generic | |
59 | body params | |
60 | (org-babel-variable-assignments:ocaml params))) | |
86fbb8ca CD |
61 | (session (org-babel-prep-session:ocaml |
62 | (cdr (assoc :session params)) params)) | |
63 | (raw (org-babel-comint-with-output | |
64 | (session org-babel-ocaml-eoe-output t full-body) | |
65 | (insert | |
66 | (concat | |
67 | (org-babel-chomp full-body)"\n"org-babel-ocaml-eoe-indicator)) | |
68 | (tuareg-interactive-send-input))) | |
69 | (clean | |
70 | (car (let ((re (regexp-quote org-babel-ocaml-eoe-output)) out) | |
71 | (delq nil (mapcar (lambda (line) | |
72 | (if out | |
73 | (progn (setq out nil) line) | |
74 | (when (string-match re line) | |
75 | (progn (setq out t) nil)))) | |
76 | (mapcar #'org-babel-trim (reverse raw)))))))) | |
77 | (org-babel-reassemble-table | |
78 | (org-babel-ocaml-parse-output (org-babel-trim clean)) | |
79 | (org-babel-pick-name | |
afe98dfa | 80 | (cdr (assoc :colname-names params)) (cdr (assoc :colnames params))) |
86fbb8ca | 81 | (org-babel-pick-name |
afe98dfa | 82 | (cdr (assoc :rowname-names params)) (cdr (assoc :rownames params)))))) |
86fbb8ca CD |
83 | |
84 | (defvar tuareg-interactive-buffer-name) | |
85 | (defun org-babel-prep-session:ocaml (session params) | |
86 | "Prepare SESSION according to the header arguments in PARAMS." | |
87 | (require 'tuareg) | |
88 | (let ((tuareg-interactive-buffer-name (if (and (not (string= session "none")) | |
89 | (not (string= session "default")) | |
90 | (stringp session)) | |
91 | session | |
92 | tuareg-interactive-buffer-name))) | |
93 | (save-window-excursion (tuareg-run-caml) | |
94 | (get-buffer tuareg-interactive-buffer-name)))) | |
95 | ||
afe98dfa CD |
96 | (defun org-babel-variable-assignments:ocaml (params) |
97 | "Return list of ocaml statements assigning the block's variables" | |
98 | (mapcar | |
99 | (lambda (pair) (format "let %s = %s;;" (car pair) | |
100 | (org-babel-ocaml-elisp-to-ocaml (cdr pair)))) | |
101 | (mapcar #'cdr (org-babel-get-header params :var)))) | |
c7015153 | 102 | |
86fbb8ca CD |
103 | (defun org-babel-ocaml-elisp-to-ocaml (val) |
104 | "Return a string of ocaml code which evaluates to VAL." | |
105 | (if (listp val) | |
106 | (concat "[|" (mapconcat #'org-babel-ocaml-elisp-to-ocaml val "; ") "|]") | |
107 | (format "%S" val))) | |
108 | ||
109 | (defun org-babel-ocaml-parse-output (output) | |
110 | "Parse OUTPUT. | |
111 | OUTPUT is string output from an ocaml process." | |
112 | (let ((regexp "%s = \\(.+\\)$")) | |
113 | (cond | |
114 | ((string-match (format regexp "string") output) | |
115 | (org-babel-read (match-string 1 output))) | |
116 | ((or (string-match (format regexp "int") output) | |
117 | (string-match (format regexp "float") output)) | |
118 | (string-to-number (match-string 1 output))) | |
119 | ((string-match (format regexp "list") output) | |
120 | (org-babel-ocaml-read-list (match-string 1 output))) | |
121 | ((string-match (format regexp "array") output) | |
122 | (org-babel-ocaml-read-array (match-string 1 output))) | |
123 | (t (message "don't recognize type of %s" output) output)))) | |
124 | ||
125 | (defun org-babel-ocaml-read-list (results) | |
126 | "Convert RESULTS into an elisp table or string. | |
127 | If the results look like a table, then convert them into an | |
128 | Emacs-lisp table, otherwise return the results as a string." | |
3ab2c837 | 129 | (org-babel-script-escape (replace-regexp-in-string ";" "," results))) |
86fbb8ca CD |
130 | |
131 | (defun org-babel-ocaml-read-array (results) | |
132 | "Convert RESULTS into an elisp table or string. | |
133 | If the results look like a table, then convert them into an | |
134 | Emacs-lisp table, otherwise return the results as a string." | |
3ab2c837 BG |
135 | (org-babel-script-escape |
136 | (replace-regexp-in-string | |
137 | "\\[|" "[" (replace-regexp-in-string | |
138 | "|\\]" "]" (replace-regexp-in-string | |
139 | "; " "," results))))) | |
86fbb8ca CD |
140 | |
141 | (provide 'ob-ocaml) | |
142 | ||
5b409b39 | 143 | |
86fbb8ca CD |
144 | |
145 | ;;; ob-ocaml.el ends here |