@effekt-lang/effekt 0.25.0 → 0.27.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 CHANGED
Binary file
@@ -8,14 +8,54 @@ import option
8
8
  /// A mutable 0-indexed fixed-sized array.
9
9
  extern type Array[T]
10
10
 
11
+ /** We represent arrays like positive types.
12
+ * The tag is 0 and the obj points to memory with the following layout:
13
+ *
14
+ * +--[ Header ]--+------+------------+
15
+ * | Rc | Eraser | Size | Fields ... |
16
+ * +--------------+------+------------+
17
+ */
18
+
19
+ extern llvm """
20
+ declare noalias ptr @calloc(i64, i64)
21
+
22
+ define void @array_erase_fields(ptr %array_pointer) {
23
+ entry:
24
+ %data_pointer = getelementptr inbounds i64, ptr %array_pointer, i64 1
25
+ %size = load i64, ptr %array_pointer, align 8
26
+ %size_eq_0 = icmp eq i64 %size, 0
27
+ br i1 %size_eq_0, label %exit, label %loop
28
+ loop:
29
+ %loop_phi = phi i64 [ %inc, %loop ], [ 0, %entry ]
30
+
31
+ %element_pointer = getelementptr inbounds %Pos, ptr %data_pointer, i64 %loop_phi
32
+ %element = load %Pos, ptr %element_pointer
33
+
34
+ call void @erasePositive(%Pos %element)
35
+ %inc = add nuw i64 %loop_phi, 1
36
+ %cmp = icmp ult i64 %inc, %size
37
+ br i1 %cmp, label %loop, label %exit
38
+ exit:
39
+ ret void
40
+ }
41
+ """
42
+
11
43
  /// Allocates a new array of size `size`, keeping its values _undefined_.
12
44
  /// Prefer using `array` constructor instead to ensure that values are defined.
13
45
  extern global def allocate[T](size: Int): Array[T] =
14
46
  js "(new Array(${size}))"
15
47
  chez "(make-vector ${size})" // creates an array filled with 0s on CS
16
48
  llvm """
17
- %z = call %Pos @c_array_new(%Int ${size})
18
- ret %Pos %z
49
+ %size0 = shl i64 ${size}, 4
50
+ %size1 = add i64 %size0, 24
51
+ %calloc = tail call noalias ptr @calloc(i64 %size1, i64 1)
52
+ %eraser_pointer = getelementptr ptr, ptr %calloc, i64 1
53
+ %size_pointer = getelementptr ptr, ptr %calloc, i64 2
54
+ store i64 0, ptr %calloc
55
+ store ptr @array_erase_fields, ptr %eraser_pointer
56
+ store i64 ${size}, ptr %size_pointer
57
+ %ret_pos = insertvalue %Pos { i64 0, ptr poison }, ptr %calloc, 1
58
+ ret %Pos %ret_pos
19
59
  """
20
60
  vm "array::allocate(Int)"
21
61
 
@@ -49,8 +89,12 @@ extern pure def size[T](arr: Array[T]): Int =
49
89
  js "${arr}.length"
50
90
  chez "(vector-length ${arr})"
51
91
  llvm """
52
- %z = call %Int @c_array_size(%Pos ${arr})
53
- ret %Int %z
92
+ %pos_data = extractvalue %Pos ${arr}, 1
93
+ %size_pointer = getelementptr inbounds i64, ptr %pos_data, i64 2
94
+ %size = load i64, ptr %size_pointer
95
+
96
+ tail call void @erasePositive(%Pos ${arr})
97
+ ret i64 %size
54
98
  """
55
99
  vm "array::size[T](Array[T])"
56
100
 
@@ -62,8 +106,15 @@ extern global def unsafeGet[T](arr: Array[T], index: Int): T =
62
106
  js "${arr}[${index}]"
63
107
  chez "(vector-ref ${arr} ${index})"
64
108
  llvm """
65
- %z = call %Pos @c_array_get(%Pos ${arr}, %Int ${index})
66
- ret %Pos %z
109
+ %pos_data = extractvalue %Pos ${arr}, 1
110
+
111
+ %data_pointer = getelementptr inbounds ptr, ptr %pos_data, i64 3
112
+ %element_pointer = getelementptr inbounds %Pos, ptr %data_pointer, i64 ${index}
113
+ %element = load %Pos, ptr %element_pointer
114
+
115
+ tail call void @sharePositive(%Pos %element)
116
+ tail call void @erasePositive(%Pos ${arr})
117
+ ret %Pos %element
67
118
  """
