1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861
|
% Copyright 2005-2018 Cisco Systems, Inc.
%
% Licensed under the Apache License, Version 2.0 (the "License");
% you may not use this file except in compliance with the License.
% You may obtain a copy of the License at
%
% http://www.apache.org/licenses/LICENSE-2.0
%
% Unless required by applicable law or agreed to in writing, software
% distributed under the License is distributed on an "AS IS" BASIS,
% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
% See the License for the specific language governing permissions and
% limitations under the License.
\chapter{Using Chez Scheme\label{CHPTUSE}}
{\ChezScheme} is often used interactively to support program development
and debugging, yet it may also be used to create stand-alone applications
with no interactive component.
This chapter describes the various ways in which {\ChezScheme} is
typically used and, more generally, how to get the most out of the
system.
Sections~\ref{SECTUSEINTERACTION}, \ref{SECTUSEEXPEDITOR},
and~\ref{SECTUSEINTERACTIONENVIRONMENT} describe how
one uses {\ChezScheme} interactively.
Section~\ref{SECTUSELIBRARIES} discusses how libraries and RNRS
top-level programs are used in {\ChezScheme}.
Section~\ref{SECTUSESCRIPTING} covers support for writing and running
Scheme scripts, including compiled scripts and compiled
RNRS top-level programs.
Section~\ref{SECTUSEOPTIMIZATION} describes how to structure
and compile an application to get the most efficient code possible out
of the compiler.
Section~\ref{SECTUSECUSTOMIZATION} describes how one can customize the
startup process, e.g., to alter or eliminate the command-line options,
to preload Scheme or foreign code, or to run {\ChezScheme} as a subordinate
program of another program.
Section~\ref{SECTUSEAPPLICATIONS} describes how to build applications
using {\ChezScheme} with {\PetiteChezScheme} for run-time support.
Finally, Section~\ref{SECTUSECOMMANDLINE} covers command-line options used when
invoking {\ChezScheme}.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Interacting with Chez Scheme\label{SECTUSEINTERACTION}}
One of the simplest and most effective ways to write and test Scheme
programs is to compose them using a text editor, like \scheme{vi} or
\scheme{emacs}, and test them interactively with {\ChezScheme} running in
a shell window.
When {\ChezScheme} is installed with default options, entering the command
\scheme{scheme} at the shell's prompt starts an interactive Scheme
session.
The command \scheme{petite} does the same for {\PetiteChezScheme}.
After entering this command, you should see a short greeting followed
by an angle-bracket on a line by itself, like this:
\schemedisplay
Chez Scheme Version 9.5.1
Copyright 1984-2017 Cisco Systems, Inc.
>
\endschemedisplay
You also should see that the cursor is sitting one space to the
right of the angle-bracket.
The angle-bracket is a prompt issued by the system's ``REPL,''
which stands for ``Read Eval Print Loop,'' so called because it
reads, evaluates, and prints an expression, then loops back to
read, evaluate, and print the next, and so on.
(In {\ChezScheme}, the REPL is also called a waiter.)
In response to the prompt, you can type any Scheme expression.
If the expression is well-formed, the REPL will run the expression
and print the value.
Here are a few examples:
\schemedisplay
> 3
3
> (+ 3 4)
7
> (cons 'a '(b c d))
(a b c d)
\endschemedisplay
The reader used by the REPL is more sophisticated than an ordinary
reader.
In fact, it's a full-blown ``expression editor'' (``expeditor'' for short)
like a regular text editor but for just one expression at a time.
One thing you might soon notice is that the system automatically indents
the second and subsequent lines of an expression.
For example, let's say we want to define \scheme{fact}, a procedure that
implements the factorial function.
If we type \scheme{(define fact} followed by the enter key, the cursor
should be sitting under the first \scheme{e} in \scheme{define}, so that
if we then type \scheme{(lambda (x)}, we should see:
\schemedisplay
> (define fact
(lambda (x)
\endschemedisplay
The expeditor also allows us to move around within the expression
(even across lines) and edit the expression to correct mistakes.
After typing:
\schemedisplay
> (define fact
(lambda (x)
(if (= n 0)
0
(* n (fact
\endschemedisplay
we might notice that the procedure's argument is named \scheme{x}
but we have been referencing it as \scheme{n}.
We can move back to the second line using the arrow keys,
remove the offending \scheme{x} with the backspace key, and
replace it with \scheme{n}.
\schemedisplay
> (define fact
(lambda (n)
(if (= n 0)
0
(* n (fact
\endschemedisplay
We can then return to the end of the expression with the arrow
keys and complete the definition.
\schemedisplay
> (define fact
(lambda (n)
(if (= n 0)
0
(* n (fact (- n 1))))))
\endschemedisplay
Now that we have a complete form with balanced parentheses,
if we hit enter with the cursor just after the final parenthesis,
the expeditor will send it on to the evaluator.
We'll know that it has accepted the definition when we get another
right-angle prompt.
Now we can test our definition by entering, say, \scheme{(fact 6)}
in response to the prompt:
\schemedisplay
> (fact 6)
0
\endschemedisplay
The printed value isn't what we'd hoped for, since $6!$ is actually $720$.
The problem, of course, is that the base-case return-value \scheme{0}
should have been \scheme{1}.
Fortunately, we don't have to retype the definition to correct the
mistake.
Instead, we can use the expeditor's history mechanism to retrieve the
earlier definition.
The up-arrow key moves backward through the history.
In this case, the first up-arrow retrieves \scheme{(fact 6)}, and
the second retrieves the \scheme{fact} definition.
As we move back through the history, the expression editor shows us
only the first line, so after two up arrows, this is all we see of
the definition:
\schemedisplay
> (define fact
\endschemedisplay
We can force the expeditor to show the entire expression by typing
\scheme{^L} (control \scheme{L}, i.e., the control and \scheme{L} keys
pressed together):
\schemedisplay
> (define fact
(lambda (n)
(if (= n 0)
0
(* n (fact (- n 1))))))
\endschemedisplay
Now we can move to the fourth line and change the \scheme{0} to a
\scheme{1}.
\schemedisplay
> (define fact
(lambda (n)
(if (= n 0)
1
(* n (fact (- n 1))))))
\endschemedisplay
We're now ready to enter the corrected definition.
If the cursor is on the fourth line and we hit enter, however, it will
just open up a new line between the old fourth and fifth lines.
This is useful in other circumstances, but not now.
Of course, we can work around this by using the arrow keys to move
to the end of the expression, but an easier way is to type
\scheme{^J}, which forces the expression to be entered immediately
no matter where the cursor is.
Finally, we can bring back \scheme{(fact 6)} with another two
hits of the up-arrow key and try it again:
\schemedisplay
> (fact 6)
720
\endschemedisplay
To exit from the REPL and return back to the shell, we can type
\scheme{^D} or call the \scheme{exit} procedure.
The interaction described above uses just a few of the expeditor's
features.
The expeditor's remaining features are described in the following
section.
Running programs may be interrupted by typing the interrupt
character (typically \scheme{^C}).
In response, the
system enters a debug handler, which prompts for input with a
\scheme{break>} prompt.
One of several commands may be issued to the break handler (followed by a
newline), including
\begin{description}
\item[``e''] or end-of-file to exit from the handler and continue,
\item[``r''] to stop execution and reset to the current caf\'e,
\item[``a''] to abort {\ChezScheme},
\item[``n''] to enter a new caf\'e (see below),
\item[``i''] to inspect the current continuation,
\item[``s''] to display statistics about the interrupted program, and
\item[``?''] to display a list of these options.
\end{description}
When an exception other than a warning occurs, the default exception
handler prints a message that describes the exception to the console
error port.
If a REPL is running, the exception handler then returns to the REPL,
where the programmer can call the \scheme{debug} procedure to start up the
debug handler, if desired.
The debug handler is similar to the break handler and allows the
programmer to inspect the continuation (control
stack) of the exception to help determine the cause of the problem.
If no REPL is running, as is the case for a script or top-level program
run via the \index{\scheme{--script} command-line option}\scheme{--script}
or \index{\scheme{--program} command-line option}\scheme{--program}
command-line options, the default exception handler exits from the script
or program after printing the message.
To allow scripts and top-level programs to be debugged,
the default exception handler can be forced via the
\index{\scheme{debug-on-exception}}\scheme{debug-on-exception}
parameter or the
\index{\scheme{--debug-on-exception} command-line option}\scheme{--debug-on-exception} command-line option
to invoke \scheme{debug} directly.
Developing a large program entirely in the REPL is unmanageable, and we
usually even want to store smaller programs in a file for future use.
(The expeditor's history is saved across Scheme sessions, but there is a
limit on the number of items, so it is not a good idea to count on a
program remaining in the history indefinitely.)
Thus, a Scheme programmer typically creates a file containing Scheme
source code using a text editor, such as \scheme{vi}, and loads the file
into {\ChezScheme} to test them.
The conventional filename extension for {\ChezScheme} source files is
``\scheme{.ss},'' but the file can have any extension or even no extension
at all.
A source file can be loaded during an interactive session by typing
\index{\scheme{load}}\scheme{(load "\var{path}")}.
Files to be loaded can also be named on the command line when the
system is started.
Any form that can be typed interactively can be placed in a file to be loaded.
{\ChezScheme} compiles source forms as it sees them to machine
code before evaluating them, i.e., ``just in time.''
In order to speed loading of a large file or group of files, each file
can be compiled ahead of time via
\index{\scheme{compile-file}}\scheme{compile-file}, which puts the
compiled code into a separate object file.
For example, \scheme{(compile-file "\var{path}")} compiles
the forms in the file \var{path}.ss and places the
resulting object code in the file \var{path}.so.
Loading a pre-compiled file is essentially no different from
loading the source file, except that loading is faster since
compilation has already been done.
\index{\scheme{compile-file}}When compiling a file or set of files, it is often more convenient to
use a shell command than to enter {\ChezScheme} interactively to perform
the compilation.
This is easily accomplished by ``piping'' in the command to compile
the file as shown below.
\schemedisplay
echo '(compile-file "\var{filename}")' | scheme -q
\endschemedisplay
The \scheme{-q} option suppresses the system's greeting messages for more
compact output, which is especially useful when compiling numerous
files.
The single-quote marks surrounding the \scheme{compile-file} call
should be left off for Windows shells.
When running in this ``batch'' mode, especially from within ``make''
files, it is often desirable to force the default exception handler to exit
immediately to the shell with a nonzero exit status.
This may be accomplished by setting the
\index{\scheme{reset-handler}}\scheme{reset-handler} to
\scheme{abort}.
\schemedisplay
echo '(reset-handler abort) (compile-file "\var{filename}")' | scheme -q
\endschemedisplay
One can also redefine the
\index{\scheme{base-exception-handler}}\scheme{base-exception-handler}
(Section~\ref{SECTSYSTEMEXCEPTIONS}) to achieve a similar effect
while exercising more control over the format of the messages that
are produced.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Expression Editor\label{SECTUSEEXPEDITOR}}
When Chez Scheme is used interactively in a shell window, as described
above, or when \scheme{new-cafe} is invoked explicitly from a top-level
program or script run via \scheme{--program} or \scheme{--script}, the
waiter's ``prompt and read'' procedure employs an expression editor that
permits entry and editing of single- and multiple-line expressions,
automatically indents expressions as they are entered, supports
identifier completion outside string constants based on the identifiers defined
in the interactive environment, and supports filename completion within
string constants.
The expression editor also maintains a history of expressions typed during
and across sessions and supports tcsh-like history movement and search
commands.
Other editing commands include simple cursor movement via
arrow keys, deletion of characters via backspace and delete, and
movement, deletion, and other commands using mostly
emacs key bindings.
The expression editor does not run if the TERM environment variable is not
set (on Unix-based systems), if the standard input or output files have
been redirected, or if the \scheme{--eedisable} command-line option
(Section~\ref{SECTUSECOMMANDLINE}) has been used.
The history is saved across sessions, by default, in the file
``.chezscheme\_history'' in the user's home directory.
The \scheme{--eehistory} command-line option
(Section~\ref{SECTUSECOMMANDLINE}) can be used to specify a different
location for the history file or to disable the saving and restoring of
the history file.
Keys for nearly all printing characters (letters, digits, and special
characters) are ``self inserting'' by default.
The open parenthesis, close parenthesis, open bracket, and close bracket
keys are self inserting as well, but also cause the editor to ``flash''
to the matching delimiter, if any.
Furthermore, when a close parenthesis or close bracket is typed, it is
automatically corrected to match the corresponding open delimiter, if any.
Key bindings for other keys and key sequences initially recognized by
the expression editor are given below, organized into groups by function.
Some keys or key sequences serve more than one purpose depending upon
context.
For example, tab is used for identifier completion, filename completion,
and indentation.
Such bindings are shown in each applicable functional group.
Multiple-key sequences are displayed with hyphens between the keys of
the sequences, but these hyphens should not be entered.
When two or more key sequences perform the same operation, the sequences
are shown separated by commas.
Detailed descriptions of the editing commands are given in
Chapter~\ref{CHPTEXPEDITOR}, which also describes parameters that allow
control over the expression editor, mechanisms for adding or changing key
bindings, and mechanisms for creating new commands.
\xdef\cntl#1{\scheme{^#1}}
\newenvironment{expeditorblock}[1]
{\iflatex\par\smallskip\null\vbox\bgroup\fi #1:\par\begin{tabular}{ll}}
{\iflatex\\[-1em]\phantom{xxxxxxxxxxxxxxxxxxxxx}\fi\end{tabular}\iflatex\removelastskip\egroup\fi\par}
\bigskip
\begin{expeditorblock}{Newlines, acceptance, exiting, and redisplay}
enter, \cntl{M} & accept balanced entry if used at end of entry;\\
& else add a newline before the cursor and indent\\
\cntl{J} & accept entry unconditionally\\
\cntl{O} & insert newline after the cursor and indent\\
\cntl{D} & exit from the waiter if entry is empty;\\
& else delete character under cursor\\
\cntl{Z} & suspend to shell if shell supports job control\\
\cntl{L} & redisplay entry\\
\cntl{L}-\cntl{L} & clear screen and redisplay entry
\end{expeditorblock}
\begin{expeditorblock}{Basic movement and deletion}
leftarrow, \cntl{B} & move cursor left\\
rightarrow, \cntl{F} & move cursor right\\
uparrow, \cntl{P} & move cursor up; from top of unmodified entry,\\
& move to preceding history entry.\\
downarrow, \cntl{N} & move cursor down; from bottom of unmodified entry,\\
& move to next history entry\\
\cntl{D} & delete character under cursor if entry not empty,\\
& else exit from the waiter\\
backspace, \cntl{H} & delete character before cursor\\
delete & delete character under cursor
\end{expeditorblock}
\begin{expeditorblock}{Line movement and deletion}
home, \cntl{A} & move cursor to beginning of line\\
end, \cntl{E} & move cursor to end of line\\
\cntl{K},
esc-k & delete to end of line or, if cursor is at the end\\
& of a line, join with next line\\
\cntl{U} & delete contents of current line
\end{expeditorblock}
When used on the first line of a multiline entry of which only the first line
is displayed, i.e., immediately after history movement, \cntl{U} deletes the
contents of the entire entry, like \cntl{G} (described below).
\begin{expeditorblock}{Expression movement and deletion}
esc-\cntl{F} & move cursor to next expression\\
esc-\cntl{B} & move cursor to preceding expression\\
esc-\scheme{]} & move cursor to matching delimiter\\
\cntl{]} & flash cursor to matching delimiter\\
esc-\cntl{K},
esc-delete & delete next expression\\
esc-backspace,
esc-\cntl{H} & delete preceding expression
\end{expeditorblock}
\begin{expeditorblock}{Entry movement and deletion}
esc-\scheme{<} & move cursor to beginning of entry\\
esc-\scheme{>} & move cursor to end of entry\\
\cntl{G} & delete current entry contents\\
\cntl{C} & delete current entry contents; reset to end of history
\end{expeditorblock}
\begin{expeditorblock}{Indentation}
tab & re-indent current line if identifier/filename prefix\\
& not just entered; else insert completion\\
esc-tab & re-indent current line unconditionally\\
esc-\scheme{q},
esc-\scheme{Q},
esc-\cntl{Q} & re-indent each line of entry
\end{expeditorblock}
\begin{expeditorblock}{Identifier/filename completion}
tab & insert completion if identifier/filename prefix just\\
& entered; else re-indent current line\\
tab-tab & show possible identifier/filename completions at end\\
& of identifier/filename just typed, else re-indent\\
\cntl{R} & insert next identifier/filename completion
\end{expeditorblock}
Identifier completion is performed outside of a string constant, and filename
completion is performed within a string constant.
(In determining whether the cursor is within a string constant, the
expression editor looks only at the current line and so can be fooled
by string constants that span multiple lines.)
If at end of existing identifier or filename, i.e., not one just typed, the first tab
re-indents, the second tab inserts identifier completion, and the third
shows possible completions.
\begin{expeditorblock}{History movement}
uparrow, \cntl{P} & move to preceding entry if at top of unmodified\\
& entry; else move up within entry\\
downarrow, \cntl{N} & move to next entry if at bottom of unmodified\\
& entry; else move down within entry\\
esc-uparrow,
esc-\cntl{P} & move to preceding entry from unmodified entry\\
esc-downarrow,
esc-\cntl{N} & move to next entry from unmodified entry\\
esc-p & search backward through history for given prefix\\
esc-n & search forward through history for given prefix\\
esc-P & search backward through history for given string\\
esc-N & search forward through history for given string
\end{expeditorblock}
To search, enter a prefix or string followed by one of the search key
sequences.
Follow with additional search key sequences to search further backward or
forward in the history.
For example, enter ``(define'' followed by one or more esc-p key sequences
to search backward for entries that are definitions, or ``(define''
followed by one or more esc-P key sequences for entries that contain
definitions.
\begin{expeditorblock}{Word and page movement}
esc-\scheme{f},
esc-\scheme{F} & move cursor to end of next word\\
esc-\scheme{b},
esc-\scheme{B} & move cursor to start of preceding word\\
\cntl{X}-\scheme{[} & move cursor up one screen page\\
\cntl{X}-\scheme{]} & move cursor down one screen page
\end{expeditorblock}
\begin{expeditorblock}{Inserting saved text}
\cntl{Y} & insert most recently deleted text\\
\cntl{V} & insert contents of window selection/paste buffer
\end{expeditorblock}
\begin{expeditorblock}{Mark operations}
\cntl{@},
\cntl{}space,
\cntl{^} & set mark to current cursor position\\
\cntl{X}-\cntl{X} & move cursor to mark, leave mark at old cursor position\\
\cntl{W} & delete between current cursor position and mark
\end{expeditorblock}
\begin{expeditorblock}{Command repetition}
esc-\cntl{U} & repeat next command four times\\
esc-\cntl{U}-$n$ & repeat next command $n$ times
\end{expeditorblock}
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{The Interaction Environment\label{SECTUSEINTERACTIONENVIRONMENT}}
\index{top-level programs}\index{interactive top level}\index{interaction environment}%
In the language of the Revised$^6$ Report, code is structured into
libraries and ``top-level programs.''
The Revised$^6$ Report does not require an implementation to support
interactive use, and it does not specify how an interactive top level
should operate, leaving such details up to the implementation.
In {\ChezScheme}, when one enters definitions or expressions at the
prompt or loads them from a file, they operate on an
interaction environment, which is a mutable environment that initially
holds bindings only for built-in keywords and primitives.
It may be augmented by user-defined identifier bindings via top-level
definitions.
The interaction environment is also referred to as the top-level
environment, because it is at the top level for purposes of scoping.
Programs entered at the prompt or loaded from a file via \scheme{load}
should not be confused with RNRS top-level programs, which are
actually more similar to libraries in their behavior.
In particular, while the same identifier can be defined multiple times
in the interaction environment, to support incremental program
development, an identifier can be defined at most once in an RNRS
top-level program.
The default interaction environment used for any code that occurs outside
of an RNRS top-level program or library (including such code typed at
a prompt or loaded from a file) contains all of the bindings of the
\scheme{(chezscheme)} library (or \scheme{scheme} module, which exports the
same set of bindings).
This set contains a number of bindings that are not in the RNRS libraries.
It also contains a number of bindings that extend the RNRS counterparts in
some way and are thus not strictly compatible with the RNRS bindings for
the same identifiers.
To replace these with bindings strictly compatible with RNRS, simply
import the \scheme{rnrs} libraries into the interaction environment by
typing the following into the REPL or loading it from a file:
\schemedisplay
(import
(rnrs)
(rnrs eval)
(rnrs mutable-pairs)
(rnrs mutable-strings)
(rnrs r5rs))
\endschemedisplay
\index{\scheme{interaction-environment}}%
To obtain an interaction environment that contains all \emph{and only}
RNRS bindings, use the following.
\schemedisplay
(interaction-environment
(copy-environment
(environment
'(rnrs)
'(rnrs eval)
'(rnrs mutable-pairs)
'(rnrs mutable-strings)
'(rnrs r5rs))
#t))
\endschemedisplay
To be useful for most purposes, \scheme{library} and \scheme{import}
should probably also be included, from the \scheme{(chezscheme)} library.
\schemedisplay
(interaction-environment
(copy-environment
(environment
'(rnrs)
'(rnrs eval)
'(rnrs mutable-pairs)
'(rnrs mutable-strings)
'(rnrs r5rs)
'(only (chezscheme) library import))
#t))
\endschemedisplay
It might also be useful to include \scheme{debug} in the set of
identifiers imported from \scheme{(chezscheme)} to allow the debugger to be
entered after an exception is raised.
Most of the identifiers bound in the default interaction environment that
are not strictly compatible with the Revised$^6$ Report are variables bound to
procedures with extended interfaces, i.e., optional arguments or extended
argument domains.
The others are keywords bound to transformers that extend the Revised$^6$
Report syntax in some way.
This should not be a problem except for programs that count on
exceptions being raised in cases that coincide with the extensions.
For example, if a program passes the \scheme{=} procedure a single numeric
argument and expects an exception to be raised, it will fail in the
initial interaction environment because \scheme{=} returns \scheme{#t}
when passed a single numeric argument.
Within the default interaction environment and those created as described
above, variables that name built-in procedures are read-only, i.e.,
cannot be assigned, since they resolve to the read-only bindings exported
from the \scheme{(chezscheme)} library or some other library:
\schemedisplay
(set! cons +) ;=> \var{exception: cons is immutable}
\endschemedisplay
Before assigning a variable bound to the name of a built-in
procedure, the programmer must first define the variable.
For example,
\schemedisplay
(define cons-count 0)
(define original-cons cons)
(define cons
(lambda (x y)
(set! cons-count (+ cons-count 1))
(original-cons x y)))
\endschemedisplay
redefines \scheme{cons} to count the number of times it is called, and
\schemedisplay
(set! cons original-cons)
\endschemedisplay
assigns \scheme{cons} to its original value.
Once a variable has been defined in the interaction environment using
\scheme{define}, a subsequent definition of the same variable is equivalent
to a \scheme{set!}, so
\schemedisplay
(define cons original-cons)
\endschemedisplay
has the same effect as the \scheme{set!} above.
The expression
\schemedisplay
(import (only (chezscheme) cons))
\endschemedisplay
also binds \scheme{cons} to its original value.
It also returns it to its original read-only state.
The simpler redefinition
\schemedisplay
(define cons (let () (import scheme) cons))
\endschemedisplay
turns \scheme{cons} into a mutable variable with the same value as it
originally had.
Doing so, however, prevents the compiler from generating efficient code
for calls to \scheme{cons} or producing warning messages when
\scheme{cons} is passed the wrong number of arguments.
All identifiers not bound in the initial interaction environment and
not defined by the programmer are treated as ``potentially bound'' as
variables to facilitate the definition of mutually recursive
procedures.
For example, assuming that \scheme{yin} and \scheme{yang} have not
been defined,
\schemedisplay
(define yin (lambda () (- (yang) 1)))
\endschemedisplay
defines \scheme{yin} at top level as a variable bound to a procedure that calls
the value of the top-level variable \scheme{yang}, even though \scheme{yang}
has not yet been defined.
If this is followed by
\schemedisplay
(define yang (lambda () (+ (yin) 1)))
\endschemedisplay
the result is a mutually recursive pair of procedures that, when called,
will loop indefinitely or until the system runs out of space to hold the
recursion stack.
If \scheme{yang} must be defined as anything other than a variable, its
definition should precede the definition of \scheme{yin}, since the compiler
assumes \scheme{yang} is a variable in the absence of any indication to
the contrary when \scheme{yang} has not yet been defined.
\index{\scheme{free-identifier=?}}%
A subtle consequence of this useful quirk of the interaction environment is that
the procedure
\scheme{free-identifier=?} (Section~\ref{TSPL:SECTSYNTAXCASE} of {\TSPLFOUR})
does not consider unbound library identifiers to be equivalent to (as yet)
undefined top-level identifiers, even if they have the
same name, because the latter are actually assumed to be valid variable bindings.
\schemedisplay
(library (A) (export a)
(import (rnrs))
(define-syntax a
(lambda (x)
(syntax-case x ()
[(_ id) (free-identifier=? #'id #'undefined)]))))
(let () (import (A)) (a undefined)) ;=> #f
\endschemedisplay
\index{auxiliary keywords}%
If it is necessary that they have the same binding, as in the case where
an identifier is used as an auxiliary keyword in a syntactic abstraction
exported from a library and used at top level, the library should define
and export a binding for the identifier.
\schemedisplay
(library (A) (export a aux-a)
(import (rnrs) (only (chezscheme) syntax-error))
(define-syntax aux-a
(lambda (x)
(syntax-error x "invalid context")))
(define-syntax a
(lambda (x)
(syntax-case x (aux-a)
[(_ aux-a) #''okay]
[(_ _) #''oops]))))
(let () (import (A)) (a aux-a)) ;=> okay
(let () (import (only (A) a)) (a aux-a)) ;=> oops
\endschemedisplay
This issue does not arise when libraries are used entirely within other
libraries or within RNRS top-level programs, since the interaction
environment does not come into play.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Using Libraries and Top-Level Programs\label{SECTUSELIBRARIES}}
\index{libraries}%
\index{top-level-programs}%
An R6RS library can be defined directly in the REPL, loaded explicitly
from a file (using \scheme{load} or \scheme{load-library}), or loaded
implicitly from a file via \scheme{import}.
When defined directly in the REPL or loaded explicitly from a file, a
library form can be used to redefine an existing library, but
\scheme{import} never reloads a library once it has been defined.
A library to be loaded implicitly via \scheme{import}
must reside in a file whose name reflects the name of the library.
For example, if the library's name is \scheme{(tools sorting)}, the
base name of the file must be \scheme{sorting} with a valid extension, and
the file must be in a directory named \scheme{tools} which itself resides
in one of the directories searched by \scheme{import}.
The set of directories searched by \scheme{import} is determined by
the
\index{\scheme{library-directories}}\scheme{library-directories}
parameter, and the set of
extensions is determined by the
\index{\scheme{library-extensions}}\scheme{library-extensions}
parameter.
The values of both parameters are lists of pairs of strings.
The first string in each \scheme{library-directories} pair identifies a
source-file base directory, and the second identifies the corresponding
object-file base directory.
Similarly, the first string in each \scheme{library-extensions} pair
identifies a source-file extension, and the second identifies the
corresponding object-file extension.
The full path of a library source or object file consists of the source or
object base followed by the components of the library name, separated by
slashes, with the library extension added on the end.
For example, for base \scheme{/usr/lib/scheme}, library name
\scheme{(app lib1)}, and extension \scheme{.sls}, the full path is
\scheme{/usr/lib/scheme/app/lib1.sls}.
So, if \scheme{(library-directories)} contains the pathnames
\scheme{"/usr/lib/scheme/libraries"} and \scheme{"."}, and
\scheme{(library-extensions)} contains the extensions \scheme{.ss}
and \scheme{.sls}, the path of the \scheme{(tools sorting)}
library must be one of the following.
\schemedisplay
/usr/lib/scheme/libraries/tools/sorting.ss
/usr/lib/scheme/libraries/tools/sorting.sls
./tools/sorting.ss
./tools/sorting.sls
\endschemedisplay
When searching for a library, \scheme{import} first constructs a partial
name from the list of components in the library name, e.g., \scheme{a/b}
for library \scheme{(a b)}.
It then searches for the partial name in each pair
of base directories, in order, trying each of the source extensions then
each of the object extensions in turn before moving onto the next pair of
base directories.
If the partial name is an absolute pathname, e.g., \scheme{~/.myappinit}
for a library named \scheme{(~/.myappinit)}, only the specified absolute
path is searched, first with each source extension, then with each object
extension.
If the expander finds both a source file and its corresponding object
file, and the object file is not older than the source file, the
expander loads the object file.
If the object file does not exist, if the object file is older, or
if after loading the object file, the expander determines it was
built using a library or include file that has changed, the source
file is loaded or compiled, depending on the value of the parameter
\index{\scheme{compile-imported-libraries}}\scheme{compile-imported-libraries}.
If \scheme{compile-imported-libraries}
is set to \scheme{#t}, the expander
compiles the library via the value of the \scheme{compile-library-handler}
parameter, which by default calls \scheme{compile-library} (which is described below).
Otherwise, the expander loads the source file.
(Loading the source file actually causes the code to be compiled,
assuming the default value of \scheme{current-eval}, but the compiled
code is not saved to an object file.)
An exception is raised during this process if a
source or object file exists but is not readable or if an object
file cannot be created.
\index{\scheme{--import-notify} command-line option}%
\index{\scheme{import-notify}}%
The search process used by the expander when processing an \scheme{import}
for a library that has not yet been loaded can be monitored by
setting the parameter \scheme{import-notify} to \scheme{#t}.
This parameter can be set from the command line via the
\scheme{--import-notify} command-line option.
Whenever the expander determines it must compile a library to a file or
load one from source, it adds the directory in which the file resides to
the front of the
\index{\scheme{source-directories}}\scheme{source-directories}
list while compiling or loading the library.
This allows a library to include files stored in or relative to its
own directory.
When \scheme{import} compiles a library as described above, it does not
also load the compiled library, because this would cause portions of
library to be reevaluated.
Because of this, run-time expressions in the file outside of a
\scheme{library} form will not be evaluated.
If such expressions are present and should be evaluated, the library
should be compiled ahead of time or loaded explicitly.
\index{\scheme{compile-library}}%
\index{\scheme{compile-imported-libraries}}%
A file containing a library may be compiled with \scheme{compile-file}
or \scheme{compile-library}.
The only difference between the two is that the latter treats the source
file as if it were prefixed by an implicit \scheme{#!r6rs}, which
disables {\ChezScheme} lexical extensions unless an explicit
\scheme{#!chezscheme} marker appears in the file.
Any libraries upon which the library depends must be compiled first.
If one of the libraries imported by the library is subsequently
recompiled (say because it was modified), the importing library must also
be recompiled.
Compilation and recompilation of imported libraries must be done
explicitly by default but is done automatically when the parameter
\scheme{compile-imported-libraries} is set to \scheme{#t} before
compiling the importing library.
As with \scheme{compile-file}, \scheme{compile-library} can be used
in ``batch'' mode via a shell command:
\schemedisplay
echo '(compile-library "\var{filename}")' | scheme -q
\endschemedisplay
with single-quote marks surrounding the \scheme{compile-library} call
omitted for Windows shells.
An RNRS top-level-program usually resides in a file, but one can also
enter one directly into the REPL using the \scheme{top-level-program}
forms, e.g.:
\schemedisplay
(top-level-program
(import (rnrs))
(display "What's up?\n"))
\endschemedisplay
A top-level program stored in a file does not have the \scheme{top-level-program}
wrapper, so the same top-level program in a file is just:
\schemedisplay
(import (rnrs))
(display "What's up?\n")
\endschemedisplay
A top-level program stored in a file can be loaded from the file via the
\scheme{load-program} procedure.
A top-level program can also be loaded via \scheme{load}, but not without
affecting the semantics.
A program loaded via \scheme{load} is scoped at top level, where it can
see all top-level bindings, whereas a top-level program loaded via
\scheme{load-program} is self-contained, i.e., it can see only the
bindings made visible by the leading \scheme{import} form.
Also, the variable bindings in a program loaded via \scheme{load} also
become top-level bindings, whereas they are local to the program when
the program is loaded via \scheme{load-program}.
Moreover, \scheme{load-program}, like \scheme{load-library}, treats the
source file as if it were prefixed by an implicit \scheme{#!r6rs}, which
disables {\ChezScheme} lexical extensions unless an explicit
\scheme{#!chezscheme} marker appears in the file.
A program loaded via \scheme{load} is also likely to be less efficient.
Since the program's variables are not local to the program, the compiler
must assume they could change at any time, which inhibits many of its
optimizations.
\index{\scheme{compile-program}}%
Top-level programs may be compiled using
\index{\scheme{compile-program}}\scheme{compile-program}, which is like
\scheme{compile-file} but, as with \scheme{load-program}, properly
implements the semantics and lexical restrictions of top-level programs.
\scheme{compile-program} also copies the leading \scheme{#!} line,
if any, from the source file to the object file, resulting in an
executable object file.
Any libraries upon which the top-level program depends, other than
built-in libraries, must be compiled first.
The program must be recompiled if any of the libraries upon which
it depends are recompiled.
Compilation and recompilation of imported libraries must be done
explicitly by default but is done automatically when the parameter
\scheme{compile-imported-libraries} is set to \scheme{#t} before
compiling the importing library.
As with \scheme{compile-file} and \scheme{compile-library},
\scheme{compile-program} can be used in ``batch'' mode via a shell
command:
\schemedisplay
echo '(compile-program "\var{filename}")' | scheme -q
\endschemedisplay
with single-quote marks surrounding the \scheme{compile-program} call
omitted for Windows shells.
\scheme{compile-program} returns a list of libraries directly invoked by
the compiled top-level program.
When combined with the
\index{\scheme{library-requirements}}\scheme{library-requirements} and
\index{\scheme{library-object-filename}}\scheme{library-object-filename}
procedures, the list of libraries returned by \scheme{compile-program} can
be used to determine the set of files that must be distributed with the
compiled program file.
When run, a compiled program automatically loads the run-time code for
each library upon which it depends, as if via \scheme{revisit}.
If the program also imports one of the same libraries at run time, e.g.,
via the \scheme{environment} procedure, the system will attempt to load
the compile-time information from the same file.
The compile-time information can also be loaded explicitly from the
same or a different file via \scheme{load} or \scheme{visit}.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Scheme Shell Scripts\label{SECTUSESCRIPTING}}
\index{\scheme{--script} command-line option}%
\index{Scheme shell scripts}%
\index{scripting}%
When the \scheme{--script} command-line option is present, the named file is
treated as a Scheme shell script, and the command-line is made
available via the parameter
\scheme{command-line}.
This is primarily useful on Unix-based systems, where the script file
itself may be made executable.
To support executable shell scripts, the system ignores the first
line of a loaded script if it begins with \scheme{#!} followed by
a space or forward slash.
For example, assuming that the {\ChezScheme} executable has been
installed as /usr/bin/scheme, the following script prints its command-line
arguments.
\schemedisplay
#! /usr/bin/scheme --script
(for-each
(lambda (x) (display x) (newline))
(cdr (command-line)))
\endschemedisplay
The following script implements the traditional Unix \scheme{echo}
command.
\schemedisplay
#! /usr/bin/scheme --script
(let ([args (cdr (command-line))])
(unless (null? args)
(let-values ([(newline? args)
(if (equal? (car args) "-n")
(values #f (cdr args))
(values #t args))])
(do ([args args (cdr args)] [sep "" " "])
((null? args))
(printf "~a~a" sep (car args)))
(when newline? (newline)))))
\endschemedisplay
Scripts may be compiled using \index{\scheme{compile-script}}\scheme{compile-script}, which is like
\scheme{compile-file} but differs in that it
copies the leading \scheme{#!} line from the source-file script
into the object file.
If {\PetiteChezScheme} is installed, but not {\ChezScheme},
\scheme{/usr/bin/scheme} may be
replaced with \scheme{/usr/bin/petite}.
\index{\scheme{--program} command-line option}%
\index{top-level programs}%
The \scheme{--program} command-line option is like \scheme{--script}
except that the script file is treated as an RNRS top-level program
(Chapter~\ref{CHPTLIBRARIES}).
The following RNRS top-level program implements the traditional Unix
\scheme{echo} command, as with the script above.
\schemedisplay
#! /usr/bin/scheme --program
(import (rnrs))
(let ([args (cdr (command-line))])
(unless (null? args)
(let-values ([(newline? args)
(if (equal? (car args) "-n")
(values #f (cdr args))
(values #t args))])
(do ([args args (cdr args)] [sep "" " "])
((null? args))
(display sep)
(display (car args)))
(when newline? (newline)))))
\endschemedisplay
Again, if only {\PetiteChezScheme} is installed, \scheme{/usr/bin/scheme}
may be replaced with \scheme{/usr/bin/petite}.
\scheme{scheme-script} may be used in place of \scheme{scheme --program}
or \scheme{petite --program}, i.e.,
\schemedisplay
#! /usr/bin/scheme-script
\endschemedisplay
\scheme{scheme-script} runs {\ChezScheme}, if available,
otherwise {\PetiteChezScheme}.
It is also possible to use \scheme{/usr/bin/env}, as recommended in the
Revised$^6$ Report nonnormative appendices, which allows
\scheme{scheme-script} to appear anywhere in the user's path.
\schemedisplay
#! /usr/bin/env scheme-script
\endschemedisplay
\index{\scheme{--libdirs} command-line option}%
\index{\scheme{--libexts} command-line option}%
If a top-level program depends on libraries other than those built into
{\ChezScheme}, the \scheme{--libdirs} option can be used to specify
which source and object directories to search.
Similarly, if a library upon which a top-level program depends has an
extension other than one of the standard extensions, the
\scheme{--libexts} option can be used to specify additional extensions
to search.
\index{\scheme{library-directories}}%
\index{\scheme{library-extensions}}%
These options set the corresponding {\ChezScheme} parameters
\scheme{library-directories} and \scheme{library-extensions},
which are described in Section~\ref{SECTUSELIBRARIES}.
The format of the arguments to \scheme{--libdirs} and
\scheme{--libexts} is the same:
a sequence of substrings separated by a single separator
character.
The separator character is a colon (:), except under Windows where it is a
semi-colon (;).
Between single separators, the source and object strings, if both are
specified, are separated by two separator characters.
If a single separator character appears at the end of the string,
the specified pairs are added to the front of the existing list;
otherwise, the specified pairs replace the existing list.
For example, where the separator is a colon,
\schemedisplay
scheme --libdirs "/home/moi/lib:"
\endschemedisplay
adds the source/object directory pair
\schemedisplay
("/home/moi/lib" . "/home/moi/lib")
\endschemedisplay
to the front of the default set of library directories, and
\schemedisplay
scheme --libdirs "/home/moi/libsrc::/home/moi/libobj:"
\endschemedisplay
adds the source/object directory pair
\schemedisplay
("/home/moi/libsrc" . "/home/moi/libobj")
\endschemedisplay
to the front of the default set of library directories.
The parameters are set after all boot files have been loaded.
\index{CHEZSCHEMELIBDIRS}\index{CHEZSCHEMELIBEXTS}%
If no \scheme{--libdirs} option appears and the CHEZSCHEMELIBDIRS
environment variable is set, the string value of CHEZSCHEMELIBDIRS is
treated as if it were specified by a \scheme{--libdirs} option.
Similarly, if no \scheme{--libexts} option appears and the CHEZSCHEMELIBEXTS
environment variable is set, the string value of CHEZSCHEMELIBEXTS is
treated as if it were specified by a \scheme{--libexts} option.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Optimization\label{SECTUSEOPTIMIZATION}}
\index{optimization}To get the most out of the {\ChezScheme} compiler, it is necessary to
give it a little bit of help.
The most important assistance is to avoid the use of top-level
(interaction-environment) bindings.
Top-level bindings are convenient and appropriate during program
development, since they simplify testing, redefinition, and tracing
(Section~\ref{SECTDEBUGTRACING}) of individual procedures and
syntactic forms.
This convenience comes at a sizable price, however.
\index{copy propagation}\index{inlining}The compiler can propagate copies (of one variable to another or of
a constant to a variable) and inline procedures bound to local,
unassigned variables within a single top-level expression.
For the procedures it does not inline, it can avoid constructing and
passing unneeded closures, bypass argument-count checks, branch to the
proper entry point in a case-lambda, and build rest arguments (more
efficiently) on the caller side, where the length of the rest list is
known at compile time.
It can also discard the definitions of unreferenced variables, so there's
no penalty for including a large library of routines, only a few of
which are actually used.
It cannot do any of this with top-level variable bindings, since the
top-level bindings can change at any time and new references to those
bindings can be introduced at any time.
\index{libraries}%
\index{top-level-programs}%
Fortunately, it is easy to restructure a program to avoid top-level
bindings.
This is naturally accomplished for portable code by placing the
code into a single RNRS top-level program or by placing a portion
of the code in a top-level program and the remainder in one or
more separate libraries.
Although not portable, one can also put all of the code into a
single top-level \scheme{module} form or \scheme{let} expression,
perhaps using \scheme{include} to bring in portions of the
code from separate files.
The compiler performs some optimization even across library
boundaries, so the penalty for breaking a program up in this
manner is generally acceptable.
The compiler also supports whole-program optimization (via
\scheme{compile-whole-program}), which can be used to eliminate all
overhead for placing portions of a program into separate libraries.
Once an application's code has been placed into a single top-level program or into
a top-level program and one or more libraries, the code can be loaded
from source via \scheme{load-program} or compiled via
\index{\scheme{compile-program}}\scheme{compile-program}
and
\index{\scheme{compile-library}}\scheme{compile-library},
as described in Section~\ref{SECTUSELIBRARIES}.
Be sure not to use \scheme{compile-file} for the top-level program
since this does not preserve the semantics nor result in code that
is as efficient.
With an application structured as a single top-level program or as a
top-level program and one or more libraries that do not interact
frequently, we have done most of what can be done to help the compiler,
but there are still a few more things we can do.
\index{safety}\index{\scheme{optimize-level}}%
First, we can allow the compiler to generate ``unsafe'' code, i.e.,
allow the compiler to generate code in which the usual run-time type
checks have been disabled.
We do this by using the compiler's ``optimize level 3'' when compiling
the program and library files.
This can be accomplished by setting the parameter \scheme{optimize-level}
to 3 while compiling the library or
program, e.g.:
\schemedisplay
(parameterize ([optimize-level 3]) (compile-program "\var{filename}"))
\endschemedisplay
\index{\scheme{--optimize-level} command-line option}%
or in batch mode via the \scheme{--optimize-level} command-line option:
\schemedisplay
echo '(compile-program "\var{filename}")' | scheme -q --optimize-level 3
\endschemedisplay
It may also be useful to experiment with some of the other compiler
control parameters and also with the storage manager's run-time
operation.
The compiler-control parameters, including \scheme{optimize-level}, are
described in Section~\ref{SECTMISCOPTIMIZE}, and the storage manager
control parameters are described in Section~\ref{SECTSMGMTGC}.
\index{profiling}%
Finally, it is often useful to ``profile'' your code to determine that
parts of the code that are executed most frequently.
While this will not help the system optimize your code, it can help
you identify ``hot spots'' where you need to concentrate your own
hand-optimization efforts.
In these hot spots, consider using more efficient operators, like
fixnum or flonum operators in place of generic arithmetic operators,
and using explicit loops rather than nested combinations of
linear list-processing operators like \scheme{append}, \scheme{reverse},
and \scheme{map}.
These operators can make code more readable when used judiciously,
but they can slow down time-critical code.
Section~\ref{SECTMISCPROFILE} describes how to use the compiler's support
for automatic profiling.
Be sure that profiling is not enabled when you compile your production
code, since the code introduced into the generated code to perform the
profiling adds significant run-time overhead.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Customization\label{SECTUSECUSTOMIZATION}}
\index{customization}%
\index{kernel}%
\index{petite.boot}%
\index{scheme.boot}%
{\ChezScheme} and {\PetiteChezScheme} are built from several
subsystems: a ``kernel'' encapsulated in a static or shared
library (dynamic link library) that contains operating-system
interface and low-level storage management code,
an executable that parses command-line arguments and calls
into the kernel to initialize and run the system, a base
boot file (petite.boot) that contains the bulk of the run-time library code,
and an additional boot file (scheme.boot), for {\ChezScheme} only,
that contains the compiler.
While the kernel and base boot file are essential to the
operation of all programs, the executable may be replaced or
even eliminated, and the compiler boot file need be loaded only
if the compiler is actually used.
In fact, the compiler is typically not loaded for distributed
applications unless the application creates and executes code at run time.
The kernel exports a set of entry points that are used to initialize
the Scheme system, load boot or heap files, run an interactive Scheme
session, run script files, and deinitialize the system.
In the threaded versions of the system, the kernel also exports
entry points for activating, deactivating, and destroying threads.
These entry points may be used to create your own executable image
that has different (or no) command-line options or to run Scheme
as a subordinate program within another program, i.e., for use as
an extension language.
These entry points are described in Section~\ref{SECTFOREIGNCLIB},
along with other entry points for accessing and modifying Scheme
data structures and calling Scheme procedures.
\index{main.c}%
The file main.c in the 'c' subdirectory contains the
``main'' routine for the distributed executable image; look at
this file to gain an understanding of how the system startup
entry points are used.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Building and Distributing Applications\label{SECTUSEAPPLICATIONS}}
\index{applications}%
\index{distributing applications}%
Although useful as a stand-alone Scheme system,
{\PetiteChezScheme} was conceived as a run-time system for compiled
{\ChezScheme} applications.
The remainder of
this section describes how to create and distribute such applications
using {\PetiteChezScheme}.
It begins with a discussion of the characteristics of
{\PetiteChezScheme} and how it compares with {\ChezScheme},
then describes how to prepare application source code,
how to build and run applications, and how to distribute them.
\parheader{Petite Chez Scheme Characteristics}
Although interpreter-based, {\PetiteChezScheme} evaluates Scheme source
code faster than might be expected.
Some of the reasons for this are listed below.
\begin{itemize}
\item The run-time system is fully compiled, so library implementations
of primitives ranging from \scheme{+} and \scheme{car} to \scheme{sort}
and \scheme{printf} are just as efficient as in {\ChezScheme}, although
they cannot be open-coded as in code compiled by {\ChezScheme}.
\item The interpreter is itself a compiled Scheme application.
Because it is written in Scheme, it directly benefits from various
characteristics of Scheme that would have to be dealt with explicitly
and with additional overhead in most other languages, including
proper treatment of tail calls, first-class procedures, automatic
storage management, and continuations.
\item The interpreter employs a preprocessor that
converts the code into a form that can be interpreted
efficiently.
In fact, the preprocessor shares its front end with the compiler, and
this front end performs a variety of source-level optimizations.
\end{itemize}
\noindent
Nevertheless, compiled code is still more efficient for most
applications.
The difference between the speed of interpreted and compiled code
varies significantly from one application to another, but often amounts
to a factor of five and sometimes to a factor of ten or more.
Several additional limitations result from the fact that
{\PetiteChezScheme} does not include the compiler:
\begin{itemize}
\item The compiler must be present to process \scheme{foreign-procedure}
and \scheme{foreign-callable} expressions, even when these forms are
evaluated by the interpreter.
These forms cannot be processed by the interpreter alone, so
they cannot appear in source code to be processed by {\PetiteChezScheme}.
Compiled versions of \scheme{foreign-procedure} and \scheme{foreign-callable}
forms may, however, be included
in compiled code loaded into {\PetiteChezScheme}.
\item Inspector information is attached to code objects, which are
generated only by the compiler, so source information and variable names
are not available for interpreted procedures or continuations into
interpreted procedures.
This makes the inspector less effective for debugging interpreted code
than it is for debugging compiled code.
\item Procedure names are also attached to code objects, so while
the compiler associates a name with each procedure when
an appropriate name can be determined, the interpreter does not do so.
This mostly impacts the quality of error messages, e.g., an error message
might read ``incorrect number of arguments to \scheme{#<procedure>}''
rather than the likely more useful ``incorrect number of arguments to
\scheme{#<procedure \var{name}>}.''
\item The compiler detects, at compile time, some potential errors
that the interpreter does not detect and reports them via compile-time
warnings that identify the expression or the location in the source
file, if any, where the expression appears.
\item Automatic profiling cannot be enabled for interpreted code as it
is for compiled code when \scheme{compile-profile} is set to \scheme{#t}.
\end{itemize}
Except as noted above, {\PetiteChezScheme} does not restrict what
programs can do, and like {\ChezScheme}, it places essentially no
limits on the size of programs or the memory images they create,
beyond the inherent limitations of the underlying hardware or
operating system.
\parheader{Compiled scripts and programs}
One simple mechanism for distributing an application is to structure it as
a script or RNRS top-level program, use
\index{\scheme{compile-script}}\scheme{compile-script} or
\index{\scheme{compile-program}}\scheme{compile-program}, as appropriate
to compile it as described in Section~\ref{SECTUSESCRIPTING}, and
distribute the resulting object file along with a complete distribution of
{\PetiteChezScheme}.
When this mechanism is used on Unix-based systems, if the source file
begins with \scheme{#!} and the path that follows is the path to the
{\ChezScheme} executable, e.g., \scheme{/usr/bin/scheme}, the one at the
front of the object file should be replaced with the path to the
{\PetiteChezScheme} executable, e.g., \scheme{/usr/bin/petite}.
The path may have to be adjusted by the application's installation
program based on where {\PetiteChezScheme} is installed on the target
system.
When used under Windows, the application's installation program should
set up an appropriate shortcut that starts {\PetiteChezScheme} with the
\scheme{--script} or \scheme{--program} option, as appropriate, followed
by the path to the object file.
The remainder of this section describes how to distribute applications
that do not require {\PetiteChezScheme} to be installed as a stand-alone
system on the target machine.
\parheader{Preparing Application Code}
While it is possible to distribute applications in source-code form,
i.e., as a set of Scheme source files to be loaded into {\PetiteChezScheme}
by the end user, distributing compiled code has two major
advantages over distributing source code.
First, compiled code is usually much more efficient, as discussed in
the preceding section, and second, compiled code is in binary form and
thus provides more protection for proprietary application code.
Application source code generally consists of a set of Scheme source
files possibly augmented by foreign code developed specifically for the
application and packaged in shared libraries (also known as shared
objects or, on Windows, dynamic link libraries).
The following assumes that any shared-library source code has been
converted into object form; how to do this varies by platform.
(Some hints are given in Section~\ref{SECTFOREIGNACCESS}.)
The result is a set of one or more shared libraries that are loaded
explicitly by the Scheme source code during program initialization.
Once the shared libraries have been created, the next step is to
compile the Scheme source files into a set of Scheme object files.
Doing so typically involves simply invoking \index{\scheme{compile-file}}\scheme{compile-file},
\index{\scheme{compile-library}}\scheme{compile-library},
or
\index{\scheme{compile-program}}\scheme{compile-program},
as appropriate,
on each source file to produce the corresponding object file.
This may be done within a build script or ``make'' file via a
command line such as the following:
\schemedisplay
echo '(compile-file "\var{filename}")' | scheme
\endschemedisplay
\noindent
which produces the object file \scheme{filename.so} from the source
file \scheme{filename.ss}.
If the application code has been developed interactively or is usually
loaded directly from source,
it may be necessary to make some adjustments to a file to be
compiled if the file contains expressions or definitions that
affect the compilation of subsequent forms in the file.
This can be accomplished via \scheme{eval-when}
(Section~\ref{SECTMISCCOMPILEEVAL}).
This is not typically necessary or desirable if the application consists
of a set of RNRS libraries and programs.
You may also wish to disable generation of inspector information
both to reduce the size of the compiled application code and to
prevent others from having access to the expanded source code that
is retained as part of the inspector information.
To do so, set the parameter
\index{\scheme{generate-inspector-information}}\scheme{generate-inspector-information}
to \scheme{#f} while compiling each file
The downside of disabling inspector information is that the information
will not be present if you need to debug your application, so it is
usually desirable to disable inspector information only for production
builds of your application.
An alternative is to compile the code with inspector information enabled
and strip out the debugging information later with
\index{\scheme{strip-fasl-file}}\scheme{strip-fasl-file}.
The Scheme startup procedure determines what the system does when
it is started.
The default startup procedure loads the files listed on the command
line (via \scheme{load}) and starts up a new caf\'e, like this.
\schemedisplay
(lambda fns (for-each load fns) (new-cafe))
\endschemedisplay
The startup procedure may be changed via the parameter
\index{\scheme{scheme-start}}\scheme{scheme-start}.
The following example demonstrates the installation of a variant of the
default startup procedure that prints the name of each file before
loading it.
\schemedisplay
(scheme-start
(lambda fns
(for-each
(lambda (fn)
(printf "loading ~a ..." fn)
(load fn)
(printf "~%"))
fns)
(new-cafe)))
\endschemedisplay
A typical application startup procedure would first invoke the
application's initialization procedure(s) and then start the
application itself:
\schemedisplay
(scheme-start
(lambda fns
(initialize-application)
(start-application fns)))
\endschemedisplay
Any shared libraries that must be present during the running of an
application must be loaded during initialization.
In addition, all foreign procedure expressions must be executed
after the shared libraries are loaded so that the addresses
of foreign routines are available to be recorded with the resulting foreign
procedures.
The following demonstrates one way in which initialization might be
accomplished for an application that links to a foreign procedure
\scheme{show_state} in the Windows shared library \scheme{state.dll}:
\schemedisplay
(define show-state)
(define app-init
(lambda ()
(load-shared-object "state.dll")
(set! show-state
(foreign-procedure "show_state" (integer-32)
integer-32))))
(scheme-start
(lambda fns
(app-init)
(app-run fns)))
\endschemedisplay
\parheader{Building and Running the Application}
Building and running an application is straightforward once all shared
libraries have been built and Scheme source files have been compiled
to object code.
Although not strictly necessary, we suggest that you concatenate your
object files, if you have more than one, into a single object file
via the \scheme{concatenate-object-files} procedure.
Placing all of the object code into a single file
simplifies both building and distribution of applications.
For top-level programs with separate libraries,
\index{\scheme{compile-whole-program}}\scheme{compile-whole-program}
can be used to produce a single, fully optimized object file.
Otherwise, when concatenating object files, put each library after the
libraries it depends upon, with the program last.
With the Scheme object code contained within a single composite object file,
it is possible to run the application simply by loading the composite
object file into {\PetiteChezScheme}, e.g.:
\schemedisplay
petite app.so
\endschemedisplay
\noindent
where \scheme{app.so} is the name of the composite object file,
and invoking the startup procedure to restart the system:
\schemedisplay
> ((scheme-start))
\endschemedisplay
\noindent
The point of setting \scheme{scheme-start}, however, is to allow the
set of object files to be converted into a
\index{boot files}\emph{boot file}.
Boot files are loaded during the process of building the initial heap.
Because of this, boot files have the following advantages over ordinary
object files.
\begin{itemize}
\item Any code and data structures contained in the boot file or created
while it is loaded is automatically compacted along with the base run-time
library code and made static.
Static code and data are never collected by the storage manager, so
garbage collection overhead is reduced.
(It is also possible to make code and data static explicitly at any
time via the \scheme{collect} procedure.)
\item The system looks for boot files automatically in a set of standard
directories based on the name of the executable image, so you can
install a copy of the {\PetiteChezScheme} executable image under your
application's name and spare your users from supplying any command-line
arguments or running a separate script to load the application code.
\end{itemize}
\index{\scheme{scheme-start}}%
When an application is packaged into a boot file, the source code
that is compiled and converted into a boot file should set
\scheme{scheme-start} to a procedure that starts the application,
as shown in the example above.
The application should not be started directly from the boot file,
because boot files are loaded before final initialization of the
Scheme system.
The value of \scheme{scheme-start} is invoked automatically after
final initialization.
A boot file is simply an object file containing the code for
one or more source files, prefixed by a boot header.
The boot header identifies a base boot file upon which the application
directly depends, or possibly two or more alternatives upon which the
application can be run.
In most cases, petite.boot will be identified as the base boot
file, but in a layered application it may be another boot file of your
creation that in turn depends upon petite.boot.
The base boot file, and its base boot file, if any, are loaded
automatically when your application boot file is loaded.
Boot files are created with \index{\scheme{make-boot-file}}\scheme{make-boot-file}.
This procedure accepts two or more arguments.
The first is a string naming the file into which the boot header and
object code should be placed, the second is a list of strings naming base
boot files, and the remainder are strings naming input files.
For example, the call:
\schemedisplay
(make-boot-file "app.boot" '("petite") "app1.so" "app2.ss" "app3.so")
\endschemedisplay
creates the boot file app.boot that identifies a dependency upon petite.boot
and contains the object code for app1.so, the object code resulting from
compiling app2.ss, and the object code for app3.so.
The call:
\schemedisplay
(make-boot-file "app.boot" '("scheme" "petite") "app.so")
\endschemedisplay
creates a header file that identifies a dependency upon either
scheme.boot or petite.boot, with the object code from app.so.
In the former case, the system will automatically load petite.boot
when the application boot file is loaded, and in the latter it will
load scheme.boot if it can find it, otherwise petite.boot.
This would allow your application to run on top of the full
{\ChezScheme} if present, otherwise {\PetiteChezScheme}.
In most cases, you can construct your application
so it does not depend upon features of scheme.boot (specifically,
the compiler) by specifying only \scheme{"petite"} in the call to
\scheme{make-boot-file}.
If your application calls \scheme{eval}, however, and you wish to
allow users to be able to take
advantage of the faster execution speed of compiled code, then specifying
both \scheme{"scheme"} and \scheme{"petite"}
is appropriate.
Here is how we might create and run a simple ``echo'' application
from a Linux shell:
\schemedisplay
echo '(suppress-greeting #t)' > myecho.ss
echo '(scheme-start (lambda fns (printf "~{~a~^ ~}\n" fns)))' >> myecho.ss
echo '(compile-file "myecho.ss") \
(make-boot-file "myecho.boot" (quote ("petite")) "myecho.so")' \
| scheme -q
scheme -b myecho.boot hello world
\endschemedisplay
If we take the extra step of installing a copy of the {\PetiteChezScheme}
executable as \scheme{myecho} and copying \scheme{myecho.boot} into
the same directory as \scheme{petite.boot} (or set SCHEMEHEAPDIRS to
include the directory containing myecho.boot), we can simply invoke
\scheme{myecho} to run our echo application:
\schemedisplay
myecho hello world
\endschemedisplay
\parheader{Distributing the Application}
Distributing an application involves can be as simple as creating a
distribution package that includes the following items:
\begin{itemize}
\item the {\PetiteChezScheme} distribution,
\item the application boot file,
\item any application-specific shared libraries,
\item an application installation script.
\end{itemize}
\noindent
The application installation script should install {\PetiteChezScheme}
if not already installed on the target system.
It should install the application boot file in the same directory as
the {\PetiteChezScheme} boot file petite.boot is installed,
and it should install the application shared libraries, if any,
either in the same location or in a standard location for shared libraries
on the target system.
It should also create a link to or copy of the {\PetiteChezScheme}
executable under the name of your application, i.e., the name given
to your application boot file.
Where appropriate, it should also install desktop and start-menu
shortcuts to run the executable.
%----------------------------------------------------------------------------
%----------------------------------------------------------------------------
\section{Command-Line Options\label{SECTUSECOMMANDLINE}}
\index{command-line options}%
\index{\scheme{-q} command-line option}%
\index{\scheme{--quiet} command-line option}%
\index{\scheme{--script} command-line option}%
\index{\scheme{--program} command-line option}%
\index{\scheme{--libdirs} command-line option}%
\index{\scheme{--libexts} command-line option}%
\index{\scheme{--compile-imported-libraries} command-line option}%
\index{\scheme{--import-notify} command-line option}%
\index{\scheme{--optimize-level} command-line option}%
\index{\scheme{--debug-on-exception} command-line option}%
\index{\scheme{--eedisable} command-line-option}%
\index{\scheme{--eehistory} command-line-option}%
\index{\scheme{--enable-object-counts} command-line-option}%
\index{\scheme{--retain-static-relocation} command-line option}%
\index{\scheme{-b} command-line option}%
\index{\scheme{--boot} command-line option}%
\index{\scheme{--verbose} command-line option}%
\index{\scheme{--version} command-line option}%
\index{\scheme{--help} command-line option}%
\index{\scheme{--} command-line option}%
{\ChezScheme} recognizes the following command-line options.
\begin{tabular}{ll}
\scheme{-q}, \scheme{--quiet}
& ~~suppress greeting and prompt\\
\scheme{--script \var{path}}
& ~~run as shell script\\
\scheme{--program \var{path}}
& ~~run rnrs top-level program as shell script\\
\scheme{--libdirs \var{dir}:...}
& ~~set library directories\\
\scheme{--libexts \var{ext}:...}
& ~~set library extensions\\
\scheme{--compile-imported-libraries}
& ~~compile libraries before loading\\
\scheme{--import-notify}
& ~~enable import search messages\\
\scheme{--optimize-level 0 | 1 | 2 | 3}
& ~~set initial optimize level\\
\scheme{--debug-on-exception}
& ~~on uncaught exception, call \scheme{debug}\\
\scheme{--eedisable}
& ~~disable expression editor\\
\scheme{--eehistory off | \var{path}}
& ~~expression-editor history file\\
\scheme{--enable-object-counts}
& ~~have collector maintain object counts\\
\scheme{--retain-static-relocation}
& ~~keep reloc info for compute-size, etc.\\
\scheme{-b \var{path}}, \scheme{--boot \var{path}}
& ~~load boot file\\
\scheme{--verbose}
& ~~trace boot-file search process\\
\scheme{--version}
& ~~print version and exit\\
\scheme{--help}
& ~~print help and exit\\
\scheme{--}
& ~~pass through remaining args\\
\end{tabular}
\index{\scheme{-h} command-line option}%
\index{\scheme{--heap} command-line option}%
\index{\scheme{-s} command-line option}%
\index{\scheme{--saveheap} command-line option}%
\index{\scheme{-c} command-line option}%
\index{\scheme{--compact} command-line option}%
The following options are recognized but cause the system to print an
error message and exit because saved heaps are no longer supported.
\begin{tabular}{ll}
\scheme{-h \var{path}}, \scheme{--heap \var{path}}
& ~~load heap file\\
\scheme{-s[\var{n}] \var{path}}, \scheme{--saveheap[\var{n}] \var{path}}
& ~~save heap file\\
\scheme{-c}, \scheme{--compact}
& ~~toggle compaction flag\\
\end{tabular}
With the default \scheme{scheme-start} procedure (Section~\ref{SECTUSEAPPLICATIONS}),
any remaining command-line arguments are treated as the names of files
to be loaded before {\ChezScheme} begins interacting with the user, unless
the \scheme{--script} or \scheme{--program} is present, in which case the
remaining arguments are made available to the script via the \scheme{command-line}
parameter (Section~\ref{SECTUSEINTERACTION}).
Most of the options are described elsewhere in this chapter, and a few
are self-explanatory.
The remainder pertain to the loading of boot files at system start-up
time and are described below.
\index{boot files}%
\index{heap files}%
When {\ChezScheme} is run, it looks for one or more boot files
to load.
Boot files contain the compiled Scheme code that implements most of
the Scheme system, including the interpreter, compiler, and most
libraries.
Boot
files may be specified explicitly on the command
line via \scheme{-b}
options or implicitly.
In the simplest case, no \scheme{-b}
options
are given and the necessary boot
files are loaded
automatically based on the name of the executable.
For example, if the executable name is ``frob'', the
system looks for
``frob.boot'' in a set of standard directories.
It also looks for and loads any subordinate
boot files required
by
``frob.boot''.
Subordinate
boot files are also loaded automatically for the
first boot file
explicitly specified via the command line.
Each boot file must be listed before those that depend upon it.
The \scheme{--verbose} option may be used to trace the
file searching process and must appear before any boot
arguments for which search tracing is desired.
Ordinarily, the search for
boot files is limited to a set of
installation directories, but this may be overridden by setting
the environment variable \index{\scheme{SCHEMEHEAPDIRS}}\scheme{SCHEMEHEAPDIRS}.
\scheme{SCHEMEHEAPDIRS} should be a colon-separated list of directories, listed in
the order in which they should be searched.
Within each directory, the two-character escape sequence ``\scheme{%v}''
is replaced by the current version, and the two-character escape sequence
``\scheme{%m}'' is replaced by the machine type.
A percent followed by any other character is replaced by the second
character; in particular, ``\scheme{%%}'' is replaced by ``\scheme{%}'', and
``\scheme{%:}'' is replaced by ``\scheme{:}''.
If \scheme{SCHEMEHEAPDIRS} ends in a non-escaped colon, the default directories are
searched after those in \scheme{SCHEMEHEAPDIRS}; otherwise, only those listed in
\scheme{SCHEMEHEAPDIRS} are searched.
Under Windows, semi-colons are used in place of colons, and one additional
escape is recognized: ``\scheme{%x},'' which is replaced by the directory in
which the executable file resides.
The default search path under Windows consists of ``\scheme{%x}''
and ``\scheme{%x\..\..\boot\%m}.''
The registry key \scheme{HeapSearchPath} in
\scheme{HKLM\SOFTWARE\Chez Scheme\csv\var{version}}, where
\var{version} is the {\ChezScheme} version number, e.g.,
\scheme{7.9.4}, can be set to override the default search path,
and the \scheme{SCHEMEHEAPDIRS} environment variable
overrides both the default and the registry setting, if any.
Boot files consist of ordinary compiled code and consist of
a boot header and the compiled code for one or more
source files.
See Section~\ref{SECTUSEAPPLICATIONS} for instructions on how to create
boot files.
|