Commit | Line | Data |
---|---|---|
86fbb8ca CD |
1 | ;;; ob-ocaml.el --- org-babel functions for ocaml evaluation |
2 | ||
73b0cd50 | 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 | |
acedf35c | 8 | ;; Version: 7.4 |
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 | ;; | |
32 | ;; For now lets only allow evaluation using the ocaml interpreter. | |
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 | ||
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)))) | |
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." | |
128 | (org-babel-read | |
129 | (if (and (stringp results) (string-match "^\\[.+\\]$" results)) | |
130 | (org-babel-read | |
131 | (replace-regexp-in-string | |
132 | "\\[" "(" (replace-regexp-in-string | |
133 | "\\]" ")" (replace-regexp-in-string | |
134 | "; " " " (replace-regexp-in-string | |
135 | "'" "\"" results))))) | |
136 | results))) | |
137 | ||
138 | (defun org-babel-ocaml-read-array (results) | |
139 | "Convert RESULTS into an elisp table or string. | |
140 | If the results look like a table, then convert them into an | |
141 | Emacs-lisp table, otherwise return the results as a string." | |
142 | (org-babel-read | |
143 | (if (and (stringp results) (string-match "^\\[.+\\]$" results)) | |
144 | (org-babel-read | |
145 | (concat | |
146 | "'" (replace-regexp-in-string | |
147 | "\\[|" "(" (replace-regexp-in-string | |
148 | "|\\]" ")" (replace-regexp-in-string | |
149 | "; " " " (replace-regexp-in-string | |
150 | "'" "\"" results)))))) | |
151 | results))) | |
152 | ||
153 | (provide 'ob-ocaml) | |
154 | ||
86fbb8ca CD |
155 | |
156 | ;;; ob-ocaml.el ends here |