68
119
  vm "array::unsafeGet[T](Array[T], Int)"
69
120
 
@@ -82,8 +133,15 @@ extern global def unsafeSet[T](arr: Array[T], index: Int, value: T): Unit =
82
133
  js "array$set(${arr}, ${index}, ${value})"
83
134
  chez "(begin (vector-set! ${arr} ${index} ${value}) #f)"
84
135
  llvm """
85
- %z = call %Pos @c_array_set(%Pos ${arr}, %Int ${index}, %Pos ${value})
86
- ret %Pos %z
136
+ %array_data = extractvalue %Pos ${arr}, 1
137
+
138
+ %data_pointer = getelementptr inbounds i64, ptr %array_data, i64 3
139
+ %element_pointer = getelementptr inbounds %Pos, ptr %data_pointer, i64 ${index}
140
+ %element = load %Pos, ptr %element_pointer, align 8
141
+ tail call void @erasePositive(%Pos %element)
142
+ store %Pos ${value}, ptr %element_pointer, align 8
143
+ tail call void @erasePositive(%Pos ${arr})
144
+ ret %Pos zeroinitializer
87
145
  """
88
146
  vm "array::unsafeSet[T](Array[T], Int, T)"
89
147
 
@@ -2,6 +2,17 @@ module bytearray
2
2
 
3
3
  /**
4
4
  * A memory managed, mutable, fixed-length array of bytes.
5
+ *
6
+ * We represent bytearrays like positive types.
7
+ *
8
+ * - The field `tag` contains the size
9
+ * - The field `obj` points to memory with the following layout:
10
+ *
11
+ * +--[ Header ]--+--------------+
12
+ * | Rc | Eraser | Contents ... |
13
+ * +--------------+--------------+
14
+ *
15
+ * The eraser does nothing.
5
16
  */
6
17
  extern type ByteArray
7
18
  // = llvm "%Pos"
@@ -12,32 +23,47 @@ extern type ByteArray
12
23
  extern global def allocate(size: Int): ByteArray =
13
24
  js "(new Uint8Array(${size}))"
14
25
  llvm """
15
- %arr = call %Pos @c_bytearray_new(%Int ${size})
16
- ret %Pos %arr
26
+ %object_size = add i64 ${size}, 16
27
+ %object_alloc = tail call noalias ptr @malloc(i64 noundef %object_size)
28
+ store i64 0, ptr %object_alloc, align 8
29
+ %object_data_ptr = getelementptr inbounds i8, ptr %object_alloc, i64 8
30
+ store ptr @bytearray_erase_noop, ptr %object_data_ptr, align 8
31
+ %ret_object1 = insertvalue %Pos poison, i64 ${size}, 0
32
+ %ret_object2 = insertvalue %Pos %ret_object1, ptr %object_alloc, 1
33
+ ret %Pos %ret_object2
17
34
  """
18
35
  chez "(make-bytevector ${size})"
19
36
 
20
37
  extern pure def size(arr: ByteArray): Int =
21
38
  js "${arr}.length"
22
39
  llvm """
23
- %size = call %Int @c_bytearray_size(%Pos ${arr})
24
- ret %Int %size
40
+ %size = extractvalue %Pos ${arr}, 0
41
+ tail call void @erasePositive(%Pos ${arr})
42
+ ret i64 %size
25
43
  """
26
44
  chez "(bytevector-length ${arr})"
27
45
 
28
46
  extern global def unsafeGet(arr: ByteArray, index: Int): Byte =
29
47
  js "(${arr})[${index}]"
30
48
  llvm """
31
- %byte = call %Byte @c_bytearray_get(%Pos ${arr}, %Int ${index})
32
- ret %Byte %byte
49
+ %arr_ptr = extractvalue %Pos ${arr}, 1
50
+ %arr_data_ptr = getelementptr inbounds i8, ptr %arr_ptr, i64 16
51
+ %element_ptr = getelementptr inbounds i8, ptr %arr_data_ptr, i64 ${index}
52
+ %element = load i8, ptr %element_ptr, align 1
53
+ tail call void @erasePositive(%Pos ${arr})
54
+ ret i8 %element
33
55
  """
