[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: More Compiled S-Expression Questions
Quoting Brent Fulgham:
> Is it possible to create a single compiled representation of this
> that could be stored and reloaded without going through the
> overhead of re-parsing and evaluating?
I'm not sure what you're asking, though I see a couple of
possibilities:
1. Your application gets some code at run-time that you want to cache
in a string-friendly database (possibly the filesystem).
2. You want to compile some static Scheme code to be embedded in the
application.
The first seems more likely, and I'll suggest a method for that first.
I have an answer for the second close at hand, though, so I've included
it.
----------------------------------------
Answer 1: Compiling code at run-time and storing it for later use
Compile phase:
Use the `(begin ...)' trick to get a single expression.
Use scheme_make_string_input_port() to get a port.
Use scheme_read() to get an S-expression.
Use scheme_compile() to get compiled code.
Use scheme_make_string_output_port() to get a new output port.
Use scheme_write() to write the compiled code to the output port.
Use scheme_get_sized_string_output() to get the compiled code in
string form. Beware that the string might contain nul characters.
Eval phase:
Use scheme_make_sized_string_input_port() to convert the string of
compiled code into a port of compiled code. (Use the _sized version
because the string might have nul characters.)
Enable bytecode reading using
scheme_set_param(scheme_config, MZCONFIG_CAN_READ_COMPILED, scheme_true)
Use scheme_read() to get the compiled code.
Use scheme_eval() to evaluate it.
----------------------------------------
Answer 2: Compiling static code and embedding it in an application
Compile phase:
Use the following little program that takes any number of
S-expressions from the current input port, and sends C code to the
current output port:
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
(let ([DIGITS-PER-LINE 15]
[p (open-output-string)])
(let loop ()
(let ([expr (read)])
(unless (eof-object? expr)
(let ([c (compile expr)])
(write c p)
(loop)))))
(let ([s (get-output-string p)])
(printf "static unsigned char expr[] = {~n ")
(let loop ([chars (string->list s)][pos 0])
(unless (null? chars)
(let ([char (car chars)])
(printf "~a, " (char->integer char)))
(loop (cdr chars)
(if (= pos DIGITS-PER-LINE)
(begin
(printf "~n ")
0)
(add1 pos)))))
(printf "0};~n")
(printf "#define COMPILED_STR_SIZE ~a~n"
(string-length s))))
; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ;
The output C code has the form
static unsigned char expr[] = {
... <a bunch of numbers> ... };
#define COMPILED_STR_SIZE <number>
Copy it or #include it into your C code.
Eval phase:
Convert the string to a port, using
scheme_make_sized_string_input_port(expr, COMPILED_STR_SIZE)
Turn on bytecode reading using
scheme_set_param(scheme_config, MZCONFIG_CAN_READ_COMPILED, scheme_true)
Read and eval until the port returns EOF:
while (1) {
expr = scheme_read(port);
if (SAME_OBJ(expr, scheme_eof))
break;
scheme_eval_multi(expr, env);
}
Matthew