dhall 0.1.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,9 +2,11 @@
2
2
 
3
3
  require "cbor"
4
4
  require "digest/sha2"
5
+ require "multihashes"
5
6
 
6
7
  require "dhall/ast"
7
8
  require "dhall/builtins"
9
+ require "dhall/parser"
8
10
 
9
11
  module Dhall
10
12
  def self.from_binary(cbor_binary)
@@ -34,10 +36,13 @@ module Dhall
34
36
  CBOR.encode(as_json)
35
37
  end
36
38
  end
37
- alias to_binary to_cbor
39
+
40
+ def to_binary
41
+ CBOR.encode(::CBOR::Tagged.new(55799, self))
42
+ end
38
43
 
39
44
  def digest(digest: Digest::SHA2.new(256))
40
- (digest << normalize.to_binary).freeze
45
+ (digest << normalize.to_cbor).freeze
41
46
  end
42
47
 
43
48
  def cache_key
@@ -80,15 +85,21 @@ module Dhall
80
85
 
81
86
  class List
82
87
  def self.decode(type, *els)
83
- type = type.nil? ? nil : Dhall.decode(type)
88
+ type = type.nil? ? nil : Builtins[:List].call(Dhall.decode(type))
84
89
  if els.empty?
85
- EmptyList.new(element_type: type)
90
+ EmptyList.new(type: type)
86
91
  else
87
- List.new(elements: els.map(&Dhall.method(:decode)), element_type: type)
92
+ List.new(elements: els.map(&Dhall.method(:decode)), type: type)
88
93
  end
89
94
  end
90
95
  end
91
96
 
97
+ class EmptyList
98
+ def self.decode(type)
99
+ EmptyList.new(type: Dhall.decode(type))
100
+ end
101
+ end
102
+
92
103
  class Optional
93
104
  def self.decode(type, value=nil)
94
105
  if value.nil?
@@ -102,6 +113,15 @@ module Dhall
102
113
  end
103
114
  end
104
115
 
116
+ class ToMap
117
+ def self.decode(record, type=nil)
118
+ new(
119
+ record: Dhall.decode(record),
120
+ type: type.nil? ? nil : Dhall.decode(type)
121
+ )
122
+ end
123
+ end
124
+
105
125
  class Merge
106
126
  def self.decode(record, input, type=nil)