34
56
  chez "(bytevector-u8-ref ${arr} ${index})"
35
57
 
36
58
  extern global def unsafeSet(arr: ByteArray, index: Int, value: Byte): Unit =
37
59
  js "bytearray$set(${arr}, ${index}, ${value})"
38
60
  llvm """
39
- %z = call %Pos @c_bytearray_set(%Pos ${arr}, %Int ${index}, %Byte ${value})
40
- ret %Pos %z
61
+ %arr_ptr = extractvalue %Pos ${arr}, 1
62
+ %arr_data_ptr = getelementptr inbounds i8, ptr %arr_ptr, i64 16
63
+ %element_ptr = getelementptr inbounds i8, ptr %arr_data_ptr, i64 ${index}
64
+ store i8 ${value}, ptr %element_ptr, align 1
65
+ tail call void @erasePositive(%Pos ${arr})
66
+ ret %Pos zeroinitializer
41
67
  """
42
68
  chez "(bytevector-u8-set! ${arr} ${index} ${value})"
43
69
 
@@ -121,6 +147,12 @@ extern js """
121
147
  }
122
148
  """
123
149
 
150
+ extern llvm """
151
+ define void @bytearray_erase_noop(ptr readnone %0) {
152
+ ret void
153
+ }
154
+ """
155
+
124
156
  extern chez """
125
157
  (define (bytearray$compare b1 b2)
126
158
  (let ([len1 (bytevector-length b1)]
@@ -9,17 +9,44 @@ extern js """
9
9
  }
10
10
  """
11
11
 
12
+ extern llvm """
13
+ define void @c_ref_erase_field(ptr %0) {
14
+ %field = load %Pos, ptr %0, align 8
15
+ tail call void @erasePositive(%Pos %field)
16
+ ret void
17
+ }
18
+ """
19
+
12
20
  /// Global, mutable references
13
21
  extern type Ref[T]
14
22
 
23
+ /** We represent references like positive types in LLVM
24
+ * The tag is 0 and the obj points to memory with the following layout:
25
+ *
26
+ * +--[ Header ]--------------+------------+
27
+ * | ReferenceCount | Eraser | Field |
28
+ * +--------------------------+------------+
29
+ */
30
+
15
31
  /// Allocates a new reference, keeping its value _undefined_.
16
32
  /// Prefer using `ref` constructor instead to ensure that the value is defined.
17
33
  extern global def allocate[T](): Ref[T] =
18
34
  js "{ value: undefined }"
19
35
  chez "(box #f)"
20
36
  llvm """
21
- %z = call %Pos @c_ref_fresh(%Pos zeroinitializer)
22
- ret %Pos %z
37
+ ; sizeof Header + sizeof Pos = 32
38
+ %ref = tail call noalias ptr @malloc(i64 noundef 32)
39
+ %refEraser = getelementptr ptr, ptr %ref, i64 1
40
+ %fieldTag = getelementptr ptr, ptr %ref, i64 2
41
+ %fieldData_pointer = getelementptr ptr, ptr %ref, i64 3
42
+
43
+ store i64 0, ptr %ref, align 8
44
+ store ptr @c_ref_erase_field, ptr %refEraser, align 8
45
+ store i64 0, ptr %fieldTag, align 8
46
+ store ptr null, ptr %fieldData_pointer, align 8
47
+
48
+ %refWrap = insertvalue %Pos { i64 0, ptr poison }, ptr %ref, 1
49
+ ret %Pos %refWrap
23
50
  """
24
51
 
25
52
  /// Creates a new reference with the initial value `init`.
@@ -27,8 +54,20 @@ extern global def ref[T](init: T): Ref[T] =
27
54
  js "{ value: ${init} }"
28
55
  chez "(box ${init})"
29
56
  llvm """
