@effekt-lang/effekt 0.50.0 → 0.52.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 +1 -1
- package/libraries/common/effekt.effekt +4 -0
- package/libraries/common/io/error.effekt +96 -83
- package/libraries/common/json.effekt +5 -5
- package/libraries/common/random.effekt +1 -1
- package/libraries/common/scanner.effekt +8 -8
- package/libraries/common/stream.effekt +1 -1
- package/libraries/common/string.effekt +1 -1
- package/libraries/llvm/forward-declare-c.ll +1 -0
- package/libraries/llvm/io.c +6 -2
- package/libraries/llvm/main.c +1 -0
- package/licenses/eclipse public license, version 2.0 - epl-2.0.html +2 -2
- package/licenses/mit license - mit-license.html +56 -66
- package/licenses/the bsd license - bsd-license.html +58 -62
- package/licenses/the mit license - mit.html +58 -66
- package/package.json +1 -1
package/bin/effekt
CHANGED
|
Binary file
|
|
@@ -164,6 +164,10 @@ extern def unsafeSubstring(str: String, from: Int, to: Int) at {}: String =
|
|
|
164
164
|
extern def random() at io: Double =
|
|
165
165
|
js "Math.random()"
|
|
166
166
|
chez "(random 1.0)"
|
|
167
|
+
llvm """
|
|
168
|
+
%r = call double @c_io_random()
|
|
169
|
+
ret double %r
|
|
170
|
+
"""
|
|
167
171
|
vm "effekt::random()"
|
|
168
172
|
|
|
169
173
|
// References and state
|
|
@@ -362,97 +362,110 @@ namespace internal {
|
|
|
362
362
|
declare %Int @c_error_number(%Int)
|
|
363
363
|
"""
|
|
364
364
|
|
|
365
|
-
|
|
366
|
-
const
|
|
365
|
+
extern jsNode """
|
|
366
|
+
const { getSystemErrorName } = require('node:util');
|
|
367
367
|
|
|
368
368
|
/**
|
|
369
369
|
* Maps the error code to a Effekt-stable (platform independent) numeric value.
|
|
370
370
|
*
|
|
371
371
|
* Tries to use most common errno integer values, but introduces fresh values (> 200)
|
|
372
372
|
* for those without common errno values.
|
|
373
|
+
*
|
|
374
|
+
* The mapping from platfrom-specific error codes to Effekt error codes is handled by
|
|
375
|
+
* getSystemErrorName from 'node:util', which in turn uses the error code conventions from libuv.
|
|
376
|
+
* For reference, see the following Deno code which is more readable than the NodeJS implementation:
|
|
377
|
+
* https://github.com/denoland/deno/blob/8fb073d7b4ea83b57fd1bf9875681347b414bbe6/ext/node/polyfills/internal_binding/uv.ts
|
|
373
378
|
*/
|
|
374
379
|
function errorNumber(errno) {
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
380
|
+
const mapByName = {
|
|
381
|
+
EPERM: 1,
|
|
382
|
+
ENOENT: 2,
|
|
383
|
+
ESRCH: 3,
|
|
384
|
+
EINTR: 4,
|
|
385
|
+
EIO: 5,
|
|
386
|
+
ENXIO: 6,
|
|
387
|
+
E2BIG: 7,
|
|
388
|
+
EBADF: 9,
|
|
389
|
+
EAGAIN: 11,
|
|
390
|
+
ENOMEM: 12,
|
|
391
|
+
EACCES: 13,
|
|
392
|
+
EFAULT: 14,
|
|
393
|
+
EBUSY: 16,
|
|
394
|
+
EEXIST: 17,
|
|
395
|
+
EXDEV: 18,
|
|
396
|
+
ENODEV: 19,
|
|
397
|
+
ENOTDIR: 20,
|
|
398
|
+
EISDIR: 21,
|
|
399
|
+
EINVAL: 22,
|
|
400
|
+
ENFILE: 23,
|
|
401
|
+
EMFILE: 24,
|
|
402
|
+
ENOTTY: 25,
|
|
403
|
+
ETXTBSY: 26,
|
|
404
|
+
EFBIG: 27,
|
|
405
|
+
ENOSPC: 28,
|
|
406
|
+
ESPIPE: 29,
|
|
407
|
+
EROFS: 30,
|
|
408
|
+
EMLINK: 31,
|
|
409
|
+
EPIPE: 32,
|
|
410
|
+
ERANGE: 34,
|
|
411
|
+
ENAMETOOLONG: 36,
|
|
412
|
+
ELOOP: 40,
|
|
413
|
+
EOVERFLOW: 75,
|
|
414
|
+
EFTYPE: 79,
|
|
415
|
+
EILSEQ: 84,
|
|
416
|
+
ENOTSOCK: 88,
|
|
417
|
+
EDESTADDRREQ: 89,
|
|
418
|
+
EMSGSIZE: 90,
|
|
419
|
+
EPROTOTYPE: 91,
|
|
420
|
+
ENOPROTOOPT: 92,
|
|
421
|
+
EPROTONOSUPPORT: 93,
|
|
422
|
+
ESOCKTNOSUPPORT: 94,
|
|
423
|
+
ENOTSUP: 95,
|
|
424
|
+
EAFNOSUPPORT: 97,
|
|
425
|
+
EADDRINUSE: 98,
|
|
426
|
+
EADDRNOTAVAIL: 99,
|
|
427
|
+
ENETDOWN: 100,
|
|
428
|
+
ENETUNREACH: 101,
|
|
429
|
+
ECONNABORTED: 103,
|
|
430
|
+
ECONNRESET: 104,
|
|
431
|
+
ENOBUFS: 105,
|
|
432
|
+
EISCONN: 106,
|
|
433
|
+
ENOTCONN: 107,
|
|
434
|
+
ETIMEDOUT: 110,
|
|
435
|
+
ECONNREFUSED: 111,
|
|
436
|
+
EHOSTUNREACH: 113,
|
|
437
|
+
EALREADY: 114,
|
|
438
|
+
ECANCELED: 125,
|
|
439
|
+
|
|
440
|
+
EAI_ADDRFAMILY: 200,
|
|
441
|
+
EAI_AGAIN: 201,
|
|
442
|
+
EAI_BADFLAGS: 202,
|
|
443
|
+
EAI_BADHINTS: 203,
|
|
444
|
+
EAI_CANCELED: 204,
|
|
445
|
+
EAI_FAIL: 205,
|
|
446
|
+
EAI_FAMILY: 206,
|
|
447
|
+
EAI_MEMORY: 207,
|
|
448
|
+
EAI_NODATA: 208,
|
|
449
|
+
EAI_NONAME: 209,
|
|
450
|
+
EAI_OVERFLOW: 210,
|
|
451
|
+
EAI_PROTOCOL: 211,
|
|
452
|
+
EAI_SERVICE: 212,
|
|
453
|
+
EAI_SOCKTYPE: 213,
|
|
454
|
+
ECHARSET: 215,
|
|
455
|
+
ENONET: 216,
|
|
456
|
+
UNKNOWN: 217,
|
|
457
|
+
EOF: 218,
|
|
458
|
+
EUNATCH: 219,
|
|
459
|
+
ESHUTDOWN: 220
|
|
454
460
|
};
|
|
455
|
-
|
|
461
|
+
|
|
462
|
+
// When the error code is not known, we return 217 (UNKNOWN).
|
|
463
|
+
try {
|
|
464
|
+
const name = getSystemErrorName(errno);
|
|
465
|
+
return mapByName[name] ?? 217;
|
|
466
|
+
} catch {
|
|
467
|
+
return 217;
|
|
468
|
+
}
|
|
456
469
|
}
|
|
457
470
|
"""
|
|
458
471
|
|
|
@@ -469,7 +482,7 @@ namespace internal {
|
|
|
469
482
|
def checkResult(result: Int): Int / Exception[IOError] =
|
|
470
483
|
if (result < 0) {
|
|
471
484
|
val ioError = fromNumber(internal::errorNumber(result));
|
|
472
|
-
do raise
|
|
485
|
+
do raise(ioError, message(ioError))
|
|
473
486
|
} else {
|
|
474
487
|
result
|
|
475
488
|
}
|
|
@@ -158,7 +158,7 @@ def readQuotedString(): Unit / { Scan[Char], emit[Char], Exception[WrongFormat]
|
|
|
158
158
|
def decodeJson(): Unit / {Scan[Char], JsonBuilder, Exception[WrongFormat]} = {
|
|
159
159
|
with boundary
|
|
160
160
|
skipWhitespace()
|
|
161
|
-
if(do peek
|
|
161
|
+
if(do peek() is c) {
|
|
162
162
|
c match {
|
|
163
163
|
case 'n' => expectString("null"); do null()
|
|
164
164
|
case 't' => expectString("true"); do bool(true)
|
|
@@ -177,7 +177,7 @@ def decodeJsonObject(): Unit / {Scan[Char], JsonObjectBuilder, Exception[WrongFo
|
|
|
177
177
|
expectString("{")
|
|
178
178
|
with boundary
|
|
179
179
|
skipWhitespace()
|
|
180
|
-
while(do peek
|
|
180
|
+
while(do peek() is c and (c != '}')) {
|
|
181
181
|
if (not(first)) { expectString(",") }
|
|
182
182
|
val k = string::collect { readQuotedString() }
|
|
183
183
|
skipWhitespace()
|
|
@@ -188,20 +188,20 @@ def decodeJsonObject(): Unit / {Scan[Char], JsonObjectBuilder, Exception[WrongFo
|
|
|
188
188
|
skipWhitespace()
|
|
189
189
|
first = false
|
|
190
190
|
}
|
|
191
|
-
do skip
|
|
191
|
+
do skip()
|
|
192
192
|
}
|
|
193
193
|
def decodeJsonList(): Unit / {Scan[Char], JsonBuilder, Exception[WrongFormat]} = {
|
|
194
194
|
var first = true
|
|
195
195
|
expectString("[")
|
|
196
196
|
with boundary
|
|
197
197
|
skipWhitespace()
|
|
198
|
-
while(do peek
|
|
198
|
+
while(do peek() is c and (c != ']')) {
|
|
199
199
|
if (not(first)) { expectString(",") }
|
|
200
200
|
decodeJson()
|
|
201
201
|
skipWhitespace()
|
|
202
202
|
first = false
|
|
203
203
|
}
|
|
204
|
-
do skip
|
|
204
|
+
do skip()
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
// --------------------------------------------------------------------------------
|
|
@@ -73,7 +73,7 @@ def devurandom { randomnessReader: () => Unit / random }: Unit / Exception[IOErr
|
|
|
73
73
|
try {
|
|
74
74
|
with readFile("/dev/urandom")
|
|
75
75
|
try randomnessReader() with random {
|
|
76
|
-
resume(do read
|
|
76
|
+
resume(do read())
|
|
77
77
|
}
|
|
78
78
|
} with stop {
|
|
79
79
|
do raise(io::error::EOF(), "Unexpected EOF when reading /dev/urandom!")
|
|
@@ -12,8 +12,8 @@ interface Scan[A] {
|
|
|
12
12
|
|
|
13
13
|
/// Advance the Scanner to the next character, returning it.
|
|
14
14
|
def read[A](): A / { Scan[A], stop } = {
|
|
15
|
-
val t = do peek
|
|
16
|
-
do skip
|
|
15
|
+
val t = do peek()
|
|
16
|
+
do skip()
|
|
17
17
|
return t
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -26,9 +26,9 @@ def expect(message: String) { scanner: () => Unit / stop }: Unit / Exception[Wro
|
|
|
26
26
|
|
|
27
27
|
/// Check that the next token satisfies the predicate and skip and return it when it does.
|
|
28
28
|
def readIf[A] { predicate: A => Bool }: A / { Scan[A], stop } = {
|
|
29
|
-
val t = do peek
|
|
29
|
+
val t = do peek()
|
|
30
30
|
if (predicate(t)) {
|
|
31
|
-
do skip
|
|
31
|
+
do skip()
|
|
32
32
|
return t
|
|
33
33
|
} else {
|
|
34
34
|
do stop()
|
|
@@ -42,7 +42,7 @@ def skipIf[A] { predicate: A => Bool }: Unit / { Scan[A], stop } = {
|
|
|
42
42
|
|
|
43
43
|
def readSome[A, B] { convert: A => Option[B] }: B / { Scan[A], stop } =
|
|
44
44
|
if (convert(do peek()) is Some(t)) {
|
|
45
|
-
do skip
|
|
45
|
+
do skip()
|
|
46
46
|
return t
|
|
47
47
|
} else {
|
|
48
48
|
do stop()
|
|
@@ -53,7 +53,7 @@ def tryRead[A, B] { convert: A => B / Exception[WrongFormat] }: B / { Scan[A], s
|
|
|
53
53
|
with on[WrongFormat].default { do stop() }
|
|
54
54
|
|
|
55
55
|
val t = convert(do peek())
|
|
56
|
-
do skip
|
|
56
|
+
do skip()
|
|
57
57
|
return t
|
|
58
58
|
}
|
|
59
59
|
|
|
@@ -130,7 +130,7 @@ def scanner[A, R] { scanner: () => R / Scan[A] }: R / read[A] = {
|
|
|
130
130
|
def peek() = resume {
|
|
131
131
|
last match {
|
|
132
132
|
case None() =>
|
|
133
|
-
val t = do read
|
|
133
|
+
val t = do read()
|
|
134
134
|
last = Some(t)
|
|
135
135
|
return t
|
|
136
136
|
case Some(t) =>
|
|
@@ -140,7 +140,7 @@ def scanner[A, R] { scanner: () => R / Scan[A] }: R / read[A] = {
|
|
|
140
140
|
def skip() = resume {
|
|
141
141
|
last match {
|
|
142
142
|
case None() =>
|
|
143
|
-
val _ = do read
|
|
143
|
+
val _ = do read()
|
|
144
144
|
return ()
|
|
145
145
|
case Some(t) =>
|
|
146
146
|
last = None()
|
package/libraries/llvm/io.c
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
#include <uv.h>
|
|
5
5
|
#include <string.h> // to compare flag names
|
|
6
6
|
|
|
7
|
-
// Println and Readln
|
|
8
|
-
//
|
|
7
|
+
// Println and Readln and Random
|
|
8
|
+
// -----------------------------
|
|
9
9
|
|
|
10
10
|
void c_io_println(String text) {
|
|
11
11
|
for (uint64_t j = 0; j < text.tag; ++j) {
|
|
@@ -34,6 +34,10 @@ String c_io_readln() {
|
|
|
34
34
|
return result;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
double c_io_random(void) {
|
|
38
|
+
return (double)rand() / (double)RAND_MAX;
|
|
39
|
+
}
|
|
40
|
+
|
|
37
41
|
// Lib UV Bindings
|
|
38
42
|
// ---------------
|
|
39
43
|
// Ideas behind the LLVM / libuv implementation.
|
package/libraries/llvm/main.c
CHANGED
|
@@ -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/og-image.jpg"><meta name=twitter:image content="https://www.eclipse.org/images/og-image.jpg"><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/og-image.jpg"><meta name=twitter:image content="https://www.eclipse.org/images/og-image.jpg"><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=1763320624"><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">
|
|
@@ -64,4 +64,4 @@ open source software collaboration and innovation.</p></div><div class=mega-menu
|
|
|
64
64
|
<i class="fa-brands fa-linkedin-in fa-stack-1x fa-inverse" aria-hidden=true></i>
|
|
65
65
|
<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">
|
|
66
66
|
<button class="footer-end-newsletter-submit btn btn-link" id=mc-embedded-subscribe type=submit name=subscribe>
|
|
67
|
-
<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-sm-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=
|
|
67
|
+
<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-sm-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=1763320624"></script><script>(function(){})(jQuery,document)</script></div></body></html>
|