Guest User

Untitled

a guest
Jul 23rd, 2016
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.61 KB | None | 0 0
  1. module SelfFunctions
  2. export @selftype
  3.  
  4. immutable SelfFunction{F <: Function}
  5. name::Symbol
  6. typ::DataType
  7. f::F
  8. end
  9. Base.show(io::IO, sf::SelfFunction) = print(io, "$(sf.name) (self function of type $(sf.typ))")
  10. @inline (sf::SelfFunction)(args...) = sf.f(args...)
  11.  
  12.  
  13. selfcall(f::SelfFunction, t, args...) = f(t, args...)
  14. selfcall(f, t, args...) = f(args...)
  15.  
  16. macro selftype(maker_macro, typname::Symbol)
  17. esc(generate_selfmacro(maker_macro, :(fieldnames($typname)), typname))
  18. end
  19.  
  20. macro selftype(maker_macro, typedef::Expr)
  21. const fields = map(fieldname, filter(isfield, typedef.args[3].args))
  22. const tname = typename(typedef)
  23. esc(quote
  24. $typedef
  25. $(generate_selfmacro(maker_macro, fields, tname))
  26. end)
  27. end
  28.  
  29. function generate_selfmacro(name, fields, tname)
  30. @gensym self fname fimpl iname
  31. quote
  32. macro $(name)(funcdef)
  33. const $self = gensym("self")
  34. const $fname = $funcname(funcdef)
  35. const $fimpl = $funcimpl(funcdef, $fields, $self)
  36. const $iname = $funcname($fimpl)
  37. $(esc)(quote
  38. $($fimpl)
  39. const $($fname) = $($SelfFunction)(Symbol($(string($fname))), $($tname), $($iname))
  40. end)
  41. end
  42. end
  43. end
  44.  
  45. fieldname(arg::Expr) = arg.args[1]
  46. fieldname(arg::Symbol) = arg
  47.  
  48. isfield(arg::Expr) = arg.head == :(::)
  49. isfield(arg::Symbol) = true
  50. isfield(x) = false
  51.  
  52. typename(def::Expr) = def.args[2]
  53. funcname(def::Expr) = def.head == :macrocall? funcname(def.args[2]) : def.args[1].args[1]
  54.  
  55. function funcimpl(def, fields, self)
  56. const (addmeta, fdef) = function_meta(def)
  57. const (sig, body) = fdef.args
  58. const (name,args) = [sig.args[1], sig.args[2:end]]
  59. const nbody = format_calls(body, fields, self)
  60. const nname = gensym("$(name)_selfimpl")
  61. const nargs = [self;args]
  62. const nsig = :($nname($(nargs...)))
  63. addmeta(Expr(:function, nsig, nbody))
  64. end
  65.  
  66. function function_meta(def::Expr)
  67. const meta = []
  68. while def.head == :macrocall
  69. unshift!(meta, def.args[1])
  70. def = def.args[2]
  71. end
  72. function addmeta(ndef)
  73. for m in meta
  74. ndef = Expr(:macrocall, m, ndef)
  75. end
  76. return ndef
  77. end
  78. return (addmeta, def)
  79. end
  80.  
  81. function format_calls(body, fields, self)
  82. nbody = Expr(body.head)
  83. nbody.args = map(redef_call(self, fields), body.args)
  84. nbody
  85. end
  86.  
  87. function redef_call(self, fields)
  88. function rcall(x::Expr)
  89. if x.head == :call
  90. :($selfcall($(rcall(x.args[1])), $self, $(map(rcall, x.args[2:end])...)))
  91. elseif x.head == :.
  92. x
  93. elseif x.head == :quote
  94. rcall_quoted(x)
  95. elseif x.head in [:(=), :function] && length(x.args) > 1
  96. Expr(x.head, x.args[1], rcall(x.args[2]))
  97. else
  98. Expr(x.head, map(rcall, x.args)...)
  99. end
  100. end
  101. rcall(x::Symbol) = x in fields? :($(self).$(x)) : x
  102. rcall(x::QuoteNode) = rcall_quoted(x)
  103. rcall(x) = x
  104.  
  105. function rcall_quoted(x::Expr, depth)
  106. walkin(d) = Expr(x.head, map(y->rcall_quoted(y,d), x.args)...)
  107.  
  108. if x.head == :quote
  109. walkin(depth+1)
  110. elseif x.head == :$
  111. if depth == 1
  112. Expr(:$, rcall(x.args[1]))
  113. else
  114. walkin(depth-1)
  115. end
  116. else
  117. walkin(depth)
  118. end
  119. end
  120. rcall_quoted(x::QuoteNode,depth) = QuoteNode(rcall_quoted(x.value, depth+1))
  121. rcall_quoted(x,depth) = x
  122. rcall_quoted(x) = rcall_quoted(x,0)
  123.  
  124. return rcall
  125. end
  126.  
  127. end
  128.  
  129. ## Examples
  130. #= Use preexisting type
  131.  
  132. using SelfFunctions
  133.  
  134. type MyType
  135. x::Int
  136. end
  137.  
  138. @selftype self MyType
  139.  
  140. =##= Define and then use type
  141.  
  142. using SelfFunctions
  143.  
  144. @selftype self type MyType
  145. x::Int
  146. end
  147.  
  148. =##= Usage of generated macro
  149.  
  150. @self function inc()
  151. x += 1
  152. end
  153.  
  154. @self function inc2()
  155. inc()
  156. inc()
  157. end
  158.  
  159. const mt = MyType(0)
  160. inc(mt) # mt.x: 0 -> 1
  161. inc2(mt) # mt.x: 1 -> 3
  162.  
  163. =###
Advertisement
Add Comment
Please, Sign In to add comment