Type Systems As Macros Comp Le * a T * Te N * Te a Is W S E * E N L L C O

Type Systems As Macros Comp Le * a T * Te N * Te a Is W S E * E N L L C O

rtifact Type Systems as Macros Comp le * A t * te n * te A is W s E * e n l l C o L D C o P * * c u e m s O E u e e P n R t v e o d t * y * s E a a l d u e a Stephen Chang Alex Knauth Ben Greenman t PLT @ Northeastern University, Boston, MA, USA fstchang,alexknauth,[email protected] Abstract bles a special instance of a macro system and our approach exploits synergies resulting from this insight. We present TURNSTILE, a metalanguage for creating typed embed- ded languages. To implement the type system, programmers write With our macro-based approach, programmers may implement type checking rules resembling traditional judgment syntax. To a wide range of type rules, yet they need not create a type system implement the semantics, they incorporate elaborations into these from scratch since they may reuse components of the macro sys- tem itself for type checking. Indeed, programmers need only supply rules. TURNSTILE critically depends on the idea of linguistic reuse. It exploits a macro system in a novel way to simultaneously type their desired type rules in an intuitive mathematical form. Creating check and rewrite a surface program into a target language. Reusing type systems with macros also fosters robust linguistic abstractions, a macro system also yields modular implementations whose rules e.g., they report type errors with surface language terms. Finally, may be mixed and matched to create other languages. Combined our approach produces naturally modular type systems that dually serve as libraries of mixable and matchable type rules, enabling with typical compiler and runtime reuse, TURNSTILE produces per- formant typed embedded languages with little effort. further linguistic reuse [27]. When combined with the typical reuse of the runtime that embedded languages enjoy, our approach inher- Categories and Subject Descriptors D.3.2 [Programming Lan- its the performance of its host and thus produces practical typed guages]: Specialized application languages languages with significantly reduced effort. We use Racket [12, 15], a production-quality Lisp and Scheme Keywords macros, type systems, typed embedded DSLs descendant, as our host language since Lisps are already a popular platform for creating embedded languages [17, 20]. Racket’s macro 1. Typed Embedded Languages system in particular continues to improve on its predecessors [14] and has even influenced macro system design in modern non-Lisp As Paul Hudak asserted, “we really don’t want to build a pro- languages [6, 8, 10, 48]. Thus programmers have created Racket- gramming language from scratch ... better, let’s inherit the in- embedded languages for accomplishing a variety of tasks such as frastructure of some other language” [23]. Unsurprisingly, many book publishing [7], program synthesis [44], and writing secure modern languages support the creation of such embedded lan- shell scripts [32]. guages [3, 18, 20, 22, 24–26, 41, 43, 46]. The first part of the paper (§2-3) demonstrates a connection be- Programmers who wish to create typed embedded languages, tween type rules and macros by reusing Racket’s macro infrastruc- however, have more limited options. Such languages typically reuse ture for type checking in the creation of a typed embedded lan- their host’s type system but, as a prominent project [45] recently guage. The second part (§4) introduces TURNSTILE, a metalan- remarked, this “confines them to hthati type system.” Also, reusing guage that abstracts the insights and techniques from the first part a type system may not create proper abstractions, e.g., type errors into convenient linguistic constructs. The third part (§5-7) shows may be reported in host language terms. At the other extreme, that our approach both accommodates a variety of type systems and a programmer can implement a type system from scratch [42], scales to realistic combinations of type system features. We demon- expending considerable effort and passing up many of the reuse strate the former by implementing fifteen core languages ranging benefits that embedding a language promises in the first place. from simply-typed to F!, and the latter with the creation of a full- We present an alternative approach to implementing typed em- sized ML-like functional language that also supports basic Haskell- bedded languages. Rather than reuse a type system, we embed a style type classes. type system in a host’s macro system. In other words, type check- ing is computed as part of macro expansion. Such an embedding fits naturally since a typical type checking algorithm traverses a surface program, synthesizes information from it, and then uses this infor- 2. Creating Embedded Languages in Racket mation to rewrite the program, if it satisfies certain conditions, into This section summarizes the creation of embedded languages with a target language. This kind of algorithm exactly matches the ideal Racket. Racket is not a single language but rather an ecosystem use case for macros. From this perspective, a type checker resem- with which to create languages [12]. Racket code is organized into modules, e.g. LAM:1 #lang racket lam Permission to make digital or hard copies of part or all of this work for personal or classroom use is granted without fee (define-m (lm x e) (λ (x) e)) provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. (provide lm) Abstracting with credit is permitted. To copy otherwise, to republish, to post on servers, or to redistribute to lists, contact the Owner/Author(s). Request permissions from [email protected] or Publications Dept., ACM, Inc., fax +1 (212) 869-0481. POPL ’17, January 18 - 20, 2017, Paris, France 1 Code note: For clarity and conciseness, this paper stylizes code and thus Copyright © 2017 held by owner/author(s). Publication rights licensed to ACM. ACM 978-1-4503-4660-3/17/01. $15.00 its examples may not run exactly as presented. Full, runnable examples are DOI: http://dx.doi.org/10.1145/http://dx.doi.org/10.1145/3009837.3009886 available at: www.ccs.neu.edu/home/stchang/popl2017/ A #lang racket declaration allows LAM to use forms and func- τ ::= τ !τ e ::= x j λx:τ : e j e e Γ ::= x:τ; : : : (types, terms) tions from the main Racket language. LAM defines and exports one 2 macro, lm, denoting single-argument functions. A Racket macro x:τ 2 Γ Γ; x:τ1 ` e : τ2 consumes and produces syntax object data structures. The lm macro (T-VAR) (T-ABS) Γ ` x : τ Γ ` λx:τ1 : e : τ1 !τ2 specifies its usage shape with input pattern (lm x e) (in yellow Γ ` e1 : τ1 !τ2 Γ ` e2 : τ1 to help readability), which binds pattern variables x and e to sub- (T-APP) pieces of the input, the parameter and body, respectively. The out- Γ ` e1 e2 : τ2 put syntax (λ (x) e) (gray denotes syntax object construction) er(x) = x; er(λx:τ : e) = λx : er(e); er(e e0) = er(e) er(e0) (erase) references these pattern variables (λ is Racket’s λ). Implementation sketch: A module serves multiple roles in the Racket ecosystem. Run- ning LAM as a program produces no result since it consists of only #lang racket stlc a macro definition. But LAM is also a language: (define-m (checked-λ : : :) hwhen T-ABSi er( )) #lang lam lam-prog (define-m (checked-app :::) hwhen T-APPi er( )) (lm x (lm y x)); => hfunctioni ((lm x x) (lm x x)); stx error! fn application undefined Figure 2. Simply-typed λ-calculus A module declaring #lang lam may only write lm functions; using any other form results in an error. Finally, a Racket module may be used as a library, as in the following LC module: 1 (define-m (checked-app efn earg); v0 #lang racket lc 2 #:with (! τin τout) (compute-τ efn ) (require lam) 3 #:with τarg (compute-τ earg ) (provide (rename-out [lm λ] [app #%app])) 4 #:when (τ= τarg τin ) (define-m (app efn earg) (#%app efn earg)) 5 #:with efn (erase-τ efn ) LC imports lm from LAM and also defines app, which corresponds 6 #:with earg (erase-τ earg ) to single-argument function application. LC exports lm and app with new names, λ and #%app, respectively. The #%app in the out- 7 (add-τ (#%app efn earg) τout )) put of app is core-Racket’s function application form, though pro- grammers need not write it explicitly. Instead, macro expansion im- Figure 3. A type checking function application macro plicitly inserts it before applied functions. This enables modifying the behavior of function application, as we do here by exporting app as #%app. Thus a program in the LC language looks like: sion contains only references to Racket’s core syntax. This paper shows how to embed type checking within macro expansion. #lang lc lc-prog ((λ x (x x)) (λ x (x x))); => loop! 3. A Typed λ-Calculus Embedded Language where λ corresponds to lm in LAM and applying a λ behaves LC from section 2 implements the untyped λ-calculus. This section according to app in LC. Running LC-PROG loops forever. augments LC with types and type checking by transcribing formal Figure 1 depicts compilation of a Racket program, which in- type rules directly into its macro definitions, producing the simply- cludes macro expansion. The Racket compiler first “reads” a pro- typed λ-calculus and demonstrating that Racket’s macro infrastruc- gram’s surface text into a syntax object, which is a tree of symbols ture can be reused for type checking.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    12 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us