2 .-----.-----.----.--------.
4 |_____|_____|____|__|__|__| [exa] embeddable scheme
7 Minimalistic, lightweight scheme machine written in C++. Primarily focused for
8 use as embedded scripting language in any application, extensible to any level
9 of scheme impossibility.
11 Before any work with this program, please see the license in LICENSE file.
12 If you didn't receive your copy of LICENSE, please download it from web:
14 http://www.gnu.org/licenses/gpl-3.0.txt
17 ESCM was written by Mirek [exa] Kratochvil for some higher purposes of computer
18 science in 2007-2008. You can contact me at <exa.exa@gmail.com>.
23 |__| |___._|__ | frequently answered questions
28 Why should I use Scheme as my scripting language, and why should I use
29 ESCM interpreter for that?
31 Scheme is a wonderful scrpiting language, to observe it, learn it.
32 You can look up a very good scheme tutorial called "Teach yourself
33 scheme in fixnum days" by Dorai Sitaram.
35 ESCM aims to be the best scheme that can be used for embedding and
36 scripting, with cleanly and readably written internals and rich
37 programmer/user interface.
41 Is there any tutorial for embedding ESCM in my application?
43 Look at `src/interp.cpp' in this package, there's an implementation of
44 complete interpreter using libreadline (which gives bash-like features).
45 It should come well-commented so that any experienced-enough programmer
50 How can I add functions and/or variables to my ESCM environment?
52 Look at `include/macros.h', there are some macros that could possibly
53 help you. File `src/builtins.cpp' contains all the scheme internals
54 implemented, so you can gain inspiration there. Basically, writing a
55 lambda is a very simple process:
57 You want to call it this way:
61 So you write the function, with use of one macro:
63 #include "path_to_escm/macros.h"
65 static escm_func_handler(thenums) {
66 for(int i=0;i<1000;++i)printf("%d\n",i);
70 return_scm(NULL) means that you don't return anything, in scheme that
71 will be seen as returning the () empty list. `static' keyword is not
72 necessary here, but it can be usuable when writing larger projects.
74 Then, if you have your environment
79 you have to "register" the function, or, put the reference to the global
82 escm_add_func_handler(e,"write-teh-numz",thenums);
84 ...and then you can use it!
86 Any other object can be added to environment using the add_global method
89 e->add_global("variable",new_scm(e,number,5)
92 in a result, scheme will evaluate correctly:
98 How can I guess which environment was my C++ function called from?
100 Every function declared with escm_func_handler macro has the caller
101 environment accesible via escm_environment local variable. This can be
102 used for memory allocation (which you will most probably need.)
104 This is an example of function that always returns #t:
106 escm_func_handler(foo) {
107 return new_scm(escm_environment,boolean,true)
108 ->collectable<scm>();
111 When writing larger handlers, this will most probably help:
113 #define e escm_environment // :D
117 How do I manipulate internal scheme data?
118 How do I create scheme data type of my own?
120 Every scheme-related data in escm is represented as a class derived from
121 the very basic scm class. Generally, the data is created this way:
126 scm*a=new_scm(e,string,"foobar!");
128 This creates new object on scheme heap, with a type of string, filled
129 with foobar. As all scheme objects are garbage-collected, this object is
130 initially protected, so it doesn't get deleted accidentally before you
131 bind it somewhere, so the garbage collector can "reach" it (and
132 therefore decide that it won't be deleted).
134 You may want to mark the object as collectable after you set some
137 e->add_global("aaa",a);
138 /*now, that the object is referenced by the global frame,
139 it is reachable for the collector and won't be deleted by
142 a->mark_collectable();
143 /* If the string gets out somehow, gc can delete it. */
145 For user convenience, expression-like collectable-marking was added:
147 return a->collectable<string>();
149 or you can combine it even like this:
151 return new_scm(e,string,"returned string") ->
152 collectable<string>();
154 Please note that collectable-marking is recursive, so when you possibly
155 had scheme object like this:
157 (1 . (2 . (3 . (4 . 0))))
159 You don't have to mark all 4 pairs, but only the first one (with '1'),
160 and other get marked properly because they're children of the first
163 In ESCM we have several such string- and pair-like "basic" types:
165 -- C++ class -- scheme expression
171 pair (1 . 2) (1 2 3 4)
172 closure (lambda (foo) foo)
175 Please note that we work only with pointers to these classes, never
176 directly. There are several more classes to handle scheme internals,
177 those include class frame, continuation, lambda, macro, and derivees.
179 NOTE: we will describe work with macros later.
181 You may work with classes through pointers, you can see file
182 `include/types.h' to see what every class contains. You can work with
183 number class this way:
189 Constructors of the classes are closely related to the new_scm macro we
190 have seen earlier. For example using
192 new_scm(e,type,foo,bar)
194 will allocate the memory for `type' in heap that belongs to scm_env e,
195 and then will call a constructor:
199 Destructors are properly called, too, but the time of object deletion is
200 rather unpredictable - so for example having some `printf's in ~type
201 destructor will make the program throw the lines on garbage collection,
202 which can be years after the objects were really used. On the other
203 hand, this can be interesting to observe. (measure how many % of your
204 objects get redundant, or just to do some statistics)
207 Please note that because of principle of garbage collection, when your
208 custom scheme object refers to another garbage-collected scheme objects,
209 it has to be able to mark those objects as it's children. This is done
210 with the scm* get_child(int) function. Every scheme object has to have
211 one, and every such function has to behave in this way:
213 1] if it's called with a number n, it returns pointer to n-th child.
214 2] if it's called with a higher number, it returns constant
215 escm_no_more_children.
217 Usually the function gets called sequentially with values increasing
218 from zero. You must not return any pointers that point on anything other
219 than the class scm's derivee, but you can return NULL.
221 You can see some examples of get_child() functions in `include/types.h'
224 If you need some memory allocation in the scheme machine, you can use
225 classical C/C++ memory allocation methods, and if you need the data on
226 the escm's heap (so it can get stored to a file or something), you can
227 use the data scheme this way:
229 a=new_data_scm(scm_env_pointer,size)
231 and access allocated data with dataof() macro, for example:
233 memcpy(dataof(a),pointer,size);
236 With all of this in mind, creating a garbage-collectable class is pretty
237 simple. Look, for example, at header of class for letters.
239 class character: public scm
243 inline character (scm_env*e, char a) : scm (e)
248 virtual std::string display_internal (int style);
251 scm_env*e is passed to the constructor because of need for more
252 construct-time allocations.
254 Notice the display_internal() function - it formats an object to some
255 human-readable form and returns it in std::string from STL. When style
256 is 0, then it's formatted like scheme source code, otherwise it's
257 formated for standart output. For example:
259 style -- -- type -- output string
266 To get garbage-collection working well, you have to code correct
267 get_child function. For example, class pair could look like this:
269 class pair : public scm {
273 virtual scm* get_child(int i) {
277 default: return escm_no_more_children;
287 How do I get data from/to a functions?
288 How do I get function arguments which were passed to C++ code?
289 How do I return value from a C++ function to scheme?
291 Arguments which the function was called with can be retrieved with
292 macros defined in `include/macros.h'. Those are:
296 arg_count count of arguments, without tail
299 has_arg true if there's one or more "classical"
302 pop_arg() pops that argument
304 has_tail_arg true if the next argument is "tail"
306 pop_tail_arg() pops it
308 pop_arg_type(T) pops the corresponding argument, but
309 pop_tail_arg_type(T) returns NULL if it's not of type T.
311 Note, classical and tail arguments mean roughly this in scheme:
313 (function classical-arg classical-arg . tail-arg)
316 To return a value from the function, use return_scm macro:
318 return_scm(new_scm(e,boolean,true));
320 This is not a "real return", function code may continue even below the
321 return_scm macro, but do not try to return any other value. (because you
322 would most probably cause the next function in call-stack to return that
323 value, which could bring not-really-interesting results)
329 Macros differ from functions in some ways:
331 1] when you call a macro, the arguments don't get evaluated.
332 2] macro gets the arguments in one list, does something with them,
333 evaluates to a value, and this value is then evaluated again.
335 Simple explanation for non-schemers: Macro is a code generator. It gets
336 something, creates a scheme code, and that code then gets evaluated.
338 In ESCM, the code can be generated by another scheme code, or by some
341 Macro in scheme code looks like this:
343 (macro (a form) (cdr form))
346 ; this is equivalent definition:
348 (define a (macro (form) (cdr form)))
350 Note that macro is called with its whole syntax, so this would create an
353 (macro (a form) form)
356 ; => (a) => (a) => (a) => ...
359 In C++, macro can be defined just like the function. We can implement
362 escm_macro_handler(a,code)
364 return_macro_code(code->d);
367 You might NOT want the interpreter to evaluate things you created, and
368 use it as a result of whole operation - then you need to play with the
369 continuations a little. There are several macros defined that way:
371 #define e escm_environment
373 escm_macro_handler(lambda,code)
375 pair* c = pair_p (code->d);
376 if (!c) e->throw_exception (code);
377 return_scm (new_scm (e, closure,
378 c->a, pair_p (c->d), e->cont->env)
379 ->collectable<scm>() );
382 escm_macro_handler(begin,code)
384 e->replace_cont (new_scm
385 (e, codevector_continuation, pair_p (code->d) )
386 ->collectable<continuation>() );
389 escm_macro_handler(quote,code)
391 if(pair_p (code->d) )
392 return_scm (((pair*)(code->d))->a);
397 How can I see what error occured?
399 ESCM has classical scheme error mechanism. You may define *error-hook*
400 to set desired error-handling behavior.
402 For example, when using the interpreter:
407 > (define (*error-hook* . x)
408 | (display "error: ")
414 error: bad macro syntax
418 error: ("invalid define symbol format" 123)
421 R5RS scheme features like catch/throw and error stack should be defined
422 in scheme initialization file.
425 How do I catch escm errors?
426 How are the exceptions implemented in escm?
428 Simply, as in every scheme. There should be *globally* defined variable
429 *ERROR-HOOK* (with asterisks), which is lambda. Every exception
430 generated by internal escm code, embedded code, or (error) call is then
431 fed to it. For example you might have noticed that "clean" interpreter
432 doesn't really print out error messages. Fix is simple:
434 (define (*error-hook* . x)
439 Notice that argument has variable length, so anything can be passed to
442 Implementing some other error-handling stacks depends on your choice.
443 Default escm interpreter should come with some solution.
447 How do I generate an exception?
449 From scheme code, lambda (error) is predefined in default builtins, you
452 (error 'any 'description 'here)
454 Note that error is lambda, so arguments get evaluated before throwing.
456 When implementing some builtin C++ function, you may use any of scm_env
457 provided member error generators:
459 void scm_env::throw_exception (scm* s)
460 void scm_env::throw_string_exception (char* s)
461 void scm_env::throw_desc_exception (char*desc, scm* s)
463 All those do the same thing - throw an exception which is then usually
464 passed to *error-hook*. You can safely emulate their behavior using
465 C++ exception mechanism, mostly because escm exceptions are built upon
466 that one. You should also be careful if you try to write some code that
467 catches (scm*) - if it calls _any_ escm code, it must be prepared to
468 catch its exceptions and probably forward them by another throw.
470 So, generally, example definition of builtin (error) should be
471 sufficient to explain all of this:
474 void op_error (scm_env*e, scm*arglist)
476 e->throw_exception (arglist);
479 Macros for exception handling similar to the parameter handling macros
480 found above should be implemented as well, self-explainable from file