1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module ConcreteSyntax
9
10 module Module
11
12 module Expression
13
14 class Struct < Expression::Abstract
15 attr_reader :body_decls
16
17
18 def initialize(loc, body_decls)
19 ASSERT.kind_of body_decls, ::Array
20
21 super(loc)
22
23 @body_decls = body_decls
24 end
25
26
27 def to_s
28 format("%%STRUCT {%s}",
29 if self.body_decls.empty?
30 ' '
31 else
32 self.body_decls.map(&:to_s).join(' ')
33 end
34 )
35 end
36
37
38 def pretty_print(q)
39 PRT.group_for_enum(
40 q, self.body_decls, bb:'%STRUCT {', eb:'}', sep:' '
41 ) do |decl| q.pp decl end
42 end
43
44
45 private
46
47 def __desugar__(env, event)
48 expr_by_label = (
49 self.body_decls.inject([]) {
50 |array, decl|
51 ASSERT.kind_of array, ::Array
52 ASSERT.kind_of decl, Declaration::Abstract
53
54 array + decl.exported_vars
55 }.inject({}) { |hash, vpat|
56 ASSERT.kind_of hash, ::Hash
57 ASSERT.kind_of vpat, CSCP::ElementOfContainer::Variable
58
59 label = vpat.var_sym
60 expr = ASCE.make_identifier(vpat.loc, vpat.var_sym)
61
62 hash.merge(label => expr) { |_lab, _old_expr, new_expr|
63 new_expr
64 }
65 }
66 )
67
68 expr = ASCE.make_struct self.loc, expr_by_label
69
70 if self.body_decls.empty?
71 expr
72 else
73 new_env = env.enter event
74
75 ASCE.make_let(
76 self.loc,
77
78 ASCD.make_seq_of_declaration(
79 self.loc,
80 self.body_decls.map { |decl| decl.desugar new_env }
81 ),
82
83 expr
84 )
85 end
86 end
87 end
88
89
90 module_function
91
92 def make_struct(loc, body_decls)
93 ASSERT.kind_of loc, LOC::Entry
94 ASSERT.kind_of body_decls, ::Array
95
96 Struct.new(loc, body_decls.freeze).freeze
97 end
98
99 end # Umu::ConcreteSyntax::Module::Expression
100
101 end # Umu::ConcreteSyntax::Module
102
103 end # Umu::ConcreteSyntax
104
105 end # Umu