add read mes

This commit is contained in:
Ugric committed 2026-07-28 00:52:01 +01:00
1 parent 8a27bd8455
commit 9797fc8bfb
16 files changed
+884 -203

No files matched your search

+59 -3
View File
@@ -1,4 +1,60 @@
# docs
read the [spec](spec)
# Chloride / Argon Documentation
- [Variable and function assignment](variable-and-function-assignment)
This is community documentation for **Argon**, the programming language, as implemented by
**Chloride**, its C-based interpreter (a bytecode compiler + virtual machine).
If you already know a scripting language like Python or JavaScript, most of this will feel
familiar. Argon uses `do` blocks instead of `{ }`, and functions are declared as
`let name(args) = do ... `.
> **Note:** This documentation is written from reading the interpreter's source code and
> test suite, since the project doesn't yet have complete official docs. If something here
> looks wrong, trust the source code (and please fix this doc!).
## Start here
- [Installation](getting-started/README.md)
- [Your first program](getting-started/first-program/README.md)
- [Running the REPL](tooling/repl/README.md)
## Language guide
- [Variables and `let`](language/variables/README.md)
- [Operators](language/operators/README.md)
- [Control flow](language/control-flow/README.md)
- [`if` / `else`](language/control-flow/if/README.md)
- [`while` loops](language/control-flow/while/README.md)
- [`for` loops and iterators](language/control-flow/for/README.md)
- [`break` and `continue`](language/control-flow/break-continue/README.md)
- [Functions](language/functions/README.md)
- [Strings](language/strings/README.md)
- [Arrays](language/arrays/README.md)
- [Dictionaries and tuples](language/dictionaries-and-tuples/README.md)
- [Classes and objects](language/classes/README.md)
- [Errors and exceptions](language/error-handling/README.md)
- [Modules and `import`](language/modules/README.md)
## Standard library
- [`term`](standard-library/term/README.md) — printing and input
- [`maths`](standard-library/maths/README.md)
- [`random`](standard-library/random/README.md)
- [`path`](standard-library/path/README.md)
- [`json`](standard-library/json/README.md)
- [`file`](standard-library/file/README.md)
- [`date`](standard-library/date/README.md)
- [`time`](standard-library/time/README.md)
- [`network`](standard-library/network/README.md)
- [`threading`](standard-library/threading/README.md)
- [`regex`](standard-library/regex/README.md)
## Tooling
- [Command line usage](tooling/README.md)
- [The REPL](tooling/repl/README.md)
- [Building from source](tooling/building-from-source/README.md)
## License
Chloride is released under the GNU General Public License v3.0 (or later). See the
project's `LICENSE` file for details.
+2 -2
View File
@@ -1,3 +1,3 @@
title: Argon v3
description: This is the documentation for the Argon v3 Programming language.
title: Argon
description: This is the documentation for the Argon Programming language. This Documentation mainly targets the chloride interpreter.
theme: jekyll-theme-dinky
+71
View File
@@ -0,0 +1,71 @@
# Installation
Chloride mainly targets **Linux**, **macOS**, **Windows**, and **FreeBSD**, in that order of
priority. Official builds are produced for Linux x86_64, Windows x86_64, and macOS arm64.
If your platform isn't officially supported, feel free to open an issue, or build from
source (see [Building from source](../tooling/building-from-source/README.md)) and send a
pull request.
## Debian (and Debian-based distributions)
Add the Open-Argon apt repository:
```bash
sudo curl https://git.wbell.dev/api/packages/Open-Argon/debian/repository.key -o /etc/apt/keyrings/gitea-Open-Argon.asc
echo "deb [signed-by=/etc/apt/keyrings/gitea-Open-Argon.asc] https://git.wbell.dev/api/packages/Open-Argon/debian trixie main" | sudo tee -a /etc/apt/sources.list.d/gitea.list
sudo apt update
```
Then install:
```bash
sudo apt install argon
```
## Fedora (and Fedora-based distributions)
Import the signing key:
```bash
curl https://git.wbell.dev/Open-Argon/Chloride/raw/branch/main/gpg/argon-packages-public.gpg | sudo rpm --import -
```
Add the repository:
```bash
# on RedHat based distributions
dnf config-manager --add-repo https://git.wbell.dev/api/packages/Open-Argon/rpm.repo
# Fedora 41+ (DNF5)
dnf config-manager addrepo --from-repofile=https://git.wbell.dev/api/packages/Open-Argon/rpm.repo
```
Then install:
```bash
sudo dnf install argon
```
## Windows
There's no package manager distribution yet (no winget/chocolatey), but a Windows setup
executable is built for every release.
## macOS (Homebrew)
Homebrew is the recommended way to install on macOS, supporting both Apple Silicon and
Intel:
```bash
brew tap open-argon/argon https://git.wbell.dev/Open-Argon/homebrew-open-argon
brew install argon
```
## Building from source
If none of the above work for you, see [Building from source](../tooling/building-from-source/README.md).
## Next steps
Once `argon` is installed, head to [Your first program](first-program/README.md).
+56
View File
@@ -0,0 +1,56 @@
# Your first program
Create a file called `hello.ar`:
```
term.log("Hello, world!")
```
Run it with the `argon` interpreter:
```bash
argon hello.ar
```
You should see:
```
Hello, world!
```
## A quick tour
Argon files use the `.ar` extension. Comments start with `#`:
```
# this is a comment
let name = "world"
term.log(`Hello, $(name)!`)
```
Notice the backtick string above — this is a **template string**, and anything inside
`$( ... )` is evaluated as Argon code and interpolated into the string. See
[Strings](../../language/strings/README.md) for more.
Blocks in Argon are introduced with the `do` keyword rather than braces:
```
let add(a, b) = do
return a + b
let x = 5
if (x > 3) do
term.log("big")
else do
term.log("small")
```
Whitespace/indentation is not significant for parsing (the `do ... ` block continues until
the parser determines it's finished based on structure), but you should still indent
consistently for readability — see the examples throughout this documentation.
## Next steps
- [Variables and `let`](../../language/variables/README.md)
- [Functions](../../language/functions/README.md)
- [Control flow](../../language/control-flow/README.md)
View File
Whitespace-only changes.
+20
View File
@@ -0,0 +1,20 @@
# Control flow
Argon has the control flow constructs you'd expect from a C-family / scripting language:
- [`if` / `else`](if/README.md)
- [`while` loops](while/README.md)
- [`for` loops and iterators](for/README.md)
- [`break` and `continue`](break-continue/README.md)
All of these use `do` blocks instead of curly braces. A condition is always wrapped in
parentheses:
```
if (x > 0) do
term.log("positive")
```
A single-statement body doesn't strictly need `do` in every case (see
[`factorial.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/factorial.ar), where `if (n) return x*factorial(n)`
has no `do`), but using `do` for multi-statement bodies is required.
@@ -0,0 +1,33 @@
# `break` and `continue`
`break` exits the nearest enclosing loop; `continue` skips to the next iteration.
```
let f() = do
let x = 10
let i = 0
while (i < 100) do
i = i + 1
if (i > (x * 2)) break
if (i > x) continue
term.log(i)
term.log(i, x)
let g() = f()
g()
```
(from
[`loop_continue_and_break_test.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/loop_continue_and_break_test.ar))
This example logs `1` through `10` (stopping the `term.log(i)` calls once `i > x`, via
`continue`), then keeps looping silently until `i` exceeds `x * 2`, at which point `break`
exits the loop entirely and the final `term.log(i, x)` runs — printing `21 10`.
Both keywords work inside `for` loops too, in exactly the same way.
## Next
- [Functions](../../functions/README.md)
+74
View File
@@ -0,0 +1,74 @@
# `for` loops and iterators
## Basic syntax
```
for (x in 0 until 1e7) do
...
```
(from [`range_test.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/range_test.ar))
`for (item in iterable) do ...` iterates over anything **iterable** — arrays, ranges,
strings, dictionaries, or any custom object that implements the iterator protocol
described below.
```
for (item in [1, 2, 3]) do
term.log(item)
```
## Ranges
`a until b` produces a range you can loop over. The standard library also exposes a
`range(...)` function (used e.g. in
[`map_filter_sort.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/map_filter_sort.ar) as
`range(-1000000, 1000000)`), which is the built-in `range` type
(`ARGON_RANGE_ITERATOR_TYPE`) constructed directly.
## The iterator protocol
Any object can be made iterable by implementing two dunder methods:
- `__iter__(self)` — returns an **iterator** object.
- `__next__(self)` — called repeatedly on the iterator; each call returns the next value,
or throws `StopIteration()` once exhausted.
Here's a full custom range implementation from the test suite:
```
class custom_range_iterator do
this.__init__(self, stop) = do
self.current = 0
self.stop = stop
this.__next__(self) = do
if (self.stop <= self.current) do
throw StopIteration()
let result = self.current
self.current = self.current + 1
return result
class custom_range do
this.__init__(self, stop) = do
self.stop = stop
this.__iter__(self) = custom_range_iterator(self.stop)
for (x in custom_range(1e4)) do
for (y in custom_range(1e3)) do
...
```
(from [`custom_range.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/custom_range.ar))
`StopIteration` is one of the built-in system exceptions (see
[Errors and exceptions](../../error-handling/README.md)) and is how iterators signal "no
more values" — it's caught internally by the `for` loop machinery, not something you
usually need to catch yourself.
## Nested loops
Loops can be nested arbitrarily, as shown in the `custom_range` example above.
## Next
- [`break` and `continue`](../break-continue/README.md)
+44
View File
@@ -0,0 +1,44 @@
# `if` / `else`
```
let x = 5
if (x > 10) do
term.log("big")
else if (x > 0) do
term.log("small positive")
else do
term.log("zero or negative")
```
## Single-statement form
If the body is a single statement, `do` can be omitted:
```
let factorial(x) = do
let n = x - 1
if (n) return x*factorial(n)
return 1
```
(from [`factorial.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/factorial.ar))
## Truthiness
Any value can be used as a condition. `0`, `null`, `false`, and empty strings/collections
are falsy; everything else is truthy. In the `factorial.ar` example above, `if (n)` is
shorthand for "if `n` is not zero".
## Ternary expression
For simple conditional *expressions* (not statements), see the ternary operator described
in [Operators](../../operators/README.md#ternary-conditional-expression):
```
let sign = a < b ? -1 : a > b ? 1 : 0
```
## Next
- [`while` loops](../while/README.md)
+44
View File
@@ -0,0 +1,44 @@
# `while` loops
```
let i = 0
while (i < 10) do
term.log(i)
i += 1
```
A `while` loop with a truthy constant condition (e.g. a non-zero length) can be used to
drain a collection:
```
import "../stdlib/random" expose random
let x = []
let i = 0
while (i < 1e6) do
x.append(i)
i = i + 1
let y = []
while (x.length) do # loops while x.length is truthy (non-zero)
let result = x.pop(random.int(0, x.length - 1))
y.append(result)
```
(from [`array_pop.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/array_pop.ar))
## `while` as an expression-friendly loop
`while` conditions are parenthesized expressions, so they can contain assignments,
function calls, comparisons, etc. — anything that evaluates to a value.
## Infinite loops
There's no dedicated `loop` keyword; use `while (true) do ...` and `break` to exit (see
[`break` and `continue`](../break-continue/README.md)). The test suite has a file named
[`foreverloop.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/foreverloop.ar) demonstrating this pattern.
## Next
- [`for` loops and iterators](../for/README.md)
+155
View File
@@ -0,0 +1,155 @@
# Functions
## Declaring a function
Functions are declared with `let`, just like variables — a function is a value:
```
let add(a, b) = do
return a + b
term.log(add(2, 3)) # 5
```
For a single-expression body, you can skip `do` and `return` entirely:
```
let square(x) = x * x
```
This is the same pattern used for one-line class methods (see
[Classes and objects](../classes/README.md)).
## Anonymous (lambda) functions
Functions don't need a name. An anonymous function is written the same way, just without
an identifier before the parameter list:
```
term.log(()=10) # a zero-argument anonymous function returning 10
term.log((x)=10)
term.log((x,y)=10)
term.log((x,y,z)=10)
# named versions, for comparison:
term.log(a()=10)
term.log(b(x)=10)
```
(from [`anonymous_function.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/anonymous_function.ar))
Anonymous functions are commonly passed directly as arguments, e.g. to `array.map`:
```
term.log(
array(range(-1000000, 1000000))
.map((val) = val * val)
.filter((val) = val < 10000)
.sort((a, b) = a < b ? -1 : a > b ? 1 : 0)
)
```
(from [`map_filter_sort.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/map_filter_sort.ar) — this also shows
method chaining on arrays; see [Arrays](../arrays/README.md).)
## Default arguments
```
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))
## Variadic arguments: `*args` and `**kwargs`
A function can collect any extra positional arguments into an array with `*args`, and any
extra keyword arguments into a dictionary with `**kwargs`:
```
let f(*args, **kwargs) = do
term.log(args, kwargs)
f("Hello world", *[1, 2, 3], **{x: 1, y: 5, z: 7})
```
(from [`argument_unpacking.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/argument_unpacking.ar)) — note that
`*` and `**` are also used at the **call site** to unpack an existing array/dictionary into
positional/keyword arguments, exactly like the definition-site collectors.
### Mixing required, default, `*args`, and `**kwargs`
```
let f(x, a=null, *args, **kwargs) = do
return `x=$(x), a=$(a), args=$(args), kwargs=$(kwargs)`
term.log(f(1))
term.log(f(1, 2))
term.log(f(1, 2, 3))
term.log(f(a=2, *["this should go to x"]))
term.log(f(1, a=2, **["this should go to kwargs"]))
term.log(f(1, a=2, **{wow: "this should go to kwargs"}))
term.log(f(a=2, **{x: "this should go to x"}))
```
(from
[`test_mixed_args_defaults_and_unpacking.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/test_mixed_args_defaults_and_unpacking.ar))
This shows that keyword arguments can fill in named parameters like `x` even when passed
via `**{x: ...}`, and that unpacking a plain array with `**` still works, filling in
`kwargs` positionally in the array's order.
## Recursion
Functions can call themselves normally:
```
let factorial(x) = do
let n = x - 1
if (n) return x * factorial(n)
return 1
```
(from [`factorial.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/factorial.ar))
## Closures
Functions capture variables from their enclosing scope:
```
let f() = do
let x = 10
let i = 0
while (i < 100) do
i = i + 1
...
let g() = f()
g()
```
(from
[`loop_continue_and_break_test.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/loop_continue_and_break_test.ar))
## Functions as methods on built-in types
You can attach a method directly to a built-in type, e.g. `string`:
```
string.cool(self) = do
term.log(self, self.length)
return 10
'hello world'.cool()
string.cool('goodbye world')
```
(from [`class_method.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/class_method.ar)) — note the two
equivalent call styles: as an instance method (`'hello world'.cool()`) or as an explicit
call on the type passing `self` (`string.cool('goodbye world')`).
## Next
- [Classes and objects](../classes/README.md)
- [Error handling](../error-handling/README.md)
+119
View File
@@ -0,0 +1,119 @@
# Operators
## Arithmetic
| Operator | Meaning |
|----------|-----------------|
| `+` | addition |
| `-` | subtraction / unary negation |
| `*` | multiplication |
| `/` | division |
| `//` | floor division |
| `%` | modulo |
| `**` | exponent (based on the `EXPONENT_FUNCTION` builtin) |
```
term.log(1 + 2) # 3
term.log(7 // 2) # 3
term.log(7 % 2) # 1
```
Every arithmetic operator is backed by a global function you can also call directly, and
which classes can override by implementing the matching dunder method (e.g. `__add__`):
```
term.log(add(1, 2)) # 3
term.log(subtract(5, 2)) # 3
term.log(multiply(2, 3)) # 6
term.log(divide(6, 2)) # 3
term.log(floor_divide(7, 2))# 3
term.log(modulo(7, 2)) # 1
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).
## Comparison
| Operator | Meaning |
|----------|---------|
| `==` | equal |
| `!=` | not equal |
| `<` | less than |
| `<=` | less than or equal |
| `>` | greater than |
| `>=` | greater than or equal |
These also have global function equivalents: `equal`, `not_equal`, `less_than`,
`less_than_equal`, `greater_than`, `greater_than_equal` — and each is backed by a dunder
method (`__equal__`, `__less_than__`, etc.) that a class can override, e.g. the standard
`number` and `string` types both implement their own comparison dunders.
## Logical operators
```
a && b # logical AND
a || b # logical OR (used in stdlib code, e.g. path.ar's `while ("//" in p)` style checks)
!a # logical NOT
```
See [`my_first_calculator.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/my_first_calculator.ar) for repeated
use of `&&` in condition chains.
## The `in` operator
Test membership in a string, array, or dictionary:
```
term.log("ell" in "hello") # true, substring check
term.log(3 in [1,2,3]) # true
term.log("key" in {key: 1}) # true, checks dictionary keys
```
This is backed by the `__contains__` dunder method, which is implemented on strings,
arrays, and dictionaries — and can be implemented on your own classes too.
## Ternary conditional expression
```
let result = a < b ? -1 : a > b ? 1 : 0
```
This is the pattern used in
[`map_filter_sort.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/map_filter_sort.ar) to write a comparator
function in one line.
## String concatenation
`+` also works on strings:
```
term.log("hello " + "world")
```
## Ranges
`a until b` (as seen in
[`range_test.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/range_test.ar)) produces an iterable range, most
commonly used with `for`:
```
for (x in 0 until 1e7) do
...
```
See [`for` loops](../control-flow/for/README.md) for more on ranges and the built-in
`range()` function.
## Unary operators
```
-x # negation
!x # logical not
```
## Next
- [Control flow](../control-flow/README.md)
+118
View File
@@ -0,0 +1,118 @@
# Strings
Strings can be written with single or double quotes:
```
let a = "hello"
let b = 'hello'
```
## Template strings
Backtick strings support interpolation via `$( ... )`, where anything inside the
parentheses is evaluated as Argon code:
```
let wow = "this is cool"
term.log(
`hello world
$(
do
term.log("wow")
return wow
)`
)
```
(from [`templates.ar`](../../../chloride/tests/templates.ar)) — this demonstrates that the
interpolated expression can be an entire `do` block with side effects, not just a simple
variable.
A simpler, more common case:
```
let name = "world"
term.log(`Hello, $(name)!`)
```
Template strings also support unicode escapes like `\u1324`:
```
throw MyError(`hel\u1324lo`)
```
(from [`error_system.ar`](../../../chloride/tests/error_system.ar))
## Escape sequences
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`](../../../chloride/stdlib/json/init.ar) for the full escape table
used when parsing JSON strings — the same escapes are valid in Argon string literals).
## Indexing and slicing
Strings support the same indexing/slicing syntax as arrays — see
[Arrays](../arrays/README.md#indexing-and-slicing) for the full slice syntax
(`s[1:]`, `s[:5]`, `s[::-1]`, negative indices, step values, etc).
```
let s = "hello"
term.log(s[0]) # "h"
term.log(s[-1]) # "o"
term.log(s[1:3]) # "el"
```
## Built-in string methods
Strings support (at minimum) the following built-in methods and properties, based on the
interpreter's string type implementation:
| Member | Description |
|---|---|
| `.length` | number of characters |
| `.upper()` | uppercase copy |
| `.lower()` | lowercase copy |
| `.title()` | title-cased copy |
| `.replace(old, new)` | replace all occurrences |
| `.split(sep)` | split into an array of strings |
| `.strip()` | strip surrounding whitespace |
| `.index_of(sub)` | index of a substring |
| `.chr()` / `.ord()` | character/code-point conversion |
| `in` | substring membership test (`"ell" in "hello"`) |
| `[start:stop:step]` | slicing |
```
let __starts_with__(s, prefix) = do
if (prefix.length > s.length) do
return false
return s[0:prefix.length] == prefix
```
(from [`stdlib/path/init.ar`](../../../chloride/stdlib/path/init.ar), showing `.length` and
slicing used together)
## Comparing strings
Strings support the usual comparison operators (`==`, `!=`, `<`, `<=`, `>`, `>=`), which
compare lexicographically.
## Joining strings
Arrays of strings can be joined with `.join(sep)` — see
[Arrays](../arrays/README.md#join).
## Converting to a string
Every object has a `__string__()` method used for display/printing, and calling
`string(value)` converts any value to its string form:
```
term.log(string(123)) # "123"
```
## Next
- [Arrays](../arrays/README.md)
+89
View File
@@ -0,0 +1,89 @@
# Variables
Declare a variable with `let`:
```
let x = 10
let name = "chloride"
let pi = 3.14159
```
Once declared, you can reassign without `let`:
```
let x = 10
x = 20
x = x + 1
```
Argon also has compound assignment operators:
```
let i = 0
i += 1 # i = i + 1
i -= 1
i *= 2
i /= 2
```
(See [`iteration.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/iteration.ar) in the test suite for `+=` used
in a loop counter.)
## Dynamic typing
Argon is dynamically typed — a variable can hold any type, and the type isn't declared up
front:
```
let value = 10
value = "now I'm a string"
value = [1, 2, 3]
```
## `null`
The absence of a value is `null`:
```
let x = null
```
## Everything is an object
Unlike some older/simpler interpreters, in Chloride **every value is an object** — numbers,
strings, booleans, functions, and `null` all have an underlying type and can have methods
called on them:
```
term.log((5).__string__())
term.log("hi".length)
```
You can find a value's type with the built-in `type()` function:
```
term.log(type(5)) # number
term.log(type("hi")) # string
term.log(type([1,2])) # array
```
and check whether something is an instance of a type (or class) with `is_instance`:
```
term.log(is_instance(5, number)) # true
term.log(is_instance("hi", string)) # true
```
## Scope
Variables declared with `let` are scoped to the block/function they're declared in.
Functions form closures over the scope they were defined in — see
[Functions](../functions/README.md) for details, and
[`loop_continue_and_break_test.ar`](https://git.wbell.dev/Open-Argon/Chloride/src/commit/8e1ee06b88200ab112cf34e49efe969030ea435c/tests/loop_continue_and_break_test.ar)
for an example of a nested function (`g`) calling an outer function (`f`) that itself
closes over local variables.
## Next
- [Operators](../operators/README.md)
- [Control flow](../control-flow/README.md)
-119
View File
@@ -1,119 +0,0 @@
# ARGON 3 BETA 1.0
This is the specification on how to create an Argon interpreter.
This specification should be used as a guildline, and is subject to change for later versions.
Later updates for Argon 3 should be backwards compatable (where possible) with code designed for older versions
of the interpreter.
The Argon 3 interpreter is not intentionally designed to understand code written for Argon 1 and/or 2, but may
follow some design patterns found in those interpreters.
Argon 3 is a programming language primarily designed for maths computation, it is designed to use techniques and
rules set in maths. It's designed to be easy for mathematicians to write and understand algorithms in.
(e.g. `f(x) = x^2` to set a function)
reused variables, and infomation for use in understanding the pseudo REGEX:
- NAME = [a-zA-Z][a-za-z0-9]\*
- spaces used in the pseudo REGEX should be taken as 1 or many spaces.
- there can be 0 or more spaces around any of the pseudo REGEX
## set variable
`(let or nothing) {NAME} = {ANY}`
let variables will set variables. at the end of a opperation (e.g. if, while, or function) drop the
variable stack.
having no verb at the start suggests the program would like to edit a variables from a different stack.
if there is no variable found in the other stacks, then it sets one in the current stack as a let.
example:
```javascript
let x = 10
y = 20
let z = x + y
```
setting variables returns the value, which can be used.
example:
```javascript
if ((x = 10) > 5) do
term.log(x, 'is bigger than 5')
```
## functions
`(let or nothing) {NAME}({PARAMS}) = {CODE}`
the starting verb follows the rules set by [set variable](#set-variable).
function can be called by using its name followed by brackets with the params.
example:
```javascript
let f(x) = x^2 + 2*x + 1
term.log('f(10) =', f(10))
```
output:
```javascript
f(10) = 121
```
if the function does not return, then the value returned is `null`
## wrap
```
do
{CODE}
```
a wrap encloses code indented in after the word `do` its used to create a new scope, so variables set from
inside the wraps scope are deleted once the wrap is finished.
example:
```javascript
let name = null
do
name = input('name: ')
let age = input('age: ')
log('you are', age, 'years old!')
term.log('hello', name)
term.log('we do not know your age anymore because it got deleted when the wrap finished.')
```
A wrap, unless specificifed otherwise, can have a return value. This value can be used as the value of the wrap.
example:
```javascript
let password = do
let password = passwordInput("set password: ")
while (password.length < 8) do
term.log("password must be longer then 8 characters!")
password = passwordInput("set password: ")
return password
term.log("your password is", password)
```
If the wrap does not take a return value, then the wrap passes the return value back to a parent wrap.
## Comments
`#{COMMENT}`
Comments allow the programmer to write a message into their code, without the message being processed by the computer.
@@ -1,79 +0,0 @@
# Variable Assignment
To define a variable in Argon, you can use either the `let` keyword or simply assign a value to a variable name without using `let`. Here's how you can define a variable using both methods:
Method 1: Using the `let` keyword
To define a variable using the `let` keyword, you need to specify the variable name and its initial value. Here's an example:
```javascript
let x = 10
```
In this example, we define a variable named `x` and initialise it with a value of `10`. The `let` keyword tells the Argon interpreter to define the variable on the current stack. If `x` already exists in the current stack, then it will throw a `Name Error` of `Name Error: variable "x" already exists`.
Method 2: Assigning a value to a variable name
You can also define a variable by simply assigning a value to a variable name without using `let`. Here's an example:
```javascript
x = 10
```
In this example, we define a variable named `x` and initialise it with a value of `10`. If the variable does not exist on any of the stacks below the current, then it will be created on the current stack. If the variable already exists on any of the stacks below the current, then it will be replaced on the highest stack that contains the variable.
It's worth noting that if you define a variable without using let, it will be created on the current stack, and if you define a variable using let, it will also be created on the current stack but won't be replaced on a lower stack. This means that variables defined with let are only accessible within the current scope and cannot be accessed from nested scopes.
Here's an example that demonstrates this:
```javascript
let x = 10
do
let x = 20
term.log(x) # Output: 20
term.log(x) # Output: 10
```
In this example, we define a variable `x` with a value of `10` using `let`. We then create a new block using the `do` keyword, which creates a new scope. Within this scope, we define a new variable `x` with a value of `20` using let. When we log the value of `x` using `term.log` within the scope, we get the value `20`. However, when we log the value of `x` outside of the scope, we get the value `10`, which is the value of the `x` variable defined in the outer scope. This demonstrates how variables defined with `let` are only accessible within the current scope and cannot be accessed from nested scopes.
```javascript
let x = 10
do
x = 20
term.log(x) # Output: 20
term.log(x) # Output: 20
```
In this example, we define a variable `x` with a value of `10` using `let`. We then create a new block using the `do` keyword, which creates a new scope. Within this scope, we re-assign the value of `x` to `20` without using `let`. When we log the value of `x` using `term.log` within the scope, we get the value `20`. When we log the value of x outside of the scope, we also get the value `20`, because the re-assignment of `x` in the nested scope affects the value of `x` in the outer scope. This demonstrates how re-assigning a variable without using let will replace the value of the variable in the current scope, and will also affect the value of the variable in any enclosing scopes.
# Function Assignment
`let` works exactly the same way as it does in variable assignment.
```javascript
let square(x) = do
return x * x
```
In this example, we define a function named `square` with a parameter `x`. The function body uses a `do` block to group multiple statements together, and then returns the result of `x * x`. Note that the `return` keyword is used to indicate that the value of the expression `x * x` is the result of the function. This syntax is useful when you need to group multiple statements together or do some additional processing before returning a result.
```javascript
let square(x) = x * x
```
In this example, we define a function named `square` with a parameter `x`. The function body simply multiplies `x` by itself and returns the result. This syntax is more concise and easier to read when you have a simple expression that can be evaluated in a single line.
you can define an anonymous function using a syntax similar to defining a named function, but without providing a name. Here's an example:
```javascript
let square = (x) = x * x
```
In this example, we define an anonymous function that takes one parameter `x` and returns the result of `x * x`. We store this function in a variable named `square`.
Anonymous functions are useful when you need to define a small, one-off function that you don't need to use again later in your code. They can be passed as arguments to other functions, assigned to variables, and used wherever you would use a named function.
Both of these ways will work the same way when you call the function with an argument. For example, if you call the function `square` with an argument of `4`, you will get a result of `16`:
```javascript
let result = square(4)
term.log(result) # Output: 16
```
In this example, we call the square function with an argument of `5` and store the result in a variable named `result`. We log the value of `result` to the console using `term.log`.