Skip to content
Snippets Groups Projects
Commit 2e5cd290 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Improve doc

parent 20794e72
No related branches found
No related tags found
1 merge request!145git subrepo clone git@gitlab.com:OlMon/org-themes.git packages/org-themes
...@@ -22,6 +22,7 @@ if (EMACS) ...@@ -22,6 +22,7 @@ if (EMACS)
"${PUGS_SOURCE_DIR}/doc/lisp/build-doc-config.el" "${PUGS_SOURCE_DIR}/doc/lisp/build-doc-config.el"
"${PUGS_SOURCE_DIR}/doc/lisp/share/pugs.el" "${PUGS_SOURCE_DIR}/doc/lisp/share/pugs.el"
"${PUGS_SOURCE_DIR}/doc/lisp/share/ob-pugs.el" "${PUGS_SOURCE_DIR}/doc/lisp/share/ob-pugs.el"
"${PUGS_SOURCE_DIR}/doc/lisp/share/ob-pugs-error.el"
) )
add_custom_command( add_custom_command(
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
(custom-set-variables (custom-set-variables
'(org-export-html-postamble nil) '(org-export-html-postamble nil)
;; By now pugs is not known by Pygments raw text is better ;; By now pugs is not known by Pygments raw text is better
'(org-latex-minted-langs '((pugs "Text"))) '(org-latex-minted-langs '((pugs "Text") (pugs-error "Text")))
'(org-confirm-babel-evaluate nil) '(org-confirm-babel-evaluate nil)
'(org-html-validation-link nil) '(org-html-validation-link nil)
'(org-src-fontify-natively t) '(org-src-fontify-natively t)
...@@ -77,9 +77,16 @@ ...@@ -77,9 +77,16 @@
(load-library "${HOME}/share/pugs.el") (load-library "${HOME}/share/pugs.el")
(require 'pugs-mode) (require 'pugs-mode)
;; allow to use pugs mode when dealing with invalid examples
(define-derived-mode pugs-error-mode pugs-mode "pugs-error"
"pugs-error mode "
)
(add-to-list 'auto-mode-alist '("\\.pgs?\\'" . pugs-mode)) (add-to-list 'auto-mode-alist '("\\.pgs?\\'" . pugs-mode))
(load-library "${HOME}/share/ob-pugs.el") (load-library "${HOME}/share/ob-pugs.el")
(require 'ob-pugs) (require 'ob-pugs)
(load-library "${HOME}/share/ob-pugs-error.el")
(require 'ob-pugs-error)
(org-babel-do-load-languages (org-babel-do-load-languages
'org-babel-load-languages 'org-babel-load-languages
...@@ -87,6 +94,7 @@ ...@@ -87,6 +94,7 @@
(emacs-lisp . t) (emacs-lisp . t)
(shell . t) (shell . t)
(pugs . t) (pugs . t)
(pugs-error . t)
(C . t) (C . t)
(gnuplot . t) (gnuplot . t)
(js . t) (js . t)
......
;;; ob-pugs-error.el --- org-babel functions for pugs evaluation
;; Copyright (C) your name here
;; Author: your name here
;; Keywords: literate programming, reproducible research
;; Homepage: https://orgmode.org
;; Version: 0.01
;;; License:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This file is not intended to ever be loaded by org-babel, rather it is a
;; pugs for use in adding new language support to Org-babel. Good first
;; steps are to copy this file to a file named by the language you are adding,
;; and then use `query-replace' to replace all strings of "pugs" in this
;; file with the name of your new language.
;; After the `query-replace' step, it is recommended to load the file and
;; register it to org-babel either via the customize menu, or by evaluating the
;; line: (add-to-list 'org-babel-load-languages '(pugs . t)) where
;; `pugs' should have been replaced by the name of the language you are
;; implementing (note that this applies to all occurrences of 'pugs' in this
;; file).
;; After that continue by creating a simple code block that looks like e.g.
;;
;; #+begin_src pugs-error
;; test
;; #+end_src
;; Finally you can use `edebug' to instrumentalize
;; `org-babel-expand-body:pugs-error' and continue to evaluate the code block. You
;; try to add header keywords and change the body of the code block and
;; reevaluate the code block to observe how things get handled.
;;
;; If you have questions as to any of the portions of the file defined
;; below please look to existing language support for guidance.
;;
;; If you are planning on adding a language to org-babel we would ask
;; that if possible you fill out the FSF copyright assignment form
;; available at https://orgmode.org/request-assign-future.txt as this
;; will make it possible to include your language support in the core
;; of Org-mode, otherwise unassigned language support files can still
;; be included in the contrib/ directory of the Org-mode repository.
;;; Requirements:
;; Use this section to list the requirements of this language. Most
;; languages will require that at least the language be installed on
;; the user's system, and the Emacs major mode relevant to the
;; language be installed as well.
;;; Code:
(require 'ob)
(require 'ob-ref)
(require 'ob-comint)
(require 'ob-eval)
;; possibly require modes required for your language
;; optionally define a file extension for this language
(add-to-list 'org-babel-tangle-lang-exts '("pugs-error" . "pgs"))
;; optionally declare default header arguments for this language
(defvar org-babel-default-header-args:pugs-error '())
;; This function expands the body of a source code block by doing things like
;; prepending argument definitions to the body, it should be called by the
;; `org-babel-execute:pugs-error' function below. Variables get concatenated in
;; the `mapconcat' form, therefore to change the formatting you can edit the
;; `format' form.
(defun org-babel-expand-body:pugs-error (body params &optional processed-params)
"Expand BODY according to PARAMS, return the expanded body."
(require 'inf-pugs-error nil t)
(let ((vars (org-babel--get-vars (or processed-params (org-babel-process-params params)))))
(concat
(mapconcat ;; define any variables
(lambda (pair)
(format "%s=%S"
(car pair) (org-babel-pugs-error-var-to-pugs-error (cdr pair))))
vars "\n")
"\n" body "\n")))
;; This is the main function which is called to evaluate a code
;; block.
;;
;; This function will evaluate the body of the source code and
;; return the results as emacs-lisp depending on the value of the
;; :results header argument
;; - output means that the output to STDOUT will be captured and
;; returned
;; - value means that the value of the last statement in the
;; source code block will be returned
;;
;; The most common first step in this function is the expansion of the
;; PARAMS argument using `org-babel-process-params'.
;;
;; Please feel free to not implement options which aren't appropriate
;; for your language (e.g. not all languages support interactive
;; "session" evaluation). Also you are free to define any new header
;; arguments which you feel may be useful -- all header arguments
;; specified by the user will be available in the PARAMS variable.
;; SDP: This is a very simple version.
;; SDP: I kept the original example just after if needed in future.
(defun org-babel-execute:pugs-error (body params)
"Execute a block of pugs-error code with org-babel."
(setq org-babel-eval-verbose t)
(let ((in-file (org-babel-temp-file "n" ".pgs"))
(verbosity (or (cdr (assq :verbosity params)) 0)))
(with-temp-file in-file
(insert body))
(org-babel-eval
(format "${PUGS} --no-preamble --no-color %s 2>&1 | sed 's@/.*\.pgs:@test.pgs:@'"
(org-babel-process-file-name in-file))
"")))
;; SDP: original `org-babel-execute:pugs-error' example.
;; (defun org-babel-execute:pugs-error (body params)
;; "Execute a block of Pugs-error code with org-babel.
;; This function is called by `org-babel-execute-src-block'"
;; (message "executing Pugs-error source code block")
;; (let* ((processed-params (org-babel-process-params params))
;; ;; set the session if the value of the session keyword is not the
;; ;; string `none'
;; (session (unless (string= value "none")
;; (org-babel-pugs-error-initiate-session
;; (cdr (assq :session processed-params)))))
;; ;; variables assigned for use in the block
;; (vars (org-babel--get-vars processed-params))
;; (result-params (assq :result-params processed-params))
;; ;; either OUTPUT or VALUE which should behave as described above
;; (result-type (assq :result-type processed-params))
;; ;; expand the body with `org-babel-expand-body:pugs-error'
;; (full-body (org-babel-expand-body:pugs-error
;; body params processed-params)))
;; ;; actually execute the source-code block either in a session or
;; ;; possibly by dropping it to a temporary file and evaluating the
;; ;; file.
;; ;;
;; ;; for session based evaluation the functions defined in
;; ;; `org-babel-comint' will probably be helpful.
;; ;;
;; ;; for external evaluation the functions defined in
;; ;; `org-babel-eval' will probably be helpful.
;; ;;
;; ;; when forming a shell command, or a fragment of code in some
;; ;; other language, please preprocess any file names involved with
;; ;; the function `org-babel-process-file-name'. (See the way that
;; ;; function is used in the language files)
;; ))
;; This function should be used to assign any variables in params in
;; the context of the session environment.
(defun org-babel-prep-session:pugs-error (session params)
"Prepare SESSION according to the header arguments specified in PARAMS."
)
(defun org-babel-pugs-error-var-to-pugs-error (var)
"Convert an elisp var into a string of pugs-error source code
specifying a var of the same value."
(format "%S" var))
(defun org-babel-pugs-error-table-or-string (results)
"If the results look like a table, then convert them into an
Emacs-lisp table, otherwise return the results as a string."
)
(defun org-babel-pugs-error-initiate-session (&optional session)
"If there is not a current inferior-process-buffer in SESSION then create.
Return the initialized session."
(unless (string= session "none")
))
(provide 'ob-pugs-error)
;;; ob-pugs-error.el ends here
;;; pugs-error -- simple major mode for pgs files used to document errors
;;; Commentary:
;;; inherits pugs mode
;;; Code:
(define-derived-mode pugs-error-mode pugs-mode "pugs-error"
"pugs mode is a major mode for editing pugs files"
;; define pugs keywords
)
(provide 'pugs-error-mode)
;;; (provide 'pugs-error-mode)
;;; pugs-error.el ends here
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#+LANGUAGE: en #+LANGUAGE: en
#+ATTR_LATEX: :width 4cm #+ATTR_LATEX: :width 4cm
#+HTML_HEAD_EXTRA: <style> pre.src-pugs:before { content: 'pugs'; } </style> #+HTML_HEAD_EXTRA: <style> pre.src-pugs:before { content: 'pugs'; } </style>
#+HTML_HEAD_EXTRA: <style> pre.src-pugs-error:before { content: 'invalid pugs'; } </style>
#+HTML_HEAD_EXTRA: <style> .remark{ @extend .todo !optional;} </style>
#+LATEX_CLASS_OPTIONS: [10pt] #+LATEX_CLASS_OPTIONS: [10pt]
#+LATEX_HEADER: \usepackage[hmargin=2.5cm,vmargin=1.5cm]{geometry} #+LATEX_HEADER: \usepackage[hmargin=2.5cm,vmargin=1.5cm]{geometry}
#+LATEX_COMPILER: pdflatex --shell-escape #+LATEX_COMPILER: pdflatex --shell-escape
...@@ -25,6 +26,12 @@ ...@@ -25,6 +26,12 @@
#+LATEX_HEADER_EXTRA: \AfterEndEnvironment{minted}{\end{mdframed}} #+LATEX_HEADER_EXTRA: \AfterEndEnvironment{minted}{\end{mdframed}}
#+LATEX_HEADER_EXTRA: \BeforeBeginEnvironment{verbatim}{\begin{mdframed}[linecolor=gray,backgroundcolor=green!5]} #+LATEX_HEADER_EXTRA: \BeforeBeginEnvironment{verbatim}{\begin{mdframed}[linecolor=gray,backgroundcolor=green!5]}
#+LATEX_HEADER_EXTRA: \AfterEndEnvironment{verbatim}{\end{mdframed}} #+LATEX_HEADER_EXTRA: \AfterEndEnvironment{verbatim}{\end{mdframed}}
#+LATEX_HEADER_EXTRA: \newtheorem{note}{Note}
#+LATEX_HEADER_EXTRA: \BeforeBeginEnvironment{note}{\begin{mdframed}[linecolor=orange,backgroundcolor=orange!5]}
#+LATEX_HEADER_EXTRA: \AfterEndEnvironment{note}{\end{mdframed}}
#+LATEX_HEADER_EXTRA: \newtheorem{warning}{Warning}
#+LATEX_HEADER_EXTRA: \BeforeBeginEnvironment{warning}{\begin{mdframed}[linecolor=red,backgroundcolor=red!5]}
#+LATEX_HEADER_EXTRA: \AfterEndEnvironment{warning}{\end{mdframed}}
* Introduction * Introduction
...@@ -359,7 +366,7 @@ modifications themselves look easy. Obviously, any experienced ...@@ -359,7 +366,7 @@ modifications themselves look easy. Obviously, any experienced
programmer knows that writing the code is only the first step of a programmer knows that writing the code is only the first step of a
much longer process which requires rigorous tests and validations, the much longer process which requires rigorous tests and validations, the
enrichment of a non-regression database. Generally one also desires to enrichment of a non-regression database. Generally one also desires to
*ensure that the development is used within the correct bounds which ensure that the development is used within the correct bounds which
requires to implement some checking. In a perfect world, an up-to-date requires to implement some checking. In a perfect world, an up-to-date
documentation of the functionality and its domain of validity. documentation of the functionality and its domain of validity.
...@@ -415,15 +422,311 @@ Actually, ~cout~ is itself a variable, we will come to this later. ...@@ -415,15 +422,311 @@ Actually, ~cout~ is itself a variable, we will come to this later.
~pugs~ is a strongly typed language. It means that a variable *cannot* ~pugs~ is a strongly typed language. It means that a variable *cannot*
change of type in its lifetime. change of type in its lifetime.
*** Declaration and affectation syntax
**** Declaration of simple variables
To declare a variable ~v~ of a given type ~V~, one writes
#+BEGIN_SRC pugs :exports source
let v:V;
#+END_SRC
This instruction is read as
#+begin_verse
Let $v\in V$.
#+end_verse
Actually,
- ~let~ is the declaration keyword,
- ~v~ is the variable name,
- ~:~ is a separation token (can be read as "/in/" in this context),
- ~V~ is the identifier of the type, and
- ~;~ marks the end of the instruction.
For instance to declare a real variable ~x~, one writes
#+NAME: declare-R
#+BEGIN_SRC pugs :exports both :results none
let x:R;
#+END_SRC
The instructions that follow the declaration of a variable can use it
while defined in the same scope, but it cannot be used before. Also,
after its declaration, one cannot declare another variable with the
same name in the same scope.
#+NAME: redeclare-variable
#+BEGIN_SRC pugs-error :exports both :results output
let x:R; // first declaration
let x:R; // second declaration
#+END_SRC
produces the following error
#+results: redeclare-variable
**** Affectation of simple variables
To affect the value of an expression ~expression~ to variable ~v~ one
simply uses the ~=~ operator. Thus assuming that a variable ~v~ has
already been /declared/, one writes simply
#+BEGIN_SRC pugs :exports source
v = expression;
#+END_SRC
There is not to much to comment, reading is quite natural
- ~v~ is the variable name,
- ~=~ is the affectation operator,
- ~expression~ is some code that provide a value (it can be another
variable, an arithmetic expression, the result of a function,...),
and
- ~;~ marks the end of the instruction.
One for instance can write
#+NAME: simple-affectations-example
#+BEGIN_SRC pugs :exports both :results output
import math; // to load sin function
let a:N;
let b:N;
let x:R;
a=3;
b=2+a;
x=sin(b)+a;
cout << "a = " << a << " b = " << b << " x = " << x << "\n";
#+END_SRC
In this example, we imported the `math` module which provides the
`sin` function. and we used the ~N~ data type of natural integers
($\mathbb{N}\equiv\mathbb{Z}_{\ge0}$).
Running the example gives the following result.
#+results: simple-affectations-example
#+BEGIN_warning
Actually, *separating* the *declaration* from the *initialization* of a
variable is quite *dangerous*. This is prone to errors and can lead to
the use of undefined values. During the compilation of scripts, ~pugs~
detects uninitialized values. For instance,
#+NAME: uninitialized-variable
#+BEGIN_SRC pugs-error :exports both :results output
let x:R;
let y:R;
y=x+1;
#+END_SRC
produces the following compilation error
#+results: uninitialized-variable
For more complex constructions, it can be very difficult to detect at
compile time, this is why it is *encourage* to use variable definition
(see [[definition-simple-variables]]).
Observe nonetheless, ~pugs~ checks at runtime that used variables are
correctly defined. If not an error is produced.
#+END_warning
**** Definition of simple variables<<definition-simple-variables>>
The best way to define variables is the following. To define a
variable ~v~ of a given type ~V~, from an expression one writes
#+BEGIN_SRC pugs :exports source
let v:V, v = expression;
#+END_SRC
- ~let~ is the declaration keyword,
- ~v~ is the variable name,
- ~:~ is a separation token (can be read as "/in/" in this context),
- ~V~ is the identifier of the type,
- ~,~ is the separator that indicates the beginning of the affectation,
- ~expression~ is some code that provide a value (it can be another
variable, an expression, the result of a function,...),
and
- ~;~ marks the end of the instruction.
A practical example is
#+NAME: simple-definition-example
#+BEGIN_SRC pugs :exports both :results output
import math; // to load sin function
let a:N, a=3;
let b:N, b=2+a;
let x:R, x=sin(b)+a;
cout << "a = " << a << " b = " << b << " x = " << x << "\n";
#+END_SRC
which produces the result
#+results: simple-definition-example
**** Compound declarations and affectations
We shall now see some weird constructions that are not useful by
themselves but which are important when dealing with builtin functions.
We just give an example which should be enough to explain the syntax.
#+NAME: compound-definition-example
#+BEGIN_SRC pugs :exports both :results output
let (a, b, x):N*N*R;
(x,b) = (2.3, 12);
a = 3;
cout << "a = " << a << " b = " << b << " x = " << x << "\n";
let (c,y,d) : N*R*N, (c, y, d) = (8, 1e-3, 2);
cout << "c = " << c << " d = " << d << " y = " << y << "\n";
#+END_SRC
which produces the result
#+results: compound-definition-example
The only potential mistake with this construction, is that variables
must appear in the same order in the declaration part and in the
affectation part of a definition. For instance, the following code is
invalid.
#+NAME: invalid-compound-definition
#+BEGIN_SRC pugs-error :exports both :results output
let (x,y):R*R, (y,x) = (0,1);
#+END_SRC
It produces the following error
#+results: invalid-compound-definition
which is easy to fix.
*** TODO Basic types<<basic-types>> *** TODO Basic types<<basic-types>>
Basic types in ~pugs~ are boolean ~B~, natural integers ~N~, integers ~Z~, Basic types in ~pugs~ are boolean ~B~, natural integers ~N~, integers ~Z~,
real ~R~, small vectors ~R^1~, ~R^2~ and ~R^3~, small matrices ~R^1x1~, ~R^2x2~ real ~R~, small vectors ~R^1~, ~R^2~ and ~R^3~, small matrices ~R^1x1~, ~R^2x2~
and ~R^3x3~ and strings ~string~. and ~R^3x3~ and strings ~string~.
#+BEGIN_note
Observe that while mathematically, obviously $\mathbb{R} = \mathbb{R}^1
= \mathbb{R}^{1\times1}$, the data types ~R~, ~R^1~ and ~R^1x1~ are different
in ~pugs~ and are *not implicitly* convertible from one to the other!
This may sound strange but there are few reasons for that.
- First, these are the reflect of internal ~pugs~ ~C++~-data types that
are used to write algorithms. In its core design pugs aim at writing
numerical methods generically with regard to the dimension. One of
the ingredients to achieve this purpose is to use dimension $1$
vectors and matrices when some algorithms reduce to dimension $1$
instead of ~double~ values. To avoid ambiguity that may arise in some
situations (this can lead to very tricky code), we decided to forbid
automatic conversions of these types with ~double~. When designing the
language we adopt the same rule to avoid ambiguity.
- A second reason is connected to the first one. Since ~pugs~ aims at
providing numerical methods for problems in dimension $1$, $2$ or
$3$, this allow to distinguish the nature of the underlying objects.
- It is natural to consider that the coordinates of the vertices
defining a mesh in dimension $d$ are elements of $\mathbb{R}^d$,
- or that a velocity or a displacement are also defined as
$\mathbb{R}^d$ values.
Thus using ~R^1~ in dimension $1$ for this kind data precise their
nature in some sense .
#+END_note
**** Variables of basic types are stored by value
This means that each variable of basic type allocates its own memory
to store its data. This is the natural behavior for variables thus one
understands easily that in the following example:
#+NAME: basic-type-value-storage
#+BEGIN_SRC pugs :exports both :results output
let a:N, a = 3;
let b:N, b = a;
a = 1;
cout << "a = " << a << " b = " << b << "\n";
#+END_SRC
which produces the expected result
#+results: basic-type-value-storage
When defining ~b~, the *value* contained is ~a~ is copied to set the value
of ~b~. Thus changing ~a~'s value does not impact the variable ~b~.
*** TODO Declaration and affectation syntax **** Variables of basic types are mutable
In ~pugs~ the only variables that are mutable (their value can be
*modified*) are of basic types. Executing the following code
#+NAME: basic-type-mutable-value
#+BEGIN_SRC pugs :exports both :results output
let a:N, a = 2;
a += 3;
cout << "a = " << a << "\n";
#+END_SRC
gives
#+results: basic-type-mutable-value
which is not a surprise. However, the use of the ~+=~ operator results
in the modification of the stored value. There is no copy.
Actually, this is not really important from the user point of
view. One just have to keep in mind that, as it will be depicted
after, high-level variables *are not mutable*: their values can be
*replaced* by a new ones but *cannot be modified*.
*** Implicit type conversions
In order to avoid ambiguities, in ~pugs~, there is *no implicit*
conversion in general.
#+BEGIN_note
Actually, there are only two situations for which implicit type
conversion can occur
- when the value is given as a parameter of a function, or
- when the value is used as the returned value of a function.
This will be detailed in section [[functions]].
#+END_note
This means that all affectation, unary and binary operators are
defined for all types.
*** Operators
**** Affectation operators
In the ~pugs~ language the affectation operators are the following.
| operator | description |
|----------+----------------------|
| ~=~ | affectation operator |
|----------+----------------------|
| ~+=~ | increment operator |
| ~-=~ | decrement operator |
| ~*=~ | multiply operator |
| ~/=~ | divide operator |
#+BEGIN_note
It is important to note that in ~pugs~ language, affectation operators
have *no* return value. This is a notable difference with ~C~ or
~C++~. Again, this is done to avoid common mistakes that can be
difficult to address. For instance, the following ~C++~ code is valid
but does not produce the expected result.
#+BEGIN_SRC C++ :exports source
bool b = true;
// do things ...
if (b=false) {
// do other things ...
}
#+END_SRC
Obviously the mistake is that the test should have been ~(b==false)~,
since otherwise, the following block is never executed (in ~C++~, the
result of an affectation is the value affected to the variable, which
is always false in that case.
This cannot happen with ~pugs~. A similar example
#+NAME: no-affectation-result
#+BEGIN_SRC pugs-error :exports both :results output
let b:B, b=true;
// do things
if (b=false) {
// do other things
}
#+END_SRC
produces the following error
#+results: no-affectation-result
#+END_note
Here is the complete list of supported affectation operators according
to left hand side variable type (/lvalue/ type) and right hand side
expression type (/rvalue/ type).
**** Unary operators
**** Binary operators
*** TODO High-level types<<high-level-types>> *** TODO High-level types<<high-level-types>>
...@@ -449,6 +752,10 @@ and ~R^3x3~ and strings ~string~. ...@@ -449,6 +752,10 @@ and ~R^3x3~ and strings ~string~.
** TODO Functions<<functions>> ** TODO Functions<<functions>>
*** Pure functions
*** Implicit type conversion for parameters and returned values
*** User-defined functions *** User-defined functions
*** Builtin functions *** Builtin functions
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment