345 |
\label{sec:api} |
\label{sec:api} |
346 |
|
|
347 |
Functions that control CM's operation are accessible as members of a |
Functions that control CM's operation are accessible as members of a |
348 |
structure named {\tt CM}. Here is a description of the members of |
structure named {\tt CM}. This structure itself is exported from a |
349 |
this structure: |
library called {\tt host-cm.cm}. Other libraries can exploit CM's |
350 |
|
functionality simply by putting a {\tt host-cm.cm} entry into their |
351 |
|
own description files. Section~\ref{sec:dynlink} shows one |
352 |
|
interesting used of this feature. |
353 |
|
|
354 |
|
The library is pre-registered at the interactive prompt which is more |
355 |
|
than a mere convenience: Structure {\tt CM} must be known a-priori at |
356 |
|
top level because otherwise there would also be no way to make it known. |
357 |
|
|
358 |
|
Here is a description of the structure's members: |
359 |
|
|
360 |
\subsubsection*{Compiling} |
\subsubsection*{Compiling} |
361 |
|
|
1071 |
Less common kinds of rules can also be defined using the generic |
Less common kinds of rules can also be defined using the generic |
1072 |
interface {\tt Tools.registerClass}. |
interface {\tt Tools.registerClass}. |
1073 |
|
|
1074 |
|
\section{Example: Dynamic linking} |
1075 |
|
\label{sec:dynlink} |
1076 |
|
|
1077 |
|
Autoloading is convenient and avoids wasted memory for modules that |
1078 |
|
have not been mentioned yet. However, sometimes one wants to be more |
1079 |
|
aggressive and save the space needed for a function until---at |
1080 |
|
runtime---that function is actually being dynamically invoked. |
1081 |
|
|
1082 |
|
CM does not provide immediate support for this kind of {\em dynamic |
1083 |
|
linking}, but it is quite simple to achieve the effect by carefully |
1084 |
|
arranging some helper libraries and associated stub code. |
1085 |
|
|
1086 |
|
Consider the following module: |
1087 |
|
\begin{verbatim} |
1088 |
|
structure F = struct |
1089 |
|
fun f (x: int): int = |
1090 |
|
G.g x + H.h (2 * x + 1) |
1091 |
|
end |
1092 |
|
\end{verbatim} |
1093 |
|
|
1094 |
|
Let us further assume that the implementations of structures {\tt G} |
1095 |
|
and {\tt H} are rather large so that it would be worthwhile to avoid |
1096 |
|
loading the code for {\tt G} and {\tt H} until {\tt F.f} is called |
1097 |
|
with some actual argument. Of course, if {\tt F} were bigger, then we |
1098 |
|
also want to avoid loading {\tt F} itself. |
1099 |
|
|
1100 |
|
To achieve this goal, we first define a {\em hook} module which will |
1101 |
|
be the place where the actual implementation of our function will be |
1102 |
|
registered once it has been loaded. This hook module is then wrapped |
1103 |
|
into a hook library. Thus, we have {\tt f-hook.cm}: |
1104 |
|
\begin{verbatim} |
1105 |
|
Library |
1106 |
|
structure F_Hook |
1107 |
|
is |
1108 |
|
f-hook.sml |
1109 |
|
\end{verbatim} |
1110 |
|
|
1111 |
|
and {\tt f-hook.sml}: |
1112 |
|
|
1113 |
|
\begin{verbatim} |
1114 |
|
structure F_Hook = struct |
1115 |
|
local |
1116 |
|
fun placeholder (i: int) : int = |
1117 |
|
raise Fail "F_Hook.f: unitinialized" |
1118 |
|
val r = ref placeholder |
1119 |
|
in |
1120 |
|
fun init f = r := f |
1121 |
|
fun f x = !r x |
1122 |
|
end |
1123 |
|
end |
1124 |
|
\end{verbatim} |
1125 |
|
|
1126 |
|
The hook module provides a reference cell into which a function of |
1127 |
|
type equal to {\tt F.f} can be installed. Here we have chosen to hide |
1128 |
|
the actual reference cell behind a {\bf local} construct. Accessor |
1129 |
|
functions are provided to install something into the hook |
1130 |
|
({\tt init}) and to invoke the so-installed value ({\tt f}). |
1131 |
|
|
1132 |
|
With this preparation we can write the implementation module {\tt f-impl.sml} |
1133 |
|
in such a way that not only does it provide the actual |
1134 |
|
code but also installs itself into the hook: |
1135 |
|
\begin{verbatim} |
1136 |
|
structure F_Impl = struct |
1137 |
|
local |
1138 |
|
fun f (x: int): int = |
1139 |
|
G.g x + H.h (2 * x + 1) |
1140 |
|
in |
1141 |
|
val _ = F_Hook.init f |
1142 |
|
end |
1143 |
|
end |
1144 |
|
\end{verbatim} |
1145 |
|
\noindent The implementation module is wrapped into its implementation |
1146 |
|
library {\tt f-impl.cm}: |
1147 |
|
\begin{verbatim} |
1148 |
|
Library |
1149 |
|
structure F_Impl |
1150 |
|
is |
1151 |
|
f-impl.sml |
1152 |
|
f-hook.cm |
1153 |
|
g.cm (* imports G *) |
1154 |
|
h.cm (* imports H *) |
1155 |
|
\end{verbatim} |
1156 |
|
\noindent Note that {\tt f-impl.cm} must mention {\tt f-hook.cm} for |
1157 |
|
{\tt f-impl.sml} to be able to access structure {\tt F\_Hook}. |
1158 |
|
|
1159 |
|
Finally, we replace the original contents of {\tt f.sml} with a stub |
1160 |
|
module that defines structure {\tt F}: |
1161 |
|
\begin{verbatim} |
1162 |
|
structure F = struct |
1163 |
|
local |
1164 |
|
val initialized = ref false |
1165 |
|
in |
1166 |
|
fun f x = |
1167 |
|
(if !initialized then () |
1168 |
|
else if CM.make "f-impl.cm" then initialized := true |
1169 |
|
else raise Fail "dynamic linkage for F.f failed"; |
1170 |
|
F_Hook.f x) |
1171 |
|
end |
1172 |
|
end |
1173 |
|
\end{verbatim} |
1174 |
|
\noindent The trick here is to explicitly invoke {\tt CM.make} the |
1175 |
|
first time {\tt F.f} is called. This will then cause {\tt f-impl.cm} |
1176 |
|
(and therefore {\tt g.cm} and also {\tt h.cm}) to be loaded and the |
1177 |
|
``real'' implementation of {\tt F.f} to be registered with the hook |
1178 |
|
module from where it will then be available to this and future calls |
1179 |
|
of {\tt F.f}. |
1180 |
|
|
1181 |
|
For the new {\tt f.sml} to be compiled successfully it must be placed |
1182 |
|
into a library {\tt f.cm} that mentions {\tt f-hook.cm} and {\tt |
1183 |
|
host-cm.cm}. As we have seen, {\tt f-hook.cm} exports {\tt F\_Hook.f} |
1184 |
|
and {\tt host-cm.cm} is needed because it exports {\tt CM.make}: |
1185 |
|
\begin{verbatim} |
1186 |
|
Library |
1187 |
|
structure F |
1188 |
|
is |
1189 |
|
f.sml |
1190 |
|
f-hook.cm |
1191 |
|
host-cm.cm |
1192 |
|
\end{verbatim} |
1193 |
|
|
1194 |
|
\noindent{\bf Beware!} This solution makes use of {\tt host-cm.cm} |
1195 |
|
which in turn requires the SML/NJ compiler to be present. Therefore, |
1196 |
|
is worthwhile only for really large program modules where the benefits |
1197 |
|
of their absence are not outweighed be the need for the compiler. |
1198 |
|
|
1199 |
\section{Some history} |
\section{Some history} |
1200 |
|
|
1201 |
Although its programming model is more general, CM's implementation is |
Although its programming model is more general, CM's implementation is |