@effekt-lang/effekt 0.28.0 → 0.30.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/bin/effekt +0 -0
- package/libraries/chez/common/effekt_primitives.ss +32 -1
- package/libraries/common/effekt.effekt +5 -5
- package/libraries/common/random.effekt +186 -0
- package/libraries/common/stream.effekt +107 -2
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +41 -32
- package/licenses/the bsd license - bsd-license.html +41 -32
- package/licenses/the mit license - mit.html +42 -33
- package/package.json +1 -1
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -64,8 +64,39 @@
|
|
|
64
64
|
(display str)
|
|
65
65
|
(newline))
|
|
66
66
|
|
|
67
|
+
; Custom structural equality that properly handles records
|
|
67
68
|
(define (equal_impl obj1 obj2)
|
|
68
|
-
(
|
|
69
|
+
(cond
|
|
70
|
+
; Same object reference (fast path)
|
|
71
|
+
[(eq? obj1 obj2) #t]
|
|
72
|
+
|
|
73
|
+
; If both are records, compare them structurally
|
|
74
|
+
[(and (record? obj1) (record? obj2))
|
|
75
|
+
(let* ([rtd1 (record-rtd obj1)]
|
|
76
|
+
[rtd2 (record-rtd obj2)])
|
|
77
|
+
; Check if same record type
|
|
78
|
+
(if (eq? rtd1 rtd2)
|
|
79
|
+
(let* ([n (vector-length (record-type-field-names rtd1))]
|
|
80
|
+
[result #t])
|
|
81
|
+
; Compare all fields recursively
|
|
82
|
+
(do ([i 0 (+ i 1)])
|
|
83
|
+
((or (= i n) (not result)) result)
|
|
84
|
+
(let ([field1 ((record-accessor rtd1 i) obj1)]
|
|
85
|
+
[field2 ((record-accessor rtd2 i) obj2)])
|
|
86
|
+
(if (not (equal_impl field1 field2))
|
|
87
|
+
(set! result #f)))))
|
|
88
|
+
#f))]
|
|
89
|
+
|
|
90
|
+
; For lists, compare elements recursively
|
|
91
|
+
[(and (list? obj1) (list? obj2))
|
|
92
|
+
(and (= (length obj1) (length obj2))
|
|
93
|
+
(let loop ([l1 obj1] [l2 obj2])
|
|
94
|
+
(or (null? l1)
|
|
95
|
+
(and (equal_impl (car l1) (car l2))
|
|
96
|
+
(loop (cdr l1) (cdr l2))))))]
|
|
97
|
+
|
|
98
|
+
; For all other types, use Scheme's built-in equal?
|
|
99
|
+
[else (equal? obj1 obj2)]))
|
|
69
100
|
|
|
70
101
|
(define-syntax thunk
|
|
71
102
|
(syntax-rules ()
|
|
@@ -110,7 +110,7 @@ extern io def inspect[R](value: R): Unit =
|
|
|
110
110
|
// Strings
|
|
111
111
|
// =======
|
|
112
112
|
extern pure def infixConcat(s1: String, s2: String): String =
|
|
113
|
-
js "
|
|
113
|
+
js "${s1} + ${s2}"
|
|
114
114
|
chez "(string-append ${s1} ${s2})"
|
|
115
115
|
llvm """
|
|
116
116
|
%spz = call %Pos @c_bytearray_concatenate(%Pos ${s1}, %Pos ${s2})
|
|
@@ -203,7 +203,7 @@ def println(o: Ordering): Unit = println(o.show)
|
|
|
203
203
|
/// Structural equality: Not available in the LLVM backend
|
|
204
204
|
extern pure def equals[R](x: R, y: R): Bool =
|
|
205
205
|
js "$effekt.equals(${x}, ${y})"
|
|
206
|
-
chez "(
|
|
206
|
+
chez "(equal_impl ${x} ${y})"
|
|
207
207
|
|
|
208
208
|
def differsFrom[R](x: R, y: R): Bool =
|
|
209
209
|
not(equals(x, y))
|
|
@@ -344,7 +344,7 @@ extern pure def infixSub(x: Double, y: Double): Double =
|
|
|
344
344
|
|
|
345
345
|
extern pure def infixDiv(x: Double, y: Double): Double =
|
|
346
346
|
js "(${x} / ${y})"
|
|
347
|
-
chez "(/ ${x} ${y})"
|
|
347
|
+
chez "(fl/ ${x} ${y})"
|
|
348
348
|
llvm "%z = fdiv %Double ${x}, ${y} ret %Double %z"
|
|
349
349
|
vm "effekt::infixDiv(Double, Double)"
|
|
350
350
|
|
|
@@ -442,14 +442,14 @@ extern pure def toInt(d: Double): Int =
|
|
|
442
442
|
|
|
443
443
|
extern pure def toDouble(d: Int): Double =
|
|
444
444
|
js "${d}"
|
|
445
|
-
chez "${d}"
|
|
445
|
+
chez "(fixnum->flonum ${d})"
|
|
446
446
|
llvm "%z = sitofp i64 ${d} to double ret double %z"
|
|
447
447
|
vm "effekt::toDouble(Int)"
|
|
448
448
|
|
|
449
449
|
|
|
450
450
|
extern pure def round(d: Double): Int =
|
|
451
451
|
js "Math.round(${d})"
|
|
452
|
-
chez "(round ${d})"
|
|
452
|
+
chez "(flonum->fixnum (round ${d}))"
|
|
453
453
|
llvm """
|
|
454
454
|
%i = call %Double @llvm.round.f64(double ${d})
|
|
455
455
|
%z = fptosi double %i to %Int ret %Int %z
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
module random
|
|
2
|
+
|
|
3
|
+
import stream
|
|
4
|
+
import io/error
|
|
5
|
+
|
|
6
|
+
/// Infinite pull stream of random bytes.
|
|
7
|
+
effect random(): Byte
|
|
8
|
+
|
|
9
|
+
// ---------------------
|
|
10
|
+
// Sources of randomness
|
|
11
|
+
|
|
12
|
+
/// A streaming source (push stream) of byte-level randomness
|
|
13
|
+
/// based on Park and Miller's MINSTD with revised parameters.
|
|
14
|
+
///
|
|
15
|
+
/// Deterministic: needs a 32bit `seed` -- you can use `bench::timestamp`.
|
|
16
|
+
def minstd(seed: Int): Unit / emit[Byte] = {
|
|
17
|
+
// Initialize state with seed, ensuring it's not zero
|
|
18
|
+
var state = if (seed == 0) 1 else seed
|
|
19
|
+
|
|
20
|
+
def nextInt(): Int = {
|
|
21
|
+
// Uses only at most 32-bit integers internally
|
|
22
|
+
// (Schrage's method: https://en.wikipedia.org/wiki/Lehmer_random_number_generator#Schrage's_method)
|
|
23
|
+
val a = 48271
|
|
24
|
+
val m = 2147483647
|
|
25
|
+
|
|
26
|
+
val q = m / a // 44488
|
|
27
|
+
val r = m.mod(a) // 3399
|
|
28
|
+
|
|
29
|
+
val div = state / q // max: M / Q = A = 48271
|
|
30
|
+
val rem = state.mod(q) // max: Q - 1 = 44487
|
|
31
|
+
|
|
32
|
+
val s = rem * a; // max: 44487 * 48271 = 2147431977
|
|
33
|
+
val t = div * r; // max: 48271 * 3399 = 164073129
|
|
34
|
+
|
|
35
|
+
val result = s - t
|
|
36
|
+
// keep the state positive
|
|
37
|
+
if (result < 0) result + m else result
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
while (true) {
|
|
41
|
+
state = nextInt()
|
|
42
|
+
val b = state.mod(256).toByte
|
|
43
|
+
do emit(b)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// A thin wrapper over `minstd`, handling a reader of random bytes.
|
|
48
|
+
///
|
|
49
|
+
/// Deterministic: needs a 32bit `seed` -- you can use `bench::timestamp`.
|
|
50
|
+
///
|
|
51
|
+
/// Implementation is similar to `stream::source`, specialized for bytes and the `random` effect.
|
|
52
|
+
def minstd(seed: Int) { randomnessReader: () => Unit / random }: Unit = {
|
|
53
|
+
var next = box { 255.toByte } // sentinel value
|
|
54
|
+
next = box {
|
|
55
|
+
try {
|
|
56
|
+
minstd(seed)
|
|
57
|
+
<> // safe: randomness generator cannot run out of numbers...
|
|
58
|
+
} with emit[Byte] { v =>
|
|
59
|
+
next = box { resume(()) }
|
|
60
|
+
v
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try randomnessReader() with random {
|
|
65
|
+
resume(next())
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// CSPRNG from `/dev/urandom`, handling a reader of random bytes.
|
|
70
|
+
/// Only works on Unix-like OSes!
|
|
71
|
+
def devurandom { randomnessReader: () => Unit / random }: Unit / Exception[IOError] =
|
|
72
|
+
try {
|
|
73
|
+
with readFile("/dev/urandom")
|
|
74
|
+
try randomnessReader() with random {
|
|
75
|
+
resume(do read[Byte]())
|
|
76
|
+
}
|
|
77
|
+
} with stop {
|
|
78
|
+
do raise(io::error::EOF(), "Unexpected EOF when reading /dev/urandom!")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ------------------------
|
|
82
|
+
// Functions using `random`
|
|
83
|
+
//
|
|
84
|
+
// Always two variants:
|
|
85
|
+
// - readType(): Type / random
|
|
86
|
+
// - readTypes(): Unit / {emit[Type], random}
|
|
87
|
+
|
|
88
|
+
def randomByte(): Byte / random = do random()
|
|
89
|
+
def randomBytes(): Unit / {emit[Byte], random} =
|
|
90
|
+
while (true) do emit(do random())
|
|
91
|
+
|
|
92
|
+
def randomBool(): Bool / random = {
|
|
93
|
+
val b = do random()
|
|
94
|
+
b.toInt.mod(2) == 1
|
|
95
|
+
}
|
|
96
|
+
def randomBools(): Unit / {emit[Bool], random} =
|
|
97
|
+
while (true) do emit(randomBool())
|
|
98
|
+
|
|
99
|
+
def randomInt32(): Int / random = {
|
|
100
|
+
var result = 0
|
|
101
|
+
repeat(4) {
|
|
102
|
+
val b = do random()
|
|
103
|
+
result = result * 256 + b.toInt
|
|
104
|
+
}
|
|
105
|
+
val signBit = result.bitwiseShr(31).bitwiseAnd(1) == 0
|
|
106
|
+
result.mod(1.bitwiseShl(31)).abs * if (signBit) 1 else -1
|
|
107
|
+
}
|
|
108
|
+
def randomInt32s(): Unit / {emit[Int], random} =
|
|
109
|
+
while (true) do emit(randomInt32())
|
|
110
|
+
|
|
111
|
+
/// `max` is _inclusive_!
|
|
112
|
+
def randomInt(min: Int, max: Int): Int / random = {
|
|
113
|
+
if (min > max) {
|
|
114
|
+
randomInt(max, min)
|
|
115
|
+
} else {
|
|
116
|
+
val range = max - min + 1
|
|
117
|
+
val bytesNeeded = (log(range.toDouble) / log(256.0)).ceil
|
|
118
|
+
|
|
119
|
+
var result = 0
|
|
120
|
+
repeat(bytesNeeded) {
|
|
121
|
+
val b = do random()
|
|
122
|
+
result = result * 256 + b.toInt
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
min + (abs(result).mod(range))
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/// `max` is _inclusive_!
|
|
129
|
+
def randomInts(min: Int, max: Int): Unit / {emit[Int], random} =
|
|
130
|
+
while (true) do emit(randomInt(min, max))
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
/// Random double between 0.0 and 1.0
|
|
134
|
+
def randomDouble(): Double / random =
|
|
135
|
+
(randomInt32().toDouble / 1.bitwiseShl(31).toDouble).abs
|
|
136
|
+
// This is not perfect, but it will do for now.
|
|
137
|
+
def randomDoubles(): Unit / {emit[Double], random} =
|
|
138
|
+
while (true) do emit(randomDouble())
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
namespace examples {
|
|
142
|
+
def main() = {
|
|
143
|
+
println("prng")
|
|
144
|
+
prngRandom()
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
def prngRandom(): Unit = {
|
|
148
|
+
with minstd(1337);
|
|
149
|
+
|
|
150
|
+
println("int32s:")
|
|
151
|
+
repeat(10) {
|
|
152
|
+
println(randomInt32())
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
println("int32s, part2:")
|
|
156
|
+
repeat(10) {
|
|
157
|
+
println(randomInt(0, 2147483647))
|
|
158
|
+
println(randomInt(-2147483648, 0))
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
println("doubles:")
|
|
162
|
+
repeat(10) {
|
|
163
|
+
println(randomDouble().round(3))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
println("randomInt:")
|
|
167
|
+
repeat(10) {
|
|
168
|
+
val a = randomInt(0, 9)
|
|
169
|
+
val b = randomInt(0, 9)
|
|
170
|
+
val c = randomInt(0, 9)
|
|
171
|
+
println(a.show ++ " " ++ b.show ++ " " ++ c.show)
|
|
172
|
+
println(a*100 + b*10 + c)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
def unixRandom(): Unit = {
|
|
177
|
+
with on[IOError].report;
|
|
178
|
+
with devurandom;
|
|
179
|
+
|
|
180
|
+
val a = randomInt32()
|
|
181
|
+
val b = randomInt32()
|
|
182
|
+
|
|
183
|
+
// This is just to use the generated numbers :)
|
|
184
|
+
println((a.show ++ b.show).length != 0)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -173,10 +173,23 @@ def replicate[A](number: Int) { action: () => A }: Unit / emit[A] =
|
|
|
173
173
|
replicate(number - 1) {action}
|
|
174
174
|
}
|
|
175
175
|
|
|
176
|
+
/// Creates an infinite iterated stream given by an `initial` seed and a `step` function:
|
|
177
|
+
/// iterate(a){f} ~> a, f(a), f(f(a)), f(f(f(a))), ...
|
|
178
|
+
def iterate[A](initial: A) { step: A => A }: Unit / emit[A] = {
|
|
179
|
+
var current = initial
|
|
180
|
+
while (true) {
|
|
181
|
+
do emit(current)
|
|
182
|
+
current = step(current)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
176
185
|
|
|
177
|
-
|
|
186
|
+
|
|
187
|
+
def sum { stream: () => Unit / emit[Int] }: Int =
|
|
178
188
|
returning::sum[Unit]{stream}.second
|
|
179
189
|
|
|
190
|
+
def product { stream: () => Unit / emit[Int] }: Int =
|
|
191
|
+
returning::product[Unit]{stream}.second
|
|
192
|
+
|
|
180
193
|
def collectList[A] { stream: () => Unit / emit[A] }: List[A] =
|
|
181
194
|
returning::collectList[A, Unit]{stream}.second
|
|
182
195
|
|
|
@@ -409,6 +422,88 @@ def each(string: String): Unit / emit[Char] =
|
|
|
409
422
|
def collectString { stream: () => Unit / emit[Char] }: String =
|
|
410
423
|
returning::collectString[Unit]{stream}.second
|
|
411
424
|
|
|
425
|
+
namespace internal {
|
|
426
|
+
effect snapshot(): Unit
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/// Use cons to handle prod, but also emit to the outside.
|
|
430
|
+
/// The outside controls iteration, i.e., if cons aborts, the rest of prod will still be emitted.
|
|
431
|
+
///
|
|
432
|
+
/// Starts by executing cons. Will stop cons during execution if the outside stops consuming.
|
|
433
|
+
///
|
|
434
|
+
/// Example, printing all values consumed by the outside:
|
|
435
|
+
///
|
|
436
|
+
/// with teeing{ {s} => for{s}{ e => println(e) } }
|
|
437
|
+
/// prod() // some producer
|
|
438
|
+
///
|
|
439
|
+
/// Laws-ish (hopefully):
|
|
440
|
+
/// - hnd{ prd() } === hnd{ teeing{t}{ prd() } } for all hnd and t that calls its argument at most once (and has no other captures)
|
|
441
|
+
def teeing[A]{ cons: { => Unit / emit[A] } => Unit }{ prod: => Unit / emit[A] }: Unit / emit[A] = region r {
|
|
442
|
+
var consDone = false
|
|
443
|
+
var k in r = box { prod() } // what still needs to run of prod after cons exits
|
|
444
|
+
try {
|
|
445
|
+
cons{
|
|
446
|
+
try {
|
|
447
|
+
prod()
|
|
448
|
+
k = box { () }
|
|
449
|
+
} with emit[A] { v =>
|
|
450
|
+
do internal::snapshot() // remember that we need to continue here if cons aborts
|
|
451
|
+
if(not(consDone)) do emit(v)
|
|
452
|
+
outer.emit(v)
|
|
453
|
+
resume(())
|
|
454
|
+
}
|
|
455
|
+
if(consDone) do stop() // cons already exited, so skip continuing there
|
|
456
|
+
} // end cons
|
|
457
|
+
consDone = true
|
|
458
|
+
}
|
|
459
|
+
with stop { () => () }
|
|
460
|
+
with outer: emit[A]{ v => resume(do emit(v)) }
|
|
461
|
+
with internal::snapshot{ () =>
|
|
462
|
+
k = box { resume(()) }
|
|
463
|
+
resume(())
|
|
464
|
+
}
|
|
465
|
+
k()
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/// Binds a `teeing`-like function in the body, stopping the inner producer once all consumers in tees are done consuming.
|
|
469
|
+
///
|
|
470
|
+
/// Example of use, equivalent to `tee[A]{cns1}{cns2}{prd}`:
|
|
471
|
+
///
|
|
472
|
+
/// manyTee[A] { {tee} =>
|
|
473
|
+
/// with tee{cns1}
|
|
474
|
+
/// with tee{cns2}
|
|
475
|
+
/// prd()
|
|
476
|
+
/// }
|
|
477
|
+
///
|
|
478
|
+
def manyTee[A]{ body: { { { => Unit / emit[A] } => Unit }{ => Unit / emit[A] } => Unit / emit[A] } => Unit / emit[A] }: Unit = {
|
|
479
|
+
var running = 0
|
|
480
|
+
try {
|
|
481
|
+
body{ {hnd}{prod} =>
|
|
482
|
+
running = running + 1
|
|
483
|
+
teeing[A]{ {b} => hnd{b}; running = running - 1 }{prod}
|
|
484
|
+
}
|
|
485
|
+
} with emit[A] { _ =>
|
|
486
|
+
if(running > 0) resume(())
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/// Streams prod to both cons1 and cons2. Stops once both cons1 and cons2 stopped.
|
|
491
|
+
/// Only runs prod once, resuming at most once at each emit.
|
|
492
|
+
///
|
|
493
|
+
/// var sumRes = 0
|
|
494
|
+
/// var productRes = 0
|
|
495
|
+
/// tee{ s => sumRes = sum{s} }{ s => productRes = product{s} }{ range(0, 10) }
|
|
496
|
+
/// assertEquals(sum{ range(0, 10) }, sumRes)
|
|
497
|
+
/// assertEquals(product{ range(0, 10) }, productRes)
|
|
498
|
+
///
|
|
499
|
+
def tee[A]{ cons1: { => Unit / emit[A] } => Unit }{ cons2: { => Unit / emit[A] } => Unit }{ prod: => Unit / emit[A] }: Unit = {
|
|
500
|
+
manyTee[A]{ {tee} =>
|
|
501
|
+
with tee{cons1}
|
|
502
|
+
with tee{cons2}
|
|
503
|
+
prod()
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
412
507
|
namespace returning {
|
|
413
508
|
|
|
414
509
|
/// Canonical handler of push streams that performs `action` for every
|
|
@@ -461,7 +556,7 @@ def limit[A, R](number: Int) { stream: () => R / emit[A] }: R / { emit[A], stop
|
|
|
461
556
|
}
|
|
462
557
|
}
|
|
463
558
|
|
|
464
|
-
def sum[R] { stream
|
|
559
|
+
def sum[R] { stream: () => R / emit[Int] }: (R, Int) = {
|
|
465
560
|
var s = 0;
|
|
466
561
|
try {
|
|
467
562
|
(stream(), s)
|
|
@@ -471,6 +566,16 @@ def sum[R] { stream : () => R / emit[Int] }: (R, Int) = {
|
|
|
471
566
|
}
|
|
472
567
|
}
|
|
473
568
|
|
|
569
|
+
def product[R] { stream: () => R / emit[Int] }: (R, Int) = {
|
|
570
|
+
var s = 1;
|
|
571
|
+
try {
|
|
572
|
+
(stream(), s)
|
|
573
|
+
} with emit[Int] { v =>
|
|
574
|
+
s = s * v;
|
|
575
|
+
resume(())
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
|
|
474
579
|
def collectList[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
|
|
475
580
|
try {
|
|
476
581
|
(stream(), Nil())
|
|
@@ -1,5 +1,5 @@
|
|
|
1
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>
|
|
2
|
-
<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.144.2"><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=
|
|
2
|
+
<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.144.2"><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=1746987328"><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>
|
|
3
3
|
<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>
|
|
4
4
|
<button>
|
|
5
5
|
<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">
|
|
@@ -60,4 +60,4 @@ open source software collaboration and innovation.</p></div><div class=mega-menu
|
|
|
60
60
|
<i class="fa-brands fa-linkedin-in fa-stack-1x fa-inverse" aria-hidden=true></i>
|
|
61
61
|
<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://eclipse.us6.list-manage.com/subscribe/post?u=eaf9e1f06f194eadc66788a85&id=e7538485cd&f_id=00f9c2e1f0" 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">
|
|
62
62
|
<button class="footer-end-newsletter-submit btn btn-link" id=mc-embedded-subscribe type=submit name=subscribe>
|
|
63
|
-
<i class="fa fa-solid fa-envelope fa-lg" aria-hidden=true></i></button></div></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=
|
|
63
|
+
<i class="fa fa-solid fa-envelope fa-lg" aria-hidden=true></i></button></div></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=1746987328"></script><script>(function(){})(jQuery,document)</script></div></body></html>
|