dhall 0.1.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -21,23 +21,21 @@ module Dhall
21
21
 
22
22
  module Expression
23
23
  def value
24
- key =
25
- [:let_binding, :lambda, :forall, :arrow, :if, :merge]
26
- .find { |k| captures.key?(k) }
27
-
28
- return public_send(key) if key
24
+ return list if string =~ /\A\[\s*\]/
29
25
 
30
26
  key =
31
- [:empty_collection, :non_empty_optional]
27
+ [:let_binding, :lambda, :forall, :arrow, :if, :merge, :tomap, :assert]
32
28
  .find { |k| captures.key?(k) }
33
- key ? capture(key).value : super
29
+
30
+ key ? public_send(key) : super
34
31
  end
35
32
 
36
33
  def let_binding
37
- LetBlock.for(
38
- lets: captures(:let_binding).map(&:value),
39
- body: capture(:expression).value
40
- )
34
+ captures(:let_binding).reverse.reduce(
35
+ capture(:expression).value
36
+ ) do |inside, let|
37
+ LetIn.new(let: let.value, body: inside)
38
+ end
41
39
  end
42
40
 
43
41
  def lambda
@@ -78,6 +76,21 @@ module Dhall
78
76
  type: capture(:application_expression)&.value
79
77
  )
80
78
  end
79
+
80
+ def list
81
+ EmptyList.new(type: capture(:application_expression).value)
82
+ end
83
+
84
+ def tomap
85
+ ToMap.new(
86
+ record: capture(:import_expression).value,
87
+ type: capture(:application_expression).value
88
+ )
89
+ end
90
+
91
+ def assert
92
+ Assertion.new(type: capture(:expression).value)
93
+ end
81
94
  end
82
95
 
83
96
  OPERATORS = {
@@ -92,7 +105,8 @@ module Dhall
92
105
  combine_types_expression: :RecursiveRecordTypeMerge,
93
106
  times_expression: :Times,
94
107
  equal_expression: :Equal,
95
- not_equal_expression: :NotEqual
108
+ not_equal_expression: :NotEqual,
109
+ equivalent_expression: :Equivalent
96
110
  }.freeze
97
111
 
98
112
  OPERATORS.to_a.zip(
@@ -109,22 +123,44 @@ module Dhall
109
123
 
110
124
  module ApplicationExpression
111
125
  def value
112
- some = capture(:some) ? [Variable["Some"]] : []
113
- els = some + captures(:import_expression).map(&:value)
126
+ first_expr = [capture(:first_application_expression).value]
127
+ els = first_expr + captures(:import_expression).map(&:value)
114
128
  els.reduce do |f, arg|
115
129
  Application.for(function: f, argument: arg)
116
130
  end
117
131
  end
118
132
  end
119
133
 
134
+ module FirstApplicationExpression
135
+ def value
136
+ if captures.key?(:merge)
137
+ merge
138
+ elsif captures.key?(:some)
139
+ Optional.new(value: capture(:import_expression).value)
140
+ elsif captures.key?(:tomap)
141
+ ToMap.new(record: capture(:import_expression).value)
142
+ else
143
+ super
144
+ end
145
+ end
146
+
147
+ def merge
148
+ Merge.new(
149
+ record: captures(:import_expression)[0].value,
150
+ input: captures(:import_expression)[1].value,
151
+ type: nil
152
+ )
153
+ end
154
+ end
155
+
120
156
  module SelectorExpression
121
157
  def value
122
158
  record = capture(:primitive_expression).value
123
- selectors = captures(:selector).map(&:value)
124
- selectors.reduce(record) do |rec, sels|
159
+ captures(:selector).map(&:value).reduce(record) do |rec, sels|
125
160
  if sels.is_a?(Array)
126
- return EmptyRecordProjection.new(record: rec) if sels.empty?
127
- RecordProjection.new(record: rec, selectors: sels)
161
+ RecordProjection.for(rec, sels)
162
+ elsif sels.is_a?(Dhall::Expression)
163
+ RecordProjectionByExpression.new(record: rec, selector: sels)
128
164
  else
129
165
  RecordSelection.new(record: rec, selector: sels)
130
166
  end
@@ -132,18 +168,36 @@ module Dhall
132
168
  end
133
169
  end
134
170
 
135
- module Labels
171
+ module Selector
136
172
  def value
137
- captures(:any_label).map(&:value)
173
+ if captures.key?(:type_selector)
174
+ capture(:expression).value
175
+ elsif captures.key?(:labels)
176
+ captures(:any_label).map(&:value)
177
+ else
178
+ super
179
+ end
138
180
  end
139
181
  end
140
182
 
141
183
  module Label
184
+ module Quoted
185
+ def quoted?
186
+ true
187
+ end
188
+ end
189
+
190
+ module Unquoted
191
+ def quoted?
192
+ false
193
+ end
194
+ end
195
+
142
196
  def value
143
197
  if first.string == "`"
144
- matches[1].string
198
+ matches[1].string.extend(Quoted)
145
199
  else
146
- string
200
+ string.extend(Unquoted)
147
201
  end
148
202
  end
149
203
  end
@@ -203,7 +257,7 @@ module Dhall
203
257
  .map(&:value)
204
258
  .chunk { |s| s.is_a?(String) }
205
259
  .flat_map do |(strs, group)|
206
- strs ? group.map { |s| s.encode("UTF-16BE") }.join : group
260
+ strs ? group.join : group
207
261
  end
208
262
  )
