176 lines
No EOL
3 KiB
Markdown
176 lines
No EOL
3 KiB
Markdown
# Persist
|
|
|
|
> **Warning**
|
|
>
|
|
> This project is in very early state of development, it is strictly unusable and you should not be expecting the project to ever produce a reliable product.
|
|
>
|
|
> For now, this repository is released publicly in the hope that someone might find interest in the ideas and implementations of the project.
|
|
|
|
---
|
|
|
|
## Description
|
|
|
|
A message oriented, dynamic, strongly typed scripting language with context serialization.
|
|
|
|
### Messages
|
|
|
|
The program can be seen as a collection of loaded actors all awaiting messages to process.
|
|
They can, in turn send messages to other actors.
|
|
|
|
This is like encapsulating function calls in serializable structures that are passed between objects.
|
|
|
|
### Dynamic
|
|
|
|
Persistence is meant to introduce dynamic loading behaviour, and allows for easy hotloading of new objects or types.
|
|
|
|
### Context serialization
|
|
|
|
The most distinct feature of persistence is that every object, including function logic is serializable.
|
|
This allows the runtime to export a resumable snapshot of a session.
|
|
|
|
---
|
|
|
|
## Examples
|
|
|
|
### Objects
|
|
|
|
strictly everything is somehow an object with properties:
|
|
functions, type declarations, modules...
|
|
|
|
```rs
|
|
|
|
/// type declaration
|
|
let Person = type{
|
|
name: string,
|
|
age: int,
|
|
};
|
|
|
|
/// Associating function is adding properties to the type
|
|
Person.new = fn(name: string, age: int): Person {
|
|
Person { name, age }
|
|
};
|
|
|
|
/// instructions can be ran in global scope
|
|
let bob = Person.new("bob", 25);
|
|
|
|
```
|
|
|
|
### Signals
|
|
|
|
Signals are sent from one object to another.
|
|
|
|
```rs
|
|
|
|
/// Signal declaration
|
|
let Present = sig[]: string;
|
|
|
|
Person|>Present = fn(self) {
|
|
"my name is "
|
|
+ self.name
|
|
+ ", I am "
|
|
+ self.age
|
|
};
|
|
|
|
/// Sending a signal to an object
|
|
bob<|Present{};
|
|
|
|
```
|
|
|
|
### Traits
|
|
|
|
Traits are sets of signal handlers.
|
|
|
|
```rs
|
|
|
|
let Human = trait[Present];
|
|
|
|
let Chocolatine = type[];
|
|
let GetName = sig[]: string;
|
|
let MakeChocolatine = sig(ammount: int): [Chocolatine];
|
|
|
|
/// Traits can be chained
|
|
let Baker = trait[GetName, MakeChocolatine];
|
|
|
|
/// you can define implementations on Traits
|
|
Baker|>Present[] = fn(self) {
|
|
"my name is " + self<|GetName() + ", I am a baker"
|
|
};
|
|
|
|
```
|
|
|
|
### Modules
|
|
|
|
```rs
|
|
|
|
let a = {
|
|
let Tree = obj{
|
|
height: int
|
|
};
|
|
|
|
Tree.new = fn(height: int): Tree {
|
|
Tree { int }
|
|
};
|
|
|
|
let a_tree = Tree.new(5);
|
|
|
|
auto { Tree, a_tree }
|
|
};
|
|
|
|
/// re export
|
|
let Tree = a.Tree;
|
|
|
|
let b = {
|
|
let Measure = sig(): int;
|
|
Measure|>Tree = fn() {
|
|
self.height
|
|
};
|
|
|
|
auto { Measure }
|
|
};
|
|
|
|
/// append methods
|
|
a.Tree.get_height = fn(self) {
|
|
self.height
|
|
};
|
|
|
|
```
|
|
|
|
### module exportation
|
|
|
|
```rs
|
|
|
|
let a = 4;
|
|
let b = "hello";
|
|
|
|
let add = fn(a: int, b: int): int a + b;
|
|
|
|
let serialized: string = export(auto { a, b, add });
|
|
|
|
let deserialized: Obj = import(serialized);
|
|
|
|
deserialized.add(19, deserialized.a);
|
|
|
|
```
|
|
|
|
primitive types
|
|
- `int`
|
|
- `float`
|
|
- `str`
|
|
- `bool`
|
|
- `Type<T>`
|
|
- `Trait<I, O>`
|
|
- `Trait`
|
|
- `Obj<T>`
|
|
- `Fn<I, O>`
|
|
- `Arr<T>`
|
|
|
|
considerations:
|
|
- move semantic ?
|
|
- shadowing ?
|
|
- expressions instead of statements ?
|
|
- type inference ?
|
|
- fn return inference ?
|
|
- references ? (gc)
|
|
- serialization ?
|
|
- algebraic types ?
|
|
- tuple ? |