mirror of
https://github.com/Open-Argon/docs.git
synced 2026-10-28 09:43:55 +00:00
add more documentation
This commit is contained in:
1 parent
ac8d522d34
commit
56f4abd891
21 files changed
+988
-31
No files matched your search
@@ -74,7 +74,7 @@ x[0] = 10
|
||||
### `.pop`
|
||||
|
||||
```
|
||||
import "../stdlib/random" expose random
|
||||
import "random" expose random
|
||||
|
||||
let x = []
|
||||
let i = 0
|
||||
@@ -108,7 +108,7 @@ produces a range object, and `array(...)` converts it to a concrete array first.
|
||||
### Random shuffle via swapping
|
||||
|
||||
```
|
||||
import "../stdlib/random" expose random
|
||||
import "random" expose random
|
||||
|
||||
let x = []
|
||||
let i = 0
|
||||
|
||||
@@ -11,7 +11,7 @@ A `while` loop with a truthy constant condition (e.g. a non-zero length) can be
|
||||
drain a collection:
|
||||
|
||||
```
|
||||
import "../stdlib/random" expose random
|
||||
import "random" expose random
|
||||
|
||||
let x = []
|
||||
let i = 0
|
||||
|
||||
@@ -46,7 +46,7 @@ for (keyval in value) do
|
||||
...
|
||||
```
|
||||
|
||||
(adapted from [`stdlib/json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/json/init.ar)'s `stringify`
|
||||
(adapted from [`stdlib/json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43json/init.ar)'s `stringify`
|
||||
function, which walks a dictionary's entries this way to build JSON output)
|
||||
|
||||
### Converting to/from a dictionary
|
||||
@@ -74,7 +74,7 @@ let split(p) = do
|
||||
return tuple(head, tail)
|
||||
```
|
||||
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/path/init.ar)'s `split` function,
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43path/init.ar)'s `split` function,
|
||||
which returns a `tuple(head, tail)`)
|
||||
|
||||
### Indexing a tuple
|
||||
|
||||
@@ -44,7 +44,7 @@ let is_relative_to(p, base) = do
|
||||
return false
|
||||
```
|
||||
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/path/init.ar))
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43path/init.ar))
|
||||
|
||||
## Defining custom exceptions
|
||||
|
||||
@@ -94,8 +94,8 @@ The global scope defines a hierarchy of built-in exceptions you can catch or sub
|
||||
|
||||
Module-specific standard library packages (like `file` and `regex`) also define their own
|
||||
exception subclasses in an `exceptions.ar` file — see, for example,
|
||||
[`stdlib/file/exceptions.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/file/exceptions.ar) and
|
||||
[`stdlib/regex/exceptions.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/regex/exceptions.ar).
|
||||
[`stdlib/file/exceptions.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43file/exceptions.ar) and
|
||||
[`stdlib/regex/exceptions.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43regex/exceptions.ar).
|
||||
|
||||
## Next
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ let round(num, precision=1) = do
|
||||
...
|
||||
```
|
||||
|
||||
(from [`stdlib/maths/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/maths/init.ar))
|
||||
(from [`stdlib/maths/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43maths/init.ar))
|
||||
|
||||
## Variadic arguments: `*args` and `**kwargs`
|
||||
|
||||
|
||||
@@ -31,14 +31,14 @@ import "<path>" [as <name>] [expose <name1> <name2> ...] | [expose *]
|
||||
let __rand__ = load_native_code(path.resolve(program.file.directory, "native", "bin", "random" + platform.lib_ext))
|
||||
```
|
||||
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/random/init.ar)) — after this,
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43random/init.ar)) — after this,
|
||||
`maths.int(...)` and `path.resolve(...)` refer to functions defined in those modules.
|
||||
|
||||
- **`expose name1 name2 ...`** pulls specific top-level names out of the imported file
|
||||
directly into your current scope, so you can use them unqualified:
|
||||
|
||||
```
|
||||
import "../stdlib/random" expose random
|
||||
import "random" expose random
|
||||
```
|
||||
|
||||
(from [`array_pop.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/array_pop.ar)) — after this, `random` (an
|
||||
@@ -50,7 +50,7 @@ import "<path>" [as <name>] [expose <name1> <name2> ...] | [expose *]
|
||||
|
||||
Import paths are relative to the importing file. `.ar` files can import both other user
|
||||
files (e.g. `"import_test.ar"`) and standard library modules by relative path (e.g.
|
||||
`"../stdlib/random"`, which imports a directory containing an `init.ar`).
|
||||
`"random"`, which imports a directory containing an `init.ar`).
|
||||
|
||||
## Circular imports
|
||||
|
||||
@@ -79,7 +79,7 @@ let __rand__ = load_native_code(
|
||||
)
|
||||
```
|
||||
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/random/init.ar), using
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43random/init.ar), using
|
||||
`program.file.directory` to locate a native shared library relative to the module's own
|
||||
location)
|
||||
|
||||
@@ -100,7 +100,7 @@ location)
|
||||
let home = env["HOME"]
|
||||
```
|
||||
|
||||
(pattern seen in [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/path/init.ar)'s
|
||||
(pattern seen in [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43path/init.ar)'s
|
||||
`expand_user` function, which reads `env["HOME"]` or `env["USERPROFILE"]`)
|
||||
|
||||
## Loading native code
|
||||
|
||||
@@ -33,7 +33,7 @@ term.log(exponent(2, 3)) # 8
|
||||
|
||||
Numeric literals also support scientific notation and hex, e.g. `1e5`, `1e7`, `0xD800`
|
||||
(see [`array_set.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/array_set.ar) for `1e5` and
|
||||
[`json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/json/init.ar) for hex literals).
|
||||
[`json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43json/init.ar) for hex literals).
|
||||
|
||||
## Comparison
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ throw MyError(`hel\u1324lo`)
|
||||
|
||||
Standard escapes are supported inside strings, including `\"`, `\\`, `\/`, `\b`, `\f`,
|
||||
`\n`, `\r`, `\t`, and `\uXXXX` (see the JSON standard library's string parser at
|
||||
[`stdlib/json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/json/init.ar) for the full escape table
|
||||
[`stdlib/json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43json/init.ar) for the full escape table
|
||||
used when parsing JSON strings — the same escapes are valid in Argon string literals).
|
||||
|
||||
## Indexing and slicing
|
||||
@@ -91,7 +91,7 @@ let __starts_with__(s, prefix) = do
|
||||
return s[0:prefix.length] == prefix
|
||||
```
|
||||
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/path/init.ar), showing `.length` and
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43path/init.ar), showing `.length` and
|
||||
slicing used together)
|
||||
|
||||
## Comparing strings
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
# `date`
|
||||
|
||||
```
|
||||
import "date" as date
|
||||
```
|
||||
|
||||
Provides date and time handling using Unix timestamps internally. Dates are represented with millisecond precision and support creation, formatting, parsing, and accessing or modifying date components.
|
||||
|
||||
## `Date(timestamp_ms=null, timestamp_s=null, date=null, year=null, month=null, ...)`
|
||||
|
||||
Creates a new date object.
|
||||
|
||||
Dates can be created from timestamps:
|
||||
|
||||
```
|
||||
let a = date.Date(timestamp_ms=0)
|
||||
term.log(a.to_string()) # "1970-01-01 00:00:00"
|
||||
|
||||
let b = date.Date(timestamp_s=1)
|
||||
term.log(b.to_string()) # "1970-01-01 00:00:01"
|
||||
```
|
||||
|
||||
A date can also be copied from another `Date` object:
|
||||
|
||||
```
|
||||
let a = date.Date(timestamp_s=100)
|
||||
let b = date.Date(date=a)
|
||||
|
||||
term.log(b.unix()) # 100
|
||||
```
|
||||
|
||||
Individual date components can be provided when constructing a date. Missing components use the default values:
|
||||
|
||||
```
|
||||
let d = date.Date(year=2026, month=7, day=28)
|
||||
|
||||
term.log(d.to_string()) # "2026-07-28 00:00:00"
|
||||
```
|
||||
|
||||
## `Date.now()`
|
||||
|
||||
Returns a `Date` representing the current time.
|
||||
|
||||
```
|
||||
let now = date.Date.now()
|
||||
|
||||
term.log(now.to_string())
|
||||
```
|
||||
|
||||
## `Date.now_utc()`
|
||||
|
||||
Returns the current UTC time.
|
||||
|
||||
Currently this is equivalent to `Date.now()` because dates are stored internally as UTC timestamps.
|
||||
|
||||
## `Date.from_string(str, fmt="%Y-%m-%d %H:%M:%S")`
|
||||
|
||||
Creates a `Date` by parsing a formatted date string.
|
||||
|
||||
```
|
||||
let d = date.Date.from_string("2026-07-28 12:30:00")
|
||||
|
||||
term.log(d.year) # 2026
|
||||
term.log(d.month) # 7
|
||||
term.log(d.day) # 28
|
||||
```
|
||||
|
||||
The format string uses `strftime`-style format specifiers:
|
||||
|
||||
```
|
||||
let d = date.Date.from_string("28/07/2026", "%d/%m/%Y")
|
||||
|
||||
term.log(d.to_string()) # "2026-07-28 00:00:00"
|
||||
```
|
||||
|
||||
## `date.unix()`
|
||||
|
||||
Returns the date as a Unix timestamp in seconds.
|
||||
|
||||
```
|
||||
let d = date.Date(timestamp_s=1000)
|
||||
|
||||
term.log(d.unix()) # 1000
|
||||
```
|
||||
|
||||
## `date.unix_ms()`
|
||||
|
||||
Returns the date as a Unix timestamp in milliseconds.
|
||||
|
||||
```
|
||||
let d = date.Date(timestamp_ms=1000)
|
||||
|
||||
term.log(d.unix_ms()) # 1000
|
||||
```
|
||||
|
||||
## Date properties
|
||||
|
||||
The following properties are available:
|
||||
|
||||
- `year`
|
||||
- `month`
|
||||
- `day`
|
||||
- `hour`
|
||||
- `minute`
|
||||
- `second`
|
||||
- `day_of_week`
|
||||
- `day_of_year`
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
let d = date.Date(year=2026, month=7, day=28, hour=15)
|
||||
|
||||
term.log(d.year) # 2026
|
||||
term.log(d.month) # 7
|
||||
term.log(d.day) # 28
|
||||
term.log(d.hour) # 15
|
||||
```
|
||||
|
||||
`day_of_week` returns the weekday number, and `day_of_year` returns the day number within the year.
|
||||
|
||||
## `date.to_string(fmt="%Y-%m-%d %H:%M:%S")`
|
||||
|
||||
Formats the date as a UTC string.
|
||||
|
||||
```
|
||||
let d = date.Date(year=2026, month=7, day=28)
|
||||
|
||||
term.log(d.to_string())
|
||||
# "2026-07-28 00:00:00"
|
||||
|
||||
term.log(d.to_string("%d/%m/%Y"))
|
||||
# "28/07/2026"
|
||||
```
|
||||
|
||||
## `date.to_local_string(fmt="%Y-%m-%d %H:%M:%S")`
|
||||
|
||||
Formats the date using the local timezone.
|
||||
|
||||
```
|
||||
let d = date.Date.now()
|
||||
|
||||
term.log(d.to_local_string())
|
||||
```
|
||||
|
||||
## `date.http_date()`
|
||||
|
||||
Formats the date using the HTTP-date format.
|
||||
|
||||
```
|
||||
let d = date.Date(timestamp_s=0)
|
||||
|
||||
term.log(d.http_date())
|
||||
# "Thu, 01 Jan 1970 00:00:00 GMT"
|
||||
```
|
||||
|
||||
## Date modification
|
||||
|
||||
The date components can be changed using setters:
|
||||
|
||||
- `set_year(value)`
|
||||
- `set_month(value)`
|
||||
- `set_day(value)`
|
||||
- `set_hour(value)`
|
||||
- `set_minute(value)`
|
||||
- `set_second(value)`
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
let d = date.Date(year=2026, month=1, day=1)
|
||||
|
||||
d.set_month(7)
|
||||
d.set_day(28)
|
||||
|
||||
term.log(d.to_string())
|
||||
# "2026-07-28 00:00:00"
|
||||
```
|
||||
|
||||
## `Date.monotonic()`
|
||||
|
||||
Returns the current monotonic clock value.
|
||||
|
||||
Unlike normal timestamps, monotonic time is not affected by system clock changes and is intended for measuring durations.
|
||||
|
||||
```
|
||||
let start = date.Date.monotonic()
|
||||
|
||||
# do some work
|
||||
|
||||
let elapsed = date.Date.monotonic() - start
|
||||
```
|
||||
|
||||
## Format strings
|
||||
|
||||
Formatting and parsing functions use `strftime`-style format codes.
|
||||
|
||||
Common format codes:
|
||||
|
||||
| Code | Meaning | Example |
|
||||
| --- | --- | --- |
|
||||
| `%Y` | Four digit year | `2026` |
|
||||
| `%m` | Month number | `07` |
|
||||
| `%d` | Day of month | `28` |
|
||||
| `%H` | Hour (24-hour clock) | `15` |
|
||||
| `%M` | Minute | `30` |
|
||||
| `%S` | Second | `00` |
|
||||
| `%a` | Short weekday name | `Tue` |
|
||||
| `%b` | Short month name | `Jul` |
|
||||
|
||||
## Timezones
|
||||
|
||||
`Date` objects store timestamps as UTC internally.
|
||||
|
||||
Functions ending in `_utc` operate directly on UTC values, while local formatting functions apply the system timezone.
|
||||
|
||||
## Next
|
||||
|
||||
- [`json`](../json/README.md)
|
||||
- [`file`](../file/README.md)
|
||||
@@ -5,7 +5,7 @@ import "file" expose open
|
||||
```
|
||||
|
||||
Filesystem I/O (native code backed), see
|
||||
[`stdlib/file/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/file/init.ar).
|
||||
[`stdlib/file/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43file/init.ar).
|
||||
|
||||
## `open(path, mode="r")`
|
||||
|
||||
@@ -45,7 +45,7 @@ file.
|
||||
## Exceptions
|
||||
|
||||
`file` defines its own exception hierarchy (all subclasses of the base `FileError`), from
|
||||
[`stdlib/file/exceptions.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/file/exceptions.ar):
|
||||
[`stdlib/file/exceptions.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43file/exceptions.ar):
|
||||
|
||||
- `FileError` — general file error base class.
|
||||
- `FileReadError` — raised when reading fails (e.g. reading a file not opened in read
|
||||
@@ -67,7 +67,7 @@ catch (FileNotFoundError as e) do
|
||||
|
||||
Attempting to open a file with an invalid mode string raises a `FileError` before any
|
||||
filesystem access happens — see `_validate_mode` in
|
||||
[`stdlib/file/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/file/init.ar), which also demonstrates
|
||||
[`stdlib/file/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43file/init.ar), which also demonstrates
|
||||
Argon's `not in` operator:
|
||||
|
||||
```
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# `json`
|
||||
|
||||
```
|
||||
import "../stdlib/json" as json
|
||||
import "json" as json
|
||||
```
|
||||
|
||||
A pure-Argon JSON encoder/decoder (see
|
||||
[`stdlib/json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/json/init.ar)).
|
||||
[`stdlib/json/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43json/init.ar)).
|
||||
|
||||
## `json.stringify(value, pretty=false)`
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# `maths`
|
||||
|
||||
```
|
||||
import "../stdlib/maths" as maths
|
||||
import "maths" as maths
|
||||
```
|
||||
|
||||
The full implementation, from
|
||||
[`stdlib/maths/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/maths/init.ar):
|
||||
[`stdlib/maths/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43maths/init.ar):
|
||||
|
||||
```
|
||||
let abs(num) = do
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
# `network`
|
||||
|
||||
```
|
||||
import "network" as network
|
||||
```
|
||||
|
||||
Provides TCP networking support, including TCP servers, clients, sending and receiving data, and socket configuration.
|
||||
|
||||
## Socket errors
|
||||
|
||||
Network failures raise `network.SocketError`.
|
||||
|
||||
```
|
||||
try do
|
||||
let client = network.tcp_client("example.com", 80)
|
||||
catch network.SocketError as e do
|
||||
term.log("Connection failed")
|
||||
```
|
||||
|
||||
## `network.tcp(port)`
|
||||
|
||||
Creates a TCP server socket listening on the specified port.
|
||||
|
||||
```
|
||||
let server = network.tcp(8080)
|
||||
```
|
||||
|
||||
Connections can be accepted using `accept()`:
|
||||
|
||||
```
|
||||
let connection = server.accept()
|
||||
```
|
||||
|
||||
## `network.tcp.accept()`
|
||||
|
||||
Waits for and accepts an incoming TCP connection.
|
||||
|
||||
Returns a `tcp_connection` object.
|
||||
|
||||
```
|
||||
let server = network.tcp(8080)
|
||||
|
||||
let client = server.accept()
|
||||
```
|
||||
|
||||
## `network.tcp_client(host, port)`
|
||||
|
||||
Connects to a TCP server.
|
||||
|
||||
```
|
||||
let client = network.tcp_client("localhost", 8080)
|
||||
```
|
||||
|
||||
The returned object can send and receive data.
|
||||
|
||||
## Sending and receiving data
|
||||
|
||||
### `send(buffer)`
|
||||
|
||||
Sends raw data through the socket.
|
||||
|
||||
```
|
||||
client.send(buffer)
|
||||
```
|
||||
|
||||
Returns the number of bytes sent.
|
||||
|
||||
### `send_string(string)`
|
||||
|
||||
Sends a string through the socket.
|
||||
|
||||
```
|
||||
client.send_string("Hello, server!")
|
||||
```
|
||||
|
||||
Returns the number of bytes sent.
|
||||
|
||||
### `recv(buffer)`
|
||||
|
||||
Receives data into a buffer.
|
||||
|
||||
```
|
||||
client.recv(buffer)
|
||||
```
|
||||
|
||||
Returns the number of bytes received.
|
||||
|
||||
### `recv_string(size)`
|
||||
|
||||
Receives up to `size` bytes and returns them as a string.
|
||||
|
||||
```
|
||||
let message = client.recv_string(1024)
|
||||
```
|
||||
|
||||
### `peek(buffer)`
|
||||
|
||||
Reads data without removing it from the socket receive buffer.
|
||||
|
||||
```
|
||||
client.peek(buffer)
|
||||
```
|
||||
|
||||
## Polling
|
||||
|
||||
Sockets can be checked for readiness using `poll()`.
|
||||
|
||||
### `poll(want_read, want_write, timeout_ms)`
|
||||
|
||||
Waits until a socket is ready for reading or writing.
|
||||
|
||||
Returns a bitmask containing one or more of:
|
||||
|
||||
| Constant | Value | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `NET_POLL_READ` | `1` | Socket is ready for reading |
|
||||
| `NET_POLL_WRITE` | `2` | Socket is ready for writing |
|
||||
|
||||
A return value of `0` indicates that the timeout expired.
|
||||
|
||||
A return value of `-1` indicates an error.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
let result = client.poll(true, false, 1000)
|
||||
|
||||
if (result & network.NET_POLL_READ) do
|
||||
let data = client.recv_string(1024)
|
||||
```
|
||||
|
||||
A timeout of `-1` blocks indefinitely.
|
||||
|
||||
## Non-blocking sockets
|
||||
|
||||
### `set_nonblocking(enable)`
|
||||
|
||||
Enables or disables non-blocking mode.
|
||||
|
||||
```
|
||||
client.set_nonblocking(true)
|
||||
```
|
||||
|
||||
When enabled, socket operations return immediately instead of waiting.
|
||||
|
||||
## Socket options
|
||||
|
||||
### `set_opt(option, value)`
|
||||
|
||||
Sets a socket option.
|
||||
|
||||
Available options:
|
||||
|
||||
| Constant | Meaning |
|
||||
| --- | --- |
|
||||
| `NET_OPT_KEEPALIVE` | Enable TCP keepalive |
|
||||
| `NET_OPT_NODELAY` | Disable Nagle's algorithm |
|
||||
| `NET_OPT_REUSEADDR` | Allow address reuse |
|
||||
| `NET_OPT_RCVTIMEO` | Set receive timeout |
|
||||
| `NET_OPT_SNDTIMEO` | Set send timeout |
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
client.set_opt(network.NET_OPT_NODELAY, true)
|
||||
```
|
||||
|
||||
## Closing sockets
|
||||
|
||||
### `close()`
|
||||
|
||||
Closes the socket and releases its resources.
|
||||
|
||||
```
|
||||
client.close()
|
||||
server.close()
|
||||
```
|
||||
|
||||
## Example TCP server
|
||||
|
||||
```
|
||||
let server = network.tcp(8080)
|
||||
|
||||
while true do
|
||||
let connection = server.accept()
|
||||
|
||||
let message = connection.recv_string(1024)
|
||||
connection.send_string("Received: " + message)
|
||||
|
||||
connection.close()
|
||||
```
|
||||
|
||||
## Example TCP client
|
||||
|
||||
```
|
||||
let client = network.tcp_client("localhost", 8080)
|
||||
|
||||
client.send_string("Hello!")
|
||||
|
||||
let response = client.recv_string(1024)
|
||||
|
||||
term.log(response)
|
||||
|
||||
client.close()
|
||||
```
|
||||
|
||||
## Next
|
||||
|
||||
- [`time`](../time/README.md)
|
||||
- [`date`](../date/README.md)
|
||||
@@ -1,11 +1,11 @@
|
||||
# `path`
|
||||
|
||||
```
|
||||
import "../stdlib/path" as path
|
||||
import "path" as path
|
||||
```
|
||||
|
||||
A pure-Argon path manipulation library (see
|
||||
[`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/path/init.ar)), similar in spirit to
|
||||
[`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43path/init.ar)), similar in spirit to
|
||||
Python's `pathlib`/`os.path`. Paths are always normalised internally to use `/` as the
|
||||
separator, even on Windows.
|
||||
|
||||
@@ -57,7 +57,7 @@ let __rand__ = load_native_code(
|
||||
)
|
||||
```
|
||||
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/random/init.ar) — see
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43random/init.ar) — see
|
||||
[`program`](../../language/modules/README.md#the-program-global) and
|
||||
[`platform`](../../language/modules/README.md#the-platform-global) for the globals used
|
||||
here)
|
||||
@@ -70,7 +70,7 @@ let home = do
|
||||
return env["HOME"]
|
||||
```
|
||||
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/path/init.ar)) — this shows the
|
||||
(from [`stdlib/path/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43path/init.ar)) — this shows the
|
||||
[`env`](../../language/modules/README.md#the-env-global) global being used to find the
|
||||
user's home directory in a cross-platform way.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# `random`
|
||||
|
||||
```
|
||||
import "../stdlib/random" expose random
|
||||
import "random" expose random
|
||||
```
|
||||
|
||||
The module exposes a single ready-made `random` instance (of an internal `Random` class),
|
||||
@@ -23,7 +23,7 @@ class Random do
|
||||
let random = Random(__rand__.random_os_seed())
|
||||
```
|
||||
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/stdlib/random/init.ar)) — the underlying
|
||||
(from [`stdlib/random/init.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea43random/init.ar)) — the underlying
|
||||
random number generation is implemented in native C (`native/random.c`), loaded via
|
||||
`load_native_code`.
|
||||
|
||||
@@ -41,7 +41,7 @@ random number generation is implemented in native C (`native/random.c`), loaded
|
||||
Picking a random index and popping it (a shuffle pattern):
|
||||
|
||||
```
|
||||
import "../stdlib/random" expose random
|
||||
import "random" expose random
|
||||
|
||||
let x = []
|
||||
let i = 0
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
# `regex`
|
||||
|
||||
```
|
||||
import "regex" as regex
|
||||
```
|
||||
|
||||
Provides regular expression matching, searching, replacing, and splitting using compiled regular expressions.
|
||||
|
||||
## `regex.Regex(pattern)`
|
||||
|
||||
Creates a compiled regular expression from a pattern.
|
||||
|
||||
```
|
||||
let re = regex.Regex("[0-9]+")
|
||||
|
||||
term.log(re.match("123"))
|
||||
```
|
||||
|
||||
Compiled regular expressions can be reused multiple times.
|
||||
|
||||
## `Regex.intern(pattern)`
|
||||
|
||||
Creates or retrieves a shared compiled regular expression.
|
||||
|
||||
Interned regular expressions are cached and reused when the same pattern is requested multiple times.
|
||||
|
||||
```
|
||||
let a = regex.Regex.intern("[a-z]+")
|
||||
let b = regex.Regex.intern("[a-z]+")
|
||||
|
||||
term.log(a == b)
|
||||
```
|
||||
|
||||
Interned regular expressions are managed automatically and cannot be manually freed.
|
||||
|
||||
## `Regex.close()`
|
||||
|
||||
Frees the resources used by a regular expression.
|
||||
|
||||
```
|
||||
let re = regex.Regex("hello")
|
||||
|
||||
re.close()
|
||||
```
|
||||
|
||||
Calling `close()` on an interned regular expression raises a `RuntimeError`.
|
||||
|
||||
## `Regex.match(subject)`
|
||||
|
||||
Checks whether the regular expression matches the given string.
|
||||
|
||||
```
|
||||
let re = regex.Regex("^hello")
|
||||
|
||||
term.log(re.match("hello world"))
|
||||
```
|
||||
|
||||
Returns the match result from the regular expression engine.
|
||||
|
||||
## `Regex.find(subject)`
|
||||
|
||||
Finds the first match in a string.
|
||||
|
||||
```
|
||||
let re = regex.Regex("[0-9]+")
|
||||
|
||||
let result = re.find("abc123def")
|
||||
|
||||
term.log(result)
|
||||
```
|
||||
|
||||
Returns the first matching result, or an empty result if no match is found.
|
||||
|
||||
## `Regex.find_all(subject)`
|
||||
|
||||
Finds all matches in a string.
|
||||
|
||||
```
|
||||
let re = regex.Regex("[0-9]+")
|
||||
|
||||
let results = re.find_all("abc123def456")
|
||||
|
||||
term.log(results)
|
||||
```
|
||||
|
||||
Returns an array containing every match.
|
||||
|
||||
## `Regex.replace(subject, replacement)`
|
||||
|
||||
Replaces the first match with the given replacement.
|
||||
|
||||
```
|
||||
let re = regex.Regex("[0-9]+")
|
||||
|
||||
term.log(re.replace("abc123", "x"))
|
||||
```
|
||||
|
||||
## `Regex.replace_all(subject, replacement)`
|
||||
|
||||
Replaces every match with the given replacement.
|
||||
|
||||
```
|
||||
let re = regex.Regex("[0-9]+")
|
||||
|
||||
term.log(re.replace_all("abc123def456", "x"))
|
||||
# "abcxdefx"
|
||||
```
|
||||
|
||||
## `Regex.split(subject)`
|
||||
|
||||
Splits a string using the regular expression as the delimiter.
|
||||
|
||||
```
|
||||
let re = regex.Regex(",")
|
||||
|
||||
let parts = re.split("one,two,three")
|
||||
|
||||
term.log(parts)
|
||||
# ["one", "two", "three"]
|
||||
```
|
||||
|
||||
## Errors
|
||||
|
||||
Invalid regular expression patterns raise `RegexError`.
|
||||
|
||||
```
|
||||
regex.Regex("[")
|
||||
# RegexError
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
let number = regex.Regex("[0-9]+")
|
||||
|
||||
let text = "There are 123 apples and 456 oranges"
|
||||
|
||||
term.log(number.find_all(text))
|
||||
# ["123", "456"]
|
||||
|
||||
term.log(number.replace_all(text, "N"))
|
||||
# "There are N apples and N oranges"
|
||||
```
|
||||
|
||||
## Next
|
||||
|
||||
- [`json`](../json/README.md)
|
||||
- [`network`](../network/README.md)
|
||||
@@ -0,0 +1,151 @@
|
||||
# `threading`
|
||||
|
||||
```
|
||||
import "threading" as threading
|
||||
```
|
||||
|
||||
Provides support for running code in separate threads and storing thread-local data.
|
||||
|
||||
## `threading.Thread(target)`
|
||||
|
||||
Creates a new thread that executes the given function.
|
||||
|
||||
The target function is called with no arguments when the thread starts.
|
||||
|
||||
```
|
||||
let thread = threading.Thread(()=do
|
||||
term.log("Hello from a thread")
|
||||
)
|
||||
|
||||
thread.start()
|
||||
```
|
||||
|
||||
The target function's return value can be retrieved using `join()`.
|
||||
|
||||
## `Thread.start()`
|
||||
|
||||
Starts the thread.
|
||||
|
||||
```
|
||||
let thread = threading.Thread(()=do
|
||||
term.log("Running")
|
||||
)
|
||||
|
||||
thread.start()
|
||||
```
|
||||
|
||||
Returns the `Thread` object, allowing threads to be created and started inline:
|
||||
|
||||
```
|
||||
let thread = threading.Thread(()=do
|
||||
do_work()
|
||||
).start()
|
||||
```
|
||||
|
||||
Calling `start()` on an already started thread has no effect.
|
||||
|
||||
## `Thread.join()`
|
||||
|
||||
Waits for the thread to finish and returns the value returned by the target function.
|
||||
|
||||
```
|
||||
let thread = threading.Thread(()=do
|
||||
return 42
|
||||
)
|
||||
|
||||
thread.start()
|
||||
|
||||
let result = thread.join()
|
||||
|
||||
term.log(result) # 42
|
||||
```
|
||||
|
||||
If the thread has not been started, `join()` immediately returns the current return value.
|
||||
|
||||
## `Thread.detach()`
|
||||
|
||||
Detaches the thread, allowing it to continue running independently.
|
||||
|
||||
```
|
||||
let thread = threading.Thread(()=do
|
||||
do_work()
|
||||
)
|
||||
|
||||
thread.start()
|
||||
thread.detach()
|
||||
```
|
||||
|
||||
A detached thread cannot be joined later.
|
||||
|
||||
## `threading.get_id()`
|
||||
|
||||
Returns the ID of the current thread.
|
||||
|
||||
```
|
||||
let id = threading.get_id()
|
||||
|
||||
term.log(id)
|
||||
```
|
||||
|
||||
## `threading.Local()`
|
||||
|
||||
Creates thread-local storage.
|
||||
|
||||
Each thread has its own separate storage. Values assigned in one thread are not visible in other threads.
|
||||
|
||||
```
|
||||
let local = threading.Local()
|
||||
|
||||
let worker = ()=do
|
||||
local.value = 10
|
||||
term.log(local.value)
|
||||
|
||||
let thread = threading.Thread(worker)
|
||||
|
||||
thread.start()
|
||||
thread.join()
|
||||
|
||||
term.log(local.value)
|
||||
```
|
||||
|
||||
Thread-local values can be accessed using attributes or indexing:
|
||||
|
||||
```
|
||||
let local = threading.Local()
|
||||
|
||||
local.name = "main"
|
||||
term.log(local.name)
|
||||
|
||||
local["count"] = 5
|
||||
term.log(local["count"])
|
||||
```
|
||||
|
||||
Each thread maintains its own values internally.
|
||||
|
||||
## Example: running multiple workers
|
||||
|
||||
```
|
||||
let storage = threading.Local()
|
||||
|
||||
let worker = (value)=do
|
||||
storage.value = value
|
||||
|
||||
let output = 1000000
|
||||
for (i in 0 until output) do
|
||||
return output
|
||||
|
||||
let threads = []
|
||||
|
||||
for (i in 0 until 4) do
|
||||
threads.append(threading.Thread(()=worker(i)).start())
|
||||
|
||||
for (thread in threads) do
|
||||
term.log(thread.join())
|
||||
```
|
||||
|
||||
Each worker has its own `storage.value`, even though all workers share the same `Local` object.
|
||||
|
||||
## Next
|
||||
|
||||
- [`network`](../network/README.md)
|
||||
- [`time`](../time/README.md)
|
||||
@@ -0,0 +1,50 @@
|
||||
# `time`
|
||||
|
||||
```
|
||||
import "time" as time
|
||||
```
|
||||
|
||||
Provides functions for working with delays and timing.
|
||||
|
||||
## `time.snooze(seconds)`
|
||||
|
||||
Pauses execution for the specified number of seconds.
|
||||
|
||||
`seconds` may be an integer or a rational number.
|
||||
|
||||
```
|
||||
time.snooze(1)
|
||||
```
|
||||
|
||||
Sleeps for one second before continuing execution.
|
||||
|
||||
Fractional seconds can be used for shorter delays:
|
||||
|
||||
```
|
||||
time.snooze(0.5)
|
||||
```
|
||||
|
||||
Sleeps for half a second.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
term.log("Starting")
|
||||
|
||||
time.snooze(2)
|
||||
|
||||
term.log("Finished")
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```
|
||||
Starting
|
||||
# waits 2 seconds
|
||||
Finished
|
||||
```
|
||||
|
||||
## Next
|
||||
|
||||
- [`date`](../date/README.md)
|
||||
- [`json`](../json/README.md)
|
||||
@@ -0,0 +1,39 @@
|
||||
# Command line usage
|
||||
|
||||
Chloride provides a command line interface for running Argon programs and accessing development tools.
|
||||
|
||||
## Running a program
|
||||
|
||||
An Argon source file can be run by passing its filename to `argon`:
|
||||
|
||||
```
|
||||
argon my_program.ar
|
||||
```
|
||||
|
||||
If the file uses the `.ar` extension, the extension can be omitted:
|
||||
|
||||
```
|
||||
argon my_program
|
||||
```
|
||||
|
||||
Both commands will run the same file:
|
||||
|
||||
```
|
||||
my_program.ar
|
||||
```
|
||||
|
||||
## Checking the version
|
||||
|
||||
To display the installed Chloride version, run:
|
||||
|
||||
```
|
||||
argon --version
|
||||
```
|
||||
|
||||
This prints version information for the current installation.
|
||||
|
||||
## REPL
|
||||
|
||||
Chloride also includes an interactive REPL for running Argon code interactively.
|
||||
|
||||
See the [REPL documentation](repl/README.md) for more information.
|
||||
@@ -0,0 +1,98 @@
|
||||
# Build from source
|
||||
|
||||
If the pre-built binaries do not meet your requirements, Chloride can be built from source for your platform.
|
||||
|
||||
## Getting the source
|
||||
|
||||
Clone the Chloride repository:
|
||||
|
||||
```
|
||||
git clone https://git.wbell.dev/Open-Argon/Chloride
|
||||
cd Chloride
|
||||
```
|
||||
|
||||
Chloride uses git submodules, which must be downloaded recursively:
|
||||
|
||||
```
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
Before building Chloride, compile the standard libraries:
|
||||
|
||||
```
|
||||
./build-stdlib.sh
|
||||
```
|
||||
|
||||
## Build systems
|
||||
|
||||
There are two supported ways to build Chloride:
|
||||
|
||||
- **Conan** — recommended for users who are not developing Chloride.
|
||||
- **Make** — recommended for Chloride development, as it supports dynamic linking and provides additional debugging tools.
|
||||
|
||||
## Conan
|
||||
|
||||
Conan is a cross-platform package manager and build tool.
|
||||
|
||||
The required dependencies are:
|
||||
|
||||
- `conan`
|
||||
- `flex`
|
||||
- `cmake`
|
||||
- `gcc`
|
||||
|
||||
Install the dependencies using Conan:
|
||||
|
||||
```
|
||||
conan install . --build=missing
|
||||
```
|
||||
|
||||
Then build Chloride:
|
||||
|
||||
```
|
||||
conan build .
|
||||
```
|
||||
|
||||
The final build can be found in:
|
||||
|
||||
```
|
||||
build/dist/bin
|
||||
```
|
||||
|
||||
## Make
|
||||
|
||||
Make is intended primarily for Chloride development.
|
||||
|
||||
Unlike Conan, dependencies are not automatically managed. The exact dependencies depend on your platform and may change over time. If a build fails due to a missing dependency, check the `Makefile` or install the missing package manually.
|
||||
|
||||
Development is currently only configured for POSIX systems. If you are using Windows, it is recommended to build using **WSL**.
|
||||
|
||||
### Normal build
|
||||
|
||||
To build Chloride normally:
|
||||
|
||||
```
|
||||
make -j$(nproc)
|
||||
```
|
||||
|
||||
### Cross-compiling for Windows
|
||||
|
||||
To build a Windows version from a POSIX system:
|
||||
|
||||
```
|
||||
make -j$(nproc) TARGET_OS=windows
|
||||
```
|
||||
|
||||
### Debug builds
|
||||
|
||||
For a debug build:
|
||||
|
||||
```
|
||||
make -j$(nproc) full-debug
|
||||
```
|
||||
|
||||
For a Windows debug build:
|
||||
|
||||
```
|
||||
make -j$(nproc) full-debug TARGET_OS=windows
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
# Running the REPL
|
||||
|
||||
Before you can use Argon's REPL, start it by running:
|
||||
```bash
|
||||
argon
|
||||
```
|
||||
|
||||
This launches the REPL, which looks something like this:
|
||||
```
|
||||
Chloride v4.0.2-2-g97ad5ce Copyright (C) 2026 William Bell
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type "license".
|
||||
This is free software released under the GNU GPL Version 3 or later,
|
||||
and you are welcome to redistribute it under certain conditions; type "license" for details.
|
||||
You can learn more about what the term "free software" means at https://www.gnu.org/philosophy/free-sw.html
|
||||
|
||||
>>>
|
||||
```
|
||||
|
||||
You can enter code directly at the prompt. For example:
|
||||
```
|
||||
>>> let x = 1
|
||||
1
|
||||
>>> x+=1
|
||||
2
|
||||
>>> let f(x) = 2*x^2 + 3*x + 10
|
||||
<function f at 0x7f6df3b9ee00>
|
||||
>>> f(x)
|
||||
24
|
||||
>>>
|
||||
```
|
||||
|
||||
To write multi-line code, end a line with the `do` keyword. The REPL will continue on a new indented line. To finish the block, enter a blank line:
|
||||
```
|
||||
>>> let f(x) = do
|
||||
... x*=10
|
||||
... return x
|
||||
...
|
||||
...
|
||||
<function f at 0x7f6df3b9e000>
|
||||
>>>
|
||||
```
|
||||
Reference in new issue
Block a user