209
263
  end
@@ -232,24 +286,49 @@ module Dhall
232
286
  "t" => "\t"
233
287
  }.freeze
234
288
 
289
+ NON_CHARACTERS = [
290
+ (0xD800..0xDFFF),
291
+ (0xFFFE..0xFFFF),
292
+ (0x1FFFE..0x1FFFF),
293
+ (0x2FFFE..0x2FFFF),
294
+ (0x3FFFE..0x3FFFF),
295
+ (0x4FFFE..0x4FFFF),
296
+ (0x5FFFE..0x5FFFF),
297
+ (0x6FFFE..0x6FFFF),
298
+ (0x7FFFE..0x7FFFF),
299
+ (0x8FFFE..0x8FFFF),
300
+ (0x9FFFE..0x9FFFF),
301
+ (0xAFFFE..0xAFFFF),
302
+ (0xBFFFE..0xBFFFF),
303
+ (0xCFFFE..0xCFFFF),
304
+ (0xDFFFE..0xDFFFF),
305
+ (0xEFFFE..0xEFFFF),
306
+ (0xFFFFE..0xFFFFF),
307
+ (0x10FFFE..0x10FFFF)
308
+ ].freeze
309
+
235
310
  def value
236
311
  ESCAPES.fetch(string) do
237
- [string[1..-1]].pack("H*").force_encoding("UTF-16BE")
312
+ code = string.sub(/\Au\{?([A-F0-9]+)\}?/, "\\1").to_i(16)
313
+ NON_CHARACTERS.each do |range|
314
+ raise Citrus::ParseError, input if range.include?(code)
315
+ end
316
+ [code].pack("U*")
238
317
  end
239
318
  end
240
319
  end
241
320
 
242
321
  module SingleQuoteLiteral
243
322
  def value
244
- chunks = capture(:single_quote_continue).value
245
- indent = chunks.join.split(/\n/, -1).map { |line|
246
- line.match(/^( *|\t*)/).to_s.length
247
- }.min
323
+ chunks = capture(:single_quote_continue).value.flat_map do |chunk|
324
+ chunk.is_a?(String) ? chunk.gsub(/\r\n/, "\n").chars : chunk
325
+ end
326
+ indent = Util.indent_size(chunks.join)
248
327
 
249
328
  TextLiteral.for(
250
329
  *chunks
251
- .chunk { |c| c != "\n" }
252
- .flat_map { |(line, chunk)| line ? chunk[indent..-1] : chunk }
330
+ .chunk { |c| c != "\n" }
331
+ .flat_map { |(line, chunk)| line ? chunk[indent..-1] : chunk }
253
332
  )
254
333
  end
255
334
  end
@@ -260,6 +339,12 @@ module Dhall
260
339
  end
261
340
  end
262
341
 
342
+ module EndOfLine
343
+ def value
344
+ "\n"
345
+ end
346
+ end
347
+
263
348
  module Interpolation
264
349
  def value
265
350
  capture(:complete_expression).value
@@ -284,18 +369,21 @@ module Dhall
284
369
  end
285
370
  end
286
371
 
287
- module Identifier
372
+ module Variable
288
373
  def value
