Created
April 20, 2012 23:10
-
-
Save pao/2432554 to your computer and use it in GitHub Desktop.
Julia interfaces prototype
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
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()) |
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
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