Robert Bruce Findler’s research while affiliated with Northwestern University and other places

What is this page?


This page lists works of an author who doesn't have a ResearchGate profile or hasn't added the works to their profile yet. It is automatically generated from public (personal) data to further our legitimate goal of comprehensive and accurate scientific recordkeeping. If you are this author and want this page removed, please let us know.

Publications (107)


The Functional, the Imperative, and the Sudoku: Getting Good, Bad, and Ugly to Get Along (Functional Pearl)
  • Article

August 2024

·

6 Reads

Proceedings of the ACM on Programming Languages

Manuel Serrano

·

Robert Bruce Findler

Conventional wisdom suggests that the benefits of functional programming no longer apply in the presence of even a small amount of imperative code, as if the addition of imperative code effectively subtracts. And yet, as we show in this paper, combining functional programming with the special imperative language Esterel provides a multiplicative improvement to the benefits of functional programming. The key to the benefit of both Esterel and functional programming stems from a restriction that both share. As in functional programming, where only the inputs to a function determine its outputs, the state of an Esterel computation is fully determined by the program’s input and the state that the computation had in the previous time step, where the notion of a time step is explicit in the language. Esterel’s guarantee holds even though Esterel programs feature concurrent threads, mutable state, and the ability to create, suspend, and even terminate threads as the computation proceeds. This similarity is the root of the benefits that programmers accrue as they informally reason about their program’s behavior. To illustrate these benefits, the bulk of this paper consists of an in-depth exploration of HipHop code (a mashup of JavaScript and Esterel) that implements a Sudoku solver, showing how it is possible to write code that is as easy to understand as if it were written in a pure functional programming style, even though it uses multiple threads, mutable state, thread preemption, and even thread abortion. Even better, concurrent composition and task canceling provide significant program structuring benefits that allow a clean decomposition and task separation in the solver.


Fig. 11. LLVM Code Illustrating the Control Flow Graph Representation
A Calculus for Unreachable Code
  • Preprint
  • File available

July 2024

·

26 Reads

Peter Zhong

·

Shu-Hung You

·

·

[...]

·

In Racket, the LLVM IR, Rust, and other modern languages, programmers and static analyses can hint, with special annotations, that certain parts of a program are unreachable. Same as other assumptions about undefined behavior; the compiler assumes these hints are correct and transforms the program aggressively. While compile-time transformations due to undefined behavior often perplex compiler writers and developers, we show that the essence of transformations due to unreachable code can be distilled in a surprisingly small set of simple formal rules. Specifically, following the well-established tradition of understanding linguistic phenomena through calculi, we introduce the first calculus for unreachable. Its term-rewriting rules that take advantage of unreachable fall into two groups. The first group allows the compiler to delete any code downstream of unreachable, and any effect-free code upstream of unreachable. The second group consists of rules that eliminate conditional expressions when one of their branches is unreachable. We show the correctness of the rules with a novel logical relation, and we examine how they correspond to transformations due to unreachable in Racket and LLVM.

Download

Rhombus: A New Spin on Macros without All the Parentheses

October 2023

·

30 Reads

·

4 Citations

Proceedings of the ACM on Programming Languages

Rhombus is a new language that is built on Racket. It offers the same kind of language extensibility as Racket itself, but using traditional (infix) notation. Although Rhombus is far from the first language to support Lisp-style macros without Lisp-style parentheses, Rhombus offers a novel synthesis of macro technology that is practical and expressive. A key element is the use of multiple binding spaces for context-specific sublanguages. For example, expressions and pattern-matching forms can use the same operators with different meanings and without creating conflicts. Context-sensitive bindings, in turn, facilitate a language design that reduces the notational distance between the core language and macro facilities. For example, repetitions can be defined and used in binding and expression contexts generally, which enables a smoother transition from programming to metaprogramming. Finally, since handling static information (such as types) is also a necessary part of growing macros beyond Lisp, Rhombus includes support in its expansion protocol for communicating static information among bindings and expressions. The Rhombus implementation demonstrates that all of these pieces can work together in a coherent and user-friendly language.


