diff options
author | RĂ¼diger Sonderfeld <ruediger@c-plusplus.de> | 2013-06-06 19:49:03 +0200 |
---|---|---|
committer | Eric Schulte <schulte.eric@gmail.com> | 2013-06-06 12:06:26 -0600 |
commit | cdfcc064d267b795287bc1bff8796e65450dece6 (patch) | |
tree | 4521a6e02e09c7fb97212c252353cfcfa44d001c | |
parent | d57855655711e654828fee1fda6f9d2f075209a4 (diff) | |
download | org-mode-cdfcc064d267b795287bc1bff8796e65450dece6.tar.gz |
ob-C: Add list support.
* lisp/ob-C.el (org-babel-C-var-to-C): Add list support
(org-babel-C-val-to-C-list-type, org-babel-C-val-to-C-type,
org-babel-C-format-val): New functions.
(org-babel-C-ensure-main-wrap, org-babel-execute:C,
org-babel-execute:C++, rg-babel-execute:cpp, org-babel-C++-compiler,
org-babel-C-compiler): Improve docstring.
* testing/examples/ob-C-test.org (string_var): Add required std::
(Array): Add missing ID.
(Matrix): Add tests for list support.
* testing/lisp/test-ob-C.el (ob-C/table): Test succeeds.
(ob-C/list-var, ob-C/vector-var, ob-C/list-list-var): Add tests for
list support.
Signed-off-by: RĂ¼diger Sonderfeld <ruediger@c-plusplus.de>
-rw-r--r-- | lisp/ob-C.el | 98 | ||||
-rw-r--r-- | testing/examples/ob-C-test.org | 28 | ||||
-rw-r--r-- | testing/lisp/test-ob-C.el | 20 |
3 files changed, 118 insertions, 28 deletions
diff --git a/lisp/ob-C.el b/lisp/ob-C.el index b1e8a06..e9eec93 100644 --- a/lisp/ob-C.el +++ b/lisp/ob-C.el @@ -44,24 +44,24 @@ (defvar org-babel-C-compiler "gcc" "Command used to compile a C source code file into an - executable.") +executable.") (defvar org-babel-C++-compiler "g++" "Command used to compile a C++ source code file into an - executable.") +executable.") (defvar org-babel-c-variant nil "Internal variable used to hold which type of C (e.g. C or C++) is currently being evaluated.") (defun org-babel-execute:cpp (body params) - "Execute BODY according to PARAMS. This function calls -`org-babel-execute:C++'." + "Execute BODY according to PARAMS. +This function calls `org-babel-execute:C++'." (org-babel-execute:C++ body params)) (defun org-babel-execute:C++ (body params) - "Execute a block of C++ code with org-babel. This function is -called by `org-babel-execute-src-block'." + "Execute a block of C++ code with org-babel. +This function is called by `org-babel-execute-src-block'." (let ((org-babel-c-variant 'cpp)) (org-babel-C-execute body params))) (defun org-babel-expand-body:C++ (body params) @@ -70,8 +70,8 @@ header arguments (calls `org-babel-C-expand')." (let ((org-babel-c-variant 'cpp)) (org-babel-C-expand body params))) (defun org-babel-execute:C (body params) - "Execute a block of C code with org-babel. This function is -called by `org-babel-execute-src-block'." + "Execute a block of C code with org-babel. +This function is called by `org-babel-execute-src-block'." (let ((org-babel-c-variant 'c)) (org-babel-C-execute body params))) (defun org-babel-expand-body:c (body params) @@ -146,10 +146,10 @@ it's header arguments." body) "\n") "\n"))) (defun org-babel-C-ensure-main-wrap (body) - "Wrap body in a \"main\" function call if none exists." + "Wrap BODY in a \"main\" function call if none exists." (if (string-match "^[ \t]*[intvod]+[ \t\n\r]*main[ \t]*(.*)" body) body - (format "int main() {\n%s\nreturn(0);\n}\n" body))) + (format "int main() {\n%s\nreturn 0;\n}\n" body))) (defun org-babel-prep-session:C (session params) "This function does nothing as C is a compiled language with no @@ -163,6 +163,59 @@ support for sessions" ;; helper functions +(defun org-babel-C-format-val (type val) + "Handle the FORMAT part of TYPE with the data from VAL." + (let ((format-data (cadr type))) + (if (stringp format-data) + (cons "" (format format-data val)) + (funcall format-data val)))) + +(defun org-babel-C-val-to-C-type (val) + "Determine the type of VAL. +Return a list (TYPE-NAME FORMAT). TYPE-NAME should be the name of the type. +FORMAT can be either a format string or a function which is called with VAL." + (cond + ((integerp val) '("int" "%d")) + ((floatp val) '("double" "%f")) + ((or (listp val) (vectorp val)) + (lexical-let ((type (org-babel-C-val-to-C-list-type val))) + (list (car type) + (lambda (val) + (cons + (format "[%d]%s" + (length val) + (car (org-babel-C-format-val type (elt val 0)))) + (concat "{ " + (mapconcat (lambda (v) + (cdr (org-babel-C-format-val type v))) + val + ", ") + " }")))))) + (t ;; treat unknown types as string + '("char" (lambda (val) + (let ((s (format "%s" val))) ;; convert to string for unknown types + (cons (format "[%d]" (1+ (length s))) + (concat "\"" s "\"")))))))) + +(defun org-babel-C-val-to-C-list-type (val) + "Determine the C array type of a VAL." + (let (type) + (mapc + #'(lambda (i) + (let* ((tmp-type (org-babel-C-val-to-C-type i)) + (type-name (car type)) + (tmp-type-name (car tmp-type))) + (when (and type (not (string= type-name tmp-type-name))) + (if (and (member type-name '("int" "double" "int32_t")) + (member tmp-type-name '("int" "double" "int32_t"))) + (setq tmp-type '("double" "" "%f")) + (error "Only homogeneous lists are supported by C. You can not mix %s and %s" + type-name + tmp-type-name))) + (setq type tmp-type))) + val) + type)) + (defun org-babel-C-var-to-C (pair) "Convert an elisp val into a string of C code specifying a var of the same value." @@ -173,22 +226,17 @@ of the same value." (setq val (symbol-name val)) (when (= (length val) 1) (setq val (string-to-char val)))) - (cond - ((integerp val) - (format "int %S = %S;" var val)) - ((floatp val) - (format "double %S = %S;" var val)) - ((or (integerp val)) - (format "char %S = '%S';" var val)) - ((stringp val) - (format "char %S[%d] = \"%s\";" - var (+ 1 (length val)) val)) - (t - (format "u32 %S = %S;" var val))))) - + (let* ((type-data (org-babel-C-val-to-C-type val)) + (type (car type-data)) + (formated (org-babel-C-format-val type-data val)) + (suffix (car formated)) + (data (cdr formated))) + (format "%s %s%s = %s;" + type + var + suffix + data)))) (provide 'ob-C) - - ;;; ob-C.el ends here diff --git a/testing/examples/ob-C-test.org b/testing/examples/ob-C-test.org index 32ab88b..1d0a83f 100644 --- a/testing/examples/ob-C-test.org +++ b/testing/examples/ob-C-test.org @@ -24,7 +24,7 @@ #+source: string_var #+begin_src cpp :var q="word" :includes '(<iostream> <cstring>) :results silent - std::cout << q << ' ' << strlen(q); + std::cout << q << ' ' << std::strlen(q); return 0; #+end_src @@ -35,6 +35,9 @@ #+end_src * Array + :PROPERTIES: + :ID: 2df1ab83-3fa3-462a-a1f3-3aef6044a874 + :END: #+source: array #+begin_src cpp :includes "<iostream>" :results vector :results silent for (int i=1; i<3; i++) { @@ -42,3 +45,26 @@ } return 0; #+end_src +* Matrix + :PROPERTIES: + :ID: cc65d6b3-8e8e-4f9c-94cd-f5a00cdeceb5 + :END: +#+name: C-matrix +| 1 | 2 | +| 3 | 4 | + +#+source: list_var +#+begin_src cpp :var a='("abc" "def") :includes "<iostream>" :results silent + std::cout << a[0] << a[1] << sizeof(a)/sizeof(*a) << '\n'; +#+end_src + +#+source: vector_var +#+begin_src cpp :var a='[1 2] :includes "<iostream>" :results silent + std::cout << a[0] << a[1] << sizeof(a)/sizeof(*a) << '\n'; +#+end_src + +#+source: list_list_var +#+begin_src cpp :var q=C-matrix :includes "<iostream>" :results silent + std::cout << q[0][0] << ' ' << q[1][0] << '\n' + << q[0][1] << ' ' << q[1][1] << '\n'; // transpose +#+end_src diff --git a/testing/lisp/test-ob-C.el b/testing/lisp/test-ob-C.el index 4243bb6..4430ceb 100644 --- a/testing/lisp/test-ob-C.el +++ b/testing/lisp/test-ob-C.el @@ -57,10 +57,26 @@ (ert-deftest ob-C/table () "Test of a table output" - :expected-result :failed (org-test-at-id "2df1ab83-3fa3-462a-a1f3-3aef6044a874" (org-babel-next-src-block) (should (equal '((1) (2)) (org-babel-execute-src-block))))) +(ert-deftest ob-C/list-var () +"Test of a list input variable" + (org-test-at-id "cc65d6b3-8e8e-4f9c-94cd-f5a00cdeceb5" + (org-babel-next-src-block 1) + (should (string= "abcdef2" (org-babel-execute-src-block))))) + +(ert-deftest ob-C/vector-var () +"Test of a vector input variable" + (org-test-at-id "cc65d6b3-8e8e-4f9c-94cd-f5a00cdeceb5" + (org-babel-next-src-block 2) + (should (equal 122 (org-babel-execute-src-block))))) + +(ert-deftest ob-C/list-list-var () + "Test of a list list input variable" + (org-test-at-id "cc65d6b3-8e8e-4f9c-94cd-f5a00cdeceb5" + (org-babel-next-src-block 3) + (should (equal '((1 3) (2 4)) (org-babel-execute-src-block))))) + ;;; test-ob-C.el ends here - |