@grain/stdlib 0.5.12 → 0.6.0

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.
Files changed (155) hide show
  1. package/CHANGELOG.md +200 -0
  2. package/LICENSE +1 -1
  3. package/README.md +25 -2
  4. package/array.gr +1512 -199
  5. package/array.md +2032 -94
  6. package/bigint.gr +239 -140
  7. package/bigint.md +450 -106
  8. package/buffer.gr +595 -102
  9. package/buffer.md +903 -145
  10. package/bytes.gr +401 -110
  11. package/bytes.md +551 -63
  12. package/char.gr +228 -49
  13. package/char.md +373 -7
  14. package/exception.gr +26 -12
  15. package/exception.md +29 -5
  16. package/float32.gr +130 -109
  17. package/float32.md +185 -57
  18. package/float64.gr +112 -99
  19. package/float64.md +185 -57
  20. package/hash.gr +47 -37
  21. package/hash.md +21 -3
  22. package/int16.gr +430 -0
  23. package/int16.md +618 -0
  24. package/int32.gr +200 -269
  25. package/int32.md +254 -289
  26. package/int64.gr +142 -225
  27. package/int64.md +254 -289
  28. package/int8.gr +511 -0
  29. package/int8.md +786 -0
  30. package/json.gr +2084 -0
  31. package/json.md +608 -0
  32. package/list.gr +120 -68
  33. package/list.md +125 -80
  34. package/map.gr +560 -57
  35. package/map.md +672 -56
  36. package/marshal.gr +239 -227
  37. package/marshal.md +36 -4
  38. package/number.gr +626 -676
  39. package/number.md +738 -153
  40. package/option.gr +33 -35
  41. package/option.md +58 -42
  42. package/package.json +2 -2
  43. package/path.gr +148 -187
  44. package/path.md +47 -96
  45. package/pervasives.gr +75 -416
  46. package/pervasives.md +85 -180
  47. package/priorityqueue.gr +433 -74
  48. package/priorityqueue.md +422 -54
  49. package/queue.gr +362 -80
  50. package/queue.md +433 -38
  51. package/random.gr +67 -75
  52. package/random.md +68 -40
  53. package/range.gr +135 -63
  54. package/range.md +198 -43
  55. package/rational.gr +284 -0
  56. package/rational.md +545 -0
  57. package/regex.gr +933 -1066
  58. package/regex.md +59 -60
  59. package/result.gr +23 -25
  60. package/result.md +54 -39
  61. package/runtime/atof/common.gr +78 -82
  62. package/runtime/atof/common.md +22 -10
  63. package/runtime/atof/decimal.gr +102 -127
  64. package/runtime/atof/decimal.md +28 -7
  65. package/runtime/atof/lemire.gr +56 -71
  66. package/runtime/atof/lemire.md +9 -1
  67. package/runtime/atof/parse.gr +83 -110
  68. package/runtime/atof/parse.md +12 -2
  69. package/runtime/atof/slow.gr +28 -35
  70. package/runtime/atof/slow.md +9 -1
  71. package/runtime/atof/table.gr +19 -18
  72. package/runtime/atof/table.md +10 -2
  73. package/runtime/atoi/parse.gr +153 -136
  74. package/runtime/atoi/parse.md +50 -1
  75. package/runtime/bigint.gr +410 -517
  76. package/runtime/bigint.md +71 -57
  77. package/runtime/compare.gr +176 -85
  78. package/runtime/compare.md +31 -1
  79. package/runtime/dataStructures.gr +144 -32
  80. package/runtime/dataStructures.md +267 -31
  81. package/runtime/debugPrint.gr +34 -15
  82. package/runtime/debugPrint.md +37 -5
  83. package/runtime/equal.gr +53 -52
  84. package/runtime/equal.md +30 -1
  85. package/runtime/exception.gr +38 -47
  86. package/runtime/exception.md +10 -8
  87. package/runtime/gc.gr +23 -152
  88. package/runtime/gc.md +13 -17
  89. package/runtime/malloc.gr +31 -31
  90. package/runtime/malloc.md +11 -3
  91. package/runtime/numberUtils.gr +191 -172
  92. package/runtime/numberUtils.md +17 -9
  93. package/runtime/numbers.gr +1695 -1021
  94. package/runtime/numbers.md +1098 -134
  95. package/runtime/string.gr +540 -242
  96. package/runtime/string.md +76 -6
  97. package/runtime/unsafe/constants.gr +30 -13
  98. package/runtime/unsafe/constants.md +80 -0
  99. package/runtime/unsafe/conv.gr +55 -28
  100. package/runtime/unsafe/conv.md +41 -9
  101. package/runtime/unsafe/memory.gr +10 -30
  102. package/runtime/unsafe/memory.md +15 -19
  103. package/runtime/unsafe/tags.gr +37 -21
  104. package/runtime/unsafe/tags.md +88 -8
  105. package/runtime/unsafe/wasmf32.gr +30 -36
  106. package/runtime/unsafe/wasmf32.md +64 -56
  107. package/runtime/unsafe/wasmf64.gr +30 -36
  108. package/runtime/unsafe/wasmf64.md +64 -56
  109. package/runtime/unsafe/wasmi32.gr +49 -66
  110. package/runtime/unsafe/wasmi32.md +102 -94
  111. package/runtime/unsafe/wasmi64.gr +52 -79
  112. package/runtime/unsafe/wasmi64.md +108 -100
  113. package/runtime/utils/printing.gr +13 -15
  114. package/runtime/utils/printing.md +11 -3
  115. package/runtime/wasi.gr +294 -295
  116. package/runtime/wasi.md +62 -42
  117. package/set.gr +574 -64
  118. package/set.md +634 -54
  119. package/stack.gr +181 -64
  120. package/stack.md +271 -42
  121. package/string.gr +453 -533
  122. package/string.md +241 -151
  123. package/uint16.gr +369 -0
  124. package/uint16.md +585 -0
  125. package/uint32.gr +470 -0
  126. package/uint32.md +737 -0
  127. package/uint64.gr +471 -0
  128. package/uint64.md +737 -0
  129. package/uint8.gr +369 -0
  130. package/uint8.md +585 -0
  131. package/uri.gr +1093 -0
  132. package/uri.md +477 -0
  133. package/{sys → wasi}/file.gr +914 -500
  134. package/{sys → wasi}/file.md +454 -50
  135. package/wasi/process.gr +292 -0
  136. package/{sys → wasi}/process.md +164 -6
  137. package/wasi/random.gr +77 -0
  138. package/wasi/random.md +80 -0
  139. package/{sys → wasi}/time.gr +15 -22
  140. package/{sys → wasi}/time.md +5 -5
  141. package/immutablearray.gr +0 -929
  142. package/immutablearray.md +0 -1038
  143. package/immutablemap.gr +0 -493
  144. package/immutablemap.md +0 -479
  145. package/immutablepriorityqueue.gr +0 -360
  146. package/immutablepriorityqueue.md +0 -291
  147. package/immutableset.gr +0 -498
  148. package/immutableset.md +0 -449
  149. package/runtime/debug.gr +0 -2
  150. package/runtime/debug.md +0 -6
  151. package/runtime/unsafe/errors.gr +0 -36
  152. package/runtime/unsafe/errors.md +0 -204
  153. package/sys/process.gr +0 -254
  154. package/sys/random.gr +0 -79
  155. package/sys/random.md +0 -66
