@effekt-lang/effekt 0.8.0 → 0.10.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.
- package/README.md +1 -1
- package/bin/effekt +0 -0
- package/libraries/chez/callcc/effekt.ss +10 -23
- package/libraries/chez/monadic/effekt.ss +5 -13
- package/libraries/common/array.effekt +42 -31
- package/libraries/common/bytearray.effekt +22 -2
- package/libraries/common/char.effekt +58 -0
- package/libraries/common/effekt.effekt +5 -0
- package/libraries/common/io/filesystem.effekt +2 -2
- package/libraries/common/stream.effekt +419 -0
- package/libraries/common/string.effekt +0 -13
- package/libraries/js/effekt_runtime.js +5 -10
- package/libraries/llvm/bytearray.c +4 -4
- package/libraries/llvm/rts.ll +49 -159
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ If you are looking for examples of the Effekt language, we invite you to look at
|
|
|
17
17
|
|
|
18
18
|
## Installation
|
|
19
19
|
|
|
20
|
-
Please navigate to the [getting-started guide](https://effekt-lang.org/docs
|
|
20
|
+
Please navigate to the [getting-started guide](https://effekt-lang.org/docs) on our [website](https://effekt-lang.org) for detailed instructions of how to install Effekt.
|
|
21
21
|
|
|
22
22
|
## Contributing
|
|
23
23
|
|
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -1,28 +1,15 @@
|
|
|
1
|
+
(define (reset body)
|
|
2
|
+
(let ([p (newPrompt)])
|
|
3
|
+
(pushPrompt p (body p))))
|
|
1
4
|
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
; ; (let ((tmp86_121 ((Fail_109 Fail_22))))
|
|
5
|
-
; ; (Cons_73 tmp86_121 (Nil_74))))
|
|
6
|
-
; (define-syntax handle
|
|
7
|
-
; (syntax-rules ()
|
|
8
|
-
; [(_ ((cap1 (op1 (arg1 ...) k exp ...) ...) ...) body ...)
|
|
9
|
-
; (let ([P (newPrompt)])
|
|
10
|
-
; (pushPrompt P
|
|
11
|
-
; (let ([cap1 (cap1 (define-effect-op P (arg1 ...) k exp ...) ...)] ...)
|
|
12
|
-
; body ...)))]))
|
|
5
|
+
(define (shift p body)
|
|
6
|
+
(shift0-at p k (body k)))
|
|
13
7
|
|
|
14
|
-
(define-syntax
|
|
15
|
-
(syntax-rules ()
|
|
16
|
-
[(_
|
|
17
|
-
(
|
|
18
|
-
|
|
19
|
-
(body (cap1 (define-effect-op P (arg1 ...) k exp ...) ...) ...)))]))
|
|
20
|
-
|
|
21
|
-
(define-syntax define-effect-op
|
|
22
|
-
(syntax-rules ()
|
|
23
|
-
[(_ P (arg1 ...) k exp ...)
|
|
24
|
-
(lambda (arg1 ...)
|
|
25
|
-
(shift0-at P k exp ...))]))
|
|
8
|
+
;(define-syntax define-effect-op
|
|
9
|
+
; (syntax-rules ()
|
|
10
|
+
; [(_ P (arg1 ...) k exp ...)
|
|
11
|
+
; (lambda (arg1 ...)
|
|
12
|
+
; (shift0-at P k exp ...))]))
|
|
26
13
|
|
|
27
14
|
; state(init) { cell => ... }
|
|
28
15
|
(define (state init body)
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
(if (null? frames) (underflow v rest)
|
|
30
30
|
(values ((car frames) v) (cons (make-Stack (cdr frames) arena prompt) rest))))))
|
|
31
31
|
|
|
32
|
-
; Control
|
|
33
|
-
(define (reset
|
|
34
|
-
(
|
|
35
|
-
(
|
|
32
|
+
; Control -> Control
|
|
33
|
+
(define (reset c)
|
|
34
|
+
(let ([p (newPrompt)])
|
|
35
|
+
(lambda (mk)
|
|
36
|
+
((c p) (cons (make-Stack '() (make-arena) p) mk)))))
|
|
36
37
|
|
|
37
38
|
; Prompt, Body -> Control
|
|
38
39
|
(define (shift p f)
|
|
@@ -64,15 +65,6 @@
|
|
|
64
65
|
|
|
65
66
|
(define newPrompt (lambda () (string #\p)))
|
|
66
67
|
|
|
67
|
-
(define-syntax handle
|
|
68
|
-
(syntax-rules ()
|
|
69
|
-
[(_ ((cap1 (op1 (arg1 ...) kid exp) ...) ...) body)
|
|
70
|
-
(let ([p (newPrompt)])
|
|
71
|
-
(reset p (body
|
|
72
|
-
(cap1 (define-effect-op p (arg1 ...) kid exp) ...)
|
|
73
|
-
...)))]))
|
|
74
|
-
|
|
75
|
-
|
|
76
68
|
(define-syntax define-effect-op
|
|
77
69
|
(syntax-rules ()
|
|
78
70
|
[(_ p (arg1 ...) kid exp ...)
|
|
@@ -77,30 +77,7 @@ extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
|
|
|
77
77
|
ret %Pos %z
|
|
78
78
|
"""
|
|
79
79
|
|
|
80
|
-
/// Creates a copy of `arr`
|
|
81
|
-
def copy[T](arr: Array[T]): Array[T] = {
|
|
82
|
-
with on[OutOfBounds].default { <> }; // should not happen
|
|
83
|
-
val len = arr.size;
|
|
84
|
-
val newArray = allocate[T](len);
|
|
85
|
-
copy[T](arr, 0, newArray, 0, len);
|
|
86
|
-
newArray
|
|
87
|
-
}
|
|
88
80
|
|
|
89
|
-
/// Copies `length`-many elements from `from` to `to`
|
|
90
|
-
/// starting at `start` (in `from`) and `offset` (in `to`)
|
|
91
|
-
def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int): Unit / Exception[OutOfBounds] = {
|
|
92
|
-
val startValid = start >= 0 && start + length <= from.size
|
|
93
|
-
val offsetValid = offset >= 0 && offset + length <= to.size
|
|
94
|
-
|
|
95
|
-
def go(i: Int, j: Int, length: Int): Unit =
|
|
96
|
-
if (length > 0) {
|
|
97
|
-
to.unsafeSet(j, from.unsafeGet(i))
|
|
98
|
-
go(i + 1, j + 1, length - 1)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (startValid && offsetValid) go(start, offset, length)
|
|
102
|
-
else do raise(OutOfBounds(), "Array index out of bounds, when copying")
|
|
103
|
-
}
|
|
104
81
|
|
|
105
82
|
// Derived operations:
|
|
106
83
|
|
|
@@ -126,6 +103,44 @@ def build[T](size: Int) { index: Int => T }: Array[T] = {
|
|
|
126
103
|
arr
|
|
127
104
|
}
|
|
128
105
|
|
|
106
|
+
def resize[T](source: Array[T], size: Int): Array[T] = {
|
|
107
|
+
val target = allocate(size)
|
|
108
|
+
val n = min(source.size, target.size)
|
|
109
|
+
def go(i: Int): Array[T] =
|
|
110
|
+
if (i < n) {
|
|
111
|
+
target.unsafeSet(i, source.unsafeGet(i))
|
|
112
|
+
go(i + 1)
|
|
113
|
+
} else {
|
|
114
|
+
target
|
|
115
|
+
}
|
|
116
|
+
go(0)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Creates a copy of `arr`
|
|
121
|
+
*/
|
|
122
|
+
def copy[T](array: Array[T]): Array[T] =
|
|
123
|
+
array.resize(array.size)
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Copies `length`-many elements from `from` to `to`
|
|
127
|
+
* starting at `start` (in `from`) and `offset` (in `to`)
|
|
128
|
+
*/
|
|
129
|
+
def copy[T](from: Array[T], start: Int, to: Array[T], offset: Int, length: Int): Unit / Exception[OutOfBounds] = {
|
|
130
|
+
val startValid = start >= 0 && start + length <= from.size
|
|
131
|
+
val offsetValid = offset >= 0 && offset + length <= to.size
|
|
132
|
+
|
|
133
|
+
def go(i: Int, j: Int, length: Int): Unit =
|
|
134
|
+
if (length > 0) {
|
|
135
|
+
to.unsafeSet(j, from.unsafeGet(i))
|
|
136
|
+
go(i + 1, j + 1, length - 1)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (startValid && offsetValid) go(start, offset, length)
|
|
140
|
+
else do raise(OutOfBounds(), "Array index out of bounds, when copying")
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
129
144
|
// Utility functions:
|
|
130
145
|
|
|
131
146
|
def toList[T](arr: Array[T]): List[T] = {
|
|
@@ -140,26 +155,22 @@ def toList[T](arr: Array[T]): List[T] = {
|
|
|
140
155
|
|
|
141
156
|
def foreach[T](arr: Array[T]){ action: T => Unit }: Unit =
|
|
142
157
|
each(0, arr.size) { i =>
|
|
143
|
-
|
|
144
|
-
action(x)
|
|
158
|
+
action(arr.unsafeGet(i))
|
|
145
159
|
}
|
|
146
160
|
|
|
147
161
|
def foreach[T](arr: Array[T]){ action: (T) {Control} => Unit }: Unit =
|
|
148
162
|
each(0, arr.size) { (i) {label} =>
|
|
149
|
-
|
|
150
|
-
action(x) {label}
|
|
163
|
+
action(arr.unsafeGet(i)) {label}
|
|
151
164
|
}
|
|
152
165
|
|
|
153
166
|
def foreachIndex[T](arr: Array[T]){ action: (Int, T) => Unit }: Unit =
|
|
154
167
|
each(0, arr.size) { i =>
|
|
155
|
-
|
|
156
|
-
action(i, x)
|
|
168
|
+
action(i, arr.unsafeGet(i))
|
|
157
169
|
}
|
|
158
170
|
|
|
159
171
|
def foreachIndex[T](arr: Array[T]){ action: (Int, T) {Control} => Unit }: Unit =
|
|
160
172
|
each(0, arr.size) { (i) {label} =>
|
|
161
|
-
|
|
162
|
-
action(i, x) {label}
|
|
173
|
+
action(i, arr.unsafeGet(i)) {label}
|
|
163
174
|
}
|
|
164
175
|
|
|
165
176
|
def sum(list: Array[Int]): Int = {
|
|
@@ -50,13 +50,33 @@ def resize(source: ByteArray, size: Int): ByteArray = {
|
|
|
50
50
|
go(0)
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
def foreach(arr: ByteArray){ action: Byte => Unit }: Unit =
|
|
54
|
+
each(0, arr.size) { i =>
|
|
55
|
+
action(arr.unsafeGet(i))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
def foreach(arr: ByteArray){ action: (Byte) {Control} => Unit }: Unit =
|
|
59
|
+
each(0, arr.size) { (i) {label} =>
|
|
60
|
+
action(arr.unsafeGet(i)) {label}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
def foreachIndex(arr: ByteArray){ action: (Int, Byte) => Unit }: Unit =
|
|
64
|
+
each(0, arr.size) { i =>
|
|
65
|
+
action(i, arr.unsafeGet(i))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
def foreachIndex(arr: ByteArray){ action: (Int, Byte) {Control} => Unit }: Unit =
|
|
69
|
+
each(0, arr.size) { (i) {label} =>
|
|
70
|
+
action(i, arr.unsafeGet(i)) {label}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
extern pure def fromString(str: String): ByteArray =
|
|
54
74
|
js "(new TextEncoder().encode(${str}))"
|
|
55
75
|
llvm """
|
|
56
76
|
ret %Pos ${str}
|
|
57
77
|
"""
|
|
58
78
|
|
|
59
|
-
extern pure def
|
|
79
|
+
extern pure def toString(arr: ByteArray): String =
|
|
60
80
|
js "(new TextDecoder('utf-8').decode(${arr}))"
|
|
61
81
|
// assuming the buffer is already in UTF-8
|
|
62
82
|
llvm """
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/// Warning: This library currently only works with ASCII characters, **not** unicode!
|
|
2
|
+
module char
|
|
3
|
+
|
|
4
|
+
import exception
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
/// Checks if the given character is an ASCII whitespace
|
|
8
|
+
def isWhitespace(c: Char): Bool = c match {
|
|
9
|
+
case ' ' => true
|
|
10
|
+
case '\n' => true
|
|
11
|
+
case '\r' => true
|
|
12
|
+
case '\t' => true
|
|
13
|
+
case '\u0B' => true // vertical tab
|
|
14
|
+
case '\u0C' => true // form feed
|
|
15
|
+
case _ => false
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Checks if the given character is an ASCII digit in base 10
|
|
19
|
+
/// Use `digitValue(c: Char)` to get the numeric value out.
|
|
20
|
+
def isDigit(c: Char): Bool = { c >= '0' && c <= '9' }
|
|
21
|
+
|
|
22
|
+
/// Checks if the given character is an ASCII digit in the given base
|
|
23
|
+
/// Use `digitValue(c: Char, base: Int)` to get the numeric value out.
|
|
24
|
+
def isDigit(c: Char, base: Int): Bool = {
|
|
25
|
+
with on[WrongFormat].default { false }
|
|
26
|
+
val _ = digitValue(c, base)
|
|
27
|
+
true
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// Gets the value of a given ASCII digit in base 10
|
|
31
|
+
def digitValue(c: Char): Int / Exception[WrongFormat] =
|
|
32
|
+
digitValue(c, 10)
|
|
33
|
+
|
|
34
|
+
/// Gets the value of a given ASCII digit in the given base
|
|
35
|
+
def digitValue(c: Char, base: Int): Int / Exception[WrongFormat] = {
|
|
36
|
+
val v = c match {
|
|
37
|
+
case c and c >= '0' && c <= '9' => (c.toInt - '0'.toInt)
|
|
38
|
+
case c and c >= 'a' && c <= 'z' => (c.toInt - 'a'.toInt) + 10
|
|
39
|
+
case c and c >= 'A' && c <= 'Z' => (c.toInt - 'A'.toInt) + 10
|
|
40
|
+
case _ => wrongFormat("'" ++ c.toString ++ "' is not a digit")
|
|
41
|
+
}
|
|
42
|
+
if (v >= base) { wrongFormat(c.toString ++ " is not a valid digit in base " ++ base.show) } else { v }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/// Checks if a given character is a 7-bit ASCII character
|
|
46
|
+
def isASCII(c: Char): Bool = { c.toInt < 128 }
|
|
47
|
+
|
|
48
|
+
/// Checks if a given character is an ASCII lower alphabetic character
|
|
49
|
+
def isLower(c: Char): Bool = { c >= 'a' && c <= 'z' }
|
|
50
|
+
|
|
51
|
+
/// Checks if a given character is an ASCII upper alphabetic character
|
|
52
|
+
def isUpper(c: Char): Bool = { c >= 'A' && c <= 'Z' }
|
|
53
|
+
|
|
54
|
+
/// Checks if a given character is an ASCII alphabetic or numeric character
|
|
55
|
+
def isAlphanumeric(c: Char): Bool = isDigit(c) || isLower(c) || isUpper(c)
|
|
56
|
+
|
|
57
|
+
/// Checks if a given character is an ASCII alphabetic character
|
|
58
|
+
def isAlphabetic(c: Char): Bool = isLower(c) || isUpper(c)
|
|
@@ -566,6 +566,11 @@ extern pure def bitwiseAnd(x: Int, y: Int): Int =
|
|
|
566
566
|
chez "(logand ${x} ${y})"
|
|
567
567
|
llvm "%z = and %Int ${x}, ${y} ret %Int %z"
|
|
568
568
|
|
|
569
|
+
extern pure def bitwiseOr(x: Int, y: Int): Int =
|
|
570
|
+
js "(${x} | ${y})"
|
|
571
|
+
chez "(logior ${x} ${y})"
|
|
572
|
+
llvm "%z = or %Int ${x}, ${y} ret %Int %z"
|
|
573
|
+
|
|
569
574
|
extern pure def bitwiseXor(x: Int, y: Int): Int =
|
|
570
575
|
js "(${x} ^ ${y})"
|
|
571
576
|
chez "(logxor ${x} ${y})"
|
|
@@ -44,7 +44,7 @@ def readFile(path: String): String / Exception[IOError] = {
|
|
|
44
44
|
def go(): String = {
|
|
45
45
|
read(file, buffer, offset, chunkSize, -1) match {
|
|
46
46
|
case 0 =>
|
|
47
|
-
buffer.resize(offset).
|
|
47
|
+
buffer.resize(offset).toString
|
|
48
48
|
case n =>
|
|
49
49
|
offset = offset + n
|
|
50
50
|
if (offset + chunkSize > buffer.size) {
|
|
@@ -63,7 +63,7 @@ def writeFile(path: String, contents: String): Unit / Exception[IOError] = {
|
|
|
63
63
|
with on[IOError].finalize { close(file) }
|
|
64
64
|
|
|
65
65
|
val chunkSize = 1048576 // 1MB
|
|
66
|
-
val buffer = contents.
|
|
66
|
+
val buffer = contents.fromString
|
|
67
67
|
var offset = 0;
|
|
68
68
|
|
|
69
69
|
def go(): Unit = {
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
module stream
|
|
2
|
+
|
|
3
|
+
import array
|
|
4
|
+
import bytearray
|
|
5
|
+
import io/filesystem
|
|
6
|
+
import io/error
|
|
7
|
+
|
|
8
|
+
// Effects
|
|
9
|
+
// -------
|
|
10
|
+
|
|
11
|
+
/// Describes push streams by emitting values of type `A`.
|
|
12
|
+
effect emit[A](value: A): Unit
|
|
13
|
+
|
|
14
|
+
/// Describes pull streams by requiring values of type `A`.
|
|
15
|
+
///
|
|
16
|
+
/// The producer can decide to `stop` emitting values.
|
|
17
|
+
effect read[A](): A / stop
|
|
18
|
+
|
|
19
|
+
/// Signal from a producer to a consumer that there are no further values.
|
|
20
|
+
effect stop(): Nothing
|
|
21
|
+
|
|
22
|
+
/// Canonical handler of push streams that performs `action` for every
|
|
23
|
+
/// value emitted by `stream`.
|
|
24
|
+
def for[A, R] { stream: () => R / emit[A] } { action: A => Unit }: R =
|
|
25
|
+
try {
|
|
26
|
+
stream()
|
|
27
|
+
} with emit[A] { value =>
|
|
28
|
+
resume(action(value))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Like `for[A, R]`, but fixes the result of producing computation to the
|
|
32
|
+
/// common type `Unit`. This simplifies annotating the type of stream
|
|
33
|
+
/// elements `A` without having to also annotate `R`.
|
|
34
|
+
///
|
|
35
|
+
/// e.g. for[Int] { prog() } { el => println(el) }
|
|
36
|
+
def for[A] { stream: () => Unit / emit[A] } { action: A => Unit }: Unit =
|
|
37
|
+
for[A, Unit]{stream}{action}
|
|
38
|
+
|
|
39
|
+
def continually[A] { action: () => A }: Nothing / emit[A] = {
|
|
40
|
+
def go(): Nothing = {
|
|
41
|
+
do emit(action())
|
|
42
|
+
go()
|
|
43
|
+
}
|
|
44
|
+
go()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// Turns a `list` into a producer of a push stream
|
|
48
|
+
/// by emitting each contained value left-to-right.
|
|
49
|
+
def each[A](list: List[A]): Unit / emit[A] =
|
|
50
|
+
list match {
|
|
51
|
+
case Nil() => ()
|
|
52
|
+
case Cons(head, tail) =>
|
|
53
|
+
do emit(head)
|
|
54
|
+
each(tail)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Turns an `array` into a producer of a push stream
|
|
58
|
+
/// by emitting each contained value from 0 to length - 1.
|
|
59
|
+
def each[T](array: Array[T]): Unit / emit[T] = {
|
|
60
|
+
val n = array.size
|
|
61
|
+
def go(i: Int): Unit = {
|
|
62
|
+
if (i < n) {
|
|
63
|
+
do emit(array.unsafeGet(i))
|
|
64
|
+
go(i + 1)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
go(0)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/// Turns `bytes` into a producer of a push stream
|
|
71
|
+
/// by emitting each contained value from 0 to length - 1.
|
|
72
|
+
def each(bytes: ByteArray): Unit / emit[Byte] = {
|
|
73
|
+
val n = bytes.size
|
|
74
|
+
def go(i: Int): Unit = {
|
|
75
|
+
if (i < n) {
|
|
76
|
+
do emit(bytes.unsafeGet(i))
|
|
77
|
+
go(i + 1)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
go(0)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// not option
|
|
84
|
+
// not dequeue
|
|
85
|
+
// not queue
|
|
86
|
+
// not result
|
|
87
|
+
// not seq
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def boundary[R] { program: () => R / stop }: Option[R] =
|
|
91
|
+
try {
|
|
92
|
+
Some(program())
|
|
93
|
+
} with stop {
|
|
94
|
+
def stop() = None()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
def exhaustively[A] { program: () => A / stop } { action: A => Unit }: Unit =
|
|
98
|
+
try {
|
|
99
|
+
def go(): Unit = {
|
|
100
|
+
action(program())
|
|
101
|
+
go()
|
|
102
|
+
}
|
|
103
|
+
go()
|
|
104
|
+
} with stop {
|
|
105
|
+
def stop() = ()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
// In Effekt lower bounds are inclusive and upper bounds are exclusive
|
|
110
|
+
|
|
111
|
+
record Indexed[A](index: Int, value: A)
|
|
112
|
+
|
|
113
|
+
def range(lower: Int, upper: Int): Unit / emit[Int] =
|
|
114
|
+
if (lower < upper) {
|
|
115
|
+
do emit(lower)
|
|
116
|
+
range(lower + 1, upper)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
def rangeTo(upper: Int): Unit / emit[Int] =
|
|
120
|
+
range(0, upper)
|
|
121
|
+
|
|
122
|
+
def rangeFrom(lower: Int): Unit / emit[Int] = {
|
|
123
|
+
do emit(lower)
|
|
124
|
+
rangeFrom(lower + 1)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def index[A, R] { stream: () => R / emit[A] }: R / emit[Indexed[A]] = {
|
|
129
|
+
var i = 0;
|
|
130
|
+
try {
|
|
131
|
+
stream()
|
|
132
|
+
} with emit[A] { v =>
|
|
133
|
+
val c = i;
|
|
134
|
+
i = c + 1;
|
|
135
|
+
resume(do emit(Indexed(c, v)))
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/// If `number` is zero or negative it does nothing
|
|
140
|
+
def take[A, R](number: Int) { stream: () => R / emit[A] }: R / { emit[A], stop } = {
|
|
141
|
+
if (number <= 0) do stop();
|
|
142
|
+
var i = 1;
|
|
143
|
+
try {
|
|
144
|
+
stream()
|
|
145
|
+
} with emit[A] { v =>
|
|
146
|
+
if (i < number) {
|
|
147
|
+
i = i + 1;
|
|
148
|
+
resume(do emit(v))
|
|
149
|
+
} else {
|
|
150
|
+
do stop()
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// If `number` is zero or negative it does nothing
|
|
156
|
+
def replicate[A](number: Int) { action: () => A }: Unit / emit[A] =
|
|
157
|
+
if (number > 0) {
|
|
158
|
+
do emit(action())
|
|
159
|
+
replicate(number - 1) {action}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def sum[R] { stream : () => R / emit[Int] }: (R, Int) = {
|
|
164
|
+
var s = 0;
|
|
165
|
+
try {
|
|
166
|
+
(stream(), s)
|
|
167
|
+
} with emit[Int] { v =>
|
|
168
|
+
s = s + v;
|
|
169
|
+
resume(())
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
def sum { stream : () => Unit / emit[Int] }: Int =
|
|
174
|
+
sum[Unit]{stream}.second
|
|
175
|
+
|
|
176
|
+
def collectList[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
|
|
177
|
+
try {
|
|
178
|
+
(stream(), Nil())
|
|
179
|
+
} with emit[A] { (v) =>
|
|
180
|
+
val (r, vs) = resume(());
|
|
181
|
+
(r, Cons(v, vs))
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
def collectList[A] { stream: () => Unit / emit[A] }: List[A] =
|
|
185
|
+
collectList[A, Unit]{stream}.second
|
|
186
|
+
|
|
187
|
+
def collectArray[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
|
|
188
|
+
var i = 0
|
|
189
|
+
var a = array::allocate(1)
|
|
190
|
+
try {
|
|
191
|
+
(stream(), a.resize(i))
|
|
192
|
+
} with emit[A] { (v) =>
|
|
193
|
+
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
194
|
+
a.unsafeSet(i, v)
|
|
195
|
+
i = i + 1
|
|
196
|
+
resume(())
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
def collectArray[A] { stream: () => Unit / emit[A] }: Array[A] =
|
|
201
|
+
collectArray[A, Unit]{stream}.second
|
|
202
|
+
|
|
203
|
+
def collectBytes[R] { stream: () => R / emit[Byte] }: (R, ByteArray) = {
|
|
204
|
+
var i = 0
|
|
205
|
+
var a = bytearray::allocate(1)
|
|
206
|
+
try {
|
|
207
|
+
(stream(), a.resize(i))
|
|
208
|
+
} with emit[Byte] { (v) =>
|
|
209
|
+
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
210
|
+
a.unsafeSet(i, v)
|
|
211
|
+
i = i + 1
|
|
212
|
+
resume(())
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
def collectBytes { stream: () => Unit / emit[Byte] }: ByteArray =
|
|
217
|
+
collectBytes[Unit]{stream}.second
|
|
218
|
+
|
|
219
|
+
def feed[T](list: List[T]) { reader: () => Unit / read[T] } = {
|
|
220
|
+
var l = list
|
|
221
|
+
try {
|
|
222
|
+
reader()
|
|
223
|
+
} with read[T] {
|
|
224
|
+
resume {
|
|
225
|
+
l match {
|
|
226
|
+
case Nil() => do stop()
|
|
227
|
+
case Cons(value, rest) =>
|
|
228
|
+
l = rest
|
|
229
|
+
return value
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
def feed[T](array: Array[T]) { reader: () => Unit / read[T] } = {
|
|
236
|
+
var i = 0
|
|
237
|
+
try {
|
|
238
|
+
reader()
|
|
239
|
+
} with read[T] {
|
|
240
|
+
resume {
|
|
241
|
+
if (i < array.size) {
|
|
242
|
+
array.unsafeGet(i)
|
|
243
|
+
} else {
|
|
244
|
+
do stop()
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
def feed(bytes: ByteArray) { reader: () => Unit / read[Byte] } = {
|
|
251
|
+
var i = 0
|
|
252
|
+
try {
|
|
253
|
+
reader()
|
|
254
|
+
} with read[Byte] {
|
|
255
|
+
resume {
|
|
256
|
+
if (i < bytes.size) {
|
|
257
|
+
bytes.unsafeGet(i)
|
|
258
|
+
} else {
|
|
259
|
+
do stop()
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
def source[A, R] { stream: () => Unit / emit[A] } { reader: () => R / read[A] }: R = {
|
|
266
|
+
var next = box { None() }
|
|
267
|
+
next = box {
|
|
268
|
+
try {
|
|
269
|
+
stream()
|
|
270
|
+
None()
|
|
271
|
+
} with emit[A] { (v) =>
|
|
272
|
+
next = box { resume(()) }
|
|
273
|
+
Some(v)
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
try {
|
|
277
|
+
reader()
|
|
278
|
+
} with read[A] {
|
|
279
|
+
resume {
|
|
280
|
+
next().getOrElse { do stop() }
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def writeFile[R](path: String) { stream: () => R / emit[Byte] }: R / Exception[IOError] = {
|
|
287
|
+
|
|
288
|
+
val file = open(path, WriteOnly());
|
|
289
|
+
with on[IOError].finalize { close(file) }
|
|
290
|
+
|
|
291
|
+
val chunkSize = 1048576 // 1MB
|
|
292
|
+
val buffer = bytearray::allocate(chunkSize)
|
|
293
|
+
var offset = 0
|
|
294
|
+
|
|
295
|
+
def push(i: Int, n: Int): Unit = {
|
|
296
|
+
val r = write(file, buffer, i, n, -1)
|
|
297
|
+
if (r < n) {
|
|
298
|
+
push(i + r, n - r)
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
val r = stream()
|
|
304
|
+
push(0, offset)
|
|
305
|
+
return r
|
|
306
|
+
} with emit[Byte] { (byte) =>
|
|
307
|
+
if (offset >= buffer.size) { push(0, buffer.size) }
|
|
308
|
+
buffer.unsafeSet(offset, byte)
|
|
309
|
+
offset = offset + 1
|
|
310
|
+
resume(())
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
def readFile[R](path: String) { reader: () => R / read[Byte] }: R / Exception[IOError] = {
|
|
315
|
+
|
|
316
|
+
val file = open(path, ReadOnly());
|
|
317
|
+
with on[IOError].finalize { close(file) }
|
|
318
|
+
|
|
319
|
+
val chunkSize = 1048576 // 1MB
|
|
320
|
+
val buffer = bytearray::allocate(chunkSize)
|
|
321
|
+
var offset = 0
|
|
322
|
+
var length = 0
|
|
323
|
+
|
|
324
|
+
def pull(): Unit / stop = {
|
|
325
|
+
read(file, buffer, 0, chunkSize, -1) match {
|
|
326
|
+
case 0 =>
|
|
327
|
+
do stop()
|
|
328
|
+
case n =>
|
|
329
|
+
offset = 0
|
|
330
|
+
length = n
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
reader()
|
|
336
|
+
} with read[Byte] {
|
|
337
|
+
resume {
|
|
338
|
+
if (offset >= length) { pull() }
|
|
339
|
+
val byte = buffer.unsafeGet(offset)
|
|
340
|
+
offset = offset + 1
|
|
341
|
+
return byte
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
def decodeChar(): Char / {read[Byte], stop} = {
|
|
347
|
+
val b = do read().toInt
|
|
348
|
+
if (b < 128) {
|
|
349
|
+
b.toChar
|
|
350
|
+
} else if (b < 224) {
|
|
351
|
+
val part1 = bitwiseShl(bitwiseAnd(b, 31), 6)
|
|
352
|
+
val part2 = bitwiseAnd(do read().toInt, 63)
|
|
353
|
+
bitwiseOr(part1, part2).toChar
|
|
354
|
+
} else if (b < 240) {
|
|
355
|
+
val part1 = bitwiseShl(bitwiseAnd(b, 15), 12)
|
|
356
|
+
val part2 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 6)
|
|
357
|
+
val part3 = bitwiseAnd(do read().toInt, 63)
|
|
358
|
+
bitwiseOr(bitwiseOr(part1, part2), part3).toChar
|
|
359
|
+
} else {
|
|
360
|
+
val part1 = bitwiseShl(bitwiseAnd(b, 7), 18)
|
|
361
|
+
val part2 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 12)
|
|
362
|
+
val part3 = bitwiseShl(bitwiseAnd(do read().toInt, 63), 6)
|
|
363
|
+
val part4 = bitwiseAnd(do read().toInt, 63)
|
|
364
|
+
bitwiseOr(bitwiseOr(bitwiseOr(part1, part2), part3), part4).toChar
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
def encodeChar(char: Char): Unit / emit[Byte] = {
|
|
369
|
+
val code = char.toInt
|
|
370
|
+
if (code < 128) {
|
|
371
|
+
do emit(code.toByte)
|
|
372
|
+
} else if (code < 2048) {
|
|
373
|
+
do emit(bitwiseOr(192, bitwiseShr(code, 6)).toByte)
|
|
374
|
+
do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
|
|
375
|
+
} else if (code < 65536) {
|
|
376
|
+
do emit(bitwiseOr(224, bitwiseShr(code, 12)).toByte)
|
|
377
|
+
do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 6), 63)).toByte)
|
|
378
|
+
do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
|
|
379
|
+
} else {
|
|
380
|
+
do emit(bitwiseOr(240, bitwiseShr(code, 18)).toByte)
|
|
381
|
+
do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 12), 63)).toByte)
|
|
382
|
+
do emit(bitwiseOr(128, bitwiseAnd(bitwiseShr(code, 6), 63)).toByte)
|
|
383
|
+
do emit(bitwiseOr(128, bitwiseAnd(code, 63)).toByte)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
def decodeUTF8[R] { reader: () => R / read[Char] }: R / read[Byte] =
|
|
388
|
+
try {
|
|
389
|
+
reader()
|
|
390
|
+
} with read[Char] {
|
|
391
|
+
resume { decodeChar() }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
def encodeUTF8[R] { stream: () => R / emit[Char] }: R / emit[Byte] =
|
|
395
|
+
try {
|
|
396
|
+
stream()
|
|
397
|
+
} with emit[Char] { char =>
|
|
398
|
+
resume(encodeChar(char))
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
def feed(string: String) { reader: () => Unit / read[Char] } =
|
|
402
|
+
feed(string.fromString) {
|
|
403
|
+
decodeUTF8 {
|
|
404
|
+
reader()
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
def each(string: String): Unit / emit[Char] =
|
|
409
|
+
feed(string) {
|
|
410
|
+
exhaustively[Char] { do read() } { char => do emit(char) }
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
def collectString[R] { stream: () => R / emit[Char] }: (R, String) = {
|
|
414
|
+
val (result, bytes) = collectBytes { encodeUTF8 { stream } }
|
|
415
|
+
(result, bytes.toString)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
def collectString { stream: () => Unit / emit[Char] }: String =
|
|
419
|
+
collectString[Unit]{stream}.second
|
|
@@ -222,15 +222,6 @@ def lastIndexOf(str: String, sub: String, from: Int): Option[Int] = {
|
|
|
222
222
|
// extern pure def unsafeIndexOf(str: String, sub: String): Int =
|
|
223
223
|
// js "${str}.indexOf(${sub})"
|
|
224
224
|
|
|
225
|
-
interface Stream {
|
|
226
|
-
def emit(string: Char): Unit
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
def string[T] { prog: => T / Stream }: (T, String) = <>
|
|
230
|
-
|
|
231
|
-
// TODO implement after concurrent IO (we need to stub `process.stdout` in JS for browsers).
|
|
232
|
-
def printing[T] { prog: => T / Stream }: T = <>
|
|
233
|
-
|
|
234
225
|
|
|
235
226
|
// Characters
|
|
236
227
|
// ----------
|
|
@@ -299,10 +290,6 @@ extern pure def infixGte(x: Char, y: Char): Bool =
|
|
|
299
290
|
ret %Pos %adt_boolean
|
|
300
291
|
"""
|
|
301
292
|
|
|
302
|
-
// TODO iterator over codepoints (maybe use the JS primitive feature???)
|
|
303
|
-
|
|
304
|
-
extern type StringIterator
|
|
305
|
-
|
|
306
293
|
|
|
307
294
|
/**
|
|
308
295
|
* Determines the number of bytes needed by a codepoint
|
|
@@ -23,7 +23,7 @@ function Arena(_region) {
|
|
|
23
23
|
fresh: function(init) {
|
|
24
24
|
const cell = Cell(init);
|
|
25
25
|
// region keeps track what to backup, but we do not need to backup unreachable cells
|
|
26
|
-
region.push(new WeakRef(cell))
|
|
26
|
+
region.push(cell) // new WeakRef(cell))
|
|
27
27
|
return cell;
|
|
28
28
|
},
|
|
29
29
|
region: _region,
|
|
@@ -31,15 +31,14 @@ function Arena(_region) {
|
|
|
31
31
|
// a region aggregates weak references
|
|
32
32
|
const nested = Arena([])
|
|
33
33
|
// this doesn't work yet, since Arena.backup doesn't return a thunk
|
|
34
|
-
region.push(new WeakRef(nested))
|
|
34
|
+
region.push(nested) //new WeakRef(nested))
|
|
35
35
|
return nested;
|
|
36
36
|
},
|
|
37
37
|
backup: function() {
|
|
38
38
|
const _backup = []
|
|
39
39
|
let nextIndex = 0;
|
|
40
40
|
for (const ref of region) {
|
|
41
|
-
|
|
42
|
-
const cell = ref.deref()
|
|
41
|
+
const cell = ref //.deref()
|
|
43
42
|
// only backup live cells
|
|
44
43
|
if (cell) {
|
|
45
44
|
_backup[nextIndex] = cell.backup()
|
|
@@ -50,7 +49,7 @@ function Arena(_region) {
|
|
|
50
49
|
const region = []
|
|
51
50
|
let nextIndex = 0;
|
|
52
51
|
for (const restoreCell of _backup) {
|
|
53
|
-
region[nextIndex] = new WeakRef(restoreCell())
|
|
52
|
+
region[nextIndex] = restoreCell() // new WeakRef(restoreCell())
|
|
54
53
|
nextIndex++
|
|
55
54
|
}
|
|
56
55
|
return Arena(region)
|
|
@@ -114,11 +113,7 @@ function SHIFT(p, body, ks, k) {
|
|
|
114
113
|
cont = { stack: meta.stack, prompt: meta.prompt, backup: meta.arena.backup(), rest: cont }
|
|
115
114
|
meta = meta.rest
|
|
116
115
|
|
|
117
|
-
function resumeValue(a, ks, k) {
|
|
118
|
-
return resumeComp((ks, k) => k(a, ks), ks, k)
|
|
119
|
-
}
|
|
120
116
|
function resumeComp(c, ks, k) {
|
|
121
|
-
//console.log("Resuming", ks.arena)
|
|
122
117
|
let meta = { stack: k, prompt: ks.prompt, arena: ks.arena, rest: ks.rest }
|
|
123
118
|
let toRewind = cont
|
|
124
119
|
while (!!toRewind) {
|
|
@@ -133,7 +128,7 @@ function SHIFT(p, body, ks, k) {
|
|
|
133
128
|
|
|
134
129
|
let k1 = meta.stack
|
|
135
130
|
meta.stack = null
|
|
136
|
-
return body(
|
|
131
|
+
return body(resumeComp, meta, k1)
|
|
137
132
|
}
|
|
138
133
|
|
|
139
134
|
function RUN_TOPLEVEL(comp) {
|
|
@@ -81,7 +81,7 @@ char* c_bytearray_into_nullterminated_string(const struct Pos arr) {
|
|
|
81
81
|
// TODO do this in Effekt
|
|
82
82
|
struct Pos c_bytearray_show_Int(const Int n) {
|
|
83
83
|
char str[24];
|
|
84
|
-
|
|
84
|
+
snprintf(str, sizeof(str), "%" PRId64, n);
|
|
85
85
|
return c_bytearray_from_nullterminated_string(str);
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -112,14 +112,14 @@ struct Pos c_bytearray_show_Char(const uint64_t n) {
|
|
|
112
112
|
// TODO do this in Effekt
|
|
113
113
|
struct Pos c_bytearray_show_Byte(const Byte n) {
|
|
114
114
|
char str[4]; // Byte values range from 0 to 255, 3 characters + null terminator
|
|
115
|
-
|
|
115
|
+
snprintf(str, sizeof(str), "%" PRIu8, n);
|
|
116
116
|
return c_bytearray_from_nullterminated_string(str);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
// TODO do this in Effekt
|
|
120
120
|
struct Pos c_bytearray_show_Double(const Double x) {
|
|
121
|
-
char str[64]; // TODO is this large enough?
|
|
122
|
-
|
|
121
|
+
char str[64]; // TODO is this large enough?
|
|
122
|
+
snprintf(str, sizeof(str), "%g", x);
|
|
123
123
|
return c_bytearray_from_nullterminated_string(str);
|
|
124
124
|
}
|
|
125
125
|
|
package/libraries/llvm/rts.ll
CHANGED
|
@@ -58,14 +58,6 @@
|
|
|
58
58
|
; Pointers for a heap allocated stack
|
|
59
59
|
%Memory = type { %StackPointer, %Base, %Limit }
|
|
60
60
|
|
|
61
|
-
; The garbage collector differentiates three groups of types:
|
|
62
|
-
; - Values (Integer, Double)
|
|
63
|
-
; - Objects (Positive, Negative)
|
|
64
|
-
; - Strings
|
|
65
|
-
; For each group we have an arena where mutable state is allocated.
|
|
66
|
-
;
|
|
67
|
-
%Region = type [ 3 x %Memory ]
|
|
68
|
-
|
|
69
61
|
; Unique address for each handler.
|
|
70
62
|
%Prompt = type ptr
|
|
71
63
|
|
|
@@ -82,7 +74,7 @@
|
|
|
82
74
|
; This is used for two purposes:
|
|
83
75
|
; - a refied first-class list of stacks (cyclic linked-list)
|
|
84
76
|
; - as part of an intrusive linked-list of stacks (meta stack)
|
|
85
|
-
%StackValue = type { %ReferenceCount, %Memory, %
|
|
77
|
+
%StackValue = type { %ReferenceCount, %Memory, %Prompt, i1, %Stack }
|
|
86
78
|
|
|
87
79
|
|
|
88
80
|
|
|
@@ -124,7 +116,7 @@ declare void @exit(i64)
|
|
|
124
116
|
; Prompts
|
|
125
117
|
|
|
126
118
|
define private %Prompt @currentPrompt(%Stack %stack) {
|
|
127
|
-
%prompt_pointer = getelementptr %StackValue, ptr %stack, i64 0, i32
|
|
119
|
+
%prompt_pointer = getelementptr %StackValue, ptr %stack, i64 0, i32 2
|
|
128
120
|
%prompt = load %Prompt, ptr %prompt_pointer
|
|
129
121
|
ret %Prompt %prompt
|
|
130
122
|
}
|
|
@@ -222,77 +214,6 @@ define void @eraseNegative(%Neg %val) alwaysinline {
|
|
|
222
214
|
|
|
223
215
|
|
|
224
216
|
; Arena management
|
|
225
|
-
define private ptr @getRegionPointer(%Prompt %prompt) {
|
|
226
|
-
%stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
|
|
227
|
-
%stack = load %Stack, ptr %stack_pointer
|
|
228
|
-
%region_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
|
|
229
|
-
ret ptr %region_pointer
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
define private { ptr, %Reference } @alloc(i64 %index, %Prompt %prompt) alwaysinline {
|
|
233
|
-
%region_pointer = call ptr @getRegionPointer(%Prompt %prompt)
|
|
234
|
-
|
|
235
|
-
%stackPointer_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 0
|
|
236
|
-
%base_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 1
|
|
237
|
-
%limit_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 2
|
|
238
|
-
|
|
239
|
-
%stackPointer = load %StackPointer, ptr %stackPointer_pointer
|
|
240
|
-
%base = load %Base, ptr %base_pointer
|
|
241
|
-
%limit = load %Limit, ptr %limit_pointer
|
|
242
|
-
|
|
243
|
-
%object = icmp ne i64 %index, 0
|
|
244
|
-
%size = select i1 %object, i64 16, i64 8
|
|
245
|
-
|
|
246
|
-
%nextStackPointer = getelementptr i8, %StackPointer %stackPointer, i64 %size
|
|
247
|
-
|
|
248
|
-
%cmp = icmp ule %StackPointer %nextStackPointer, %limit
|
|
249
|
-
br i1 %cmp, label %continue, label %realloc
|
|
250
|
-
|
|
251
|
-
continue:
|
|
252
|
-
store %StackPointer %nextStackPointer, ptr %stackPointer_pointer
|
|
253
|
-
%intBase = ptrtoint %Base %base to i64
|
|
254
|
-
%intStackPointer = ptrtoint %StackPointer %stackPointer to i64
|
|
255
|
-
%offset = sub i64 %intStackPointer, %intBase
|
|
256
|
-
|
|
257
|
-
%ret.0 = insertvalue { ptr, %Reference } undef, %StackPointer %stackPointer, 0
|
|
258
|
-
%ret.1 = insertvalue { ptr, %Reference } %ret.0, %Prompt %prompt, 1, 0
|
|
259
|
-
%ret.2 = insertvalue { ptr, %Reference } %ret.1, i64 %offset, 1, 1
|
|
260
|
-
ret { ptr, %Reference } %ret.2
|
|
261
|
-
|
|
262
|
-
realloc:
|
|
263
|
-
%intBase_2 = ptrtoint %Base %base to i64
|
|
264
|
-
%intLimit = ptrtoint %Limit %limit to i64
|
|
265
|
-
%arenaSize = sub i64 %intLimit, %intBase_2
|
|
266
|
-
%empty = icmp eq i64 %arenaSize, 0
|
|
267
|
-
%double = mul i64 %arenaSize, 2
|
|
268
|
-
%newArenaSize = select i1 %empty, i64 1024, i64 %double
|
|
269
|
-
|
|
270
|
-
%newBase = call ptr @realloc(ptr %base, i64 %newArenaSize)
|
|
271
|
-
%newlimit = getelementptr i8, %Base %newBase, i64 %newArenaSize
|
|
272
|
-
%newStackPointer = getelementptr i8, %Base %newBase, i64 %arenaSize
|
|
273
|
-
%newNextStackPointer = getelementptr i8, %StackPointer %newStackPointer, i64 %size
|
|
274
|
-
|
|
275
|
-
store %Base %newBase, ptr %base_pointer
|
|
276
|
-
store %Limit %newlimit, ptr %limit_pointer
|
|
277
|
-
store %StackPointer %newNextStackPointer, ptr %stackPointer_pointer
|
|
278
|
-
|
|
279
|
-
%ret..0 = insertvalue { ptr, %Reference } undef, %StackPointer %newStackPointer, 0
|
|
280
|
-
%ret..1 = insertvalue { ptr, %Reference } %ret..0, %Prompt %prompt, 1, 0
|
|
281
|
-
%ret..2 = insertvalue { ptr, %Reference } %ret..1, i64 %arenaSize, 1, 1
|
|
282
|
-
ret { ptr, %Reference } %ret..2
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
define private ptr @getPointer(%Reference %reference, i64 %index, %Stack %stack) {
|
|
287
|
-
%prompt = extractvalue %Reference %reference, 0
|
|
288
|
-
%offset = extractvalue %Reference %reference, 1
|
|
289
|
-
|
|
290
|
-
%region_pointer = call ptr @getRegionPointer(%Prompt %prompt)
|
|
291
|
-
%base_pointer = getelementptr %Region, ptr %region_pointer, i64 0, i64 %index, i32 1
|
|
292
|
-
%base = load %Base, ptr %base_pointer
|
|
293
|
-
%pointer = getelementptr i8, ptr %base, i64 %offset
|
|
294
|
-
ret ptr %pointer
|
|
295
|
-
}
|
|
296
217
|
|
|
297
218
|
define private %Stack @getStack(%Prompt %prompt) {
|
|
298
219
|
%stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
|
|
@@ -414,8 +335,8 @@ define private %Stack @reset(%Stack %oldStack) {
|
|
|
414
335
|
%stackMemory = call %Memory @newMemory()
|
|
415
336
|
|
|
416
337
|
%stack.0 = insertvalue %StackValue zeroinitializer, %Memory %stackMemory, 1
|
|
417
|
-
%stack.1 = insertvalue %StackValue %stack.0, %Prompt %prompt,
|
|
418
|
-
%stack.2 = insertvalue %StackValue %stack.1, %Stack %oldStack,
|
|
338
|
+
%stack.1 = insertvalue %StackValue %stack.0, %Prompt %prompt, 2
|
|
339
|
+
%stack.2 = insertvalue %StackValue %stack.1, %Stack %oldStack, 4
|
|
419
340
|
|
|
420
341
|
store %StackValue %stack.2, %Stack %stack
|
|
421
342
|
|
|
@@ -426,7 +347,7 @@ define private %Stack @reset(%Stack %oldStack) {
|
|
|
426
347
|
}
|
|
427
348
|
|
|
428
349
|
define private void @updatePrompts(%Stack %stack) {
|
|
429
|
-
%dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32
|
|
350
|
+
%dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
|
|
430
351
|
%dirtyBit = load i1, ptr %dirtyBit_pointer
|
|
431
352
|
br i1 %dirtyBit, label %continue, label %done
|
|
432
353
|
|
|
@@ -434,7 +355,7 @@ done:
|
|
|
434
355
|
ret void
|
|
435
356
|
|
|
436
357
|
continue:
|
|
437
|
-
%prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32
|
|
358
|
+
%prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
|
|
438
359
|
%prompt = load %Prompt, ptr %prompt_pointer
|
|
439
360
|
%stack_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
|
|
440
361
|
%promptStack = load %Stack, ptr %stack_pointer
|
|
@@ -449,16 +370,16 @@ update:
|
|
|
449
370
|
store %Stack %stack, ptr %stack_pointer
|
|
450
371
|
store i1 0, ptr %dirtyBit_pointer
|
|
451
372
|
|
|
452
|
-
%next_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32
|
|
373
|
+
%next_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
|
|
453
374
|
%next = load %Stack, ptr %next_pointer
|
|
454
375
|
tail call void @updatePrompts(%Stack %next)
|
|
455
376
|
ret void
|
|
456
377
|
}
|
|
457
378
|
|
|
458
379
|
define void @displace(%Stack %stack) {
|
|
459
|
-
%prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32
|
|
460
|
-
%next_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32
|
|
461
|
-
%dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32
|
|
380
|
+
%prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
|
|
381
|
+
%next_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
|
|
382
|
+
%dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
|
|
462
383
|
%dirtyBit = load i1, ptr %dirtyBit_pointer
|
|
463
384
|
br i1 %dirtyBit, label %done, label %continue
|
|
464
385
|
|
|
@@ -478,7 +399,7 @@ continue:
|
|
|
478
399
|
|
|
479
400
|
define %Stack @resume(%Resumption %resumption, %Stack %oldStack) {
|
|
480
401
|
%uniqueResumption = call %Resumption @uniqueStack(%Resumption %resumption)
|
|
481
|
-
%rest_pointer = getelementptr %StackValue, %Resumption %uniqueResumption, i64 0, i32
|
|
402
|
+
%rest_pointer = getelementptr %StackValue, %Resumption %uniqueResumption, i64 0, i32 4
|
|
482
403
|
%start = load %Stack, ptr %rest_pointer
|
|
483
404
|
call void @updatePrompts(%Stack %start)
|
|
484
405
|
|
|
@@ -490,7 +411,7 @@ define %Stack @resume(%Resumption %resumption, %Stack %oldStack) {
|
|
|
490
411
|
define private {%Resumption, %Stack} @shift(%Stack %stack, %Prompt %prompt) {
|
|
491
412
|
%resumpion_pointer = getelementptr %PromptValue, %Prompt %prompt, i64 0, i32 1
|
|
492
413
|
%resumption = load %Stack, ptr %resumpion_pointer
|
|
493
|
-
%next_pointer = getelementptr %StackValue, %Stack %resumption, i64 0, i32
|
|
414
|
+
%next_pointer = getelementptr %StackValue, %Stack %resumption, i64 0, i32 4
|
|
494
415
|
%next = load %Stack, ptr %next_pointer
|
|
495
416
|
|
|
496
417
|
store %Stack %stack, ptr %next_pointer
|
|
@@ -522,23 +443,6 @@ return:
|
|
|
522
443
|
ret void
|
|
523
444
|
}
|
|
524
445
|
|
|
525
|
-
define private void @eraseRegion(%Region %region) alwaysinline {
|
|
526
|
-
%valuesBase = extractvalue %Region %region, 0, 1
|
|
527
|
-
call void @free(%Base %valuesBase)
|
|
528
|
-
|
|
529
|
-
%objectsBase = extractvalue %Region %region, 1, 1
|
|
530
|
-
%objectsStackPointer = extractvalue %Region %region, 1, 0
|
|
531
|
-
call void @forEachObject(%Base %objectsBase, %StackPointer %objectsStackPointer, %Eraser @erasePositive)
|
|
532
|
-
call void @free(%Base %objectsBase)
|
|
533
|
-
|
|
534
|
-
%stringsBase = extractvalue %Region %region, 2, 1
|
|
535
|
-
%stringsStackPointer = extractvalue %Region %region, 2, 0
|
|
536
|
-
call void @forEachObject(%Base %stringsBase, %StackPointer %stringsStackPointer, %Eraser @erasePositive)
|
|
537
|
-
call void @free(%Base %stringsBase)
|
|
538
|
-
|
|
539
|
-
ret void
|
|
540
|
-
}
|
|
541
|
-
|
|
542
446
|
define void @erasePrompt(%Prompt %prompt, i1 %dirtyBit) alwaysinline {
|
|
543
447
|
br i1 %dirtyBit, label %continue, label %clearPrompt
|
|
544
448
|
|
|
@@ -572,25 +476,26 @@ define void @sharePrompt(%Prompt %prompt) alwaysinline {
|
|
|
572
476
|
|
|
573
477
|
define private %Stack @underflowStack(%Stack %stack) {
|
|
574
478
|
%stackMemory = getelementptr %StackValue, %Stack %stack, i64 0, i32 1
|
|
575
|
-
%
|
|
576
|
-
%
|
|
577
|
-
%
|
|
578
|
-
%stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 5
|
|
479
|
+
%stackPrompt = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
|
|
480
|
+
%stackDirtyBit = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
|
|
481
|
+
%stackRest = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
|
|
579
482
|
|
|
580
483
|
%memory = load %Memory, ptr %stackMemory
|
|
581
|
-
%region = load %Region, ptr %stackRegion
|
|
582
484
|
%prompt = load %Prompt, ptr %stackPrompt
|
|
583
485
|
%rest = load %Stack, ptr %stackRest
|
|
584
486
|
%dirtyBit = load i1, ptr %stackDirtyBit
|
|
585
487
|
|
|
586
488
|
call void @eraseMemory(%Memory %memory)
|
|
587
|
-
call void @eraseRegion(%Region %region)
|
|
588
489
|
call void @erasePrompt(%Prompt %prompt, i1 false)
|
|
589
490
|
call void @free(%Stack %stack)
|
|
590
491
|
|
|
591
492
|
ret %Stack %rest
|
|
592
493
|
}
|
|
593
494
|
|
|
495
|
+
define private void @nop(%Stack %stack) {
|
|
496
|
+
ret void
|
|
497
|
+
}
|
|
498
|
+
|
|
594
499
|
define private %Memory @copyMemory(%Memory %memory) alwaysinline {
|
|
595
500
|
%stackPointer = extractvalue %Memory %memory, 0
|
|
596
501
|
%base = extractvalue %Memory %memory, 1
|
|
@@ -618,29 +523,6 @@ define private %Memory @copyMemory(%Memory %memory) alwaysinline {
|
|
|
618
523
|
ret %Memory %memory.2
|
|
619
524
|
}
|
|
620
525
|
|
|
621
|
-
define private %Region @copyRegion(%Region %region) alwaysinline {
|
|
622
|
-
%memory.0 = extractvalue %Region %region, 0
|
|
623
|
-
%memory.1 = extractvalue %Region %region, 1
|
|
624
|
-
%memory.2 = extractvalue %Region %region, 2
|
|
625
|
-
|
|
626
|
-
%objectsBase = extractvalue %Region %region, 1, 1
|
|
627
|
-
%objectsStackPointer = extractvalue %Region %region, 1, 0
|
|
628
|
-
call void @forEachObject(%Base %objectsBase, %StackPointer %objectsStackPointer, %Sharer @sharePositive)
|
|
629
|
-
|
|
630
|
-
%stringsBase = extractvalue %Region %region, 2, 1
|
|
631
|
-
%stringsStackPointer = extractvalue %Region %region, 2, 0
|
|
632
|
-
call void @forEachObject(%Base %stringsBase, %StackPointer %stringsStackPointer, %Sharer @sharePositive)
|
|
633
|
-
|
|
634
|
-
%newMemory.0 = call %Memory @copyMemory(%Memory %memory.0)
|
|
635
|
-
%newMemory.1 = call %Memory @copyMemory(%Memory %memory.1)
|
|
636
|
-
%newMemory.2 = call %Memory @copyMemory(%Memory %memory.2)
|
|
637
|
-
|
|
638
|
-
%region.0 = insertvalue %Region undef, %Memory %newMemory.0, 0
|
|
639
|
-
%region.1 = insertvalue %Region %region.0, %Memory %newMemory.1, 1
|
|
640
|
-
%region.2 = insertvalue %Region %region.1, %Memory %newMemory.2, 2
|
|
641
|
-
|
|
642
|
-
ret %Region %region.2
|
|
643
|
-
}
|
|
644
526
|
|
|
645
527
|
define private %Resumption @uniqueStack(%Resumption %resumption) alwaysinline {
|
|
646
528
|
|
|
@@ -655,7 +537,7 @@ done:
|
|
|
655
537
|
copy:
|
|
656
538
|
%newOldReferenceCount = sub %ReferenceCount %referenceCount, 1
|
|
657
539
|
store %ReferenceCount %newOldReferenceCount, ptr %referenceCount_pointer
|
|
658
|
-
%stack_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32
|
|
540
|
+
%stack_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 4
|
|
659
541
|
%stack = load %Stack, ptr %stack_pointer
|
|
660
542
|
|
|
661
543
|
%size = ptrtoint ptr getelementptr (%StackValue, ptr null, i64 1) to i64
|
|
@@ -668,34 +550,28 @@ loop:
|
|
|
668
550
|
%newStack = phi %Stack [%newHead, %copy], [%nextNew, %next]
|
|
669
551
|
|
|
670
552
|
%stackMemory = getelementptr %StackValue, %Stack %old, i64 0, i32 1
|
|
671
|
-
%
|
|
672
|
-
%
|
|
673
|
-
%stackRest = getelementptr %StackValue, %Stack %old, i64 0, i32 5
|
|
553
|
+
%stackPrompt = getelementptr %StackValue, %Stack %old, i64 0, i32 2
|
|
554
|
+
%stackRest = getelementptr %StackValue, %Stack %old, i64 0, i32 4
|
|
674
555
|
|
|
675
556
|
%memory = load %Memory, ptr %stackMemory
|
|
676
|
-
%region = load %Region, ptr %stackRegion
|
|
677
557
|
%prompt = load %Prompt, ptr %stackPrompt
|
|
678
558
|
%rest = load %Stack, ptr %stackRest
|
|
679
559
|
|
|
680
560
|
%newStackReferenceCounter = getelementptr %StackValue, %Stack %newStack, i64 0, i32 0
|
|
681
561
|
%newStackMemory = getelementptr %StackValue, %Stack %newStack, i64 0, i32 1
|
|
682
|
-
%
|
|
683
|
-
%
|
|
684
|
-
%
|
|
685
|
-
%newStackRest = getelementptr %StackValue, %Stack %newStack, i64 0, i32 5
|
|
562
|
+
%newStackPrompt = getelementptr %StackValue, %Stack %newStack, i64 0, i32 2
|
|
563
|
+
%newStackDirtyBit = getelementptr %StackValue, %Stack %newStack, i64 0, i32 3
|
|
564
|
+
%newStackRest = getelementptr %StackValue, %Stack %newStack, i64 0, i32 4
|
|
686
565
|
|
|
687
566
|
%newMemory = call %Memory @copyMemory(%Memory %memory)
|
|
688
567
|
|
|
689
568
|
%newStackPointer = extractvalue %Memory %newMemory, 0
|
|
690
569
|
call void @shareFrames(%StackPointer %newStackPointer)
|
|
691
570
|
|
|
692
|
-
%newRegion = call %Region @copyRegion(%Region %region)
|
|
693
|
-
|
|
694
571
|
call void @sharePrompt(%Prompt %prompt)
|
|
695
572
|
|
|
696
|
-
store
|
|
573
|
+
store %ReferenceCount 0, ptr %newStackReferenceCounter
|
|
697
574
|
store %Memory %newMemory, ptr %newStackMemory
|
|
698
|
-
store %Region %newRegion, ptr %newStackRegion
|
|
699
575
|
store %Prompt %prompt, ptr %newStackPrompt
|
|
700
576
|
store i1 1, ptr %newStackDirtyBit
|
|
701
577
|
|
|
@@ -731,7 +607,7 @@ define void @eraseResumption(%Resumption %resumption) alwaysinline {
|
|
|
731
607
|
ret void
|
|
732
608
|
|
|
733
609
|
free:
|
|
734
|
-
%stack_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32
|
|
610
|
+
%stack_pointer = getelementptr %StackValue, %Resumption %resumption, i64 0, i32 4
|
|
735
611
|
%stack = load %Stack, ptr %stack_pointer
|
|
736
612
|
store %Stack null, ptr %stack_pointer
|
|
737
613
|
call void @eraseStack(%Stack %stack)
|
|
@@ -740,20 +616,17 @@ define void @eraseResumption(%Resumption %resumption) alwaysinline {
|
|
|
740
616
|
|
|
741
617
|
define void @eraseStack(%Stack %stack) alwaysinline {
|
|
742
618
|
%stackPointer_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 1, i32 0
|
|
743
|
-
%
|
|
744
|
-
%
|
|
745
|
-
%
|
|
746
|
-
%rest_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 5
|
|
619
|
+
%prompt_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 2
|
|
620
|
+
%dirtyBit_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 3
|
|
621
|
+
%rest_pointer = getelementptr %StackValue, %Stack %stack, i64 0, i32 4
|
|
747
622
|
|
|
748
623
|
%stackPointer = load %StackPointer, ptr %stackPointer_pointer
|
|
749
|
-
%region = load %Region, ptr %region_pointer
|
|
750
624
|
%prompt = load %Stack, ptr %prompt_pointer
|
|
751
625
|
%dirtyBit = load i1, ptr %dirtyBit_pointer
|
|
752
626
|
%rest = load %Stack, ptr %rest_pointer
|
|
753
627
|
|
|
754
628
|
call void @free(%Stack %stack)
|
|
755
629
|
call void @eraseFrames(%StackPointer %stackPointer)
|
|
756
|
-
call void @eraseRegion(%Region %region)
|
|
757
630
|
call void @erasePrompt(%Prompt %prompt, i1 %dirtyBit)
|
|
758
631
|
|
|
759
632
|
%isNull = icmp eq %Stack %rest, null
|
|
@@ -787,7 +660,8 @@ define private void @eraseFrames(%StackPointer %stackPointer) alwaysinline {
|
|
|
787
660
|
|
|
788
661
|
define private tailcc void @topLevel(%Pos %val, %Stack %stack) {
|
|
789
662
|
%rest = call %Stack @underflowStack(%Stack %stack)
|
|
790
|
-
;
|
|
663
|
+
; rest holds global variables
|
|
664
|
+
call void @eraseStack(%Stack %rest)
|
|
791
665
|
ret void
|
|
792
666
|
}
|
|
793
667
|
|
|
@@ -804,7 +678,23 @@ define private void @topLevelEraser(%Environment %environment) {
|
|
|
804
678
|
@global = private global { i64, %Stack } { i64 0, %Stack null }
|
|
805
679
|
|
|
806
680
|
define private %Stack @withEmptyStack() {
|
|
807
|
-
%
|
|
681
|
+
%globals = call %Stack @reset(%Stack null)
|
|
682
|
+
|
|
683
|
+
%globalsStackPointer_pointer = getelementptr %StackValue, %Stack %globals, i64 0, i32 1, i32 0
|
|
684
|
+
%globalsStackPointer = load %StackPointer, ptr %globalsStackPointer_pointer
|
|
685
|
+
|
|
686
|
+
%returnAddressPointer.0 = getelementptr %FrameHeader, %StackPointer %globalsStackPointer, i64 0, i32 0
|
|
687
|
+
%sharerPointer.0 = getelementptr %FrameHeader, %StackPointer %globalsStackPointer, i64 0, i32 1
|
|
688
|
+
%eraserPointer.0 = getelementptr %FrameHeader, %StackPointer %globalsStackPointer, i64 0, i32 2
|
|
689
|
+
|
|
690
|
+
store ptr @nop, ptr %returnAddressPointer.0
|
|
691
|
+
store ptr @nop, ptr %sharerPointer.0
|
|
692
|
+
store ptr @free, ptr %eraserPointer.0
|
|
693
|
+
|
|
694
|
+
%globalsStackPointer_2 = getelementptr %FrameHeader, %StackPointer %globalsStackPointer, i64 1
|
|
695
|
+
store %StackPointer %globalsStackPointer_2, ptr %globalsStackPointer_pointer
|
|
696
|
+
|
|
697
|
+
%stack = call %Stack @reset(%Stack %globals)
|
|
808
698
|
|
|
809
699
|
%globalStack = getelementptr %PromptValue, %Prompt @global, i64 0, i32 1
|
|
810
700
|
store %Stack %stack, ptr %globalStack
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!doctype html><html lang=en><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Eclipse Public License 2.0 (EPL) | The Eclipse Foundation</title><meta property="og:title" content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=twitter:title content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta property="og:description" content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=twitter:description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=author content="Wayne Beaton"><link href=/favicon.ico rel=icon type=image/x-icon><meta property="og:image" content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:image content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:card content="summary"><meta name=twitter:site content="@eclipsefdn"><meta name=twitter:creator content="@eclipsefdn"><meta property="og:url" content="https://www.eclipse.org/legal/epl-2.0/"><meta property="og:type" content="website"><meta property="og:site_name" content="Eclipse Foundation"><meta name=keywords content="epl,epl-2.0,legal,foundation,eclipse,eclipse public license,license,licenses"><meta name=generator content="Hugo 0.110.0"><link rel=canonical href=https://www.eclipse.org/legal/epl-2.0/><link rel=alternate href=/legal/epl-2.0/index.xml type=application/rss+xml title><link rel=stylesheet href="/public/css/styles.css?v=
|
|
1
|
+
<!doctype html><html lang=en><head><meta charset=utf-8><meta http-equiv=x-ua-compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><title>Eclipse Public License 2.0 (EPL) | The Eclipse Foundation</title><meta property="og:title" content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=twitter:title content="Eclipse Public License 2.0 (EPL) | The Eclipse Foundation"><meta name=description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta property="og:description" content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=twitter:description content="The Eclipse Foundation provides our global community of individuals and organisations with a mature, scalable, and business-friendly environment for open source …"><meta name=author content="Wayne Beaton"><link href=/favicon.ico rel=icon type=image/x-icon><meta property="og:image" content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:image content="https://www.eclipse.org/images/logos/eclipse-foundation-400x400.png"><meta name=twitter:card content="summary"><meta name=twitter:site content="@eclipsefdn"><meta name=twitter:creator content="@eclipsefdn"><meta property="og:url" content="https://www.eclipse.org/legal/epl-2.0/"><meta property="og:type" content="website"><meta property="og:site_name" content="Eclipse Foundation"><meta name=keywords content="epl,epl-2.0,legal,foundation,eclipse,eclipse public license,license,licenses"><meta name=generator content="Hugo 0.110.0"><link rel=canonical href=https://www.eclipse.org/legal/epl-2.0/><link rel=alternate href=/legal/epl-2.0/index.xml type=application/rss+xml title><link rel=stylesheet href="/public/css/styles.css?v=1731870966"><script>(function(e,t,n,s,o){e[s]=e[s]||[],e[s].push({"gtm.start":(new Date).getTime(),event:"gtm.js"});var a=t.getElementsByTagName(n)[0],i=t.createElement(n),r=s!="dataLayer"?"&l="+s:"";i.async=!0,i.src="https://www.googletagmanager.com/gtm.js?id="+o+r,a.parentNode.insertBefore(i,a)})(window,document,"script","dataLayer","GTM-5WLCZXC")</script><script>var tableClasses="table"</script><link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet type=text/css></head><body><noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-5WLCZXC" height=0 width=0 style=display:none;visibility:hidden></iframe></noscript><a class=sr-only href=#content>Skip to main content</a><header class="header-wrapper header-wrapper" id=header><div class=header-toolbar><div class=container><div class=header-toolbar-row><div class="toolbar-btn toolbar-search-btn dropdown"><button class=dropdown-toggle id=toolbar-search type=button data-toggle=dropdown tabindex=0 aria-label=Search>
|
|
2
2
|
<i class="fa fa-search fa-lg" aria-role=none></i></button><div class="toolbar-search-bar-wrapper dropdown-menu dropdown-menu-right" aria-labelledby=toolbar-search><form action=https://www.eclipse.org/home/search method=get><div class=search-bar><input class=search-bar-input name=q placeholder=Search>
|
|
3
3
|
<button>
|
|
4
4
|
<i class="fa fa-search" type=submit></i></button></div></form></div></div><div class="toolbar-btn toolbar-user-menu-btn dropdown"><button class=dropdown-toggle id=toolbar-user-menu type=button data-toggle=dropdown tabindex=0 aria-label="User Menu">
|
|
@@ -57,5 +57,5 @@ open source software collaboration and innovation.</p></div><div class=mega-menu
|
|
|
57
57
|
<i class="fa fa-linkedin fa-stack-1x fa-inverse" aria-hidden=true></i>
|
|
58
58
|
<span class=sr-only>Linkedin account</span></span></a></li></ul></div></div><div class="footer-sections row equal-height-md font-bold"><div class=col-md-15><div class=row><section id=footer-eclipse-foundation class="footer-section col-sm-8"><div class=menu-heading>Eclipse Foundation</div><ul class=nav><li><a href=https://www.eclipse.org/org/>About</a></li><li><a href=https://projects.eclipse.org/>Projects</a></li><li><a href=https://www.eclipse.org/collaborations/>Collaborations</a></li><li><a href=https://www.eclipse.org/membership/>Membership</a></li><li><a href=https://www.eclipse.org/sponsor/>Sponsor</a></li></ul></section><section id=footer-legal class="footer-section col-sm-8"><div class=menu-heading>Legal</div><ul class=nav><li><a href=https://www.eclipse.org/legal/privacy/>Privacy Policy</a></li><li><a href=https://www.eclipse.org/legal/terms-of-use/>Terms of Use</a></li><li><a href=https://www.eclipse.org/legal/compliance/>Compliance</a></li><li><a href=https://www.eclipse.org/org/documents/Community_Code_of_Conduct.php>Code of Conduct</a></li><li><a href=https://www.eclipse.org/legal/>Legal Resources</a></li><li><a class=toolbar-manage-cookies href=# onclick=event.preventDefault()>Manage Cookies</a></li></ul></section><section id=footer-more class="footer-section col-sm-8"><div class=menu-heading>More</div><ul class=nav><li><a href=https://www.eclipse.org/security/>Report a Vulnerability</a></li><li><a href=https://status.eclipse.org/>Service Status</a></li><li><a href=https://www.eclipse.org/org/foundation/contact.php>Contact Us</a></li><li><a href=https://www.eclipse.org/projects/support/>Support</a></li></ul></section></div></div><div id=footer-end class="footer-section col-md-8 col-md-offset-1 col-sm-24"><div class=footer-end-newsletter><form id=mc-embedded-subscribe-form action=https://eclipsecon.us6.list-manage.com/subscribe/post method=post novalidate target=_blank><label class=footer-end-newsletter-label for=email>Subscribe to our Newsletter</label><div class=footer-end-newsletter-input-wrapper><input class=footer-end-newsletter-input type=email id=email name=EMAIL autocomplete=email placeholder="Enter your email address"><div><i class="fa fa-solid fa-envelope fa-lg" aria-hidden=true></i></div></div><input type=hidden name=u value=eaf9e1f06f194eadc66788a85>
|
|
59
59
|
<input type=hidden name=id value=46e57eacf1>
|
|
60
|
-
<input id=mc-embedded-subscribe type=submit name=subscribe hidden></form></div></div></div><div class="col-sm-24 margin-top-20"><div class=row><div id=copyright class=col-md-16><p id=copyright-text>Copyright © Eclipse Foundation AISBL. All Rights Reserved.</p></div></div></div><a href=# class=scrollup>Back to the top</a></div></footer><div id=footer-js><script src="/public/js/main.js?v1.0?v=
|
|
60
|
+
<input id=mc-embedded-subscribe type=submit name=subscribe hidden></form></div></div></div><div class="col-sm-24 margin-top-20"><div class=row><div id=copyright class=col-md-16><p id=copyright-text>Copyright © Eclipse Foundation AISBL. All Rights Reserved.</p></div></div></div><a href=# class=scrollup>Back to the top</a></div></footer><div id=footer-js><script src="/public/js/main.js?v1.0?v=1731870966"></script>
|
|
61
61
|
<script>(function(){})(jQuery,document)</script></div></body></html>
|