289
- name = capture(:any_label).value
374
+ Dhall::Variable.new(
375
+ name: capture(:nonreserved_label).value,
376
+ index: capture(:natural_literal)&.string.to_i
377
+ )
378
+ end
379
+ end
290
380
 
291
- return Dhall::Bool.new(value: true) if name == "True"
292
- return Dhall::Bool.new(value: false) if name == "False"
381
+ module Builtin
382
+ def value
383
+ return Dhall::Bool.new(value: true) if string == "True"
384
+ return Dhall::Bool.new(value: false) if string == "False"
293
385
 
294
- Dhall::Builtins::ALL[name]&.new ||
295
- Variable.new(
296
- name: name,
297
- index: capture(:natural_literal)&.string.to_i
298
- )
386
+ Dhall::Builtins[string.to_sym]
299
387
  end
300
388
  end
301
389
 
@@ -304,7 +392,7 @@ module Dhall
304
392
  key = [
305
393
  :complete_expression,
306
394
  :record_type_or_literal,
307
- :union_type_or_literal
395
+ :union_type
308
396
  ].find { |k| captures.key?(k) }
309
397
  key ? capture(key).value : super
310
398
  end
@@ -316,31 +404,6 @@ module Dhall
316
404
  end
317
405
  end
318
406
 
319
- module UnionTypeOrLiteralVariantType
320
- def value(label)
321
- rest = capture(:non_empty_union_type_or_literal)&.value
322
- type = UnionType.new(
323
- alternatives: { label => capture(:expression)&.value }
324
- )
325
- if rest.is_a?(Union)
326
- rest.with(alternatives: type.merge(rest.alternatives))
327
- else
328
- rest ? type.merge(rest) : type
329
- end
330
- end
331
- end
332
-
333
- module UnionLiteralVariantValue
334
- def value(label)
335
- Union.new(
336
- tag: label,
337
- value: capture(:expression).value,
338
- alternatives: captures(:union_type_entry).map(&:value)
339
- .reduce(UnionType.new(alternatives: {}), &:merge)
340
- )
341
- end
342
- end
343
-
344
407
  module UnionTypeEntry
345
408
  def value
346
409
  UnionType.new(
@@ -351,19 +414,9 @@ module Dhall
351
414
  end
352
415
  end
353
416
 
354
- module NonEmptyUnionTypeOrLiteral
417
+ module NonEmptyUnionType
355
418
  def value
356
- key = [
357
- :union_literal_variant_value,
358
- :union_type_or_literal_variant_type
359
- ].find { |k| captures.key?(k) }
360
-
361
- if key
362
- capture(key).value(capture(:any_label).value)
363
- else
364
- no_alts = UnionType.new(alternatives: {})
365
- Union.from(no_alts, capture(:any_label).value, nil)
366
- end
419
+ captures(:union_type_entry).map(&:value).reduce(&:merge)
367
420
  end
368
421
  end
369
422
 
@@ -421,25 +474,6 @@ module Dhall
421
474
 
422
475
  RecordTypeEntry = RecordLiteralEntry
423
476
 
424
- module EmptyCollection
425
- def value
426
- if captures.key?(:list)
427
- EmptyList.new(element_type: capture(:import_expression).value)
428
- else
429
- OptionalNone.new(value_type: capture(:import_expression).value)
430
- end
431
- end
432
- end
433
-
434
- module NonEmptyOptional
435
- def value
436
- Optional.new(
437
- value: capture(:expression).value,
438
- value_type: capture(:import_expression).value
439
- )
440
- end
441
- end
442
-
443
477
  module AnnotatedExpression
444
478
  def value
445
479
  if matches[1].string.empty?
@@ -468,6 +502,8 @@ module Dhall
468
502
  def value
469
503
  import_type = if captures.key?(:text)
470
504
  Dhall::Import::Text
505
+ elsif captures.key?(:location)
506
+ Dhall::Import::AsLocation
471
507
  else
472
508
  Dhall::Import::Expression
473
509
  end
@@ -487,7 +523,28 @@ module Dhall
487
523
  module Hash
488
524
  def value
489
525
  protocol, data = string.split(/:/, 2)
490
- Dhall::Import::IntegrityCheck.new(protocol, data)
526
+ Dhall::Import::IntegrityCheck.new(
527
+ code: Multihashes::TABLE.key(
528
+ protocol.sub(/\Asha(\d{3})/, "sha2-\\1")
529
+ ),
530
+ digest: [data].pack("H*")
531
+ )
532
+ end
533
+ end
534
+
535
+ module Scheme
536
+ def value
537
+ ::URI.scheme_list[string.upcase]
538
+ end
539
+ end
540
+
541
+ module Authority
542
+ def value
543
+ {
544
+ userinfo: capture(:userinfo)&.value,
545
+ host: capture(:host).value,
546
+ port: capture(:port)&.value
547
+ }
491
548
  end
492
549
  end
493
550
 
@@ -497,23 +554,24 @@ module Dhall
497
554
  "https" => Dhall::Import::Https
498
555
  }.freeze
