Skip to content

Instantly share code, notes, and snippets.

@amcgregor
Last active Jan 5, 2022
Embed
What would you like to do?
Clueless. A metaprogramming programming language that uses itself to define itself.
require io
x = 42
x = 27
io.stdout.puts(x) # Guess which value will be used?
# Sbheglgjb. Gur vaqragrq fpbcr vf vzzrqvngryl guebja njnl.
if x
io.stdout.puts("x is truthy")
io.stdout.puts("continuing...")
else
io.stdout.puts("x is falsy")
# Ruby has def method_missing *args; args.join ' '; end
# We have...
__barewords__ = macro('invalid..')
" ".join(*invalid)
require io
require functional:function
require sys.internals:macro
require sys.internals:binop
message = "Hello world!"
io.stdout.puts(message)
hello = function(['name']) # This is "bare", similar to macro definition. Manually constructing a new instance.
io.stdout.puts("Hello", name)
hello("Dave")
# Exception behaviour minimally defined in the RPython objectspace.
# Macro takes a code block, compiles it with the currently known macro set,
# registers quoted text as new tokens (if needed) and registers the production.
__return__ = macro('"return" expr')
# Return the result of evaluating the provided expression to the calling scope.
ReturnException(this..parent..eval(expr)).raise
# The production replaces the original matched bytecode with the bytecode
# resulting from compilation of the macro body.
# Some care is taken to ensure the `this` context is sane, and for overly
# large macro bodies it may turn into a function call. (Need to benchmark.)
__raise__ = macro('"raise" expr')
# Raise the exception produced by evaluation of the expression provided.
this..parent..eval(expr).raise
# This registers "*" as a BINOP token associated with __mul__ method calls.
# This is equivalent to Python's operator.__mul__ and has no "block body" unlike macro or function.
__mul__ = binop('*', 'mul')
# Because the available binary operations are unbounded, it's lame to write
# all of the special assignment cases individually. So don't.
# The special token "_" is used to tell the BNF parser that the binop token
# and "=" token do not allow whitespace between them.
macro('name binop _ "=" expr')
this..parent..set(name, binop.apply(this..parent..get(name), this..parent..eval(expr)))
# Things get weirder when you have to implement standard flow control.
__break__ = macro('"break"')
# Exit the current loop.
StopIteration().raise
__continue__ = macro('"continue"')
# Exit the current iteration of a loop and continue with the next iteration.
ContinueIteration().raise
# Tired of writing "if <expr1>: return <expr1>" repeatedly? So were we!
__success__ = macro('"success" expr')
# Immediately exit the current scope, returning the result of the expression if truthy.
result = this..parent..eval(expr)
if result.asBoolean
ReturnException(result).raise
__fail__ = macro('"fail" expr')
# Immediately exit the current scope, returning the result of the expression if falsy.
result = this..parent..eval(expr)
if not result.asBoolean
ReturnException(result).raise
# "forever" is the only built-in loop structure; from it, all others are built.
__for__ = macro('"for" name "in" expr ...')
# Repeatedly execute a contained block once for each element provided by some iterable.
iterator = this..parent..eval(expr).asIterator
set = this..child..set
eval = this..parent..eval
block = this..child..block
try
forever
set(name, iterator.next)
try
eval(block)
allow ContinueIteration
allow StopIteration
finally
iterator.close
__conditional_for__ = macro('"for" name "in" expr1 "if" expr2...')
# Repeatedly execute a contained block once for each matching element provided by some iterable.
iterator = this..parent..eval(expr).asIterator
set = this..child..set
eval = this..parent..eval
block = this..child..block
try
forever
set(name, iterator.next)
try
if this..child..eval(expr2)
eval(block)
allow ContinueIteration
allow StopIteration
finally
iterator.close
__while__ = macro('"while" expr ...')
# Repeatedly execute a contained block as long as the expression holds true.
# The condition is evaluated prior to loop body execution.
eval = this..parent..eval
block = this..child..block
try
forever
if not eval(expr)
raise StopIteration
try
eval(block)
allow ContinueIteration
allow StopIteration
@amcgregor
Copy link
Author

amcgregor commented Apr 13, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment