@effekt-lang/effekt 0.14.0 → 0.15.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/common/char.effekt +47 -23
- package/libraries/common/effekt.effekt +6 -1
- package/libraries/common/json.effekt +385 -0
- package/libraries/common/scanner.effekt +171 -0
- package/libraries/common/stream.effekt +161 -134
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +1263 -0
- package/licenses/the bsd license - bsd-license.html +1261 -0
- package/licenses/the mit license - mit.html +1261 -0
- package/package.json +1 -1
|
@@ -19,24 +19,13 @@ effect read[A](): A / stop
|
|
|
19
19
|
/// Signal from a producer to a consumer that there are no further values.
|
|
20
20
|
effect stop(): Nothing
|
|
21
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
22
|
/// Like `for[A, R]`, but ignores the result of the stream, and consequently
|
|
32
23
|
/// works for any type. Use this to annotate the type of stream elements
|
|
33
24
|
/// `A` without having to also annotate `R`.
|
|
34
25
|
///
|
|
35
26
|
/// e.g. for[Int] { prog() } { el => println(el) }
|
|
36
|
-
def for[A] { stream: () =>
|
|
37
|
-
for[A,
|
|
38
|
-
()
|
|
39
|
-
}
|
|
27
|
+
def for[A] { stream: () => Unit / emit[A] } { action: A => Unit }: Unit =
|
|
28
|
+
returning::for[A, Unit]{stream}{action}
|
|
40
29
|
|
|
41
30
|
/// Turns a `list` into a producer of a push stream
|
|
42
31
|
/// by emitting each contained value left-to-right.
|
|
@@ -81,20 +70,13 @@ def each(bytes: ByteArray): Unit / emit[Byte] = {
|
|
|
81
70
|
// not seq
|
|
82
71
|
|
|
83
72
|
|
|
84
|
-
def boundary
|
|
85
|
-
|
|
86
|
-
Some(program())
|
|
87
|
-
} with stop {
|
|
88
|
-
None()
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
def boundary { program: () => Any / stop }: Unit = {
|
|
92
|
-
boundary[Any]{program}
|
|
73
|
+
def boundary { program: () => Unit / stop }: Unit = {
|
|
74
|
+
returning::boundary[Unit]{program}
|
|
93
75
|
()
|
|
94
76
|
}
|
|
95
77
|
|
|
96
78
|
/// Run `program` forever until `stop` is thrown.
|
|
97
|
-
def exhaustively { program: () =>
|
|
79
|
+
def exhaustively { program: () => Unit / stop }: Unit =
|
|
98
80
|
try {
|
|
99
81
|
def go(): Unit = {
|
|
100
82
|
program()
|
|
@@ -105,6 +87,24 @@ def exhaustively { program: () => Any / stop }: Unit =
|
|
|
105
87
|
()
|
|
106
88
|
}
|
|
107
89
|
|
|
90
|
+
def many[A] { action: () => A / stop }: Unit / emit[A] =
|
|
91
|
+
exhaustively { do emit(action()) }
|
|
92
|
+
|
|
93
|
+
def some[A] { action: () => A / stop }: Unit / { emit[A], stop } = {
|
|
94
|
+
do emit(action())
|
|
95
|
+
many { action() }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
def optionally { program: () => Unit / stop }: Bool =
|
|
99
|
+
returning::optionally[Unit]{program}.isDefined
|
|
100
|
+
|
|
101
|
+
def attempt[R] { program: () => R / stop } { fallback: () => R }: R =
|
|
102
|
+
try {
|
|
103
|
+
program()
|
|
104
|
+
} with stop {
|
|
105
|
+
fallback()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
108
|
|
|
109
109
|
/// In Effekt lower bounds are inclusive and upper bounds are exclusive
|
|
110
110
|
record Indexed[A](index: Int, value: A)
|
|
@@ -123,39 +123,13 @@ def rangeFrom(lower: Int): Unit / emit[Int] = {
|
|
|
123
123
|
rangeFrom(lower + 1)
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
def index[A] { stream: () => Unit / emit[A] }: Unit / emit[Indexed[A]] =
|
|
127
|
+
returning::index[A, Unit]{stream}
|
|
126
128
|
|
|
127
|
-
def index[A, R] { stream: () => R / emit[A] }: R / emit[Indexed[A]] = {
|
|
128
|
-
var i = 0;
|
|
129
|
-
try {
|
|
130
|
-
stream()
|
|
131
|
-
} with emit[A] { v =>
|
|
132
|
-
val c = i;
|
|
133
|
-
i = c + 1;
|
|
134
|
-
resume(do emit(Indexed(c, v)))
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
129
|
|
|
138
130
|
/// If `number` is zero or negative it does nothing
|
|
139
|
-
def limit[A
|
|
140
|
-
|
|
141
|
-
var i = 1;
|
|
142
|
-
try {
|
|
143
|
-
stream()
|
|
144
|
-
} with emit[A] { v =>
|
|
145
|
-
if (i < number) {
|
|
146
|
-
i = i + 1;
|
|
147
|
-
resume(do emit(v))
|
|
148
|
-
} else {
|
|
149
|
-
do stop()
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/// If `number` is zero or negative it does nothing
|
|
155
|
-
def limit[A](number: Int) { stream: () => Any / emit[A] }: Unit / emit[A] =
|
|
156
|
-
boundary {
|
|
157
|
-
limit[A, Any](number){stream}
|
|
158
|
-
}
|
|
131
|
+
def limit[A](number: Int) { stream: () => Unit / emit[A] }: Unit / {emit[A], stop} =
|
|
132
|
+
returning::limit[A, Unit](number){stream}
|
|
159
133
|
|
|
160
134
|
|
|
161
135
|
/// If `number` is zero or negative it does nothing
|
|
@@ -166,61 +140,17 @@ def replicate[A](number: Int) { action: () => A }: Unit / emit[A] =
|
|
|
166
140
|
}
|
|
167
141
|
|
|
168
142
|
|
|
169
|
-
def sum
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
(stream(), s)
|
|
173
|
-
} with emit[Int] { v =>
|
|
174
|
-
s = s + v;
|
|
175
|
-
resume(())
|
|
176
|
-
}
|
|
177
|
-
}
|
|
143
|
+
def sum { stream : () => Unit / emit[Int] }: Int =
|
|
144
|
+
returning::sum[Unit]{stream}.second
|
|
178
145
|
|
|
179
|
-
def
|
|
180
|
-
|
|
146
|
+
def collectList[A] { stream: () => Unit / emit[A] }: List[A] =
|
|
147
|
+
returning::collectList[A, Unit]{stream}.second
|
|
181
148
|
|
|
182
|
-
def
|
|
183
|
-
|
|
184
|
-
(stream(), Nil())
|
|
185
|
-
} with emit[A] { (v) =>
|
|
186
|
-
val (r, vs) = resume(());
|
|
187
|
-
(r, Cons(v, vs))
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
def collectList[A] { stream: () => Any / emit[A] }: List[A] =
|
|
191
|
-
collectList[A, Any]{stream}.second
|
|
192
|
-
|
|
193
|
-
def collectArray[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
|
|
194
|
-
var i = 0
|
|
195
|
-
var a = array::allocate(1)
|
|
196
|
-
try {
|
|
197
|
-
(stream(), a.resize(i))
|
|
198
|
-
} with emit[A] { (v) =>
|
|
199
|
-
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
200
|
-
a.unsafeSet(i, v)
|
|
201
|
-
i = i + 1
|
|
202
|
-
resume(())
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
def collectArray[A] { stream: () => Any / emit[A] }: Array[A] =
|
|
207
|
-
collectArray[A, Any]{stream}.second
|
|
208
|
-
|
|
209
|
-
def collectBytes[R] { stream: () => R / emit[Byte] }: (R, ByteArray) = {
|
|
210
|
-
var i = 0
|
|
211
|
-
var a = bytearray::allocate(1)
|
|
212
|
-
try {
|
|
213
|
-
(stream(), a.resize(i))
|
|
214
|
-
} with emit[Byte] { (v) =>
|
|
215
|
-
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
216
|
-
a.unsafeSet(i, v)
|
|
217
|
-
i = i + 1
|
|
218
|
-
resume(())
|
|
219
|
-
}
|
|
220
|
-
}
|
|
149
|
+
def collectArray[A] { stream: () => Unit / emit[A] }: Array[A] =
|
|
150
|
+
returning::collectArray[A, Unit]{stream}.second
|
|
221
151
|
|
|
222
|
-
def collectBytes { stream: () =>
|
|
223
|
-
collectBytes[
|
|
152
|
+
def collectBytes { stream: () => Unit / emit[Byte] }: ByteArray =
|
|
153
|
+
returning::collectBytes[Unit]{stream}.second
|
|
224
154
|
|
|
225
155
|
def feed[T, R](list: List[T]) { reader: () => R / read[T] }: R = {
|
|
226
156
|
var l = list
|
|
@@ -272,34 +202,12 @@ def feed[R](bytes: ByteArray) { reader: () => R / read[Byte] }: R = {
|
|
|
272
202
|
}
|
|
273
203
|
}
|
|
274
204
|
|
|
275
|
-
def source[A
|
|
276
|
-
|
|
277
|
-
next = box {
|
|
278
|
-
try {
|
|
279
|
-
stream()
|
|
280
|
-
None()
|
|
281
|
-
} with emit[A] { (v) =>
|
|
282
|
-
next = box { resume(()) }
|
|
283
|
-
Some(v)
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
try {
|
|
287
|
-
reader()
|
|
288
|
-
} with read[A] {
|
|
289
|
-
resume {
|
|
290
|
-
next().getOrElse { do stop() }
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
def source[A] { stream: () => Any / emit[A] } { reader: () => Any / read[A] }: Unit = {
|
|
296
|
-
source[A, Any]{stream}{reader}
|
|
297
|
-
()
|
|
298
|
-
}
|
|
205
|
+
def source[A] { stream: () => Unit / emit[A] } { reader: () => Unit / read[A] }: Unit =
|
|
206
|
+
returning::source[A, Unit]{stream}{reader}
|
|
299
207
|
|
|
300
208
|
/// Combines two streams together producing a stream of pairs in lockstep.
|
|
301
|
-
///
|
|
302
|
-
def zip[A, B] { stream1: () =>
|
|
209
|
+
/// Terminates when either of them terminates.
|
|
210
|
+
def zip[A, B] { stream1: () => Unit / emit[A] } { stream2: () => Unit / emit[B] } { action: (A, B) => Unit }: Unit = {
|
|
303
211
|
with source[A] { stream1 }
|
|
304
212
|
with source[B] { stream2 }
|
|
305
213
|
|
|
@@ -423,7 +331,7 @@ def encodeUTF8[R] { stream: () => R / emit[Char] }: R / emit[Byte] =
|
|
|
423
331
|
resume(encodeChar(char))
|
|
424
332
|
}
|
|
425
333
|
|
|
426
|
-
def feed(string: String) { reader: () =>
|
|
334
|
+
def feed[R](string: String) { reader: () => R / read[Char] } =
|
|
427
335
|
feed(string.fromString) {
|
|
428
336
|
decodeUTF8 {
|
|
429
337
|
reader()
|
|
@@ -437,10 +345,129 @@ def each(string: String): Unit / emit[Char] =
|
|
|
437
345
|
}
|
|
438
346
|
}
|
|
439
347
|
|
|
348
|
+
def collectString { stream: () => Unit / emit[Char] }: String =
|
|
349
|
+
returning::collectString[Unit]{stream}.second
|
|
350
|
+
|
|
351
|
+
namespace returning {
|
|
352
|
+
|
|
353
|
+
/// Canonical handler of push streams that performs `action` for every
|
|
354
|
+
/// value emitted by `stream`.
|
|
355
|
+
def for[A, R] { stream: () => R / emit[A] } { action: A => Unit }: R =
|
|
356
|
+
try {
|
|
357
|
+
stream()
|
|
358
|
+
} with emit[A] { value =>
|
|
359
|
+
resume(action(value))
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
def boundary[R] { program: () => R / stop }: Option[R] =
|
|
363
|
+
try {
|
|
364
|
+
Some(program())
|
|
365
|
+
} with stop {
|
|
366
|
+
None()
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
def optionally[R] { program: () => R / stop }: Option[R] =
|
|
370
|
+
try {
|
|
371
|
+
Some(program())
|
|
372
|
+
} with stop {
|
|
373
|
+
None()
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
def index[A, R] { stream: () => R / emit[A] }: R / emit[Indexed[A]] = {
|
|
377
|
+
var i = 0;
|
|
378
|
+
try {
|
|
379
|
+
stream()
|
|
380
|
+
} with emit[A] { v =>
|
|
381
|
+
val c = i;
|
|
382
|
+
i = c + 1;
|
|
383
|
+
resume(do emit(Indexed(c, v)))
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/// If `number` is zero or negative it does nothing
|
|
388
|
+
def limit[A, R](number: Int) { stream: () => R / emit[A] }: R / { emit[A], stop } = {
|
|
389
|
+
if (number <= 0) do stop();
|
|
390
|
+
var i = 1;
|
|
391
|
+
try {
|
|
392
|
+
stream()
|
|
393
|
+
} with emit[A] { v =>
|
|
394
|
+
if (i < number) {
|
|
395
|
+
i = i + 1;
|
|
396
|
+
resume(do emit(v))
|
|
397
|
+
} else {
|
|
398
|
+
do stop()
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
def sum[R] { stream : () => R / emit[Int] }: (R, Int) = {
|
|
404
|
+
var s = 0;
|
|
405
|
+
try {
|
|
406
|
+
(stream(), s)
|
|
407
|
+
} with emit[Int] { v =>
|
|
408
|
+
s = s + v;
|
|
409
|
+
resume(())
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
def collectList[A, R] { stream: () => R / emit[A] }: (R, List[A]) =
|
|
414
|
+
try {
|
|
415
|
+
(stream(), Nil())
|
|
416
|
+
} with emit[A] { (v) =>
|
|
417
|
+
val (r, vs) = resume(());
|
|
418
|
+
(r, Cons(v, vs))
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
def collectArray[A, R] { stream: () => R / emit[A] }: (R, Array[A]) = {
|
|
422
|
+
var i = 0
|
|
423
|
+
var a = array::allocate(1)
|
|
424
|
+
try {
|
|
425
|
+
(stream(), a.resize(i))
|
|
426
|
+
} with emit[A] { (v) =>
|
|
427
|
+
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
428
|
+
a.unsafeSet(i, v)
|
|
429
|
+
i = i + 1
|
|
430
|
+
resume(())
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
def collectBytes[R] { stream: () => R / emit[Byte] }: (R, ByteArray) = {
|
|
435
|
+
var i = 0
|
|
436
|
+
var a = bytearray::allocate(1)
|
|
437
|
+
try {
|
|
438
|
+
(stream(), a.resize(i))
|
|
439
|
+
} with emit[Byte] { (v) =>
|
|
440
|
+
if (i >= a.size) { a = a.resize(2 * a.size) }
|
|
441
|
+
a.unsafeSet(i, v)
|
|
442
|
+
i = i + 1
|
|
443
|
+
resume(())
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
440
447
|
def collectString[R] { stream: () => R / emit[Char] }: (R, String) = {
|
|
441
448
|
val (result, bytes) = collectBytes[R] { encodeUTF8 { stream } }
|
|
442
449
|
(result, bytes.toString)
|
|
443
450
|
}
|
|
444
451
|
|
|
445
|
-
def
|
|
446
|
-
|
|
452
|
+
def source[A, R] { stream: () => Unit / emit[A] } { reader: () => R / read[A] }: R = {
|
|
453
|
+
var next = box { None() }
|
|
454
|
+
next = box {
|
|
455
|
+
try {
|
|
456
|
+
stream()
|
|
457
|
+
next = box { None() }
|
|
458
|
+
None()
|
|
459
|
+
} with emit[A] { (v) =>
|
|
460
|
+
next = box { resume(()) }
|
|
461
|
+
Some(v)
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
try {
|
|
465
|
+
reader()
|
|
466
|
+
} with read[A] {
|
|
467
|
+
resume {
|
|
468
|
+
next().getOrElse { do stop() }
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
}
|
|
@@ -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=1734894944"><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-brands fa-linkedin-in 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=1734894944"></script>
|
|
61
61
|
<script>(function(){})(jQuery,document)</script></div></body></html>
|