The MetaOCaml files Status report and research proposal - - PowerPoint PPT Presentation

the metaocaml files
SMART_READER_LITE
LIVE PREVIEW

The MetaOCaml files Status report and research proposal - - PowerPoint PPT Presentation

The MetaOCaml files Status report and research proposal s P r r Q&A


slide-1
SLIDE 1

The MetaOCaml files

Status report and research proposal

❖❧❡❣ ❑✐s❡❧②♦✈ ❈❤✉♥❣✲❝❤✐❡❤ ❙❤❛♥ ■❈❋P ❊✈❡✱ ✷✵✶✵ ❙♦♠❡✇❤❡r❡ ✐♥ ▼❛r②❧❛♥❞

slide-2
SLIDE 2

2/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed? (Why?)

◮ Use MetaOCaml! Extends full OCaml. Widely used.

slide-3
SLIDE 3

2/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed? (Why?)

◮ Use MetaOCaml! Extends full OCaml. Widely used.

The Design and Implementation of FFTW3

MATTEO FRIGO AND STEVEN G. JOHNSON Invited Paper

FFTW is an implementation of the discrete Fourier transform (DFT) that adapts to the hardware in order to maximize perfor-

  • mance. This paper shows that such an approach can yield an im-

plementation that is competitive with hand-optimized libraries, and describes the software structure that makes our current FFTW3 ver- sion flexible and adaptive. We further discuss a new algorithm for real-data DFTs of prime size, a new way of implementing DFTs by means of machine-specific single-instruction, multiple-data (SIMD) instructions, and how a special-purpose compiler can derive opti- mized implementations of the discrete cosine and sine transforms automatically from a DFT algorithm. Keywords—Adaptive software, cosine transform, fast Fourier transform (FFT), Fourier transform, Hartley transform, I/O tensor.

  • I. INTRODUCTION

FFTW [1] is a widely used free-software library that computes the discrete Fourier transform (DFT) and its various special cases. Its performance is competitive even with vendor-optimized programs, but unlike these programs, FFTW is not tuned to a fixed machine. Instead, FFTW uses a planner to adapt its algorithms to the hardware in

  • rder to maximize performance. The input to the planner

is a problem, a multidimensional loop of multidimensional

  • DFTs. The planner applies a set of rules to recursively

FFTW is fast, but its speed does not come at the expense of

  • flexibility. In fact, FFTW is probably the most flexible DFT

library available.

  • FFTW is written in portable C and runs well on many

architectures and operating systems.

  • FFTW computes DFTs in

time for any length . (Most other DFT implementations are either restricted to a subset of sizes or they become for certain values of , for example, when is prime.)

  • FFTW imposes no restrictions on the rank (dimension-

ality) of multidimensional transforms. (Most other im- plementations are limited to one-dimensional (1-D), or at most two-dimensional (2-D) and three-dimensional data.)

  • FFTW supports multiple and/or strided DFTs; for ex-

ample, to transform a three-component vector field or a portion of a multidimensional array. (Most implemen- tations support only a single DFT of contiguous data.)

  • FFTW supports DFTs of real data, as well as of real

symmetric/antisymmetric data [also called the discrete cosine transform (DCT) and the discrete sine transform (DST)]. The interaction of the user with FFTW occurs in two

BPF+: Exploiting Global Data-flow Optimization in a Generalized Packet Filter Architecture

Andrew Begel, Steven McCanne, Susan L. Graham University of California, Berkeley { abegel, mccanne, graham} @cs.berkeley.edu

Abstract A packer filter is a programmable

selection criterion for classify- ing or selecting packets from a packet stream in a generic, reusable

  • fashion. Previous

work on packet filters falls roughly into two cate- gories, namely those efforts that investigate flexible and extensible filter abstractions but sacrifice performance, and those that focus

  • n low-level, optimized filtering representations

but sacrifice flex-

  • ibility. Applications like network monitoring and intrusion detec-

tion, however, require both high-level expressiveness and raw per-

  • formance. In this paper,

we propose a fully general packet filter framework that affords both a high degree

  • f flexibility and good
  • performance. In our framework, a packet