package/path.gr CHANGED
@@ -1,30 +1,32 @@
1
1
  /**
2
- * @module Path: Utilities for working with system paths.
3
- *
2
+ * Utilities for working with system paths.
3
+ *
4
4
  * This module treats paths purely as a data representation and does not
5
5
  * provide functionality for interacting with the file system.
6
- *
6
+ *
7
7
  * This module explicitly encodes whether a path is absolute or relative, and
8
8
  * whether it refers to a file or a directory, as part of the `Path` type.
9
9
  *
10
10
  * Paths in this module abide by a special POSIX-like representation/grammar
11
11
  * rather than one defined by a specific operating system. The rules are as
12
12
  * follows:
13
- *
13
+ *
14
14
  * - Path separators are denoted by `/` for POSIX-like paths
15
15
  * - Absolute paths may be rooted either at the POSIX-like root `/` or at Windows-like drive roots like `C:/`
16
16
  * - Paths referencing files must not include trailing forward slashes, but paths referencing directories may
17
17
  * - The path segment `.` indicates the relative "current" directory of a path, and `..` indicates the parent directory of a path
18
- *
19
- * @example import Path from "path"
20
- *
18
+ *
19
+ * @example from "path" include Path
20
+ *
21
21
  * @since v0.5.5
22
22
  */
23
- import String from "string"
24
- import List from "list"
25
- import Option from "option"
26
- import Result from "result"
27
- import Char from "char"
23
+ module Path
24
+
25
+ from "string" include String
26
+ from "list" include List
27
+ from "option" include Option
28
+ from "result" include Result
29
+ from "char" include Char
28
30
 
29
31
  // this module is influenced by https://github.com/reasonml/reason-native/blob/a0ddab6ab25237961e32d8732b0a222ec2372d4a/src/fp/Fp.re
30
32
  // with some modifications; reason-native license:
@@ -76,22 +78,18 @@ record TFileType<a> {
76
78
  }
77
79
 
78
80
  // Rel(Number) represents the number of directories up from the base point
