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 class Cond < Abstraction::HasHead
21 alias head_expr head
22 end
23
24 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch::Rule
25
26
27
28 class Cond < Abstract
29
30 private
31
32 def __keyword__
33 'cond'
34 end
35
36
37 def __desugar__(env, event)
38 new_env = env.enter event
39
40 opnd_expr = self.expr.desugar(new_env)
41 ASSERT.kind_of opnd_expr, ASCE::Abstract
42 if opnd_expr.simple? || self.rules.size <= 1
43 rules = __desugar_rules__(env) { |_| opnd_expr }
44
45 ASCE.make_if self.loc, rules, self.desugar_else_expr(new_env)
46 else
47 ASCE.make_let(
48 self.loc,
49
50 ASCD.make_seq_of_declaration(
51 opnd_expr.loc,
52 [ASCD.make_value(opnd_expr.loc, :'%x', opnd_expr)]
53 ),
54
55 ASCE.make_if(
56 self.loc,
57 __desugar_rules__(env) { |loc|
58 ASCE.make_identifier loc, :'%x'
59 },
60 self.desugar_else_expr(new_env)
61 )
62 )
63 end
64 end
65
66
67 def __desugar_rules__(env, &fn)
68 self.rules.map { |rule|
69 ASSERT.kind_of rule, Rule::Cond
70
71 opr_expr = rule.head_expr.desugar env
72 head_expr = ASCE.make_apply(
73 rule.loc, opr_expr, fn.call(rule.loc)
74 )
75 body_expr = self.desugar_body_expr env, rule
76
77 ASCE.make_rule rule.loc, head_expr, body_expr
78 }
79 end
80 end
81
82 end # Umu::ConcreteSyntax::Core::Expression::Nary::Branch
83
84 end # Umu::ConcreteSyntax::Core::Expression::Nary
85
86
87 module_function
88
89 def make_cond_rule(loc, head_expr, body_expr)
90 ASSERT.kind_of loc, LOC::Entry
91 ASSERT.kind_of head_expr, CSCE::Abstract
92 ASSERT.kind_of body_expr, CSCE::Abstract
93
94 Nary::Branch::Rule::Cond.new(loc, head_expr, body_expr).freeze
95 end
96
97
98 def make_cond(loc, expr, fst_rule, snd_rules, opt_else_expr)
99 ASSERT.kind_of loc, LOC::Entry
100 ASSERT.kind_of expr, CSCE::Abstract
101 ASSERT.kind_of fst_rule, CSCEN::Branch::Rule::Cond
102 ASSERT.kind_of snd_rules, ::Array
103 ASSERT.opt_kind_of opt_else_expr, CSCE::Abstract
104
105 Nary::Branch::Cond.new(
106 loc, expr, fst_rule, snd_rules, opt_else_expr
107 ).freeze
108 end
109
110 end # Umu::ConcreteSyntax::Core::Expression
111
112 end # Umu::ConcreteSyntax::Core
113
114 end # Umu::ConcreteSyntax
115
116 end # Umu