How to use Rex -------------- What does a Rex program look like? Here is a sample source file | | ;;; /course/cs148/labs/rex/rsum.rex | | (in-package :user) | (use-package :rex) | | ;;; keep a running sum of the inputs seen thus far | | (defun rsum () | (some* ((sum int)) | (== sum (init-next 0 (plusm (in 'int) sum))) | (out sum))) | It is important that at the top of all source files there be (IN-PACKAGE :USER) and (USE-PACKAGE :REX) forms. Each package is a separate name space with its own symbols, some of which are acessible from the outside, some of which are used to implement the package. C programmers can think of it as something like a library. When we say (use-package :rex) we are saying we want to use the external functions and variables the rex package provides in our program. Since Rex is a declarative language, it is not possible for one to simply load up the source code of a few functions and evaluate them. Instead, we call a Rex compiler function which will turn your Rex declarations into code. The compiler is instructed to generate code for either lisp or C. If we generate lisp code, we can call a second Rex function to load up the lisp code and run the resulting Rex program in the Lisp listener. So here's how we go from a Rex source file to a running Rex program using the compiler's capacity to generate lisp. * The first thing we need to do is start lisp and create a listener. (See HOWTO-lisp for a review of how to do this.) * Second, we tell the environment of the currently running lisp where Rex lives and what parts it consists of. We need to do this so that everything gets loaded in the proper order. (load "/pro/ai/lego/rex/rex-sys-lw.lisp") * Next, we actually load the Rex compiler into lisp. (load-system 'rex) * Finally, load your Rex program. It is important that you use the "rex" extension, since when Rex generates code, it writes over the file "rsum.lisp". Here we assume you've typed in the above Rex program into the file "rsum.rex" or copied rsum.rex from /course/cs148/labs/rex to your home directory. (load "rsum.rex") * Now we're ready to call the Rex compiler, via the function MAKEM. (makem (rsum) :opt t :module 'rsum :lisp t) Notice that the first argument to the compiler, "(rsum)", is somewhat like a call to your mainline. Suppose we were to call a function MAIN, then only other Rex DEFUNS referenced from MAIN and so forth recursively would get compiled into the resulting code. The ":opt t" simply means "please optimize". There is rarely any reason *not* to pass this argument to MAKEM. The ":module 'rsum" is a means to supply a name for the program being compiled. The ":lisp t" argument means "please generate lisp for me", as opposed to C code. A lisp file containing the code generated by Rex will be created in your directory. This symbol RSUM is not redundant with the name of the source file or the DEFUN by the same name. This is because in the former case, the first argument passed to MAKEM need not be just a vanilla function call, but any legal Rex expression. And in the latter, one could conceivably define more than one Rex program within a single source file. * Finally, we can run the Rex program using REX-EX as an interface to the lisp code generated by MAKEM (rex-ex rsum :print-output t) This will prompt you for inputs and print the outputs for each cycle of execution. To stop execution, type ":eof" as the input. Note: Is it a pain in your butt to have to type (load "/pro/ai/lego/rex/rex-sys-lw.lisp") (load-system 'rex) each time you start your lisp? (This is a valid question if you won't be using Lisp for any other reason than this class which is unfortunately quite likely these days.) To save typing, you can add these two lines to your `.lispworks' file. Here's a transcript of a lisp session which loads, compiles, and runs the above Rex program. ------------------------------------------------------------------------------ CL-USER 2 > (load "/pro/ai/lego/rex/rex-sys-lw.lisp") ; Loading text file /pro/ai/lego/rex/rex-sys-lw.lisp ;; Creating system REX #P"/pro/ai/lego/rex/rex-sys-lw.lisp" CL-USER 3 > (load-system 'rex) ; Loading fasl file /pro/ai/lego/rex/defs.wfasl ; Loading fasl file /pro/ai/lego/rex/timing.wfasl ; Loading fasl file /pro/ai/lego/rex/main.wfasl ; Loading fasl file /pro/ai/lego/rex/modules.wfasl ; Loading fasl file /pro/ai/lego/rex/prims.wfasl ; Loading fasl file /pro/ai/lego/rex/binary-streams.wfasl ; Loading fasl file /pro/ai/lego/rex/runtime.wfasl ; Loading fasl file /pro/ai/lego/rex/optimize.wfasl ; Loading fasl file /pro/ai/lego/rex/aux.wfasl ; Loading fasl file /pro/ai/lego/rex/wizzy-code-gen.wfasl ; Loading fasl file /pro/ai/lego/rex/lisp-code-gen.wfasl ; Loading fasl file /pro/ai/lego/rex/c-code-gen.wfasl ; Loading fasl file /pro/ai/lego/rex/ic-code-gen.wfasl ; Loading fasl file /pro/ai/lego/rex/wizzy-top.wfasl ; Loading fasl file /pro/ai/lego/rex/utils.wfasl ; Loading fasl file /pro/ai/lego/rex/rexex.wfasl ; Loading fasl file /pro/ai/lego/rex/rex-init.wfasl (REX) CL-USER 4 > (load "rsum.rex") ; Loading text file rsum.rex #P"/home/jmk/rsum.rex" CL-USER 5 > (makem (rsum) :opt t :module 'rsum :lisp t) 8 vars Starting common sub-expression elimination10%20% Eliminated 6 common sub-expressions out of 8 nodes, leaving 2 nodes. This module has never been defined. Before using this module, you must declare it with the form (defmodule RSUM) or the form (defvalidmod RSUM). ---------------------- MODULE RSUM ----------------------- Total local vars : 2 Constants : 0 Strings : 0 State vars : 1 Propagation vars : 1 Inputs : 1 Outputs : 1 Module vars : 0 Primitive operations: iplus : 1 Submodules: -------------- MODULE RSUM AND DESCENDENTS -------------- Total vars : 2 Depth (upper bound) : 2 Parallelism (lower bound) : 1 Generating lisp code to "~/rsum.lisp" Module declaration in file "~/RSUM.test.MOD" updated. NIL CL-USER 6 > (rex-ex rsum :print-output t) ;Loading file #P"/u/jmk/rsum.lisp" ; Loading text file /u/jmk/rsum.lisp Input 0> 3 Output 0: 0 Input 0> 3 Output 0: 3 Input 0> 3 Output 0: 6 Input 0> 3 Output 0: 9 Input 0> 3 Output 0: 12 Input 0> 3 Output 0: 15 Input 0> 20 Output 0: 18 Input 0> 20 Output 0: 38 Input 0> 21 Output 0: 58 Input 0> 21 Output 0: 79 Input 0> :eof End of input data. NIL