3.1 Program Structure
3.2 Module declaration
3.3 Module initialization
3.4 Qualified notation
3.5 Inline procedures
3.6 Module access file
3.7 Reading path
Copyright
Acknowledgements
1. Table of contents
2. Overview of Bigloo
3. Modules
4. Core Language
5. Standard Library
6. Pattern Matching
7. Object System
8. Threads
9. Regular parsing
10. Lalr(1) parsing
11. Errors and Assertions
12. Eval and code interpretation
13. Macro expansion
14. Command Line Parsing
15. Explicit typing
16. The C interface
17. The Java interface
18. Bigloo Libraries
19. SRFIs
20. DSSSL support
21. Compiler description
22. User Extensions
23. Bigloo Development Environment
24. Global Index
25. Library Index
Bibliography
|
A modules is a compiler entity. That is, the Bigloo compiler compiles
modules and then, link them against libraries in order to produce
executables. A module may be split into several files but a file
cannot contain more than one module. A module is made of a
module clause that is a list for which the car is the symbol
module and followed by any Bigloo expression (that is
definitions or expressions). The module clause names the module and
define the scope of the definitions. At last, the module clause is
also the place where foreign bindings are defined and where classes
are defined.
A Bigloo program is composed of one or more Bigloo modules where a module is
defined by the following grammar:
<module> ==> <module-declaration> <module-body>
<module-declaration> ==> the module declaration
<module-body> ==> the module body |
A module is not related to a specific file and can be spread over
several files if that is convenient. In particular, there is no
relationship between module names and file names. The module declaration
(see Module Declaration) must be the first expression in the first
of the files containing the module; other expressions form the body of
the module. The module body (see Core Language) contains global
variables and functions definition and top level expressions
(see Expressions).
The module declaration form is
module name clause ... | bigloo syntax |
This form defines a module and must be the first in the file. The
argument name is a symbol naming the module and, if the same
module name is used more than once, Bigloo signals an error. The
runtime library is composed of modules that are read when a user module
is compiled so, if a user module has the same name as one of the library
modules, an error is signaled.
A simple module can be:
(module foo)
(display "this is a module")
|
The first line here is the complete module definition, the last line is
the complete module body and together they form a complete Bigloo program. If
these lines were stored in file zz.scm , invoking bigloo zz.scm
would create the executable a.out which, when obeyed, would
display this is a module on the terminal.
Note:
Some special identifiers are reserved and can't be used to name modules.
If such an identifier is used, the compiler will produce the message:
#(module t
#^
# *** ERROR:bigloo:TOP-LEVEL:Parse error
# Illegal module name -- (MODULE eval ...
|
The list of reserved identifiers may be enlarged for next release. For
the current release that list is made of: eval , foreign and
t .
|
Module clause s can be:
main name | bigloo module clause |
This clause defines the entry point for a stand alone application to be
procedure name of arity one. Bigloo invokes this procedure at the
beginning of execution providing the list, composed of the shell command
line arguments, as its single argument.
(module foo
(main start))
(define (start argv)
(display argv)
(newline))
|
Then if this program is compiled into foo and invoked using the
command foo -t bar, the list which is the argument for the main
procedure start would be ("foo" "-t" "bar") .
The special form args-parse helps main function argument parsing
(see Command Line Parsing).
|
import import ... | bigloo module clause |
An import is a list of the form:
<import> ==> <iclause> ...
<iclause> ==> (<bind-name> <module-name> <file-name> ...)
| (<bind-name> <module-name>)
| (<module-name>
| (<module-name> <file-name> ...)
<bind-name> ==> <r5rs-ident>
<module-name> ==> <r5rs-ident>
<file-name> ==> <string> |
The first alternative in iclause imports the variable named
bind-name which is defined in the module module-name ,
located in the files file-name .... The second does the same
but without specifying the name of the file where the module is located.
The third and the fourth form import all the exported variables of the module
module-name .
Note: The need for specifying in which files modules are located comes
from the fact that there is no automatic mapping between module names
and files names. Such a mapping can be defined in a ``module access file''
(see Module Access File) or in the import clause itself, as
in the first and fourth alternatives in iclause above.
Here is an example of an import clause:
(module foo
(import
;; import all bar exported bindings:
bar
;; import the hux binding exported by
;; the module hux :
(hux hux)
;; import all gee bindings. the gee module
;; is located in a file called `gee.scm':
(gee "gee.scm")))
|
|
use use ... | bigloo module clause |
use has the same meaning as import except that modules
which are used are not initialized (see Module Initialization).
Used modules are read before imported modules.
|
with with ... | bigloo module clause |
This clause specifies a list of modules which have to be
initialized at runtime and is used to force the initialization
of modules which are never imported but which are required by an
application (see Embedded Bigloo applications).
|
export export ... | bigloo module clause |
In order to make a module's global bindings available to other modules, they
have to be exported. Export clauses are in charge of this task and an
export is a list of the form:
<export> ==> <eclause> ...
<eclause> ==> <ident>
| (<ident> <ident> ...)
| (inline <ident> <ident> ...)
| (generic <ident> <ident> <ident> ...)
| <class> |
The first form of eclause allows the variable ident be exported,
the second allows the function ident , always regarded as immutable
when exported this way, to be exported and the third exports an
inline-procedure (see Inline Procedures) whose name is extracted from
the first ident after the word inline . The last two are both
connected with Bigloo's object system. The generic clause exports
generic functions (see Generic functions) and class clause exports
classes (see Class declaration).
Note: Only bindings defined in module m can be exported
by m (i.e. bindings imported by m cannot be
exported by m ).
Type information, specified in any ident in an export clause, is used
by Bigloo. Where no type information is given, a default generic type named
obj is used.
Note: The last formal argument of a multiple arity function can
not be typed because this argument is bound to be a pair
or null . This union cannot be denoted by any type.
Here is an example of the module foo that exports bindings:
(module foo
(export
;; export the bar mutable variable
bar
;; export the hux function. this
;; function takes exactly two arguments
(hux x y)
;; export the inline function gee
;; that takes at least one argument.
(inline gee x . z)))
|
|
static static ... | bigloo module clause |
A static clause has exactly the same syntax as an export
clause. However, bindings declared static are local to the module. Since
the default scope of all bindings is static, static module clauses
are useful only for program documentation.
|
from from ... | bigloo module clause |
from clauses have the same syntax as import clauses and allow
the re-exportation of imported bindings. That is, any module can
export any bindings imported via a from clause.
As an example, suppose we have module bar :
(module bar
(export (bar)))
(define (bar) "bar")
|
Now, suppose we have a module foo that imports bar , by the
means of a from clause. Module foo is able to re-export the
bar binding of module bar :
(module foo
(from (bar bar "bar.scm")))
|
A third module, let's name it gee , importing module foo , can see
the binding for function bar :
(module gee
(import (foo "foo.scm")))
(print (bar))
|
|
load load ... | bigloo module clause |
A load is a list of the form:
<load> ==> <lclause> ...
<lclause> ==> (<module-name> <file-name>)
| <module-name> |
This clause forces Bigloo to load the module specified in the lclause
in the environment used by the macro expansion mechanism. This means that
the user's macros can use all the bindings of all the load ed modules
but the load ed bindings remains unknown to the compiler.
If the module foo is defined by:
(module foo
(export (foo x)))
(define (foo x)
`(cons ,x ,x))
|
then,
(module gee
(load (foo "foo.scm")))
(define-macro (gee x)
`(cons ,(-fx x 1) ,(foo x)))
(gee 5) ==> (cons 4 (cons 5 5))
=> (4 5 . 5)
|
|
extern extern ... | bigloo module clause |
Extern (aka foreign) clauses will be explained in the foreign interface
(see C Interface).
|
java java ... | bigloo module clause |
Java clauses will be explained in the Java interface
(see Java Interface).
|
option option ... | bigloo module clause |
This clause enables variables which affect compilation to be set from inside
a module and since the expressions, option ..., are evaluated
when compiling, no code is compiled for them. They are allowed to
make side effects and to change the values of the global variables which
describe how the compiler must compile. Usually they allow the control
variables, which are described when Bigloo is invoked with the -help2
option, to be set as in the following example:
(module examplar
(option (set! *debug* 3)
(set! *verbose* 2)))
(print 'dummy)
|
Whatever arguments are passed on the command line, Bigloo will compile this
module in both verbose mode and debug mode.
|
library library ... | bigloo module clause |
This clause enables libraries (see Bigloo Libraries) when compiling and
linking Bigloo modules. The expressions library ... are symbols
naming the libraries to be used.
Here is an example of a module declaration which makes use of a library
named format :
(module test
(library format)
(main test-format)
(import (test2 "test2.scm")))
|
|
type type ... | bigloo module clause |
This forms is used to define builtin Bigloo types. It is not recommended
to use it in user programs. So, it is left undocumented.
|
3.3 Module initialization
|
Initializing a module means evaluating, at runtime, its
top level forms (global bindings are top level forms).
When a module, module1 , imports a module, module2 ,
module2 is initialized before module1 . Modules are
initialized only once, nothing being done if a module already met during
initialization is met again. Library modules are initialized before user
modules and imported modules are initialized in the same order as they
appear in import clauses.
Here is a first example with two modules. First the module foo :
;; module foo
(module foo
(main main)
(import (bar "bar.scm")))
(define (main argv)
(print "argv: " argv))
(print "foo")
|
Then the module bar
;; module bar
(module bar)
(print "bar")
|
These can be compiled into the executable a.out with:
$ bigloo -c foo.scm
$ bigloo -c bar.scm
$ bigloo foo.o bar.o
|
Execution of a.out produces:
$ a.out
-| bar
foo
argv: (a.out)
|
The explanation is:
- module
foo contains the program entry point so this is where
initialization begins.
- because
foo imports module bar , bar must be
initialized before foo . This explains why the word bar
is printed before anything else.
- module initialization for
foo is completed before main
is called. This explains why word foo is printed before main
is entered.
Let's consider another example with 3 modules:
;; module1
(module module1
(main main)
(import (module2 "module2.scm")))
(define (main argv)
(print "argv: " argv))
(print "module1")
|
The second module:
;; module2
(module module2
(import (module3 "module3.scm")))
(print "module2")
|
The third module:
;; module3
(module module3
(import (module1 "module1.scm")))
(print "module3")
|
Compile with:
$ bigloo module1.scm -c
$ bigloo module2.scm -c
$ bigloo module3.scm -c
$ bigloo module1.o module2.o module3.o
|
Execution produces:
$ a.out
-| module3
module2
module1
argv: (a.out)
|
The order of module initialization can be explicitly specified using with
and use clauses.
Global variables can be referenced using implicit notation or
using qualified notation. Implicit notation is used when
variables are referenced just by their name whereas qualified notation
is used when variables are referenced by their name and
the name of the module which defines them. Qualified notation has
the following syntax:
(@ <bind-name> <module-name>) |
and is useful when several imported modules export a
variable with the same name. Using qualified notations instead of
short notation only affects compile.
Bigloo allows procedures called inline and which differ from
normal ones only in the type of code planted. An inline procedure is a
first class object which can be manipulated in the same way as any other
procedure but when Bigloo sees a reference to one, rather than
generating a C function call to the function, the body of the inline
procedure is open-coded. The definition of an inline is given in the
following way:
define-inline (name args ...) body | bigloo syntax |
define-inline (name args ... . arg) body | bigloo syntax |
Apart from the initial word, this form has the same syntax as that used by
define for procedures. Inline procedures are exportable which means
that the compiler scans imported files to find the bodies of all inline
procedures. Here is a small example of a module which exports an inline and
a module which imports it.
;; the exporter module
(module exporter
(export (inline make-list . objs)))
(define-inline (make-list . objs) objs)
|
;; the importer module
(module importer
(import exporter))
(print (make-list 1 2 3 4 5))
|
Because of the open-coding of the exporter procedure, the above print
statement is equivalent to:
(print (let ((objs (list 1 2 3 4 5)))
objs))
|
Any procedure can be an inline. Also any exported procedure can be an inline
provided all global variables and functions it uses are also exported.
Note: Bigloo can decide to inline procedures declared with
define
but this can be achieved only with local procedures whereas procedures
declared with the define-inline form are open-coded even through
module importation.
Note: Procedures declared inline are macro expanded with
the macro defined in the module where they are invoked. That is, if
module module1 declares an inline procedure p and module
module2 imports it, p may have two different macro-expansions:
one for module1 and one for module2 .
|
Bigloo is different from languages such as C where a module is defined by a
file. For Bigloo, the module name is not necessarily the name of the file
where the text of the module is written and modules can even be split across
several files.
Since modules are defined independently of files, it is necessary to make a
link between a module and its files and there are two ways of doing this.
Choosing an import clause where the file-names are specified or creating a
``module access file''. Such a file must contain only one list , each
element of the list being of the form:
(module-name "file-name" ... "file-name")
Use the -afile <file> option to specify the ``module accessfile'' when compiling. By default Bigloo checks if a file named .afile
exists. If it exists it is loaded as a module access file.
See The Bigloo command line.
Note: The Bigloo distribution contains a tool, afile ,
that can automatically build a ``module access file''. See the manpage for
afile for details.
Imported, included or loaded files are sought first in the current directory
and then in the directories, sequentially from start to end, of the list in
the *load-path*
variable. This variable,
initially set to the empty list, can be reset by the -I option of the
compiler.
|