Constructor Specialization. Torben. Mogensen. the residual programs. 2 Overview. further work.
|
|
- Annabelle Jennings
- 5 years ago
- Views:
Transcription
1 Constructor Specialization Torben. Mogensen DIKU, University of Copenhagen, Denmark Abstract In the section on \challenging problems" in the proceedings from the rst international workshop on partial evaluation and mixed computation [BEJ88] a question is stated: \Can PE be used to generate new specialized data types, in a way analogous to generating specialized functions". Since then little has been done to address this problem. In [Lau89], new types are indeed generated, but they are all simpler versions of the types in the original program. It is, e.g. not possible to have types with more constructors than the types in the original program. I propose to alleviate this by means of constructor specialization. Constructors are specialized with respect to the static parts of their arguments, just like residual functions. I show how this is done and argue that it makes it possible to get good results from partial evaluation in cases where the traditional methods fail to produce satisfactory results. The discussion is centered around a small subset of Standard ML, but the idea applies equally well to other languages having user dened constructors, e.g. Haskell and Prolog. 1 Motivation It is usually considered bad practice if all residual programs for a given initial program share some syntactic limits with the original program, when these limits are not present in the language as a whole. This is especially true when partially evaluating an interpreter: any limits in the target programs means that the target language is not fully exploited. An example is if the number of function denitions in a residual program cannot be greater than the number of function denitions in the original program. This limitation is lifted when polyvariant specialization of functions are used ([Bul88], [JSS85], [JSS89]). The literature shows other examples of early partial evaluators having such inheritable limitations which later systems avoid, e.g. the number of arguments to functions being no greater in the residual functions than in the original functions, which is solved by variable splitting ([Ses86], [Mog88], [Rom90], [Lau89]). Basically one can look at features that the programming language allows unlimited use of, but which any particular program uses only nitely. In addition to the above, languages with user denable constructors, usually only allow a nite number of such in any particular program. Partial evaluators of such languages (e.g. [Lau89]) usually allow only constructors from the original program to appear in the residual programs. This can have the eect that data structures in the residual programs are represented suboptimally, as they will have to be forced into the mold of the data types from the original program. This is often the case in interpreters for typed languages: values of all types are represented using a single universal type, and this is carried over to the residual programs, where this ought no longer to be necessary. 2 Overview I show a simple example of a program where normal specialization techniques yield unsatisfactory results, and show that constructor specialization handles this well. I then discuss how to modify binding time analysis and specialization algorithm to handle constructor specialization. I briey touch upon possible renements to these methods and some semantic issues that are raised by constructor specialization. I then revisit the example and show how a simple modication of the program improves the result obtained through constructor specialization. This is an instance of bindingtime improvement [HH91]. Finally I conclude and discuss further work. 3 An example Consider the Standard ML program shown in gure 1. It implements a simple parser for a restricted class of grammars using only one nonterminal. EMPTY corresponds to the empty string, REC is a recursive reference to the entire grammar (and is thus the only nonterminal). SYMB indicates a terminal symbol and SEQ and ALT indicates sequence and alternative. The function parse takes a grammar and a list of terminal symbols and determines if the list is in the language generated by the grammar. It uses a stack of pieces of the grammar, which will be used to match against the remainder of the terminal list. The data type ToDo implements this stack. The parser backtracks on alternatives. Let us consider specialization of the parser with respect to a specic grammar. A simple binding time analysis will tell us that the grammar and the stack are static throughout, so we expect all to be well when specializing. Let's try the grammar G! (G)G j, which is represented in the data type by ALT(SEQ(SYMB("("),SEQ(REC,SEQ(SYMB(")"),REC))), EMPTY)
2 Figure 1: Backtracking parser datatype Gram = EMPTY REC SYMB of string SEQ of Gram*Gram ALT of Gram*Gram datatype ToDo = DONE DO of Gram*ToDo fun parse(g,s) = p(g,s,g,done) fun p(g,s,g0,todo) = case g of EMPTY => nowdo(todo,s,g0) REC => p(g0,s,g0,todo) SYMB c => s<>[] andalso (hd s)=c andalso nowdo(todo,tl s,g0) SEQ (g1,g2) => p(g1,s,g0,do(g2,todo)) ALT (g1,g2) => p(g1,s,g0,todo) orelse p(g2,s,g0,todo) fun nowdo(todo,s,g) = case todo of DONE => s=[] DO (g1,todo') => p(g1,s,g,todo') To our (maybe not so great) surprise the specialization doesn't terminate. The reason is that the stack grows unboundedly during specialization. It is clear that, in general, the size of the stack depends on the input string, so it is not the fault of the partial evaluator per se. The usual solution to handle unbounded data structures is to generalize them, either during specialization or by modifying the binding times. This, however, has the unfortunate eect that, since the grammar is stored on the stack, it too becomes dynamic. The result is that no speedup can be obtained by partial evaluation. It is not obvious that the program can be rewritten to avoid this problem (unless one uses continuations like in [Mos93], but that is a major rewrite, and not an option if the language does not support higher order functions). We take a closer look at why the generalizing the stack causes the grammar to be dynamic. When handling the sequence operator, the parser pushes a part of the grammar on the stack, using the constructor DO. Since the stack is generalized, DO is a dynamic constructor and the normal rules for binding times makes the arguments to it dynamic too. Thus, when we pop the grammar from the stack in nowdo, it is dynamic. But what if we allow dynamic constructors to have static arguments? Then we can pop a static grammar from the stack, even when this is dynamic. \How," I hear you say \are we supposed to do this?". When we use DO to push the grammar on the stack, we must generate code in the residual program that does this (the stack is dynamic, remember), and similarly we must generate residual code to pop the stack in the residual versions of nowdo. Instead of pushing the actual grammar, we can specialize DO to the grammar and use the specialized constructor to do the pushing. When popping, we do a case over the specialized versions of DO and in each branch we can use the static grammar that the corresponding constructor is specialized with. If we use the example grammar from above, we will during execution push the following bits of the grammar: SEQ(REC,SEQ(SYMB(")"),REC)) SEQ(SYMB(")"),REC) REC We can thus make three specialized versions of DO, corresponding to each of these possibilities. Let us call these DO_0, DO_1 and DO_2. When doing a case on these (in nowdo), we can in the branch corresponding to DO_0 use the fact that the grammar (g1) is SEQ(REC,SEQ(SYMB(")"),REC)) etc. Thus the grammar will remain static in all calls to p, and we obtain the residual program shown in gure 2. We have unfolded all calls to p, except the rst and the one in the branch of the REC operator. The calls to nowdo are all left residual. It can be seen that all mention of the grammar has been evaluated away during specialization. It is clear that the residual parser is much more ecient than the original. However, there is still room for improvement: there are two calls to nowdo' with constructors in the arguments. These will immediately be tested upon. Unfolding these calls can remove some dynamic pushing and popping. Note that we still need to push DO_1 and test for this against DONE. We will later see how we can modify the parser slightly so the superuous operations disappear from the residual parser. 4 A small language First we describe a small subset of Standard ML [MTH90], which will be used in the sections on binding time analysis and specialization. The syntax of the language is shown in gure 3. Note that the data type declarations are monomorphic. Polymorphic data types cause some extra bookkeeping during binding time analysis and partial evaluation, so for ease of presentation, these have been left out. For similar reasons
3 Figure 2: Residual parser using constructor specialization datatype ToDo' = DONE DO_0 of ToDo' DO_1 of ToDo' DO_2 of ToDo' fun parse'(s) = p'(s,done) fun p'(s,todo) = (s<>[] andalso (hd s)="(" andalso nowdo'(do_0 todo,tl s)) orelse nowdo'(todo,s) fun nowdo'(todo,s) = case todo of DONE => s=[] DO_0 todo' => p'(s,do_1 todo') DO_1 todo' => s<>[] andalso (hd s)=")" andalso nowdo'(do_2 todo',tl s) DO_2 todo' => p'(s,todo') Figure 3: Syntax of SML subset P rogram! Datatype F unction Datatype! datatype T ypeid = Contype + j Contype! Conid of T ypeid F unction! fun F unid P attern = Exp P attern! (V arid ; ) Exp! V arid j F unid Exp j Basic Exp j ConidExp j (Exp ; ) j case Exp of Branch + j Branch! Conid P att => Exp the language is restricted to rst order functions and no local denitions. Inx operators are assumed to be syntactic sugar for calls to basic functions, and so do not occur in the grammar. Similarly nullary constructors and functions are considered sugar for functions taking an argument of unit type. Constants are nullary basic functions. The notation Nonterminalsymbol is shorthand for a (possibly empty) sequence of separated by symbol. Similarly Nonterminal + symbol stands for a non-empty sequence. We will later use Nonterminal? to stand for zero or one occurrence of Nonterminal. 5 Binding time analysis A common way to describe binding times for functional languages is to use projections [Lau89], [Mog89], but there is no projection that naturally describes a data type where the constructors are unknown and their arguments known. So instead we will us a type-based approach like in [GJ91], [Mog92] and [Hen91]. For simplicity of presentation we'll use a simple monomorphic system, but the idea scales in the usual way to more complex systems. The binding times are described as a set of type rules. Binding time analysis consists of type inference using these rules. Figure 4 shows the syntax of annotated programs. Underlining is used to describe dynamic parts of the program. It is assumed that the program initially contains no underlines, but that a minimal consistent underlining will be provided during a type inference based binding time analysis. Details can be found in [Hen91]. Three environments are used: for variables, for functions and for constructors. All environments map their objects to binding time annotated types. is used to join environments. In case of common names in and 0, 0 takes precedence in 0. An annotated type has the form BT type! T ypeid j T ypeid j BT type j BT type! BT type where underlines denote dynamic types. For convenience of notation we will use the equivalences that the empty product type is the unit type () and that BT 1... BT n = BT 1... BT n. We will thus use BT for a completely dynamic type. Note that since the language is rst order, there is no such thing as a dynamic function. A constructor is considered a function from its argument types to its data type. If a constructor is dynamic, its data type is and vice versa, so there is no need to annotate the function space arrow. We rst present rules for a \traditional" binding type analysis and then modify these to handle constructor specialization. The \traditional" type rules are given in gure 5. The types for the dierent logical connectives are shown with the rules that have them in their conclusion. Obviously, it is the rules involving dynamic constructors that must be modied to accommodate constructor specialization. The rule for constructor declaration states that the argument type of a constructor in a dynamic data type must be dynamic. We remove this side condition. Similarly the rule for dynamic constructor application says that the argument must be dynamic. We change this so it (like in dynamic function applications) can be of any binding time. There is no need to change the rule for case-expressions, as
4 Figure 4: Annotated syntax AP rogram! ADatatype AF unction ADatatype! datatype T ypeid = AContype + j j datatype T ypeid = AContype + j AContype! Conid of AT ypeid AF unction! fun F unid AP attern = AExp AP attern! (AV arid ; ) AExp! V arid j F unid AExp j F unid AExp j Basic AExp j Basic AExp j Conid AExp j Conid AExp j (AExp ; ) j case AExp of ABranch + j j case AExp of ABranch + j ABranch! Conid AP att => AExp AT ypeid! T ypeid j T ypeid AV arid! V arid j V arid it imposes no restrictions on the arguments of constructors. One can note, though, that it is now possible to have static pattern variables in dynamic case-expressions. The modi- ed rules are shown in gure 6. The binding time analysis is thus no more complex than before the modications, if anything it is simpler. If we had used an abstract interpretation approach, we would have had to modify our binding time domain. So in this respect the type/constraint based approach is more exible. 6 Specialization We use inference rules to specify a relation between the original program and the specialized program. Again, this leaves some room for dierent implementations. The rules are shown in gures 7 and 8. The binding time environments and are used in the rules for specialization. In addition to these, maps constructors to the sets of the static arguments to which they are specialized and maps function names to sets of static arguments. The environment binds variables to partially static values. The static parts of these are values, and the dynamic parts are residual expressions: P V al! V alue j Exp j (P V al; ) j Conid(P val) We are a bit sloppy in that we use (;... ; ) both for tupling of values and for constructing tuple-expressions. Specialized functions and constructors are identied by pairs of their original names and the static parts of their arguments. These pairs must be replaced by new names in the usual way. 0 contains the goal function and the arguments to which this must be specialized. The environment ensures that all specialized functions that are called are also dened, and ensures that if a constructor is specialized, then all it's specialized versions are declared and occur in every residual case-expression where the original constructor appears in the corresponding original case-expression. This is handled in the rules for Function, Contype and Dynamic branch. The rules for Pattern and Varid are used to build specialization time environments and residual patterns. The function new creates new unique variable names. The rules for Exp specializes expressions. Static expressions produce values and dynamic expressions produce residual expressions. Partially static expressions produce a mixture of these, which must be taken apart (using %) when needed as arguments to residual function calls or dynamic constructor applications (note the similarity between the rules for these). The most interesting case is the dynamic case-expression. Each branch in the original case-expression is made into several branches in the residual case-expression. These branches are produced by the rule for Dynamic branch; the possible static arguments are fetched from and each value is used to make a residual branch: the constructor name is specialized, the pattern is specialized, a new environment is built, in which the body of the branch is specialized. If constructor specialization is not used, only a single residual branch would be produced, and all pattern variables would be dynamic. Note the similarity between the rule for Dynamic branch and for Function. The main dierence is that the rule for Dynamic branch is used in every dynamic caseexpression, whereas the rule for Function is applied only once for each function. Retyping similar to what is achieved through projection factorisation in [Lau89] is done by the rules for Type: the residual type depends on the static value. Note how these rules parallel the rules for splitting a partially static value into its static and dynamic components and for variable splitting. Static base types are replaced by the unit type and the corresponding dynamic expressions are replaced by the unit constant (). The tuple type constructor used in the rules for constructing residual types is assumed to be associative and has the unit type as unit element. New parameter lists (patterns) to functions and constructors are constructed, such that each dynamic component of a partially static value becomes a separate parameter. For formal parameters this is handled by the rules for Pattern and Variable splitting. For actual parameters the rules for splitting values into static and dynamic components are used. The operator + is used to join tuple expressions and patterns. It obeys the rules below. The rules are prioritized from top to bottom. () ++ x = x x ++ () = x x ++ y = (x; y) (x 1;... ; x n) ++ (y 1;... ; y n) = (x 1;... ; x n; y 1;... y n) x ++ (y 1;... ; y n) = (x; y 1;... ; y n) (x 1;... ; x n) ++ y = (x 1;... ; x n; y) The operation new(v ) used in the rules for Variable splitting creates a new unique name from the name V.
5 Figure 5: Type rules for binding time analysis Program: ` AP rogram / (Conid! BT type)=(f unid! BT type) ` D 1 > 1... ` D 1 > n = 1... n ; ` F n ; ` F n m m = 1... m ` D 1... D n F n 1... F n m / = Datatype: ` ADatatype > (Conid! BT type) ` datatype T i = C 1 of BT 1 j... j C n of BT n > [C 1 7! BT 1! T i ;... ; C n 7! BT n! T i] ` datatype T i = C 1 of BT 1 j... j C n of BT n > [C 1 7! BT 1! T i ;... ; C n 7! BT n! T i] Function: (Conid! BT type); (F unid! BT type) ` AF unction (F unid! BT type) Pattern: ` AP attern ; (V arid! BT type)=bt type ` P ; =BT 1 ; ; ` E : BT 2 ; ` fun F P = E [F : BT 1! BT 2] ` (V 1;... ; V n) ; [V 1 7! BT 1;... V n 7! BT n]=bt 1... BT n Exp: (Conid! BT type); (F unid! BT type); (V arid! BT type) ` AExp : BT type V = BT ; ; ` V : BT F = BT 1! BT 2 ; ; ` E : BT 1 ; ; ` F E : BT 2 F = BT 1! BT 2 ; ; ` E : BT 1 ; ; ` F E : BT 2 B : T 1! T 2 ; ; ` E : T 1 ; ; ` B E : T 2 B : T 1! T 2 ; ; ` E : T 1 ; ; ` B E : T 2 C = BT 1! T i ; ; ` E : BT 1 ; ; ` C E : T i C = BT 1! T i ; ; ` E : BT 1 ; ; ` C E : T i ; ; ` E 1 : BT 1... ; ; ` E n : BT n ; ; ` (E 1;... ; E n) : (BT 1;... ; BT n) ; ; ` E : T i ; ; ; T i ` B 1 :> BT 2... ; ; ; T i ` B n :> BT 2 ; ; ` case E of B 1j... jb n : BT 2 ; ; ` E : T i ; ; ; T i ` B 1 :> BT 2... ; ; ; T i ` B n :> BT 2 ; ; ` case E of B 1j... jb n : BT 2 Branch: (Conid! BT type); (F unid! BT type); (V arid! BT type); BT type ` ABranch :> BT type C = BT 1! T i ` P ; 0 =BT 1 ; ; 0 ` E : BT 2 ; ; ; T i ` C P => E :> BT 2
6 Figure 6: Modied type rules for binding time analysis Datatype: ` datatype T i = C 1 of BT 1 j... j C n of BT n > [C 1 7! BT 1! T i ;... ; C n 7! BT n! T i] Exp: C = BT 1! T i ; ; ` E : BT 1 ; ; ` C E : T i It is easy in an implementation of the specialization rules to maintain : entries are added whenever residual function calls are made, and residual functions are generated for each entry until all entries have denitions. New entries can never cause earlier generated residual function denitions to be invalid, so the new denitions are simply added to the existing denitions. Things are not as simple with. A new specialized constructor requires all residual case-expressions of relevant type to test on this, even those case-expressions that are already generated. Thus either regeneration of old function denitions in a standard xed-point iteration style or an ability to \backpatch" earlier generated case-expressions is needed. The rst solution is simple, but inecient. The second solution is potentially more ecient, as each piece of residual code is only generated once, but requires either destructive updating of the residual program, or a multi-pass algorithm that rst generates \pieces" of code for the caseexpression branches and then assembles these in the nal residual program. 7 Renements and semantic considerations There is a lot of room for improvement of both binding time analysis and specialization as they are shown here. First of all, polyvariant binding time analysis ([GR92], [DNBDV91]) could be used. Specialized constructors add no fundamental extra complexities to this problem, except that projections, as used in [Lau89] and [DNBDV91] appear ill-suited for describing binding times involving specialized constructors. Another problem (which is unrelated to polyvariant binding time analysis) is the fact that types are specialized monovariantly in the specialization denition presented in this paper. Thus the residual program can have no more data type declarations than the original program, something that is against our \guiding rule" of not letting limits be inherited. It also has some potential semantic problems: when specializing a constructor it is automatically assumed that it will be used in any residual version of case-expressions that use the original constructor. Consider an interpreter where a universal data type is used to represent arbitrary types. Consider this interpreter specialized with respect to a program that uses two types. The two types will in the residual program be represented by a single type, and the functions that operate on one of the types will also have to test on the constructors from the other type. This can in the worst case cause run-time errors during specialization, and at best there will be lots of \dead code" in the residual program. The solution to this is to perform polyvariant type specialization: the specialized constructors are not collected into a single type, but grouped corresponding to where they are generated and used in the residual program. It is not clear how best to do this, but one could assume that newly generated specialized constructors are in a type of their own, and only combine the types when necessary, e.g. when they occur as the result of dierent branches to the same caseexpression. A union/nd style algorithm would be suitable for this approach. The rules for specialization say nothing about what happens if specialized constructors occur in the output of the program. The most obvious solution is to disallow this by adding constrains that enforce all parts of output types to be dynamic. Another solution would be to allow specialized constructors in the output, but letting the specializer in addition to the residual program also return a specication of how the specialized constructors correspond to original terms. This can be seen as a derivor mapping the specialized data types to the original data types. Such a derivor can also be allowed as part of the input to the specializer, allowing a program to be specialized with respect to the specialized data type of another program. This can be used to specialize the interface types of multi-pass algorithms. This is an similar what Ershov calls mixed computation [BEJ88]: both residual program and residual data are produced. In our case, though, it is not actual data, but a data specication that is produced. 8 The example revisited In section 3 I promised to show a modication of the parser program from gure 1, which would allow better specialization. The problem was that, in the residual program, p' would call nowdo' with a constructor which immediately would be decomposed inside nowdo'. The problem occurs because all applications of the constructor DO are made residual. The reason we made them residual was to avoid innite growth in the stack, but this only occurs because we have recursion in the grammer. If we can generalize the stack only when recursion occurs, we can make more of the stack static. A way to do this is to leave the type ToDo static, but encapsulate the stack in a dynamic constructor of another type whenever recursion is needed. The modied parser is shown in gure 9. By making ToDo1 dynamic, we can avoid innite growth of the stack. Using the same grammar as in section 3, we will apply GENERALIZE to the following arguments DONE DO(SEQ(SYMB(")"),REC),GENERALIZED(<ToDo1>)) Note that the function generalize ensures that GENERALIZE will not be applied to an already generalized argument. This
7 Figure 7: Rules for specialization (Part 1) Program: (Conid! BT type); (F unid! BT type); (F unid! fp valg) ` AP rogram / P rogram ; ` D i > Ds i for i = 1;... ; n ; ; ; ` F n j F ns j for j = 1;... ; m 0 ; ; 0 ` D 1... D n F n 1... F n m / Ds 1... Ds n F ns 1... F ns m Datatype: (Conid! BT type); (Conid! fp valg) ` ADatatype > Datatype? ; ` datatype T i = Cs > ; ` C 1. Cs 1... ; ` C n. Cs n ; ` datatype T i = C 1j... jc n > datatype T i = Cs 1j... jcs n Contype: (Conid! BT type); (Conid! fp valg) ` AContype. Contype + j Type: (Conid! BT type); BT type ` P val & T ype C = fv 1;... ; v ng ; BT ` v 1 & T 1... ; BT ` v n & T n ; ` C of BT. (C; v 1) of T 1 j j (C; v n) of T n ; T ` v & (T ) ; T i ` v & () if T i is a base type C = BT! T i ; BT ` v & T ; T i ` C(v) & T if T i is a data type ; BT 1 ` v 1 & T 1... ; BT n ` v n & T n ; BT 1... BT n ` (v 1;... ; v n) & T 1... T n Function: (Conid! BT type); (Conid! fp valg); (F unid! BT type); (F unid! fp valg) ` AF unction F unction F = BT 1! BT 2 F = fv 1;... ; v ng ; BT 1; P ` v i ; i=p i ; ; ; ; i ` E : E i for i = 1;... ; n ; ; ; ` fun F P = E fun (F; v 1) P 1 = E 1... fun (F; v n) P n = E n Pattern: (Conid! BT type); BT type; AP attern ` (P V al ; ) ; (V arid! P val)=p attern ; BT 1; V 1 ` v 1,! v 0 1=P 1... ; BT n; V n ` v n,! v 0 n=p n ; BT 1... BT n; (V 1;... ; V n) ` (v 1;... ; v n) ; [V 1 7! v 0 1;... ; V n 7! v 0 n]=p P n Variable splitting: (Conid! BT type); BT type; V arid ` (P V al ; ),! (V arid! P val)=p attern V 0 = new(v ) ; T ; V ` (),! V 0 =V 0 ; T i; V ` v,! v=() if T i is a base type C = BT! T i ; BT; V,! v 0 =P ; T i; V ` C(v),! C(v 0 )=P if T i is a data type ; BT 1; V,! v 0 1=P 1... ; BT n; V,! v 0 n=p n ; BT 1... BT n; V ` (v 1;... ; v n),! (v 0 1;... v 0 n)=p P n
8 Figure 8: Rules for specialization (Part 2) Exp: (Conid! BT type); (Conid! fp valg); (F unid! BT type); (F unid! fp valg); (V arid! P val) ` AExp : P V al V = v ; ; ; ; ` V : v ; ; ; ; ` E : v v ` P ; 0 =P 0 ; ; ; ; 0 ` E 0 : w ; ; ; ; ` F E : w where F is dened by fun F P = E 0 F = BT 1! BT 2 ; ; ; ; ` E : v ; BT 1 ` v % v 0 =E 0 v 0 2 F ; ; ; ; ` F E : (F; v 0 ) E 0 ; ; ; ; ` E : v ; ; ; ; ` B E : b(v) ; ; ; ; ` E : E 0 ; ; ; ; ` B E : B E 0 ; ; ; ; ` E : v ; ; ; ; ` C E : C(v) C = BT 1! T i ; ; ; ; ` E : v ; BT 1 ` v % v 0 =E 0 v 0 2 C ; ; ; ; ` C E : (C; v 0 ) E 0 ; ; ; ; ` E 1 : v 1... ; ; ; ; ` E n : v n ; ; ; ; ` (E 1;... ; E n) : (v 1;... ; v n) ; ; ; ; ` E : C i(v) v ` P i ; 0 =P 0 ; ; ; ; 0 ` E i : w ; ; ; ; ` case E of C 1 P 1 => E 1 j... j C n P n => E n : w ; ; ; ; ` E : E 0 ; ; ; ; ` B i :> Bs i for i = 1;... ; n ; ; ; ; ` case E of B 1j... jb n : case E 0 of Bs 1j... jbs n Dynamic branch: (Conid! BT type); (Conid! fp valg); (F unid! BT type); (F unid! fp valg); (V arid! P val) ` ABranch :> Branch j C = BT! T i C = fv 1;... ; v ng ; BT; P ` v i ; i=p i ; ; ; ; i ` E : E i for i = 1;... ; n ; ; ; ; ` C P => E :> (C; v 1) P 1 => E 1 j... j (C; v n) P n => E n Splitting into static and dynamic parts: (Conid! BT type); BT type ` P val % V al=exp ; T ` E % ()=(E) ; T i ` v % v=() if T i is a base type C = BT! T i ; BT ` v % v 0 =E ; T i ` C(v) % C(v 0 )=E if T i is a data type ; BT 1 ` v 1 % v 0 1=E 1... ; BT n ` v n % v 0 n=e n ; BT 1... BT n ` (v 1;... ; v n) % (v 0 1;... ; v 0 n)=e E n
9 Figure 9: Modied parser datatype Gram = EMPTY REC SYMB of string SEQ of Gram*Gram ALT of Gram*Gram datatype ToDo = DONE DO of Gram*ToDo GENERALIZED ToDo1 datatype ToDo1 = GENERALIZE ToDo fun parse(g,s) = p(g,s,g,generalized(generalize(done))) fun p(g,s,g0,todo) = case g of EMPTY => nowdo(todo,s,g0) REC => p(g0,s,g0,generalize(todo)) SYMB c => s<>[] andalso (hd s)=c andalso nowdo(todo,tl s,g0) SEQ (g1,g2) => p(g1,s,g0,do(g2,todo)) ALT (g1,g2) => p(g1,s,g0,todo) orelse p(g2,s,g0,todo) fun generalize(todo) = case todo of GENERALIZED(t) => t _ => GENERALIZED(GENERALIZE(todo)) fun nowdo(todo,s,g) = case todo of DONE => s=[] DO (g1,todo') => p(g1,s,g,todo') GENERALIZED t => case t of GENERALIZE todo' => nowdo(todo',s,g) Figure 10: Residual modied parser datatype ToDo1' = GENERALIZE_0 GENERALIZE_1 of ToDo1' fun parse'(s) = p'(s,generalize_0) fun p'(s,todo) = (s<>[] andalso (hd s)="(" andalso p'(tl s,generalize_1(todo))) orelse (case todo of GENERALIZE_0 => s = [] GENERALIZE_1(todo') => (s<>[] andalso (hd s)=")" andalso p'(tl s,todo'))
10 would have lead to extra dynamic construction and decomposition. We get the residual program shown in gure 10. All calls to nowdo and all calls to p except the initial call and the call in the REC branch are unfolded. It is now clear from the residual program that the depth of the stack is the number of outstanding parenthesis. Note that the todo argument of p has been retyped: where it originally was ToDo it is now a specialized instance of ToDo1, which is the type of the dynamic argument to a constructor (GENERALIZED) of the original type. The \trick" of generalizing unbounded structures only at particular places, guarded by constructors like GENERALIZE and GENERALIZED corresponds closely to a similar \trick" which is used to generalize continuations in Similix, where the guards are eta-conversions ([Bon91], [Mos93]). 9 Conclusion and further work I rst got the idea of constructor specialization in 1987 when I was writing an interpreter for a functional language in a term rewrite language. This interpreter used a stack and partial evaluatially evaluating it caused the same problems with unbounded stacks as shown in the example here. I considered ways of handling this problem and found that constructor specialization would help. I didn't follow up on the idea, as my attention turned elsewhere. But I have always thought the idea had merit, so I have now tried to formalize the idea and present them to a greater public. I believe constructor specialization will have most impact on two kinds of program: those that use a stack or similar structure (as shown in the example) and interpreters that use a single data type to encode a large family of types in the implemented languages. The latter problem has been investigated in [Lau91b] and [HL91] in the context of selfappliction, where a double level of coding is needed. Constructor specialization does not handle the problem of large space requirements that these papers have dierent solutions to, but instead improves the quality of the residual programs (e.g. compiled programs) by \inventing" suitable data types for each residual program. As mentioned in section 7, the presented specialization method needs a further renement to handle this really well. In higher order languages the problem of unbounded stack can sometimes be solved by using continuations. This is the case with the parser shown in the example, and it is also the solution chosen in [Mos93]. There is no similar approach that will work for coding of data-structures in interpreters. It is in general possible to replace arbitrary algebraic types with higher order functions, but it doesn't yield the desired result and will in most cases cause problems in typed languages, when recursive data types (legal) are replaced by recursive function types (illegal). In the abstract I said that the ideas are applicable to other languages and mentioned Haskell and Prolog. Haskell is suciently similar to ML that this is no surprise. Prolog has two properties that can cause problems: it is untyped and it allows unication of terms containing unbound variables. The untyped nature is not much of a problem, as specialization is mostly at the constructor level rather than the type level anyway. Unication can be a problem, though. It boils down to what happens when two dierently specialized versions of the same constructor are unied. If the static arguments to which they are specialized are uniable, the unication should succeed. But if dierent names are given to the specialized constructors, unication will fail. A solution to this problem is to make sure that the static parts are only uniable if they are in fact equal. If they are ground, this is cartainly true. It would therefore seem reasonable to require the parameters to which constructors are specialized to be ground. In Logimix [MB93], predicates are (for similar reasons) only specialized with respect to ground parameters, so it is not unreasonable that the same should apply to constructors. Another problem is what happens when specialized constructors are unied with values supplied at runtime to the residual program. This problem is similar to the problem of specialized constructors in input and output mentioned in section 7, and can indeed be solved in a similar fashion. At present (March 1993) I have no implementation of constructor specialization except for a prototype binding time analysis, so this is obviously the next step. When the basic method is implemented the renements mentioned in section 7 can be considered. It is possible that constructor specialization can be added to Similix's partially static data-type feature [Bon93]. I will discuss this with Anders Bondorf. References [BEJ88] [Bon91] [Bon93] D. Bjrner, A.P. Ershov, and N.D. Jones, editors. Partial Evaluation and Mixed Computation. Proceedings of the IFIP TC2 Workshop, Gammel Averns, Denmark, October Amsterdam: North-Holland, A. Bondorf. Compiling laziness by partial evaluation. In S.L. Peyton Jones, G. Hutton, and C. Kehler Holst, editors, Functional Programming, Glasgow 1990, pages 9{22, Berlin: Springer-Verlag, A. Bondorf. Similix Manual, System Version 5.0. Technical Report, DIKU, University of Copenhagen, Denmark, [Bul88] M.A. Bulyonkov. A theoretical approach to polyvariant mixed computation. In D. Bjrner, A.P. Ershov, and N.D. Jones, editors, Partial Evaluation and Mixed Computation, pages 51{ 64, Amsterdam: North-Holland, [DNBDV91] A. De Niel, E. Bevers, and K. De Vlaminck. Program bifurcation for a polymorphically typed functional language. In Partial Evaluation and Semantics-Based Program Manipulation, New Haven, Connecticut (Sigplan Notices, vol. 26, no. 9, September 1991), pages 142{153, New York: ACM, [GJ91] [GR92] C.K. Gomard and N.D. Jones. A partial evaluator for the untyped lambda-calculus. Journal of Functional Programming, 1(1):21{69, January M. Gengler and B. Rytz. A polyvariant binding time analysis handling partially known values. In M. Billaud et al., editors, WSA '92, Static Analysis, Bordeaux, France, September Bigre vols 81{82, 1992, pages 322{330, Rennes: IRISA, 1992.
11 [Hen91] [HH91] F. Henglein. Ecient type inference for higherorder binding-time analysis. In J. Hughes, editor, Functional Programming Languages and Computer Architecture, Cambridge, Massachusetts, August 1991 (Lecture Notes in Computer Science, vol. 523), pages 448{472, ACM, Berlin: Springer-Verlag, C.K. Holst and J. Hughes. Towards bindingtime improvement for free. In S.L. Peyton Jones, G. Hutton, and C. Kehler Holst, editors, Functional Programming, Glasgow 1990, pages 83{100, Berlin: Springer-Verlag, [HL91] C.K. Holst and J. Launchbury. Handwriting cogen to avoid problems with static typing. In Draft Proceedings, Fourth Annual Glasgow Workshop on Functional Programming, Skye, Scotland, pages 210{218, Glasgow University, [JSS85] [JSS89] N.D. Jones, P. Sestoft, and H. Sndergaard. An experiment in partial evaluation: the generation of a compiler generator. In J.-P. Jouannaud, editor, Rewriting Techniques and Applications, Dijon, France. (Lecture Notes in Computer Science, vol. 202), pages 124{140, Berlin: Springer-Verlag, N.D. Jones, P. Sestoft, and H. Sndergaard. Mix: a self-applicable partial evaluator for experiments in compiler generation. Lisp and Symbolic Computation, 2(1):9{50, [Lau89] J. Launchbury. Projection Factorisations in Partial Evaluation. PhD thesis, Department of Computing, University of Glasgow, November Revised version in [Lau91a]. [Lau91a] J. Launchbury. Projection Factorisations in Partial Evaluation. Cambridge: Cambridge University Press, [Lau91b] J. Launchbury. A strongly-typed selfapplicable partial evaluator. In J. Hughes, editor, Functional Programming Languages and Computer Architecture, Cambridge, Massachusetts, August 1991 (Lecture Notes in Computer Science, vol. 523), pages 145{164, ACM, Berlin: Springer-Verlag, [MB93] T. Mogensen and A. Bondorf. Logimix: a self-applicable partial evaluator for Prolog. In K.-K. Lau and T. Clement, editors, LOPSTR 92. Workshops in Computing, Berlin: Springer- Verlag, January [Mog88] T. Mogensen. Partially static structures in a self-applicable partial evaluator. In D. Bjrner, A.P. Ershov, and N.D. Jones, editors, Partial Evaluation and Mixed Computation, pages 325{347, Amsterdam: North-Holland, [Mog89] T. Mogensen. Binding time analysis for polymorphically typed higher order languages. In J. Diaz and F. Orejas, editors, TAPSOFT '89. [Mog92] Proc. Int. Conf. Theory and Practice of Software Development, Barcelona, Spain, March 1989 (Lecture Notes in Computer Science, vol. 352), pages 298{312, Berlin: Springer-Verlag, T. Mogensen. Self-applicable partial evaluation for pure lambda calculus. In Partial Evaluation and Semantics-Based Program Manipulation, San Francisco, California, June 1992 (Technical Report YALEU/DCS/RR-909), pages 116{ 121, New Haven, CT: Yale University, [Mos93] C. Mossin. Partial evaluation of general parsers. In PEPM '93: ACM Symposium on Partial Evaluation and Semantics-Based Program Manipulation, New York: ACM, [MTH90] R. Milner, M. Tofte, and R. Harper. The Definition of Standard ML. MIT Press, [Rom90] S.A. Romanenko. Arity raiser and its use in program specialization. In N. Jones, editor, ESOP '90. 3rd European Symposium on Programming, Copenhagen, Denmark, May 1990 (Lecture Notes in Computer Science, vol. 432), pages 341{360, Berlin: Springer-Verlag, [Ses86] P. Sestoft. The structure of a self-applicable partial evaluator. In H. Ganzinger and N.D. Jones, editors, Programs as Data Objects, Copenhagen, Denmark, 1985 (Lecture Notes in Computer Science, vol. 217), pages 236{256, Berlin: Springer-Verlag, 1986.
Information Processing Letters Vol. 30, No. 2, pp , January Acad. Andrei Ershov, ed. Partial Evaluation of Pattern Matching in Strings
Information Processing Letters Vol. 30, No. 2, pp. 79-86, January 1989 Acad. Andrei Ershov, ed. Partial Evaluation of Pattern Matching in Strings Charles Consel Olivier Danvy LITP DIKU { Computer Science
More informationwhich a value is evaluated. When parallelising a program, instances of this class need to be produced for all the program's types. The paper commented
A Type-Sensitive Preprocessor For Haskell Noel Winstanley Department of Computer Science University of Glasgow September 4, 1997 Abstract This paper presents a preprocessor which generates code from type
More informationThunks (continued) Olivier Danvy, John Hatcli. Department of Computing and Information Sciences. Kansas State University. Manhattan, Kansas 66506, USA
Thunks (continued) Olivier Danvy, John Hatcli Department of Computing and Information Sciences Kansas State University Manhattan, Kansas 66506, USA e-mail: (danvy, hatcli)@cis.ksu.edu Abstract: Call-by-name
More informationSelf-applicable Partial Evaluation for Pure Lambda Calculus
Self-applicable Partial Evaluation for Pure Lambda Calculus Torben Æ. Mogensen DIKU, University of Copenhagen, Denmark Abstract Partial evaluation of an applied lambda calculus was done some years ago
More informationImproving CPS-Based Partial Evaluation: Writing Cogen by Hand
Improving CPS-Based Partial Evaluation: Writing Cogen by Hand Anders Bondorf DIKU Department of Computer Science Universitetsparken 1 DK-2100 Copenhagen, Denmark anders@diku.dk Dirk Dussart Departement
More informationUniversity of Utrecht. 1992; Fokker, 1995), the use of monads to structure functional programs (Wadler,
J. Functional Programming 1 (1): 1{000, January 1993 c 1993 Cambridge University Press 1 F U N C T I O N A L P E A R L S Monadic Parsing in Haskell Graham Hutton University of Nottingham Erik Meijer University
More informationinterpreted program is type correct. However, if the interpreted program has already been type checked and it is known to be type correct so using the
An exercise in dependent types: A well-typed interpreter Lennart Augustsson Magnus Carlsson Department of Computing Sciences Chalmers University of Technology S-412 96 G teborg, Sweden Email: {augustss,magnus}@cs.chalmers.se
More information(Refer Slide Time: 4:00)
Principles of Programming Languages Dr. S. Arun Kumar Department of Computer Science & Engineering Indian Institute of Technology, Delhi Lecture - 38 Meanings Let us look at abstracts namely functional
More informationthe application rule M : x:a: B N : A M N : (x:a: B) N and the reduction rule (x: A: B) N! Bfx := Ng. Their algorithm is not fully satisfactory in the
The Semi-Full Closure of Pure Type Systems? Gilles Barthe Institutionen for Datavetenskap, Chalmers Tekniska Hogskola, Goteborg, Sweden Departamento de Informatica, Universidade do Minho, Braga, Portugal
More informationExpressions that talk about themselves. Maarten Fokkinga, University of Twente, dept. INF, Version of May 6, 1994
Expressions that talk about themselves Maarten Fokkinga, University of Twente, dept. INF, fokkinga@cs.utwente.nl Version of May 6, 1994 Introduction Self-reference occurs frequently in theoretical investigations
More informationlanguage (no restrictions due to self-application) the generator manipulates only syntax trees (no need to implement a self-interpreter) values in gen
Multi-Level Specialization (Extended Abstract) Robert Gluck 1 and Jesper Jrgensen 2 1 DIKU, Department of Computer Science, University of Copenhagen, Universitetsparken 1, DK-2100 Copenhagen, Denmark.
More informationChalmers University of Technology. Without adding any primitives to the language, we dene a concurrency monad transformer
J. Functional Programming 1 (1): 1{000, January 1993 c 1993 Cambridge University Press 1 F U N C T I O N A L P E A R L S A Poor Man's Concurrency Monad Koen Claessen Chalmers University of Technology email:
More informationDemonstrating Lambda Calculus Reduction
Electronic Notes in Theoretical Computer Science 45 (2001) URL: http://www.elsevier.nl/locate/entcs/volume45.html 9 pages Demonstrating Lambda Calculus Reduction Peter Sestoft 1 Department of Mathematics
More information1. true / false By a compiler we mean a program that translates to code that will run natively on some machine.
1. true / false By a compiler we mean a program that translates to code that will run natively on some machine. 2. true / false ML can be compiled. 3. true / false FORTRAN can reasonably be considered
More informationAn Efficient Staging Algorithm for Binding-Time Analysis
An Efficient Staging Algorithm for Binding-Time Analysis Takuma Murakami 1, Zhenjiang Hu 1,2, Kazuhiko Kakehi 1, and Masato Takeichi 1 1 Department of Mathematical Informatics, Graduate School of Information
More information6.001 Notes: Section 8.1
6.001 Notes: Section 8.1 Slide 8.1.1 In this lecture we are going to introduce a new data type, specifically to deal with symbols. This may sound a bit odd, but if you step back, you may realize that everything
More informationresidual residual program final result
C-Mix: Making Easily Maintainable C-Programs run FAST The C-Mix Group, DIKU, University of Copenhagen Abstract C-Mix is a tool based on state-of-the-art technology that solves the dilemma of whether to
More informationperform. If more storage is required, more can be added without having to modify the processor (provided that the extra memory is still addressable).
How to Make Zuse's Z3 a Universal Computer Raul Rojas January 14, 1998 Abstract The computing machine Z3, built by Konrad Zuse between 1938 and 1941, could only execute xed sequences of oating-point arithmetical
More informationLogimix: A Self-Applicable Partial Evaluator for Prolog
Logimix: A Self-Applicable Partial Evaluator for Prolog Torben Æ. Mogensen DIKU, Department of Computer Science, University of Copenhagen Copenhagen, Denmark e-mail: torbenm@diku.dk Anders Bondorf DIKU,
More informationTo figure this out we need a more precise understanding of how ML works
Announcements: What are the following numbers: 74/2/70/17 (2:30,2:30,3:35,7:30) PS2 due Thursday 9/20 11:59PM Guest lecture on Tuesday 9/25 o No RDZ office hours next Friday, I am on travel A brief comment
More informationwhen a process of the form if be then p else q is executed and also when an output action is performed. 1. Unnecessary substitution: Let p = c!25 c?x:
URL: http://www.elsevier.nl/locate/entcs/volume27.html 7 pages Towards Veried Lazy Implementation of Concurrent Value-Passing Languages (Abstract) Anna Ingolfsdottir (annai@cs.auc.dk) BRICS, Dept. of Computer
More information1.1 Limitations in Turner et al.'s analysis Turner et al.'s analysis can handle simple cases of zero usage by use of structural rules similar to those
Types for 0, 1 or many uses Torben. Mogensen DIKU Universitetsparken 1 DK-2100 Copenhagen O Denmark email: torbenm@diku.dk phone: (+45) 35321404 fax: (+45) 35321401 Abstract. This paper will present an
More informationThe Essence of Compiling with Continuations
RETROSPECTIVE: The Essence of Compiling with Continuations Cormac Flanagan Amr Sabry Bruce F. Duba Matthias Felleisen Systems Research Center Compaq cormac.flanagan@compaq.com Dept. of Computer Science
More informationTyped Racket: Racket with Static Types
Typed Racket: Racket with Static Types Version 5.0.2 Sam Tobin-Hochstadt November 6, 2010 Typed Racket is a family of languages, each of which enforce that programs written in the language obey a type
More informationCS 6110 S14 Lecture 1 Introduction 24 January 2014
CS 6110 S14 Lecture 1 Introduction 24 January 2014 1 Introduction What is a program? Is it just something that tells the computer what to do? Yes, but there is much more to it than that. The basic expressions
More informationHutton, Graham and Bahr, Patrick (2016) Cutting out continuations. In: WadlerFest, April 2016, Edinburgh, Scotland.
Hutton, Graham and Bahr, Patrick (2016) Cutting out continuations. In: WadlerFest, 11-12 April 2016, Edinburgh, Scotland. Access from the University of Nottingham repository: http://eprints.nottingham.ac.uk/32703/1/cutting.pdf
More informationAn Approach to Polyvariant Binding Time Analysis for a Stack-Based Language
Supported by Russian Foundation for Basic Research project No. 06-01-00574-a and No. 08-07-00280-a, and Russian Federal Agency of Science and Innovation project No. 2007-4-1.4-18-02-064. An Approach to
More informationAn Approach to Polyvariant Binding Time Analysis for a Stack-Based Language
An Approach to Polyvariant Binding Time Analysis for a Stack-Based Language Yuri A. Klimov Keldysh Institute of Applied Mathematics, Russian Academy of Sciences RU-125047 Moscow, Russia, yuklimov@keldysh.ru
More information7. Introduction to Denotational Semantics. Oscar Nierstrasz
7. Introduction to Denotational Semantics Oscar Nierstrasz Roadmap > Syntax and Semantics > Semantics of Expressions > Semantics of Assignment > Other Issues References > D. A. Schmidt, Denotational Semantics,
More informationParallel Rewriting of Graphs through the. Pullback Approach. Michel Bauderon 1. Laboratoire Bordelais de Recherche en Informatique
URL: http://www.elsevier.nl/locate/entcs/volume.html 8 pages Parallel Rewriting of Graphs through the Pullback Approach Michel Bauderon Laboratoire Bordelais de Recherche en Informatique Universite Bordeaux
More informationHandout 10: Imperative programs and the Lambda Calculus
06-02552 Princ of Progr Languages (and Extended ) The University of Birmingham Spring Semester 2016-17 School of Computer Science c Uday Reddy2016-17 Handout 10: Imperative programs and the Lambda Calculus
More informationCSCI-GA Scripting Languages
CSCI-GA.3033.003 Scripting Languages 12/02/2013 OCaml 1 Acknowledgement The material on these slides is based on notes provided by Dexter Kozen. 2 About OCaml A functional programming language All computation
More informationExtracting the Range of cps from Affine Typing
Extracting the Range of cps from Affine Typing Extended Abstract Josh Berdine, Peter W. O Hearn Queen Mary, University of London {berdine, ohearn}@dcs.qmul.ac.uk Hayo Thielecke The University of Birmingham
More informationConclusions and further reading
Chapter 18 Conclusions and further reading We have not been exhaustive in the description of the Caml Light features. We only introduced general concepts in functional programming, and we have insisted
More informationLecture 2 - Graph Theory Fundamentals - Reachability and Exploration 1
CME 305: Discrete Mathematics and Algorithms Instructor: Professor Aaron Sidford (sidford@stanford.edu) January 11, 2018 Lecture 2 - Graph Theory Fundamentals - Reachability and Exploration 1 In this lecture
More informationSuppose a merchant wants to provide faster service to \big spenders" whose records indicate recent spending exceeding some threshold. Determining whet
Multi-Stage Specialization with Relative Binding Times Mark Leone Indiana University Peter Lee Carnegie Mellon University Technical Report #497 Computer Science Department, Indiana University November
More informationOnce Upon a Polymorphic Type
Once Upon a Polymorphic Type Keith Wansbrough Computer Laboratory University of Cambridge kw217@cl.cam.ac.uk http://www.cl.cam.ac.uk/users/kw217/ Simon Peyton Jones Microsoft Research Cambridge 20 January,
More informationProgramming Systems in Artificial Intelligence Functional Programming
Click to add Text Programming Systems in Artificial Intelligence Functional Programming Siegfried Nijssen 8/03/16 Discover thediscover world at the Leiden world University at Leiden University Overview
More informationConstrained Types and their Expressiveness
Constrained Types and their Expressiveness JENS PALSBERG Massachusetts Institute of Technology and SCOTT SMITH Johns Hopkins University A constrained type consists of both a standard type and a constraint
More informationproc {Produce State Out} local State2 Out2 in State2 = State + 1 Out = State Out2 {Produce State2 Out2}
Laziness and Declarative Concurrency Raphael Collet Universite Catholique de Louvain, B-1348 Louvain-la-Neuve, Belgium raph@info.ucl.ac.be May 7, 2004 Abstract Concurrency and distribution in a programming
More informationA Small Interpreted Language
A Small Interpreted Language What would you need to build a small computing language based on mathematical principles? The language should be simple, Turing equivalent (i.e.: it can compute anything that
More informationTyped Scheme: Scheme with Static Types
Typed Scheme: Scheme with Static Types Version 4.1.1 Sam Tobin-Hochstadt October 5, 2008 Typed Scheme is a Scheme-like language, with a type system that supports common Scheme programming idioms. Explicit
More informationNormalization Code in Standard ML. fun union n1 n2 = (* Make nodes `equal' *) let val (btl1,btl2) = (geteqr bt1,geteqr bt2)
A Normalization Code in Standard ML The following Standard ML code can be used for solving constraint systems. The code assumes that phase 1 described earlier has been performed during constraint generation.
More informationHigher-Order Conditional Term Rewriting. In this paper, we extend the notions of rst-order conditional rewrite systems
Higher-Order Conditional Term Rewriting in the L Logic Programming Language Preliminary Results Amy Felty AT&T Bell Laboratories 600 Mountain Avenue Murray Hill, NJ 07974 Abstract In this paper, we extend
More informationLists. Michael P. Fourman. February 2, 2010
Lists Michael P. Fourman February 2, 2010 1 Introduction The list is a fundamental datatype in most functional languages. ML is no exception; list is a built-in ML type constructor. However, to introduce
More informationC311 Lab #3 Representation Independence: Representation Independent Interpreters
C311 Lab #3 Representation Independence: Representation Independent Interpreters Will Byrd webyrd@indiana.edu February 5, 2005 (based on Professor Friedman s lecture on January 29, 2004) 1 Introduction
More informationCS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011
CS152: Programming Languages Lecture 11 STLC Extensions and Related Topics Dan Grossman Spring 2011 Review e ::= λx. e x e e c v ::= λx. e c τ ::= int τ τ Γ ::= Γ, x : τ (λx. e) v e[v/x] e 1 e 1 e 1 e
More informationThe Typed Racket Guide
The Typed Racket Guide Version 5.3.6 Sam Tobin-Hochstadt and Vincent St-Amour August 9, 2013 Typed Racket is a family of languages, each of which enforce
More informationThe design of a programming language for provably correct programs: success and failure
The design of a programming language for provably correct programs: success and failure Don Sannella Laboratory for Foundations of Computer Science School of Informatics, University of Edinburgh http://homepages.inf.ed.ac.uk/dts
More informationClosures. Mooly Sagiv. Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming
Closures Mooly Sagiv Michael Clarkson, Cornell CS 3110 Data Structures and Functional Programming Summary 1. Predictive Parsing 2. Large Step Operational Semantics (Natural) 3. Small Step Operational Semantics
More informationThe role of semantic analysis in a compiler
Semantic Analysis Outline The role of semantic analysis in a compiler A laundry list of tasks Scope Static vs. Dynamic scoping Implementation: symbol tables Types Static analyses that detect type errors
More informationProgramming Languages Third Edition
Programming Languages Third Edition Chapter 12 Formal Semantics Objectives Become familiar with a sample small language for the purpose of semantic specification Understand operational semantics Understand
More informationA Parallel Intermediate Representation based on. Lambda Expressions. Timothy A. Budd. Oregon State University. Corvallis, Oregon.
A Parallel Intermediate Representation based on Lambda Expressions Timothy A. Budd Department of Computer Science Oregon State University Corvallis, Oregon 97331 budd@cs.orst.edu September 20, 1994 Abstract
More informationSemantic Analysis. Lecture 9. February 7, 2018
Semantic Analysis Lecture 9 February 7, 2018 Midterm 1 Compiler Stages 12 / 14 COOL Programming 10 / 12 Regular Languages 26 / 30 Context-free Languages 17 / 21 Parsing 20 / 23 Extra Credit 4 / 6 Average
More informationTYPE INFERENCE. François Pottier. The Programming Languages Mentoring ICFP August 30, 2015
TYPE INFERENCE François Pottier The Programming Languages Mentoring Workshop @ ICFP August 30, 2015 What is type inference? What is the type of this OCaml function? let f verbose msg = if verbose then
More informationChapter 13: Reference. Why reference Typing Evaluation Store Typings Safety Notes
Chapter 13: Reference Why reference Typing Evaluation Store Typings Safety Notes References Computational Effects Also known as side effects. A function or expression is said to have a side effect if,
More informationSemantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler so far
Outline Semantic Analysis The role of semantic analysis in a compiler A laundry list of tasks Scope Static vs. Dynamic scoping Implementation: symbol tables Types Statically vs. Dynamically typed languages
More informationSemantic Analysis. Outline. The role of semantic analysis in a compiler. Scope. Types. Where we are. The Compiler Front-End
Outline Semantic Analysis The role of semantic analysis in a compiler A laundry list of tasks Scope Static vs. Dynamic scoping Implementation: symbol tables Types Static analyses that detect type errors
More informationCMSC 330: Organization of Programming Languages. Formal Semantics of a Prog. Lang. Specifying Syntax, Semantics
Recall Architecture of Compilers, Interpreters CMSC 330: Organization of Programming Languages Source Scanner Parser Static Analyzer Operational Semantics Intermediate Representation Front End Back End
More informationOperational Semantics
15-819K: Logic Programming Lecture 4 Operational Semantics Frank Pfenning September 7, 2006 In this lecture we begin in the quest to formally capture the operational semantics in order to prove properties
More informationSML Style Guide. Last Revised: 31st August 2011
SML Style Guide Last Revised: 31st August 2011 It is an old observation that the best writers sometimes disregard the rules of rhetoric. When they do so, however, the reader will usually find in the sentence
More informationLet us dene the basic notation and list some results. We will consider that stack eects (type signatures) form a polycyclic monoid (introduced in [NiP
Validation of Stack Eects in Java Bytecode Jaanus Poial Institute of Computer Science University of Tartu, Estonia e-mail: jaanus@cs.ut.ee February 21, 1997 Abstract The Java language is widely used in
More information6.001 Notes: Section 6.1
6.001 Notes: Section 6.1 Slide 6.1.1 When we first starting talking about Scheme expressions, you may recall we said that (almost) every Scheme expression had three components, a syntax (legal ways of
More information1 INTRODUCTION 2 Represent a multiset as an association list, where the rst argument of a pair is an item and the second argument is the multiplicity
Programming with Multisets J.W. Lloyd Department of Computer Science University of Bristol Bristol BS8 1UB, UK Abstract This paper proposes a novel way of introducing multisets into declarative programming
More informationControl Flow Analysis with SAT Solvers
Control Flow Analysis with SAT Solvers Steven Lyde, Matthew Might University of Utah, Salt Lake City, Utah, USA Abstract. Control flow analyses statically determine the control flow of programs. This is
More informationA Boolean Expression. Reachability Analysis or Bisimulation. Equation Solver. Boolean. equations.
A Framework for Embedded Real-time System Design? Jin-Young Choi 1, Hee-Hwan Kwak 2, and Insup Lee 2 1 Department of Computer Science and Engineering, Korea Univerity choi@formal.korea.ac.kr 2 Department
More informationIntroduction to Functional Programming: Lecture 7 2 Functions as innite data structures Ordinary ML data structures are always nite. We can, however,
Introduction to Functional Programming: Lecture 7 1 Introduction to Functional Programming John Harrison University of Cambridge Lecture 7 Innite data structures Topics covered: Functions as innite data
More information(Refer Slide Time: 01:01)
Principles of Programming Languages Dr. S. Arun Kumar Department of Computer Science & Engineering Indian Institute of Technology, Delhi Lecture - 32 Monomorphism Welcome to lecture 32. So today I will
More informationLambda Calculus and Type Inference
Lambda Calculus and Type Inference Björn Lisper Dept. of Computer Science and Engineering Mälardalen University bjorn.lisper@mdh.se http://www.idt.mdh.se/ blr/ October 13, 2004 Lambda Calculus and Type
More informationIncremental Flow Analysis. Andreas Krall and Thomas Berger. Institut fur Computersprachen. Technische Universitat Wien. Argentinierstrae 8
Incremental Flow Analysis Andreas Krall and Thomas Berger Institut fur Computersprachen Technische Universitat Wien Argentinierstrae 8 A-1040 Wien fandi,tbg@mips.complang.tuwien.ac.at Abstract Abstract
More informationData Abstraction. An Abstraction for Inductive Data Types. Philip W. L. Fong.
Data Abstraction An Abstraction for Inductive Data Types Philip W. L. Fong pwlfong@cs.uregina.ca Department of Computer Science University of Regina Regina, Saskatchewan, Canada Introduction This lecture
More informationInduction and Semantics in Dafny
15-414 Lecture 11 1 Instructor: Matt Fredrikson Induction and Semantics in Dafny TA: Ryan Wagner Encoding the syntax of Imp Recall the abstract syntax of Imp: a AExp ::= n Z x Var a 1 + a 2 b BExp ::=
More informationCSE3322 Programming Languages and Implementation
Monash University School of Computer Science & Software Engineering Sample Exam 2004 CSE3322 Programming Languages and Implementation Total Time Allowed: 3 Hours 1. Reading time is of 10 minutes duration.
More informationKeyNote: Trust Management for Public-Key. 180 Park Avenue. Florham Park, NJ USA.
KeyNote: Trust Management for Public-Key Infrastructures Matt Blaze 1 Joan Feigenbaum 1 Angelos D. Keromytis 2 1 AT&T Labs { Research 180 Park Avenue Florham Park, NJ 07932 USA fmab,jfg@research.att.com
More information2 M. Sperber and P. Thiemann are traditionally implemented by recursive descent. The traditional model underlying LR parsing complicates understanding
Generation of LR Parsers by Partial Evaluation MICHAEL SPERBER Universitat Tubingen and PETER THIEMANN University of Nottingham Partial evaluation can turn a general parser into a parser generator. We
More informationMore about Formatting. Olivier Danvy. Aarhus University. December Abstract
More about Formatting Olivier Danvy Computer Science Department Aarhus University (danvy@daimi.aau.dk) December 1993 Abstract This is an extension of the \format" example, in our POPL tutorial [2]. The
More informationTail Calls. CMSC 330: Organization of Programming Languages. Tail Recursion. Tail Recursion (cont d) Names and Binding. Tail Recursion (cont d)
CMSC 330: Organization of Programming Languages Tail Calls A tail call is a function call that is the last thing a function does before it returns let add x y = x + y let f z = add z z (* tail call *)
More informationJOURNAL OF OBJECT TECHNOLOGY
JOURNAL OF OBJECT TECHNOLOGY Online at www.jot.fm. Published by ETH Zurich, Chair of Software Engineering JOT, 2002 Vol. 1, No. 2, July-August 2002 The Theory of Classification Part 2: The Scratch-Built
More informationType Specialisation for Imperative Languages. 0. e 0 is the code part or dynamic part of the result of applying
Type Specialisation for Imperative Languages Dirk Dussart John Hughes y Peter Thiemann z Abstract We extend type specialisation to a computational lambda calculus with rst-class references. The resulting
More informationSORT INFERENCE \coregular" signatures, they derive an algorithm for computing a most general typing for expressions e which is only slightly more comp
Haskell Overloading is DEXPTIME{complete Helmut Seidl Fachbereich Informatik Universitat des Saarlandes Postfach 151150 D{66041 Saarbrucken Germany seidl@cs.uni-sb.de Febr., 1994 Keywords: Haskell type
More informationCS 11 Haskell track: lecture 1
CS 11 Haskell track: lecture 1 This week: Introduction/motivation/pep talk Basics of Haskell Prerequisite Knowledge of basic functional programming e.g. Scheme, Ocaml, Erlang CS 1, CS 4 "permission of
More informationSAMOS: an Active Object{Oriented Database System. Stella Gatziu, Klaus R. Dittrich. Database Technology Research Group
SAMOS: an Active Object{Oriented Database System Stella Gatziu, Klaus R. Dittrich Database Technology Research Group Institut fur Informatik, Universitat Zurich fgatziu, dittrichg@ifi.unizh.ch to appear
More informationProc. XVIII Conf. Latinoamericana de Informatica, PANEL'92, pages , August Timed automata have been proposed in [1, 8] to model nite-s
Proc. XVIII Conf. Latinoamericana de Informatica, PANEL'92, pages 1243 1250, August 1992 1 Compiling Timed Algebras into Timed Automata Sergio Yovine VERIMAG Centre Equation, 2 Ave de Vignate, 38610 Gieres,
More informationA Functional Graph Library
A Functional Graph Library Christian Doczkal Universität des Saarlandes Abstract. Algorithms on graphs are of great importance, both in teaching and in the implementation of specific problems. Martin Erwig
More informationNatural Semantics [14] within the Centaur system [6], and the Typol formalism [8] which provides us with executable specications. The outcome of such
A Formal Executable Semantics for Java Isabelle Attali, Denis Caromel, Marjorie Russo INRIA Sophia Antipolis, CNRS - I3S - Univ. Nice Sophia Antipolis, BP 93, 06902 Sophia Antipolis Cedex - France tel:
More informationA Functional Evaluation Model
A Functional Evaluation Model COS 326 Andrew W. Appel Princeton University slides copyright 2013-2015 David Walker and Andrew W. Appel A Functional Evaluation Model In order to be able to write a program,
More informationCS 360: Programming Languages Lecture 10: Introduction to Haskell
CS 360: Programming Languages Lecture 10: Introduction to Haskell Geoffrey Mainland Drexel University Thursday, February 5, 2015 Adapted from Brent Yorgey s course Introduction to Haskell. Section 1 Administrivia
More informationType and Eect Systems via Abstract Interpretation. Jer^ome Vouillon. Pierre Jouvelot. CRI, Ecole des Mines de Paris. Abstract
Type and Eect Systems via Abstract Interpretation Jer^ome Vouillon Pierre Jouvelot CRI, Ecole des Mines de Paris fvouillon, jouvelotg@cri.ensmp.fr July 12, 1995 Abstract Abstract interpretation and type
More informationProducts and Records
Products and Records Michael P. Fourman February 2, 2010 1 Simple structured types Tuples Given a value v 1 of type t 1 and a value v 2 of type t 2, we can form a pair, (v 1, v 2 ), containing these values.
More informationCompiler Theory. (Semantic Analysis and Run-Time Environments)
Compiler Theory (Semantic Analysis and Run-Time Environments) 005 Semantic Actions A compiler must do more than recognise whether a sentence belongs to the language of a grammar it must do something useful
More informationCMSC330. Objects, Functional Programming, and lambda calculus
CMSC330 Objects, Functional Programming, and lambda calculus 1 OOP vs. FP Object-oriented programming (OOP) Computation as interactions between objects Objects encapsulate mutable data (state) Accessed
More informationHarvard School of Engineering and Applied Sciences CS 152: Programming Languages
Harvard School of Engineering and Applied Sciences CS 152: Programming Languages Lecture 18 Thursday, March 29, 2018 In abstract algebra, algebraic structures are defined by a set of elements and operations
More information3. Functional Programming. Oscar Nierstrasz
3. Functional Programming Oscar Nierstrasz Roadmap > Functional vs. Imperative Programming > Pattern Matching > Referential Transparency > Lazy Evaluation > Recursion > Higher Order and Curried Functions
More informationPROFESSOR: Last time, we took a look at an explicit control evaluator for Lisp, and that bridged the gap between
MITOCW Lecture 10A [MUSIC PLAYING] PROFESSOR: Last time, we took a look at an explicit control evaluator for Lisp, and that bridged the gap between all these high-level languages like Lisp and the query
More informationData Types The ML Type System
7 Data Types 7.2.4 The ML Type System The following is an ML version of the tail-recursive Fibonacci function introduced Fibonacci function in ML in Section 6.6.1: EXAMPLE 7.96 1. fun fib (n) = 2. let
More informationCS 415 Midterm Exam Spring 2002
CS 415 Midterm Exam Spring 2002 Name KEY Email Address Student ID # Pledge: This exam is closed note, closed book. Good Luck! Score Fortran Algol 60 Compilation Names, Bindings, Scope Functional Programming
More informationArbitrary-rank polymorphism in (GHC) Haskell
Arbitrary-rank polymorphism in (GHC) Haskell CAS 743 Stephen Forrest 20 March 2006 Damas-Milner Type System A Damas-Milner type system (also called Hindley-Milner) is a traditional type system for functional
More informationLecture 3: Recursion; Structural Induction
15-150 Lecture 3: Recursion; Structural Induction Lecture by Dan Licata January 24, 2012 Today, we are going to talk about one of the most important ideas in functional programming, structural recursion
More informationComp 411 Principles of Programming Languages Lecture 3 Parsing. Corky Cartwright January 11, 2019
Comp 411 Principles of Programming Languages Lecture 3 Parsing Corky Cartwright January 11, 2019 Top Down Parsing What is a context-free grammar (CFG)? A recursive definition of a set of strings; it is
More informationLecture Notes on Data Representation
Lecture Notes on Data Representation 15-814: Types and Programming Languages Frank Pfenning Lecture 9 Tuesday, October 2, 2018 1 Introduction In this lecture we ll see our type system in action. In particular
More information