Highly illogical, Kirk: spotting type mismatches in the large despite broken contracts, unsound types, and too many linters

October 2022

·

9 Reads

·

2 Citations

Proceedings of the ACM on Programming Languages

The DefinitelyTyped repository hosts type declarations for thousands of JavaScript libraries. Given the lack of formal connection between the types and the corresponding code, a natural question is are the types right? An equally important question, as DefinitelyTyped and the libraries it supports change over time, is how can we keep the types from becoming wrong? In this paper we offer Scotty, a tool that detects mismatches between the types and code in the Definitely-Typed repository. More specifically, Scotty checks each package by converting its types into contracts and installing the contracts on the boundary between the library and its test suite. Running the test suite in this environment can reveal mismatches between the types and the JavaScript code. As automation and generality are both essential if such a tool is going to remain useful in the long term, we focus on techniques that sacrifice completeness, instead preferring to avoid false positives. Scotty currently handles about 26% of the 8006 packages on DefinitelyTyped (61% of the packages whose code is available and whose test suite passes). Perhaps unsurprisingly, running the tests with these contracts in place revealed many errors in Definitely-Typed. More surprisingly, despite the inherent limitations of the techniques we use, this exercise led to one hundred accepted pull requests that fix errors in DefinitelyTyped, demonstrating the value of this approach for the long-term maintenance of DefinitelyTyped. It also revealed a number of lessons about working in the JavaScript ecosystem and how details beyond the semantics of the language can be surprisingly important. Best of all, it also revealed a few places where programmers preferred incorrect types, suggesting some avenues of research to improve TypeScript.


Figure 8: The Full Input Evolution Cycle
Sound and Complete Concolic Testing for Higher-order Functions

March 2021

·

28 Reads

·

1 Citation

Lecture Notes in Computer Science

Higher-order functions have become a staple of modern programming languages. However, such values stymie concolic testers, as the SMT solvers at their hearts are inherently first-order. This paper lays a formal foundations for concolic testing higher-order functional programs. Three ideas enable our results: (i) our tester considers only program inputs in a canonical form; (ii) it collects novel constraints from the evaluation of the canonical inputs to search the space of inputs with partial help from an SMT solver and (iii) it collects constraints from canonical inputs even when they are arguments to concretized calls. We prove that (i) concolic evaluation is sound with respect to concrete evaluation; (ii) modulo concretization and SMT solver incompleteness, the search for a counter-example succeeds if a user program has a bug and (iii) this search amounts to directed evolution of inputs targeting hard-to-reach corners of the program.


Dynamic Symbolic Execution of Higher-Order Functions

June 2020

·

23 Reads

The effectiveness of concolic testing deteriorates as the size of programs increases. A promising way out is to test programs modularly, e.g., on a per function or class basis. Alas, this idea hits a roadblock in modern programming languages In modern languages, components expect functions, objects, and even classes as inputs. The crux of the problem is that existing concolic testing techniques cannot faithfully capture the complex interactions between a higher-order program and its inputs in order to distill it in a first-order formula that an SMT solver can work with. In this paper, we take the first step towards solving the problem; we offer a design, semantics, and prototype for concolic testing of higher-order functions. Inspired by work on higher-order symbolic execution, our model constructs inputs for higher-order functions with a canonical shape. This enables the concolic tester to keep track of which pieces of the control-flow path of the higher-order function depend on the shape of its input and which do not. The concolic tester encodes the pieces that do not depend on the shape of the input as a first-order formula. Subsequently, similar to a first-order concolic tester, it leverages an SMT solver to produce another input with the same shape but that explores a different control-flow path of the higher-order function. As a separate dimension, the concolic tester iteratively explores the canonical shapes for the input and, investigating all the ways a higher-order function can interact with its input, searching for bugs. To validate our design, we prove that if a higher-order function has a bug, our concolic tester will eventually construct an input that triggers the bug. Using our design as a blueprint, we implement a prototype concolic tester and confirm that it discovers bugs in a variety of higher-order programs from the literature.



Does blame shifting work?

December 2019

·

