Project of message oriented, dynamic, strongly typed scripting language with context serialization.
Find a file
2024-06-22 22:44:01 +02:00
src add start of eval impl 2024-06-22 22:44:01 +02:00
.gitignore added readme with base semantic concepts 2022-08-25 13:01:04 +03:00
Cargo.lock start implementing 2024-06-07 03:31:12 +02:00
Cargo.toml start implementing 2024-06-07 03:31:12 +02:00
README.md added readme with base semantic concepts 2022-08-25 13:01:04 +03:00
run.sh start implementing 2024-06-07 03:31:12 +02:00
rustfmt.toml start implementing 2024-06-07 03:31:12 +02:00

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...


/// 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.


/// 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.


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


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


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 ?