Last active
December 23, 2015 22:19
-
-
Save zmaril/6702476 to your computer and use it in GitHub Desktop.
Reverse polish notation macro compiler
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Messing around with macro compilation and embedded languages in Julia. | |
#Below is a reverse polish notation compiler built into a macro. | |
#Be forewarned, I don't 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. | |
#So here is a sum of an array | |
#rpn"100 20 fill 1!sum" | |
#Finding the average of a logspace | |
#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