103 Reads

·

6 Citations

Proceedings of the ACM on Programming Languages

Contract systems, especially of the higher-order flavor, go hand in hand with blame. The pragmatic purpose of blame is to narrow down the code that a programmer needs to examine to locate the bug when the contract system discovers a contract violation. Or so the literature on higher-order contracts claims. In reality, however, there is neither empirical nor theoretical evidence that connects blame with the location of bugs. The reputation of blame as a tool for weeding out bugs rests on anecdotes about how programmers use contracts to shift blame and their attention from one part of a program to another until they discover the source of the problem. This paper aims to fill the apparent gap and shed light to the relation between blame and bugs. To that end, we introduce an empirical methodology for investigating whether, for a given contract system, it is possible to translate blame information to the location of bugs in a systematic manner. Our methodology is inspired by how programmers attempt to increase the precision of the contracts of a blamed component in order to shift blame to another component, which becomes the next candidate for containing the bug. In particular, we construct a framework that enables us to ask for a contract system whether (i) the process of blame shifting causes blame to eventually settle to the component that contains the bug; and (ii) every shift moves blame ``closer'' to the faulty component. Our methodology offers a rigorous means for evaluating the pragmatics of contract systems, and we employ it to analyze Racket's contract system. Along the way, we uncover subtle points about the pragmatic meaning of contracts and blame in Racket: (i) the expressiveness of Racket's off-the-shelf contract language is not sufficient to narrow down the blamed portion of the code to the faulty component in all cases; and (ii) contracts that trigger state changes (even unexpectedly, perhaps in the runtime system's data structures or caches) interfere with program evaluation in subtle ways and thus blame shifting can lead programmers on a detour when searching for a bug. These points highlight how evaluations such as ours suggest fixes to language design.


How to evaluate the performance of gradual type systems

February 2019

·

124 Reads

·

22 Citations

Journal of Functional Programming

A sound gradual type system ensures that untyped components of a program can never break the guarantees of statically typed components. This assurance relies on runtime checks, which in turn impose performance overhead in proportion to the frequency and nature of interaction between typed and untyped components. The literature on gradual typing lacks rigorous descriptions of methods for measuring the performance of gradual type systems. This gap has consequences for the implementors of gradual type systems and developers who use such systems. Without systematic evaluation of mixed-typed programs, implementors cannot precisely determine how improvements to a gradual type system affect performance. Developers cannot predict whether adding types to part of a program will significantly degrade (or improve) its performance. This paper presents the first method for evaluating the performance of sound gradual type systems. The method quantifies both the absolute performance of a gradual type system and the relative performance of two implementations of the same gradual type system. To validate the method, the paper reports on its application to 20 programs and 3 implementations of Typed Racket.


Fig. 19. Eval
Fig. 20. Next Instant
A calculus for Esterel: if can, can. if no can, no can.

January 2019

·

116 Reads

·

8 Citations

Proceedings of the ACM on Programming Languages

The language Esterel has found success in many safety-critical applications, such as fly-by-wire systems and nuclear power plant control software. Its imperative style is natural to programmers building such systems and its precise semantics makes it work well for reasoning about programs. Existing semantics of Esterel generally fall into two categories: translation to Boolean circuits, or operational semantics that give a procedure for running a whole program. In contrast, equational theories enable reasoning about program behavior via equational rewrites at the source level. Such theories form the basis for proofs of transformations inside compilers or for program refactorings, and defining program evaluation syntactically. This paper presents the first such equational calculus for Esterel. It also illustrates the calculus’s usefulness with a series of example equivalences and discuss how it enabled us to find bugs in Esterel implementations.


Citations (84)


... Related efforts in these directions show early promise. A variety of designs [2,17,23,41,42,53] have explored the integration of macros with Algol-style language syntax. A syntax-speclike metalanguage in a host with such traditional syntax would need to integrate these ideas into its means for specifying grammar. ...

Reference:

Compiled, Extensible, Multi-language DSLs (Functional Pearl)
Rhombus: A New Spin on Macros without All the Parentheses
  • Citing Article
  • October 2023

Proceedings of the ACM on Programming Languages

... The standard approach to debug sound gradual programs is the use of blame reports generated by a blame semantics. Researchers have shown that these blame reports do not always work, with some example erroneous programs that are complex enough to surface issues with these blame reports: for some programs, blame error messages point to misleading places that do not need to be changed to address the program failure [21]. We want to include in our program selection some of these errors from the literature, where alternative approaches are likely to provide either confusing or misleading information. ...

Does blame shifting work?

Proceedings of the ACM on Programming Languages

... FUTURE is a large existing Racket library equipped with trace contracts, plus an application that stresses the functionality. Four of the benchmark programs (DUNGEON, JPEG, LNM, TETRIS) are variants on programs from the standard gradual typing benchmark suite (Greenman et al., 2019). Three (DATAFLOW, FISH, TICKET) are programs developed for use in university courses. ...

Reference:

Trace contracts
How to evaluate the performance of gradual type systems

Journal of Functional Programming

... Program computations are treated as manipulations to these streams to influence their evolution in time. Streams are well-suited for modeling embedded systems, which often handle streams of inputs and outputs in real time [28]. For example, an autonomous vehicle must constantly interpret sensor data and produce control commands in a timely fashion to avoid an accident. ...

A calculus for Esterel: if can, can. if no can, no can.

Proceedings of the ACM on Programming Languages

... Gradually-typed languages come in many varieties because the question of how to enforce static types in the midst of untyped code exposes a complex design space. Full enforcement via behavioral contracts is a compelling vision [21,64], but leads to high run-time overhead [29] without custom runtime support [3,20,39]. One alternative is to enforce only the top-level shape of types, but this can still lead to overheads of 2x or more [25,28,72]. A second alternative is to forbid untyped data structures from entering typed code [43,48,75]. ...

Collapsible contracts: fixing a pathology of gradual typing

Proceedings of the ACM on Programming Languages

... Usability evaluation of the overall framework was reported for three di↵erent scenarios. Florence et al. in [106] proposed a Patient-Oriented Prescription Programming Language (POP-PL). More specifically, the authors implemented a prototype of the language and evaluated its design by writing prescriptions in the new language, 590 as well as administering a usability survey to medical professionals. ...

POP-PL: A Patient-Oriented Prescription Programming Language
  • Citing Article
  • July 2018

ACM Transactions on Programming Languages and Systems

... As far as this paper is concerned, Racket's core comes with the usual contemporary linguistic constructs of a mostlyfunctional language: structures and first-class instances; first-class and higher-order functions; pattern matching; but also mutable data structures and assignable variables. For prototyping languages, Racket features an expressive macro system for seamlessly extending the language with new constructs [21] and even domain-specific languages [26]. ...

A programmable programming language
  • Citing Article
  • February 2018

Communications of the ACM

... Sentences of the IMP2 language are enumerated based on the structure of syntactically valid abstract syntax trees (ASTs). Using standard methods for enumerating combinatorial structures [20,21], we implemented a system for constructing enumerators based on combinators [17,22] that allow us to build and compose complex enumerations from simpler ones. The enumerations of numbers, truth values, and other atomic elements are combined to produce enumerations of arithmetic and boolean expressions, which are themselves combined to produce enumerations of assignments and control structures, all the way up to the top-level sentences specified by the language grammar. ...

Fair enumeration combinators
  • Citing Article
  • August 2017

Journal of Functional Programming

... At the heart of our prototype is a language built on top of Rosette Bodik 2013, 2014), a framework for constructing domain-specific languages that employ SAT solvers. We start with most of the features from Rosette itself, but use Racket's domain-specific language support (Felleisen et al. 2018;St-Amour et al. 2017) to adjust Rosette to concolic evaluation. More specifically, we replace Rosette's conditional expressions (that employ symbolic execution) with ones that compute specific values at conditional tests and in order to avoid exploring both branches of any given conditional. ...

Herbarium Racketensis: a stroll through the woods (functional pearl)
  • Citing Article
  • August 2017

Proceedings of the ACM on Programming Languages