filter is expressed in a high-level language that is compiled into a highly efficient native

  • implementation. The optimization phase
  • f the compiler uses a

flowgraph set relation called edge dominators and the novel appli- cation of an optimization technique that we call “redundant predi- cate elimination,” in which we interleave partial redundancy elim- ination, predicate assertion propagation, and flowgraph edge elim- ination to carry out the filter predicate

  • ptimization. Our resulting

packet-filtering framework, which we call BPF+, derives from the BSD packet filter (BPF), and includes a filter program translator, a byte code

  • ptimizer, a

byte code safety verifier to allow code

lo mi-

grate across protection boundaries, and a just-in-time assembler to convert byte codes to efficient native

  • code. Despite

the high degree

  • f flexibility afforded by our generalized

framework, our perfor- mance measurements show that our system achieves performance comparable to state-of-the-art packet filter architectures and better than hand-coded filters written in C.

1 Introduction

Over the past decade, a number

  • f innovative research

efforts have built upon each

  • ther by iteratively refining the concept
  • f a

pucker

  • filter. First proposed

by Mogul, Rashid, and Accetta in 19874161, a packet filter in its simplest form is a programmable abstraction for a boolean predicate function applied to a stream

  • f packets

to select some specific subset

  • f that stream.

While this filtering model has been heavily exploited for network monitoring, traffic collection, performance measurement, and user-level protocol demultiplexing, more recently, filtering has been proposed for packet classification

Permission to make digital
  • r hard
copies
  • f all or part
  • f this
work for personal
  • r classroom
use is granted without fee provided that copies are not made
  • r distributed
for profit
  • r commercial
advan- tage and that copies bear this notice and the full citation
  • n the
first page. To copy
  • therwise,
to republish, to post
  • n servars
  • r to
redistribute to lists, requires prior specific permission andlor a fee. SIGCOMM ‘99 8/99 Cambridge, MA, USA 0 1999 ACM 1-581 13.135~6/99/0008...$5.00

