dhall 0.3.0 → 0.5.2
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.
- checksums.yaml +5 -5
- data/bin/dhall-compile +38 -4
- data/bin/json-to-dhall +1 -1
- data/bin/yaml-to-dhall +1 -1
- data/dhall.gemspec +4 -0
- data/lib/dhall/as_dhall.rb +6 -0
- data/lib/dhall/ast.rb +291 -116
- data/lib/dhall/binary.rb +92 -17
- data/lib/dhall/builtins.rb +179 -238
- data/lib/dhall/coder.rb +6 -1
- data/lib/dhall/normalize.rb +59 -31
- data/lib/dhall/parser.citrus +73 -43
- data/lib/dhall/parser.rb +136 -103
- data/lib/dhall/resolve.rb +42 -32
- data/lib/dhall/typecheck.rb +171 -34
- data/lib/dhall/types.rb +19 -0
- data/lib/dhall/util.rb +49 -0
- data/lib/dhall.rb +1 -0
- metadata +60 -4
- data/lib/dhall/visitor.rb +0 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c6ba874fec536af3a57ea4a0ca59f040076ebc03ed639dcd44a5a2b79e8bf252
|
4
|
+
data.tar.gz: 4408343df3c63a8c96f6e191f3109a2110ae4b6f3ab06aee58c15b2e7439f6ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3fdb1ed15e039261aedfc608d612eb4739b7a0204aa26524d66e8999d14ed71cc4e2b5964077f88cf860a99454548c7c2aae2188de9a9687fb173e780441fe4
|
7
|
+
data.tar.gz: 0b9b101c0ccaec5d6be7bbfab0a3698c1eb81f91c06ba9efe663391ce56e8e71613fb0f4cd37af12cc68e7973278fcd9f47190d80a0369c14230a3e0480cdda1
|
data/bin/dhall-compile
CHANGED
@@ -13,19 +13,43 @@ def compile(source)
|
|
13
13
|
resolver: Dhall::Resolvers::Default.new(
|
14
14
|
max_depth: Float::INFINITY
|
15
15
|
)
|
16
|
-
)
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
module FilenameWriter
|
20
|
+
def self.write(_, out, dhall)
|
21
|
+
warn out
|
22
|
+
out.dirname.mkpath
|
23
|
+
out.write(dhall.to_binary)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module CacheWriter
|
28
|
+
def self.write(output_directory, out, dhall)
|
29
|
+
base = "1220#{dhall.digest.hexdigest}"
|
30
|
+
out = out.dirname + base
|
31
|
+
if output_directory
|
32
|
+
out = output_directory + base
|
33
|
+
out.dirname.mkpath
|
34
|
+
end
|
35
|
+
warn out
|
36
|
+
out.write(dhall.to_cbor)
|
37
|
+
end
|
17
38
|
end
|
18
39
|
|
19
40
|
def compile_file(file_path, relative_to: Pathname.new("."))
|
41
|
+
$stderr.print "#{file_path} => "
|
20
42
|
out = file_path.sub_ext(@extension)
|
21
43
|
if @output_directory
|
22
44
|
out = @output_directory + out.relative_path_from(relative_to)
|
23
|
-
out.dirname.mkpath
|
24
45
|
end
|
25
|
-
|
26
|
-
|
46
|
+
compile(file_path.expand_path).then do |dhall|
|
47
|
+
@writer.write(@output_directory, out, dhall)
|
48
|
+
end
|
27
49
|
end
|
28
50
|
|
51
|
+
@writer = FilenameWriter
|
52
|
+
# rubocop:disable Metrics/BlockLength
|
29
53
|
opt_parser = OptionParser.new do |opts|
|
30
54
|
opts.banner = "Usage: dhall-compile [options] [-] [files_and_dirs]"
|
31
55
|
|
@@ -45,11 +69,21 @@ opt_parser = OptionParser.new do |opts|
|
|
45
69
|
@extension = ext ? ".#{ext}" : ""
|
46
70
|
end
|
47
71
|
|
72
|
+
opts.on(
|
73
|
+
"-c",
|
74
|
+
"--cache",
|
75
|
+
"Write output in standard dhall file cache format"
|
76
|
+
) do
|
77
|
+
@extension = ""
|
78
|
+
@writer = CacheWriter
|
79
|
+
end
|
80
|
+
|
48
81
|
opts.on("-h", "--help", "Show this usage information") do
|
49
82
|
warn opts
|
50
83
|
exit
|
51
84
|
end
|
52
85
|
end
|
86
|
+
# rubocop:enable Metrics/BlockLength
|
53
87
|
|
54
88
|
opt_parser.parse!
|
55
89
|
|
data/bin/json-to-dhall
CHANGED
data/bin/yaml-to-dhall
CHANGED
data/dhall.gemspec
CHANGED
@@ -25,12 +25,16 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
+
spec.add_dependency "base32", "~> 0.3.2"
|
28
29
|
spec.add_dependency "cbor", "~> 0.5.9.3"
|
29
30
|
spec.add_dependency "citrus", "~> 3.0"
|
31
|
+
spec.add_dependency "lazy_object", "~> 0.0.3"
|
32
|
+
spec.add_dependency "multihashes", "~> 0.2.0"
|
30
33
|
spec.add_dependency "promise.rb", "~> 0.7.4"
|
31
34
|
spec.add_dependency "value_semantics", "~> 3.0"
|
32
35
|
|
33
36
|
spec.add_development_dependency "abnf", "~> 0.0.1"
|
37
|
+
spec.add_development_dependency "minitest-fail-fast", "~> 0.1.0"
|
34
38
|
spec.add_development_dependency "simplecov", "~> 0.16.1"
|
35
39
|
spec.add_development_dependency "webmock", "~> 3.5"
|
36
40
|
end
|
data/lib/dhall/as_dhall.rb
CHANGED
data/lib/dhall/ast.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "base32"
|
4
|
+
require "lazy_object"
|
5
|
+
require "multihashes"
|
3
6
|
require "uri"
|
4
7
|
require "value_semantics"
|
5
8
|
|
@@ -33,8 +36,7 @@ module Dhall
|
|
33
36
|
end
|
34
37
|
|
35
38
|
def *(other)
|
36
|
-
|
37
|
-
when Natural
|
39
|
+
if other.is_a?(Natural) && other.zero?
|
38
40
|
other * self
|
39
41
|
else
|
40
42
|
Operator::Times.new(lhs: self, rhs: other)
|
@@ -68,7 +70,7 @@ module Dhall
|
|
68
70
|
def dhall_eq(other)
|
69
71
|
if self == other
|
70
72
|
Bool.new(value: true)
|
71
|
-
elsif other.
|
73
|
+
elsif other == Bool.new(value: true)
|
72
74
|
other.dhall_eq(self)
|
73
75
|
else
|
74
76
|
Operator::Equal.new(lhs: self, rhs: other)
|
@@ -102,6 +104,10 @@ module Dhall
|
|
102
104
|
end
|
103
105
|
end
|
104
106
|
|
107
|
+
def annotate(type)
|
108
|
+
TypeAnnotation.new(value: self, type: type)
|
109
|
+
end
|
110
|
+
|
105
111
|
def to_s
|
106
112
|
inspect
|
107
113
|
end
|
@@ -128,7 +134,7 @@ module Dhall
|
|
128
134
|
def flatten
|
129
135
|
f, args = if function.is_a?(Application)
|
130
136
|
function.flatten
|
131
|
-
elsif function.is_a?(
|
137
|
+
elsif function.is_a?(BuiltinFunction) &&
|
132
138
|
(unfilled = function.unfill).is_a?(Application)
|
133
139
|
unfilled.flatten
|
134
140
|
else
|
@@ -216,7 +222,29 @@ module Dhall
|
|
216
222
|
end
|
217
223
|
end
|
218
224
|
|
219
|
-
class
|
225
|
+
class RubyObjectRaw < Expression
|
226
|
+
def initialize(object)
|
227
|
+
@object = object
|
228
|
+
end
|
229
|
+
|
230
|
+
def unwrap
|
231
|
+
@object
|
232
|
+
end
|
233
|
+
|
234
|
+
def respond_to_missing?(m)
|
235
|
+
super || @object.respond_to?(m)
|
236
|
+
end
|
237
|
+
|
238
|
+
def method_missing(m, *args, &block)
|
239
|
+
if @object.respond_to?(m)
|
240
|
+
@object.public_send(m, *args, &block)
|
241
|
+
else
|
242
|
+
super
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
class FunctionProxyRaw < Function
|
220
248
|
def initialize(callable, curry: true)
|
221
249
|
@callable = if !curry
|
222
250
|
callable
|
@@ -230,7 +258,7 @@ module Dhall
|
|
230
258
|
end
|
231
259
|
|
232
260
|
def call(*args, &block)
|
233
|
-
@callable.call(*args.map { |arg| arg&.as_dhall }, &block)
|
261
|
+
RubyObjectRaw.new(@callable.call(*args.map { |arg| arg&.as_dhall }, &block))
|
234
262
|
end
|
235
263
|
|
236
264
|
def as_json
|
@@ -238,6 +266,12 @@ module Dhall
|
|
238
266
|
end
|
239
267
|
end
|
240
268
|
|
269
|
+
class FunctionProxy < FunctionProxyRaw
|
270
|
+
def call(*args, &block)
|
271
|
+
super.unwrap.as_dhall
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
241
275
|
class Bool < Expression
|
242
276
|
include(ValueSemantics.for_attributes do
|
243
277
|
value Bool()
|
@@ -317,6 +351,33 @@ module Dhall
|
|
317
351
|
[3, OPERATORS.index(self.class), lhs.as_json, rhs.as_json]
|
318
352
|
end
|
319
353
|
|
354
|
+
module FetchFromMerge
|
355
|
+
def fetch_second_record(first, second, selector)
|
356
|
+
rec = self.class.new(
|
357
|
+
self.class::FETCH2K => second.slice(selector),
|
358
|
+
self.class::FETCH1K => first
|
359
|
+
).normalize
|
360
|
+
|
361
|
+
if rec.class == self.class
|
362
|
+
RecordSelection.new(record: rec, selector: selector)
|
363
|
+
else
|
364
|
+
rec.fetch(selector)
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def fetch(selector)
|
369
|
+
first = public_send(self.class::FETCH1K)
|
370
|
+
second = public_send(self.class::FETCH2K)
|
371
|
+
if first.is_a?(Record)
|
372
|
+
first.fetch(selector) { second.fetch(selector) }
|
373
|
+
elsif second.is_a?(Record)
|
374
|
+
fetch_second_record(first, second, selector)
|
375
|
+
else
|
376
|
+
super
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
320
381
|
class Or < Operator; end
|
321
382
|
class And < Operator; end
|
322
383
|
class Equal < Operator; end
|
@@ -325,17 +386,27 @@ module Dhall
|
|
325
386
|
class Times < Operator; end
|
326
387
|
class TextConcatenate < Operator; end
|
327
388
|
class ListConcatenate < Operator; end
|
328
|
-
class RecursiveRecordMerge < Operator
|
329
|
-
|
389
|
+
class RecursiveRecordMerge < Operator
|
390
|
+
FETCH1K = :lhs
|
391
|
+
FETCH2K = :rhs
|
392
|
+
include FetchFromMerge
|
393
|
+
end
|
394
|
+
class RightBiasedRecordMerge < Operator
|
395
|
+
FETCH1K = :rhs
|
396
|
+
FETCH2K = :lhs
|
397
|
+
include FetchFromMerge
|
398
|
+
end
|
330
399
|
class RecursiveRecordTypeMerge < Operator; end
|
331
400
|
class ImportFallback < Operator; end
|
401
|
+
class Equivalent < Operator; end
|
332
402
|
|
333
403
|
OPERATORS = [
|
334
404
|
Or, And, Equal, NotEqual,
|
335
405
|
Plus, Times,
|
336
406
|
TextConcatenate, ListConcatenate,
|
337
407
|
RecursiveRecordMerge, RightBiasedRecordMerge, RecursiveRecordTypeMerge,
|
338
|
-
ImportFallback
|
408
|
+
ImportFallback,
|
409
|
+
Equivalent
|
339
410
|
].freeze
|
340
411
|
end
|
341
412
|
|
@@ -344,9 +415,18 @@ module Dhall
|
|
344
415
|
|
345
416
|
include(ValueSemantics.for_attributes do
|
346
417
|
elements Util::ArrayOf.new(Expression, min: 1)
|
347
|
-
|
418
|
+
type Either(nil, Expression), default: nil
|
348
419
|
end)
|
349
420
|
|
421
|
+
def initialize(attrs)
|
422
|
+
if attrs.key?(:element_type)
|
423
|
+
et = attrs.delete(:element_type)
|
424
|
+
attrs[:type] = self.class.as_dhall.call(et) if et
|
425
|
+
end
|
426
|
+
|
427
|
+
super
|
428
|
+
end
|
429
|
+
|
350
430
|
def self.of(*args, type: nil)
|
351
431
|
if args.empty?
|
352
432
|
EmptyList.new(element_type: type)
|
@@ -359,11 +439,13 @@ module Dhall
|
|
359
439
|
Builtins[:List]
|
360
440
|
end
|
361
441
|
|
362
|
-
def
|
363
|
-
|
364
|
-
|
365
|
-
argument
|
366
|
-
|
442
|
+
def element_type
|
443
|
+
if type.nil?
|
444
|
+
elsif type.is_a?(Application) && type.function == Builtins[:List]
|
445
|
+
type.argument
|
446
|
+
else
|
447
|
+
raise "Cannot get element_type of: #{type.inspect}"
|
448
|
+
end
|
367
449
|
end
|
368
450
|
|
369
451
|
def as_json
|
@@ -371,9 +453,10 @@ module Dhall
|
|
371
453
|
end
|
372
454
|
|
373
455
|
def map(type: nil, &block)
|
456
|
+
type = type.nil? ? nil : Builtins[:List].call(type.as_dhall)
|
374
457
|
with(
|
375
|
-
elements:
|
376
|
-
|
458
|
+
elements: elements.each_with_index.map(&block),
|
459
|
+
type: type
|
377
460
|
)
|
378
461
|
end
|
379
462
|
|
@@ -421,11 +504,22 @@ module Dhall
|
|
421
504
|
|
422
505
|
class EmptyList < List
|
423
506
|
include(ValueSemantics.for_attributes do
|
424
|
-
|
507
|
+
type Either(nil, Expression)
|
425
508
|
end)
|
426
509
|
|
510
|
+
def initialize(attrs)
|
511
|
+
if attrs.key?(:element_type)
|
512
|
+
et = attrs.delete(:element_type)
|
513
|
+
attrs[:type] = self.class.as_dhall.call(et) if et
|
514
|
+
end
|
515
|
+
|
516
|
+
super
|
517
|
+
end
|
518
|
+
|
427
519
|
def as_json
|
428
520
|
[4, element_type.as_json]
|
521
|
+
rescue
|
522
|
+
[28, type.as_json]
|
429
523
|
end
|
430
524
|
|
431
525
|
def map(type: nil)
|
@@ -460,6 +554,10 @@ module Dhall
|
|
460
554
|
self
|
461
555
|
end
|
462
556
|
|
557
|
+
def join(*)
|
558
|
+
""
|
559
|
+
end
|
560
|
+
|
463
561
|
def concat(other)
|
464
562
|
other
|
465
563
|
end
|
@@ -547,7 +645,7 @@ module Dhall
|
|
547
645
|
include(ValueSemantics.for_attributes do
|
548
646
|
record Expression
|
549
647
|
input Expression
|
550
|
-
type Either(Expression, nil)
|
648
|
+
type Either(Expression, nil), default: nil
|
551
649
|
end)
|
552
650
|
|
553
651
|
def as_json
|
@@ -556,6 +654,18 @@ module Dhall
|
|
556
654
|
end
|
557
655
|
end
|
558
656
|
|
657
|
+
class ToMap < Expression
|
658
|
+
include(ValueSemantics.for_attributes do
|
659
|
+
record Expression
|
660
|
+
type Either(Expression, nil), default: nil
|
661
|
+
end)
|
662
|
+
|
663
|
+
def as_json
|
664
|
+
[27, record.as_json] +
|
665
|
+
(type.nil? ? [] : [type.as_json])
|
666
|
+
end
|
667
|
+
end
|
668
|
+
|
559
669
|
class RecordType < Expression
|
560
670
|
include(ValueSemantics.for_attributes do
|
561
671
|
record Util::HashOf.new(::String, Expression, min: 1)
|
@@ -793,11 +903,38 @@ module Dhall
|
|
793
903
|
selectors Util::ArrayOf.new(::String, min: 1)
|
794
904
|
end)
|
795
905
|
|
906
|
+
def self.for(record, selectors)
|
907
|
+
if selectors.empty?
|
908
|
+
EmptyRecordProjection.new(record: record)
|
909
|
+
else
|
910
|
+
new(record: record, selectors: selectors)
|
911
|
+
end
|
912
|
+
end
|
913
|
+
|
914
|
+
def fetch(selector)
|
915
|
+
record.fetch(selector)
|
916
|
+
end
|
917
|
+
|
796
918
|
def as_json
|
797
919
|
[10, record.as_json, *selectors]
|
798
920
|
end
|
799
921
|
end
|
800
922
|
|
923
|
+
class RecordProjectionByExpression < Expression
|
924
|
+
include(ValueSemantics.for_attributes do
|
925
|
+
record Expression
|
926
|
+
selector Expression
|
927
|
+
end)
|
928
|
+
|
929
|
+
def fetch(selector)
|
930
|
+
record.fetch(selector)
|
931
|
+
end
|
932
|
+
|
933
|
+
def as_json
|
934
|
+
[10, record.as_json, [selector.as_json]]
|
935
|
+
end
|
936
|
+
end
|
937
|
+
|
801
938
|
class EmptyRecordProjection < Expression
|
802
939
|
include(ValueSemantics.for_attributes do
|
803
940
|
record Expression
|
@@ -968,8 +1105,8 @@ module Dhall
|
|
968
1105
|
class If < Expression
|
969
1106
|
include(ValueSemantics.for_attributes do
|
970
1107
|
predicate Expression
|
971
|
-
|
972
|
-
|
1108
|
+
def_attr :then, Expression
|
1109
|
+
def_attr :else, Expression
|
973
1110
|
end)
|
974
1111
|
|
975
1112
|
def as_json
|
@@ -1189,91 +1326,92 @@ module Dhall
|
|
1189
1326
|
class Import < Expression
|
1190
1327
|
class IntegrityCheck
|
1191
1328
|
include(ValueSemantics.for_attributes do
|
1192
|
-
|
1193
|
-
|
1329
|
+
code ::Integer
|
1330
|
+
digest ::String
|
1194
1331
|
end)
|
1195
1332
|
|
1196
1333
|
class FailureException < StandardError; end
|
1197
1334
|
|
1198
|
-
def
|
1199
|
-
|
1200
|
-
protocol: protocol,
|
1201
|
-
data: data
|
1202
|
-
)
|
1335
|
+
def to_s
|
1336
|
+
"#{Multihashes::TABLE[code].sub(/\Asha2-/, "sha")}:#{hexdigest}"
|
1203
1337
|
end
|
1204
1338
|
|
1205
|
-
def
|
1206
|
-
"
|
1339
|
+
def hexdigest
|
1340
|
+
digest.unpack("H*").first.encode(Encoding::UTF_8)
|
1207
1341
|
end
|
1208
1342
|
|
1209
|
-
def
|
1210
|
-
|
1343
|
+
def ipfs
|
1344
|
+
"/ipfs/b#{Base32.encode("\x01\x55" + as_json).downcase.sub(/=*$/, "")}"
|
1345
|
+
end
|
1211
1346
|
|
1347
|
+
def check(expr)
|
1212
1348
|
expr = expr.normalize
|
1213
1349
|
return expr if expr.cache_key == to_s
|
1214
1350
|
|
1215
|
-
raise FailureException, "#{expr}
|
1351
|
+
raise FailureException, "#{expr} hash #{expr.cache_key}" \
|
1352
|
+
" does not match #{self}"
|
1216
1353
|
end
|
1217
1354
|
|
1218
1355
|
def as_json
|
1219
|
-
|
1356
|
+
Multihashes.encode(digest, Multihashes::TABLE[code])
|
1220
1357
|
end
|
1221
1358
|
end
|
1222
1359
|
|
1223
|
-
class
|
1224
|
-
|
1225
|
-
headers Either(nil, Expression)
|
1226
|
-
authority ::String
|
1227
|
-
path ArrayOf(::String)
|
1228
|
-
query Either(nil, ::String)
|
1229
|
-
end)
|
1360
|
+
class NoIntegrityCheck < IntegrityCheck
|
1361
|
+
def initialize; end
|
1230
1362
|
|
1231
|
-
def
|
1232
|
-
|
1233
|
-
headers: headers,
|
1234
|
-
authority: authority,
|
1235
|
-
path: path,
|
1236
|
-
query: query,
|
1237
|
-
)
|
1363
|
+
def to_s
|
1364
|
+
""
|
1238
1365
|
end
|
1239
1366
|
|
1240
|
-
def
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
*hash.fetch(:path, path),
|
1245
|
-
hash.fetch(:query, query)
|
1246
|
-
)
|
1367
|
+
def hexdigest; end
|
1368
|
+
|
1369
|
+
def check(expr)
|
1370
|
+
expr.normalize
|
1247
1371
|
end
|
1248
1372
|
|
1249
|
-
def
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1373
|
+
def as_json
|
1374
|
+
nil
|
1375
|
+
end
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
Location = LazyObject.new do
|
1379
|
+
UnionType.new(
|
1380
|
+
alternatives: {
|
1381
|
+
"Local" => Builtins[:Text],
|
1382
|
+
"Remote" => Builtins[:Text],
|
1383
|
+
"Environment" => Builtins[:Text],
|
1384
|
+
"Missing" => nil
|
1385
|
+
}
|
1386
|
+
)
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
class URI
|
1390
|
+
include(ValueSemantics.for_attributes do
|
1391
|
+
uri ::URI
|
1392
|
+
headers Either(nil, Expression), default: nil
|
1393
|
+
end)
|
1394
|
+
|
1395
|
+
def with(attrs)
|
1396
|
+
if attrs.key?(:path)
|
1397
|
+
attrs[:uri] =
|
1398
|
+
uri + Util.path_components_to_uri(*attrs.delete(:path))
|
1399
|
+
end
|
1400
|
+
|
1401
|
+
super
|
1257
1402
|
end
|
1258
1403
|
|
1259
1404
|
def headers
|
1260
1405
|
header_type = RecordType.new(
|
1261
1406
|
record: {
|
1262
|
-
"
|
1263
|
-
"
|
1407
|
+
"mapKey" => Builtins[:Text],
|
1408
|
+
"mapValue" => Builtins[:Text]
|
1264
1409
|
}
|
1265
1410
|
)
|
1266
1411
|
|
1267
1412
|
super || EmptyList.new(element_type: header_type)
|
1268
1413
|
end
|
1269
1414
|
|
1270
|
-
def uri
|
1271
|
-
escaped_path = path.map do |c|
|
1272
|
-
::URI.encode_www_form_component(c).gsub("+", "%20")
|
1273
|
-
end
|
1274
|
-
URI("#{scheme}://#{authority}/#{escaped_path.join("/")}?#{query}")
|
1275
|
-
end
|
1276
|
-
|
1277
1415
|
def chain_onto(relative_to)
|
1278
1416
|
if headers.is_a?(Import)
|
1279
1417
|
with(headers: headers.with(path: headers.real_path(relative_to)))
|
@@ -1284,23 +1422,43 @@ module Dhall
|
|
1284
1422
|
|
1285
1423
|
def canonical
|
1286
1424
|
with(
|
1287
|
-
path: (path[1..-1] + [""])
|
1288
|
-
.reduce([[], path.first]) { |(pth, prev), c|
|
1425
|
+
path: (path[1..-1] + [""]).reduce([[], path.first]) { |(pth, prev), c|
|
1289
1426
|
c == ".." ? [pth, prev] : [pth + [prev], c]
|
1290
1427
|
}.first.reject { |c| c == "." }
|
1291
1428
|
)
|
1292
1429
|
end
|
1293
1430
|
|
1431
|
+
def port
|
1432
|
+
uri.port && uri.port != uri.default_port ? uri.port : nil
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
def authority
|
1436
|
+
[
|
1437
|
+
uri.userinfo,
|
1438
|
+
[uri.host, port].compact.join(":")
|
1439
|
+
].compact.join("@")
|
1440
|
+
end
|
1441
|
+
|
1294
1442
|
def origin
|
1295
|
-
"#{scheme}://#{authority}"
|
1443
|
+
"#{uri.scheme}://#{authority}"
|
1296
1444
|
end
|
1297
1445
|
|
1298
1446
|
def to_s
|
1299
1447
|
uri.to_s
|
1300
1448
|
end
|
1301
1449
|
|
1450
|
+
def location
|
1451
|
+
Union.from(Location, "Remote", to_s.as_dhall)
|
1452
|
+
end
|
1453
|
+
|
1454
|
+
def path
|
1455
|
+
path = uri.path.split(/\//, -1)
|
1456
|
+
path = path[1..-1] if path.length > 1 && path.first.empty?
|
1457
|
+
path
|
1458
|
+
end
|
1459
|
+
|
1302
1460
|
def as_json
|
1303
|
-
[@headers&.as_json, authority, *path, query]
|
1461
|
+
[@headers&.as_json, authority, *path, uri.query]
|
1304
1462
|
end
|
1305
1463
|
end
|
1306
1464
|
|
@@ -1308,20 +1466,12 @@ module Dhall
|
|
1308
1466
|
def resolve(resolver)
|
1309
1467
|
resolver.resolve_http(self)
|
1310
1468
|
end
|
1311
|
-
|
1312
|
-
def scheme
|
1313
|
-
"http"
|
1314
|
-
end
|
1315
1469
|
end
|
1316
1470
|
|
1317
1471
|
class Https < URI
|
1318
1472
|
def resolve(resolver)
|
1319
1473
|
resolver.resolve_https(self)
|
1320
1474
|
end
|
1321
|
-
|
1322
|
-
def scheme
|
1323
|
-
"https"
|
1324
|
-
end
|
1325
1475
|
end
|
1326
1476
|
|
1327
1477
|
class Path
|
@@ -1366,6 +1516,10 @@ module Dhall
|
|
1366
1516
|
pathname.to_s
|
1367
1517
|
end
|
1368
1518
|
|
1519
|
+
def location
|
1520
|
+
Union.from(Location, "Local", to_s.as_dhall)
|
1521
|
+
end
|
1522
|
+
|
1369
1523
|
def as_json
|
1370
1524
|
path
|
1371
1525
|
end
|
@@ -1376,8 +1530,8 @@ module Dhall
|
|
1376
1530
|
Pathname.new("/").join(*path)
|
1377
1531
|
end
|
1378
1532
|
|
1379
|
-
def to_uri(scheme,
|
1380
|
-
scheme.new(
|
1533
|
+
def to_uri(scheme, base_uri)
|
1534
|
+
scheme.new(uri: base_uri + Util.path_components_to_uri(*path))
|
1381
1535
|
end
|
1382
1536
|
|
1383
1537
|
def chain_onto(relative_to)
|
@@ -1394,6 +1548,10 @@ module Dhall
|
|
1394
1548
|
Pathname.new(".").join(*path)
|
1395
1549
|
end
|
1396
1550
|
|
1551
|
+
def to_s
|
1552
|
+
"./#{pathname}"
|
1553
|
+
end
|
1554
|
+
|
1397
1555
|
def chain_onto(relative_to)
|
1398
1556
|
relative_to.with(
|
1399
1557
|
path: relative_to.path[0..-2] + path
|
@@ -1473,6 +1631,10 @@ module Dhall
|
|
1473
1631
|
end}"
|
1474
1632
|
end
|
1475
1633
|
|
1634
|
+
def location
|
1635
|
+
Union.from(Location, "Environment", to_s.as_dhall)
|
1636
|
+
end
|
1637
|
+
|
1476
1638
|
def hash
|
1477
1639
|
@var.hash
|
1478
1640
|
end
|
@@ -1480,7 +1642,7 @@ module Dhall
|
|
1480
1642
|
def eql?(other)
|
1481
1643
|
other.is_a?(self.class) && other.var == var
|
1482
1644
|
end
|
1483
|
-
alias eql?
|
1645
|
+
alias == eql?
|
1484
1646
|
|
1485
1647
|
def as_json
|
1486
1648
|
@var
|
@@ -1506,6 +1668,15 @@ module Dhall
|
|
1506
1668
|
"missing"
|
1507
1669
|
end
|
1508
1670
|
|
1671
|
+
def location
|
1672
|
+
Union.from(Location, "Missing", nil)
|
1673
|
+
end
|
1674
|
+
|
1675
|
+
def eql?(other)
|
1676
|
+
other.class == self.class
|
1677
|
+
end
|
1678
|
+
alias == eql?
|
1679
|
+
|
1509
1680
|
def as_json
|
1510
1681
|
[]
|
1511
1682
|
end
|
@@ -1525,9 +1696,16 @@ module Dhall
|
|
1525
1696
|
end
|
1526
1697
|
end
|
1527
1698
|
|
1699
|
+
class AsLocation
|
1700
|
+
def self.call(*)
|
1701
|
+
raise "AsLocation is only a marker, you don't actually call it"
|
1702
|
+
end
|
1703
|
+
end
|
1704
|
+
|
1528
1705
|
IMPORT_TYPES = [
|
1529
1706
|
Expression,
|
1530
|
-
Text
|
1707
|
+
Text,
|
1708
|
+
AsLocation
|
1531
1709
|
].freeze
|
1532
1710
|
|
1533
1711
|
PATH_TYPES = [
|
@@ -1537,14 +1715,14 @@ module Dhall
|
|
1537
1715
|
].freeze
|
1538
1716
|
|
1539
1717
|
include(ValueSemantics.for_attributes do
|
1540
|
-
integrity_check IntegrityCheck, default:
|
1718
|
+
integrity_check IntegrityCheck, default: NoIntegrityCheck.new
|
1541
1719
|
import_type Class
|
1542
1720
|
path Either(*PATH_TYPES)
|
1543
1721
|
end)
|
1544
1722
|
|
1545
1723
|
def initialize(integrity_check, import_type, path)
|
1546
1724
|
super(
|
1547
|
-
integrity_check: integrity_check ||
|
1725
|
+
integrity_check: integrity_check || NoIntegrityCheck.new,
|
1548
1726
|
import_type: import_type,
|
1549
1727
|
path: path
|
1550
1728
|
)
|
@@ -1562,15 +1740,18 @@ module Dhall
|
|
1562
1740
|
path.chain_onto(relative_to).canonical
|
1563
1741
|
end
|
1564
1742
|
|
1565
|
-
def
|
1566
|
-
|
1743
|
+
def parse_resolve_check(raw, deadline: Util::NoDeadline.new, **kwargs)
|
1744
|
+
import_type.call(raw, deadline: deadline).resolve(**kwargs).then do |e|
|
1745
|
+
integrity_check.check(TypeChecker.annotate(e))
|
1746
|
+
end
|
1567
1747
|
end
|
1568
1748
|
|
1569
1749
|
def cache_key(relative_to)
|
1570
|
-
|
1750
|
+
key = integrity_check.to_s
|
1751
|
+
if key.empty?
|
1571
1752
|
real_path(relative_to)
|
1572
1753
|
else
|
1573
|
-
|
1754
|
+
key
|
1574
1755
|
end
|
1575
1756
|
end
|
1576
1757
|
|
@@ -1609,10 +1790,10 @@ module Dhall
|
|
1609
1790
|
|
1610
1791
|
def flatten
|
1611
1792
|
flattened = body.is_a?(LetIn) ? body.flatten : body
|
1612
|
-
if flattened.is_a?(
|
1613
|
-
LetBlock.
|
1793
|
+
if flattened.is_a?(LetBlock)
|
1794
|
+
LetBlock.new(lets: lets + flattened.lets, body: flattened.body)
|
1614
1795
|
else
|
1615
|
-
|
1796
|
+
LetBlock.new(lets: lets, body: body)
|
1616
1797
|
end
|
1617
1798
|
end
|
1618
1799
|
|
@@ -1635,28 +1816,16 @@ module Dhall
|
|
1635
1816
|
end
|
1636
1817
|
|
1637
1818
|
def as_json
|
1638
|
-
|
1819
|
+
flatten.as_json
|
1639
1820
|
end
|
1640
1821
|
end
|
1641
1822
|
|
1642
|
-
class LetBlock
|
1823
|
+
class LetBlock
|
1643
1824
|
include(ValueSemantics.for_attributes do
|
1644
|
-
lets Util::ArrayOf.new(Let
|
1825
|
+
lets Util::ArrayOf.new(Let)
|
1645
1826
|
body Expression
|
1646
1827
|
end)
|
1647
1828
|
|
1648
|
-
def self.for(lets:, body:)
|
1649
|
-
if lets.length == 1
|
1650
|
-
LetIn.new(let: lets.first, body: body)
|
1651
|
-
else
|
1652
|
-
new(lets: lets, body: body)
|
1653
|
-
end
|
1654
|
-
end
|
1655
|
-
|
1656
|
-
def flatten
|
1657
|
-
unflatten.flatten
|
1658
|
-
end
|
1659
|
-
|
1660
1829
|
def unflatten
|
1661
1830
|
lets.reverse.reduce(body) do |inside, let|
|
1662
1831
|
letin = LetIn.new(let: let, body: inside)
|
@@ -1664,10 +1833,6 @@ module Dhall
|
|
1664
1833
|
end
|
1665
1834
|
end
|
1666
1835
|
|
1667
|
-
def desugar
|
1668
|
-
unflatten(&:desugar)
|
1669
|
-
end
|
1670
|
-
|
1671
1836
|
def as_json
|
1672
1837
|
[25, *lets.flat_map(&:as_json), body.as_json]
|
1673
1838
|
end
|
@@ -1683,4 +1848,14 @@ module Dhall
|
|
1683
1848
|
[26, value.as_json, type.as_json]
|
1684
1849
|
end
|
1685
1850
|
end
|
1851
|
+
|
1852
|
+
class Assertion < Expression
|
1853
|
+
include(ValueSemantics.for_attributes do
|
1854
|
+
type Expression
|
1855
|
+
end)
|
1856
|
+
|
1857
|
+
def as_json
|
1858
|
+
[19, type.as_json]
|
1859
|
+
end
|
1860
|
+
end
|
1686
1861
|
end
|