AL is a live, ACID, (eventually) bitemporal, relational-object operating system built around an append-only command log. It combines inspiration from:
XTDB
GlamorousToolkit/Pharo
Git
PROLOG/Logtalk
LISP
BEAM
Urbit
The goal of the system is to merge the ideas of the relational paradigm and of the metaobject protocol, and, as a north star, to be the personal computing environment of the future. This runtime is the prototypical version of AL, written in Elixir. The irony of the first Erlang interpreter having been written in PROLOG is not lost on us.
- Live Smalltalk-style objects, defined relationally. No more faux-ADTs. Define protocols and their implementations. Mix and match at your leisure. With bidirectional method resolution informed by WAM semantics.
- Shutdown your system, continue later. All transactions are backed up by an on-disk database, hydrated at startup.
- ACID transactions ensure your work is safe and easy to reason about.
- CLP over finite domains, including over objects, both durable and ephemeral.
- Git-Like branching behaviour. Fork your system at different points in the system's history.
And to come:
- Bitemporality features: Query objects as of certain times, working with system and business time separately
For discussion of the design philosophy of AL and resources that were consulted during its design, please see: https://forum.anoma.net/t/design-philosophy-of-al-bibliography/2698
Install from terminal using iex -S mix or as a mix dependency.
From IEx, you can run require AL.
lib/examples contains examples.
lib/AL/package contains the bundled packages (the bootstrap package is the foundational one).
lib/AL contains the runtime code.
Look inside a live object.
rundoexamine(:object,info)endExtend an inherited method
rundodefclass:animal,super: :objectdodefmethod(:describe,[self,:i_am_animal])doendenddefclass:pet,super: :animaldodefmethod(:describe,[self,d])docall_next_method(self,[parent])unify(d,[:i_am_pet,parent])endendnew(:pet,rex)describe(rex,result)endRun a method backwards.
rundofactorial(n,120)endPropagate constraints about and between objects
rundodefclass:rectangle,super: :value,ivars: [:width,:height,:perimeter]dodefmethod(:init,[self,args,new])doslot_get(args,:width,w)slot_get(args,:height,h)slot_get(args,:perimeter,p)eq(p,2*w+2*h)unify(new,%{class: :rectangle,width: w,height: h,perimeter: p})enddefmethod(:get_slot,[self,k,v])dovm_map_get(self,k,v)enddefmethod(:area,[self,result])doget_slot(self,:width,w)get_slot(self,:height,h)vm_is(result,w*h)endendnew(:rectangle,%{width: w,height: 3,perimeter: 16},r)area(r,a)endInfer an object's identity from its class and a slot
rundodefclass:vehicle,super: :objectdoenddefclass:car,super: :vehicledoenddefclass:bicycle,super: :vehicledoenddefclass:fire_hydrant,super: :objectdoendset_slots(:car,%{color: :red})set_slots(:bicycle,%{color: :blue})set_slots(:fire_hydrant,%{color: :red})new(:car,my_car)new(:bicycle,my_bike)new(:fire_hydrant,hydrant)class(x,:vehicle)get_slot(x,:color,:red)endAL persists to a local, gitignored Mnesia store (.mnesiastore/ by default) that every iex -S mix/mix run/mix test invocation in a checkout shares unless told otherwise.
You can utilise forks to have multiple streams work on the same node without conflict.
fork=AL.Branch.fork()<-forkfromHEADAL.Branch.checkout(fork)<-changeHEADtoforkAL.Branch.discard(fork)<-discardtheforkFurther isolation should be accomplished by configuration of the Mnesiastore dir.
Metacellonewrepository:'github://anoma/AL-Ex:main/src';
baseline:'AL';
loadIf you have an existing bridge with a different version you want to run this without error then run:
Metacellonewrepository:'github://anoma/AL-Ex:main/src';
baseline:'AL';
load:#dev