Fix template tags in posts
This commit is contained in:
@@ -51,7 +51,7 @@ Instead of fighting with a borrow checker, simply get an address of a variable:
|
||||
|
||||
Classes may have a finalizer defined and thus have **automatic resource control**.
|
||||
|
||||
Onyx implements real **traits** as [composable units of behaviour](https://en.wikipedia.org/wiki/Trait_(computer_programming)) thanks to powerful function management tools like aliasing, implementation transferring, un-declaring and renaming.
|
||||
Onyx implements real **traits** as [composable units of behaviour](<https://en.wikipedia.org/wiki/Trait_(computer_programming)>) thanks to powerful function management tools like aliasing, implementation transferring, un-declaring and renaming.
|
||||
|
||||
Classes and traits together impose **object-oriented** capabilities of the language.
|
||||
|
||||
@@ -348,7 +348,7 @@ export int main () {
|
||||
|
||||
server.listen("localost", 3000)
|
||||
catch |e|
|
||||
Std.puts("Caught \@{{ e }}\n")
|
||||
Std.puts("Caught \@{{ e }}\n")
|
||||
|
||||
while final loc = backtrace.pop?()
|
||||
Std.cout << "At " <<
|
||||
@@ -367,7 +367,7 @@ export int main () {
|
||||
|
||||
Thanks to powerful abstractions and type inference, you won't need to manually use `socket` each time you want to spin up a web server on Linux!
|
||||
|
||||
Oh, by the way, did you notice the `\@{{ e }}` thing?
|
||||
Oh, by the way, did you notice the `\@{{ e }}` thing?
|
||||
It was me, <s>Dio</s> macro!
|
||||
|
||||
### Macros
|
||||
@@ -382,9 +382,9 @@ Let's examine a straightforward macro example.
|
||||
import "stdio.h"
|
||||
|
||||
export void main() {
|
||||
{% for i = 0, 2 do %}
|
||||
unsafe! $puts("i = {{ i }}")
|
||||
{% end %}
|
||||
{% for i = 0, 2 do %}
|
||||
unsafe! $puts("i = {{ i }}")
|
||||
{% end %}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -411,11 +411,11 @@ Well, yes, you have to trust the code you run.
|
||||
You do trust C libraries you link to your programs, right?
|
||||
|
||||
However, you won't trust an NPM package, because an NPM package author does not care about their reputation, and because NPM does not have auditing features.
|
||||
This is the Open-Source sustainability problem addresses in the [previous article]((/posts/2020-08-16-system-programming-in-2k20)) and potentially solved by the aforementioned [Onyx Software Foundation](#the-onyx-software-foundation).
|
||||
This is the Open-Source sustainability problem addresses in the [previous article](<(/posts/2020-08-16-system-programming-in-2k20)>) and potentially solved by the aforementioned [Onyx Software Foundation](#the-onyx-software-foundation).
|
||||
|
||||
As a result, given that you do have access to code you require, authors of packages your program depends on are appropriately rewarded for their work, and the Foundation sponsors audition of selected packages, you should be safe.
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
Back to the possibilities.
|
||||
Macro use-cases include:
|
||||
@@ -430,7 +430,7 @@ For example, you can compute a Fibonacci number sequence in a macro, and output
|
||||
Let's examine the following small snippet:
|
||||
|
||||
```text
|
||||
{%
|
||||
{%
|
||||
-- Local context is preserved
|
||||
-- during this file compilation
|
||||
local function fib(n)
|
||||
@@ -449,7 +449,7 @@ Let's examine the following small snippet:
|
||||
# This is a macro "function", which
|
||||
# may be used directly from Onyx code.
|
||||
macro @fib(n)
|
||||
{{ fib(n) }}
|
||||
{{ fib(n) }}
|
||||
end
|
||||
|
||||
import "stdio.h"
|
||||
@@ -463,7 +463,7 @@ In this example, `@fib(10)` would evaluate during compilation and emit a number
|
||||
|
||||
Of course, this would increase compilation times, and it is your responsibility to find the right balance based on your needs.
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
::: hero
|
||||
|
||||
@@ -475,7 +475,7 @@ This is how it might look like:
|
||||
|
||||
```text
|
||||
macro @gen_class(name)
|
||||
{%
|
||||
{%
|
||||
-- Accessing system configuration
|
||||
local db_path = os.getenv("DB_PATH")
|
||||
|
||||
@@ -529,7 +529,7 @@ class User
|
||||
end
|
||||
```
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
::: hero
|
||||
|
||||
@@ -541,14 +541,14 @@ Nuff said.
|
||||
For example:
|
||||
|
||||
```text
|
||||
{% if nx.target.isa.id == "amd64" then %}
|
||||
{% if nx.target.isa.id == "amd64" then %}
|
||||
$printf("This is amd64")
|
||||
{% else %}
|
||||
{% else %}
|
||||
$printf("This is not amd64")
|
||||
{% end %}
|
||||
{% end %}
|
||||
```
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
::: hero
|
||||
|
||||
@@ -568,16 +568,16 @@ reopen Int<Base: 2, Signed: S, Size: Z> forall S, Z
|
||||
final result = unsafe! uninitialized self
|
||||
final overflowed? = unsafe! uninitialized Bit
|
||||
|
||||
\{%
|
||||
\{%
|
||||
local s = nx.scope.S.val and "s" or "u"
|
||||
local t = "i" .. nx.scope.Z.val
|
||||
%}
|
||||
|
||||
unsafe! asm
|
||||
template llvm
|
||||
%res = call {\{{ t }}, i1} @llvm.\{{ s }}add.\
|
||||
with.overflow.\{{ t }}(\{{ t }} $0, \{{ t }} $1)
|
||||
$2 = extractvalue {\{{ t }}, i1} %res, 1
|
||||
%res = call {\{{ t }}, i1} @llvm.\{{ s }}add.\
|
||||
with.overflow.\{{ t }}(\{{ t }} $0, \{{ t }} $1)
|
||||
$2 = extractvalue {\{{ t }}, i1} %res, 1
|
||||
in r(this), r(another)
|
||||
out =r(overflowed?)
|
||||
end
|
||||
@@ -587,7 +587,7 @@ reopen Int<Base: 2, Signed: S, Size: Z> forall S, Z
|
||||
else
|
||||
unsafe! asm
|
||||
template llvm
|
||||
$0 = extractvalue {\{{ t }}, i1} %res, 0
|
||||
$0 = extractvalue {\{{ t }}, i1} %res, 0
|
||||
out =r(result)
|
||||
end
|
||||
|
||||
@@ -600,7 +600,7 @@ end
|
||||
This is a fairly complex example making use of the inline assembly feature.
|
||||
But this is what the language is capable of.
|
||||
|
||||
Notice that delayed macro blocks, i.e. those beginning with `{{`, are evaluated on every specialization, so the contents of the `add` function would be different for `Int<Base: 2, Signed: true, Size: 16>` (a.k.a. `SBin16`) and `Int<Base: 2, Signed: false, Size: 32>` (a.k.a. `UBin32`).
|
||||
Notice that delayed macro blocks, i.e. those beginning with `{{`, are evaluated on every specialization, so the contents of the `add` function would be different for `Int<Base: 2, Signed: true, Size: 16>` (a.k.a. `SBin16`) and `Int<Base: 2, Signed: false, Size: 32>` (a.k.a. `UBin32`).
|
||||
|
||||
There were other features of Onyx mentioned in the example: 1) reopening certain or broad (the `forall` thing), specializations, 2) aliasing.
|
||||
In fact, this is how integer aliasing looks like in the Core API:
|
||||
@@ -612,11 +612,11 @@ alias IBin<*>, Bin<*> = Int<2, *>
|
||||
|
||||
# Use a macro to DRY the code.
|
||||
private macro @alias_binary_sizes(id)
|
||||
alias \{{ id }}8 = \{{ id }}<8>
|
||||
alias \{{ id }}16 = \{{ id }}<16>
|
||||
alias \{{ id }}32 = \{{ id }}<32>
|
||||
alias \{{ id }}64 = \{{ id }}<64>
|
||||
alias \{{ id }}128 = \{{ id }}<128>
|
||||
alias \{{ id }}8 = \{{ id }}<8>
|
||||
alias \{{ id }}16 = \{{ id }}<16>
|
||||
alias \{{ id }}32 = \{{ id }}<32>
|
||||
alias \{{ id }}64 = \{{ id }}<64>
|
||||
alias \{{ id }}128 = \{{ id }}<128>
|
||||
end
|
||||
|
||||
# Signed binary integers.
|
||||
@@ -630,10 +630,10 @@ alias UIBin<*>, UBin<*> = IBin<false, *>
|
||||
@alias_binary_sizes("UBin")
|
||||
```
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
Macro code can generate other macro code.
|
||||
The algorithm is to evaluate immediate macros (e.g. `{% %}`) immediately once they are met in the code by some lexer, but evaluate delayed macros (e.g. `\{% %}`) only when the time is right, for example, per specialization.
|
||||
The algorithm is to evaluate immediate macros (e.g. `{% %}`) immediately once they are met in the code by some lexer, but evaluate delayed macros (e.g. `\{% %}`) only when the time is right, for example, per specialization.
|
||||
|
||||
This allows to avoid embarrassing situations like [this](https://github.com/diesel-rs/diesel/blob/master/diesel/src/macros/tuples.rs) in Rust.
|
||||
|
||||
@@ -685,10 +685,10 @@ Let's modify the function a bit:
|
||||
|
||||
```text
|
||||
def do_draw(x ~ Drawable2D)
|
||||
{% print("Immediate: " ..
|
||||
{% print("Immediate: " ..
|
||||
nx.ctx.x.real_type:dump()) %}
|
||||
|
||||
\{% print("Specialized: " ..
|
||||
\{% print("Specialized: " ..
|
||||
nx.ctx.x.real_type:dump()) %}
|
||||
end
|
||||
|
||||
@@ -714,11 +714,11 @@ It is still possible to operate on a real type in this case thanks to type infor
|
||||
|
||||
```text
|
||||
def do_draw(x ~ Drawable2D)
|
||||
\{% if nx.ctx.x.real_type == nx.lkp("Point") %}
|
||||
\{% if nx.ctx.x.real_type == nx.lkp("Point") %}
|
||||
# x : Point # Panic! It is still `Undef`
|
||||
# x.point_specific_method # Panic!
|
||||
(unsafe! x as Point).point_specific_method
|
||||
\{% end %}
|
||||
\{% end %}
|
||||
end
|
||||
```
|
||||
|
||||
@@ -788,7 +788,7 @@ Incapsulation at its finest!
|
||||
|
||||
Some more highlights of the language's features:
|
||||
|
||||
* SIMD vectors and matrices built-in with literals.
|
||||
- SIMD vectors and matrices built-in with literals.
|
||||
It looks like this:
|
||||
|
||||
```text
|
||||
@@ -822,7 +822,7 @@ Some more highlights of the language's features:
|
||||
> = Tensor<T, Z, 0>
|
||||
```
|
||||
|
||||
* "Magic" literals inspired by Ruby:
|
||||
- "Magic" literals inspired by Ruby:
|
||||
|
||||
```text
|
||||
let vec = %i<1 2 3 4>
|
||||
@@ -830,7 +830,7 @@ Some more highlights of the language's features:
|
||||
let ary = %f64[1 2 3]
|
||||
```
|
||||
|
||||
* [IEC](https://en.wikipedia.org/wiki/Kibibyte) and [SI](https://en.wikipedia.org/wiki/Kilobyte) numerical literal prefixes:
|
||||
- [IEC](https://en.wikipedia.org/wiki/Kibibyte) and [SI](https://en.wikipedia.org/wiki/Kilobyte) numerical literal prefixes:
|
||||
|
||||
```text
|
||||
# Kibi
|
||||
@@ -845,7 +845,7 @@ Some more highlights of the language's features:
|
||||
42_000_000.017)
|
||||
```
|
||||
|
||||
* String and character literals with default UTF-8 encoding and UCS charset.
|
||||
- String and character literals with default UTF-8 encoding and UCS charset.
|
||||
The language allows custom string and character literal suffixes for custom encodings.
|
||||
|
||||
```text
|
||||
@@ -867,7 +867,7 @@ Some more highlights of the language's features:
|
||||
@assert(@sizeof(c) == 4)
|
||||
```
|
||||
|
||||
* Distinct aliasing allows having a type with different methods, but the same layout.
|
||||
- Distinct aliasing allows having a type with different methods, but the same layout.
|
||||
For example, the `String` type is a distinct alias to an array of codeunits:
|
||||
|
||||
```text
|
||||
@@ -881,7 +881,7 @@ Some more highlights of the language's features:
|
||||
end
|
||||
```
|
||||
|
||||
* `Any` real type implies a variant of all possible types.
|
||||
- `Any` real type implies a variant of all possible types.
|
||||
In practice, it is often constrained by an imaginary type to reduce the number of contained options and define behaviour.
|
||||
For example:
|
||||
|
||||
@@ -914,7 +914,7 @@ Some more highlights of the language's features:
|
||||
end
|
||||
```
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
I could continue digging into Onyx features and examples, but for an introductory post, that should be enough.
|
||||
|
||||
@@ -980,7 +980,7 @@ In addition to monetary funding, NXSF would also sponsor recurring security audi
|
||||
|
||||
Apart from funding packages, the Foundation will sponsor projects and events related to Onyx, including teaching conferences, teaching materials, integrations etc.
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
Onyx is the perfect balance between productivity and performance, a language understandable well both by humans and machines.
|
||||
|
||||
@@ -989,7 +989,7 @@ I heartfully believe that Onyx may become a new lingua franca for decades until
|
||||
|
||||
Visit [nxsf.org](https://nxsf.org) to stay updated, and...
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
::: hero
|
||||
|
||||
@@ -997,4 +997,4 @@ Visit [nxsf.org](https://nxsf.org) to stay updated, and...
|
||||
|
||||
:::
|
||||
|
||||
----
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user