239 research outputs found
Injecting Language Workbench Technology into Mainstream Languages
Eelco Visser envisioned a future where DSLs become a commonplace abstraction in software development. He took strides towards implementing this vision with the Spoofax language workbench. However, his vision is far from the mainstream of programming today. How will the many mainstream programmers encounter and adopt language workbench technology? We propose that the macro systems found in emerging industrial languages open a path towards delivering language workbenches as easy-to-adopt libraries. To develop the idea, we sketch an implementation of a language workbench as a macro-library atop Racket and identify the key features of the macro system needed to enable this evolution path
Linguistic support for unit testing
technical reportExisting systems for writing unit tests exploit built-in language constructs, such as reflection, to simulate the addition of testing constructs. While these simulations provide the minimally necessary functionality, they fail to support testing properly in many instances. In response, we have designed, implemented, and evaluated extensions for Java that enable programmers to express test cases with language constructs. Not surprisingly, these true language extensions improve testing in many different ways, starting with basic statical checks but also allowing the collection of additional information about the unit tests
Recommended from our members
Abstract Models of Memory Management
Most specifications of garbage collectors concentrate on the low-level algorithmic details of how to find and preserve accessible objects. Often, they focus on bit-level manipulations such as "scanning stack frames," "marking objects," "tagging data," etc. While these details are important in some contexts, they often obscure the more fundamental aspects of memory management: what objects are garbage and why? We develop a series of calculi that are just low-level enough that we can express allocation and garbage collection, yet are sufficiently abstract that we many formally prove the correctness of various memory management strategies. By making the heap of a program syntactically apparent, we can specify memory actions as rewriting rules that allocate values on the heap and automatically dereference pointers to such objects when needed. this formulation permits the specification of garbage collection as a relation that removes portions of the heap without affecting the outcome of the evaluation. Our high-level approach allows us to specify in a compact manner a wide variety of memory management techniques, including standard trace-based garbage collection (i.e., the family of copying and mark/sweep collection algorithms), generational collection, and type-based, tag-free collection. Furthermore, since the definition of garbage is based on the semantics of the underlying language instead of the conservative approximation of inaccessibility, we are able to specify and prove the idea that type inference can be used to collect some objects that are accessible but never used.Engineering and Applied Science
An Approach to Call-by-Name Delimited Continuations
International audienceWe show that a variant of Parigot's λμ-calculus, originally due to de Groote and proved to satisfy Böhm's theorem by Saurin, is canonically interpretable as a call-by-name calculus of delim- ited control. This observation is expressed using Ariola et al's call-by-value calculus of delimited control, an extension of λμ-calculus with delimited control known to be equationally equivalent to Danvy and Filinski's calculus with shift and reset. Our main result then is that de Groote and Saurin's variant of λμ-calculus is equivalent to a canonical call-by-name variant of Ariola et al's calculus. The rest of the paper is devoted to a comparative study of the call-by-name and call-by-value variants of Ariola et al's calculus, covering in particular the questions of simple typing, operational semantics, and continuation-passing-style semantics. Finally, we discuss the relevance of Ariola et al's calculus as a uniform framework for representing different calculi of delimited continuations, including "lazy" variants such as Sabry's shift and lazy reset calculus
From Macros to DSLs: The Evolution of Racket
The Racket language promotes a language-oriented style of programming. Developers create many domain-specific languages, write programs in them, and compose these programs via Racket code. This style of programming can work only if creating and composing little languages is simple and effective. While Racket\u27s Lisp heritage might suggest that macros suffice, its design team discovered significant shortcomings and had to improve them in many ways. This paper presents the evolution of Racket\u27s macro system, including a false start, and assesses its current state
Lazy Evaluation and Delimited Control
The call-by-need lambda calculus provides an equational framework for
reasoning syntactically about lazy evaluation. This paper examines its
operational characteristics. By a series of reasoning steps, we systematically
unpack the standard-order reduction relation of the calculus and discover a
novel abstract machine definition which, like the calculus, goes "under
lambdas." We prove that machine evaluation is equivalent to standard-order
evaluation. Unlike traditional abstract machines, delimited control plays a
significant role in the machine's behavior. In particular, the machine replaces
the manipulation of a heap using store-based effects with disciplined
management of the evaluation stack using control-based effects. In short, state
is replaced with control. To further articulate this observation, we present a
simulation of call-by-need in a call-by-value language using delimited control
operations
The Racket Manifesto
The creation of a programming language calls for guiding principles that point the developers to goals. This article spells out the three basic principles behind the 20-year development of Racket. First, programming is about stating and solving problems, and this activity normally takes place in a context with its own language of discourse; good programmers ought to formulate this language as a programming language. Hence, Racket is a programming language for creating new programming languages. Second, by following this language-oriented approach to programming, systems become multi-lingual collections of interconnected components. Each language and component must be able to protect its specific invariants. In support, Racket offers protection mechanisms to implement a full language spectrum, from C-level bit manipulation to soundly typed extensions. Third, because Racket considers programming as problem solving in the correct language, Racket also turns extra-linguistic mechanisms into linguistic constructs, especially mechanisms for managing resources and projects. The paper explains these principles and how Racket lives up to them, presents the evaluation framework behind the design process, and concludes with a sketch of Racket\u27s imperfections and opportunities for future improvements
- …