Skip to content

Commit

Permalink
Update docs. Add Incomplete/Planned feature tags.
Browse files Browse the repository at this point in the history
  • Loading branch information
fubark committed Sep 19, 2023
1 parent 888198e commit f95cd18
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 34 deletions.
5 changes: 4 additions & 1 deletion docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
## Using Cyber.
The best way to get started with Cyber is to try using it for scripting or for a project. This lets you get a taste of the language and in the process learn more about it. If you run into a bug or notice something that is inconsistent with the [docs](https://fubark.github.io/cyber), please report an issue.

## Read the docs.
The [docs](https://fubark.github.io/cyber) contains an overview of all the features currently in the language as well as incomplete/planned features.

## Building Cyber.
The next step you might take is building Cyber on your own machine. You'll learn how to test and build the source which is useful if you want to make code contributions. See [Building](https://github.com/fubark/cyber/blob/master/docs/build.md).

Cyber is written in Zig. One way to learn Zig is to fix some [problem sets](https://github.com/ratfactor/ziglings). If you know C, you'll pick up Zig quickly.
Cyber is written in Zig and C. One way to learn Zig is to fix some [problem sets](https://github.com/ratfactor/ziglings). If you know C, you'll pick up Zig quickly.

## Language Design.
After v1.0 of Cyber, the language won't be changing much, at least that is the goal. So if you have a feature idea for the language or you don't like how something is designed, now would be a good time to propose it. You can use the [docs](https://fubark.github.io/cyber) as a canonical reference to the current language features.
Expand Down
2 changes: 2 additions & 0 deletions docs/hugo/content/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ Cyber is a fast, efficient, and concurrent scripting language. To learn more abo

Cyber is easy to learn. These docs provide a reference manual for the language. You can read it in order or jump around using the navigation.

You may come across features that are marked `Incomplete` or `Planned`. This is because the docs are written as if all features have been completed already.

## Hello World.
```cy
import m 'math'
Expand Down
8 changes: 8 additions & 0 deletions docs/hugo/content/docs/toc/aot-jit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: "AOT/JIT"
bookFlatSection: true
weight: 13
---

# AOT and JIT
> _Planned Feature_
11 changes: 9 additions & 2 deletions docs/hugo/content/docs/toc/concurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,18 @@ func bar():
var fiber = coinit foo()
coresume fiber
```
`coresume` also returns the resulting value. In a future version of Cyber, you will be able to yield back results and pass values back when resuming.
`coresume` also returns the resulting value.
```cy
func foo():
return 123

var fiber = coinit foo()
print(coresume fiber) -- '123'
```

`coyield` can return a value back to `coresume`.
> _Planned Feature_
Use `Fiber.status()` to get the current state of the fiber.
```cy
func foo():
Expand All @@ -63,7 +67,10 @@ print fiber.status() -- '#done'
The main execution context is a fiber as well. Once the main fiber has finished, the VM is done and control is returned to the host.

## Gas mileage.
> _Planned Feature_
## Async.
> _Planned Feature_
## Multi-thread.
## Multi-thread.
> _Planned Feature_
4 changes: 3 additions & 1 deletion docs/hugo/content/docs/toc/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ for 0..10 each i:

## Matching.
Matching is similar to a switch statement. The expression to the right of `match` is evaluated and execution jumps to the declared case with the matching value. Multiple cases can be grouped together using a comma separator. An optional `else` fallback case is executed when no other cases were matched.
> _Incomplete: Not all types can be used in the case clause such as ranges._
```cy
var val = 1000
match val:
Expand All @@ -138,4 +139,5 @@ match val:
## Try/Catch.
The `try catch` statement, `try else` and `try` expressions provide a way to catch a throwing error and resume execution in a different branch. Learn more about [Error Handling]({{<relref "/docs/toc/errors">}}).

## Deferred Execution.
## Deferred Execution.
> _Planned Feature_
6 changes: 4 additions & 2 deletions docs/hugo/content/docs/toc/data-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ a = 0b1010 -- binary.
a = 0u'🐶' -- UTF-8 rune.
```

Arbitrary values can be converted to a `int` using the type as a function.
Arbitrary values can be converted to a `int` using the type as a function.
```cy
var a = '123'
var b = int(a)
Expand Down Expand Up @@ -68,12 +68,13 @@ var b = float(a)
```

### Big Numbers.
Big numbers will be supported in a future version of Cyber.
> _Planned Feature_
## Strings.
The `string` type represents a sequence of UTF-8 codepoints, also known as `runes`. Each rune is stored internally as 1-4 bytes and can be represented as an `int`. Under the hood, Cyber implements 6 different internal string types to optimize string operations, but the user just sees them as one type and doesn't need to care about this detail under normal usage.

Strings are **immutable**, so operations that do string manipulation return a new string. By default, small strings are interned to reduce memory footprint. To mutate an existing string, use the [StringBuffer](#string-buffer).
> _Planned Feature_
A string is always UTF-8 validated. [rawstrings](#rawstring) outperform strings but you'll have to validate them and take care of indexing yourself.

Expand Down Expand Up @@ -388,6 +389,7 @@ map = {
Entries can also follow a `{}:` block.
This gives structure to the entries and has
the added benefit of allowing multi-line lambdas.
> _Planned Feature_
```cy
var colors = {}:
red: 0xFF0000
Expand Down
3 changes: 2 additions & 1 deletion docs/hugo/content/docs/toc/embedding.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ bookFlatSection: true
weight: 11
---

# Embedding.
# Embedding.
> _Planned Feature_
6 changes: 5 additions & 1 deletion docs/hugo/content/docs/toc/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ weight: 7
Cyber provides error values and try/catch mechanisms to handle expected errors. For unexpected errors, panics can be used as a fail-fast mechanism to abort the currently running fiber.

## Error value.
The `error` type is a primitive that contains either an enum value or a symbol value. Errors can wrap symbols for convenience but the underlying ID value won't be consistent. Use your own enums if you want reliable ID values. In a future version of Cyber, you'll be able to attach an optional payload value.
The `error` type is a primitive that contains either an enum value or a symbol value. Errors can wrap symbols for convenience but the underlying ID value won't be consistent. Use your own enums if you want reliable ID values.
```cy
-- Shorthand for creating an error value with a symbol.
var err = error.Oops
Expand All @@ -23,6 +23,10 @@ type MyError enum:
-- Creates an error that wraps an enum value.
err = error(MyError.boom)
```

You can attach an optional payload value to an error.
> _Planned Feature_

Since errors are primitives, they can be compared using the `==` operator.
```cy
if err == error.Oops:
Expand Down
2 changes: 2 additions & 0 deletions docs/hugo/content/docs/toc/ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ lib.add(123, 321)
If the path argument to `bindLib` is just a filename, the search steps for the library is specific to the operating system. Provide an absolute (eg. '/foo/mylib.so') or relative (eg. './mylib.so') path to load from a direct location instead. When the path argument is `none`, it loads the currently running executable as a library allowing you to bind exported functions from the Cyber CLI or your own embedded Cyber app/runtime.

When using `CFunc` or `CStruct` declarations, [symbols]({{<relref "/docs/toc/data-types#symbols">}}) are used to represent default type mappings from Cyber to C and back:
> _Incomplete: This is not the final API for dynamically loading and interfacing with C libraries. The plan is to parse a subset of C headers to bind to Cyber types and functions._
| Binding | Cyber | C | Details |
| -- | -- | -- | -- |
| #bool | bool | bool |
Expand Down
13 changes: 12 additions & 1 deletion docs/hugo/content/docs/toc/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ weight: 4
In Cyber, there are first-class functions (or function values) and static functions.

## Static Functions.
Static functions are not initally values themselves. They allow function calls to be optimal since they don't need to resolve a dynamic value.
Static functions are not initially values themselves. They allow function calls to be optimal since they don't need to resolve a dynamic value.

Static functions are declared with the `func` keyword and must have a name.
```cy
Expand Down Expand Up @@ -123,6 +123,15 @@ func foo():
print a -- Compile Error: Can't reference local from static function.
```
## Named Parameters.
> _Planned Feature_
## Optional Parameters.
> _Planned Feature_
## Variadic Parameters.
> _Planned Feature_
## Function Calls.
The straightforward way to call a function is to use parentheses.
Expand All @@ -136,6 +145,7 @@ var d = dist(x0: 10, x1: 20, y0: 30, y1: 40)
```
The shorthand method for calling functions omits parentheses and commas. This only works for functions that accept parameters:
> _Incomplete: Only the most trivial cases work with the shorthand method. The case with operators being separated by spaces might not end up being implemented._
```cy
var d = dist 100 100 200 200 -- Calls the function `dist`.
Expand Down Expand Up @@ -168,6 +178,7 @@ a = myFunc 'hello' (otherFunc 1+2 'world')
```

The call expression block continues to add arguments from the block's body. If arguments are omitted from the initial call expression they can be added inside using the `..` syntax. Arguments mapped to named parameters have a key value syntax separated by a `:`. All other arguments are added into a list and passed as the last argument.
> _Planned Feature_
```cy
foo(123):
..func ():
Expand Down
46 changes: 35 additions & 11 deletions docs/hugo/content/docs/toc/memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,51 @@ Cyber provides memory safety by default.

## ARC.
Cyber uses ARC or automatic reference counting to manage memory.
ARC has less overhead compared to a tracing garbage collector and reduces GC pauses which makes Cyber suitable for realtime applications. ARC is also deterministic unlike tracing GCs which usually run on a separate thread(s).
ARC is deterministic and has less overhead compared to a tracing garbage collector. Reference counting distributes memory management, which reduces GC pauses and makes ARC suitable for realtime applications. One common issue in ARC implementations is reference cycles which Cyber addresses with [Weak References](#weak-references) and it's very own [Cycle Detection](#cycle-detection).

### Reference Counting.
In Cyber, there are [primitive and object]({{<relref "/docs/toc/data-types">}}) values. Primitives don't need any memory management, since they are copied by value and no heap allocation is required (with the exception of primitives being captured by a [closure]({{<relref "#closures">}})).

Objects are managed by ARC and each object has their own reference counter. Upon creating a new object, it receives a reference count of 1. When the object is copied, it's `retained` and the reference count increments by 1. When an object reference is no longer reachable in the current stack frame, it is `released` and the reference count decrements by 1. For example, at the end of a function call, all the local variables (that can potentially be an object reference) in the function are no longer reachable so they are released.
Object are managed by ARC and each object has its own reference counter. Upon creating a new object, it receives a reference count of 1. When the object is copied, it's `retained` and the reference count increments by 1. When an object value is removed from it's parent or is no longer reachable in the current stack frame, it is `released` and the reference count decrements by 1.

Once the reference count reaches 0 and the object (eg. lists and maps) also contains child references, each child reference is released thereby decrementing their reference counts by 1. Afterwards, the object is freed from memory.
Once the reference count reaches 0 and the object (eg. List or Map) also contains child references, each child reference is released thereby decrementing their reference counts by 1. Afterwards, the object is freed from memory.

### Optimizations.
Cyber's compiler can reduce the number of retain/release ops since it can infer value types even though they are dynamically typed to the user. Arguments passed to functions are only retained depending on the analysis from the callsite. ARC expressions do not retain temporary values unless it is required for the happy path. In the rare case that a temporary value is released before it is used, the value behaves as if it was the `none` value.
The compiler can reduce the number of retain/release ops since it can infer value types even though they are dynamically typed to the user. Arguments passed to functions are only retained depending on the analysis from the callsite.

### Closures.
When primitive variables are captured by a [closure]({{<relref "/docs/toc/functions#closures">}}), they are boxed and allocated on the heap. This means they are managed by ARC and are cleaned up when there are no more references to them.
When primitive variables are captured by a [closure]({{<relref "/docs/toc/functions#closures">}}), they are boxed and allocated on the heap. This means they are managed by ARC and cleaned up when there are no more references to them.

### Fibers.
[Fibers]({{<relref "/docs/toc/concurrency#fibers">}}) are freed by ARC just like any other object. Once there are no references to the fiber, it begins to release it's child references by unwinding its call stack.
[Fibers]({{<relref "/docs/toc/concurrency#fibers">}}) are freed by ARC just like any other object. Once there are no references to the fiber, it begins to release it's child references by unwinding it's call stack.

## Heap.
Many object types in Cyber are small enough to be at or under 40 bytes. To take advantage of this, Cyber can reserve object pools to quickly allocate and free these small objects with very little bookkeeping. Bigger objects are allocated and managed by `mimalloc` which has proven to be a fast and reliable general purpose heap allocator.

## Weak Refs.

## Cycle Detection.
Many object types in Cyber are small enough to be at or under 40 bytes. To take advantage of this, Cyber can reserve object pools to quickly allocate and free these small objects with very little bookkeeping. Bigger objects are allocated and managed by `mimalloc` which has proven to be a fast and reliable general-purpose heap allocator.

## Weak References.
> _Planned Feature_
## Cycle Detection.
The cycle detector is also considered a GC and frees abandoned objects managed by ARC. Although weak references can remove cycles altogether, Cyber does not force you to use them and provides a manual GC as a one-time catch all solution.
> _Incomplete Feature: Only the main fiber stack is cleaned up at the moment._
To invoke the GC, call the builtin function: `performGC`.
```cy
func foo():
-- Create a reference cycle.
var a = []
var b = []
a.append(b)
b.append(a)

var res = performGC()
-- Cycle still alive in the current stack so no cleanup is done.
print res['numCycFreed'] -- Output: 0
print res['numObjFreed'] -- Output: 0

foo()
var res = performGC()
-- `a` and `b` are no longer reachable, so the GC does work.
print res['numCycFreed'] -- Output: 2
print res['numObjFreed'] -- Output: 2
```
94 changes: 89 additions & 5 deletions docs/hugo/content/docs/toc/metaprogramming.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,105 @@ weight: 10
# Metaprogramming.

## Operator overloading.
All operators are implemented as object methods.
> _Incomplete: Not all operators have transitioned to the method paradigm._
Normally this would impact performance, but Cyber's compiler generates specialized bytecode ops for builtin types like `int` and `float`. The VM performs inline caching at runtime to eliminate the overhead of evaluating operators on dynamic operands.

To overload an operator for a object type, declare `$prefix`, `$infix`, `$postfix` methods:
> _Incomplete: Although operator overloading is supported in the VM and builtin types use it, it is not currently enabled for user types._
```cy
type Vec2 object:
x float
y float

func $infix+(self, o):
return Vec2{
x: x + o.x,
y: y + o.y,
}

func $prefix-(self):
return Vec2{ x: -x, y: -y }

var a = Vec2{ x: 1, y: 2}
var b = a + Vec2{ x: 3, y: 4 }
var c = -a
```

Some special operators have their own name:
```cy
type MyCollection object:
arr List

func $index(self, idx):
return arr[idx * 2]

func $setIndex(self, idx, val):
arr[idx * 2] = val

var a = MyCollection{ arr: [1, 2, 3, 4] }
print a[1] -- Prints `3`
```

A list of all supported operators:
* `$prefix~(_)`
* `$prefix-(_)`
* `$infix>(_, _)`
* `$infix>=(_, _)`
* `$infix<(_, _)`
* `$infix<=(_, _)`
* `$infix+(_, _)`
* `$infix-(_, _)`
* `$infix*(_, _)`
* `$infix/(_, _)`
* `$infix%(_, _)`
* `$infix^(_, _)`
* `$infix&(_, _)`
* `$infix|(_, _)`
* `$infix||(_, _)`
* `$infix<<(_, _)`
* `$infix>>(_, _)`
* `$index(_, _)`
* `$setIndex(_, _, _)`
* `$slice(_, _, _)`

## Custom operators.
> _Planned Feature_
## Magic functions.

### Calling a module symbol.
Declare a `<call>` function to allow invoking a module as a function. Currently, this is only available to builtin types like `float`.
### Call module.
Declare a `$call` function to allow invoking a module as a function.
> _Incomplete: Although $call function is supported in the VM and builtin modules use it, it is not currently enabled for user modules._
```cy
-- Type declarations are also modules.
-- Object types are also modules.
type Vec2 object:
x float
y float

func <call>(x float, y float) Vec2:
func $call(x float, y float) Vec2:
return Vec2{ x: x, y: y }

var v = Vec2(1, 2)
```

### Getter/Setter.
> _Planned Feature_
### Missing method.
Declare a `$missing` method as a fallback when a method was not found in an instance.
> _Planned Feature_
```cy
type A object:
func $missing(self, args...):
return args.len

var a = A{};
print a.foo() -- Output: '0'
print a.bar(1, 2) -- Output: '2'
```

## Reflection.
A `metatype` object references an internal type. Use the `typeof` builtin to get the `metatype` of a value.
```cy
Expand All @@ -43,9 +123,13 @@ func id(self) int
```

## Annotations.
> _Planned Feature_
## Runtime eval.
> _Planned Feature_
## Generics.
> _Planned Feature_
## Compile-time.
## Compile-time.
> _Planned Feature_
Loading

0 comments on commit f95cd18

Please sign in to comment.