@effekt-lang/effekt 0.3.0 → 0.5.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 (44) hide show
  1. package/README.md +6 -18
  2. package/bin/effekt +0 -0
  3. package/libraries/common/args.effekt +0 -27
  4. package/libraries/common/array.effekt +34 -63
  5. package/libraries/common/bench.effekt +40 -22
  6. package/libraries/common/buffer.effekt +8 -20
  7. package/libraries/common/bytes.effekt +5 -15
  8. package/libraries/common/dequeue.effekt +5 -5
  9. package/libraries/common/effekt.effekt +51 -92
  10. package/libraries/common/exception.effekt +0 -1
  11. package/libraries/common/io/console.effekt +30 -36
  12. package/libraries/common/io/error.effekt +131 -30
  13. package/libraries/common/io/filesystem.effekt +262 -0
  14. package/libraries/common/io/network.effekt +30 -54
  15. package/libraries/common/io/time.effekt +9 -12
  16. package/libraries/common/io.effekt +54 -124
  17. package/libraries/common/list.effekt +345 -327
  18. package/libraries/common/process.effekt +0 -1
  19. package/libraries/common/queue.effekt +1 -3
  20. package/libraries/common/ref.effekt +11 -24
  21. package/libraries/common/result.effekt +6 -14
  22. package/libraries/common/seq.effekt +28 -49
  23. package/libraries/common/string/tty.effekt +66 -0
  24. package/libraries/common/string.effekt +7 -49
  25. package/libraries/common/test.effekt +96 -34
  26. package/libraries/js/unsafe/cont.effekt +1 -1
  27. package/libraries/llvm/io.c +258 -378
  28. package/libraries/llvm/main.c +3 -0
  29. package/libraries/llvm/rts.ll +57 -38
  30. package/libraries/llvm/types.c +10 -1
  31. package/licenses/eclipse public license, version 2.0 - epl-2.0.html +4 -4
  32. package/licenses/mit license - mit-license.html +21 -20
  33. package/licenses/the bsd license - bsd-license.html +20 -21
  34. package/licenses/the mit license - mit.html +22 -21
  35. package/package.json +1 -1
  36. package/libraries/chez/lift/effekt.ss +0 -118
  37. package/libraries/common/io/files.effekt +0 -282
  38. package/libraries/js/io.js +0 -143
  39. package/libraries/llvm/io.ll +0 -19
  40. package/libraries/ml/effekt.sml +0 -65
  41. package/libraries/ml/internal/mllist.effekt +0 -9
  42. package/libraries/ml/internal/mloption.effekt +0 -18
  43. package/libraries/ml/random.effekt +0 -85
  44. package/libraries/ml/text/regex.effekt +0 -102
