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 Nary
15
16 module Branch
17
18 module Rule
19
20 module Abstraction
21
22 class Abstract < Umu::Abstraction::Model
23 def line_num
24 self.loc.line_num
25 end
26
27
28 def desugar_poly_rule(_env)
29 raise X::InternalSubclassResponsibility
30 end
31 end
32
33
34
35 class HasHead < Abstract
36 attr_reader :head, :body_expr
37
38
39 def initialize(loc, head, body_expr)
40 ASSERT.kind_of head, Umu::Abstraction::Model
41 ASSERT.kind_of body_expr, CSCE::Abstract
42
43 super(loc)
44
45 @head = head
46 @body_expr = body_expr
47 end
48
49
50 def to_s
51 format "%s -> %s", self.head.to_s, self.body_expr.to_s
52 end
53
54
55 def pretty_print(q)
56 q.pp self.head
57 q.text ' -> '
58 q.pp self.body_expr
59 end
60 end
61
62 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch::Rule::Abstraction
63
64 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch::Rule
65
66
67
68 class Abstract < Expression::Abstract
69 attr_reader :expr, :fst_rule, :snd_rules, :opt_else_expr
70
71
72 def initialize(loc, expr, fst_rule, snd_rules, opt_else_expr)
73 ASSERT.kind_of expr, CSCE::Abstract
74 ASSERT.kind_of fst_rule,
75 CSCEN::Branch::Rule::Abstraction::Abstract
76 ASSERT.kind_of snd_rules, ::Array
77 ASSERT.opt_kind_of opt_else_expr, CSCE::Abstract
78
79 super(loc)
80
81 @expr = expr
82 @fst_rule = fst_rule
83 @snd_rules = snd_rules
84 @opt_else_expr = opt_else_expr
85 end
86
87
88 def to_s
89 format("%%%s %s %%OF { %s %s}",
90 __keyword__.upcase,
91
92 self.expr.to_s,
93
94 self.rules.map(&:to_s).join(' | '),
95 (
96 if self.opt_else_expr
97 format("%%ELSE -> %s", self.opt_else_expr.to_s)
98 else
99 ''
100 end
101 )
102 )
103 end
104
105
106 def pretty_print(q)
107 q.text format("%%%s ", __keyword__.upcase)
108 q.pp self.expr
109 q.text ' %OF {'
110
111 q.breakable
112
113 self.rules.each do |rule|
114 q.breakable
115
116 PRT.group q, bb:'| ' do
117 q.pp rule
118 end
119 end
120
121 if self.opt_else_expr
122 else_expr = self.opt_else_expr
123
124 q.breakable ' '
125
126 PRT.group q, bb:'%ELSE -> ' do
127 q.pp else_expr
128 end
129 end
130
131 q.breakable
132
133 q.text '}'
134 end
135
136
137 def rules
138 [self.fst_rule] + self.snd_rules
139 end
140
141
142 def desugar_body_expr(env, rule)
143 ASSERT.kind_of rule, Nary::Branch::Rule::Abstraction::HasHead
144
145 body_expr = rule.body_expr.desugar(env)
146
147 ASSERT.kind_of body_expr, ASCE::Abstract
148 end
149
150
151 def desugar_else_expr(env)
152 else_expr = if self.opt_else_expr
153 self.opt_else_expr.desugar(env)
154 else
155 ASCE.make_raise(
156 self.loc,
157 X::UnmatchError,
158 ASCE.make_string(self.loc, "No rules matched")
159 )
160 end
161
162 ASSERT.kind_of else_expr, ASCE::Abstract
163 end
164
165
166 private
167
168 def __keyword__
169 raise X::InternalSubclassResponsibility
170 end
171 end
172
173 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch
174
175 end # Umu::ConcreteSyntax::Core::Expression::Nary
176
177 end # Umu::ConcreteSyntax::Core::Expression
178
179 end # Umu::ConcreteSyntax::Core
180
181 end # Umu::ConcreteSyntax
182
183 end # Umu