79
- enum Base {
81
+ enum rec Base {
80
82
  Rel(Number),
81
83
  Abs(AbsoluteRoot),
82
- },
83
- type PathInfo = (Base, FileType, List<String>),
84
- record TBase<a> {
84
+ }
85
+ and type PathInfo = (Base, FileType, List<String>)
86
+ and record TBase<a> {
85
87
  base: Base,
86
- },
87
- /**
88
- * @section Types: Type declarations included in the Path module.
89
- */
90
-
88
+ }
91
89
  /**
92
90
  * Represents an absolute path's anchor point.
93
91
  */
94
- export enum AbsoluteRoot {
92
+ and provide enum AbsoluteRoot {
95
93
  Root,
96
94
  Drive(Char),
97
95
  }
@@ -101,28 +99,28 @@ export enum AbsoluteRoot {
101
99
  /**
102
100
  * Represents a relative path.
103
101
  */
104
- record Relative {
102
+ abstract record Relative {
105
103
  _rel: Void,
106
104
  }
107
105
 
108
106
  /**
109
107
  * Represents an absolute path.
110
108
  */
111
- record Absolute {
109
+ abstract record Absolute {
112
110
  _abs: Void,
113
111
  }
114
112
 
115
113
  /**
116
114
  * Represents a path referencing a file.
117
115
  */
118
- record File {
116
+ abstract record File {
119
117
  _file: Void,
120
118
  }
121
119
 
122
120
  /**
123
121
  * Represents a path referencing a directory.
124
122
  */
125
- record Directory {
123
+ abstract record Directory {
126
124
  _directory: Void,
127
125
  }
128
126
 
@@ -130,11 +128,11 @@ record Directory {
130
128
  * Represents a path typed on (`Absolute` or `Relative`) and (`File` or
131
129
  * `Directory`)
132
130
  */
133
- type TypedPath<a, b> = (TBase<a>, TFileType<b>, List<String>),
131
+ abstract type rec TypedPath<a, b> = (TBase<a>, TFileType<b>, List<String>)
134
132
  /**
135
133
  * Represents a system path.
136
134
  */
137
- export enum Path {
135
+ and provide enum Path {
138
136
  AbsoluteFile(TypedPath<Absolute, File>),
139
137
  AbsoluteDir(TypedPath<Absolute, Directory>),
140
138
  RelativeFile(TypedPath<Relative, File>),
@@ -144,7 +142,7 @@ export enum Path {
144
142
  /**
145
143
  * Represents a platform-specific path encoding scheme.
146
144
  */
147
- export enum Platform {
145
+ provide enum Platform {
148
146
  Windows,
149
147
  Posix,
150
148
  }
@@ -152,14 +150,14 @@ export enum Platform {
152
150
  /**
153
151
  * Represents an error that can occur when finding a property of a path.
154
152
  */
155
- export enum PathOperationError {
153
+ provide enum PathOperationError {
156
154
  IncompatiblePathType,
157
155
  }
158
156
 
159
157
  /**
160
158
  * Represents an error that can occur when appending paths.
161
159
  */
162
- export enum AppendError {
160
+ provide enum AppendError {
163
161
  AppendToFile,
164
162
  AppendAbsolute,
165
163
  }
@@ -167,7 +165,7 @@ export enum AppendError {
167
165
  /**
168
166
  * Represents the status of an ancestry check between two paths.
169
167
  */
170
- export enum AncestryStatus {
168
+ provide enum AncestryStatus {
171
169
  Descendant,
172
170
  Ancestor,
173
171
  Self,
@@ -178,7 +176,7 @@ export enum AncestryStatus {
178
176
  * Represents an error that can occur when the types of paths are incompatible
179
177
  * for an operation.
180
178
  */
181
- export enum IncompatibilityError {
179
+ provide enum IncompatibilityError {
182
180
  DifferentRoots,
183
181
  DifferentBases,
184
182
  }
@@ -186,15 +184,11 @@ export enum IncompatibilityError {
186
184
  /**
187
185
  * Represents possible errors for the `relativeTo` operation.
188
186
  */
189
- export enum RelativizationError {
187
+ provide enum RelativizationError {
190
188
  Incompatible(IncompatibilityError),
191
189
  ImpossibleRelativization,
192
190
  }
193
191
 
194
- /**
195
- * @section Values: Functions for working with Paths.
196
- */
197
-
198
192
  let makeToken = str => {
199
193
  match (str) {
200
194
  "." => Dot,
@@ -232,7 +226,7 @@ let lexPath = (pathStr, platform) => {
232
226
  for (let mut i = 0; i < len; i += 1) {
233
227
  if (isSeparator(String.charAt(i, pathStr))) {
234
228
  if (segBeginI != i) {
235
- let tok = makeToken(String.slice(segBeginI, i, pathStr))
229
+ let tok = makeToken(String.slice(segBeginI, end=i, pathStr))
236
230
  revTokens = [tok, ...revTokens]
237
231
  }
238
232
  revTokens = [Slash, ...revTokens]
@@ -240,7 +234,7 @@ let lexPath = (pathStr, platform) => {
240
234
  }
241
235
  }
242
236
  if (segBeginI < len) {
243
- let lastPart = String.slice(segBeginI, len, pathStr)
237
+ let lastPart = String.slice(segBeginI, end=len, pathStr)
244
238
  revTokens = [makeToken(lastPart), ...revTokens]
245
239
  }
246
240
  List.reverse(revTokens)
@@ -304,7 +298,7 @@ let parseAbs = (tokens, fileType) => {
304
298
  }
305
299
  }
306
300
 
307
- // TODO(#1496): expose these functions once module system added
301
+ // TODO(#1496): provide these functions once module system added
308
302
 
309
303
  let absoluteFile = tokens => {
310
304
  let pathOpt = parseAbs(tokens, File)
@@ -359,53 +353,37 @@ let fromStringHelper = (pathStr, platform) => {
359
353
  }
360
354
  let isDir = !isFilePath(tokens)
361
355
 
362
- let path = (variant, mkPath, pathType) => {
363
- variant(
364
- Option.expect("Impossible: failed parse of " ++ pathType, mkPath(tokens))
365
- )
356
+ let path = (mkPath, pathType) => {
357
+ Option.expect("Impossible: failed parse of " ++ pathType, mkPath(tokens))
366
358
  }
367
359
 
368
360
  match ((isAbs, isDir)) {
369
- (true, true) => path(AbsoluteDir, absoluteDir, "absolute dir"),
370
- (true, false) => path(AbsoluteFile, absoluteFile, "absolute file"),
371
- (false, true) => path(RelativeDir, relativeDir, "relative dir"),
372
- (false, false) => path(RelativeFile, relativeFile, "relative file"),
361
+ (true, true) => AbsoluteDir(path(absoluteDir, "absolute dir")),
362
+ (true, false) => AbsoluteFile(path(absoluteFile, "absolute file")),
363
+ (false, true) => RelativeDir(path(relativeDir, "relative dir")),
364
+ (false, false) => RelativeFile(path(relativeFile, "relative file")),
373
365
  }
374
366
  }
375
367
 
376
- /**
377
- * Parses a path string into a `Path`. Paths will be parsed as file paths
378
- * rather than directory paths if there is ambiguity.
379
- *
380
- * @param pathStr: The string to parse as a path
381
- * @returns The path wrapped with details encoded within the type
382
- *
383
- * @example fromString("/bin/") // an absolute Path referencing the directory /bin/
384
- * @example fromString("file.txt") // a relative Path referencing the file ./file.txt
385
- * @example fromString(".") // a relative Path referencing the current directory
386
- *
387
- * @since v0.5.5
388
- */
389
- export let fromString = pathStr => {
390
- fromStringHelper(pathStr, Posix)
391
- }
392
-
393
368
  /**
394
369
  * Parses a path string into a `Path` using the path separators appropriate to
395
370
  * the given platform (`/` for `Posix` and either `/` or `\` for `Windows`).
396
371
  * Paths will be parsed as file paths rather than directory paths if there is
397
372
  * ambiguity.
398
- *
373
+ *
399
374
  * @param pathStr: The string to parse as a path
400
375
  * @param platform: The platform whose path separators should be used for parsing
401
376
  * @returns The path wrapped with details encoded within the type
402
- *
403
- * @example fromPlatformString("/bin/", Posix) // an absolute Path referencing the directory /bin/
404
- * @example fromPlatformString("C:\\file.txt", Windows) // a relative Path referencing the file C:\file.txt
405
- *
377
+ *
378
+ * @example fromString("file.txt") // a relative Path referencing the file ./file.txt
379
+ * @example fromString(".") // a relative Path referencing the current directory
380
+ * @example fromString("/bin/", Posix) // an absolute Path referencing the directory /bin/
381
+ * @example fromString("C:\\file.txt", Windows) // a relative Path referencing the file C:\file.txt
382
+ *
406
383
  * @since v0.5.5
384
+ * @history v0.6.0: Merged with `fromPlatformString`; modified signature to accept platform
407
385
  */
408
- export let fromPlatformString = (pathStr, platform) => {
386
+ provide let fromString = (pathStr, platform=Posix) => {
409
387
  fromStringHelper(pathStr, platform)
410
388
  }
411
389
 
@@ -436,66 +414,52 @@ let toStringHelper = (path, platform) => {
436
414
  List.join(sep, segs)
437
415
  }
438
416
 
439
- /**
440
- * Converts the given `Path` into a string, using the `/` path separator.
441
- * A trailing slash is added to directory paths.
442
- *
443
- * @param path: The path to convert to a string
444
- * @returns A string representing the given path
445
- *
446
- * @example toString(fromString("/file.txt")) == "/file.txt"
447
- * @example toString(fromString("dir/")) == "./dir/"
448
- *
449
- * @since v0.5.5
450
- */
451
- export let toString = path => {
452
- toStringHelper(pathInfo(path), Posix)
453
- }
454
-
455
417
  /**
456
418
  * Converts the given `Path` into a string, using the canonical path separator
457
419
  * appropriate to the given platform (`/` for `Posix` and `\` for `Windows`).
458
420
  * A trailing slash is added to directory paths.
459
- *
421
+ *
460
422
  * @param path: The path to convert to a string
461
423
  * @param platform: The `Platform` to use to represent the path as a string
462
424
  * @returns A string representing the given path
463
- *
464
- * @example toPlatformString(fromString("dir/"), Posix) == "./dir/"
465
- * @example toPlatformString(fromString("C:/file.txt"), Windows) == "C:\\file.txt"
466
- *
425
+ *
426
+ * @example toString(fromString("/file.txt")) == "/file.txt"
427
+ * @example toString(fromString("dir/"), Posix) == "./dir/"
428
+ * @example toString(fromString("C:/file.txt"), Windows) == "C:\\file.txt"
429
+ *
467
430
  * @since v0.5.5
431
+ * @history v0.6.0: Merged with `toPlatformString`; modified signature to accept platform
468
432
  */
469
- export let toPlatformString = (path, platform) => {
433
+ provide let toString = (path, platform=Posix) => {
470
434
  toStringHelper(pathInfo(path), platform)
471
435
  }
472
436
 
473
437
  /**
474
438
  * Determines whether the path is a directory path.
475
- *
439
+ *
476
440
  * @param path: The path to inspect
477
441
  * @returns `true` if the path is a directory path or `false` otherwise
478
- *
442
+ *
479
443
  * @example isDirectory(fromString("file.txt")) == false
480
444
  * @example isDirectory(fromString("/bin/")) == true
481
- *
445
+ *
482
446
  * @since v0.5.5
483
447
  */
484
- export let isDirectory = path => {
448
+ provide let isDirectory = path => {
485
449
  let (_, fileType, _) = pathInfo(path)
486
450
  fileType == Dir
487
451
  }
488
452
 
489
453
  /**
490
454
  * Determines whether the path is an absolute path.
491
- *
455
+ *
492
456
  * @param path: The path to inspect
493
457
  * @returns `true` if the path is absolute or `false` otherwise
494
- *
458
+ *
495
459
  * @example isAbsolute(fromString("/Users/me")) == true
496
460
  * @example isAbsolute(fromString("./file.txt")) == false
497
461
  */
498
- export let isAbsolute = path => {
462
+ provide let isAbsolute = path => {
499
463
  let (base, _, _) = pathInfo(path)
500
464
  match (base) {
501
465
  Abs(_) => true,
@@ -506,32 +470,33 @@ export let isAbsolute = path => {
506
470
  // should only be used on relative path appended to directory path
507
471
  let rec appendHelper = (path: PathInfo, toAppend: PathInfo) =>
508
472
  match (toAppend) {
509
- (Rel(up2), ft, s2) =>
510
- match (path) {
511
- (Rel(up1), _, []) => (Rel(up1 + up2), ft, s2),
512
- (Abs(_) as d, _, []) => (d, ft, s2),
513
- (d, pft, [_, ...rest] as s1) => {
514
- if (up2 > 0) appendHelper((d, pft, rest), (Rel(up2 - 1), ft, s2))
515
- else (d, ft, List.append(s2, s1))
516
- },
473
+ (Rel(up2), ft, s2) => match (path) {
474
+ (Rel(up1), _, []) => (Rel(up1 + up2), ft, s2),
475
+ (Abs(_) as d, _, []) => (d, ft, s2),
476
+ (d, pft, [_, ...rest] as s1) => {
477
+ if (up2 > 0)
478
+ appendHelper((d, pft, rest), (Rel(up2 - 1), ft, s2))
479
+ else
480
+ (d, ft, List.append(s2, s1))
517
481
  },
482
+ },
518
483
  (Abs(_), _, _) => fail "Impossible: relative path encoded as absolute path",
519
484
  }: PathInfo
520
485
 
521
486
  /**
522
487
  * Creates a new path by appending a relative path segment to a directory path.
523
- *
488
+ *
524
489
  * @param path: The base path
525
490
  * @param toAppend: The relative path to append
526
491
  * @returns `Ok(path)` combining the base and appended paths or `Err(err)` if the paths are incompatible
527
- *
492
+ *
528
493
  * @example append(fromString("./dir/"), fromString("file.txt")) == Ok(fromString("./dir/file.txt"))
529
494
  * @example append(fromString("a.txt"), fromString("b.sh")) == Err(AppendToFile) // cannot append to file path
530
495
  * @example append(fromString("./dir/"), fromString("/dir2")) == Err(AppendAbsolute) // cannot append an absolute path
531
- *
496
+ *
532
497
  * @since v0.5.5
533
498
  */
534
- export let append = (path: Path, toAppend: Path) => {
499
+ provide let append = (path: Path, toAppend: Path) => {
535
500
  match ((pathInfo(path), pathInfo(toAppend))) {
536
501
  ((_, File, _), _) => Err(AppendToFile),
537
502
  (_, (Abs(_), _, _)) => Err(AppendAbsolute),
@@ -561,8 +526,10 @@ let relativeToHelper = (source: PathInfo, dest: PathInfo) => {
561
526
  let result = match ((source, dest)) {
562
527
  ((_, File, [name, ..._]), _) when source == dest => Ok((1, [name])),
563
528
  ((Abs(r1), _, s1), (Abs(r2), _, s2)) =>
564
- if (r1 != r2) Err(Incompatible(DifferentRoots))
565
- else relativizeDepth((0, List.reverse(s1)), (0, List.reverse(s2))),
529
+ if (r1 != r2)
530
+ Err(Incompatible(DifferentRoots))
531
+ else
532
+ relativizeDepth((0, List.reverse(s1)), (0, List.reverse(s2))),
566
533
  ((Rel(up1), _, s1), (Rel(up2), _, s2)) =>
567
534
  relativizeDepth((up1, List.reverse(s1)), (up2, List.reverse(s2))),
568
535
  _ => fail "Impossible: paths should have both been absolute or relative",
@@ -578,45 +545,44 @@ let relativeToHelper = (source: PathInfo, dest: PathInfo) => {
578
545
  /**
579
546
  * Attempts to construct a new relative path which will lead to the destination
580
547
  * path from the source path.
581
- *
548
+ *
582
549
  * If the source and destination are incompatible in their bases, the result
583
550
  * will be `Err(IncompatibilityError)`.
584
551
  *
585
552
  * If the route to the destination cannot be concretely determined from the
586
553
  * source, the result will be `Err(ImpossibleRelativization)`.
587
- *
554
+ *
588
555
  * @param source: The source path
589
556
  * @param dest: The destination path to resolve
590
557
  * @returns `Ok(path)` containing the relative path if successfully resolved or `Err(err)` otherwise
591
- *
558
+ *
592
559
  * @example relativeTo(fromString("/usr"), fromString("/usr/bin")) == Ok(fromString("./bin"))
593
560
  * @example relativeTo(fromString("/home/me"), fromString("/home/me")) == Ok(fromString("."))
594
561
  * @example relativeTo(fromString("/file.txt"), fromString("/etc/")) == Ok(fromString("../etc/"))
595
562
  * @example relativeTo(fromString(".."), fromString("../../thing")) Ok(fromString("../thing"))
596
563
  * @example relativeTo(fromString("/usr/bin"), fromString("C:/Users")) == Err(Incompatible(DifferentRoots))
597
564
  * @example relativeTo(fromString("../here"), fromString("./there")) == Err(ImpossibleRelativization)
598
- *
565
+ *
599
566
  * @since v0.5.5
600
567
  */
601
- export let relativeTo = (source, dest) => {
568
+ provide let relativeTo = (source, dest) => {
602
569
  let pathInfo1 = pathInfo(source)
603
570
  let (base1, _, _) = pathInfo1
604
571
  let pathInfo2 = pathInfo(dest)
605
572
  let (base2, _, _) = pathInfo2
606
573
  match ((base1, base2)) {
607
- (Abs(_), Rel(_)) | (Abs(_), Rel(_)) => Err(Incompatible(DifferentBases)),
574
+ (Abs(_), Rel(_)) | (Rel(_), Abs(_)) => Err(Incompatible(DifferentBases)),
608
575
  _ => Result.map(toPath, relativeToHelper(pathInfo1, pathInfo2)),
609
576
  }
610
577
  }
611
578
 
612
- let rec segsAncestry = (baseSegs, pathSegs) =>
613
- match ((baseSegs, pathSegs)) {
614
- ([], []) => Self,
615
- ([], _) => Descendant,
616
- (_, []) => Ancestor,
617
- ([first1, ..._], [first2, ..._]) when first1 != first2 => NoLineage,
618
- ([_, ...rest1], [_, ...rest2]) => segsAncestry(rest1, rest2),
619
- }
579
+ let rec segsAncestry = (baseSegs, pathSegs) => match ((baseSegs, pathSegs)) {
580
+ ([], []) => Self,
581
+ ([], _) => Descendant,
582
+ (_, []) => Ancestor,
583
+ ([first1, ..._], [first2, ..._]) when first1 != first2 => NoLineage,
584
+ ([_, ...rest1], [_, ...rest2]) => segsAncestry(rest1, rest2),
585
+ }
620
586
 
621
587
  // should be used on paths with same absolute/relativeness
622
588
  let ancestryHelper = (base: PathInfo, path: PathInfo) => {
@@ -630,22 +596,22 @@ let ancestryHelper = (base: PathInfo, path: PathInfo) => {
630
596
 
631
597
  /**
632
598
  * Determines the relative ancestry betwen two paths.
633
- *
599
+ *
634
600
  * @param base: The first path to consider
635
601
  * @param path: The second path to consider
636
602
  * @returns `Ok(ancestryStatus)` with the relative ancestry between the paths if they are compatible or `Err(err)` if they are incompatible
637
- *
603
+ *
638
604
  * @example ancestry(fromString("/usr"), fromString("/usr/bin/bash")) == Ok(Ancestor)
639
605
  * @example ancestry(fromString("/Users/me"), fromString("/Users")) == Ok(Descendant)
640
606
  * @example ancestry(fromString("/usr"), fromString("/etc")) == Ok(Neither)
641
607
  * @example ancestry(fromString("C:/dir1"), fromString("/dir2")) == Err(DifferentRoots)
642
- *
608
+ *
643
609
  * @since v0.5.5
644
610
  */
645
- export let ancestry = (path1: Path, path2: Path) => {
646
- let pathInfo1 = pathInfo(path1)
611
+ provide let ancestry = (base: Path, path: Path) => {
612
+ let pathInfo1 = pathInfo(base)
647
613
  let (base1, _, _) = pathInfo1
648
- let pathInfo2 = pathInfo(path2)
614
+ let pathInfo2 = pathInfo(path)
649
615
  let (base2, _, _) = pathInfo2
650
616
  match ((base1, base2)) {
651
617
  (Rel(_), Abs(_)) | (Abs(_), Rel(_)) => Err(DifferentBases),
@@ -653,81 +619,77 @@ export let ancestry = (path1: Path, path2: Path) => {
653
619
  }
654
620
  }
655
621
 
656
- let parentHelper = (path: PathInfo) =>
657
- match (path) {
658
- (base, _, [_, ...rest]) => (base, Dir, rest),
659
- (Rel(upDirs), _, []) => (Rel(upDirs + 1), Dir, []),
660
- (Abs(_) as base, _, []) => (base, Dir, []),
661
- }: PathInfo
622
+ let parentHelper = (path: PathInfo) => match (path) {
623
+ (base, _, [_, ...rest]) => (base, Dir, rest),
624
+ (Rel(upDirs), _, []) => (Rel(upDirs + 1), Dir, []),
625
+ (Abs(_) as base, _, []) => (base, Dir, []),
626
+ }: PathInfo
662
627
 
663
628
  /**
664
629
  * Retrieves the path corresponding to the parent directory of the given path.
665
- *
630
+ *
666
631
  * @param path: The path to inspect
667
632
  * @returns A path corresponding to the parent directory of the given path
668
- *
633
+ *
669
634
  * @example parent(fromString("./dir/inner")) == fromString("./dir/")
670
635
  * @example parent(fromString("/")) == fromString("/")
671
- *
636
+ *
672
637
  * @since v0.5.5
673
638
  */
674
- export let parent = (path: Path) => {
639
+ provide let parent = (path: Path) => {
675
640
  toPath(parentHelper(pathInfo(path)))
676
641
  }
677
642
 
678
- let basenameHelper = (path: PathInfo) =>
679
- match (path) {
680
- (_, _, [name, ..._]) => Some(name),
681
- _ => None,
682
- }
643
+ let basenameHelper = (path: PathInfo) => match (path) {
644
+ (_, _, [name, ..._]) => Some(name),
645
+ _ => None,
646
+ }
683
647
 
684
648
  /**
685
649
  * Retrieves the basename (named final segment) of a path.
686
- *
650
+ *
687
651
  * @param path: The path to inspect
688
652
  * @returns `Some(path)` containing the basename of the path or `None` if the path does not have one
689
- *
653
+ *
690
654
  * @example basename(fromString("./dir/file.txt")) == Some("file.txt")
691
655
  * @example basename(fromString(".."))) == None
692
- *
656
+ *
693
657
  * @since v0.5.5
694
658
  */
695
- export let basename = (path: Path) => {
659
+ provide let basename = (path: Path) => {
696
660
  basenameHelper(pathInfo(path))
697
661
  }
698
662
 
699
663
  // should only be used on file paths
700
- let stemExtHelper = (path: PathInfo) =>
701
- match (path) {
702
- (_, _, [name, ..._]) => {
703
- let len = String.length(name)
704
- // trim first character (which is possibly a .) off as trick for
705
- // splitting .a.b.c into .a, .b.c
706
- match (String.indexOf(".", String.slice(1, len, name))) {
707
- Some(dotI) => {
708
- let dotI = dotI + 1
709
- (String.slice(0, dotI, name), String.slice(dotI, len, name))
710
- },
711
- None => (name, ""),
712
- }
713
- },
714
- _ => ("", ""),
715
- }
664
+ let stemExtHelper = (path: PathInfo) => match (path) {
665
+ (_, _, [name, ..._]) => {
666
+ // trim first character (which is possibly a .) off as trick for
667
+ // splitting .a.b.c into .a, .b.c
668
+ match (String.indexOf(".", String.slice(1, name))) {
669
+ Some(dotI) => {
670
+ let dotI = dotI + 1
671
+ (String.slice(0, end=dotI, name), String.slice(dotI, name))
672
+ },
673
+ None => (name, ""),
674
+ }
675
+ },
676
+ _ => ("", ""),
677
+ }
716
678
 
717
679
  /**
718
680
  * Retrieves the basename of a file path without the extension.
719
- *
681
+ *
720
682
  * @param path: The path to inspect
721
683
  * @returns `Ok(path)` containing the stem of the file path or `Err(err)` if the path is a directory path
722
- *
684
+ *
723
685
  * @example stem(fromString("file.txt")) == Ok("file")
724
686
  * @example stem(fromString(".gitignore")) == Ok(".gitignore")
725
687
  * @example stem(fromString(".a.tar.gz")) == Ok(".a")
726
688
  * @example stem(fromString("/dir/")) == Err(IncompatiblePathType) // can only take stem of a file path
727
- *
689
+ *
728
690
  * @since v0.5.5
729
691
  */
730
- export let stem = (path: Path) => {
692
+ provide let stem = (path: Path) => {
731
693
  match (pathInfo(path)) {
732
694
  (_, Dir, _) => Err(IncompatiblePathType),
733
695
  pathInfo => {
@@ -739,18 +701,18 @@ export let stem = (path: Path) => {
739
701
 
740
702
  /**
741
703
  * Retrieves the extension on the basename of a file path.
742
- *
704
+ *
743
705
  * @param path: The path to inspect
744
706
  * @returns `Ok(path)` containing the extension of the file path or `Err(err)` if the path is a directory path
745
- *
707
+ *
746
708
  * @example extension(fromString("file.txt")) == Ok(".txt")
747
709
  * @example extension(fromString(".gitignore")) == Ok("")
748
710
  * @example extension(fromString(".a.tar.gz")) == Ok(".tar.gz")
749
711
  * @example extension(fromString("/dir/")) == Err(IncompatiblePathType) // can only take extension of a file path
750
- *
712
+ *
751
713
  * @since v0.5.5
752
714
  */
753
- export let extension = (path: Path) => {
715
+ provide let extension = (path: Path) => {
754
716
  match (pathInfo(path)) {
755
717
  (_, Dir, _) => Err(IncompatiblePathType),
756
718
  pathInfo => {
@@ -761,25 +723,24 @@ export let extension = (path: Path) => {
761
723
  }
762
724
 
763
725
  // should only be used on absolute paths
764
- let rootHelper = (path: PathInfo) =>
765
- match (path) {
766
- (Abs(root), _, _) => root,
767
- _ => fail "Impossible: malformed absolute path data",
768
- }
726
+ let rootHelper = (path: PathInfo) => match (path) {
727
+ (Abs(root), _, _) => root,
728
+ _ => fail "Impossible: malformed absolute path data",
729
+ }
769
730
 
770
731
  /**
771
732
  * Retrieves the root of the absolute path.
772
- *
733
+ *
773
734
  * @param path: The path to inspect
774
735
  * @returns `Ok(root)` containing the root of the path or `Err(err)` if the path is a relative path
775
- *
736
+ *
776
737
  * @example root(fromString("C:/Users/me/")) == Ok(Drive('C'))
777
738
  * @example root(fromString("/home/me/")) == Ok(Root)
778
739
  * @example root(fromString("./file.txt")) == Err(IncompatiblePathType)
779
- *
740
+ *
780
741
  * @since v0.5.5
781
742
  */
782
- export let root = (path: Path) => {
743
+ provide let root = (path: Path) => {
783
744
  match (pathInfo(path)) {
784
745
  (Rel(_), _, _) => Err(IncompatiblePathType),
785
746
  pathInfo => Ok(rootHelper(pathInfo)),