Although run-time language composition is common, it normally takes the form of a crude Foreign Function Interface (FFI). While useful, such compositions tend to be coarse-grained and slow. In this paper we introduce a novel fine-grained syntactic composition of PHP and Python which allows users to embed each language inside the other, including referencing variables across languages. This composition raises novel design and implementation challenges. We show that good solutions can be found to the design challenges; and that the resulting implementation imposes an acceptable performance overhead of, at most, 2.6x.
There has been a long-standing desire for language composition (see e.g. @cite_17 ), and many flavours have developed since then. Extensible languages (e.g. @cite_27 @cite_29 @cite_4 ) aim to grow a language as required by a user. However, the base language places restrictions on what extensions are possible (e.g. due to parsing restrictions) and performant @cite_19 . Translating one language into another (with e.g. Stratego @cite_0 ) removes many of the limitations on what is expressible, but full-scale translations are complex (e.g. @cite_1 ) and typically suffer the same performance issues as extensible languages. However, for small use cases, or where performance is not important, either approach can work well.
@cite_4 @cite_29 @cite_1 @cite_0 @cite_19 @cite_27 @cite_17
1944501883 2054887300 2123357908 1481474677 2013901208 2011016867 2085595137
A frequent dilemma in the design of a database programming language is the choice between a language with a rich set of tailored notations for schema definitions, query expressions, etc., and a small, simple core language. We address this dilemma by proposing extensible grammars, a syntax-definition formalism for incremental language extensions and restrictions based on an initial core language. As a value flows across the boundary between interoperating languages, it must be checked and converted to fit the types and representations of the target language. For simple forms of data, the checks and coercions can be immediate; for higher order data, such as functions and objects, some must be delayed until the value is used in a particular way. Typically, these coercions and checks are implemented by an ad-hoc mixture of wrappers, reflection, and dynamic predicates. We observe that 1) the wrapper and reflection operations fit the profile of mirrors, 2) the checks correspond to contracts, and 3) the timing and shape of mirror operations coincide with the timing and shape of contract operations. Based on these insights, we present a new model of interoperability that builds on the ideas of mirrors and contracts, and we describe an interoperable implementation of Java and Scheme that is guided by the model. Preprint of paper published in: Science of Computer Programming (Elsevier), 72 (1-2), 2008; doi:10.1016 j.scico.2007.11.003 Stratego XT is a language and toolset for program transformation. The Stratego language provides rewrite rules for expressing basic transformations, programmable rewriting strategies for controlling the application of rules, concrete syntax for expressing the patterns of rules in the syntax of the object language, and dynamic rewrite rules for expressing context-sensitive transformations, thus supporting the development of transformation components at a high level of abstraction. The XT toolset offers a collection of flexible, reusable transformation components, and tools for generating such components from declarative specifications. Complete program transformation systems are composed from these components. This paper gives an overview of Stratego XT 0.17, including a description of the Stratego language and XT transformation tools; a discussion of the implementation techniques and software engineering process; and a description of applications built with Stratego XT. Experimental evaluation is key to systems research. Because modern systems are complex and non-deterministic, good experimental methodology demands that researchers account for uncertainty. To obtain valid results, they are expected to run many iterations of benchmarks, invoke virtual machines (VMs) several times, or even rebuild VM or benchmark binaries more than once. All this repetition costs time to complete experiments. Currently, many evaluations give up on sufficient repetition or rigorous statistical methods, or even run benchmarks only in training sizes. The results reported often lack proper variation estimates and, when a small difference between two systems is reported, some are simply unreliable. In contrast, we provide a statistically rigorous methodology for repetition and summarising results that makes efficient use of experimentation time. Time efficiency comes from two key observations. First, a given benchmark on a given platform is typically prone to much less non-determinism than the common worst-case of published corner-case studies. Second, repetition is most needed where most uncertainty arises (whether between builds, between executions or between iterations). We capture experimentation cost with a novel mathematical model, which we use to identify the number of repetitions at each level of an experiment necessary and sufficient to obtain a given level of precision. We present our methodology as a cookbook that guides researchers on the number of repetitions they should run to obtain reliable results. We also show how to present results with an effect size confidence interval. As an example, we show how to use our methodology to conduct throughput experiments with the DaCapo and SPEC CPU benchmarks on three recent platforms. An operational extensible language system is described. The system and its base language are appraised with respect to efficiency, flexibility, and utility for different categories of users. Our discussion of the motivation for extensible languages rests on a basic premise, namely that there exist diverse programming language requirements which are becoming continually more diverse, and that it is of critical importance that each user in the spectrum of users be supplied with a language facility appropriate to his problem area. That is, there are, in fact, "scientific" problems, "data processing" problems," information retrieval" problems, "symbol manipulation" problems, "system programming" problems, and so on and each problem area has its particular and peculiar units of data, unit transactions, and preferred ways of writing. For example, the kinds of unit data and unit transactions include integers which are to be added, floating point numbers to be multiplied, "infinite" precision rational numbers to be divided, strings to be concatenated, records into which a field is to be inserted, files to be sorted, matrices to be inverted, equations to be simplified, sets to be unioned, and so on. A part of our premise is that it is not enough to have a language which is formally sufficient to host the particular data and unit transactions some user has in mind. Rather, it is of critical importance that the kinds of data and unit transactions which he wants to think of as primitive be available, effectively as primitives, in his language facility.