finished: release 0.1.10 page
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 29 Mar 2024 03:23:44 +0000 (22:23 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 29 Mar 2024 03:23:44 +0000 (22:23 -0500)
www/news-articles/release-0.1.10.html
www/static/css/new_style.css

index cd53c7b42d9ea481d5a55d6acbdd84fced7b5730..66b8b1cd880257420edc00da1533ea1890cfba37 100644 (file)
 <h2>JavaScript Interop</h2>
 <p>
+    Onyx now has a proper JavaScript interop layer, which makes using Onyx from JavaScript easier than ever.
+    This interop comes in two parts: the <code>#js</code> directive and the <code>code.js</code> package.
+</p>
+<p>
+    The <code>#js</code> directive is used to include JS source code in the project.
+    When any <code>#js</code> directive is encountered in the code, an additional JS file will be generated by the compiler.
+</p>
+<p>
+    <code>#js</code> has the following syntax.
+</p>
+
+<pre class="hljs"><code class="language-onyx">// Include JS from string literal
+#js """
+    // Raw JS source code here
+"""
+
+// Inlcude JS from file
+#js #file "./source.js"
+
+// Specify order of JS partial with an int literal
+// Lower numbers are inserted first
+#js 100 #file "./source.js"
+</code></pre>
+
+<p>
+    This by itself does not help you interop with JavaScript, but it is required to have the compiler
+    also generate the additional source code to make your project work. In fact, you may never have to
+    use it directly, as it is more intended for library authors.
+</p>
+<p>
+    To actually interop with JS, there is now the <a href="https://docs.onyxlang.io/packages/core.js"><code>core.js</code> package</a>. This package was inspired
+    by Go's <a href="https://pkg.go.dev/syscall/js"><code>syscall/js</code></a>, which provides a thin abstraction
+    layer over JavaScript's common operations, like function calls, <code>new</code> and <code>obj["foo"]</code>.
+</p>
+<p>
+    Here is a simple example/demo that creates a button on the page, and when it is clicked, alerts with a message.
 </p>
 
+<pre class="hljs"><code class="language-onyx">use core.js
+
+main :: () {
+    document := js.Global->get("document");
+
+    button := document->call("createElement", "button");
+    button->set("innerHTML", "Click me!");
+    button->call("addEventListener", js.func((this, args) => {
+        js.Global->call("alert", "Hello from Onyx!");
+
+        return js.Undefined;
+    }));
+
+    document->get("body")->call("appendChild", button);
+}
+</code></pre>
+
+<p>
+    To use this in on your page, you can use the following JavaScript.
+    It will load the JavaScript file generated by the compiler, and use the
+    <code>Onyx</code> class to load and link the WebAssembly binary, from
+    which you can call <code>start</code> to start the program.
+</p>
+
+<pre class="hljs"><code class="language-html">&lt;script type="module"&gt;
+    import Onyx from "/out.wasm.js"
+    (await Onyx.load("/out.wasm")).start()
+&lt;/script&gt;
+</code></pre>
+
+<p>
+    Finally, compile the code with the <code>-r js</code> flag.
+</p>
+
+<pre class="hljs"><code class="language-sh">onyx build -r js program.onyx
+</code></pre>
+
+<p>
+    While this is a very low-level interface to JavaScript, it does enable Onyx
+    to be used in a whole new class of applications on the web. More auxillary packages
+    can be developed to provide specialized APIs for comming things such as the DOM, WebSockets,
+    or <a href="https://github.com/onyx-lang/pkg-webgl2">WebGL</a>.
+</p>
+
+
 <h2>Deprecation of <code>#inject</code></h2>
 <p>
+    As I have written more Onyx code, I have realized I use <code>#inject</code> <em>all the time</em>.
+    It has become so ubiquitous in my code that I experimented with extending the parser so the <code>#inject</code>
+    directive would not be required, and I loved it. For this reason, <code>#inject</code> is being deprecated.
+</p>
+
+<p>
+    Now you can simply add a new scoped binding like you would with any other binding.
+</p>
+
+<pre class="hljs"><code class="language-onyx">Dog :: struct {}
+
+// No #inject here!
+Dog.speak :: (d: &Dog) {
+    println("Bark!");
+}
+</code></pre>
+
+<p>
+    Note that without the <code>#inject</code> keyword, there is no equivalent of the
+    <a href="https://docs.onyxlang.io/book/directives/inject.html">block form</a>.
+    Each scoped binding must be specified individually on a new line. I prefer this,
+    as it prevents what I consider unnecessary indentation.
+</p>
+
+<p>
+    In a future release yet to be determined, the <code>#inject</code> directive will be
+    removed entirely, but for now all programs with it will still compile.
 </p>
 
 <h2><code>Array</code> and <code>Slice</code> structures</h2>
 <p>
+    There has been a long running inconsistency in Onyx where dynamic arrays and slices were
+    not like other types, in that they could not have methods and required you to use functions
+    defined in the standard library from the <code>core.array</code> and <code>core.slice</code> packages.
+</p>
+<p>
+    This has finally been addressed with the addition of the <code>Array</code> and <code>Slice</code> builtin
+    structures. They serve as "namespaces" for methods in dynamics arrays and slices respectively.
+</p>
+<p>
+    The core library now defines all dynamic array functionality as methods on <code>Array</code> and all
+    slice functionality as methods on <code>Slice</code>. All existing definitions from <code>core.array</code>
+    and <code>core.slice</code> still exist to maintain backwards compatibility, but the new locations of
+    these definitions should be preferred.
+</p>
+
+<pre class="hljs"><code class="language-onyx">// No need to use anything :)
+
+main :: () {
+    arr := make([..] i32);
+
+    for i in 0 .. 10 {
+        // Use as a method.
+        arr->push(i);
+
+        // Use a static function on Array.
+        Array.push(&arr, i);
+    }
+
+    logf(.Info, "Array: {}", arr);
+}
+</code></pre>
+
+<p>
+    These changes represent a larger move towards standardizing the pattern that associated procedures
+    for a type are defined as bindings within the type's scope. That way, the consumer of library can either choose
+    to use the procedure as a "method", i.e. <code>x->proc(y)</code>, or as a standard procedure prefix with the type
+    name, i.e. <code>X.proc(&x, y)</code>. When the procedure lives in a package, they are forced to use the standard
+    procedure syntax.
 </p>
 
 <h2>Minor syntax additions</h2>
+
+<h3>Auto-disposing locals</h3>
+<p>
+    A very common pattern in Onyx is to create/allocate a resource, then <code>defer</code> the release/free of the resource
+    on the next line. As an experiment, there is now a way to automate the freeing of a resource, called <em>auto-disposing locals</em> (<em>I'm still working on the name...</em>).
+</p>
 <p>
+    To mark a local variable as auto-disposing, simply place the <code>use</code> keyword in front of its declaration.
+</p>
+<pre class="hljs"><code class="language-onyx">main :: () {
+    use arr := make([..] i32);
+}
+</code></pre>
+<p>
+    This code will automatically insert a deferred call to the builtin overloaded procedure <code>__dispose_used_local</code>, which
+    can be overloaded to define how to dispose of the resource.
+    It has the <code>delete</code> procedure in the list of overloads, so anything you can call <code>delete</code> on,
+    you can <code>use</code>. This is the equivalent code without <code>use</code>.
+</p>
+<pre class="hljs"><code class="language-onyx">main :: () {
+    arr := make([..] i32);
+    defer __dispose_used_local(&arr);
+}
+</code></pre>
+<p>
+    As stated before, this feature is experimental and probably not perfect yet, but after using the 
+    <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/using"><code>using</code> keyword in C#</a>, I wanted to have something similar in Onyx.
 </p>
 
 <h3>Inclusive Range (<code>..=</code>)</h3>
 <p>
+    As a small convenience, there is now an inclusive range operator, <code>..=</code>.
+    This operator is <a href="https://github.com/onyx-lang/onyx/blob/297cadce463fabf7ac68fa602b89d879e2892422/compiler/src/checker.c#L1965">equivalent</a> to <code>x .. (y + 1)</code>.
 </p>
-
-<h3><code>range64</code></h3>
 <p>
+    While a small addition, it cleans up a lot of ugly <code>+ 1</code>s around many codebases.
 </p>
 
 <h2>Revamped CLI</h2>
 <p>
+    The command-line interface got a major face-lift in this update.
+    It features new shorthand for common commands like <code>build</code> and <code>run</code>.
+    It also includes <em>colors</em> on Linux and MacOS.
+    This might not seem worth mentioning but these little improvements add to the overall developer
+    experience and make Onyx <em>feel</em> more polished and production-ready.
 </p>
 
-<pre class="hljs"><code class="language-onyx">
+<h2>Updating</h2>
+<p>
+    To update to the newest version of Onyx simply use the same install script found on the homepage.
+    It will automatically detect your previous install and will override it with the new version.
+</p>
+<pre class="hljs"><code class="language-sh">$ sh <(curl https://get.onyxlang.io -sSfL)
 </code></pre>
-
+<p>
+    <em>In the future, you will be able to use the <code>onyx self-upgrade</code> command!</em>
+</p>
 
 <h2>Full Changelog</h2>
 <h3>Additions</h3>
 </ul>
 
 <h3>Removals</h3>
-<p><em>Nothing to mention here!</em></p>
+<ul>
+    <li><code>os.with_file</code></li>
+</ul>
 
 <h3>Changes</h3>
 <ul>
index 36c9f1cf4e0d449d55836b15f9236144771e4f9e..755c5a3b19b65b9f4fb31376fc2649e17495ae15 100644 (file)
@@ -60,7 +60,7 @@ a.link-button {
 
 a.link-button:hover {
     /* top: -6px; */
-    box-shadow: 0 6px 15px 8px rgba(200, 200, 230, 0.2);
+    /* box-shadow: 0 6px 15px 8px rgba(200, 200, 230, 0.2); */
     cursor: pointer;
 }
 
@@ -75,7 +75,7 @@ a.cta-button {
     font-size: 16pt;
     background-color: var(--secondary);
     color: var(--text);
-    box-shadow: 0px 3px 12px 2px rgba(200, 200, 230, 0.2);
+    /* box-shadow: 0px 3px 12px 2px rgba(200, 200, 230, 0.2); */
     position: relative;
     top: 0;
     transition: all 0.2s;
@@ -83,7 +83,7 @@ a.cta-button {
 
 a.cta-button:hover {
     /* top: -6px; */
-    box-shadow: 0 6px 15px 8px rgba(200, 200, 230, 0.2);
+    /* box-shadow: 0 6px 15px 8px rgba(200, 200, 230, 0.2); */
     cursor: pointer;
 }
 
@@ -102,6 +102,7 @@ a.cta-button:hover {
 
 .container > p {
     margin-top: 20px;
+    line-height: 1.5rem;
 }
 
 .container ul, .container ol {
@@ -119,7 +120,7 @@ a.cta-button:hover {
 
 .container.card > * {
     background: linear-gradient(135deg, var(--background), var(--accent-background));
-    box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2);
+    /* box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2); */
     border-radius: 8px;
     border: 1px solid var(--primary);
     padding: 8px;
@@ -284,7 +285,7 @@ navbar a span.active {
 navbar a span:hover {
     cursor: pointer;
     background-color: var(--header-accent);
-    box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2);
+    /* box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2); */
 }
 
 navbar a:visited {
@@ -372,7 +373,7 @@ main pre {
     background: linear-gradient(135deg, var(--background), var(--accent-background));
     border: 1px solid var(--primary);
     border-radius: 6px;
-    box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2);
+    /* box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2); */
     padding: 8px;
     display: block;
     overflow-y: auto;
@@ -500,7 +501,7 @@ table {
     border: 1px solid var(--accent);
     width: 100%;
     background: linear-gradient(135deg, #000, var(--accent-background));
-    box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2);
+    /* box-shadow: 0px 3px 16px 8px rgba(150, 150, 230, 0.2); */
     margin-top: 24px !important;
 }