From: Brendan Hansen Date: Fri, 29 Mar 2024 03:23:44 +0000 (-0500) Subject: finished: release 0.1.10 page X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=af65c41865eb523f4c28eaebcc8cd22f3c09ece1;p=onyxlang.io.git finished: release 0.1.10 page --- diff --git a/www/news-articles/release-0.1.10.html b/www/news-articles/release-0.1.10.html index cd53c7b..66b8b1c 100644 --- a/www/news-articles/release-0.1.10.html +++ b/www/news-articles/release-0.1.10.html @@ -1,34 +1,219 @@

JavaScript Interop

+ Onyx now has a proper JavaScript interop layer, which makes using Onyx from JavaScript easier than ever. + This interop comes in two parts: the #js directive and the code.js package. +

+

+ The #js directive is used to include JS source code in the project. + When any #js directive is encountered in the code, an additional JS file will be generated by the compiler. +

+

+ #js has the following syntax. +

+ +
// 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"
+
+ +

+ 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. +

+

+ To actually interop with JS, there is now the core.js package. This package was inspired + by Go's syscall/js, which provides a thin abstraction + layer over JavaScript's common operations, like function calls, new and obj["foo"]. +

+

+ Here is a simple example/demo that creates a button on the page, and when it is clicked, alerts with a message.

+
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);
+}
+
+ +

+ 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 + Onyx class to load and link the WebAssembly binary, from + which you can call start to start the program. +

+ +
<script type="module">
+    import Onyx from "/out.wasm.js"
+    (await Onyx.load("/out.wasm")).start()
+</script>
+
+ +

+ Finally, compile the code with the -r js flag. +

+ +
onyx build -r js program.onyx
+
+ +

+ 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 WebGL. +

+ +

Deprecation of #inject

+ As I have written more Onyx code, I have realized I use #inject all the time. + It has become so ubiquitous in my code that I experimented with extending the parser so the #inject + directive would not be required, and I loved it. For this reason, #inject is being deprecated. +

+ +

+ Now you can simply add a new scoped binding like you would with any other binding. +

+ +
Dog :: struct {}
+
+// No #inject here!
+Dog.speak :: (d: &Dog) {
+    println("Bark!");
+}
+
+ +

+ Note that without the #inject keyword, there is no equivalent of the + block form. + Each scoped binding must be specified individually on a new line. I prefer this, + as it prevents what I consider unnecessary indentation. +

+ +

+ In a future release yet to be determined, the #inject directive will be + removed entirely, but for now all programs with it will still compile.

Array and Slice structures

+ 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 core.array and core.slice packages. +

+

+ This has finally been addressed with the addition of the Array and Slice builtin + structures. They serve as "namespaces" for methods in dynamics arrays and slices respectively. +

+

+ The core library now defines all dynamic array functionality as methods on Array and all + slice functionality as methods on Slice. All existing definitions from core.array + and core.slice still exist to maintain backwards compatibility, but the new locations of + these definitions should be preferred. +

+ +
// 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);
+}
+
+ +

+ 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. x->proc(y), or as a standard procedure prefix with the type + name, i.e. X.proc(&x, y). When the procedure lives in a package, they are forced to use the standard + procedure syntax.

Minor syntax additions

+ +

Auto-disposing locals

+

+ A very common pattern in Onyx is to create/allocate a resource, then defer 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 auto-disposing locals (I'm still working on the name...). +

+ To mark a local variable as auto-disposing, simply place the use keyword in front of its declaration. +

+
main :: () {
+    use arr := make([..] i32);
+}
+
+

+ This code will automatically insert a deferred call to the builtin overloaded procedure __dispose_used_local, which + can be overloaded to define how to dispose of the resource. + It has the delete procedure in the list of overloads, so anything you can call delete on, + you can use. This is the equivalent code without use. +

+
main :: () {
+    arr := make([..] i32);
+    defer __dispose_used_local(&arr);
+}
+
+

+ As stated before, this feature is experimental and probably not perfect yet, but after using the + using keyword in C#, I wanted to have something similar in Onyx.

Inclusive Range (..=)

+ As a small convenience, there is now an inclusive range operator, ..=. + This operator is equivalent to x .. (y + 1).

- -

range64

+ While a small addition, it cleans up a lot of ugly + 1s around many codebases.

Revamped CLI

+ The command-line interface got a major face-lift in this update. + It features new shorthand for common commands like build and run. + It also includes colors on Linux and MacOS. + This might not seem worth mentioning but these little improvements add to the overall developer + experience and make Onyx feel more polished and production-ready.

-

+

Updating

+

+ 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. +

+
$ sh <(curl https://get.onyxlang.io -sSfL)
 
- +

+ In the future, you will be able to use the onyx self-upgrade command! +

Full Changelog

Additions

@@ -71,7 +256,9 @@

Removals

-

Nothing to mention here!

+
    +
  • os.with_file
  • +

Changes

    diff --git a/www/static/css/new_style.css b/www/static/css/new_style.css index 36c9f1c..755c5a3 100644 --- a/www/static/css/new_style.css +++ b/www/static/css/new_style.css @@ -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; }