((section 2 "Outdated CHICKEN release" (p "This is a manual page for an old and unsupported version of CHICKEN. If you are still using it, please consider migrating to the latest version. You can find the manual for the latest release " (int-link "/manual" "here") ".") (toc) (tags "faq" "manual")) (section 2 "FAQ" (p "This is the list of Frequently Asked Questions about CHICKEN Scheme. If you have a question not answered here, feel free to post to the chicken-users mailing list; if you consider your question general enough, feel free to add it to this list.") (section 3 "General " (section 4 "Why yet another Scheme implementation?" (p "Since Scheme is a relatively simple language, a large number of implementations exist and each has its specific advantages and disadvantages. Some are fast, some provide a rich programming environment. Some are free, others are tailored to specific domains, and so on. The reasons for the existence of CHICKEN are:") (ul (li "CHICKEN is portable because it generates C code that runs on a large number of platforms.") (li "CHICKEN is extensible, since its code generation scheme and runtime system/garbage collector fits neatly into a C environment.") (li "CHICKEN is free and can be freely distributed, including its source code.") (li "CHICKEN offers better performance than nearly all interpreter based implementations, but still provides full Scheme semantics.") (li "As far as we know, CHICKEN is the first implementation of Scheme that uses Henry Baker's " (link "http://home.pipeline.com/~hbaker1/CheneyMTA.html" "Cheney on the M.T.A") " concept."))) (section 4 "What should I do if I find a bug?" (p "Fill a ticket at " (link "http://bugs.call-cc.org" "bugs.call-cc.org") " with some hints about the problem, like version/build of the compiler, platform, system configuration, code that causes the bug, etc."))) (section 3 "Specific" (section 4 ("Why are values defined with " (tt "define-foreign-variable") " or " (tt "define-constant") " or " (tt "define-inline") " not seen outside of the containing source file?") (p "Accesses to foreign variables are translated directly into C constructs that access the variable, so the Scheme name given to that variable does only exist during compile-time. The same goes for constant- and inline-definitions: The name is only there to tell the compiler that this reference is to be replaced with the actual value.")) (section 4 ("How does " (tt "cond-expand") " know which features are registered in used units?") (p "Each unit used via " (tt "(declare (uses ...))") " is registered as a feature and so a symbol with the unit-name can be tested by " (tt "cond-expand") " during macro-expansion-time. Features registered using the " (tt "register-feature!") " procedure are only available during run-time of the compiled file. You can use the " (tt "eval-when") " form to register features at compile time.")) (section 4 ("Why are constants defined by " (tt "define-constant") " not honoured in " (tt "case") " constructs?") (p (tt "case") " expands into a cascaded " (tt "if") " expression, where the first item in each arm is treated as a quoted list. So the " (tt "case") " macro can not infer whether a symbol is to be treated as a constant-name (defined via " (tt "define-constant") ") or a literal symbol.")) (section 4 "How can I enable case sensitive reading/writing in user code?" (p "To enable the " (tt "read") " procedure to read symbols and identifiers case sensitive, you can set the parameter " (tt "case-sensitivity") " to " (tt "#t") ".")) (section 4 "Why doesn't CHICKEN support the full numeric tower by default?" (p "The short answer is to use the " (int-link "/egg/numbers" "numbers") " egg:") (highlight scheme "% chicken-install numbers\n% csi -q\n#;1> (use numbers)") (p "The long answer:") (p "There are a number of reasons for this:") (p "- For most applications of Scheme fixnums (exact word-sized integers) and flonums (64-bit floating-point numbers) are more than sufficient;") (p "- Interfacing to C is simpler;") (p "- Dispatching of arithmetic operations is more efficient.")) (section 4 "Does CHICKEN support native threads?" (p "Native threads are not supported for two reasons. One, the runtime system is not reentrant.  Two, concurrency implemented properly would require mandatory locking of every object that could be potentially shared between two threads. The garbage-collection algorithm would then become much more complex and inefficient, since the location of every object has to be accessed via a thread synchronization protocol. Such a design would make native threads in CHICKEN essentially equivalent to Unix processes and shared memory.") (p "For a different approach to concurrency, please see the " (int-link "/egg/mpi" "mpi") " or " (int-link "/egg/concurrent-native-callbacks" "concurrent-native-callbacks") " egg.") (p (link "http://www.stylewarning.com/blog/about" "Robert Smith") " has put " (link "http://www.stylewarning.com/blog/bounties" "a bounty") " on a release-quality implementation of native threads.")) (section 4 "Does CHICKEN support Unicode strings?" (p "The system does not directly support Unicode, but there is an extension for UTF-8 strings: " (int-link "/egg/utf8" "utf8") "."))) (section 3 "Why are `dynamic-wind' thunks not executed when a SRFI-18 thread signals an error?" (p "Here is what Marc Feeley, the author of " (link "http://srfi.schemers.org/srfi-18" "SRFI-18") " has to say about this subject:") (pre "   >No the default exception handler shouldn't invoke the after\n   > thunks of the current continuation.  That's because the\n   > exception handler doesn't \"continue\" at the initial\n   > continuation of that thread.  Here are the relevant words of\n   > SRFI 18:\n   \n   >\n   >  Moreover, in this dynamic environment the exception handler\n   >  is bound to the \"initial exception handler\" which is a unary\n   >  procedure which causes the (then) current thread to store in\n   >  its end-exception field an \"uncaught exception\" object whose\n   >  \"reason\" is the argument of the handler, abandon all mutexes\n   >  it owns, and finally terminate.\n   >\n   \n   >The rationale is that, when an uncaught exception occurs in a\n   >thread the thread is in bad shape and things have gone\n   >sufficiently wrong that there is no universally acceptable way to\n   >continue execution.  Executing after thunks could require a\n   >whole lot of processing that the thread is not in a shape to do.\n   >So the safe thing is to terminate the thread.  If the programmer\n   >knows how to recover from an exception, then he can capture the\n   >continuation early on, and install an exception handler which\n   >invokes the continuation.  When the continuation is invoked the\n   >after thunks will execute.")) (section 3 "Platform specific" (section 4 "How do I generate a DLL under MS Windows (tm) ?" (p "Use " (tt "csc") " in combination with the " (tt "-dll") " option:") (p (tt "C:\\> csc foo.scm -dll"))) (section 4 "How do I generate a GUI application under Windows(tm)?" (p "Invoke " (tt "csc") " with the " (tt "-gui") " option.  In GUI-mode, the runtime system displays error messages in a message box and does some rudimentary command-line parsing.")) (section 4 "Compiling very large files under Windows with the Microsoft C compiler fails with a message indicating insufficient heap space." (p "It seems that the Microsoft C compiler can only handle files up to a certain size, and it doesn't utilize virtual memory as well as the GNU C compiler, for example. Try closing running applications. If that fails, try to break up the Scheme code into several library units.")) (section 4 ("When I run " (tt "csi") " inside an emacs buffer under Windows, nothing happens.") (p "Invoke " (tt "csi") " with the " (tt "-:c") " runtime option. Under Windows the interpreter thinks it is not running under control of a terminal and doesn't print the prompt and does not flush the output stream properly.")) (section 4 ("On Windows, " (tt "csc.exe") " seems to be doing something wrong.") (p "The Windows development tools include a C# compiler with the same name. Either invoke " (tt "csc.exe") " with a full pathname, or put the directory where you installed CHICKEN in front of the MS development tool path in the " (tt "PATH") " environment variable.")) (section 4 "On Windows source and/or output filenames with embedded whitespace are not found." (p "There is no current workaround. Do not use filenames with embedded whitespace for code. However, command names with embedded whitespace will work correctly."))) (section 3 "Customization" (section 4 "How do I run custom startup code before the runtime-system is invoked?" (p "When you invoke the C compiler for your translated Scheme source program, add the C compiler option " (tt "-DC_EMBEDDED") ", or pass " (tt "-embedded") " to the " (tt "csc") " driver program, so no entry-point function will be generated (" (tt "main()") "). When your are finished with your startup processing, invoke:") (highlight c "CHICKEN_main(argc, argv, C_toplevel);") (p "where " (tt "C_toplevel") " is the entry-point into the compiled Scheme code. You should add the following  declarations at the head of your code:") (highlight c "#include \"chicken.h\"\nextern void C_toplevel(C_word,C_word,C_word) C_noret;")) (section 4 "How can I add compiled user passes?" (p "To add a compiled user pass instead of an interpreted one, create a library unit and recompile the main unit of the compiler (in the file " (tt "chicken.scm") ") with an additional " (tt "uses") " declaration. Then link all compiler modules and your (compiled) extension to create a new version of the compiler, like this (assuming all sources are in the current directory):") (highlight scheme "  % cat userpass.scm\n  ;;;; userpass.scm - My very own compiler pass\n\n  (declare (unit userpass))\n\n  ;; Perhaps more user passes/extensions are added:\n  (let ([old (user-pass)])\n    (user-pass\n      (lambda (x)\n        (let ([x2 (do-something-with x)])\n\t   (if old\n\t       (old x2)\n\t       x2) ) ) ) )") (pre "% csc -c -x userpass.scm\n% csc chicken.scm -c -o chicken-extended.o -uses userpass\n% gcc chicken-extended.o support.o easyffi.o compiler.o optimizer.o batch-driver.o c-platform.o \\\nc-backend.o userpass.o `csc -ldflags -libs` -o chicken-extended") (p "On platforms that support it (Linux ELF, Solaris, Windows + VC++), compiled code can be loaded via " (tt "-extend") " just like source files (see " (tt "load") " in the User's Manual)."))) (section 3 "Macros" (section 4 ("Where is " (tt "define-macro") "?") (p "With CHICKEN 4, the macro-expansion subsystem is now hygienic where old Lisp-style low-level macros are not available anymore. " (tt "define-syntax") " can define hygienic macros using " (tt "syntax-rules") " or low-level macros with user-controlled hygienic with " (i "explicit renaming") " macros. Translating old-style macros into ER-macros isn't that hard, see " (int-link "Macros") " for more information.")) (section 4 ("Why are low-level macros defined with " (tt "define-syntax") " complaining about unbound variables?") (p "Macro bodies that are defined and used in a compiled source-file are evaluated during compilation and so have no access to anything created with " (tt "define") ". Use " (tt "define-for-syntax") " instead.")) (section 4 ("Why isn't " (tt "load") " properly loading my library of macros?") (p "During compile-time, macros are only available in the source file in which they are defined. Files included via " (tt "include") " are considered part of the containing file."))) (section 3 "Warnings and errors" (section 4 "Why does my program crash when I use callback functions (from Scheme to C and back to Scheme again)?" (p "There are two reasons why code involving callbacks can crash out of no apparent reason:") (ol (li "It is important to use " (tt "foreign-safe-lambda/foreign-safe-lambda*") " for the C code that is to call back into Scheme. If this is not done than sooner or later the available stack space will be exhausted.") (li "If the C code uses a large amount of stack storage, or if Scheme-to-C-to-Scheme calls are nested deeply, then the available nursery space on the stack will run low. To avoid this it might be advisable to run the compiled code with a larger nursery setting, i.e. run the code with " (tt "-:s...") " and a larger value than the default (for example " (tt "-:s300k") "), or use the " (tt "-nursery") " compiler option.  Note that this can decrease runtime performance on some platforms."))) (section 4 ("Why does the linker complain about a missing function " (tt "_C_..._toplevel") "?") (p "This message indicates that your program uses a library-unit, but that the object-file or library was not supplied to the linker. If you have the unit " (tt "foo") ", which is contained in " (tt "foo.o") " than you have to supply it to the linker like this (assuming a GCC environment):") (p (tt "% csc program.scm foo.o -o program"))) (section 4 ("Why does the linker complain about a missing function " (tt "_C_toplevel") "?") (p "This means you have compiled a library unit as an application. When a unit-declaration (as in " (tt "(declare (unit ...))") ") is given, then this file has a specially named toplevel entry procedure. Just remove the declaration, or compile this file to an object-module and link it to your application code.")) (section 4 ("Why does my program crash when I compile a file with " (tt "-unsafe") " or unsafe declarations?") (p "The compiler option " (tt "-unsafe") " or the declaration " (tt "(declare (unsafe))") " disable certain safety-checks to improve performance, so code that would normally trigger an error will work unexpectedly or even crash the running application. It is advisable to develop and debug a program in safe mode (without unsafe declarations) and use this feature only if the application works properly.")) (section 4 "Why don't toplevel-continuations captured in interpreted code work?" (p "Consider the following piece of code:") (highlight scheme "  \n(define k (call-with-current-continuation (lambda (k) k)))\n(k k)") (p "When compiled, this will loop endlessly. But when interpreted, " (tt "(k k)") " will return to the read-eval-print loop! This happens because the continuation captured will eventually read the next toplevel expression from the standard-input (or an input-file if loading from a file). At the moment " (tt "k") " was defined, the next expression was " (tt "(k k)") ". But when " (tt "k") " is invoked, the next expression will be whatever follows after " (tt "(k k)") ". In other words, invoking a captured continuation will not rewind the file-position of the input source. A solution is to wrap the whole code into a " (tt "(begin ...)") " expression, so all toplevel expressions will be loaded together.")) (section 4 ("Why does " (tt "define-reader-ctor") " not work in my compiled program?") (p "The following piece of code does not work as expected:") (highlight scheme " (eval-when (compile)\n (define-reader-ctor 'integer->char integer->char) )\n (print #,(integer->char 33))") (p "The problem is that the compiler reads the complete source-file before doing any processing on it, so the sharp-comma form is encountered before the reader-ctor is defined. A possible solution is to include the file containing the sharp-comma form, like this:") (highlight scheme " (eval-when (compile)\n (define-reader-ctor 'integer->char integer->char) )\n \n (include \"other-file\")") (highlight scheme " ;;; other-file.scm:\n (print #,(integer->char 33))")) (section 4 "Why do built-in units, such as srfi-1, srfi-18, and posix fail to load?" (p "When you try to " (tt "use") " a built-in unit such as " (tt "srfi-18") ", you may get the following error:") (highlight scheme " #;1> (use srfi-18)\n ; loading library srfi-18 ...\n Error: (load-library) unable to load library\n srfi-18\n \"dlopen(libchicken.dylib, 9): image not found\"                ;; on a Mac\n \"libchicken.so: cannot open shared object file: No such file or directory\"  ;; Linux") (p "Another symptom is that " (tt "(require 'srfi-18)") " will silently fail.") (p "This typically happens because the CHICKEN libraries have been installed in a non-standard location, such as your home directory.  The workaround is to explicitly tell the dynamic linker where to look for your libraries:") (pre "export DYLD_LIBRARY_PATH=~/scheme/chicken/lib:$DYLD_LIBRARY_PATH ;; Mac\nexport LD_LIBRARY_PATH=~/scheme/chicken/lib:$LD_LIBRARY_PATH    ;; Linux")) (section 4 "How can I increase the size of the trace shown when runtime errors are detected?" (p "When a runtime error is detected, CHICKEN will print the last entries from the trace of functions called (unless your executable was compiled with the " (tt "-no-trace") " option. By default, only 16 entries will be shown. To increase this number pass the " (tt "-:aN") " parameter to your executable."))) (section 3 "Optimizations" (section 4 "How can I obtain smaller executables?" (p "If you don't need " (tt "eval") " or the stuff in the " (tt "extras") " library unit, you can just use the " (tt "library") " unit:") (highlight scheme "\t(declare (uses library))\n\t(display \"Hello, world!\\n\")") (p "(Don't forget to compile with the " (tt "-explicit-use") " option) Compiled with Visual C++ this generates an executable of around 240 kilobytes. It is theoretically possible to compile something without the library, but a program would have to implement quite a lot of support code on its own.")) (section 4 "How can I obtain faster executables?" (p "There are a number of declaration specifiers that should be used to speed up compiled files: declaring " (tt "(standard-bindings)") " is mandatory, since this enables most optimizations. Even if some standard procedures should be redefined, you can list untouched bindings in the declaration. Declaring " (tt "(extended-bindings)") " lets the compiler choose faster versions of certain internal library functions. This might give another speedup. You can also use the the " (tt "usual-integrations") " declaration, which is identical to declaring " (tt "standard-bindings") " and " (tt "extended-bindings") " (note that " (tt "usual-integrations") " is set by default). Declaring " (tt "(block)") " tells the compiler that global procedures are not changed outside the current compilation unit, this gives the compiler some more opportunities for optimization. If no floating point arithmetic is required, then declaring " (tt "(number-type fixnum)") " can give a big performance improvement, because the compiler can now inline most arithmetic operations. Declaring " (tt "(unsafe)") " will switch off most safety checks. If threads are not used, you can declare " (tt "(disable-interrupts)") ". You should always use maximum optimizations settings for your C compiler. Good GCC compiler options on Pentium (and compatible) hardware are: " (tt "-Os -fomit-frame-pointer -fno-strict-aliasing") " Some programs are very sensitive to the setting of the nursery (the first heap-generation). You should experiment with different nursery settings (either by compiling with the " (tt "-nursery") " option or by using the " (tt "-:s...") " runtime option).")) (section 4 ("Which non-standard procedures are treated specially when the " (tt "extended-bindings") " or " (tt "usual-integrations") " declaration or compiler option is used?") (p "The following standard bindings are handled specially, depending on optimization options and compiler settings:") (p (tt "*") " " (tt "+") " " (tt "-") " " (tt "/") " " (tt "<=") " " (tt "<") " " (tt "=") " " (tt ">=") " " (tt ">") " " (tt "abs") " " (tt "acos") " " (tt "apply") " " (tt "asin") " " (tt "assoc") " " (tt "assv") " " (tt "atan") " " (tt "boolean?") " " (tt "c...r") " " (tt "call-with-current-continuation") " " (tt "call-with-values") " " (tt "ceiling") " " (tt "char->integer") " " (tt "char-alphabetic?") " " (tt "char-downcase") " " (tt "char-lower-case?") " " (tt "char-numeric?") " " (tt "char-upcae") " " (tt "char-upper-case?") " " (tt "char-whitespace?") " " (tt "char<=?") " " (tt "char<?") " " (tt "char=?") " " (tt "char>=?") " " (tt "char>?") " " (tt "char?") " " (tt "complex?") " " (tt "cons") " " (tt "cos") " " (tt "current-input-port") " " (tt "current-output-port") " " (tt "eof-object?") " " (tt "eq?") " " (tt "equal?") " " (tt "eqv?") " " (tt "even?") " " (tt "exact->inexact") " " (tt "exact?") " " (tt "exp") " " (tt "floor") " " (tt "for-each") " " (tt "for-each") " " (tt "gcd") " " (tt "inexact->exact") " " (tt "inexact?") " " (tt "integer->char") " " (tt "lcm") " " (tt "length") " " (tt "list-ref") " " (tt "list-tail") " " (tt "list?") " " (tt "list") " " (tt "log") " " (tt "make-vector") " " (tt "map") " " (tt "member") " " (tt "memq") " " (tt "memv") " " (tt "negative?") " " (tt "not") " " (tt "null?") " " (tt "number->string") " " (tt "number?") " " (tt "odd?") " " (tt "pair?") " " (tt "positive?") " " (tt "procedure?") " " (tt "quotient") " " (tt "rational?") " " (tt "read-string") " " (tt "real?") " " (tt "remainder") " " (tt "round") " " (tt "set-car!") " " (tt "set-cdr!") " " (tt "sin") " " (tt "sqrt") " " (tt "string->number") " " (tt "string-append") " " (tt "string-ci=?") " " (tt "string-length") " " (tt "string-ref") " " (tt "string-set!") " " (tt "string=?") " " (tt "string?") " " (tt "string") " " (tt "substring") " " (tt "symbol?") " " (tt "tan") " " (tt "truncate") " " (tt "values") " " (tt "vector-length") " " (tt "vector-ref") " " (tt "vector-set!") " " (tt "vector?") " " (tt "vector") " " (tt "write-char") " " (tt "zero?")) (p "The following extended bindings are handled specially:") (p (tt "add1") " " (tt "alist-cons") " " (tt "any?") " " (tt "arithmetic-shift") " " (tt "atom?") " " (tt "bit-set?") " " (tt "bitwise-and") " " (tt "bitwise-ior") " " (tt "bitwise-not") " " (tt "bitwise-xor") " " (tt "blob-size") " " (tt "block-ref") " " (tt "block-set!") " " (tt "call/cc") " " (tt "current-error-port") " " (tt "current-thread") " " (tt "error") " " (tt "f32vector->blob/shared") " " (tt "f32vector-length") " " (tt "f32vector-ref") " " (tt "f64vector->blob/shared") " " (tt "f64vector-length") " " (tt "f64vector-ref") " " (tt "finite?") " " (tt "first") " " (tt "fixnum?") " " (tt "flonum?") " " (tt "flush-output") " " (tt "foldl") " " (tt "foldr") " " (tt "format") " " (tt "fourth") " " (tt "fp*") " " (tt "fp+") " " (tt "fp-") " " (tt "fp/") " " (tt "fp<=") " " (tt "fp<") " " (tt "fp=") " " (tt "fp=") " " (tt "fp>=") " " (tt "fp>=") " " (tt "fp>") " " (tt "fp>") " " (tt "fpabs") " " (tt "fpacos") " " (tt "fpasin") " " (tt "fpatan2") " " (tt "fpatan") " " (tt "fpceiling") " " (tt "fpcos") " " (tt "fpexpt") " " (tt "fpexp") " " (tt "fpfloor") " " (tt "fpinteger?") " " (tt "fplog") " " (tt "fpmax") " " (tt "fpmin") " " (tt "fpneg") " " (tt "fprintf") " " (tt "fpround") " " (tt "fpsin") " " (tt "fpsqrt") " " (tt "fptan") " " (tt "fptruncate") " " (tt "fx*?") " " (tt "fx*") " " (tt "fx+?") " " (tt "fx+") " " (tt "fx-?") " " (tt "fx-") " " (tt "fx/?") " " (tt "fx/") " " (tt "fx=") " " (tt "fx>=") " " (tt "fx>") " " (tt "fxand") " " (tt "fxeven?") " " (tt "fxior") " " (tt "fxmax") " " (tt "fxmin") " " (tt "fxmod") " " (tt "fxneg") " " (tt "fxnot") " " (tt "fxodd?") " " (tt "fxshl") " " (tt "fxshr") " " (tt "fxxor") " " (tt "hash-table-ref") " " (tt "identity") " " (tt "locative->object") " " (tt "locative-ref") " " (tt "locative-set!") " " (tt "locative?") " " (tt "make-record-instance") " " (tt "not-pair?") " " (tt "null-list?") " " (tt "number-of-slots") " " (tt "o") " " (tt "pointer+") " " (tt "pointer->object") " " (tt "pointer-f32-ref") " " (tt "pointer-f32-set!") " " (tt "pointer-f64-ref") " " (tt "pointer-f64-set!") " " (tt "pointer-s16-ref") " " (tt "pointer-s16-set!") " " (tt "pointer-s32-ref") " " (tt "pointer-s32-set!") " " (tt "pointer-s8-ref") " " (tt "pointer-s8-set!") " " (tt "pointer-u16-ref") " " (tt "pointer-u16-set!") " " (tt "pointer-u32-ref") " " (tt "pointer-u32-set!") " " (tt "pointer-u8-ref") " " (tt "pointer-u8-set!") " " (tt "pointer=?") " " (tt "print*") " " (tt "printf") " " (tt "print") " " (tt "s16vector->blob/shared") " " (tt "s16vector-length") " " (tt "s16vector-ref") " " (tt "s16vector-set!") " " (tt "s32vector->blob/shared") " " (tt "s32vector-length") " " (tt "s32vector-ref") " " (tt "s32vector-set!") " " (tt "s8vector->blob/shared") " " (tt "s8vector-length") " " (tt "s8vector-ref") " " (tt "s8vector-set!") " " (tt "second") " " (tt "signum") " " (tt "sprintf") " " (tt "sub1") " " (tt "substring-ci=?") " " (tt "substring-index-ci") " " (tt "substring-index") " " (tt "substring=?") " " (tt "third") " " (tt "thread-specific-set!") " " (tt "thread-specific") " " (tt "u16vector->blob/shared") " " (tt "u16vector-length") " " (tt "u16vector-ref") " " (tt "u16vector-set!") " " (tt "u32vector->blob/shared") " " (tt "u32vector-length") " " (tt "u32vector-ref") " " (tt "u32vector-set!") " " (tt "u8vector->blob/shared") " " (tt "u8vector-length") " " (tt "u8vector-ref") " " (tt "u8vector-set!") " " (tt "xcons"))) (section 4 "What's the difference betweem \"block\" and \"local\" mode?" (p "In " (tt "block") " mode, the compiler assumes that definitions in the current file are not visible from outside of the current compilation unit, so unused definitions can be removed and calls can be inlined. In " (tt "local") " mode, definitions are not hidden, but the compiler assumes that they are not modified from other compilation units (or code evaluated at runtime), and thus allows inlining of them.")) (section 4 "Can I load compiled code at runtime?" (p "Yes. You can load compiled at code at runtime with " (tt "load") " just as well as you can load Scheme source code.  Compiled code will, of course, run faster.") (p "To do this, pass to " (tt "load") " a path for a shared object.  Use a form such as " (tt "(load \"foo.so\")") " and run " (tt "csc -shared foo.scm") " to produce " (tt "foo.so") " from " (tt "foo.scm") " (at which point " (tt "foo.scm") " will no longer be required).") (p "If you have compiled code that contains a " (tt "module") " definition, then executing the code will \"register\" the module to allow importing the bindings provided by the module into a running Scheme process. The information required to use a module is in this case embedded in the compiled code. Compiling another program that uses this (compiled) module is more difficult: the used module will not necessarily be loaded into the compiler, so the registration will not be executed. In this case the information about what bindings the compiled module exports must be separated from the actual code that executes at runtime. To make this possible, compiling a module can be done in such a manner that an \"import library\" is created. This is a file that contains the binding information of the module and we can use it to compile a file that refers to that module. An example can perhaps make this clearer:") (pre " ;; my-module.scm\n \n (module my-module (...) ...)") (pre " ;; use-my-module.scm") (pre " (import my-module)\n ...") (p "Compile the module and generate an import library for the \"my-module\" module:") (pre " % csc -s my-module.scm -emit-import-library my-module") (p "Compile the program that uses the module:") (pre " % csc use-my-module.scm")) (section 4 "Why is my program which uses regular expressions so slow?" (p "The regular expression engine has recently been replaced by " (link "http://wiki.call-cc.org/users/alex shinn" "alex shinn") "'s excellent " (tt "irregex") " library, which is fully implemented in Scheme. Precompiling regular expressions to internal forms is somewhat slower than with the old PCRE-based regex engine. It is advisable to use " (tt "irregex") " to precompile regular expressions outside of time-critical loops and use them where performance matters."))) (section 3 "Garbage collection" (section 4 ("Why does a loop that doesn't " (tt "cons") " still trigger garbage collections?") (p "Under CHICKEN's implementation policy, tail recursion is achieved simply by avoiding returns from function calls. Since the programs are CPS converted, a continuous sequence of nested procedure calls is performed. At some stage the stack-space has to run out and the current procedure and its parameters (including the current continuation) are stored somewhere in the runtime system. Now a minor garbage collection occurs and rescues all live data from the stack (the first heap generation) and moves it into the the second heap generation. Then the stack is cleared (using a " (tt "longjmp") ") and execution can continue from the saved state. With this method arbitrary recursion (in tail- or non-tail position) can happen, provided the application doesn't run out of heap-space. (The difference between a tail- and a non-tail call is that the tail-call has no live data after it invokes its continuation - and so the amount of heap-space needed stays constant)")) (section 4 "Why do finalizers not seem to work in simple cases in the interpeter?" (p "Consider the following interaction in CSI:") (pre "#;1> (define x '(1 2 3))\n#;2> (define (yammer x) (print x \" is dead\"))\n#;3> (set-finalizer! x yammer)\n(1 2 3)\n#;4> (gc #t)\n157812\n#;5> (define x #f)\n#;6> (gc #t)\n157812\n#;7>") (p "While you might expect objects to be reclaimed and \"" (i "(1 2 3) is dead") "\" printed, it won't happen: the literal list gets held in the interpreter history, because it is the result value of the set-finalizer! call. Running this in a normal program will work fine.") (p "When testing finalizers from the interpreter, you might want to define a trivial macro such as") (pre "(define-syntax v\n  (syntax-rules ()\n    ((_ x) (begin (print x) (void)))))") (p "and wrap calls to " (tt "set-finalizer!") " in it."))) (section 3 "Interpreter" (section 4 "Does CSI support history and autocompletion?" (p "CSI doesn't support it natively but it can be activated with one of the " (link "http://wiki.call-cc.org/egg/readline" "readline") ", " (link "http://wiki.call-cc.org/egg/linenoise" "linenoise") " or " (link "http://wiki.call-cc.org/egg/parley" "parley") " eggs. Out of these three, the parley egg is recommended. After installing parley, add the following to your " (tt "~/.csirc") " or equivalent file:") (highlight scheme "(use parley)\n(let ((old (current-input-port)))\n  (current-input-port (make-parley-port old)))") (p "Users of *nix-like systems (including Cygwin), may also want to check out " (link "http://utopia.knoware.nl/~hlub/rlwrap/" "rlwrap") ".  This program lets you \"wrap\" another process (e.g. " (tt "rlwrap csi") ") with the readline library, giving you history, autocompletion, and the ability to set the keystroke set. Vi fans can get vi keystrokes by adding \"set editing-mode vi\" to their " (tt ".inputrc") " file.")) (section 4 ("Does code loaded with " (tt "load") " run compiled or interpreted?") (p "If you compile a file with a call to " (tt "load") ", the code will be loaded at runtime and, if the file loaded is a Scheme source code file (instead of a shared object), it will be interpreted (even if the caller program is compiled).")) (section 4 "How do I use extended (non-standard) syntax in evaluated code at run-time?" (p "Normally, only standard Scheme syntax is available to the evaluator. To use the extensions provided in the CHICKEN compiler and interpreter, add:") (highlight scheme "(require-library chicken-syntax)"))) (section 3 "Extensions " (section 4 "Where is \"chicken-setup\" ?" (p (tt "chicken-setup") " has been rewritten from scratch and its functionality is now contained in the three tools " (tt "chicken-install") ", " (tt "chicken-uninstall") " and " (tt "chicken-status") ". See the " (int-link "Extensions") " chapter for more information.")) (section 4 "How can I install CHICKEN eggs to a non-default location?" (p "You can just set the " (tt "CHICKEN_REPOSITORY") " environment variable. It should contain the path where you want eggs to be installed:") (pre "$ export CHICKEN_REPOSITORY=~/eggs/lib/chicken/5\n$ chicken-install -init ~/eggs/lib/chicken/5\n$ chicken-install -p ~/eggs/ extensionname") (p "In order to make programs (including csi) see these eggs, you should set this variable when you run them. See the " (int-link "Extensions#Changing repository location" "Extensions/Changing repository location") " section of the manual for more information on that.") (p "Alternatively, you can call the " (tt "repository-path") " Scheme procedure before loading the eggs, as in:") (highlight scheme "(repository-path \"/home/azul/eggs\")\n(use format-modular)") (p "Note, however, that using " (tt "repository-path") " as above hard-codes the location of your eggs in your source files.  While this might not be an issue in your case, it might be safe to keep this configuration outside of the source code (that is, specifying it as an environment variable) to make it easier to maintain.") (p "The repository needs to be initialized before use. See the documentation for the " (tt "-init") " option to " (tt "chicken-install") ", in " (int-link "Extensions") ".")) (section 4 "Can I install chicken eggs as a non-root user?" (p "Yes, just install them in a directory you can write to by using " (tt "CHICKEN_REPOSITORY") " (see above).")) (section 4 ("Why does downloading an extension via " (tt "chicken-install") " fail on Windows Vista?") (p "Possibly the Windows Firewall is active, which prevents " (tt "chicken-install") " from opening a TCP connection to the egg repository. Try disabling the firewall temporarily.") (hr) (p "Previous: " (int-link "Bugs and limitations")) (p "Next: " (int-link "Acknowledgements"))))))