30
- %z = call %Pos @c_ref_fresh(%Pos ${init})
31
- ret %Pos %z
57
+ %initTag = extractvalue %Pos ${init}, 0
58
+ %initObject_pointer = extractvalue %Pos ${init}, 1
59
+ ; sizeof Header + sizeof Pos = 32
60
+ %ref = tail call noalias ptr @malloc(i64 noundef 32)
61
+ %refEraser = getelementptr ptr, ptr %ref, i64 1
62
+ %refField = getelementptr ptr, ptr %ref, i64 2
63
+
64
+ store i64 0, ptr %ref, align 8
65
+ store ptr @c_ref_erase_field, ptr %refEraser, align 8
66
+ store %Pos ${init}, ptr %refField, align 8
67
+
68
+ %refWrap = insertvalue %Pos { i64 0, ptr poison }, ptr %ref, 1
69
+
70
+ ret %Pos %refWrap
32
71
  """
33
72
  vm "ref::ref[T](T)"
34
73
 
@@ -36,9 +75,15 @@ extern global def ref[T](init: T): Ref[T] =
36
75
  extern global def get[T](ref: Ref[T]): T =
37
76
  js "${ref}.value"
38
77
  chez "(unbox ${ref})"
39
- llvm """
40
- %z = call %Pos @c_ref_get(%Pos ${ref})
41
- ret %Pos %z
78
+ llvm """
79
+ %ref_pointer = extractvalue %Pos ${ref}, 1
80
+ %refField_pointer = getelementptr inbounds ptr, ptr %ref_pointer, i64 2
81
+ %refField = load %Pos, ptr %refField_pointer, align 8
82
+
83
+ tail call void @sharePositive(%Pos %refField)
84
+ tail call void @erasePositive(%Pos ${ref})
85
+
86
+ ret %Pos %refField
42
87
  """
43
88
  vm "ref::get[T](Ref[T])"
44
89
 
@@ -47,7 +92,15 @@ extern global def set[T](ref: Ref[T], value: T): Unit =
47
92
  js "set$impl(${ref}, ${value})"
48
93
  chez "(set-box! ${ref} ${value})"
49
94
  llvm """
50
- %z = call %Pos @c_ref_set(%Pos ${ref}, %Pos ${value})
51
- ret %Pos %z
95
+ %refField_pointer = extractvalue %Pos ${ref}, 1
96
+
97
+ %field_pointer = getelementptr ptr, ptr %refField_pointer, i64 2
98
+ %field = load %Pos, ptr %field_pointer, align 8
99
+
100
+ tail call void @erasePositive(%Pos %field)
101
+ store %Pos ${value}, ptr %field_pointer
102
+ tail call void @erasePositive(%Pos ${ref})
103
+
104
+ ret %Pos zeroinitializer
52
105
  """
53
106
  vm "ref::set[T](Ref[T], T)"
@@ -35,10 +35,11 @@ def stringBuffer[A] { prog: => A / StringBuffer }: A = {
35
35
  resume(())
36
36
  }
37
37
  def flush() = {
38
- // resize buffer to strip trailing zeros that otherwise would be converted into 0x00 characters
38
+ // resize (& copy) buffer to strip trailing zeros that otherwise would be converted into 0x00 characters
39
39
  val str = bytearray::resize(buffer, pos).toString()
40
- // after flushing, the stringbuffer should be empty again
41
- buffer = bytearray::allocate(initialCapacity)
40
+ // NOTE: Keep the `buffer` as-is (no wipe, no realloc),
41
+ // just reset the `pos` in case we want to use it again.
42
+ pos = 0
42
43
  resume(str)
43
44
  }
44
45
  }
@@ -55,11 +56,22 @@ def s { prog: () => Unit / { literal, splice[String] } }: String =
55
56
  namespace examples {
56
57
  def main() = {
57
58
  with stringBuffer
59
+
58
60
  do write("hello")
59
61
  do write(", world")
60
62
  // prints `hello, world`
61
63
  println(do flush())
64
+
62
65
  // prints the empty string
63
66
  println(do flush())
67
+
68
+ do write("Ef")
69
+ do write("fe")
70
+ do write("kt")
71
+ do write(" = ")
72
+ do write("")
73
+ do write("Effekt")
74
+ // prints `Effekt = Effekt`
75
+ println(do flush())
64
76
  }
65
77
  }
@@ -13,8 +13,6 @@
13
13
  #include "bytearray.c"
14
14
  #include "io.c"
15
15
  #include "panic.c"
16
- #include "ref.c"
17
- #include "array.c"
18
16
 
19
17
 
20
18
  extern void effektMain();
@@ -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=1743598368"><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
+ <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=1745172931"><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&amp;id=e7538485cd&amp;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 &copy; 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=1743598368"></script><script>(function(){})(jQuery,document)</script></div></body></html>
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 &copy; 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=1745172931"></script><script>(function(){})(jQuery,document)</script></div></body></html>