@@ -1,143 +0,0 @@
1
-
2
- /**
3
- * Maps the error code to a Effekt-stable (platform independent) numeric value.
4
- *
5
- * Tries to use most common errno integer values, but introduces fresh values (> 200)
6
- * for those without common errno values.
7
- */
8
- function errnoToStableId(errorName) {
9
- const errorMap = {
10
- EPERM: 1,
11
- ENOENT: 2,
12
- ESRCH: 3,
13
- EINTR: 4,
14
- EIO: 5,
15
- ENXIO: 6,
16
- E2BIG: 7,
17
- EBADF: 9,
18
- EAGAIN: 11,
19
- ENOMEM: 12,
20
- EACCES: 13,
21
- EFAULT: 14,
22
- EBUSY: 16,
23
- EEXIST: 17,
24
- EXDEV: 18,
25
- ENODEV: 19,
26
- ENOTDIR: 20,
27
- EISDIR: 21,
28
- EINVAL: 22,
29
- ENFILE: 23,
30
- EMFILE: 24,
31
- ENOTTY: 25,
32
- ETXTBSY: 26,
33
- EFBIG: 27,
34
- ENOSPC: 28,
35
- ESPIPE: 29,
36
- EROFS: 30,
37
- EMLINK: 31,
38
- EPIPE: 32,
39
- ERANGE: 34,
40
- ENAMETOOLONG: 36,
41
- ELOOP: 40,
42
- EOVERFLOW: 75,
43
- EFTYPE: 79,
44
- EILSEQ: 84,
45
- ENOTSOCK: 88,
46
- EDESTADDRREQ: 89,
47
- EMSGSIZE: 90,
48
- EPROTOTYPE: 91,
49
- ENOPROTOOPT: 92,
50
- EPROTONOSUPPORT: 93,
51
- ESOCKTNOSUPPORT: 94,
52
- ENOTSUP: 95,
53
- EAFNOSUPPORT: 97,
54
- EADDRINUSE: 98,
55
- EADDRNOTAVAIL: 99,
56
- ENETDOWN: 100,
57
- ENETUNREACH: 101,
58
- ECONNABORTED: 103,
59
- ECONNRESET: 104,
60
- ENOBUFS: 105,
61
- EISCONN: 106,
62
- ENOTCONN: 107,
63
- ETIMEDOUT: 110,
64
- ECONNREFUSED: 111,
65
- EHOSTUNREACH: 113,
66
- EALREADY: 114,
67
- ECANCELED: 125,
68
- EAI_ADDRFAMILY: 200,
69
- EAI_AGAIN: 201,
70
- EAI_BADFLAGS: 202,
71
- EAI_BADHINTS: 203,
72
- EAI_CANCELED: 204,
73
- EAI_FAIL: 205,
74
- EAI_FAMILY: 206,
75
- EAI_MEMORY: 207,
76
- EAI_NODATA: 208,
77
- EAI_NONAME: 209,
78
- EAI_OVERFLOW: 210,
79
- EAI_PROTOCOL: 211,
80
- EAI_SERVICE: 212,
81
- EAI_SOCKTYPE: 213,
82
- ECHARSET: 215,
83
- ENONET: 216,
84
- UNKNOWN: 217,
85
- EOF: 218,
86
- EUNATCH: 219,
87
- ESHUTDOWN: 220
88
- };
89
-
90
- return errorMap[errorName] || -1; // Default to -1 for unknown error names
91
- }
92
-
93
- function openFile(path, mode, onSuccess, onFailure) {
94
- fs.open(path, mode,
95
- (err, fd) => {
96
- if (!!err) {
97
- console.error(err)
98
- return onFailure(errnoToStableId(err.code)).run();
99
- } else {
100
- return onSuccess(fd).run();
101
- }
102
- });
103
- return $effekt.unit;
104
- }
105
-
106
- function readFile(fd, buffer, offset, onSuccess, onFailure) {
107
- let position = offset === -1 ? null : offset;
108
- fs.read(fd, toBuffer(buffer), 0, buffer.length, position,
109
- (err, bytesRead) => {
110
- if (!!err) {
111
- return onFailure(errnoToStableId(err.code)).run()
112
- } else {
113
- return onSuccess(bytesRead).run()
114
- }
115
- })
116
- return $effekt.unit;
117
- }
118
-
119
- /**
120
- * @see {https://nodejs.org/api/fs.html#fswritefd-buffer-offset-length-position-callback
121
- */
122
- function writeFile(fd, buffer, offset, onSuccess, onFailure) {
123
- let position = offset === -1 ? null : offset;
124
- fs.write(fd, toBuffer(buffer), 0, buffer.length, position,
125
- (err, bytesWritten) => {
126
- if (!!err) {
127
- return onFailure(errnoToStableId(err.code)).run()
128
- } else {
129
- return onSuccess(bytesWritten).run()
130
- }
131
- })
132
- return $effekt.unit;
133
- }
134
-
135
-
136
-
137
- /**
138
- * Nodejs file operations expect buffers, but we represent buffers as typed arrays.
139
- * This function converts between the two without copying.
140
- */
141
- function toBuffer(buffer) {
142
- return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength)
143
- }
@@ -1,19 +0,0 @@
1
- declare i64 @uv_error_to_errno(i64)
2
- declare ptr @uv_strerror(i32)
3
-
4
- declare ptr @uv_default_loop()
5
- declare i32 @uv_run(ptr, i32)
6
- declare void @uv_stop(ptr)
7
- declare void @uv_loop_close(ptr)
8
-
9
- ; Helpers defined in C
10
- declare void @c_timer_wait(i64, %Neg)
11
- declare i64 @c_file_open(%Pos, %Pos, %Neg, %Neg)
12
- declare void @c_file_close(%Pos)
13
- declare void @c_file_read(i32, %Pos, i64, ptr, ptr)
14
- declare void @c_file_write(i32, %Pos, i64, ptr, ptr)
15
- declare %Pos @c_filedescriptor_show(%Pos)
16
-
17
- declare %Pos @c_promise_make()
18
- declare void @c_promise_resolve(%Pos, %Pos)
19
- declare void @c_promise_await(%Pos, %Neg)
@@ -1,65 +0,0 @@
1
- (* EVIDENCE *)
2
- fun lift m k1 k2 = m (fn a => k1 a k2);
3
- fun nested ev1 ev2 m = ev1 (ev2 m);
4
- fun here x = x;
5
-
6
- (* REGIONS *)
7
- (* type region = ((() -> () -> ()) list) ref *)
8
- fun newRegion () = ref nil
9
- fun backup cell = fn () => let val oldState = !cell in fn () => cell := oldState end
10
- fun fresh r init = let val cell = ref init in (r := (backup cell) :: (!r); cell) end
11
- fun withRegion body =
12
- let val r = newRegion()
13
- fun lift m k = let val fields = map (fn f => f()) (!r) in
14
- m (fn a => (map (fn f => f()) fields; k a)) end
15
- in body lift r end
16
-
17
- (* SHOW INSTANCES *)
18
- fun show'int x =
19
- let val s = (Int.toString x) in
20
- case String.sub (s, 0) of
21
- #"~" => "-" ^ String.extract (s, 1, NONE)
22
- | _ => s
23
- end;
24
-
25
- (*
26
- To align with the js backend inf and nan is rewritten
27
- - `nan` -> `NaN`
28
- - `inf` -> `Infinity`
29
- - `~2.1` -> `-2.1`
30
- They do still disagree on the truncating of `2.0` to `2` (ml does not).
31
- *)
32
- fun show'real x =
33
- let val s = (Real.toString x) in
34
- case s of
35
- "nan" => "NaN"
36
- | "inf" => "Infinity"
37
- | _ => case String.sub (s, 0) of
38
- #"~" => "-" ^ String.extract (s, 1, NONE)
39
- | _ => s
40
- end;
41
-
42
- fun show'unit x = ""
43
-
44
- fun show'bool x = Bool.toString x
45
-
46
- fun show'string x = x
47
-
48
- (* TIMING *)
49
- val mlStartTime = Time.toMilliseconds (Time.now ());
50
-
51
- (* RANDOM *)
52
- fun mlRandomReal () =
53
- let
54
- val r = MLton.Random.rand ();
55
- val rreal = MLton.Real.fromWord r;
56
- val wsize = Real.fromInt Word.wordSize;
57
- fun shiftRight r shift = r / (Math.pow(2.0, shift))
58
- in
59
- shiftRight rreal wsize
60
- end;
61
-
62
- (* HOLES *)
63
- exception Hole
64
-
65
- exception Absurd
@@ -1,9 +0,0 @@
1
- module internal/mllist
2
-
3
- extern type MLList[Elem] // = 'elem list
4
- extern pure def isEmpty[A](l: MLList[A]): Bool = ml "null ${l}"
5
- extern pure def head[A](l: MLList[A]): A = ml "hd ${l}"
6
- extern pure def tail[A](l: MLList[A]): MLList[A] = ml "tl ${l}"
7
-
8
- def toList[A](l: MLList[A]): List[A] =
9
- if (l.isEmpty) Nil() else Cons(l.head, toList(l.tail))
@@ -1,18 +0,0 @@
1
- module internal/mloption
2
-
3
- import effekt
4
- import option
5
-
6
- extern type MLOption[T]
7
-
8
- extern pure def isDefined[T](opt: MLOption[T]): Bool =
9
- ml "Option.isSome ${opt}"
10
-
11
- def isEmpty[T](opt: MLOption[T]): Bool = not(opt.isDefined())
12
-
13
- extern pure def force[T](opt: MLOption[T]): T =
14
- ml "Option.valOf ${opt}"
15
-
16
- def toOption[T](opt: MLOption[T]): Option[T] = {
17
- if (isDefined(opt)) Some(force(opt)) else None()
18
- }
@@ -1,85 +0,0 @@
1
- module random
2
-
3
- /**
4
- * Imperative Random Numbers
5
- * -------------------------
6
- * The following are simple bindings for the following SML/NJ module:
7
- * https://www.smlnj.org/doc/smlnj-lib/Util/str-Random.html
8
- *
9
- * They are not supposed to be used directly, but only via the
10
- * effect [[Random]], below.
11
- */
12
- extern type RNG // = int * int
13
- extern io def seed(n: Int, m: Int): RNG = ml "Random.rand (${n}, ${m})"
14
- extern pure def toString(s: RNG): String = ml "Random.toString ${s}"
15
-
16
- extern io def int(s: RNG): Int = ml "Random.randInt ${s}"
17
- extern io def int(s: RNG, from: Int, to: Int): Int = ml "Random.randRange (${from}, ${to}) ${s}"
18
- extern io def double(s: RNG): Double = ml "Random.randReal ${s}"
19
-
20
-
21
- /**
22
- * Functional Random Numbers
23
- * -------------------------
24
- * The following are simple bindings for the following SML/NJ module:
25
- * https://www.smlnj.org/doc/smlnj-lib/Util/str-Rand.html
26
- *
27
- * They are not supposed to be used directly, but only via the
28
- * effect [[Random]], below.
29
- */
30
- extern type PseudoRNG
31
- extern pure def random(s: PseudoRNG): PseudoRNG =
32
- ml "Rand.random ${s}"
33
- extern pure def range(s: PseudoRNG, n: Int, m: Int): Int =
34
- ml "Rand.range (${n}, ${m}) ${s}"
35
- extern pure def norm(s: PseudoRNG): Double =
36
- ml "Rand.norm ${s}"
37
-
38
- // converting two integers into a word that is between randMin and randMax is completely made up
39
- extern pure def pseudo(n: Int, m: Int): PseudoRNG =
40
- ml "Word.fromInt ((Word.toInt Rand.randMin) + ((abs (${n} * ${m})) mod (Word.toInt Rand.randMax)))"
41
-
42
-
43
-
44
- // "Public" API
45
- // ------------
46
-
47
- /**
48
- * A random number generator.
49
- *
50
- * Supposed to be used as an effect: `do randomInt(0, 10)`.
51
- * There are two canonical implementations as effect handlers (see below).
52
- */
53
- interface Random {
54
- // returns a random integer between `from` and `to`
55
- def randomInt(from: Int, to: Int): Int
56
- // returns a random double between 0.0 and 1.0
57
- def randomDouble(): Double
58
- }
59
-
60
- /**
61
- * Imperative random numbers. Does not perform backtracking.
62
- */
63
- def withRandom[R](n: Int, m: Int) { prog: => R / Random } = {
64
- // should be second class, is mutated...
65
- val rng = seed(n, m)
66
- try { prog() }
67
- with Random {
68
- def randomInt(from, to) = resume(rng.int(from, to))
69
- def randomDouble() = resume(rng.double())
70
- }
71
- }
72
-
73
- /**
74
- * Functional, pseudo random numbers. According to SMLNJ docs it is faster than the imperative version
75
- */
76
- def withPseudoRandom[R](n: Int, m: Int) { prog: => R / Random } = {
77
- // should be second class, is mutated...
78
- var rng = pseudo(n, m)
79
- def next() = rng = random(rng);
80
- try { prog() }
81
- with Random {
82
- def randomInt(from, to) = { next(); resume(rng.range(from, to)) }
83
- def randomDouble() = { next(); resume(rng.norm()) }
84
- }
85
- }
@@ -1,102 +0,0 @@
1
- module text/regex
2
-
3
- import internal/mllist
4
- import internal/mloption
5
-
6
- extern type Char // TODO move to text/string
7
- type Chars = MLList[Char]
8
-
9
-
10
- extern pure def chars(str: String): Chars = ml "String.explode ${str}"
11
- extern pure def toString(chars: Chars): String = ml "String.implode ${chars}"
12
-
13
- extern ml """
14
-
15
- (** The RegExp module is created by choosing a parser (P) and an engine (E)
16
- * for regular expressions.
17
- *
18
- * There is no big choice for the parser, since only Awk syntax is supported.
19
- * For the regular expression engine, we choose Ken Thompson's algorighm.
20
- *
21
- * Also see:
22
- * <https://stackoverflow.com/questions/35462919/how-to-use-regex-in-smlnj>
23
- * <https://www.smlnj.org/doc/smlnj-lib/RegExp/fun-RegExpFn.html>
24
- *)
25
- structure RegExp = RegExpFn(
26
- structure P = AwkSyntax
27
- structure E = ThompsonEngine
28
- (* structure E = BackTrackEngine *)
29
- (* structure E = DfaEngine *)
30
- )
31
- """
32
-
33
- // The type of regular expressions (ML representation)
34
- extern type Regex
35
-
36
- record Match(matched: String)
37
-
38
- // TODO handle CannotParse and CannotCompile ml exceptions.
39
- extern pure def regex(regexString: String): Regex =
40
- ml "RegExp.compileString ${regexString}"
41
-
42
-
43
- // A stream of elements of type Elem, read from a source of type Source
44
- extern type MLStream[Elem, Source] // = ('elem, 'source) StringCvt.reader
45
-
46
- // Internal ml type that represents matches
47
- // <https://www.smlnj.org/doc/smlnj-lib/RegExp/str-MatchTree.html>
48
- extern type MLMatchResult // = match * char list
49
-
50
- extern ml """
51
- type regex_match = {len: int, pos: char list} MatchTree.match_tree;
52
- fun matchedString (match : regex_match * char list) =
53
- let val res = MatchTree.root (#1 match)
54
- in String.implode (List.take (#pos res, #len res)) end;
55
-
56
- fun remainderChars (match : regex_match * char list) =
57
- let val res = MatchTree.root (#1 match)
58
- in List.drop (#pos res, #len res) end;
59
-
60
- (** The remainder is just a draft and doesn't work yet...) *)
61
-
62
- (** MatchTree -> string list **)
63
- fun allMatched (matchtree: regex_match) =
64
- MatchTree.foldl (fn (m, b) => (String.implode (List.take (#pos m, #len m))) :: b) nil matchtree
65
- fun allBut str = RegExp.compileString ("[^" ^ str ^ "]+");
66
-
67
- fun unsafeSplit str sep =
68
- case (RegExp.find (allBut str) List.getItem (String.explode str)) of
69
- NONE => nil
70
- | SOME v => allMatched (#1 v);
71
- """
72
-
73
- extern pure def getMatch(result: MLMatchResult): String =
74
- ml "matchedString ${result}"
75
- extern pure def getRemainder(result: MLMatchResult): Chars =
76
- ml "remainderChars ${result}"
77
-
78
- extern pure def unsafeSplit(str: String, ch: Char): MLList[String] =
79
- ml "String.fields (fn c => c = ${ch}) ${str}"
80
-
81
- extern pure def unsafeMatchPrefix(r: Regex, str: Chars): MLOption[MLMatchResult] =
82
- ml "RegExp.prefix ${r} List.getItem ${str}"
83
-
84
- extern pure def unsafeSplit(str: String, sep: String): MLList[String] =
85
- ml "unsafeSplit ${str} ${sep}"
86
-
87
- extern ml """
88
- val NEWLINE_CHAR = #"\n";
89
- """
90
-
91
- extern pure def unsafeLines(str: String): MLList[String] =
92
- ml "String.fields (fn c => c = NEWLINE_CHAR) ${str}"
93
-
94
- def lines(str: String): List[String] = unsafeLines(str).toList
95
-
96
- def split(str: String, sep: String): List[String] = unsafeSplit(str, sep).toList
97
-
98
- def exec(reg: Regex, str: String): Option[Match] = {
99
- val matched = reg.unsafeMatchPrefix(str.chars)
100
- if (matched.isDefined) { Some(Match(matched.force.getMatch())) }
101
- else { None() }
102
- }