dhall 0.1.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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