• Stars
    star
    77
  • Rank 416,225 (Top 9 %)
  • Language
    Clojure
  • License
    Eclipse Public Li...
  • Created over 10 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Staged compilation for Clojure through environment & special-form aware syntax-quoting.

Meta-Clojure

Overview

Meta-Clojure provides staged compilation for Clojure. It includes a form of syntax quoting that is aware of both local environments and special-forms. Among other things, this makes many macros easier to write. Perhaps more importantly, it simplifies control over when code gets evaluated or compiled.

Usage

(require '[metaclj.core :refer [defmeta defbn syntax] :as meta])

Meta-Macros

The defmeta form is analogous to defmacro, but is expected to return Syntax objects (forms plus their environments) instead of plain forms.

(defmeta my-if [test then else]
  (syntax (if test then else)))

Note that you don't need to unquote any of the parameters to if, since the syntax form is aware of the meta-macro's environment.

Call-By-Name

Since it's common for macros to have a body that always templates code with a syntax-quoter, the convenience macro defbn provides a way to create "call-by-name" macros:

(defbn my-if [test then else]
  (if test then else))

Both versions of my-if have correct "lazy" behavior: they will only evaluate one arm of the conditional.

Staged Compilation

The meta/do macro will perform meta-quoting on zero or more forms, then evaluate each of them:

(meta/do 1 2 3)
;;=> 3

Combined with unquoting, this enables you to perform arbitrary computation at compile time:

(let [x 2 y 4]
  (meta/do ~(+ x y)))
;;=> 6

Unquoting is syntax aware and provides automatic splicing:

(let [args (syntax 2 4)]
  (meta/do ~(+ args)))
;;=> 6

You can use function expressions to defer computation. Note that the unquoted expression will still be evaluated at compile time:

(let [x 2 y 4]
  (meta/do (fn [] ~(+ x y))))
;=> #<Fn@32b2ad39 user/eval15784$fn__15788>

You can prove this to yourself by using meta/translate, which is a cousin of macroexpand-all:

(let [x 2 y 4]
  (meta/translate (fn [] ~(+ x y))))
=> ((fn* ([] 6)))

Note that the returned value is wrapped in a seq, since Meta-Clojure uniformly supports multiple expressions with implicit splicing:

(let [x (syntax 2 3)]
  (meta/translate 1 x 4))
;=> (1 2 3 4)

Status

  • The comments at the bottom of core.clj and the code in core_test.clj form my testbed.
  • Many known bugs and incomplete behavior.
  • Some special forms not yet supported: case, deftype, and reify.
  • No progress yet on Exotypes
  • Use of clojure.core/eval is unavoidable at the top level, but it could be compiled away for more interior forms.
  • Maybe someday I'll revive EClj and build its compiler on Meta-Clojure.

References

License

Copyright Β© 2016 Brandon Bloom

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

More Repositories

1

fipp

Fast Idiomatic Pretty Printer for Clojure
Clojure
513
star
2

jseg

A super simple, in-memory, JS graph database.
JavaScript
467
star
3

backtick

Clojure's syntax-quote reader macro as a normal macro
Clojure
193
star
4

cljs-vdom

Yet another (but somewhat novel) virtual DOM library
Clojure
121
star
5

eclj

Extensible Clojure
Clojure
103
star
6

factjor

A Factor-inspired, concatenative DSL for Clojure
Clojure
95
star
7

asyncx

Some push sequence operators built with Clojure's core.async
Clojure
53
star
8

cleff

Algebraic Effect Handlers for Clojure
Clojure
45
star
9

proact

Yet another ClojureScript UI framework
Clojure
32
star
10

qplan

Solver for multi-way, multi-output dataflow property models
Clojure
32
star
11

dispatch-map

Persistent map with Clojure's multimethod dispatch semantics
Clojure
29
star
12

html2coffeekup

Converts HTML to Coffeekup markup
CoffeeScript
26
star
13

ambiparse

Parsing with "disambiguation filters" in Clojure
Clojure
22
star
14

terra-java

Lua/Terra + Java Native Interface
Terra
21
star
15

transduce

map-state, mapcat-state, etc for state transducers in Clojure
Clojure
21
star
16

domscript

Clojure
19
star
17

libclj

Embeddable reader and printer for Clojure forms
C
17
star
18

retree

Functional combinators for strategy-based tree-rewriting in Clojure
Clojure
15
star
19

cljsd

slow work in progress towards better cljs tools
Clojure
13
star
20

csearch.vim

Similar to ack.vim, but for golang's http://code.google.com/p/codesearch/
Vim Script
10
star
21

rtlcat

more concatenative experiments
Scheme
7
star
22

vim-factor

Pathogen-friendly packaging of Factor's Vim support (BSD licensed). I have no plans of actively maintaining this, it's mainly for personal convenience.
Vim Script
7
star
23

waet

The WebAssembly Edn Toolkit
Clojure
7
star
24

ascribe

Attribute Grammars in Clojure
Clojure
5
star
25

cljs-cps

Continuation Passing Transform for ClojureScript
Clojure
5
star
26

exstate

Some crazy thing inspired by plan9 & datomic
Clojure
4
star
27

libclj-ruby

Ruby extension for libclj
Ruby
2
star
28

metaclj-js

Staged JavaScript Metaprogramming from Clojure
Clojure
2
star
29

glens

Clojure
2
star
30

try_jade_and_stylus

Simple Node.js app to experiment with Jade and Stylus in the spirit of http://haml-lang.com/try.html and http://sass-lang.com/try.html
JavaScript
2
star
31

kovasir

Experiments in IR, instruction scheduling, and code gen
Clojure
2
star
32

goog-edit

Build scripts for extracting a stand alone Google Closure Rich Text Editor
2
star
33

vim-proto

Google's proto.vim for Protocol Buffer syntax; pathogen friendly
Vim Script
2
star
34

petri

Clojure
1
star
35

bulletcombinators

Automatically exported from code.google.com/p/bulletcombinators
Python
1
star
36

nyhub

Hacked up little script to find interesting GitHub users to meet
Clojure
1
star
37

noast

experiment in compiling without an ast
Go
1
star
38

astexplorer-cue

astexplorer.net support for cuelang.org
JavaScript
1
star
39

class-scheduler

A jQuery experiment from my college days
JavaScript
1
star
40

thinkfuse-schedule

Adapts common reoccurring schedule rules form iCal to ActiveModel.
Ruby
1
star