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 Case
21
22 class Atom < Abstract
23 alias atom_value obj
24
25 def initialize(loc, atom_value)
26 ASSERT.kind_of atom_value, VCA::Abstract
27
28 super
29 end
30
31
32 def to_s
33 self.obj.to_s
34 end
35
36
37 def pretty_print(q)
38 self.obj.pretty_print(q)
39 end
40
41
42 def type_sym
43 :Atom
44 end
45
46
47 def desugar_for_rule(env, case_expr)
48 ASSERT.kind_of case_expr, Branch::Case
49
50 fst_head_value = self.atom_value
51 fst_head_type_sym = self.type_sym
52 fst_head_line_num = self.loc.line_num
53 fst_head_value_type_sym = self.atom_value.type_sym
54
55 leafs = case_expr.rules.inject({}) { |leafs, rule|
56 ASSERT.kind_of leafs, ::Hash
57 ASSERT.kind_of rule, Rule::Abstraction::Abstract
58
59 head = rule.head
60 ASSERT.kind_of head, Rule::Case::Abstract
61
62 head_type_sym = head.type_sym
63 head_line_num = head.loc.line_num
64 unless head.kind_of? Rule::Case::Atom
65 raise X::SyntaxError.new(
66 rule.loc,
67 format("Inconsistent rule categories " +
68 "in case-expression, " +
69 "1st is %s : %s(#%d), " +
70 "but another is %s : %s(#%d)",
71 __escape_string_format__(fst_head_value.to_s),
72 fst_head_type_sym.to_s,
73 fst_head_line_num + 1,
74 __escape_string_format__(head.to_s),
75 head_type_sym.to_s,
76 head_line_num + 1
77 )
78 )
79 end
80
81 head_value = head.atom_value
82 head_value_type_sym = head.atom_value.type_sym
83 ASSERT.kind_of head_value, VCA::Abstract
84 unless head_value.class == fst_head_value.class
85 raise X::SyntaxError.new(
86 rule.loc,
87 format("Inconsistent rule types in case-expression, " +
88 "1st is %s : %s(#%d), " +
89 "but another is %s : %s(#%d)",
90 __escape_string_format__(fst_head_value.to_s),
91 fst_head_value_type_sym.to_s,
92 fst_head_line_num + 1,
93 __escape_string_format__(head_value.to_s),
94 head_value_type_sym.to_s,
95 head_line_num + 1
96 )
97 )
98 end
99
100 body_expr = case_expr.desugar_body_expr env, rule
101
102 leafs.merge(head_value.val => body_expr) { |val, _, _|
103 raise X::SyntaxError.new(
104 rule.loc,
105 format("Duplicated rules in case-expression: %s : %s",
106 head_value.to_s,
107 head_value_type_sym.to_s
108 )
109 )
110 }
111 }
112
113 ASCE.make_switch(
114 case_expr.loc,
115 case_expr.expr.desugar(env),
116 fst_head_value.type_sym,
117 leafs,
118 case_expr.desugar_else_expr(env)
119 )
120 end
121 end
122
123 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch::Rule::Case
124
125 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch::Rule
126
127 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch
128
129 end # Umu::ConcreteSyntax::Core::Expression::Nary
130
131
132 module_function
133
134 def make_case_rule_atom(loc, atom_value)
135 ASSERT.kind_of loc, LOC::Entry
136 ASSERT.kind_of atom_value, VCA::Abstract
137
138 Nary::Branch::Rule::Case::Atom.new(
139 loc, atom_value
140 ).freeze
141 end
142
143 end # Umu::ConcreteSyntax::Core::Expression
144
145 end # Umu::ConcreteSyntax::Core
146
147 end # Umu::ConcreteSyntax
148
149 end # Umu