1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module ConcreteSyntax
9
10 module Core
11
12 module Expression
13
14 module SExpression
15
16 class Abstract < Expression::Abstract
17 end
18
19
20
21 class Nil < Abstract
22 def to_s
23 '()'
24 end
25
26
27 private
28
29 def __desugar__(_env, _event)
30 ASCE.make_s_expr_nil self.loc
31 end
32 end
33
34
35
36 class Atom < Abstract
37 attr_reader :atom_val
38
39 def initialize(loc, atom_val)
40 ASSERT.kind_of atom_val, ::Object
41
42 super(loc)
43
44 @atom_val = atom_val
45 end
46
47
48 def to_s
49 self.atom_val.to_s
50 end
51
52
53 private
54
55 def __desugar__(env, event)
56 ASCE.make_s_expr_atom self.loc, self.atom_val
57 end
58 end
59
60
61
62 class Embeded < Abstract
63 attr_reader :expr
64
65 def initialize(loc, expr)
66 ASSERT.kind_of expr, CSCE::Abstract
67
68 super(loc)
69
70 @expr = expr
71 end
72
73
74 def to_s
75 self.expr.to_s
76 end
77
78
79 def pretty_print(q)
80 q.pp self.expr
81 end
82
83
84 private
85
86 def __desugar__(env, event)
87 ASCE.make_s_expr_embeded self.loc, self.expr.desugar(env)
88 end
89 end
90
91
92
93 class List < Abstract
94 attr_reader :fst_expr, :snd_exprs, :opt_expr
95
96 def initialize(loc, fst_expr, snd_exprs, opt_expr)
97 ASSERT.kind_of fst_expr, SExpression::Abstract
98 ASSERT.kind_of snd_exprs, ::Array
99 ASSERT.opt_kind_of opt_expr, SExpression::Abstract
100 snd_exprs.each do |expr|
101 ASSERT.kind_of expr, SExpression::Abstract
102 end
103
104 super(loc)
105
106 @fst_expr = fst_expr
107 @snd_exprs = snd_exprs
108 @opt_expr = opt_expr
109 end
110
111
112 def exprs
113 [self.fst_expr] + self.snd_exprs
114 end
115
116
117 def to_s
118 format("%%S(%s%s)",
119 self.exprs.map(&:to_s).join(' '),
120
121 if self.opt_expr
122 format " . %s", self.opt_expr.to_s
123 else
124 ''
125 end
126 )
127 end
128
129
130 def pretty_print(q)
131 PRT.group_for_enum q, self.exprs, bb:'%S(', join:' '
132
133 q.breakable
134
135 if self.opt_expr
136 PRT.group q, bb:'.', sep:' ' do
137 q.pp self.opt_expr
138 end
139 end
140 q.text ')'
141 end
142
143
144 private
145
146 def __desugar__(env, event)
147 ASCE.make_s_expr_list(
148 self.loc,
149
150 self.fst_expr.desugar(env),
151
152 self.snd_exprs.map { |expr| expr.desugar(env) },
153
154 if self.opt_expr
155 self.opt_expr.desugar(env)
156 else
157 nil
158 end
159 )
160 end
161 end
162
163 end # Umu::ConcreteSyntax::Core::Expression::SExpression
164
165
166 module_function
167
168 def make_s_expr_nil(loc)
169 ASSERT.kind_of loc, LOC::Entry
170
171 SExpression::Nil.new(loc).freeze
172 end
173
174
175 def make_s_expr_int(loc, val)
176 ASSERT.kind_of loc, LOC::Entry
177 ASSERT.kind_of val, ::Integer
178
179 SExpression::Atom.new(
180 loc, VC.make_integer(val)
181 ).freeze
182 end
183
184
185 def make_s_expr_float(loc, val)
186 ASSERT.kind_of loc, LOC::Entry
187 ASSERT.kind_of val, ::Float
188
189 SExpression::Atom.new(
190 loc, VC.make_float(val)
191 ).freeze
192 end
193
194
195 def make_s_expr_string(loc, val)
196 ASSERT.kind_of loc, LOC::Entry
197 ASSERT.kind_of val, ::String
198
199 SExpression::Atom.new(
200 loc, VC.make_symbol(val.to_sym)
201 ).freeze
202 end
203
204
205 def make_s_expr_symbol(loc, sym)
206 ASSERT.kind_of loc, LOC::Entry
207 ASSERT.kind_of sym, ::Symbol
208
209 SExpression::Atom.new(
210 loc, VC.make_symbol(sym)
211 ).freeze
212 end
213
214
215 def make_s_expr_embeded(loc, expr)
216 ASSERT.kind_of loc, LOC::Entry
217 ASSERT.kind_of expr, CSCE::Abstract
218
219 SExpression::Embeded.new(loc, expr).freeze
220 end
221
222
223 def make_s_expr_list(loc, fst_expr, snd_exprs, opt_expr = nil)
224 ASSERT.kind_of loc, LOC::Entry
225 ASSERT.kind_of fst_expr, SExpression::Abstract
226 ASSERT.kind_of snd_exprs, ::Array
227 ASSERT.opt_kind_of opt_expr, SExpression::Abstract
228
229 SExpression::List.new(
230 loc, fst_expr, snd_exprs.freeze, opt_expr
231 ).freeze
232 end
233
234 end # Umu::ConcreteSyntax::Core::Expression
235
236 end # Umu::ConcreteSyntax::Core
237
238 end # Umu::ConcreteSyntax
239
240 end # Umu