/
infix.ex
68 lines (65 loc) · 1.62 KB
/
infix.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
defmodule Infix do
defmacro __using__(_) do
quote do
import unquote(__MODULE__), only: [{:|||, 2}]
end
end
defmacro left ||| right do
[p, d] = elem(right, 2)
quote bind_quoted: [f: left, p: p, d: d] do
file =
__MODULE__
|> to_string()
|> String.split(".")
|> Enum.at(-1)
# better module-to-filename mechanism
|> String.downcase()
|> (&("lib/" <> &1 <> ".ex")).()
|> File.read!()
{l0, l1} =
file
|> Code.string_to_quoted()
|> elem(1)
|> Macro.prewalk({:s1, {0, 0}}, fn x, {s, t} ->
case s do
:s0 ->
{x, {:s0, t}}
:s1 ->
case x do
{:def, _, _} ->
{x, {:s2, t}}
_ ->
{x, {:s1, t}}
end
:s2 ->
case x do
{^f, [line: l], _} ->
{x, {:s3, {l, 0}}}
_ ->
{x, {:s1, t}}
end
:s3 ->
case x do
{:def, [line: l], _} ->
{x, {:s0, t}}
{_, [line: l], _} ->
{e1, e2} = t
{x, {:s3, {e1, max(e2, l)}}}
_ ->
{x, {:s3, t}}
end
end
end)
|> elem(1)
|> elem(1)
String.split(file, "\n")
|> Enum.take(l1)
|> Enum.drop(l0)
|> Enum.split(p-1)
|> (fn {x, y} -> x ++ [d] ++ y end).()
|> Enum.join("\n")
|> Code.compile_string()
:ok
end
end
end