107
127
  new(
@@ -140,10 +160,14 @@ module Dhall
140
160
 
141
161
  class RecordProjection
142
162
  def self.decode(record, *selectors)
143
- if selectors.empty?
144
- EmptyRecordProjection.new(record: Dhall.decode(record))
163
+ record = Dhall.decode(record)
164
+ if selectors.length == 1 && selectors[0].is_a?(Array)
165
+ RecordProjectionByExpression.new(
166
+ record: record,
167
+ selector: Dhall.decode(selectors[0][0])
168
+ )
145
169
  else
146
- new(record: Dhall.decode(record), selectors: selectors)
170
+ self.for(record, selectors)
147
171
  end
148
172
  end
149
173
  end
@@ -189,31 +213,79 @@ module Dhall
189
213
  end
190
214
  end
191
215
 
216
+ class Assertion
217
+ def self.decode(type)
218
+ new(type: Dhall.decode(type))
219
+ end
220
+ end
221
+
192
222
  class Import
223
+ class IntegrityCheck
224
+ def self.decode(integrity_check)
225
+ return unless integrity_check
226
+
227
+ IntegrityCheck.new(
228
+ Multihashes.decode(integrity_check).select { |k, _|
229
+ [:code, :digest].include?(k)
230
+ }
231
+ )
232
+ end
233
+ end
234
+
235
+ class URI
236
+ def self.decode(headers, authority, *path, query)
237
+ uri = ::URI.scheme_list[name.split(/::/).last.upcase].build(
238
+ Parser.parse(authority, root: :authority).value.merge(
239
+ path: "/#{path.join("/")}"
240
+ )
241
+ )
242
+ uri.instance_variable_set(:@query, query)
243
+ new(headers: headers, uri: uri)
244
+ end
245
+ end
246
+
247
+ class Path
248
+ def self.decode(*args)
249
+ new(*args)
250
+ end
251
+ end
252
+
253
+ class EnvironmentVariable
254
+ def self.decode(*args)
255
+ new(*args)
256
+ end
257
+ end
258
+
259
+ class MissingImport
260
+ def self.decode(*args)
261
+ new(*args)
262
+ end
263
+ end
264
+
193
265
  def self.decode(integrity_check, import_type, path_type, *parts)
194
266
  parts[0] = Dhall.decode(parts[0]) if path_type < 2 && !parts[0].nil?
195
- parts[0] = EnvironmentVariable.decode(parts[0]) if path_type == 6
267
+ path_type = PATH_TYPES.fetch(path_type)
196
268
 
197
269
  new(
198
- IntegrityCheck.new(*integrity_check),
270
+ IntegrityCheck.decode(integrity_check),
199
271
  IMPORT_TYPES[import_type],
200
- PATH_TYPES[path_type].new(*parts)
272
+ path_type.decode(*parts)
201
273
  )
202
274
  end
203
275
  end
204
276
 
205
- class LetBlock
277
+ class LetIn
206
278
  def self.decode(*parts)
207
279
  body = Dhall.decode(parts.pop)
208
- lets = parts.each_slice(3).map do |(var, type, assign)|
280
+ parts.each_slice(3).map { |(var, type, assign)|
209
281
  Let.new(
210
282
  var: var,
211
283
  assign: Dhall.decode(assign),
212
284
  type: type.nil? ? nil : Dhall.decode(type)
213
285
  )
286
+ }.reverse.reduce(body) do |inside, let|
287
+ LetIn.new(let: let, body: inside)
214
288
  end
215
-
216
- self.for(lets: lets, body: body)
217
289
  end
218
290
  end
219
291
 
@@ -223,13 +295,21 @@ module Dhall
223
295
  end
224
296
  end
225
297
 
298
+ def self.handle_tag(e)
299
+ return e unless e.is_a?(::CBOR::Tagged)
300
+ return e.value if e.tag == 55799
301
+
302
+ raise "Unknown tag: #{e.inspect}"
303
+ end
304
+
226
305
  BINARY = {
227
306
  ::TrueClass => ->(e) { Bool.new(value: e) },
228
307
  ::FalseClass => ->(e) { Bool.new(value: e) },
229
308
  ::Float => ->(e) { Double.new(value: e) },
230
- ::String => ->(e) { Builtins::ALL[e]&.new || Variable.new(name: e) },
309
+ ::String => ->(e) { Builtins[e.to_sym] || (raise "Unknown builtin") },
231
310
  ::Integer => ->(e) { Variable.new(index: e) },
232
311
  ::Array => lambda { |e|
312
+ e = e.map(&method(:handle_tag))
233
313
  if e.length == 2 && e.first.is_a?(::String)
234
314
  Variable.new(name: e[0], index: e[1])
235
315
  else
@@ -238,11 +318,7 @@ module Dhall
238
318
  (raise "Unknown expression: #{e.inspect}")
239
319
  end
240
320
  },
241
- ::CBOR::Tagged => lambda { |e|
242
- return Dhall.decode(e.value) if e.tag == 55799
243
-
244
- raise "Unknown tag: #{e.inspect}"
245
- }
321
+ ::CBOR::Tagged => ->(e) { Dhall.decode(handle_tag(e)) }
246
322
  }.freeze
247
323
 
248
324
  BINARY_TAGS = [
@@ -265,13 +341,15 @@ module Dhall
265
341
  Integer,
266
342
  nil,
267
343
  TextLiteral,
268
- nil,
344
+ Assertion,
269
345
  nil,
270
346
  nil,
271
347
  nil,
272
348
  nil,
273
349
  Import,
274
- LetBlock,
275
- TypeAnnotation
350
+ LetIn,
351
+ TypeAnnotation,
352
+ ToMap,
353
+ EmptyList
276
354
  ].freeze
277
355
  end
@@ -6,93 +6,74 @@ module Dhall
6
6
  class Builtin < Expression
7
7
  include(ValueSemantics.for_attributes {})
8
8
 
9
- def call(*args)
10
- # Do not auto-normalize builtins to avoid recursion loop
11
- args.reduce(self) do |f, arg|
9
+ def as_json
10
+ self.class.name&.split(/::/)&.last&.tr("_", "/").to_s
11
+ end
12
+ end
13
+
14
+ class BuiltinFunction < Builtin
15
+ include(ValueSemantics.for_attributes do
16
+ partial_application ArrayOf(Expression), default: []
17
+ end)
18
+
19
+ def unfill(*args)
20
+ (args.empty? ? partial_application : args).reduce(self.class.new) do |f, arg|
12
21
  Application.new(function: f, argument: arg)
13
22
  end
14
23
  end
15
24
 
16
- def unfill
17
- attributes.reduce(self.class.new) do |f, attr|
18
- if send(attr.name).nil?
19
- f
20
- else
21
- Application.new(function: f, argument: send(attr.name))
22
- end
25
+ def call(*new_args)
26
+ args = partial_application + new_args
27
+ if args.length == method(:uncurried_call).arity
28
+ uncurried_call(*args)
29
+ else
30
+ with(partial_application: args)
23
31
  end
24
32
  end
25
33
 
26
34
  def as_json
27
- if (unfilled = unfill).class != self.class
35
+ if (unfilled = unfill) != self
28
36
  unfilled.as_json
29
37
  else
30
- self.class.name&.split(/::/)&.last&.tr("_", "/").to_s
38
+ super
31
39
  end
32
40
  end
41
+ end
33
42
 
34
- protected
43
+ module Builtins
44
+ # rubocop:disable Style/ClassAndModuleCamelCase
35
45
 
36
- def attributes
37
- self.class.value_semantics.attributes
38
- end
46
+ class Double_show < BuiltinFunction
47
+ protected
39
48
 
40
- def fill_next_if_valid(value)
41
- with(attributes.each_with_object({}) do |attr, h|
42
- if !send(attr.name).nil?
43
- h[attr.name] = send(attr.name)
44
- elsif attr.validate?(value)
45
- h[attr.name] = value
46
- value = nil
47
- else
48
- return nil
49
- end
50
- end)
51
- end
49
+ def uncurried_call(arg)
50
+ return unfill(arg) unless arg.is_a?(Dhall::Double)
52
51
 
53
- def full?
54
- attributes.all? { |attr| !send(attr.name).nil? }
52
+ Dhall::Text.new(value: arg.to_s)
53
+ end
55
54
  end
56
55
 
57
- def fill_or_call(arg, &block)
58
- full? ? block[arg] : fill_next_if_valid(arg)
59
- end
60
- end
56
+ class Integer_show < BuiltinFunction
57
+ protected
61
58
 
62
- module Builtins
63
- # rubocop:disable Style/ClassAndModuleCamelCase
59
+ def uncurried_call(arg)
60
+ return unfill(arg) unless arg.is_a?(Dhall::Integer)
64
61
 
65
- class Double_show < Builtin
66
- def call(arg)
67
- if arg.is_a?(Double)
68
- Text.new(value: arg.to_s)
69
- else
70
- super
71
- end
62
+ Dhall::Text.new(value: arg.to_s)
72
63
  end
73
64
  end
74
65
 
75
- class Integer_show < Builtin
76
- def call(arg)
77
- if arg.is_a?(Integer)
78
- Text.new(value: arg.to_s)
79
- else
80
- super
81
- end
82
- end
83
- end
66
+ class Integer_toDouble < BuiltinFunction
67
+ protected
84
68
 
85
- class Integer_toDouble < Builtin
86
- def call(arg)
87
- if arg.is_a?(Integer)
88
- Double.new(value: arg.value.to_f)
89
- else
90
- super
91
- end
69
+ def uncurried_call(arg)
70
+ return unfill(arg) unless arg.is_a?(Dhall::Integer)
71
+
72
+ Dhall::Double.new(value: arg.value.to_f)
92
73
  end
93
74
  end
94
75
 
95
- class Natural_build < Builtin
76
+ class Natural_build < BuiltinFunction
96
77
  def fusion(arg, *bogus)
97
78
  if bogus.empty? &&
98
79
  arg.is_a?(Application) &&
@@ -103,91 +84,105 @@ module Dhall
103
84
  end
104
85
  end
105
86
 
106
- def call(arg)
87
+ protected
88
+
89
+ def uncurried_call(arg)
107
90
  arg.call(
108
- Variable.new(name: "Natural"),
91
+ Natural.new,
109
92
  Function.of_arguments(
110
- Variable.new(name: "Natural"),
111
- body: Variable["_"] + Natural.new(value: 1)
93
+ Natural.new,
94
+ body: Variable["_"] + Dhall::Natural.new(value: 1)
112
95
  ),
113
- Natural.new(value: 0)
96
+ Dhall::Natural.new(value: 0)
114
97
  )
115
98
  end
116
99
  end
117
100
 
118
- class Natural_even < Builtin
119
- def call(nat)
120
- if nat.is_a?(Natural)
121
- Bool.new(value: nat.even?)
122
- else
123
- super
101
+ class Natural_subtract < BuiltinFunction
102
+ protected
103
+
104
+ def uncurried_call(x, y)
105
+ return y if zero?(x) || zero?(y)
106
+
107
+ return Dhall::Natural.new(value: 0) if x == y
108
+
109
+ unless x.is_a?(Dhall::Natural) && y.is_a?(Dhall::Natural)
110
+ return unfill(x, y)
124
111
  end
112
+
113
+ Dhall::Natural.new(value: [y.to_i - x.to_i, 0].max)
114
+ end
115
+
116
+ def zero?(x)
117
+ Natural_isZero.new.call(x) === true
125
118
  end
126
119
  end
127
120
 
128
- class Natural_fold < Builtin
129
- include(ValueSemantics.for_attributes do
130
- nat Either(nil, Natural), default: nil
131
- type Either(nil, Expression), default: nil
132
- f Either(nil, Expression), default: nil
133
- end)
121
+ class Natural_even < BuiltinFunction
122
+ protected
134
123
 
135
- def call(arg)
136
- fill_or_call(arg) do
137
- if @nat.zero?
138
- arg.normalize
139
- else
140
- @f.call(with(nat: nat.pred).call(arg))
141
- end
142
- end || super
124
+ def uncurried_call(nat)
125
+ return unfill(nat) unless nat.is_a?(Dhall::Natural)
126
+
127
+ Dhall::Bool.new(value: nat.even?)
143
128
  end
144
129
  end
145
130
 
146
- class Natural_isZero < Builtin
147
- def call(nat)
148
- if nat.is_a?(Natural)
149
- Bool.new(value: nat.zero?)
131
+ class Natural_fold < BuiltinFunction
132
+ protected
133
+
134
+ def uncurried_call(nat, type, f, z)
135
+ return unfill(nat, type, f, z) unless nat.is_a?(Dhall::Natural)
136
+
137
+ if nat.zero?
138
+ z.normalize
150
139
  else
151
- super
140
+ f.call(Natural_fold.new.call(nat.pred, type, f, z))
152
141
  end
153
142
  end
154
143
  end
155
144
 
156
- class Natural_odd < Builtin
157
- def call(nat)
158
- if nat.is_a?(Natural)
159
- Bool.new(value: nat.odd?)
160
- else
161
- super
162
- end
145
+ class Natural_isZero < BuiltinFunction
146
+ protected
147
+
148
+ def uncurried_call(nat)
149
+ return unfill(nat) unless nat.is_a?(Dhall::Natural)
150
+
151
+ Dhall::Bool.new(value: nat.zero?)
163
152
  end
164
153
  end
165
154
 
166
- class Natural_show < Builtin
167
- def call(nat)
168
- if nat.is_a?(Natural)
169
- Text.new(value: nat.to_s)
170
- else
171
- super
172
- end
155
+ class Natural_odd < BuiltinFunction
156
+ protected
157
+
158
+ def uncurried_call(nat)
159
+ return unfill(nat) unless nat.is_a?(Dhall::Natural)
160
+
161
+ Dhall::Bool.new(value: nat.odd?)
173
162
  end
174
163
  end
175
164
 
176
- class Natural_toInteger < Builtin
177
- def call(nat)
178
- if nat.is_a?(Natural)
179
- Integer.new(value: nat.value)
180
- else
181
- super
182
- end
165
+ class Natural_show < BuiltinFunction
166
+ protected
167
+
168
+ def uncurried_call(nat)
169
+ return unfill(nat) unless nat.is_a?(Dhall::Natural)
170
+
171
+ Dhall::Text.new(value: nat.to_s)
183
172
  end
184
173
  end
185
174
 
186
- class List_build < Builtin
187
- include(ValueSemantics.for_attributes do
188
- type Either(nil, Expression), default: nil
189
- end)
175
+ class Natural_toInteger < BuiltinFunction
176
+ protected
177
+
178
+ def uncurried_call(nat)
179
+ return unfill(nat) unless nat.is_a?(Dhall::Natural)
190
180
 
181
+ Dhall::Integer.new(value: nat.value)
182
+ end
183
+ end
184
+
185
+ class List_build < BuiltinFunction
191
186
  def fusion(*args)
192
187
  _, arg, = args
193
188
  if arg.is_a?(Application) &&
@@ -199,80 +194,55 @@ module Dhall
199
194
  end
200
195
  end
201
196
 
202
- def call(arg)
203
- fill_or_call(arg) do
204
- arg.call(
205
- Variable["List"].call(type),
206
- cons,
207
- EmptyList.new(element_type: type)
208
- )
209
- end
210
- end
211
-
212
197
  protected
213
198
 
214
- def cons
199
+ def uncurried_call(type, arg)
200
+ arg.call(
201
+ List.new.call(type),
202
+ cons(type),
203
+ EmptyList.new(element_type: type)
204
+ )
205
+ end
206
+
207
+ def cons(type)
215
208
  Function.of_arguments(
216
209
  type,
217
- Variable["List"].call(type.shift(1, "_", 0)),
218
- body: List.of(Variable["_", 1]).concat(Variable["_"])
210
+ List.new.call(type.shift(1, "_", 0)),
211
+ body: Dhall::List.of(Variable["_", 1]).concat(Variable["_"])
219
212
  )
220
213
  end
221
214
  end
222
215
 
223
- class List_fold < Builtin
224
- include(ValueSemantics.for_attributes do
225
- ltype Either(nil, Expression), default: nil
226
- list Either(nil, List), default: nil
227
- ztype Either(nil, Expression), default: nil
228
- f Either(nil, Expression), default: nil
229
- end)
230
-
231
- def call(arg)
232
- fill_or_call(arg) do
233
- list.reduce(arg, &f).normalize
234
- end || super
235
- end
236
- end
216
+ class List_fold < BuiltinFunction
217
+ protected
237
218
 
238
- class List_head < Builtin
239
- include(ValueSemantics.for_attributes do
240
- type Either(nil, Expression), default: nil
241
- end)
219
+ def uncurried_call(ltype, list, ztype, f, z)
220
+ return unfill(ltype, list, ztype, f, z) unless list.is_a?(Dhall::List)
242
221
 
243
- def call(arg)
244
- fill_or_call(arg) do
245
- if arg.is_a?(List)
246
- arg.first
247
- else
248
- super
249
- end
250
- end
222
+ list.reduce(z, &f).normalize
251
223
  end
252
224
  end
253
225
 
254
- class List_indexed < Builtin
255
- include(ValueSemantics.for_attributes do
256
- type Either(nil, Expression), default: nil
257
- end)
226
+ class List_head < BuiltinFunction
227
+ protected
258
228
 
259
- def call(arg)
260
- fill_or_call(arg) do
261
- if arg.is_a?(List)
262
- _call(arg)
263
- else
264
- super
265
- end
266
- end
229
+ def uncurried_call(type, list)
230
+ return unfill(type, list) unless list.is_a?(Dhall::List)
231
+
232
+ list.first
267
233
  end
234
+ end
268
235
 
236
+ class List_indexed < BuiltinFunction
269
237
  protected
270
238
 
271
- def _call(arg)
272
- arg.map(type: indexed_type(type)) { |x, idx|
239
+ def uncurried_call(type, list)
240
+ return unfill(type, list) unless list.is_a?(Dhall::List)
241
+
242
+ list.map(type: indexed_type(type)) { |x, idx|
273
243
  Record.new(
274
244
  record: {
275
- "index" => Natural.new(value: idx),
245
+ "index" => Dhall::Natural.new(value: idx),
276
246
  "value" => x
277
247
  }
278
248
  )
@@ -282,66 +252,44 @@ module Dhall
282
252
  def indexed_type(value_type)
283
253
  RecordType.new(
284
254
  record: {
285
- "index" => Variable.new(name: "Natural"),
255
+ "index" => Natural.new,
286
256
  "value" => value_type
287
257
  }
288
258
  )
289
259
  end
290
260
  end
291
261
 
292
- class List_last < Builtin
293
- include(ValueSemantics.for_attributes do
294
- type Either(nil, Expression), default: nil
295
- end)
262
+ class List_last < BuiltinFunction
263
+ protected
296
264
 
297
- def call(arg)
298
- fill_or_call(arg) do
299
- if arg.is_a?(List)
300
- arg.last
301
- else
302
- super
303
- end
304
- end
265
+ def uncurried_call(type, list)
266
+ return unfill(type, list) unless list.is_a?(Dhall::List)
267
+
268
+ list.last
305
269
  end
306
270
  end
307
271
 
308
- class List_length < Builtin
309
- include(ValueSemantics.for_attributes do
310
- type Either(nil, Expression), default: nil
311
- end)
272
+ class List_length < BuiltinFunction
273
+ protected
312
274
 
313
- def call(arg)
314
- fill_or_call(arg) do
315
- if arg.is_a?(List)
316
- Natural.new(value: arg.length)
317
- else
318
- super
319
- end
320
- end
275
+ def uncurried_call(type, list)
276
+ return unfill(type, list) unless list.is_a?(Dhall::List)
277
+
278
+ Dhall::Natural.new(value: list.length)
321
279
  end
322
280
  end
323
281
 
324
- class List_reverse < Builtin
325
- include(ValueSemantics.for_attributes do
326
- type Either(nil, Expression), default: nil
327
- end)
282
+ class List_reverse < BuiltinFunction
283
+ protected
328
284
 
329
- def call(arg)
330
- fill_or_call(arg) do
331
- if arg.is_a?(List)
332
- arg.reverse
333
- else
334
- super
335
- end
336
- end
285
+ def uncurried_call(type, list)
286
+ return unfill(type, list) unless list.is_a?(Dhall::List)
287
+
288
+ list.reverse
337
289
  end
338
290
  end
339
291
 
340
- class Optional_build < Builtin
341
- include(ValueSemantics.for_attributes do
342
- type Either(nil, Expression), default: nil
343
- end)
344
-
292
+ class Optional_build < BuiltinFunction
345
293
  def fusion(*args)
346
294
  _, arg, = args
347
295
  if arg.is_a?(Application) &&
@@ -353,22 +301,20 @@ module Dhall
353
301
  end
354
302
  end
355
303
 
356
- def call(arg)
357
- fill_or_call(arg) do
358
- arg.call(
359
- Variable["Optional"].call(type),
360
- some,
361
- OptionalNone.new(value_type: type)
362
- )
363
- end
364
- end
365
-
366
304
  protected
367
305
 
368
- def some
306
+ def uncurried_call(type, f)
307
+ f.call(
308
+ Optional.new.call(type),
309
+ some(type),
310
+ OptionalNone.new(value_type: type)
311
+ )
312
+ end
313
+
314
+ def some(type)
369
315
  Function.of_arguments(
370
316
  type,
371
- body: Optional.new(
317
+ body: Dhall::Optional.new(
372
318
  value: Variable["_"],
373
319
  value_type: type
374
320
  )
@@ -376,24 +322,19 @@ module Dhall
376
322
  end
377
323
  end
378
324
 
379
- class Optional_fold < Builtin
380
- include(ValueSemantics.for_attributes do
381
- type Either(nil, Expression), default: nil
382
- optional Either(nil, Optional), default: nil
383
- ztype Either(nil, Expression), default: nil
384
- f Either(nil, Expression), default: nil
385
- end)
325
+ class Optional_fold < BuiltinFunction
326
+ protected
386
327
 
387
- def call(*args)
388
- args.reduce(self) do |fold, arg|
389
- fold.fill_or_call(arg) do
390
- fold.optional.reduce(arg, &fold.f)
391
- end || super
328
+ def uncurried_call(type, optional, ztype, f, z)
329
+ unless optional.is_a?(Dhall::Optional)
330
+ return unfill(type, optional, ztype, f, z)
392
331
  end
332
+
333
+ optional.reduce(z, &f)
393
334
  end
394
335
  end
395
336
 
396
- class Text_show < Builtin
337
+ class Text_show < BuiltinFunction
397
338
  ENCODE = (Hash.new { |_, x| "\\u%04x" % x.ord }).merge(
398
339
  "\"" => "\\\"",
399
340
  "\\" => "\\\\",
@@ -404,22 +345,61 @@ module Dhall
404
345
  "\t" => "\\t"
405
346
  )
406
347
 
348
+ protected
349
+
350
+ def uncurried_call(text)
351
+ return unfill(text) unless text.is_a?(Dhall::Text)
352
+
353
+ Dhall::Text.new(
354
+ value: "\"#{text.to_s.gsub(
355
+ /["\$\\\b\f\n\r\t\u0000-\u001F]/,
356
+ &ENCODE
357
+ )}\""
358
+ )
359
+ end
360
+ end
361
+
362
+ class Bool < Builtin
363
+ end
364
+
365
+ class Optional < Builtin
366
+ end
367
+
368
+ class Natural < Builtin
369
+ end
370
+
371
+ class Integer < Builtin
372
+ end
373
+
374
+ class Double < Builtin
375
+ end
376
+
377
+ class Text < Builtin
378
+ end
379
+
380
+ class List < Builtin
381
+ end
382
+
383
+ class None < Builtin
407
384
  def call(arg)
408
- if arg.is_a?(Text)
409
- Text.new(
410
- value: "\"#{arg.value.gsub(
411
- /["\$\\\b\f\n\r\t\u0000-\u001F]/,
412
- &ENCODE
413
- )}\""
414
- )
415
- else
416
- super
417
- end
385
+ OptionalNone.new(value_type: arg)
418
386
  end
419
387
  end
420
388
 
389
+ class Type < Builtin
390
+ end
391
+
392
+ class Kind < Builtin
393
+ end
394
+
395
+ class Sort < Builtin
396
+ end
397
+
421
398
  # rubocop:enable Style/ClassAndModuleCamelCase
422
399
 
423
- ALL = Hash[constants.map { |c| [c.to_s.tr("_", "/"), const_get(c)] }]
400
+ def self.[](k)
401
+ const = constants.find { |c| c.to_s.tr("_", "/").to_sym == k }
402
+ const && const_get(const).new
403
+ end
424
404
  end
425
405
  end