1+ require " ./template/*"
2+
13module Bindgen
24 # Conversion templates for `Call::Result`. They govern how a call result's
35 # code should be transformed to become usable under a certain platform.
@@ -12,116 +14,5 @@ module Bindgen
1214 Basic .new(pattern, simple: simple)
1315 end
1416 end
15-
16- # Base class of the templates.
17- abstract class Base
18- # Performs a template substitution.
19- abstract def template (code : String ) : String
20-
21- # Is this a no-operation template?
22- def no_op ?
23- {{ @type == Bindgen ::Template ::None }}
24- end
25-
26- # Combines two templates into one. The *other* template is run after the
27- # current template.
28- def followed_by (other : Base ) : Base
29- return other if no_op?
30- return self if other.no_op?
31- Sequence .new(self , other)
32- end
33- end
34-
35- # The no-op template that returns *code* unmodified.
36- class None < Base
37- def template (code ) : String
38- code
39- end
40-
41- def == (_other : self )
42- true
43- end
44- end
45-
46- # The default template. Uses `Util.template` to substitute *code* into the
47- # given *pattern*.
48- #
49- # If *simple* is given, the template will only use a subset of the features;
50- # `%` performs substitution, whereas the escape sequence `%%` outputs a
51- # literal percent sign.
52- class Basic < Base
53- def initialize (@pattern : String , @simple = false )
54- end
55-
56- def template (code ) : String
57- if @simple
58- @pattern .gsub(/%+/ ) do |m |
59- literals = " %" * (m.size // 2 )
60- out_code = code if m.size % 2 == 1
61- " #{ literals } #{ out_code } "
62- end
63- else
64- Util .template(@pattern , code)
65- end
66- end
67-
68- def_equals @pattern , @simple
69- end
70-
71- # Compound template which runs *code* through multiple child templater, in
72- # the order they are given in the constructor.
73- class Sequence < Base
74- getter children = Array (Base ).new
75-
76- def initialize (* conversions : Base )
77- conversions.each do |conversion |
78- # Flatten `Sequence` templates automatically.
79- if conversion.is_a?(Sequence )
80- @children .concat(conversion.children)
81- else
82- @children << conversion
83- end
84- end
85- end
86-
87- def template (code ) : String
88- @children .each do |conversion |
89- code = conversion.template(code)
90- end
91-
92- code
93- end
94-
95- def_equals @children
96- end
97-
98- # Template to transform `Proc`s for Crystal wrapper types into `Proc`
99- # expressions for binding types.
100- class ProcFromWrapper < Base
101- def initialize (@proc_type : Parser ::Type , @db : TypeDatabase )
102- end
103-
104- def template (code ) : String
105- args = @proc_type .template.not_nil!.arguments
106- func_args = args[1 ..- 1 ].map_with_index do |type , i |
107- Parser ::Argument .new(" arg#{ i } " , type )
108- end
109- proc_call = Parser ::Method .build(
110- name: " call" ,
111- return_type: args.first,
112- arguments: func_args,
113- class_name: " Proc" ,
114- )
115-
116- # The templated code shouldn't contain braces, since an outer template
117- # that comes from a config file might treat the code block as an
118- # environment variable.
119- builder = CallBuilder ::CrystalFromCpp .new(@db )
120- call = builder.build(proc_call, receiver: " _proc_" , do_block: true )
121- call.body.to_code(call, Graph ::Platform ::Crystal )
122- end
123-
124- def_equals @proc_type , @db
125- end
12617 end
12718end
0 commit comments