1 # coding: utf-8
2 # frozen_string_literal: true
3
4
5
6 module Umu
7
8 module Value
9
10 module Core
11
12 module Struct
13
14 class Field < ::Object
15 attr_reader :label, :value
16
17
18 def initialize(label, value)
19 ASSERT.kind_of label, ::Symbol
20 ASSERT.kind_of value, VC::Top
21
22 super()
23
24 @label = label
25 @value = value
26 end
27
28
29 def to_s
30 case self.value
31 when Entry
32 format "structure %s", self.label.to_s
33 when Fun
34 format "fun %s", self.label.to_s
35 else
36 format "val %s : %s", self.label.to_s, self.value.type_sym.to_s
37 end
38 end
39
40
41 def pretty_print(q)
42 case self.value
43 when Entry
44 q.text format(
45 "structure %s", self.label.to_s
46 )
47 when Fun
48 q.text format(
49 "fun %s", self.label.to_s
50 )
51 else
52 q.text format(
53 "val %s : %s", self.label.to_s, self.value.type_sym.to_s
54 )
55 end
56 end
57 end
58
59
60
61 class Entry < Top
62 TYPE_SYM = :Struct
63
64 include Enumerable
65
66 attr_reader :value_by_label
67
68
69 def initialize(value_by_label)
70 ASSERT.kind_of value_by_label, ::Hash
71
72 @value_by_label = value_by_label
73 end
74
75
76 def each
77 self.value_by_label.each do |label, value|
78 ASSERT.kind_of label, ::Symbol
79 ASSERT.kind_of value, VC::Top
80
81 yield VC.make_struct_field label, value
82 end
83 end
84
85
86 def to_s
87 format "struct {%s}", self.map(&:to_s).join(' ')
88 end
89
90
91 def pretty_print(q)
92 PRT.group_for_enum q, self, bb:'struct {', eb:'}', sep:' '
93 end
94
95
96 def select(sel_lab, loc, env)
97 ASSERT.kind_of sel_lab, ::Symbol
98 ASSERT.kind_of loc, LOC::Entry
99
100 value = self.value_by_label[sel_lab]
101 unless value
102 raise X::SelectionError.new(
103 loc,
104 env,
105 "Unknown selector label: '%s'", sel_lab
106 )
107 end
108
109 ASSERT.kind_of value, VC::Top
110 end
111 end
112
113 end # Umu::Value::Core::Struct
114
115
116 module_function
117
118 def make_struct_field(label, value)
119 ASSERT.kind_of label, ::Symbol
120 ASSERT.kind_of value, VC::Top
121
122 Struct::Field.new(label, value).freeze
123 end
124
125
126 def make_struct(value_by_label)
127 ASSERT.kind_of value_by_label, ::Hash
128
129 Struct::Entry.new(value_by_label.freeze).freeze
130 end
131
132 end # Umu::Value::Core
133
134 end # Umu::Value
135
136 end # Umu