499
556
 
557
+ def http(key)
558
+ @http ||= capture(:http_raw)
559
+ @http.capture(key)&.value
560
+ end
561
+
500
562
  def value
501
- http = capture(:http_raw)
502
- SCHEME.fetch(http.capture(:scheme).value).new(
503
- capture(:import_hashed)&.value(Dhall::Import::Expression),
504
- http.capture(:authority).value,
505
- *unescaped_components,
506
- http.capture(:query)&.value
563
+ uri = http(:scheme).build(
564
+ http(:authority).merge(
565
+ path: http(:url_path) || "/"
566
+ )
507
567
  )
508
- end
509
568
 
510
- def unescaped_components
511
- capture(:http_raw)
512
- .capture(:path)
513
- .captures(:path_component)
514
- .map do |pc|
515
- pc.value(URI.method(:unescape))
516
- end
569
+ uri.instance_variable_set(:@query, http(:query))
570
+
571
+ SCHEME.fetch(uri.scheme).new(
572
+ headers: capture(:import_expression)&.value,
573
+ uri: uri
574
+ )
517
575
  end
518
576
  end
519
577
 
@@ -521,9 +579,9 @@ module Dhall
521
579
  def value
522
580
  Dhall::Import::EnvironmentVariable.new(
523
581
  if captures.key?(:bash_environment_variable)
524
- capture(:bash_environment_variable).string
582
+ capture(:bash_environment_variable).value
525
583
  else
526
- capture(:posix_environment_variable).value.encode("utf-8")
584
+ capture(:posix_environment_variable).value
527
585
  end
528
586
  )
529
587
  end
@@ -531,12 +589,22 @@ module Dhall
531
589
 
532
590
  module PosixEnvironmentVariable
533
591
  def value
534
- matches.map(&:value).join
592
+ matches.map(&:value).join.encode(Encoding::UTF_8)
535
593
  end
536
594
  end
537
595
 
538
596
  module PosixEnvironmentVariableCharacter
539
- ESCAPES = Dhall::Import::EnvironmentVariable::ESCAPES
597
+ ESCAPES = {
598
+ "\"" => "\"",
599
+ "\\" => "\\",
600
+ "a" => "\a",
601
+ "b" => "\b",
602
+ "f" => "\f",
603
+ "n" => "\n",
604
+ "r" => "\r",
605
+ "t" => "\t",
606
+ "v" => "\v"
607
+ }.freeze
540
608
 
541
609
  def value
542
610
  if first&.string == "\\"
@@ -580,15 +648,28 @@ module Dhall
580
648
  end
581
649
 
582
650
  module PathComponent
583
- def value(unescaper=:itself.to_proc)
651
+ def value(escaper=:itself.to_proc)
584
652
  if captures.key?(:quoted_path_component)
585
- capture(:quoted_path_component).value
653
+ escaper.call(capture(:quoted_path_component).value)
586
654
  else
587
- unescaper.call(capture(:unquoted_path_component).value)
655
+ capture(:unquoted_path_component).value
588
656
  end
589
657
  end
590
658
  end
591
659
 
660
+ module UrlPath
661
+ def value
662
+ "/" + matches.map { |pc|
663
+ if pc.captures.key?(:path_component)
664
+ # We escape here because ruby stdlib URI just stores path unparsed
665
+ pc.value(Util.method(:uri_escape))
666
+ else
667
+ pc.string[1..-1]
668
+ end
669
+ }.join("/")
670
+ end
671
+ end
672
+
592
673
  module Missing
593
674
  def value
594
675
  Dhall::Import::MissingImport.new