1+ defmodule ElixirScript.Passes.HandleOverridables do
2+ @ moduledoc false
3+
4+ def execute ( compiler_data , opts ) do
5+ new_data = Enum . map ( compiler_data . data , fn { module_name , module_data } ->
6+ overridables = get_overridables ( module_data . ast )
7+ ast = handle_overridable ( module_data . ast , overridables )
8+ module_data = Map . put ( module_data , :ast , ast )
9+
10+ { module_name , module_data }
11+ end )
12+
13+ Map . put ( compiler_data , :data , new_data )
14+ end
15+
16+ defp get_overridables ( { :__block__ , [ ] , body } ) do
17+ defover = Enum . find ( body , fn
18+ { :defoverridable , _ , _ } ->
19+ true
20+ _ ->
21+ false
22+ end )
23+
24+ if is_nil ( defover ) do
25+ [ ]
26+ else
27+ { :defoverridable , _ , [ overridables ] } = defover
28+ overridables
29+ end
30+ end
31+
32+ defp handle_overridable ( ast , [ ] ) do
33+ ast
34+ end
35+
36+ defp handle_overridable ( { :__block__ , [ ] , body } , overridables ) do
37+ result = body
38+ |> Enum . reduce ( % { overridables: [ ] , overridable_found: false , body: [ ] } , fn
39+ { :def , def_context , [ { name , context , params } , function_body ] } = ast , % { overridable_found: false } = acc ->
40+ Map . put ( acc , :overridables , acc . overridables ++ [ ast ] )
41+
42+ { :defoverridable , _ , _ } , acc ->
43+ Map . put ( acc , :overridable_found , true )
44+ x , acc ->
45+ Map . put ( acc , :body , acc . body ++ [ x ] )
46+ end )
47+
48+ processed_overridables = Enum . map ( result . overridables , fn
49+ { :def , def_context , [ { name , context , params } , function_body ] } = ast ->
50+ arity = get_arity ( params )
51+
52+ found = Enum . any? ( result . body , fn
53+ { :def , _ , [ { name_from_body , _ , params_from_body } , _ ] } ->
54+ if { name , arity } == { name_from_body , get_arity ( params_from_body ) } do
55+ true
56+ else
57+ false
58+ end
59+ _ ->
60+ false
61+ end )
62+
63+ if found do
64+ super_name = String . to_atom ( "__super__" <> to_string ( name ) )
65+ { :defp , def_context , [ { super_name , context , params } , function_body ] }
66+ else
67+ ast
68+ end
69+ end )
70+
71+ body = processed_overridables ++ result . body
72+ { :__block__ , [ ] , body }
73+ end
74+
75+ defp get_arity ( params ) do
76+ cond do
77+ is_nil ( params ) ->
78+ 0
79+ is_atom ( params ) ->
80+ 0
81+ true ->
82+ length ( params )
83+ end
84+ end
85+
86+ end
0 commit comments