in routers (e.g., for real-time services

  • r layer-four switching) [ 14,

201, firewall filtering, and intrusion detection [19]. The earliest representations for packet filters were based

  • n

an imperative execution model. In this form, a packet filter is represented as a sequence

  • f instructions that conform to some

abstract virtual machine, much as modern Java byte codes rep- resent programs that can be executed

  • n a Java virtual machine.

Mogul ef al.‘s original packet filter (known as the CMU/Stanford packet filter or CSPF) was based

  • n a stack-oriented

virtual ma- chine, where selected packet contents could be pushed

  • n a stack

and boolean and arithmetic operations could be performed over these stack operands. The BSD packet filter (BPF) modernized CSPF with a higher-performance register-model instruction set. Sub- sequent research introduced a number

  • f further improvements:

the Mach Packet Filter (MPF) extended BPF to efficiently support an arbitrary number

  • f independent

filters [24]; PathFinder provided a new virtual machine abstraction based

  • n pattern-matching

that achieved impressive performance enhancements and was amenable to hardware implementation [2]; and DPF enhanced Pathfinder’s core model with dynamic-code generation (DCG) to exploit run- time knowledge for even greater performance [7]. An alternative approach to the imperative style of packet filtering was explored by Jayaram and Cytron [ 131. A filter specification takes the form of a set

  • f rules written as

a context-free grammar. An LR parser then interprets the grammar

  • n the fly for each

processed packet. More recent work on packet ciassification for “layer four switch- ing” has focused

  • n table-based

representations

  • f predicate

tem- plates to yield very high filtering performance. Srinivasan ef

  • al. [20]

propose a special data structure that they call a “grid of tries” to re- duce the common case

  • f source/destination

classification to a few memory references, while Lakshman and Stiliadis [I41 elegantly cast packet classification as the multidimensional point location problem from computational geometry. None of the earlier work addresses the issue of compiling an abstract, declarative representation

  • f a packet filter into an effi-

cient low-level form. It also does not consider the minimization of computation by exploiting semantic redundancies across multiple, independent filters in a generalizable

  • fashion. Work on such opti-

mizations has not been forthcoming for good reason. If we model a packet filter program as a function of boolean predicates, we can reduce filter optimization to the “decision tree reduction” [lo] prob-

  • Icm. Since

this problem is “NP-complete”, we know that filter opti- mization is a hard

  • problem. As a

natural consequence, decision tree reduction methods have relied upon heuriskcs for optimization [5]. Fortunately, many packet filters have a regular structure that we can use to our advantage in our optimization framework. One way to exploit this structure is to account for it in the underlying filtering engine itself. Both PathFinder and MPF are based

  • n this design

principle: PathFinder utilizes a template-based matching scheme 123

slide-4
SLIDE 4

2/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed? (Why?)

◮ Use MetaOCaml! Extends full OCaml. Widely used.

The Design and Implementation of FFTW3

MATTEO FRIGO AND STEVEN G. JOHNSON Invited Paper

FFTW is an implementation of the discrete Fourier transform (DFT) that adapts to the hardware in order to maximize perfor-

  • mance. This paper shows that such an approach can yield an im-

plementation that is competitive with hand-optimized libraries, and describes the software structure that makes our current FFTW3 ver- sion flexible and adaptive. We further discuss a new algorithm for real-data DFTs of prime size, a new way of implementing DFTs by means of machine-specific single-instruction, multiple-data (SIMD) instructions, and how a special-purpose compiler can derive opti- mized implementations of the discrete cosine and sine transforms automatically from a DFT algorithm. Keywords—Adaptive software, cosine transform, fast Fourier transform (FFT), Fourier transform, Hartley transform, I/O tensor.

  • I. INTRODUCTION

FFTW [1] is a widely used free-software library that computes the discrete Fourier transform (DFT) and its various special cases. Its performance is competitive even with vendor-optimized programs, but unlike these programs, FFTW is not tuned to a fixed machine. Instead, FFTW uses a planner to adapt its algorithms to the hardware in

  • rder to maximize performance. The input to the planner

is a problem, a multidimensional loop of multidimensional

  • DFTs. The planner applies a set of rules to recursively

FFTW is fast, but its speed does not come at the expense of

  • flexibility. In fact, FFTW is probably the most flexible DFT

library available.

  • FFTW is written in portable C and runs well on many

architectures and operating systems.

  • FFTW computes DFTs in

time for any length . (Most other DFT implementations are either restricted to a subset of sizes or they become for certain values of , for example, when is prime.)

  • FFTW imposes no restrictions on the rank (dimension-

ality) of multidimensional transforms. (Most other im- plementations are limited to one-dimensional (1-D), or at most two-dimensional (2-D) and three-dimensional data.)

  • FFTW supports multiple and/or strided DFTs; for ex-

ample, to transform a three-component vector field or a portion of a multidimensional array. (Most implemen- tations support only a single DFT of contiguous data.)

  • FFTW supports DFTs of real data, as well as of real

symmetric/antisymmetric data [also called the discrete cosine transform (DCT) and the discrete sine transform (DST)]. The interaction of the user with FFTW occurs in two

BPF+: Exploiting Global Data-flow Optimization in a Generalized Packet Filter Architecture

Andrew Begel, Steven McCanne, Susan L. Graham University of California, Berkeley { abegel, mccanne, graham} @cs.berkeley.edu

Abstract A packer filter is a programmable

selection criterion for classify- ing or selecting packets from a packet stream in a generic, reusable

  • fashion. Previous

work on packet filters falls roughly into two cate- gories, namely those efforts that investigate flexible and extensible filter abstractions but sacrifice performance, and those that focus

  • n low-level, optimized filtering representations

but sacrifice flex-

  • ibility. Applications like network monitoring and intrusion detec-

tion, however, require both high-level expressiveness and raw per-

  • formance. In this paper,

we propose a fully general packet filter framework that affords both a high degree

  • f flexibility and good
  • performance. In our framework, a packet

filter is expressed in a high-level language that is compiled into a highly efficient native

  • implementation. The optimization phase
  • f the compiler uses a

flowgraph set relation called edge dominators and the novel appli- cation of an optimization technique that we call “redundant predi- cate elimination,” in which we interleave partial redundancy elim- ination, predicate assertion propagation, and flowgraph edge elim- ination to carry out the filter predicate

  • ptimization. Our resulting

packet-filtering framework, which we call BPF+, derives from the BSD packet filter (BPF), and includes a filter program translator, a byte code

  • ptimizer, a

byte code safety verifier to allow code

lo mi-

grate across protection boundaries, and a just-in-time assembler to convert byte codes to efficient native

  • code. Despite

the high degree

  • f flexibility afforded by our generalized

framework, our perfor- mance measurements show that our system achieves performance comparable to state-of-the-art packet filter architectures and better than hand-coded filters written in C.

1 Introduction

Over the past decade, a number

  • f innovative research

efforts have built upon each

  • ther by iteratively refining the concept
  • f a

pucker

  • filter. First proposed

by Mogul, Rashid, and Accetta in 19874161, a packet filter in its simplest form is a programmable abstraction for a boolean predicate function applied to a stream

  • f packets

to select some specific subset

  • f that stream.

While this filtering model has been heavily exploited for network monitoring, traffic collection, performance measurement, and user-level protocol demultiplexing, more recently, filtering has been proposed for packet classification

Permission to make digital
  • r hard
copies
  • f all or part
  • f this
work for personal
  • r classroom
use is granted without fee provided that copies are not made
  • r distributed
for profit
  • r commercial
advan- tage and that copies bear this notice and the full citation
  • n the
first page. To copy
  • therwise,
to republish, to post
  • n servars
  • r to
redistribute to lists, requires prior specific permission andlor a fee. SIGCOMM ‘99 8/99 Cambridge, MA, USA 0 1999 ACM 1-581 13.135~6/99/0008...$5.00

in routers (e.g., for real-time services

  • r layer-four switching) [ 14,

201, firewall filtering, and intrusion detection [19]. The earliest representations for packet filters were based

  • n

an imperative execution model. In this form, a packet filter is represented as a sequence

  • f instructions that conform to some

abstract virtual machine, much as modern Java byte codes rep- resent programs that can be executed

  • n a Java virtual machine.

Mogul ef al.‘s original packet filter (known as the CMU/Stanford packet filter or CSPF) was based

  • n a stack-oriented

virtual ma- chine, where selected packet contents could be pushed

  • n a stack

and boolean and arithmetic operations could be performed over these stack operands. The BSD packet filter (BPF) modernized CSPF with a higher-performance register-model instruction set. Sub- sequent research introduced a number

  • f further improvements:

the Mach Packet Filter (MPF) extended BPF to efficiently support an arbitrary number

  • f independent

filters [24]; PathFinder provided a new virtual machine abstraction based

  • n pattern-matching

that achieved impressive performance enhancements and was amenable to hardware implementation [2]; and DPF enhanced Pathfinder’s core model with dynamic-code generation (DCG) to exploit run- time knowledge for even greater performance [7]. An alternative approach to the imperative style of packet filtering was explored by Jayaram and Cytron [ 131. A filter specification takes the form of a set

  • f rules written as

a context-free grammar. An LR parser then interprets the grammar

  • n the fly for each

processed packet. More recent work on packet ciassification for “layer four switch- ing” has focused

  • n table-based

representations

  • f predicate

tem- plates to yield very high filtering performance. Srinivasan ef

  • al. [20]

propose a special data structure that they call a “grid of tries” to re- duce the common case

  • f source/destination

classification to a few memory references, while Lakshman and Stiliadis [I41 elegantly cast packet classification as the multidimensional point location problem from computational geometry. None of the earlier work addresses the issue of compiling an abstract, declarative representation

  • f a packet filter into an effi-

cient low-level form. It also does not consider the minimization of computation by exploiting semantic redundancies across multiple, independent filters in a generalizable

  • fashion. Work on such opti-

mizations has not been forthcoming for good reason. If we model a packet filter program as a function of boolean predicates, we can reduce filter optimization to the “decision tree reduction” [lo] prob-

  • Icm. Since

this problem is “NP-complete”, we know that filter opti- mization is a hard

  • problem. As a

natural consequence, decision tree reduction methods have relied upon heuriskcs for optimization [5]. Fortunately, many packet filters have a regular structure that we can use to our advantage in our optimization framework. One way to exploit this structure is to account for it in the underlying filtering engine itself. Both PathFinder and MPF are based

  • n this design

principle: PathFinder utilizes a template-based matching scheme 123

Accomplishments and Research Challenges in Meta-programming

Invited Paper

Tim Sheard Pacific Software Research Center OGI School of Science and Engineering Oregon Health & Science University sheard@cse.ogi.edu, http://www.cse.ogi.edu/˜ {}sheard

1 Introduction

In the last ten years the study of meta-programming systems, as formal systems worthy of study in their own right, has vastly accelerated. In that time a lot has been accomplished, yet much remains to be done. In this invited talk I wish to review recent accomplishments and future research challenges in hopes that this will spur interest in meta-programming in general and lead to new and better meta-programming systems.

Standard ML as a Meta-Programming Language Sam uel Kamin
  • Computer
Science Dept. Univ ersit y
  • f
Illinois Urbana, Illinois s-kamin@ui uc. ed u Septem b er 20, 1996 Abstract Meta-programming languages,
  • r
program generators, are languages whose programs pro- duce programs in
  • ther
languages. W e sho w ho w Standard ML mak es an excellen t meta- programmi ng language, b y adding appropriate program-v alued | b y whic h w e mean string- v alued |
  • p
erations for eac h domain. W e do so b y giving four examples
  • f
meta-programm ing languages: a top-do wn parser generator; a \geometric region serv er" language mo delled
  • n
  • ne
dev elop ed at Y ale; a v ersion
  • f
the \Message Sp ecication Language," dev elop ed at Oregon Graduate Institute; and a prett y-prin ting sp ecication language. Em b edding meta- programmi ng languages in ML in this w a y is easy to do, and the result is a language that, unlik e most meta-programm ing languages, is higher-order. 1 In tro duction It is a kind
  • f
folklore in the programmi ng language comm unit y that programmi ng language =
  • calculus
+ constan ts In this pap er, w e explore this claim b y dev eloping sev eral languages b y adding constan ts to Standard ML. All
  • f
  • ur
examples are meta-program m ing languages, in tended to aid in the pro duction
  • f
C++ programs. The examples are:
  • T
  • p-down
p arser gener ator. This is a w ell kno wn example
  • f
\com binator-st yle" program- ming [8]. The com binators used in dev eloping a parser in a functional language can b e redened to generate a parser in C++.
  • Ge
  • metric
r e gion server. The Hask ell co de presen ted b y Carlson et al. [4 ] to solv e this problem directly can b e mo died to pro duce C++ co de that solv es it. The metaprogram is remark ably similar to the
  • riginal.
  • Supp
  • rted
b y NSF Con tract CCR 93{03043 1
slide-5
SLIDE 5

2/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed? (Why?)

◮ Use MetaOCaml! Extends full OCaml. Widely used.

slide-6
SLIDE 6

2/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed? (Why?)

◮ Use MetaOCaml! Extends full OCaml. Widely used.

MetaOCaml BER MetaOCaml –January 2006 March 2010–? OCaml 3.09.1 OCaml 3.11.2 bytecode + native bytecode

slide-7
SLIDE 7

2/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed?

◮ Use MetaOCaml! Extends full OCaml. Widely used.

How to type-check generated code?

◮ Preserve type environments ◮ Rename shadowed identifiers? ◮ Follow explicit substitutions?

How to maintain type soundness with side effects?

◮ Later binders delimit earlier effects ◮ Regions of generated names? ◮ Earlier effects prevent later generalization?

How to implement code generation as syntactic sugar?

◮ camlp4/5 quotations ◮ Represent let-polymorphism by higher polymorphism?

slide-8
SLIDE 8

3/15

Crash course

MetaOCaml is not quite like Lisp bracket

.<x + y>.

quasiquote

‘(+ x y)

escape

.~body

unquote

,body

run

.!code

eval

(eval code)

persist

r ’,r

slide-9
SLIDE 9

3/15

Crash course

MetaOCaml is not quite like Lisp bracket

.<x + y>.

quasiquote

‘(+ x y)

escape

.~body

unquote

,body

run

.!code

eval

(eval code)

persist

r ’,r .<fun x -> .~(let body = .<x>. in .<fun x -> .~body>.)>. ‘(lambda (x) ,(let ((body ‘x)) ‘(lambda (x) ,body))) ‘(lambda (x) (lambda (x) x))

Implicit binding context . . .

slide-10
SLIDE 10

3/15

Crash course

MetaOCaml is not quite like Lisp bracket

.<x + y>.

quasiquote

‘(+ x y)

escape

.~body

unquote

,body

run

.!code

eval

(eval code)

persist

r ’,r .<fun x -> .~(let body = .<x>. in .<fun x -> .~body>.)>. .<fun x_1 -> .~(let body = .<x_1>. in .<fun x -> .~body>.)>. .<fun x_1 -> .~.<fun x -> .~.<x_1>.>.>. .<fun x_1 -> .~.<fun x_2 -> .~.<x_1>.>.>. .<fun x_1 -> .~.<fun x_2 -> x_1>.>. .<fun x_1 -> fun x_2 -> x_1>.

slide-11
SLIDE 11

3/15

Crash course

MetaOCaml is not quite like Lisp bracket

.<x + y>.

quasiquote

‘(+ x y)

escape

.~body

unquote

,body

run

.!code

eval

(eval code)

persist

r ’,r .<fun x -> .~(let body = .<x>. in .<fun x -> .~body>.)>. .<fun x_1 -> .~(let body = .<x_1>. in .<fun x -> .~body>.)>. .<fun x_1 -> .~.<fun x -> .~.<x_1>.>.>. .<fun x_1 -> .~.<fun x_2 -> .~.<x_1>.>.>. .<fun x_1 -> .~.<fun x_2 -> x_1>.>. .<fun x_1 -> fun x_2 -> x_1>.

slide-12
SLIDE 12

4/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed?

◮ Use MetaOCaml! Extends full OCaml. Widely used.

How to type-check generated code?

◮ Preserve type environments ◮ Rename shadowed identifiers? ◮ Follow explicit substitutions?

How to maintain type soundness with side effects?

◮ Later binders delimit earlier effects ◮ Regions of generated names? ◮ Earlier effects prevent later generalization?

How to implement code generation as syntactic sugar?

◮ camlp4/5 quotations ◮ Represent let-polymorphism by higher polymorphism?

slide-13
SLIDE 13

5/15

Passes

Source text parse AST type-check Typed IR compile Executable run

slide-14
SLIDE 14

5/15

Passes

Source text parse AST type-check Typed IR compile Executable run generated code never goes wrong either

slide-15
SLIDE 15

5/15

Passes

Source text parse AST type-check Typed IR Typed IR compile compile Executable Executable run run generated code never goes wrong either

slide-16
SLIDE 16

5/15

Passes

Source text parse AST type-check Typed IR Typed IR compile compile Executable Executable run run generated code never goes wrong either each node annotated with type environment

slide-17
SLIDE 17

5/15

Passes

Source text parse AST AST type-check type-check Typed IR Typed IR compile compile Executable Executable run run

slide-18
SLIDE 18

6/15

Preserving type environments

# type foo = Foo let x = .<Foo>. type bar = Foo | Bar let y = .<Foo>. let z = .<(.~x, .~y)>. ;; val z : (’a, foo * bar) code = .<((Foo), (Foo))>.

slide-19
SLIDE 19

6/15

Preserving type environments

# type foo = Foo let x = .<Foo>. type bar = Foo | Bar let y = .<Foo>. let z = .<(.~x, .~y)>. ;; val z : (’a, foo * bar) code = .<((Foo), (Foo))>.

Currently, .<Foo>. means to make an AST node Foo and stash the type environment here in it.

slide-20
SLIDE 20

6/15

Preserving type environments

# type foo = Foo let x = .<Foo>. type bar = Foo | Bar let y = .<Foo>. let z = .<(.~x, .~y)>. ;; val z : (’a, foo * bar) code = .<((Foo), (Foo))>.

Perhaps simpler:

type foo = Foo1 type bar = Foo2 | Bar .cmo

Need guidance from a calculus with explicit substitutions!

slide-21
SLIDE 21

7/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed?

◮ Use MetaOCaml! Extends full OCaml. Widely used.

How to type-check generated code?

◮ Preserve type environments ◮ Rename shadowed identifiers? ◮ Follow explicit substitutions?

How to maintain type soundness with side effects?

◮ Later binders delimit earlier effects ◮ Regions of generated names? ◮ Earlier effects prevent later generalization?

How to implement code generation as syntactic sugar?

◮ camlp4/5 quotations ◮ Represent let-polymorphism by higher polymorphism?

slide-22
SLIDE 22

8/15

Scope extrusion

Pure staging works great, especially with polymorphism. But effects are oh so useful.

slide-23
SLIDE 23

8/15

Scope extrusion

Pure staging works great, especially with polymorphism. But effects are oh so useful.

# let code = let r = ref .<1>. in let _ = .<fun x -> .~(r := .<x>.; .<()>.)>. in !r ;; val code : (’a, int) code = .<x_1>.

slide-24
SLIDE 24

8/15

Scope extrusion

Pure staging works great, especially with polymorphism. But effects are oh so useful.

# let code = let r = ref .<1>. in let _ = .<fun x -> .~(r := .<x>.; .<()>.)>. in !r ;; val code : (’a, int) code = .<x_1>. # .!code ;; Unbound value x_1 Exception: Trx.TypeCheckingError.

To restore soundness: later binders delimit earlier effects To express even more: regions of generated names?

slide-25
SLIDE 25

9/15

Imperative polymorphism redux

#

✿✿✿

let

✿✿✿✿✿✿

f ()✿✿ =

✿✿✿✿✿

ref

✿✿✿✿

[]

slide-26
SLIDE 26

9/15

Imperative polymorphism redux

#

✿✿✿

let

✿✿✿✿✿✿

f ()✿✿ =

✿✿✿✿✿

ref

✿✿✿✿

[] in f () := [1]; "hello" :: !(f ()) ;;

  • : string list = ["hello"]
slide-27
SLIDE 27

10/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿ ref✿✿✿✿ []

slide-28
SLIDE 28

10/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿ ref✿✿✿✿ [] in f () := [1]; "hello" :: !(f ())>. ;; val c : (’a, string list) code = .<let f_2 () = ref [] in f_2 () := [1]; "hello" :: !(f_2 ())>. # .!c ;;

  • : string list = ["hello"]
slide-29
SLIDE 29

11/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿✿✿✿✿✿✿ .~(.<ref

✿✿✿✿✿✿✿✿

[]>.)

slide-30
SLIDE 30

11/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿✿✿✿✿✿✿ .~(.<ref

✿✿✿✿✿✿✿✿

[]>.) in f () := [1]; "hello" :: !(f ())>. ;; val c : (’a, string list) code = .<let f_2 () = ref [] in f_2 () := [1]; "hello" :: !(f_2 ())>. # .!c ;;

  • : string list = ["hello"]
slide-31
SLIDE 31

12/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿ .~(let r = ref [] in

✿✿✿✿✿✿✿✿✿

.<r>.)

slide-32
SLIDE 32

12/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿ .~(let r = ref [] in

✿✿✿✿✿✿✿✿✿

.<r>.) in f () := [1]; "hello" :: !(f ())>. ;; val c : (’a, string list) code = .<let f_2 () = (* cross-stage persistent value (as id: r) *) in f_2 () := [1]; "hello" :: !(f_2 ())>.

slide-33
SLIDE 33

12/15

Imperative polymorphism redux

# let c = .<✿✿✿✿ let✿✿✿✿✿ f ()

✿✿✿

=✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿✿ .~(let r = ref [] in

✿✿✿✿✿✿✿✿✿

.<r>.) in f () := [1]; "hello" :: !(f ())>. ;; val c : (’a, string list) code = .<let f_2 () = (* cross-stage persistent value (as id: r) *) in f_2 () := [1]; "hello" :: !(f_2 ())>. # .!c ;; Segmentation fault

To restore soundness: earlier effects prevent later generalization?

slide-34
SLIDE 34

13/15

Q&A

How to reconcile generality with performance?

◮ Write custom code generators! Common practice.

How to assure generated code well-formed?

◮ Use MetaOCaml! Extends full OCaml. Widely used.

How to type-check generated code?

◮ Preserve type environments ◮ Rename shadowed identifiers? ◮ Follow explicit substitutions?

How to maintain type soundness with side effects?

◮ Later binders delimit earlier effects ◮ Regions of generated names? ◮ Earlier effects prevent later generalization?

How to implement code generation as syntactic sugar?

◮ camlp4/5 quotations ◮ Represent let-polymorphism by higher polymorphism?

slide-35
SLIDE 35

14/15

Code generation as syntactic sugar

camlp4/5 quotations? CUFP BoF, tutorial. .<let id = fun x -> x in id 1>. Let_ (Lam (fun x -> x)) (fun id -> App id (Lit 1))

Seems straightforward, but how to represent polymorphic let?

❡ ✿ ✜ ❡ ✿ ✽☛✿ ✜ Gen : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜ code✮ ✦ ✭✽☛✿ ☛ ✜✮ code ❡ ✿ ✽☛✿ ✜ ❡ ✿ ✜❬✛❂☛❪ Spec : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜✮ code ✦ ✭✽☛✿ ☛ ✜ code✮

Need higher-rank, higher-kind polymorphism? Don’t generate code that uses polymorphism? ‘Metacircular let’

let id = Lam (fun x -> x) in App id id

slide-36
SLIDE 36

14/15

Code generation as syntactic sugar

camlp4/5 quotations? CUFP BoF, tutorial. .<let id = fun x -> x in id id>. Let_ (Lam (fun x -> x)) (fun id -> App id id)

Seems straightforward, but how to represent polymorphic let?

❡ ✿ ✜ ❡ ✿ ✽☛✿ ✜ Gen : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜ code✮ ✦ ✭✽☛✿ ☛ ✜✮ code ❡ ✿ ✽☛✿ ✜ ❡ ✿ ✜❬✛❂☛❪ Spec : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜✮ code ✦ ✭✽☛✿ ☛ ✜ code✮

Need higher-rank, higher-kind polymorphism? Don’t generate code that uses polymorphism? ‘Metacircular let’

let id = Lam (fun x -> x) in App id id

slide-37
SLIDE 37

14/15

Code generation as syntactic sugar

camlp4/5 quotations? CUFP BoF, tutorial. .<let id = fun x -> x in id id>. Let_ (Lam (fun x -> x)) (fun id -> App id id)

Seems straightforward, but how to represent polymorphic let?

❡ ✿ ✜ ❡ ✿ ✽☛✿ ✜ Gen : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜ code✮ ✦ ✭✽☛✿ ☛ ✜✮ code ❡ ✿ ✽☛✿ ✜ ❡ ✿ ✜❬✛❂☛❪ Spec : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜✮ code ✦ ✭✽☛✿ ☛ ✜ code✮

Need higher-rank, higher-kind polymorphism? Don’t generate code that uses polymorphism? ‘Metacircular let’

let id = Lam (fun x -> x) in App id id

slide-38
SLIDE 38

14/15

Code generation as syntactic sugar

camlp4/5 quotations? CUFP BoF, tutorial. .<let id = fun x -> x in id id>. Let_ (Lam (fun x -> x)) (fun id -> App id id)

Seems straightforward, but how to represent polymorphic let?

❡ ✿ ✜ ❡ ✿ ✽☛✿ ✜ Gen : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜ code✮ ✦ ✭✽☛✿ ☛ ✜✮ code ❡ ✿ ✽☛✿ ✜ ❡ ✿ ✜❬✛❂☛❪ Spec : ✽✜✿❄✦❄✿ ✭✽☛✿ ☛ ✜✮ code ✦ ✭✽☛✿ ☛ ✜ code✮

Need higher-rank, higher-kind polymorphism? Don’t generate code that uses polymorphism? ‘Metacircular let’

let id = Lam (fun x -> x) in App id id

slide-39
SLIDE 39

15/15

How to type-check generated code? How to maintain type soundness with side effects? How to implement code generation as syntactic sugar?