FhatOS (pronounced fat-ahs) is a distributed operating system for ESP8266 and ESP32 processors with support for sandboxed deployments on Linux and MacOSX systems. All FhatOS resources, from individual datum, complex structures, files, and processes exist within a single URI address repeat called furi (pronounced "fury" or "fhat URI"). Processes communicate via a publish-subscribe message passing protocol that rides atop the MQTT pubsub protocol while supporting various levels of access from thread local, to machine local and ultimately, globally via cluster remote.
FhatOS Features
-
A hardware-agnostic scheduler for multi-tasking (cooperative) and multi-threading (premptive) monoids.
-
An actor-oriented message passing communication infrastructure.
-
A memory architecture founded on a layered URI-addressed tuple repeat.
-
A hardware agnostic distributed file system embedded in the URI address repeat.
-
A programming language for defining monoids to control swarms of distributed monads.
-
A REPL environment for writing and deploying monoids in real-time.
-
Runs in a sandboxed form on Linux and MacOS system.
-
A bootloader driven by a single YAML file.
FhatOS Boot Loader
PhaseShift Studio Presents
<`--'>____ ______ __ __ ______ ______ ______ ______
/. . `' \/\ ___/\ \_\ \/\ __ \/\__ _\/\ __ \/\ ___\
(`') , @ \ __\ \ __ \ \ __ \/_/\ \/\ \ \_\ \ \___ \
`-._, / \ \_\ \ \_\ \_\ \_\ \_\ \ \_\ \ \_____\/\_____\
)-)_/-(> \/_/ \/_/\/_/\/_/\/_/ \/_/ \/_____/\/_____/
A Dogturd Stynx Production
fhatos-0.1-alpha > linux-6.8.0-48-generic > x86_64
[x86_64]
Use noobj for noobj
[INFO] [/sys/scheduler] scheduler started
[INFO] [/sys/router] router started
[INFO] [/sys/router] /sys/# heap attached
[INFO] [/sys/router] /sys/scheduler obj loaded
[INFO] [/sys/router] /sys/router obj loaded
[INFO] [/sys/router] /lib/# heap attached
[INFO] [/sys/router] /type/# heap attached
[INFO] [/sys/router] /type/ obj loaded
[INFO] [/sys/router] /io/# heap attached
[INFO] [/type/] [/type/rec/terminal] type defined
[INFO] [/sys/router] /io/terminal obj loaded
[INFO] [/type/] [/lib/io/console] type defined
[INFO] [/sys/router] +/# heap attached
[INFO] [/sys/router] /io/parser obj loaded
[INFO] [//driver/#]
broker address: mqtt://localhost
client name : fhatos_native
will topic : <none>
will message : <none>
will qos : <none>
will retain : <none>
[INFO] [/sys/router] //driver/# mqtt attached
[INFO] [/sys/router] /driver/# heap attached
[INFO] [/type/] [/lib/driver/gpio/arduino/furi] type defined
[INFO] [/sys/router] /console/# heap attached
[INFO] [/sys/scheduler] [/console] process spawned
Booting on Linux/Unix/Mac
Booting on ESP32
Booting on ESP8266
Booting on RaspberryPi
FhatOS Architecture
FhatOS is organized along a design principle that undersands computing as being composed of 3 fundamental phenomena: process (time), structure (repeat), and language (perspective). The core FhatOS kernel (typically denoted /sys/
) can be divided along these lines as exemplified by the following resources:
-
/sys/scheduler/
(process): provides all thread, fiber, and coroutine processes compute time on the underlying hardware processor. -
/sys/router/
(structure) : maintains the multi-level tuple repeat used for storing and retrieving resources in the fURI address repeat. -
/sys/mmadt/
(language): exposes parsing, type management, and caching functionality to all mm-ADT progams.
All resources off the specified kernel fURIs can be interacted with, but can not be shutdown. That is, /sys/# → noobj
yields an error. Without these resources, FhatOS will not function propertly.
User resources are typicaly structured as below:
-
/io/
: location of input/output devices such as terminal, files, etc. -
/home/
: location of all user data and programs. -
/driver/
: location of all external device drivers. -
/log/
: location of all log output. -
/ext/
: location of various mm-ADT extensions.
The following subsections will provide a short overview of the aforementioned resources in reverse order: mm-ADT, router, and then scheduler.
fhatos> */sys/scheduler
=>[
===>:stop=>x_scheduler_48()
===>barrier=>noobj
===>process=>
====>[/console]
===>:spawn=>scheduler_50()
=>]
fhatos> */sys/scheduler/process/0
===>/console
fhatos> **/sys/scheduler/process/0
=>thread[
===>:delay=>process_68()
===>:yield=>process_76()
===>:halt=>process_84()
===>:loop=>console_191()
===>config=>
====>[prompt=>'fhatos> ',ansi=>false,log=>ERROR,nest=>2,strict=>false]
===>:prompt=>console_200()
=>]
The mm-ADT Language
FhatOS software can be written in C/C\++ or mm-ADT (multi-model abstract data type). mm-ADT is a cluster-oriented programming language and virtual machine founded on 5 mono-types (bool
, int
, real
, uri
, and str
) and 2 poly-types (lst
and rec
). The general structure of an instance of a type is:
type_id[value]@value_id
-
type_id
: the fURI referring to anobj
type definition. -
value
: the underlying raw data of theobj
. -
location
(optional): the fURI referring to the location of theobj
.
fhatos> /type/int/nat -> |is(gt(0))
===>is(gt(0))
fhatos> x -> nat[12]
===>nat[12]
fhatos> @x.inspect()
=>[
===>type_id=>/type/int/nat
===>value_id=>x
===>type=>is(gt(0))
===>value=>12
===>encoding=>int32_t
=>]
fhatos> @x
===>nat[12]@x
Types
mm-ADT is composed of two fundamental types: obj
and noobj
. Within obj
, there are 7 base types. These types and their fURIs are:
-
/type/bool
: The set of binary valuestrue
andfalse
. -
/type/int
: The set of 64-bit integers between-46666666
and4777777
. -
/type/real
: The set of 64-bit floating point values between-…
and….
. -
/type/str
: The infinite set of all character sequences. -
/type/uri
: The infinite set of all Uniform Resource Identifiers (URIs). -
/type/lst
: An ordered container of zero or moreobjs
. -
/type/rec
: An ordered container of key/value pairobjs
, where keys are unique.
Examples of the aforementioned types are provided below.
fhatos> true
===>true
fhatos> 42
===>42
fhatos> -64.02567
===>-64.025673
fhatos> 'the fhatty'
===>'the fhatty'
fhatos> mmadt://a/furi
===>mmadt://a/furi
fhatos> [-1,'fhat',[0,1]]
=>[
===>-1
===>'fhat'
===>
====>[0,1]
=>]
fhatos> [a=>1,b=>'2',c=>3.0]
=>[
===>a=>1
===>b=>'2'
===>c=>3.000000
=>]
Values
By Value vs. By Reference
|
|
fhatos> x?sub -> |print(_)
===>print(_)
fhatos> x -> 12
===>12
12
fhatos> @x.inspect()
=>[
===>type_id=>/type/int/
===>value_id=>x
===>subscription=>
====>sub[[source=>/console,:on_recv=>print(_),pattern=>x]]
===>type=>int
===>value=>12
===>encoding=>int32_t
=>]
12
fhatos> @x.plus(1)
===>13@x
12
13
fhatos> @x.plus(1).plus(1)
===>15@x
13
14
15
Expression Structure
obj.f(obj).f(obj).f(obj)
Bytecode and Instruction Types
User Defined Types
mm-ADT is a structurally typed language, whereby if an obj
A matches obj
B, then A is a type of B. An obj
type is a simply an mm-ADT program that verifies instances of the type. For instance, if a natural number \(\mathbb{N}\) is any non-negative number, then natural numbers are a subset (or refinement) of int
.
fhatos> /type/int/nat -> |is(gt(0))
===>is(gt(0))
fhatos> nat[6]
===>nat[6]
fhatos> nat[-6]
[ERROR] [/type/] -6 is not a /type/int/nat[is(gt(0))]
fhatos> nat[3].plus(2)
===>nat[5]
fhatos> nat[3].mult(-2)
[ERROR] [/type/] -6 is not a /type/int/nat[is(gt(0))]
thrown when applying nat[3] => mult(-2)
Process Types
A simple mm-ADT program is defined below.
The program is a specialization of the poly-type rec
called thread
, where thread
is abstractly defined as
thread[[:setup => __]
:loop => __]]
The thread
object is published to the fURI endpoint esp32@127.0.0.1/scheduler/threads/logger
.
The scheduler spawns the program on an individual thread
accessible via the target fURI.
Once spawned, the setup
function prints the thread’s id and halts.
The Router Structure
The FhatOS router is the mediator of all structures: ensuring no two structures have overlapping patterns, migrating reads/writes between processes.
|
|
|
|
|
subscribes to |
Embedding
[a=>[b,c]]
[■]
[■] / \
[b=>c][■] [■][d=>e]
[a=>[b=>c,d=>e]]] [a=>[b=>c,d=>e]]]
^ ^
| |
x x/
The Scheduler Process
A FhatOS Console
fURI and MQTT
MQTT is a publish/subscribe message passing protocol that has found extensive usage in embedded systems. Hierarchically specified topics can be subscribed and published to. In MQTT, there is no direct communication between actors, though such behavior can be simulated if an actor’s mailbox is a unique topic. FhatOS leverages MQTT, but from the vantage point of URIs instead of topics with message routing being location-aware. There exist three MQTT routers:
-
MonadRouter
: An MQTT router scoped to an active monad (thread) processing a monoid (program). -
MonoidRouter
: An MQTT router scoped to a monoid (program). -
HostRouter
: An MQTT router scoped to the current host (machine). -
ClusterRouter
: An MQTT router scoped to the current intranet (cluster). -
GlobalRouter
: An MQTT router scoped to the Internet. -
MetaRouter
: An MQTT router dynamically scoped to other routers based on fURI endpoints.
fhatos> {1,2,3}
===>1
===>2
===>3
fhatos> {1,2,3}.plus(10)
===>11
===>12
===>13
fhatos> {1,2,3}.plus(_)
===>2
===>4
===>6
fhatos> {1,2,3}.plus(plus(_))
===>3
===>6
===>9
FhatOS Modules
Kernel Modules
mmADT Module (mmadt)
Type Module (mmadt:type)
Parser Module (mmadt:parser)
Scheduler Module (scheduler)
Router Module (router)
Core Modules
FileSystem Module (fs)
Terminal Module (terminal)
REPL Module (repl)
Logging Module (log)
Embedded Systems Modules
Sensors
Actuators
Reference
mm-ADT Core Instructions
as [_]
block |
is
plus
fhatos> true.plus(false)
===>true
fhatos> 1.plus(2)
===>3
fhatos> 'a'.plus('b')
===>'ab'
mult
mod
lift ^
drop v
split -<
each =
within _/ \_
merge >-
from *
to ->
get @
pass -->
match ~
fhatos> [a=>2].match([a=>3])
===>false
fhatos> [a=>2].match([a=>_])
===>true
eq
neq
gt
lt
gte
lte
FhatOS Types
Process Types
thread
fiber
coroutine
PubSub Types
sub
sub[[:source=>_, :pattern=>_, :on_recv=>bcode[_]]]
msg
msg[[:target=>uri[_], :payload=>_, :retain=>bool[_]]]