Skip to content

Instantly share code, notes, and snippets.

@pao
Created April 20, 2012 23:10
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pao/2432554 to your computer and use it in GitHub Desktop.
Save pao/2432554 to your computer and use it in GitHub Desktop.
Julia interfaces prototype
load("interface.jl")
type Blah; end
type Bluh; end
@interface FooBar{T} [
(:foo, :(T, Integer,))
(:bar, :(T, String, Integer))
]
foo(x::Blah, y::Integer) = true
foo(x::Bluh, y::Integer) = true
bar(x::Blah, y::String, z::Integer) = true
#no bar(x::Bluh,...)
verify_interface(FooBar, Blah)
verify_interface(FooBar, Bluh)
# Interface FooBar: Type Bluh is missing method bar with argument types (Bluh,String,Integer)
# Make sure things still work if the method doesn't exist
@gensym notamethod
@interface No [(:notamethod, :())]
verify_interface(No, Blah)
# Interface No: Type Blah is missing method notamethod with argument types (Blah,)
@interface Field{T} [
(:+, :(T,T))
(:-, :(T,T))
(:*, :(T,T))
(:/, :(T,T))
(:zero, :(Type{T},))
(:one, :(Type{T},))
]
verify_interface(Field, Int)
## Mixins ##
function mixin_baz(T::Type)
if all(check_interface(FooBar, eval(T)))
@eval begin
function baz(a::($T))
foo(a, 3)
printf("Bazzed a %s!\n", $T)
end
end
end
end
mixin_baz(Blah)
baz(Blah())
type Interface
name::String
sigs::Vector
tvar
end
subst_type(sig, tpe, tvar) = tuple(map(t -> tsubst(t, tpe, tvar), sig.args)...)
function tsubst(t, tpe, tvar)
if t == tvar
return tpe
elseif isa(t, Expr) && t.head == :curly
t.args[2] = tsubst(t.args[2], tpe, tvar)
end
eval(t)
end
function check_interface(iface::Interface, tpe::Type)
hasmethods = falses(size(iface.sigs))
for (sig, i) in enumerate(iface.sigs)
# first put our new type in place
args = subst_type(sig[2], tpe, iface.tvar)
method = eval(sig[1])
if isa(method, Function)
# this is unfortunate--can't check the symbol table
try
hasmethods[i] = method_exists(method, args)
catch err
# this is hokey on top of unfortunate
if isa(match(r" not defined$", err.msg), Nothing)
throw(err)
end
end
end
end
hasmethods
end
function verify_interface(iface::Interface, tpe::Type)
hasmethods = check_interface(iface, tpe)
for sig in iface.sigs[!hasmethods]
args = subst_type(sig[2], tpe, iface.tvar)
println("Interface $(iface.name): Type $tpe is missing method $(sig[1])$args")
end
all(hasmethods)
end
macro interface(name, sigs)
iname, tvar = if isa(name, Expr) && name.head == :curly
(name.args[1], name.args[2])
elseif isa(name, Symbol)
(name, :())
else
error("must be a Symbol or have a single type parameter")
end
:($iname = Interface($(string(iname)), $sigs, $expr(:quote,tvar)))
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment