Transparent Modules with Fully Syntactic Signatures Zhong Shao Dept. of Computer Science Yale University New Haven, CT 06520 shao@cs.yale.edu Technical Report YALEU/DCS/TR-1181 (supersedes TR-1161) June 24, 1999 Abstract ML-style modules are valuable in the development and maintenance of large software systems, unfortunately, none of the existing languages support them in a fully satisfactory manner. The official SML’97 Definition does not allow higher-order functors, so a module that refers to externally defined functors cannot accurately describe its import interface. MacQueen and Tofte [26] extended SML’97 with fully transparent higher-order functors, but their system does not have a type-theoretic semantics thus fails to support fully syntactic signatures. The systems of manifest types [19, 20] and translucent sums [12] support fully syntactic signatures but they may propagate fewer type equalities than fully transparent functors. This paper presents a module calculus that supports both fully transparent higher-order functors and fully syntactic signatures (and thus true separate compilation). We give a simple typetheoretic semantics to our calculus and show how to compile it into an -like -calculus extended with existential types. 1 Introduction Modular programming is one of the most commonly used techniques in the development and maintenance of large software systems. Using modularization, we can decompose a large software project into smaller pieces (modules) and then develop and understand each of them in isolation. The key ingredients in modularization are the explicit interfaces used to model inter-module dependencies. Good interfaces not only make separate compilation type-safe but also allow us to think about large systems without holding the whole system in our head at once. A powerful module language must support equally expressive interface specifications in order to achieve the optimal results. 1.1 more, different applications of the same functor can share a single copy of the implementation (i.e., object code), even though each application may produce modules with different interfaces. Functors have proven to be valuable in the modeling and organization of extensible systems [1, 10, 6, 32]. The Fox project at CMU [1] uses ML functors to represent the TCP/IP protocol layers; through functor applications, different protocol layers can be mixed and matched to generate new protocol stacks with applicationspecific requirements. Also, a standard C++ template library written using the ML functors would not require nasty cascading recompilations when the library is updated, simply because ML functors can be compiled separately before even being applied. Unfortunately, any use of functors and nested modules also implies that the underlying module language must support higherorder functors (i.e., functors passed as arguments or returned as results by other functors), because otherwise, there is no way to accurately specify the import signature of a module that refers to externally defined functors. For example, if we decompose the following ML program into two smaller pieces, one for FOO and another for BAR: functor FOO (A : SIG) = ... ...... structure BAR = struct structure B = ... structure C = FOO(B) end the fragment for BAR must treat FOO as its import argument. This essentially turns BAR into a higher-order functor since it must take another functor as its argument. Without higher-order functors, we cannot fully specify the interfaces1 of arbitrary ML programs. The lack of fully syntactic (i.e., explicit) signatures also violates the fundamental principles of modularization and makes it impossible to support Modula-2 style true separate compilation [19]. Why higher-order functors? 1.2 Standard ML [27, 28] provides a powerful module system. The main innovation of the ML module language is its support of parameterized modules, also known as functors. Unlike Modula-3 generics [31] or C++ templates [37], ML functors can be typechecked and compiled independently at its definition site; further This research was sponsored in part by the Defense Advanced Research Projects Agency ITO under the title “Software Evolution using HOT Language Technology,” DARPA Order No. D888, issued under Contract No. F30602-96-2-0232, and in part by an NSF CAREER Award CCR-9501624, and NSF Grant CCR-9633390. The views and conclusions contained in this document are those of the authors and should not be interpreted as representing the official policies, either expressed or implied, of the Defense Advanced Research Projects Agency or the U.S. Government. Main challenges Supporting higher-order functors with fully syntactic signatures turns out to be a very hard problem. Standard ML (SML) [28] only supports first-order functors. MacQueen and Tofte [26, 38] extended SML with fully transparent higher-order functors but their scheme does not provide fully syntactic signatures. Independently, Harper and Lillibridge [12] and Leroy [19] proposed to use translucent sums and manifest types to model type sharing; their scheme 1 We only need to write the signatures for first-order functors if we use a special “compilation unit” construct with import and export statements, but reasoning such construct would likely require similar formalism as reasoning higher-order modules. EMC KMC FTC AMC Figure 1: Relationship among five different calculi because abstract types must be made concrete during the translation. The translation of translucent sums is even more problem with singleton and depenatic: Crary et al [8] have to extend dent kinds to capture the sharing information in the surface language. The translation based on our new interpretation rightly turns opaque modules and abstract types into simple existential types. Furthermore, it does not need to use singleton and dependent kinds. This is significant because typechecking singleton and dependent kinds is notoriously difficult [8]. The main challenge is thus to design a module language that satisfies all of the following properties: It must have fully syntactic signatures: if we split a program at an arbitrary point, the corresponding interface must be expressible using the underlying signature calculus. It must have simple type-theoretical semantics: a clean semantics makes formal reasoning easier; it is also a prerequisite for a simple signature calculus. In the rest of this paper, we first use a series of examples to informally explain the main ideas. We then present our new Extended Module Calculus (EMC) which supports both fully transparent higher-order functors and fully syntactic signatures. We demonstrate the expressiveness of EMC by translating a version of the Abstract Module Calculus (AMC) and a version of the Transparent Module Calculus (TMC) into the EMC calculus. Finally, to support type-directed compilation [18, 15, 35, 36], we show how EMC can be translated into a Kernel Module Calculus (KMC) and then to an -like Target Calculus (FTC). The relationship among these five calculi is depicted in Figure 1. It should support fully transparent higher-order functors: higher-order functors should be a natural extension of firstorder ones; simple ML functors can propagate type sharing from the argument to the result; higher-order functors should propagate sharing in the same way. It should support opaque types and signatures: type abstraction is the standard method of hiding implementation details from the clients of a module; the same mechanism should be applicable to higher-order functors as well. It should support efficient elaboration and implementation: a module system will not be practical if it cannot be typechecked and compiled efficiently; compilation of module programs should also be compatible with the standard typedirected compilation techniques [18, 15, 35, 36]. 1.3 TMC supports fully syntactic signatures but fails to propagate as much sharing as in the MacQueen-Tofte system. Leroy [20] proposed to use applicative semantics to model full transparency, but his signature calculus is not fully syntactic since it only handles limited forms of functor expressions; this limitation was lifted in Courant’s recent proposal [7], but only at the expense of putting arbitrary module implementation code into the interfaces, which in turn compromises the very benefits of modularization and makes interface checking much harder. 2 Informal Development 2.1 Fully transparent higher-order functors We first use a series of examples to show how the MacQueen-Tofte system [26] supports fully transparent higher-order functors. We start by defining a signature SIG and a functor signature FSIG: Our contributions signature SIG = sig type t val x : t end funsig FSIG = fsig (X: SIG): SIG This paper presents a higher-order module calculus that satisfies all of the above properties. We show that fully transparent higherorder functors can also have simple type-theoretic semantics so they can be added into ML-like languages while still supporting true separate compilation. Our key idea is to adapt and incorporate the phase-splitting interpretation of higher-order modules [14, 36] into a surface module calculus—the result is a new method that propagates more sharing information (across functor application) than the system based on translucent sums [12] and manifest types [19]. More specifically, given a signature or a functor signature , we extract all the flexible components in into a single higher-order “type-constructor” variable ; here, by flexible, we mean those undefined type or module components inside . We call such as the flexroot constructor of signature . We use to denote the kind of and to denote the instantiation of whose flexible components are redirected to the corresponding entries in . An opaque view of signature can be modeled as an existential type . A transparent view of can be obtained by substituting the flexroot of with the actual constructor information. Full transparency is then achieved by propagating the flexroot information through functor application. MacQueen and Tofte use strong sum to express the module type, so signature SIG is equivalent to a dependent sum type "!#% ! and signature FSIG is same as the dependent product type $& '()* . We also define a structure S with signature SIG, and two functors F1 and F2, both with signature FSIG: structure S = struct type t=int val x=1 end functor F1 (X: SIG) struct type t=X.t functor F2 (X: SIG) struct type t=int = val x=X.x end = val x=1 end Although SIG does not define the actual type for t, functor applications such as F1(S) will always re-elaborate the body of F1 with X bound to S, so the type identity of X.t (which is int) is faithfully propagated into the result F1(S). Now suppose we define the following higher-order functor which takes a functor F as argument and applies it to the previously defined structure S: Our new phase-splitting interpretation also leads to a simpler type theory for the system based on translucent sums and manifest types. Recent work on phase-splitting transformation [14, 36, 8] has shown that ML-like module languages are better understood by translating them into an -like polymorphic -calculus. These translations, however, do not support opaque modules very well functor APPS (F: FSIG) = F(S) We can then apply APPS to functors F1 and F2: 2 The abstract approach relies on signature subsumption and strengthening [12, 19] to propagate sharing information from the functor argument to the result. But the subsumption rules are not powerful enough to support fully transparent higher-order functors. Nevertheless, the abstract approach does have fully syntactic signatures; and having a functor parameter returning an abstract result is sometimes useful. Take the functor APPS as an example, sometimes we indeed want the parameter F to be a functor that always generate new types at each application. structure R = struct structure R1 = APPS(F1) structure R2 = APPS(F2) val res = (R1.x = R2.x) ............ end In the MacQueen-Tofte system, both APPS(F1) and APPS(F2) will re-elaborate the body of APPS which in turn re-elaborates the functor body in F1 and F2; it successfully infers that R1.x and R2.x all have type int, so the equality test (R1.x = R2.x) will typecheck. 2.3 MacQueen and Tofte [26] call functors such as APPS as fully transparent modules since they faithfully propagate all sharing information in the actual argument (e.g., F1 and F2) into the result (e.g., R1 and R2). Unfortunately, their scheme does not support fully syntactic signatures. If we want to turn module R into a separate compilation unit, we have no way to completely specify its import interface. More specifically, we cannot write a signature for APPS so that all sharing information in the argument is propagated into the result. The closest we get is to assign APPS with signature: Transparent modules with syntactic signatures We would like to extend the abstract approach to support fully transparent higher-order functors. Our key idea is to adapt and incorporate the phase-splitting interpretation of higher-order modules [14, 36] into a surface module calculus; the result is a new method that propagates more sharing information (across functor application) than the system based on translucent sums and manifest types. Given a signature or a functor signature , we extract all the flexible components in into a single higher-order “typeconstructor” variable ; here, by flexible, we mean those undefined type or module components inside . We call such as the flexroot constructor of signature . We use to denote the kind of and to denote the instantiation of with all of its flexible components referring to the corresponding entries in . An opaque view of signature can be modeled as an existential type B ; a transparent view of can be obtained by substituting all occurrences of in by an actual flexroot constructor. For example, the previous signature declaration: funsig BADSIG = fsig (F: FSIG): sig type t=int val x : t end But this would not work if R also contains the following code: functor F3(X: SIG) = struct type t=real val x=3.0 end structure R3 = APPS(F3) signature SIG = sig type t val x : t end Signature BADSIG clearly does not capture the sharing information propagated during the application of APPS(F3). The actual implementation of the MacQueen-Tofte system [36] memoizes a “skeleton” for each functor body to support re-elaboration, but this is clearly too complex to be used in a surface signature calculus. can be viewed as a template of form: 2.2 I#K9L where kind is equal to Q t AR>S . We use #t TUWV to denote the t component from a constructor record —this is to emphasize its difference from the module access paths in ML (e.g., X.t). 8:<;DC7E*F"0HGJI#K9LM=N2 Translucent sums and manifest types A more severe problem of the MacQueen-Tofte system is that it lacks a clean type-theoretic semantics: its typechecker must use an operational stamp generator to model abstract types; this makes it impossible to express the typing property in the surface signature calculus. In 1994, Harper and Lillibridge [12] and Leroy [19] proposed (independently) to use translucent sums and manifest types to model ML modules; the resulting framework—which we call it the abstract approach—has a clean type-theoretic equational theory on types; furthermore, both systems support fully syntactic signatures. Leroy [21] and Harper [16] have also shown that their systems are sufficiently expressive that it can type the entire module language in the official SML’97 Definition [28]. sig type t = #t Instantiating the flexroot of * yields a signature of form: 2OFP? val x : t end ? with constructor Q t int S sig type t = int val x : t end Meanwhile, the following SML code: structure X :> SIG = struct type t=int val x=1 end creates an opaque view of SIG so module X has type I#K9L XTYJZ \[OV , or expanded to: Unfortunately, in the case of higher-order functors, the abstract approach does not propagate as much sharing as one would normally expect in the MacQueen-Tofte system. For example, the previous equality test (R1.x = R2.x) would not typecheck in Harper and Leroy’s systems [12, 19]. In fact, the abstract approach treats the signature SIG as an existential type $&% +,*!- ! and () . The the signature FSIG as a dependent product functor APPS is assigned with the following signature type: ] F@0HG I-K3L =N2 sig type t = #t 2OFP? ? val x : t end . In the rest of this paper, we follow the abstract approach to treat signature matching as opaque by default. Given a module % % % identifier and a signature , we say that has signature if % has type can be ^_ 1`aXT9bZ \[OV . The abstract flexroot constructor in retrieved using dot% notation on existentials [5]—such notation is usually written as c-d_e , but in this paper we use a more concise % notation; we to represent the % will use the overlined identifier flexroot of . ."/10324.657098:<;>= 8:<;@?A= 8:<; Applying APPS to F1 or F2 always yields a new existential package *!- ! so R1.t and R2.t are two distinct abstract types. It is informative to compare flexroot with the notion% of access paths in the abstract approach [12, 19]. A type path ! in the 3 |Po_8:';pCpEqFir\0UG1} t I#K9L= . system based on translucent sums and manifest types may denote an type (as in dot notation). Under the flexroot notation, f % abstract ! always refers to an actual type definition—the ! component % % of module —which in turn is defined % as type gJ!<T V ; in other are now redirected to the words, all the flexible components in % abstract flexroot constructor . X 032 ] F\u{= 8:<;>j FPuwlm?A=N2U8:<;vj Fir'j lNlm? X } t I-K3L I#K9Ly I-K3L where kind is equal to (the algorithm calculating such kind is given later in Section 3.2). The flexroot of TFSIG has a different kind from that of NFSIG because functors with signature TFSIG } propagate more sharing information (e.g., t I-K3L ) than those with signature NFSIG. constructor of kind Notice how functor application propagates sharing r r into the return result: the flexroot of the result is Z X[ where is the flexroot of the functor itself and X is the flexroot of the actual argument. Combining all the flexible components into a single flexroot constructor makes it easier to propagate sharing information through functor application. For example, the earlier ML code: We can now write the fully transparent version of APPS as: functor F1(X: SIG) = struct type t=X.t val x=X.x end functor APPS (F: TFSIG) = F(S) creates a functor with type:2 . X 0h2 ] Fi= 8:<;kj F*lm?Y=N2 sig type t = X.t val x : t end and we can assign it with the following interface type: ? . F 0h2 ] FirP0UG1} t I#K9L=H|Po_8:';>j FirYlm?Y=N2H8:<;>j j ~ F t C S.t lNlm? or written as signature: or if we write it in an extended signature calculus: fsig (X: SIG): sig type t = X.t val x : t end fsig (F: TFSIG): sig type t= #t(F[{t=S.t}]) val x: t end Here, the type path X.t in the result signature really refers to type #t T X V . During functor application, we create a transparent view of the actual argument following signature SIG; we instantiate the flexroot X into an actual constructor and then propagate this information into the result signature. With proper syntactic hacks, this signature can even be written as: fsig (F: TFSIG): sig type t = #t(F(S)) val x : t end The idea gets more interesting in the higher-order case. Because all functors are abstract under the abstract approach, we first need to find a way to introduce transparent higher-order functors. SML’97 uses the “:” and “:>” notation to distinguish between transparent and opaque signature matching; we borrow the same notation and use it to specify the abstract and transparent functors. In the following example, as long as we assume that all module identifiers (e.g., F and S) referred inside the constructor context #t TY V are always referring to their constructor counterparts. Getting back to the earlier example in Section 2.1 where we apply APPS to functors F1 and F2, we see why both R1.t and R2.t are now equivalent to int. To apply APPS to F1 (or F2), we match F1 (or F2) against TFSIG and calculate the flexroot F of the actual argument; F is equal to \M Q t g!#TUWVS for F1 or \M Q t int S for F2; in both cases, the t component of the result is g!#T F Z Q'!" int S<[4V which ends up as int. funsig NFSIG = fsig (X: SIG):> SIG funsig TFSIG = fsig (X: SIG): SIG Signature NFSIG represents an abstract functor that always creates fresh new types at each application. Signature TFSIG represents a fully transparent functor that always propagates the sharing information from the actual argument (i.e., X) into the result. The definition of NFSIG introduces a template of form: n6o_8:';pCpEqFir\0UGJs\t I-K3L = . s\t I-K3L X 2.4 0h2 ] FPu= 8:<;vj FPuwlm?Y=N2 ] Fx= 8:';kj Fx-lm? Our syntactic signature looks similar to Leroy’s applicative-functor approach [20] where he can also assign APPS with a signature: I#K9Lzy where kind is just r QS . Notice NFSIG does not propagate any sharing information ( ) into the result signature; instead, each functor application always returns an existential package. For example, the abstract version of functor APPS: fsig (F: FSIG): sig type t=F(S).t val x: t end This similarity, however, stays only at the surface; the underlying interpretations of the two are completely different. Under the applicative approach, a functor with signature FSIG will always generate the same abstract type if applied to the same argument. Under our scheme, an abstract functor (with signature NFSIG) always generates a new type at each application while a transparent functor (with signature TFSIG) does not. We can simulate applicative functors by opaquely matching a functor against a transparent functor signature. For example, functor APPS (F: NFSIG) = F(S) is assigned with the following interface type: . F Relationship with Leroy’s applicative functors 0h2 ] Fir<= n6oa8:<;>j FirYlm?A=N2 ] FPu{= 8:<;vj FPuwlm? or written as signature: fsig (F: NFSIG):> SIG functor F3 :> TFSIG = F1 On the other hand, the definition of TFSIG introduces a template of form: Functor F3 would have type: 2 ] F r 0HG1} t I#K9LM= . we omitted the kind annotation for u to simplify the presentation; we will do the same in the rest of the paper if the kind is clear from the context. 4 X 032 ] F u = 8:';>j F u lm?Y=N2H8:<;>j F r j lNlm? X Module expression and declaration: path mexp ) ) mdec @M r< str <' *r end u fct TU 3VhY TN V TN)V" let in #! 1< ) Module signature and specification: sig spec ) ) r< <# end sig fsig TU {3V) 3p<! #! 1< H ctxt formation ctyp formation cexp formation spec formation sig formation mexp formation mdec formation ¡ ¢£ ¢¤( ¢¤ ¢ ¢£¥q ¢£¦q ctyp equivalence spec subsumption sig subsumption ¢£1§ ¢¤©¨ª ¢7¨ Figure 3: Static semantics for AMC: a summary Core language: ctyp cexp ) ) !YYM !"'< YM <' T sig ) A µ ¯O±{²a³ £´ < # («¬w­® «° r #< end VA¬­¶T sig < < end V T fsig TU i3V) VA¬­¶T fsig TU i36V*X1 V Elaboration context: ctxt r< J' _¬wM ­+ TU 3VA¬w­·TU 3 V Figure 2: Syntax of the abstract module calculus AMC T4!A¡VA¬w1­·T4!A'V TU HVA¬w­·TU HV T4!A9VA¬w­·T4!A¡¸M !AV Because F3 is abstracted over its flexroot information, applying F3 to equivalent constructors will still result in equivalent types (e.g., 2 j~ C lm? #t F3 t int ). Figure 4: Signature strengthening in AMC One problem of the applicative approach is that it solely relies on access paths to propagate sharing. Because access paths are not allowed to contain arbitrary module expressions (doing otherwise may break abstraction), the applicative approach cannot give an accurate signature to the following functor: first define an abstract module calculus that reviews the main ideas behind translucent sums and manifest types. We then present our new EMC calculus and show how it propagates more sharing than the abstract approach. 3.1 functor PAPP (F : FSIG) (X : SIG) = let structure Y = struct type t = X.t * X.t val x = X.x * X.x end in F(Y) We use the Abstract Module Calculus (AMC) [19] as a representative of the system based on translucent sums [12] and manifest types [19, 21]. The syntax of AMC is given in Figure 2. The static semantics for AMC is summarized in Figure 3. The complete typing rules are given in Figures 4 to 6 and in Appendix A. Leroy [20] did propose to type PAPP by “lambda-lifting” module Y out of PAPP, but this dramatically alters the program structure, making the module language impractical to program with. AMC is a typical ML-style module calculus containing constructs such as module expressions (mexp), module declarations (mdec), module access paths (path), signatures (sig, specifications (spec), core-language types (ctyp) and expressions (cexp). Following Leroy [21], we use , !A , and { to denote module, type, and value identifiers, and , ! , and for module, type, and value labels. We assume that each declaration or specification in AMC simultaneously defines an internal name (e.g., r< ¹ ) and an external label (e.g., , ! , r'). Given a structure str << * end or a signa ture sig << º end, declarations and specifications defined later can refer to those defined earlier using the internal names. However, to access the module components from outside, we must use the access paths such as M , M , and M ! where is another path and , , and ! are external labels. Our approach uses the flexroot constructor to propagate sharing. We can easily give PAPP an accurate signature: fsig (F : TFSIG) (X : SIG) : sig type t = #t (F({t= #t(X) * #t(X)})) val x : t end Notice we use TFSIG rather than NFSIG to emphasize that F is a transparent functor. 3 The abstract module calculus AMC Formalization Signatures are used to type module expressions. An AMC signature can be either a functor signature or a regular signature that contains an ordered list of module, type, and value specifications. A functor signature is written as fsig TU i{3V) where denotes the argument signature and the result signature. We borrow the SML’97 notation “:” and “:>” for signature matching and use it to specify the abstract and transparent functors. Because AMC only In this section we present an Extended Module Calculus (EMC) that supports both fully transparent higher-order functors and fully syntactic signatures. EMC is an extension of Leroy and Harper’s abstract module calculus [19, 21, 12] but with support for fully transparent functors. To make the presentation easier to follow, we 5 ¾¿ sig ¡ » i3½¼ ¢¤ ia¬¡ i Ç #< ¦À 3 < # end ¢¿ i{3Ƥ¥ fct TU i3Vh fsig TU i3V) r y y à M ! Mà Á ÂQ'! a º M ÁWT9 V ¢£1 6Ì£¥* let in ¥* u fsig TU i3V) ¢¿ q y r u u ¢¿ TN È V qQ¡ Mà q S T9 V ¤¥ ¢¾TU ¡ÍV"\TU i{3V Rules for reflexivity and transitivity are omitted: u × u r ÔÕÖ % '< % r r < < ¶ ¨¿ 6 sig end ¨ sig end r % r % end end ¨ sig ¢ sig % r r u ÆT4!A'iV"¨½!A ctyp ctxt 0Ó ) << fsig TU 3V3 ) <<¡g!#T9Ù(V ) <<'6Yv9 Module constructor and kind Ù mcon u Ç ¿ ¨ 6A 3 Ç ¿ ¨ r u r u ¢¾T fsig TU 3 V ) V@¨£T fsig TU 3 V ) V z¨¿ ¾ ¢¾TU 3VȨÂTU 3 V sig % r< r % '< × << º % Ô ÕÖ 6ºØp sig end ¨ sig end % % sig Ø end ¨ sig end r and ÎÂÏªÒ ¾¤( ¾¾TU{¡V"TU{HiV All in AMC (Figure 2) plus: % ¢¤ 0¡Ñ Ç ¨¿ ¾¿ Ç ¨¿ ¢¾TN)VÈq ¢£ ¾T4!Y¡iV"PT4!A¡V Figure 5: Selected typing rules for AMC: ÎÂϽР% r M @! ¼Ä ±Å TH << ¦À{VS r A µ r 6w #<<< ÀÉ À q £ ÀËÊ £ ´ '< r r str << end sig ' # end ¤¡ str end sig end ¢ r mcfd mknd mkfd § ¢¾T4! V"¨ÂT4! V Ü Û ) ) ) ) r u ir'<¡\ >9 ÙÚ¡Ù Z Ù [ QÛ #< ÛSJ¡g T9Ù(V !qr< < b Ù r y u QÜ <' ÜJS(' !P9Rª< v9 Figure 7: Syntax of the extended module calculus EMC £1§ ¢ ¾¾TU{HiV@¨ÂTUH V identifier i of signature isr strengthened to have signature _¬ i . u Functor application (e.g., TNu V ) can propagate the sharing information in the argument ( ) into the result signature—this is achieved byu substituting the formal parameter i with the actual argument (see Figure 5). Figure 6: Signature subsumption in AMC supports abstract functors, a functor signature in AMC always uses :> to specify its result. Later in Section 3.2, we’ll extend AMC with transparent functor signatures in the form of fsig TU i{3V3 . Unfortunately, this strengthening procedure has no effect on its functor components. In the higher-order case, functor application in AMC does not propagate as much sharing as one would normally expect in the MacQueen-Tofte system. In the following, we show how to extend AMC to support fully transparent functors. AMC allows two kinds of type specifications: flexible type specification (! ) and manifest type specification (! ). Figure 6 lists the standard signature subsumption rules. Manifest types can be made opaque when matched against flexible specifications. Subsumption on functor signatures is contra-variant on the argument but covariant on the result. 3.2 Figure 5 lists the formation rules for the AMC module expressions and declarations. AMC supports the usual set of module constructs r such as module access path ( ), structure definition (str << end), r u functor definition (fct TU *Vh ), functor application ( TN V ), signature matching (½) ), and the let expression. Most of the typing rules for AMC are straightforward: signature matching in AMC is done opaquely; to type a let expression, the result signature must not contain any references to locally defined module variables (i.e., is well formed in context but not 6 ; see Figure 5). The extended module calculus EMC The extended module calculus EMC contains the same set of module expressions and declarations as those in AMC. However, EMC uses a different method to propagate sharing information; this allows EMC to support fully transparent higher-order functors. EMC also has a more expressive signature calculus so that all functors in EMC have fully syntactic signatures. The syntax of EMC is given in Figure 7. The static semantics for EMC is summarized in Figure 8. The complete typing rules are given in Figures 9 to 15 and in Appendix B. Our typing rules can be directly turned into a type-checking algorithm because the signature subsumption rules are only used at functor application and opaque signature matching (the same is true for AMC). Type sharing in AMC is propagated through signature strengthening and functor application. Signature strengthening, which is defined in Figure 4, is a variation of dot notation [4]; a module 6 àaáâ"T sig Similar forms as those for AMC (Figure 3) plus: <' end V­+Q&àaáâ"TH à_áâ"T9V6­® àaáMâ@T fsig TU i{3V) V­® ¾Ù£ ¾¤Û¤Ü ¾ÙݧÝÙ ¾¤ÛÂ§Û Ü Þ¨ª ܨ¿Ü mcon formation mcfd formation mcon equivalence mcfd equivalence mknd subsumption mkfd subsumption r àaáMâ@T4! V­ !9R ¤¡ ß 37¼Í ¾ iqà_áâ@T9V µ ¢¤Ûi«qÜ>« ³ ¤´ << r' r< ÇQ¡Û '< ÛiSJ*QÜ <# ÜJS ¡ »>9 ©¼Í ¤q _¬Ùæê)ë Ô ëAì ±{²Aí ì Ô{ÕÖ T sig +ÇÙ r u Ù Z Ù [M ¤ ¢¾T4!qV6T4!9RkV à_áâ"TU HiV­ r ±¯ _¬T9Ù£àaáâ"T96VAV A µ « ¬*T9Ù¤ åV"­æ « ´ <' ³ £ r <# end VA¬T9Ù¤q åV­ sig < ' end T fsig TU i{3V) VA¬T9Ù¤q åV­ A>9 ãÇÙ£q 6 y Ç\v9 Ù£q Ù QS Figure 10: EMC kind calculation çèqéT9V Ù ÍQ<< > 9 << S Çg¸ T9Ù(V" u y à_áâ@T4! iV­ à_áâ@TU 3V­® >9àaáâT9V y VW#<à_áâ@THPV6S à_áâ@T9V6­® à_áâ@T9 6 V ­® y à_áâ@T fsig TU i{3V3 V­æ Figure 8: Static semantics for EMC: a summary r r fsig TU i{3V) y ¥ +U¬T9ÙºZ iU[_q 4V­+ T fsig TU i3V3 AV ¬T9Ù¤q åV­ fsig TU {3V) q ¬*T9g¸ T9Ù(V@q åV6­+ a UT 3VA¬T9Ù¤*Q'< >9 <' S{V­¶TU 3 V ¢ÇÙ£q äTU ÈÙ(V6\TU v9 åV T4!Y9VA¬T9Ù¤*Q'< ! 9R <<NS{V­·T4!A¡g!#T9Ù(VAV Figure 9: EMC constructor formation T4!Y'iVA¬*T9ÙÚq åV­¶T4!Y'iV TU{HiVA¬*T9Ù¤ åV6­îTU{HiV Figure 11: Signature strengthening in EMC The EMC signature calculus contains two new features that are not present in AMC: one is the new functor signature fsig TU V¡ used to specify transparent higher-order functors; another is a simple constructor calculus that captures the sharing information (using constructor Ù and kind ) and a new type expression gJ!<T9Ù(V that selects the type field ! from constructor Ù . specifically, given a signature (or a functor signature) , we extract all the flexible components in into a single constructor variable ; we call such as the flexroot constructor of signature . We use to denote the kind of and to denote the instantiation of whose flexible components are redirected to the corresponding entries in . An opaque view of signature can be modeled as an existential type º- . A transparent view of can be obtained by substituting the flexroot of with the actual constructor information. Full transparency is then achieved by propagating the flexroot information through functor application. Transparent functors can propagate more sharing than abstract functors. For example, suppose is defined as sig ! U! end, a functor with signature fsig TU i\#VaXD corresponds to an abstract functor whose application always produces a module with a new abstract type component ! . On the other hand, a functor with signature fsig TU ih6VPh corresponds to a fully transparent functor whose application always propagates the type information from its argument into its result. Both and can be calculated easily. Figure 10 shows how to deduce à_áâ@T9V — the kind of the flexroot constructor of a module with signature . Here, à_áâ@T9V­» means that the flexible constructor part of signature is of kind and à_áâ@THåVv­ïܸð means that the flexible part in specification is of kind field Ü ð (which denotes either Ü or empty field ). Notice in addition to the flexible type specifications (!A ), functor specifications are also considered as the flexible components. A transparent functor with TU *YVY is treated as a higher-order constructor signature fsig y of kind where and are the kinds for and . An abstract functor with signature fsig TU i6PVÈP is treated as a dummy constructor that returns an empty record kind. The constructor calculus itself (see Figure 7) is similar to those used in the -like polymorphic -calculi. In this paper, we assume conall types in the core language have kind R ; we use r to denote structor variables;r and we use the record kind and ¡ Q Ü < < Ü S y u function kind to type module constructors. A record constructor consists of a sequence of core-language types (marked by label ! ) and module constructors (marked by label ). Given a record constructor Ù , the selection form g¸ T9Ù(V is a module constructor equivalent to the field of Ù while g!<T9Ù(V is a corelanguage type expression equivalent to the ! field of Ù . Figure 9 gives the formation rules for the constructor calculus; other typing rules summarized in Figure 8 are given in Appendix B. Signature is calculated using a procedure similar to the idea of signature strengthening, but signature strengthening in EMC is very different from that in AMC: instead of relying on the access path to propagate sharing, EMC uses the flexroot constructor to The constructor calculus is designed to faithfully capture the sharing information inside all EMC module constructs. More 7 ñ ò two of these rules—module identifier and functor application—are different from those for AMC (Figure 5): Only A 3¾q 6 fct TU 3Vh¥ fsig TU 3V) ¤¡ str end sig end ¢ Ç r ¾¿ sig ¡ » i3½¼ ¢¤ a¬ #< À 3 < # end r y y à M ! Mà Á ÂQ'! a º M ÁWT9 V u fsig TU 36V*X1 * y r u ¢¿ NT V@Q i à ¤¥ ¢¾TU ¡ÍV"\TU i{3V r u u V3 V ¢£ ÆT4!A'iV ô Qq-< !9R << Sû­·T4!qV strengthen a signature. Given a signature and a constructor Ù of kind àaáMâ@T9V , signature strengthening _¬Ù returns the result of substituting the flexroot constructor in with Ù . We use the auxiliary procedures given in Figure 11 to deduce a¬{Ù . Here, _¬T9Ù·& åV­ø means that instantiating by constructor Ù of kind yields signature , and ¬*T9Ù¢P åV>­· means that strengthening specification by constructor Ù of kind yields specification . The additional kind parameter is used to identify the flexible components in a signature. For all other cases, ¤ ô ­æ Figure 14: Narrowing instantiated signatures in EMC a module of signature , we use the overlined identifier to refer to the flexroot constructor hidden inside i . This is a form of dot notation [5] where represents the abstract type defined by the existential package . In AMC, signature strengthening is applied to the access identifier ( i ) itself and hidden type components are represented using access paths ( ). EMC generalizes this idea so it can propagates more sharing than AMC does. Signature strengthening produces a special form of signature whose type components are fully defined and whose functor components have abstract result signatures. This special form, which we call it instantiated signature, can be accurately defined using the following grammar: X 0Ó ¾ ô ú­+Ù äTU {3V ô Q<< v 9 <' Sû­·TU bÙ(V Figure 13: Signature subsumption in EMC Íù and ÎÝÏ¿Ò ¤ Þ¨¿à_áâ@T9y V A 3ä ô ­+ y Ù ÙÚÝ\v9 Q à _S*T9Ù V ¾Ù£q y ô fsig ¢ÆT TU 3V) V TH V"­®Ù r u r u ¢¾T fsig TU i{3 V3 V@¨ÂT fsig TU i{3 V) V u ê)ë Ô{Õ ê Õ ë í ÔÕ í ê Ô íõ Ö ëAêXö ÕÔ í÷P²õ r u r u ¢¾T fsig TU 3 V ) V@¨ÚT fsig TU 3 V3 V 0¡Ñ ¾¤( ¾¾TU{¡V"TU{HiV A µ ¢¤ «ô ú­®Û « ð ³ £´ << r r ¢¾T sig <#w end V ô ­+QÛ ð # <Û ð S All subsumption rules in AMC (Figure 6) plus: r u r r ¨¿ ¢ 6Y 3 Ç ¨ r u ÆT fsig TU i{3 V3 VȨÂT fsig TU i{3 ¾¿ Ç ¨¿ ¢¾TN)VÈq ¢£ ¾T4!Y¡iV"PT4!A¡V Figure 12: Selected typing rules for EMC: ÎϪРX ¿ ¨ ó wô àaáâ"T96V­®Ù y u i à q S T9 V r A µ r 6w #<<< ÀÉ À q £ ÀËÊ £ ´ '< r r str << end sig ' # end ¢£1 6Ì£¥* let in ¥* ù Ù r M @! ¼Ä ±Å TH << À VS Figure 13 gives the additional signature subsumption rules for the EMC signatures. Subsumption on transparent functor signatures is also contra-variant on the argument and covariant on the r re-u sult. More interestingly, a transparent signature fsig r TU Yu VPh is a subtype of its abstract counterpart fsig TU qh VP) ; this is because we can always coerce a transparent functor into an abstract one by blocking all ofr its sharing information. Finally, an abstract u signature fsig TU Y u VP) is a subtype of its transparent counterpart if the result is an instantiated signature; this corresponds to the special case where the abstract version only hides a dummy constructor so it should be equivalent to the transparent version. r sig Íù << Í ù end fsig TU i¡3V) 3ù&#! 1< H Notice under this special form, the argument of a functor signature could still be an arbitrary EMC signature, but the result must always be abstract. The following lemma can be proved by structural induction on the EMC signatures: y r More u specifically, u a kind is a dummyr' kind if it is Q{S , or where is a dummy kind, or QÜ << ÜJS where all fields ÜJ have dummy kinds. Given a context and a constructor Ù , we say Ù is a dummy constructor if ©¥Ù¾i and is a dummy kind. A dummy constructor conveys no useful information thus it can be safely eliminated. It is easy to show that if is an instantiated signature then à_áâ@T9V is a dummy kind. Lemma 3.1 Given an EMC context , a signature , a kind , and a constructor Ù , if ¥ and úúÙ¢\ and ä +¨ à_áâ@T9V then a¬{Ù is an instantiated signature and Ǥ_¬Ù . Figure 12 gives the typing rules for the EMC module expressions and declarations. Intuitively, we say a module expression has signature if has type equal to (Aà_áâ"T9V-XT9_¬WV . Given 8 ¢ ô ­+Ù¤q ¢¾TU 3V ô TU 3 V­¶TU ÈÙ(V6\TU v9 åV ¢£1§ äT4!Y'V ô T4!Y# V"­ r r r r ô ­®Û ð Ü ð £1§ ÆTU{HiV ô TU¡H V ­æJ ¾T sig end V ô T sig end V­,Q{S*Q{S äT4! V ô ! ­îT4!iVT4!9RkV Ç { u u ¾T sig #< end V ô T sig <#× end V"­+Q{ü"ý¡SJQþÈýS r r r r ¾T sig '# end V ô T sig < 'A × end V6­+QÛð ü"ý'S*Q¡Üºð þÈý'S 6A r r r < <w end V ô T sig << × end V­+Ù¤ r ¾¾T sig Ø <<w end V ô T sig #< × end V­+Ù£q 6 Ø ¾T sig ¢Qü"ýSJ*QiþÈý¡S Ù¤ r u r r u r r y ¢ ¨¿ A i{3 ¨ ÙÝÝ\v9à_áâ@T9 V- QS àaáâ"T9 V r u r u ÆT fsig TU i3 6 V -ÿ1 V ô T fsig TU i{3 V) V­+Ù¤q kì õ#²õ wÿ¹È'¹H! ±² X r r ¢ ¨¿ y u u u r u r 6Y i3 ô + ­ Ù ÙÂÝ\>9àaáâ"T9 -V Q i à r u r u ÆT fsig TU i3 V"- ÿ1 V ô T fsig TU i{3 V3 V­ £ Ù q u u r y _S*T9Ù V úàaáMâ@T9 V kì õ#²õ wÿ¹È'¹H! ±² X QS ¢Ù¤ Figure 15: Narrowing instantiated signatures in EMC (alternative version) This alternative signature narrowing procedure can also be used to verify the signature subsumption relation defined in Figure 13. To check if a functor signature is a subtype of another signature , we first compare their corresponding argument signatures, then compare their result signatures, and finally in the case that is abstract and is transparent, we invoke the signature narrowing procedure in Figure 15. If this algorithm does not get stuck, then is a sub-signature of . Only two of the typing rules in Figure 12 are different from those for AMC (in Figure 5): one for module identifier and another for functor application. To access a module identifier i , we always strengthen r u it with its flexroot constructor i . To type functor application TN V , we first notice that the typing rules for access paths (in Figure 12) satisfies the following property: if ¢q , then is an instantiated signature. This observation r can be easily established via Lemma 3.1. So we can assume has signature u is an ; furthermore, fsig TU {3V) and has signature r u instantiated signature. Typing TN V then involves checkingu if subsumes , extracting the actual flexroot information in (let’s call it Ù ), and substituting all instances of i in with construcu tor Ù and all instances of (not counting ) with access path . Here, the substitution on is the key on why can propagate more sharing and support fully transparent higher-order functors. Lemma 3.3 Given an EMC context , a signature , and an instantiated signature , if ô î­ Ù then ¤ §Ýà_áâ@T9V and Ù . Lemma 3.4 Given an EMC context , a signature , and an constructor Ù , if ¢ÇÙ£qà_áâ@T9V then ¢Ç_¬Ù£¨¿ . Constructoru Ù can be extracted from the actual argument signature of using the signature-narrowing procedure defined in Figure 14. This procedure is initially invoked upon instantiated signatures only. Given a context , the deduction úä ô ­ Ù extracts the type components from an instantiated signature and produces a constructor Ù of kind ; the specification counã ô Ë­øÛð extracts the type components in terpart and produces either Û or empty field . The side condition ¶,Ù ensures that Ù only contains identifiers defined in . We can prove the following lemma using structural induction on the EMC signatures: Lemma 3.5 Given an EMC context , two signature and , and an instantiated signature , if Ý¿ ¨¿ and ô p­®Ù£q then ô D­+Ù£q Lemma 3.6 Given an EMC context , a signature , and an instantiated signature , then ä 6¨Ú is true if and only if Ç ô D­+Ù£q succeeds. Ù·k , Proof: For the “if” part: assuming ãÌ _ô Æ­ we use structural induction on ; along the process, we create a bridging signature S’=S / C and and also show ¶, ¨Æ ; this bridge and the fact ǤM¨¿ (via Lemma 3.4) are used to connect a transparent functor signature to its abstract counterpart. For the “only if” part: we use structural induction on the size of the instantiated signature and show that if BB M¨¿ is true then Ú ô D­+Ù£q will not get stuck. The only nontrivial case r u is when is an abstract functor signature fsigr TU ii¡ u V)7 while is a transparent signature fsig TU \ Vv ; because Þ© Ȩ¤ , there must exist an instantiated bridging signature r r u u u u u such that 6Y i*Y ¾ ¨Â and 6Y iu*Y ¾ u ¨Ý ; u u u because is instantiated, we have ½p ô u ­+Ù u u from u ­ Ù from the induction hypothesis and î ô Lemma 3.5. Lemma 3.2 Given an EMC context , a signature , and an instantiated signature , let æà_áâ@T9V , if ã ¨© and wô ­®Ù , then ÇÙ¤ . Figure 15 gives an alternative signature narrowing procedure. This procedure is defined over arbitrary signatures, but it is initially invoked upon a instantiated signature only. Given a context , the deduction ^z ô ­+Ù¤ extracts the type components from an instantiated signature and produces a flexroot constructor Ù of kind (for signature ); the specification counterpart ^7 ô "­ïÛ ð _Ü ð extracts the type components in and produces either Û of kind Ü or empty field . We use ü"ý and þÈý to denote a sequence of constructor fields and kind fields. The side conditions ¶·Ù and ¶¶Qü"ýSD"QþÈý¡S ensures that Ù and ü"ý only contain identifiers defined in . It is easy to show that two signature narrowing procedures produce equivalent results. Given an EMC context , we say two signatures and are equivalent, denoted as 7Bp§Ý , if and only if both 7Dz¨¿ and ¥ ¨Ú are true. The following propositions show why the typing rules for EMC can hold together: 9 Lemma 3.7 Given an EMC context , a signature , and u an instantiated signature , assume Ǥ M¨¿ and y Ç ^ y * u à ٠à S , Q i and ä ô àaáâ"T96V"­,Ù , and rlet Á¦£ u r then (1) givenu two type expressions r and u , if 6A {3 r D and u A 3Ý7 and 6A 3Ý7 § then ¿7ÁWTU V§ÁWTU V ; r u (2) given two instantiated signatures and , if 6A 6 r u r u and 6A _» and A _ §, then r u ¢ÚÁWT9 V§ÁWT9 V . which in turn is equivalent to: ] F@0HG =N2 sig type t = #s 2mFP? #s 2mFP? val f: t end ? where kind is just Q s _R>S . In other words, if we write each signature as a template of \Ji , the hidden type specifications will be present in the kind but not in the body signature . Notice before this extension, is always equivalent to à_áâ@T9V , so all components in are always present in . Theorem 3.8 (unique typing) Given an EMC context , two signatures and , and a module expression , if ÇÚ¥q and ¢£¥q then p§Ý . 4 Expressiveness In this section, we show that both the translucent-sum-based calculus and the strong-sum-based calculus can be embedded into our EMC calculus. We also compare EMC with the stamp-based semantics of the MacQueen-Tofte system [26, 36]. Proof: Expand this theorem to cover module declarations and core language expressions; the generalized version of this theorem can be proved by structural induction on the derivation tree. 3.3 Discussions and extensions 4.1 The EMC calculus given so far only allows abstract or fully transparent result signatures. We could extend the EMC signature calculus further to support partially transparent functors: sig We use the AMC calculus presented in Section 3.1 as a representative for the system based on translucent sums [12] and manifest types [19]. Because AMC is a subset of EMC, the translation from AMC to EMC (denoted as h ) is just an identity function, We can show that this translation h maps all well typed AMC programs into well-typed EMC programs. <' fsig TU 3VÈ pv T9 å V ) Here, pv is a modifier that indicates the result signature is partially transparent, and the kind is used to fine tune the amount of sharing being propagated through functor application; a well-formed signature must have ÇàaáMâ@T9 VȨ so that the kind annotation actually make sense. Theorem 4.1 Given an AMC context , we have More aggressively, we could instead extend EMC with an abstract module specification of form: spec ) #<< i{) This seems to be less adhoc than the pv keyword but it makes it harder to reuse large signatures with small changes of transparency notations. EMC can also be extended to support other forms of module expressions in SML’97. For example, in SML’97, the let expression (at the module level) allows its body type to refer to the new type stamps generated in the let declarations. Also, SML’97 supports transparent signature matching such as: y s, but the new type s is not Here, type t is equivalent to s exported. Both of these features involve exporting values and types that make use of hidden abstract types. While it is doubtful that such extension is really useful in practice, we can support it easily by extending the EMC signature calculus with the following new form of type specifications: ) if ¥ú¡ is a valid AMC deduction then 4Ú¡ valid in EMC; similarly, if ¤ then 4 4 ; if J{ then U U 4 ; H ; if Ç then U ª 4 º U ; if ¤¥q then 4 ¿ 4 º U ; if ¤1 then 4 ª 4 ( § O . if ¤¦§ then U ¿ H ¨ H . if Çz¨¿ then U is Proof: By structural induction on the derivation tree. The main difference between EMC and AMC is the way how module identifiers and functor applications are typed. For the case of module identifiers, we use the following lemma (Lemma 4.2); for the case of functor application, notice the result of any AMC functor signature does not contain any reference to the flexroot constructor so the typing rules for AMC and EMC have the same behavior. structure A : sig type t val f : t end = struct abstype s = ... type t = s -> s fun f (x : s) = x end spec The abstract module calculus AMC Lemma 4.2 Given an AMC context , suppose is an AMC signature and -¼z , then U H_¬ § H ¬ is a valid deduction in EMC. Proof: Notice _¬ refers to the strengthening operation for AMC (as in Figure 4) while H ¬ refers to the strengthening operation for EMC (as in Figure 11). To prove this lemma, we need to show the following: given an EMC type path M ! , let i be the root identifier in , and ÛTNWV denotes the EMC constructor if , and g¸ THÛTN VAV if 7 , then the judgement D¦a !§ÂgJ!<THÛTNWVAV is valid in EMC. '<#!A hidden We can then write down the interface for A as: sig type s is hidden type t = s -> s val f : t end 10 ! path mexp ) ) ) ) ) ctyp ctme ) ) ) ) ctce ) ctxt ) sig ctsp cexp mtyp ' . r u " TNWV6" TNWV r u+ #%$THV"#%&#r T('MV"u *)U È r u \ >3 Y TN V@ let b r in u $ r u V (T 'MV6 TYP ¡@ v3 >3 ",&-TNWV6<< " $ TNWV6<< r u $ V TUV6 EQ TUV"¡@ > r - u - $ vr %.b u V TUV6 TYP ¡@ v% . . v% . . " & TU V"#< #%$TH V@ #&wTUiV6¡\ v% .b r u r u TU V@ let È in r u r u + )U È " TU V6 " TU V " $ TU V6<' ctxt-to-ctxt translation ctsp-to-ctyp translation sig-to-sig translation cexp-to-cexp translation path-to-path translation mexp-to-mexp translation ctyp-to-ctyp translation mtyp-to-sig translation mtyp-to-sig translation mtyp-to-kind translation mtyp-to-kind translation mtyp-to-mcon translation ctme-to-mcon translation Ãy , ¦Ã y 44' à ¢£6 5¶ ¢7 -85ï ¢/ .y 5ï 9-:; à y <.= ;kà ¢7 -85ïÙ ¢£ * -85ïÙ U' y Figure 18: Translation from TMC to EMC: a summary ctxt formation mtyp formation ctyp formation ctme formation ctce formation ¤¾¡ and /. Ç cexp formation mexp formation sig formation ctsp formation Ç( / ' ctyp equivalence mtyp equivalence mtyp subsumption mtyp strengthening r u r § u r u or ¾/. §0. § 0 - ¨1. .@¬¡ 2 ­ - A module expression in TMC can either be an access path ( ), a single-value-component module ( #%$*TH{V ), a single-type-component module r# u + ( # & THV ), a strong sum of two module components r u ( )U p ), a functor ( \ ), a functor application ( TN V ), or a let expression. To simplify the presentation, we restrict the TMC applir functor u cation to work on simple access only (i.e., TN V ). Arbitrary r paths u functor applications (e.g., TU V ) can just be A-normalized into the restricted form using let expressions. We also do not support type abbreviations in signatures. We insist that - be a subtype of . if they have same number of components (see the subtyping rules ¢ - 1 ¨ . in Appendix C ). These restrictions do not affect the main result because it is easy (but tedious) to extend TMC and the TMC-to-EMC translation to support the additional features. Figure 18 summarizes the translation from TMC to EMC; the actual definition is given in Appendix D. Here, h maps TMC contexts, core types (in signatures), signatures, core expressions, access paths, and module expressions into their EMC counterparts; h ; maps TMC module types into EMC kinds. The translation from TMC types to EMC types is based on the type formation rules, so the judgement £Ý6 5î maps the TMC core type into an ->5ï and Ç? .5 EMC core type ; the judgements / map the TMC module types - or . into an EMC signature . We also use judgements ª@ -85ïÙ and 7 A -85 Ù to map TMC module types and expressions (embedded inside core types) into EMC constructors. We can prove the following type preservation theorem for the TMC-to-EMC translation: Figure 17: Static semantics for TMC: a summary The transparent module calculus TMC We use the Transparent Module Calculus (TMC) as a representative of the strong-sum-based approach. The syntax of TMC is given in Figure 16; the static semantics is summarized in Figure 17; the complete typing rules are given in Appendix C. Theorem 4.3 Given a TMC context , we have: Following other strong-sum-based module systems [26, 28, 36], we distinguish module signatures ( ) from module types ( - and . ): module signatures are source-level specifications while module types are semantic objects used for typechecking. A module signature can either contain a single value specification (V T('MV ), a single type specification r u (TYP), or a pair of two other module components ( @ å \ ); it can also be a functor $ r u signature ( ). Only simple access paths (" & TNiV ) are allowed in a specification.3 An . -shaped module type is like a module signature except that in its value specification V TUV , core type can contain arbitrary module expressions ( ). - -shaped module types are slightly different from . -shaped ones: they allow manifest types (or type abbreviations) of form EQ TUiV but no flexible type specification of form TYP. The module expression inside the core type helps achieve the fully transparent propagation of the sharing information in TMC. 3 3' 1à y H' à û'6A >-ï'6A >%. Figure 16: Syntax of the transparent module calculus TMC 4.2 y yà U' The Standard ML signature calculus [28, 27] enforces a similar restriction. 11 if ÝÝ¡ is a valid deduction in TMC, then U ¡ is valid in EMC; similarly, if B' then U<£3'' ; <Ú H ' ; if Ç then U if J{ and £6 5¶ then U U { ; -85 then U <Ú 'q ; if and ¢7 if ݪ¥A - and ÝC -85 then U D 44 q ; if ¤E 5 then U '£ ; -25ï or ¢/ .5 then U <£ ; if F r u if G and © and ¥ -H5ã r .I5Ì -Ë ¨ . r J u K <Ú ô <.=;k­®Ù then U <Ú ¨¿ ¬{Ù ; and U r u r r u u if pL and and - r 0 § 7M 5ïÙ 7u M u r r5 Ù , § 9- ; and U 'ÚÙ §ÝÙ 9- ; . then 9- ;kN r u if r äu -O5 Ù and äP -O5 Ù then U < Ù §ÂÙ 9-: ; . Proof: By structural induction on the derivation tree; along the process, we need to use the following two lemmas. Q r Lemma y 4.4 Given a TMC context , suppose ä R r ÁºÂQ¡ à S , then if if if if r Module expression and declaration: r u r u u A vFthen 6A >£ÁWT%- V6§0- . r u r u u A v . 7 then 6 Y v£ÁWT9. V§:. . r r A v then 6A >¤ ÚÁWTUiV§ . r u r u then 6A >A v A¤ ¤ÁWTU VÈ- . mtyp iYM r' " v TNWV Q' << *iS(¡\ i{- <pTNiV T@>9 Í ú<pZ Ùv[a*)Uv9 ¿Ù Ýlet in ú#! < ) ) - ) U mtfd Ù mcon mcfd mknd mkfd Comparison with the stamp-based semantics + ) Û ) ) ) Ü $ r Q U V <' U S( -Ý Wi>9 Í -ï¡*v9 - #! 1< H r' " t TNWV"Q¡Û r u << ÛiS(¡g¸ T9Ù(V \v9 ÙÚ¡Ù Z Ù [ !qr ¦ < b r y u Ù QÜ <# Ü S(' !P9Rª< v9 Core language: ctyp cexp ) ) ! YM !"¡g!#T9Ù(V"<< Ya << Elaboration context: ctxt functor G1(X: SIG) = X functor G2(X: SIG) = struct abstype t = A with val x = A end end ) ®('SUÆ'6Yv9 Figure 19: Syntax of the kernel module calculus KMC as universal quantification (W ), existential quantification ( ), de$ pendent product ( ), and transparent record ( Qq S ) to model higherorder modules. The syntax of KMC is given in Figure 19. The static semantics for KMC is summarized in Figure 20. The complete typing rules are given in Figure 21 and in Appendix E. The EMC-to-KMC translation is summarized in Figure 22 and its complete definition is given in Appendix F. Both applications are legal under the stamp-based semantics: applying APPS to G1 results in a module whose t component is equal to int while applying APPS to G2 creates a module whose t component is a new abstract type. Under our scheme, the transparent version of APPS cannot be applied to G2; the abstract version works for both but it does not propagate sharing when applied to G1. We believe this lack of expressiveness is not a problem in practice. Like other module calculi KMC supports a form of simple module that consists of an ordered list of type, module, and value declarations—in KMC we use a record syntax ( Qq S ) rather than str << end to represent such simple module. Following AMC and EMC, we assume that each declaration in KMC simultaneously defines an internal name (e.g., ¹ ) and external r label (e.g., a module record , ! , ). r'Given ß Ì ' Q < < S (or type VQ U <' UºiS , declarations (or specifications) defined later can refer to those defined earlier using the internal names. Implementation A module system will not be practical if it cannot be type-checked and compiled efficiently. Our EMC calculus can be checked efficiently following the typing rules given in Section 3.2; the only nontrivial aspect of the elaboration is on how to efficiently test the equivalence between two arbitrary EMC types; we plan to use the realization-based approach used in the SML/NJ compiler [36] to propagate type definitions. The type structure of KMC resembles a typical predicative polymorphic -calculus. The constructor calculus of KMC is almost identical to that of EMC. Module kind (mknd) characterizes module constructor (mcon) Ù ; module type (mtyp) - models module expressions (mexp) . An elaboration context for KMC contains bindings for core variables ( ), core type variables (! ), module variables ( ), and module type variables ( ). EMC is also compatible with the standard type-directed compilation techniques [18, 15, 35,36]. Most of these techniques -like polymorphic lambda calare developed in the context of culi [11, 33]. In this section, we define a Kernel Module Calculus (KMC) and show how to translate EMC into KMC and then translate KMC into an -like Target Calculus (FTC). 5.1 ) ) Module type and constructor: Compilers for the strong-sum-based calculus [26, 36] use stamps to support type generativity and abstract types (TMC did not include these features). There are still higher-order module programs that are supported by the stamp-based semantics but not by our type-theoretic semantics. Take the higher-order functor APPS in Section 2.1 as an example and consider applying it to the following functors: 5 mdec Lemma 4.5 Given a TMC context , a TMC module type - , an EMC constructor Ù , and an EMC kind , if 46A (S-:'äÙ¢ is valid in EMC, then 4'ªÚÙ£ is valid in EMC as well. 4.3 path mexp , let Opaque modules are modeled with existential types [30] and dot notation [5, 4]. Given a module path of type ¸< - , we use " t TNWV to denote ’s constructor component (which should have kind ), and " v TNWV to denote the module component (which should have type Z " t TNiVA¬\3[ - ). To construct an opaque+ module, we use the module expression of form )U>9 Ù Ý where constructor Ù must be of kind , module must have type Z Ù&¬P([ - , and the resulting module has type *v9 - . The kernel module calculus KMC Unlike EMC which is based on the ML syntax, the Kernel Module Calculus (KMC) uses only well-known typing constructs such 12 ¡ » ¤ iA¢B" ¿QXU ¼Í ¾¿>9 y " t TNWVS*T%-ÂV v TNWV@qQ¡ à r <# UÀ - ¾7- 6ZU y y ÁºÂQ'! Mà M ! aà a ÁWT%-ÚV <<NS Y i{6 £¥A- $ ¢\ i{- ¥ i{-Ý - $ £¥ i{-Ý - y ¢£pTNWV"*Q¡ i à £¥A¢¾TU ÍV"TU -ÚV ¢£ ¢¾T4! V6T4! iV Figure 21: Selected typing rules for KMC: ÎÝϽР¡ ¤ £ ¤( Ù¤q ¤Û¤qÜ 7 / U £¥ £1* U ctyp equivalence mcon equivalence mcfd equivalence mtyp equivalence mtfd equivalence £1§ Ù§ÝÙ ¤Û§ÝÛ qÜ 7 -ï0 § - / U¢: § U ÙJS y ¢Ù¤q ÁºÂQ¡ à ÙJS N)Uv9 ¿Ù Ý - Aµ r ' <<<SU À É À U À Ê £´ << ¤ r' 'r Q¡ < < * SJQXU # ' UºS ctxt formation ctyp formation cexp formation mcon formation mcfd formation mtyp formation mtfd formation mexp formation mdec formation _SqT%- V y r ¢£1*U 6SUA¢ let in ¥- r M ¢"! ¼Ä ±Å T9U << UÀVS ¾£¥VWi>9 Í ¢Ù¤ ÁºÚQ' à ¢£DZ Ùv[MÁWT%-ÂV 6A>9 㤾BT"v9 ¥Y Wv9 ¢' ¤ ¾ÇQ{SQ{S 0Y[ + ¤¥{ÁWT%-ÂV **v9 - J{ ÆTU {V"\TU HV 0V\ and ÎÝÏ¿Ò ctxt-to-ctxt translation ctyp-to-ctyp translation cexp-to-cexp translation mcfd-to-mcfd translation mcon-to-mcon translation path-to-path translation sig-to-mtyp translation isig-to-mtyp translation mexp-to-mexp translation mexp coercion translation U^ 4 ^ U^ UÛE ^ HÙ_ ^ y yà yà Ãy Ãy Û yà ٠,^ à y H` à y H^ à ¾£*a5¶ ¾ ô M<b 5î Figure 22: Translation from EMC to KMC: a summary Figure 20: Static semantics for KMC: a summary Proof: Expand this theorem to cover module declarations and core language expressions; the generalized version of this theorem can be proved by structural induction on the derivation tree. KMC supports two forms of parameterized modules: one abstracted over module values (of type - ); another over module constructors (of kind $ ). A module function \ Y- has the dependent product type i]-Ý - . Dependent product is necessary because we use dot notation to access opaque modules so the return type of a function might refer to the actual argument. Dot notation [4] also requires that functions in KMC be applied to module access paths only, as in pTNWV . This is not a problem because we can always use let to introduce local declarations. The translation from EMC to KMC is quite simple. Figure 22 summarizes the main translation rules; the actual definition is given in Appendix F. Here, h ^ maps EMC contexts, core types, core expressions, module constructors, module constructor fields, and ^ translates an EMC access paths into their KMC counterparts; H signature into a KMC module type - ; H ` translates an instantiated signature in EMC into a KMC module type - ; the judgement ¤Ý¥4 5¶ translates an EMC module expression of signature into a KMC expression . We also use the judge 5 to coerce a KMC path with type ment © ô { H ^ into a KMC expression with type H ^ , assuming and are both instantiated signatures in EMC. We prove the following type preservation theorem for the EMC-to-KMC translation: Polymorphic modules in KMC are parameterized over module constructors. A module expression T"Bq Í has the quantified type Wv9 - . It can be applied to constructor Ù if Ù has kind , the result has type Z Ù&¬¡\3[ - . Theorem 5.2 Given an EMC context , we have Typing module identifier and functor application in KMC (see Figure 21) is much simpler than those in AMC and EMC. First, there is no implicit “strengthening” when we access a module identifier. Second, KMC does not have any form of subtyping: to type a functor application, we must make sure that the type of the actual argument is exactly same as that of the functor’s formal argument. if ú¡ is a valid EMC deduction then cU valid in KMC as well; similarly, if ¤ then 4 ^ 4 ^ ; ^ U ^ 4 ^; if J{ then U ^ U_ Ù ^ U ^ ; if ÇÙ¤ then U if ÛÜ then U ^ 4E Û ^ 4b Ü ^ ; Theorem 5.1 (unique typing) Given a KMC context suppose is a KMC module expression, - and - are KMC module types, if ¾£¥ and £¥A- then -¶§0- . - 13 if ù then U ^ 4 ù ^ if Çù then U ^DHù^ ; ; ¡ is into concrete ones; this makes it hard to reason about type-directed operations on values with abstract types. The translation given in this paper rightly maps all opaque modules into abstract types, so two different types in the source calculus would not be considered as equivalent in the target calculus. r y u r r' R' QVe 9 r u <# eOÈ9 ¦S Ù <'r <r<¡ \v9 Ù£¡Ù Z Ù [ Q e 3Ù X <<r embr#3 ÙÈ\S( ¡gfehT9Ù(V@" t TNWV type X << emÈ -piS $g1T9Ù(V"XQ e v -Ý - h Wi>9 Í - ¡>9 path X AM ea " vr TNWV r< X <'YVQ e <# eO6S exp \ > -Ý ú< pTNWV+ T@>9 Í <prZ Ùv[ u )U>9 Ù Ý let in ctxt X J'A v -ï'Av9 Figure 23: Syntax of the -based target calculus FTC d kind con X X context formation constructor formation type formation exp formation constructor equivalence type equivalence 6 Related Work Module systems have been an active research area in the past decade. The ML module system was first proposed by MacQueen [24] and later incorporated into Standard ML [27]. Harper and Mitchell [13] show that the SML’90 module language can be translated into a typed lambda calculus (XML) with dependent types. Together with Moggi, they later show that even in the presence of dependent types, type-checking of XML is still decidable [14], thanks to the phase-distinction property of ML-style modules. The SML’90 module language, however, contains several major problems; for example, type abbreviations are not allowed in signatures, opaque signature matching is not supported, and modules are first-order only. These problems were heavily researched [12, 19, 20, 23, 38, 26, 17] and mostly resolved in SML’97 [28]. The main remaining issue is to design a higher-order module calculus that satisfies all of the properties mentioned in the beginning of this paper (see Section 1.2). ¡ ¢Ù¤X ¢7 ¢£¥ ¢Ù§ÂÙ&_)q ¢7 -ï0 § - Figure 24: Static semantics for FTC: a summary if if if if if if Supporting higher-order functors with fully syntactic signatures turns out to be a very hard problem. In addition to the work discussed at the beginning of Section 1.2, Biswas [2] gives a semantics for the MacQueen-Tofte modules based on simple polymorphic types. His formulation differs from the phase-splitting semantics [14, 36] in that he does not treat functors as higher-order type constructors. As a result, his scheme requires encoding certain type components of kind R using higher-order types—this significantly complicates the type-checking algorithm. Russo [34]’s recent work is an extension of Biswas’s semantics to support opaque modules; he uses the existentials to model type generativity, but his typechecking algorithm still relies on the use of higher-order matching as in Biswas [2]. ¢ then U ^ U` ; ¢¿* then U ^ , ^ H ^ ; ¢£¥qi5î then U ^ £ U` ; ¢£1§ then 4 ^ 4 ^ §N4 ^ ; ¢ÙݧÚÙ q then 4^DHÙ_^k§NHÙ ^vq ; ¢¤ÛÂ§Û qÜ then U ^D UE Û ^kN § UÛ ^&Ü ; Proof: By structural induction on the derivation tree; along the process, we need to use the following lemma. Lemma 5.3 Given an EMC context , suppose and are two instantiated EMC signatures and is a KMC access path, if ú ¨Þ is valid in EMC, and U^ÞîfH^ is valid in 5 coerces from into , then KMC, and ©ú ô 6 4 ^D¤a Hj ^ is valid in KMC. 5.2 The Our kernel module calculus (KMC) is partly inspired by the work on parameterized signatures of Mark Jones [17]. Both of our approaches use higher-order type constructors to propagate sharing information. However, our notion of signatures differ from his in that we allow type components inside the module record. In fact, our module record is a transparent sum and it can contain an ordered list of type, value, and module declarations; parameterized signatures in Jones [17] only allow value components. -like target calculus FTC KMC can then be easily translated into an -like polymorphic calculus by simply dropping all the type components in the KMC transparent records (after we inline all type definitions of course) and by merging the module constructor and the core type expres sions. The result is an -based Target Calculus (FTC) as defined in Figure 23. FTC is essentially the standard predicative variant of the calculus extended with dot notation (i.e.,$ " t TNWV and " v TNWV ), existential types ( ), and dependent products ( ). Figure 24 and Appendix G gives the typing rules for FTC. The translation from KMC to FTC is omitted since it is rather trivial. 7 Conclusions A long-standing open problem on ML-style module systems is to design a calculus that supports both fully transparent higher-order functors and fully syntactic signatures. In his Ph.D. thesis [23, page 310] Mark Lillibridge made the following assessment on the difficulty of this problem: In principle it should be possible to build a system with a rich enough type system so that both separate compilation and full transparency can be achieved at the same time. Because separate compilation requires that all information needed for type checking the uses of a functor be expressible in that functor’s interface, this goal will require functor interfaces to (optionally) contain an idealized copy of the code for the functor whose behavior The fact that all the module languages given in this paper can -based calculus is important because imbe compiled into an mediately all important type-based compilation techniques [18, 35, 15, 29, 39] become applicable to these module languages as well. In a previous paper [36], we presented a type-preserving translation from the MacQueen-Tofte higher-order modules [25] into an -based calculus, however, that algorithm turns all abstract types 14 they specify, I expect such a system to be highly complicated and hard to reason about. [10] L. George. MLRISC: Customizable and reusable code generators. Technical memorandum, Lucent Bell Laboratories, Murray Hill, NJ, 1997. This paper shows that fully transparent higher-order functors can also have simple type-theoretic semantics, so they can be added to ML-like languages while still supporting true separate compilation. Our solution only involves a conservative extension over the system based on translucent sums and manifest types: modules that do not use transparent higher order functors can still have the same signature as before. [11] J. Y. Girard. Interpretation Fonctionnelle et Elimination des Coupures dans l’Arithmetique d’Ordre Superieur. PhD thesis, University of Paris VII, 1972. The new insight on full transparency also improves our understanding about other module constructs. Harper et al [14] and Shao [36] have given a type-preserving translation from ML-like . Their phasemodule languages to polymorphic -calculus splitting translations, however, do not handle opaque modules well—abstract types must be made concrete during the translation. Our new translation rightly turns opaque modules and abstract types into simple existential types. [13] R. Harper and J. C. Mitchell. On the type structure of Standard ML. ACM Trans. on Programming Languages and Systems, 15(2):211– 252, April 1993. [12] R. Harper and M. Lillibridge. A type-theoretic approach to higherorder modules with sharing. In Twenty-first Annual ACM Symp. on Principles of Prog. Languages, pages 123–137, New York, Jan 1994. ACM Press. [14] R. Harper, J. C. Mitchell, and E. Moggi. Higher-order modules and the phase distinction. In Seventeenth Annual ACM Symp. on Principles of Prog. Languages, pages 341–344, New York, Jan 1990. ACM Press. [15] R. Harper and G. Morrisett. Compiling polymorphism using intensional type analysis. In Twenty-second Annual ACM Symp. on Principles of Prog. Languages, pages 130–141, New York, Jan 1995. ACM Press. Higher-order functors and fully syntactic signatures allow us to accurately express the linking process of ML module programs inside the module language itself. In the future we plan to use the module calculus presented in this paper to formalize the configuration language used in the SML/NJ Compilation Manager [3]. We also plan to extend our module calculus to support dynamic linking [22] and mutually recursive compilation units [9, 8]. [16] R. Harper and C. Stone. An interpretation of Standard ML in type theory. Technical Report CMU–CS–97–147, School of Computer Science, Carnegie Mellon University, Pittsburgh, PA, June 1997. [17] M. P. Jones. Using parameterized signatures to express modular structure. In Twenty-third Annual ACM Symp. on Principles of Prog. Languages, pages 68–78, New York, Jan 1996. ACM Press. [18] X. Leroy. Unboxed objects and polymorphic typing. In Nineteenth Annual ACM Symp. on Principles of Prog. Languages, pages 177– 188, New York, Jan 1992. ACM Press. Longer version available as INRIA Tech Report. Acknowledgement I would like to thank Karl Crary, Robert Harper, Xavier Leroy, David MacQueen, Claudio Russo, Valery Trifonov, and the ICFP program committee for their comments and suggestions on an early version of this paper. [19] X. Leroy. Manifest types, modules, and separate compilation. In Twenty-first Annual ACM Symp. on Principles of Prog. Languages, pages 109–122, New York, Jan 1994. ACM Press. [20] X. Leroy. Applicative functors and fully transparent higher-order modules. In Twenty-second Annual ACM Symp. on Principles of Prog. Languages, pages 142–153, New York, Jan 1995. ACM Press. References [1] E. Biagioni, R. Harper, P. Lee, and B. Milnes. Signatures for a network protocol stack: A systems application of Standard ML. In 1994 ACM Conference on Lisp and Functional Programming, pages 55–64, New York, June 1994. ACM Press. [21] X. Leroy. A syntactic theory of type generativity and sharing. Journal of Functional Programming, 6(5):1–32, September 1996. [22] S. Liang and G. Bracha. Dynamic class loading in the Java virtual machine. In Proc. ACM SIGPLAN ’98 Conf. on Object-Oriented Programming Systems, Languages, and applications, pages 36–44, New York, October 1998. ACM Press. [2] S. K. Biswas. Higher-order functors with transparent signatures. In Twenty-second Annual ACM Symp. on Principles of Prog. Languages, pages 154–163, New York, Jan 1995. ACM Press. [23] M. Lillibridge. Translucent Sums: A Foundation for Higher-Order Module Systems. PhD thesis, School of Computer Science, Carnegie Mellon University, Pittsburgh, PA, May 1997. Tech Report CMU-CS97-122. [3] M. Blume. A compilation manager for SML/NJ. as part of SML/NJ User’s Guide, 1995. [4] L. Cardelli and X. Leroy. Abstract types and the dot notation. In Proc. Programming Concepts and Methods, pages 479–504. North Holland, 1990. [24] D. MacQueen. Modules for Standard ML. In 1984 ACM Conference on Lisp and Functional Programming, pages 198–207, New York, August 1984. ACM Press. [5] L. Cardelli and D. MacQueen. Persistence and type abstraction. In M. P. Atkinson, P. Buneman, and R. Morrison, editors, Data Types and Persistence, pages 31–41. Springer-Verlag, 1988. [25] D. MacQueen. Using dependent types to express modular structure. In Proc. 13th Annual ACM SIGPLAN-SIGACT Symp. on Principles of Programming Languages, pages 277–286. ACM Press, 1986. [6] S. Corrico, B. Ewbank, T. Griffin, J. Meale, and H. Trickey. A tool for developing safe and efficient database transactions. In 15th International Switching Symposium of the World Telecommunications Congress, pages 173–177, April 1995. [26] D. MacQueen and M. Tofte. A semantics for higher order functors. In The 5th European Symposium on Programming, pages 409–423, Berlin, April 1994. Spinger-Verlag. [7] J. Courant. An applicative module calculus. In M. Bidoit and M. Dauchet, editors, TAPSOFT’97: Theory and Practice of Software Development: LNCS Vol 1214, pages 622–636, New York, 1997. Springer-Verlag. [27] R. Milner, M. Tofte, and R. Harper. The Definition of Standard ML. MIT Press, Cambridge, Massachusetts, 1990. [28] R. Milner, M. Tofte, R. Harper, and D. MacQueen. The Definition of Standard ML (Revised). MIT Press, Cambridge, Massachusetts, 1997. [8] K. Crary, R. Harper, and S. Puri. What is a recursive module? In Proc. SIGPLAN ’99 Symp. on Prog. Language Design and Implementation, page (to appear). ACM Press, May 1999. [29] Y. Minamide, G. Morrisett, and R. Harper. Typed closure conversion. In Proc. 23rd Annual ACM SIGPLAN-SIGACT Symp. on Principles of Programming Languages, pages 271–283, New York, 1996. ACM Press. [9] M. Flatt and M. Felleisen. Units: Cool modules for HOT languages. In Proc. ACM SIGPLAN ’98 Conf. on Prog. Lang. Design and Implementation, pages 236–248. ACM Press, 1998. 15 A.4 [30] k J. Mitchell and G. Plotkin. Abstract types have existential type. In Proc. 11th Annual ACM SIGPLAN-SIGACT Symp. on Principles of Programming Languages, New York, 1984. ACM Press. [31] G. Nelson, editor. Systems programming with Modula-3. Prentice Hall, Englewood Cliffs, NJ, 1991. [32] J. H. Reppy and E. R. Gansner. The eXene library manual. SML/NJ documentations, March 1991. [33] J. C. Reynolds. Towards a theory of type structure. In Proceedings, Colloque sur la Programmation, Lecture Notes in Computer Science, volume 19, pages 408–425. Springer-Verlag, Berlin, 1974. [34] C. V. Russo. Types For Modules. PhD thesis, University of Edinburgh, Edinburgh, UK, June 1998. [35] Z. Shao. Flexible representation analysis. In Proc. 1997 ACM SIGPLAN International Conference on Functional Programming (ICFP’97), pages 85–98, New York, June 1997. ACM Press. [36] Z. Shao. Typed cross-module compilation. In Proc. 1998 ACM SIGPLAN International Conference on Functional Programming (ICFP’98), pages 141–152. ACM Press, September 1998. [37] B. Stroustrup, editor. The C++ Programming Languages, Third Edition. Addison Wesley, Reading, MA, 1998. [38] M. Tofte. Principal signatures for high-order ML functors. In Nineteenth Annual ACM Symp. on Principles of Prog. Languages, pages 189–199, New York, Jan 1992. ACM Press. [39] A. Tolmach. Tag-free garbage collection using explicit type parameters. In Proc. 1994 ACM Conf. on Lisp and Functional Programming, pages 1–11, New York, June 1994. ACM Press. A 6 r Aµ r '<<<A ÀÉ ÀËÊ £ ´ <' r ¢ sig < ' end (8) A.5 (9) spec formation: ¤ i>¼m ¬ lYnTHV 3 (10) ¤¡ »! ¼o ¬ lYnÍTHMV Ú!A (11) »!A>¼m ¬ lYnÍTHV ¢Ú!A' (12) £ £{H (13) Static Semantics for AMC A.6 £½¡ (1) ¢¤ ¤wÌ¡ (2) ctyp formation: ¾£ ¢¿* (ÍQ<< ! '< S ±{² Q'< ! ' < S ¢¿M ! r ¿ ¢ << À '# end% y sig y ÁºÚQ<!A à % M ! irX à M ¾r @!Y i¼Ä ±{Å T V S ÔÕÖ À {H kì õ#²õ <# ÀÉ ¤¢¡ °!A¡¼Í ¾Ú!YM§ (14) r ¢ << À '< end% y sig y ÁºÂQ'!Y % à M ! rN i à a ¢@!A ¼Ä ±Å T VS r Ô{Õ\Ö À ¤T4!Y iV kì õ-²õ '< ÀÉ ¿M !Yi§ÁWTUV (15) Static Semantics for EMC This appendix gives the rest of the typing rules for the external module calculus EMC. The formation rules for module constructors ( ¤Ù£ ), and module constructor fields ( ÚÛ¤qÜ ) are given in Figure 9 in Section 3.2. The formation rules for module expressions ( ¥+ ) and module declarations ( ©äÍ ) are given in Figure 12 in Section 3.2. The subsumption rules for signatures ( ¥¨£ ) and specifications ( ¥ä,¨Ú ) are given in Figure 13 in Section 3.2. (3) (4) cexp formation: ( ¡ »{H¼ ¤ ctyp equivalence: ¾£1§ Rules for congruence, reflexivity, symmetry, and transitivity are omitted. ctxt formation: ¤¢¡ ¤¢¡ ø! ¼ ±² ! ¼Í ¢£!Y A.3 (7) ¢ 6A 3Æ fsig TU i{3V) B A.2 ¤¢¡ sig end This appendix gives the rest of the typing rules for the abstract module calculus AMC. The formation rules for module expressions ( î+ï ) and module declarations ( î+½ ) are given in Figure 5 in Section 3.1. The subsumption rules for signatures ( + Ú¨ ), and specifications ( Þî¨Ç ) are given in Figure 6 in Section 3.1. A.1 sig formation: ¢ B.1 (5) (6) ¾¿a ¦{ÁWTUiV 16 ctxt formation: ¡ £½' (16) Ç ¤6Aã¡ (17) ¤¡ ßz¼o ¬ lYnÍTHMV ¤v9 ã' (18) a¬{Ùæê)ë Ô ëAì ±²Aí ì ÔÕÖ component. To make this work, we need revise the EMC signaturestrengthening operation so that all references to are substituted by equivalent constructors that have no such references. The new routine is shown in Figure 25 where a¬{Ù is now implemented as _¬T9Ù¢PàaáMâ@T9VAV-S p with p denoting the identity substitution. The auxiliary procedures _¬T9Ù' åV-YÁå­ means that instantiating by constructor Ù of kind under substitution Á yields signature , and ¬T9Ùzw åV-YÁ­ UYÁ* means that strengthening specification by constructor Ù of kind under substitution Á yields specification and new substitution Á . ±{¯ _¬T9Ù£qà_áâ@T9VAV-Sp r Y µ Á Ø ¿Á» « ¬T9ÙB9 åV-YÁ «'É ­® « AÁ « ³ ¤ ´ << r r T sig #< end VA¬T9ÙÍ9 åV-AÁ¸­ sig <# end T fsig TU i36V*X1 VA¬T9ÙÍ9 åV-AÁ¸­ fsig TU i36V*X1 y Ý ¬*T9ÙºZ ['9 V-YÁº­® T fsig TU 3V3 AV ¬T9ÙÍ9 åV-AÁ¸­ fsig TU 3V) y a¬*T9g¸ T9Ù(V9 åV-3Á­®æÁ*W¿Á_qÍQ i à g¸ T9Ù(VS TU i36VA¬*T9ÙBhQq#< v9 << S{V-AÁº­îTU {3 V-YÁ T4!AHVA¬*T9ÙBhQq'< P ! 9R << S{V-AÁº­îT4!Y'g!#T9Ù(VAV-hÁ T4!A¡iVA¬T9Ù9 åV-YÁº­îT4!Y¡ÁWTUiVAV-9Á TU HiVA¬*T9Ùå9 åV-YÁº­îTU UÁWTUiVAV-3Á B.5 A q ä fsig TU 3 6V@q (26) A qä fsig TU 3 6V@) (27) spec formation: ¤ Figure 25: Signature strengthening in EMC (revised) ¼m ¬ lYnTHV {3 (28) (19) ¤¡ »!Y>¼o ¬ lYnÍTHMV Ú! (29) (30) (20) »! ¼m ¬ lYnÍTHV ¢Ú!A' £ £{H (31) B.2 ctyp formation: ¾£ ¤¢¡ ø!Y¼ ±² !A'¼Í ¢£! ¢¿* (ÍQ<< ! '< S ±{² Q'< ! ' < S ¢¿M ! ¢Ù¤ ÍQq#< ! 9R <<NS ¢g!#T9Ù(V (21) B.6 B.3 cexp formation: ( Rules for congruence, reflexivity, symmetry, and transitivity are omitted. ¡ »{H¼ ¤ r< (22) ¤¢¡ °!A¡¼Í ¾Ú! § ¢¿ << À '# end% y sig y ÁºÚQ<! Mà % M ! rXM à M ¾r @! ¼Ä ±{Å T VS ÔÕÖ À kì õ#²õ <# ÀÉ {H ¾¿a ¦{ÁWTUiV B.4 r' ¢ << À '< y sig y ÁºÂQ'! à % M ! r aà a ¢@! r Ô{Õ\Ö kì õ-²õ '< ÀÉ ¿M ! §ÁWTUV (23) sig formation: ¢ ¤¡ sig end ¢ r r ±Å TH <#wr ÀÉ 6 <<<' À É ¤ r< ¢ sig Wi i¼Ä ctyp equivalence: ¾£1§ r V i\ê)ë Õ ±{í¯m² õ<õ ê Õ Yµ À ´ << À Ê ¤ << end (32) end% ¼Ä ±Å T V S À ¿! ÙÚ§ÂQ<' ! << S g!#T9Ù(V§ (24) B.7 (33) (34) mcon equivalence: ÇÙݧÝÙ q Rules for congruence, reflexivity, symmetry, and transitivity are omitted. (25) The side condition on À in this rule is not absolutely necessary. If we remove this requirement, we essentially allow free flexroot references such as even when is a locally declared structure y ÁÂQ' à 17 Ù SË¢ÇÙ 6Yv9 Ù¤ ¢¾T9\>9 Ù(V#Z Ù [i§ÁWT9Ù(V"q (35) Ù ¾T9\v9 ÙºZ \[OV"§ÝÙ¤ y ÇÙ§ÂQ'< ÈÙ <<NSJQ'< >9 << S g¸ T9Ù(V§ÝÙ r ÂQÜ ú #< Ü S Ù£A µ ¢¤Û«û§¤T9e<gfe3T9Ù(VAV"qÜ>« ³ £´ '< ZeW !- r ¢ÇQÛ << Û Sû§ÝÙ£q C.3 (36) (37) ctme formation: ¤a- ¤¢' ß v%.z¼Íw.@¬¡ ­8 A- (46) ¢¡ ø v-ï¼Í A- (47) ¤ { ¢/# $ TH V@ V TUiV (48) £ ¢/#&wTUiV@ EQ TUiV (49) r u £ @ v- r r ¢B" UT mVÈ- (50) (38) mcfd equivalence: ¢¤ÛÚ§Û Ü B.8 Rules for congruence, reflexivity, symmetry, and transitivity are omitted. mknd subsumption: ¤ Þ¨ª B.9 Rules for reflexivity and transitivity are omitted. y Yµ *Q´ '' åS à Qq´ '# ¤Ü6sRt « u ¨ªÜ « £ ´ #< ³ r< r ¢Q¡Ü <' Ü\S¨QÜ #' r S (39) Ü × S r u r u ¤ ¿ ¨ Ç ¨ ª y r y u r u Ç ¨ ª B.10 y r u ¢£ *@ >- Á ÂQ¡ à º u u B" UT V@ ÁWT%- V v% .ä¤aA$ \ >%.k v%.b r u r r $ u r v %. r ¢£ y u 7¨ . x Á¸ÂQ¡ à S u r u £ TU @ V ÁWT%- V (41) r ¾£ * - C.2 C.4 u r u u F v£ * u r u let b in A- (51) (52) £½¡ (42) ¢7 z¼o ¬ lYnÍTHMV ¤6A >¡ (43) ¢/. z¼o ¬ lYnÍTHMV ¤6A >%.ä¡ (44) C.5 mtyp formation: F- Rules for module types of form - ctyp formation: ¾£ (45) 18 (53) (54) (55) ctce formation: ¡_ ¢£ V TUiV ¾B"v$*TU V@ ctxt formation: ¤¢¡ ¾£ EQ TUiV ¢B"v&wTU V r ¢ Static Semantics for TMC This appendix gives the complete typing rules for the transparent module calculus TMC. C.1 TU VS (40) Rules for reflexivity and transitivity are omitted. C r r r u r u ¾£ * A v ¤ + r u r u ¾P)U È q@ v- - mkfd subsumption: ¤Ü¨¿Ü ©¨ £ >9 ¥¨¿ >9 " (56) and 7. : £ ¾ V TUV (57) £ EQ TUiV (58) r u A v F r u @ >- - (59) A v%.äF $ ¾ v%.b - y r u ¿*@ >- ÁºÂQ¡ à u u ¾B" TNW" V ÁWT%- V (60) Rules for module types of form . : ¤ V TUiV ¢ C.6 r u A v%. 7. r u Ç@ v%. . (63) r u A v%. 7. $ r u ¢ v%. . (64) (75) £ ¢/# & UT iV@ EQ TUiV (76) r r r u u ¾£ * A v ¤ wr u + r u ¾P)U È q@ v- - (77) .7Ý A v%.Æ$ Ç\ v3 v%.b - (78) r $ r u u ¢¿ r v %. r ¢¿y u ¢7¨ . 1 Á ÂQ¡ à S º r u u ¢¿ TN V@{ ÁWT%- V cexp formation: ( r (79) (65) ¾£ r *- r ¢ ctsp formation: ¾?' C.10 (66) u r u u F v£ *r u u let b in A- ctyp equivalence: ¤ r § (80) u Rules for congruence, reflexivity, symmetry, and transitivity are omitted. sig formation: ¢ ¤_ EQ TUV B" & TU V§ Adding bindings such as “ ” to the context is fine because each signature is also a module type of form . . C.11 /' V T('MV (67) ¢ (68) TYP r §0- u and ÝC. r §:. u C.12 ¾ (70) mexp formation: £¥- ¡ » >%.½¼y."¬ ­8¢£ ¼ r u ¿*@ >- r r ¢B " TNWV@- mtyp subsumption: ¢7- ¨x. (69) u v3 Ç $ r u ¢ v3 ¡ » >¢£ - r mtyp equivalence: ÂC- (81) Rules for congruence, reflexivity, symmetry, and transitivity are omitted. r u v3 Ç r u ¢@ v3 C.9 (74) ¤{ ¢/#$*THVÈ V TUiV (62) TYP ¢ EQ TUiV /" & TNiV C.8 TNWVS (61) ¿ V TUV ¢ ¾B" $ TNWV@{ C.7 r " EQ TUV"¨ TYP (82) r u ¾£ § r u ¢ V TU b V ¨ V TU V (83) r r ¾7¨1. ¢@ vr r u u 6A >7¨ . 1 u r u ¨¿@ v%. . (84) (71) r u u 6Y v%. 7¨ . 1 $ $ r u r u >%. ¨ %. . > (72) (73) 19 (85) y ' à D.5 path-to-path translation: , . ¬W­8mtyp strengthening: " C.13 V TUVA¬ ­ V TUV (86) (" (" TYP ¬¡ ­ . r r r u . >%. u y (88) ' <#$THV] u ¬¡ UT WV­8$ r u r u . ¬ ­ v%. - H\ >3 r u TN ]V ' r u in let È y D.1 ctxt-to-ctxt translation: U ¦Ã The translation of a core type in TMC is based on its formation rules. Given a well-formed core type in context , it is translated into EMC type if and only if the judgement ,L5° is valid. £ -25ïÙ 7",&wTU v V 5 g typ T9Ù(V D.8 mtyp-to-sig translation: F-25 = , y D.3 sig-to-sig translation: H ¦Ã V T('MV]' TYP r u H@ >3 ' $ >3 r u ' = = = = y à r u - r u u A v75 ï r sig fst 3 u snd 3 end 5 r r ¢/. 5 $ r u %. > 5 r u u A v%. F5 r u V * fsig T fst 3 @ D.9 mtyp-to-sig translation: 7.5 sig ops X3'' end sig typ end r sig fst X H u ' ; snd XH end r u fsig T fst X H 'PV@ H ' = r 5 Ç@ v- typ D.4 cexp-to-cexp translation: U ' à TNWV]' r ¾7- y (" $ ¾£65î EQ TUiV,5 sig typ end ¾7-85 U6A >-0 N U fst 3 TYP 5 r r 5ï @ >%. r . u r r ¢/. 5ï $ r u %. . > , 'i ops 20 ¾£65î\ V TUV,5 sig ops HP end ¾ ¢/. ¾£65î V TUV,5 sig ops H end ¾ ¾/.5 U6A >%. N U fst 3 = = = D.7 ctyp-to-ctyp translation: £65¶ Throughout the translation, we use fst and snd to denote EMC module labels, ops for an EMC value label, and typ for an EMC type label. A TMC module identifier is translated to an EMC identifier fst where fst is an EMC module label and denotes the stamp. j'< This appendix gives the complete translation algorithm from TMC to EMC; the main translation is denoted by h ' ; the auxiliary function that maps from - or . to EMC kind is denoted by 3 ; ; the translation from - or . to EMC signature is represented as ãz -{5 and | ./5 ; the translation from - or to EMC constructor Ù is represented as c -}5 Ù and ï ~ -5 Ù ; the translation from to EMC core type 5î . expression is represented by ¤E ("v&wTNWV] <# & (T 'MV]' u+ ' str ops NU end str typ N3'' end r str fst J4 u 4 < snd N end fct T fst X H V4 r u '_ T '\V r u let fstJ O in O = = = = r ])U b (89) Translation from TMC to EMC D.2 ctsp-to-ctyp translation: fst , '_ fst , snd D.6 mexp-to-mexp translation: 4 à u u 4X = = = (87) UT V6­8. ¬X" TU V­8r u r u @ v%. . ¬¡ ­®@ v- - ¬X" $ D EQ T<"v&wTU VAV O, NT WV]' u TNWV] r sig typ end 5 r u u Y v%. 6 7. 5 r sig fst 3 u snd 3 end 5 r u u Y v%. 6 7. 5 r u fsig T fst3 @ V q D.10 mtyp-to-kind translation: V TUiV] ; EQ TUiV]; r u U@ v- ; $ v% .b -0; = = = = D.11 V TUiV]; TYP ; r u H@ v%. . ; $ r u v%. . ; D.12 QS Q typ R>S r Q fst 9y <.=; = = = = à ; y 6A >%.ä¤ A-25 Ù ÁºÚQ fst à _S $ \ v%.b v%.b ->5 \vX<.=;¡ ÁWT9Ù(V u snd 9- <.=; y à r u r r $ ¢¤ > %. 5 Ù ¢£ y r r 7 ¨ . 1 Á ÂQ¡ à º u r r u ¢¤ TU @ V {ÁWT%- v V 5ïÙ Z Ù S r ¾£ A ; (. ; S E r r u F5ïÙ 6A > F 5 Ù r u r- u @ v- 5ïQ fst Ù snd Ù S 6A >%. ¢ D.13 r E.1 ctxt formation: ¡ £½' (90) 7U ¤6SU ¡ (91) ¤¡ ßz¼o ¬ lYnÍTHMV ¤v9 ã' (92) u y Á ÂQ fst à _S º r u \vX<. ;¡ ÁW9T Ù V u u 75ïÙ $ r u >%. 5 E.2 ctme-to-mcon translation: -25ïÙ ctyp formation: ¤ ¤¢¡ °!A¡¼Í ¢£! All TMC module expressions ( ) embedded inside the core types can be translated into EMC module constructors. The translation is based on the formation rules for . ¢¿A- -ÍQq-< ¤¡ fst ÇÙ£q -ï¼Í v ->5ïÙ ¤ -25ïÙ ¤ { ¢ 7#$*TH V@ V UT iV,5 ¾/# & !Y' < < S ¢M ! ¤¡ ß >%.½¼."¬ ­8¾£ -25 E.3 ÍQ#' P ! % '< S Çg!<T9Ù(V ¤¾¡ øH¼ £ r y qQVU y ¢ << U À '< UºiS % ÁºÂQ'! à % M ! rXa à a ¢r @! ¼Ä ± Å T VS ÔÕÖ U À { H kì õ-²õ U << U ÀÉ y r u r ¾£aq@ v- 5ïÙ Á ÂQ¡ à " TUOVS º u u B" TU V@ÁWT%- V5 g snd T9Ù(V M ¦ÁWTUV 6A >u - 5 (94) (95) cexp formation: ¤J r u £a*@ v- 5ïÙ r r ¢B" TU VÈ5ïg fst 9T Ù(V r (93) Q{S £65¶ ¢ TUV" EQ TUV,5 Q typ S r r r £ A ¢ 5ïÙ r u + ¢P)U b *@ >- u Static Semantics for KMC QS r Ù u r u u F v£ * 5 ï Ù u r u let b in A5 Ù ¢£65¶ EQ TUVv5 Q typ \OS ¢ 5 This appendix gives the rest of the typing rules for the kernel module calculus KMC. The formation rules for module expressions ( Þ- ) and module declarations ( äRU ) are given in Figure 21 in Section 5.1. - -shaped TMC module types can be translated into EMC module constructors. The translation is based on the type formation rules for - . V TUV,5 r u u S u [ ; mtyp-to-mcon translation: F-25ïÙ ¾ r ¢ QS Q typ q R>S r u Q fst <. ; snd (. y r u <. ; <-0; mtyp-to-kind translation: y 9-:; r u u u A ¤ 5ïÙ r u snd Ù S Q fst Ù 21 (96) (97) E.4 mcon formation: ÇÙ£q ¤¾' »v9 ©¼ £Íq (98) ¢¿*>9 ¾B " t TNWV@ (99) Aµ ¤Ûi«qÜ>« ³ £´ <' r' r' QÛ << ÛiSqQÜ <# ÜJS (100) E.6 ¤¢¡ °! ¼Í ¾Ú! § r y qQVU y ¢ << U À '< ÁºÂQ'! à % M ! aà a ¢@! r r Ô{Õ\Ö kì õ-²õ U '< UÀÉ (114) UºiS % ¼ Ä ±Å T VS UÀ(¿! (101) ¿M ! §ÁWTUV A>9 Ù£q 6 y ¢\v9 Ù£q (102) ÙÚ§ÂQ<' ! << S g!#T9Ù(V§ r y u ¢Ù r u ÇÙ Z Ù [a y (104) ¢Ù¤q £ bÙÚ\TU v9 åV (105) ÁÂQ' à (106) r {u 6ZU ÇQVU < < ¸ U iS r ¢ÇQVU << U S (107) A v- $ i-Ý -Ý (108) Av9 7 ¢KWv9 - (109) Av9 7¢*v9 - (110) E.10 ¤ ¢¤ H y (117) (118) ¢Ù§ÂQq'< bÙ #< SQq#' v9 <#NS ¾g T9Ù(V§ÂÙ (119) r' ÂQÜ << ÜJS Ù¤q Aµ ¾¤Û « §T9Mgf\T9Ù(VAVqÜ « ³ £´ '< r' ¢Q¡Û <# ÛSû§ÂÙ£ (120) mcfd equivalence: ¤Û§ÝÛ qÜ Rules for congruence, reflexivity, symmetry, and transitivity are omitted. E.11 mtyp equivalence: 7-ï§0-Ý Rules for congruence, reflexivity, symmetry, and transitivity are omitted. mtfd formation: ¾/U ¤ß!Y>¼o ¬ lYnÍTHMV ¾Ú! Ù SË¢ÇÙ 6Yv9 Ù¤ ¾T9\>9 Ù(V#Z Ù [i§ÁWT9Ù(V"q ¢ ¾Ù¤ ¾T9\v9 ÙºZ P[4V6§ÝÙ mtyp formation: F- ¼m ¬ lVnÍTHV £ i- (116) Rules for congruence, reflexivity, symmetry, and transitivity are omitted. ¤ £!\T4!P9RkV ¾7- (115) mcon equivalence: ÇÙݧÂÙ&aq E.9 (103) mcfield formation: ¾¤Û¤Ü ¤¡ ÇQS E.7 Rules for congruence, reflexivity, symmetry, and transitivity are omitted. Ù£ ÍQ<< > 9 << S ¢g¸ T9Ù(V@ Ù E.5 ctyp equivalence: ¢£1§\ E.8 6U (111) E.12 (112) r r Yµ < <#<SUÀ¡É UºÀ(§0U À Ê ¤´ < < 7 r' r ¢ÇQVU << UºiSû§ÂQXU <# U S (121) mtfd equivalence: 7U§KU Rules for congruence, reflexivity, symmetry, and transitivity are omitted. (113) 22 F 9QÛ Translation from EMC to KMC This appendix gives a type-preserving translation algorithm from EMC to KMC. To make the presentation easier, we first modify the EMC syntax to distinguish different uses of module access paths: path mexp ) ) i"+ wM r< )N str << fct TU 3VhúY TNX¿V@ let u end r * TN V in r' << ÛMS ^ Hg¸ T9Ù(V] ^ U\v9 _ Ù ^ r u HÙ Z Ù [ ^ U_ Ù ^ i< ^ Here, we use )N to denote the places where a module path is used as a stand-alone module expression. We then separate the formation rules for module paths from regular module expressions: H` = = = = = H^ UA i3 ^ U6>9 ^ UA y à Y!Y¡14 ^ X 4 ^ U ^ A X H ` U^A>9 4 ^ M ^ = = YTU bÙ(V] ^ = = y à - = >9àaáMâ"T9V-%Ha¬¡, ^ y à ^ ¢¿q ¢P )N y Ã Û ^ à y ¢ ô à_áâ@T9V­+Ù ¶ NHa¬¡, + 45|)U>9àaáMâ"T9V1HÙ_ ^ ^ ^ y y A i3Ƥ¥5¶ Á6QX" t TU i9V à " v TU iHV à : T"v9à_áâ@T9V- \ i{XH_¬ ^ ÁWTU V T4!14 ^ V TU b H_ Ù ^ V F.5 mcon-to-mcon translation: H Ù_ + Note: according to Lemma 3.1, is an instantiated signature, so à_áâ@T9V is always an empty kind Q{S and Ù is an empty constructor QS . we always pack each structure expression this way so that we can uniformly translate each structure identifier i in EMC into " v TU V in KMC. , ^ ^ ` In the following, we use & to denote a KMC module expression “let ia in DTU i9V ” where i is a module identifier that does not occur free in . , ^ ! g!#THÙ_ ^ V F.4 mcfd-to-mcfd translation: U ÛE YT4!iV] ^ ^ The translation from EMC mexp to KMC mexp is conducted along the EMC typing rules. Given a context , an EMC module expression is translated into a KMC expression if and only if ¤¥qi 5¶ . !A F.3 cexp-to-cexp translation: U and H - F.8 mexp-to-mexp translation: ¢¤¥45î U^A = = = µ r r ^ = QvU ù ^ << 4 ù ^ S sig ù << ù $ fsig TU i3V) ^ = Wiv9à_áâ6T96V- i{Ua¬¡, ^ y y Q " t TU i9V à " v TU i9V à i3 SU X YTU i{3 ù ] V ^ = TU iX H ù ^ V YT4!A<i] V ^ = T4!A<1 4 ^ V 4 H ^ = TU X O ^#V U ^ y m!A< ^ !]^ M Hg!#T9Ù(V] ^ , ^ F.2 ctyp-to-ctyp translation: 4 ^ à " v TU i9V Here the internal translation h ^ is applied to instantiated signatures only: The EMC-to-KMC translation is denoted as 3 ^ . A special auxiliary function that translates EMC signature into KMC existential module type - is denoted as h ` . 4X ^ The translation from EMC signature to KMC module type is defined as: q ¢ + ¢N)N q U6h!A¡ ^ = = à y As a result of this reorganization, we add the following rule to the mexp formation: ^ 4 i< ^ M ,^ y ^ F.7 sig-to-mtyp translation: H ` à ¾¿ ¾£¥ F.1 ctxt-to-ctxt translation: 4 Ù " t TU i9V F.6 path-to-path translation: + path formation mexp formation r Q UÛ ^ <# U ÛA ^ S g¸ THÙ_ ^ V \v9 % HÙ_^ r u HÙ ^ %Z UÙ ^ [ = = = = = = i9S 5 fct TU i{3Vh¥ fsig TU i{3V3 î r u ¾¿ fsig TU i{3V3 ¿ * ¨ u wô àaáâ"T96y V­® Ù y à ô T9_¬Ù(VÈ ^5¶ ÁºÚQ à ٠a r u r ¾¿ TN V@ÁWT9 v V 5ºT ^ Z9HÙ_ ^ [OVh Ù The case for cannot occur since all of their free references have been replaced by a new constructor variable in KMC. 23 ¢¡ str end sig end 5|)U>hQSWÍQS QSMhQS + _S r r Aµ < <<<wÀÉ r<£ À¸ À5¶ À A À À Ê £´ << B sig << º end úà_áâ@T9V r sig << end Ç ô ú­+ Ù + r / )Uv9 1UÙ_^ Q'q << q SMXH_¬,^ r< r str #< * end *i 5 let q <<Yq in 6 G This appendix gives the complete typing rules for the target calculus FTC. Ç ô àaáMâ"T9V"­®Ù TUH_¬Ù_ ^ V + ¾TN)V@*a5|)U>9àaáâ"T96V1 H_ Ù ^ X H_¬ ^ £¦qF5¶ <)' ¢ ¾ let in *a5 Ì£¥*a5 6 let in ¢£¥*a5¶ ê)ë Õ õ ¤TU 3a¬X" t TU i9VAV ¾TU i¡ÍV"PTU i3V5 TU i' V-<TU 4" v TU iHVAV-A £ ! ê)ë Õ õ ¢¾T4!A¡V6T4!Y¡iV5 ¤T4! V T4!A¡4 ^ V-' T4! !YHV- (122) ¾7 z¼I ¬ lYnÍTHMV ÇA v' (123) ¤¡ ßz¼o ¬ lYnÍTHMV ¤v9 ã' (124) G.2 constructor formation: ÇÙ¤ ¤¢¡ »v9 ©¼ ¢£Í (125) ¢>9 Í / " t TNiV"q (126) F.9 mexp translation with coercion: Ý¿ ô <b5î Given two instantiated EMC signatures and , suppose ª¨ , the coercion transformation ä¢ ô ¡5ï turns the KMC path with type U ^ into a KMC expression with type H ^ . Note the deduction rules given below only work when and are instantiated signatures. % To simplify the presentation, we use to represent an ordered list of EMC specifications; this can either % be an empty list ( ) or a ). Similarly, we use R specification followed by another list ( to represent an ordered list of KMC module fields. ÇQVe ô <M b5¶ ÆTU i{3V ô TUi {34VÈ-b5 TU i¡V T4! ¸a !AV r Aµ ¢ÙÈq ¦,¹£´ < ' r r r 3Ù <' e 3Ù S*XQ e 9 < ' e 9 S (127) ¾Ù¤ + -ÍQq<# e9 #< S f g ehT9Ù(VÈ (128) Av9 ÌÙ£ y Ç\v9 Ù¤ (129) Ù ¢ÆTU HiV ô UT H VÈ#b5 TU ¸a V % % #b5¶R ô % % ¢ sig end ô sig end <65 Q'RS r y u q ÇÙ r u ¢Ù Z Ù [_q (130) G.3 type formation: ¢7- £ ô #b5¶ % % r r r r ô <b5î ô -b5¶R ¢¤ 6 r< % r r % V@-b5¶ R ¾TH V ô TH % -based £½' ¤J )ê ë Õ õ úTU HV ¾¾TU V"TU Hi, V 5 TU 14X^#V-'TU V- ÆT4! iV ô T4! V@<b5 G.1 context formation: ¡ ¢¿ ¿ ¨ Ç \ô T9_¬Ù(VÈ , ^ 5¶ Static Semantics for FTC % ô #b5îR Ì 6 % % ¾TH V ô T O VÈ#b5¶R r r r r r r  ¬ A 3 r r ô àaáMâ"T9 V6­® r Ù r r 6A i3 ô T9 ¬Ù VÈ" v TU i9Vv5¶ r r r ¤T%ºTNZ9HÙ ^ [OVh V u u u u r u u ô à_áâ@T9 V­+Ù Â ¬ 6Au {3 Y 3 u u r u u 6A i3 A 3 ô T9 u ¬{Ù V@u *" v TU Vv5 + u u u / )U'9àaáMâ@T9 y V1 HÙ ^ y X H ¬\3 ^ ÁºÂXQ " t TU V à " v TU V à S r r r u C T@>9àaáMâ@T9 V- \ {X H ^ ÁWT let in V r u r u fsig TU 3 V) ô fsig TU 3 V) <6 5¶ 24 Ù£R 7g1T9Ù(V (131) Aµ 7-D·¹£´ < ' ¾ r r ¢ÇQVe '# e - S (132) A v7- $ >-Ý - (133) A>9 76 ¢KWi>9 - (134) 6A>9 7¢>9 - (135) G.4 exp formation: ¢£¥A- ¡ » >¢£ - ¼ *Q'< e¡M eMA- (136) #< S (137) y >9 ÁºÂQ¡ à B" v NT WV@ÁWT%-ÂV r ÇQXe " t TNWVS A µ £ À - À Ê £´ < < r r r #' e S QVe < < e - S 6A > ¤¥- $ ¢\ v- v- $ ¢£¥ v- - y £DTNWV@*Q' à _S*T%-OV r A ¾ r (141) (142) Ù£ ÙJSq%T -ÚV y ÇÙ£q ¤¥*Q' à ÙJS*T%-ÂV + P )Uv9 Ù Â**v9 £ (139) (140) Av9 Ì£¥A/T@>9 Í ¥VWi>9 Í £¥VWi>9 Í y ¢£pZ Ùv[M*Q¡ à (138) r u u u A >6 ¤ A ¢7r u u let in A (143) (144) (145) G.5 constructor equivalence: ¾ÙݧÝÙ Rules for congruence, reflexivity, symmetry, and transitivity are omitted. y Á¸£Q' à ٠S ¢Ù v9 ÌÙ ÆT9\v9 Ù(V#Z Ù [W§¿ÁWT9Ù(V@ Ù ¾T9\v9 ÙºZ \[OV"§ÝÙ¤ y (146) (147) ¢ÙÚ§ÂQ<< e#Ù& <<NSJQ'< ¡e 9 '< S ¢gfehT9Ù(V§ÝÙ q (148) r r ÂQXe 9 ¥ << e 9 S Aµ ÙȧÝgfemAT9Ù(VÈ ¦ ¹M£´ '< r r< ¢ÇVQ e Ù #< eO6ÙÈPSû§ÝÙ£q (149) G.6 type equivalence: 7-ï§0- Rules for congruence, reflexivity, symmetry, and transitivity are omitted. 25