Skip to content

Instantly share code, notes, and snippets.

@zmaril
Last active December 23, 2015 22:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmaril/6702476 to your computer and use it in GitHub Desktop.
Save zmaril/6702476 to your computer and use it in GitHub Desktop.
Reverse polish notation macro compiler

I've been messing around with macro compilation and embedded languages in Julia. This is a reverse polish notation compiler built into a macro. Be forewarned, I don't really know julia or how to build a compiler.

I wanted the compiler to leak, so I could pull in environmental variables. a=1; rpn"a 1 +" #Totally valid and should be 2

I wanted the compiler to be able to take in information about the number of arguments to a function. N!f tells the compiler what to do. The default for N is 2. rpn"1 2 3 3!+" # should be 6

Thanks to being a compiler that is porous (unhygenic?), this means that all the power of julia is available to you, the reverse polish notation programmer. rpn"100 20 fill 1!sum" rpn"1 2 1 logspace 1!mean"

If you are so inclined, you could use DArray with some complex entries to do distributed, complex reverse polish notation computing!

debug = false
function tokenize(code)
tokens = Any[]
for x in split(code," ")
m = match(r"(\d+)!(.+)",x)
if m == nothing
push!(tokens,parse(x))
else
numargs, f = m.captures
push!(tokens,(parse(convert(UTF8String,numargs)),parse(convert(UTF8String,f))))
end
end
return tokens
end
macro rpn_str(code)
tokens = tokenize(code)
exprs = Any[:block]
stack = Any[]
index = 1
while tokens != []
token=shift!(tokens)
evaled = try eval(token) catch e token end
if debug
print("TOKEN\n")
show(token)
print(" ")
show(evaled)
print(" ")
show(index)
print(" ")
show(exprs)
print(" ")
show(stack)
print("\n")
end
if typeof(evaled) == Function
evaled = (2,token)
end
if typeof(evaled) <: (Number,Symbol)
fargs = reverse([pop!(stack) for i in 1:evaled[1]])
f = evaled[2]
tmp = symbol("tmp$(index)")
fcall = Expr(:call)
fcall.args =unshift!(fargs,f)
assignment = Expr(:(=))
assignment.args = [tmp,fcall]
push!(exprs,assignment)
push!(stack,tmp)
index += 1
else
push!(stack,evaled)
end
end
push!(exprs,pop!(stack))
if debug
print("EXITED\n")
show(index)
print(" ")
show(exprs)
print(" ")
show(stack)
print("\n")
end
return apply(Expr,exprs)
end
rpn_a = 10
rpn_b = 20
rpn_c = [1 2 3]
print(rpn"1","\n")
print(rpn"1 2 +","\n")
print(rpn"1 rpn_a +","\n")
print(rpn"1 2 + 4 *","\n")
show(rpn"rpn_c rpn_c +")
print("\n")
print(rpn"1 2.5 3 3!+","\n")
print(rpn"1 2.5 1+2im 3!+","\n")
function test_compilation(x,y)
return rpn"x y 1+2im 3!+"
end
test_compilation(1,2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment