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