ambc
v0.1.0
Published
Compiles source code to Ambients protocol syntax
Downloads
3
Readme
Ambients Protocol Compiler (ambc)
Ambient Syntax
a[]
to AST{ "id": "a", "children": [], "capabilities": [], "create": [] }
Table of contents
Background
Ambients is a protocol for distributed computation. It allows you to request and execute computation as easily as you can data inside OrbitDB. Think of it like AWS Lambda or Azure Cloud functions, but on a decentralized peer-to-peer network.
The protocol also includes guarantees as to the verfiability and safety of the code, all without a blockchain.
Install
First, install node.js Then:
$ git clone https://github.com/aphelionz/ambc
$ cd ambc
$ npm install
Usage
Supported source languages
- Ambients Syntax
- JavaScript (WIP)
Via the command line
Usage for the CLI tool can be viewed by simply running ambc
:
$ npm install -g ambc # coming soon
$ ambc
bin.js <input> [options]
Compile source code to ambient
Positionals:
input Path to the source code file you want to compile
Options:
--help Show help [boolean]
--version Show version number [boolean]
--display Write output to stdout instead of the output file
[boolean] [default: false]
--ipfs-api Use an IPFS HTTP API by specifying a multiaddress i.e.
"/ip4/127.0.0.1/tcp/5001"
--format Output format of the compiler
[choices: "ambient", "ir", "final"] [default: "final"]
-o Use to specify a custom path to the output file i.e.
"./out/function.js"
In code
You can also use ambc
within your JavaScript code.
const js2amb = require('js2amb')
const { irParser, parse } = require('ambc')
const js = '() => "hello"'
const ambientSyntax = js2amb(js) // Outputs ambient syntax from JS
const irAst = irParser.parse(js) // Outputs intermediate representation AST
const finalAst = parse(js) // Outputs final AST
Note that to get ambient syntax from JavaScript, you will also need js2amb
.
Description
From the Ambients whitepaper:
The Ambients protocol overall is programming language-agnostic. That means almost any programming language can be used to write distributed programs, as long as there's a compiler that can process the source language and turn it into the Ambients bytecode. While most common programming languages can be used, due to the protocol primitives, functions and types, functional languages are especially well-suited to write distributed programs.
Compilation model requires all compilers to:
- compile original source code to an intermediate abstract syntax structure (usually as in Abstract Syntax Tree)
- translate the intermediate structure to the computation primitives, distribution primitives and computation abstractions of the Ambients protocol
- generate the bytecode executable from the primitives
ambc
satisfies requirements #1 and #2 by compiling ambients syntax, and JavaScript into either an intermeidate representation or final Abstract Syntax Tree.
Both ASTs are lossless encodings, meaning that no data is lost from the ambient syntax and by-proxy the original JS code. Downstream components in the overall system can satisfy requirement #3 as required.
Compiler steps
The compiler is very simple, and has only two primary steps, the second of which has two different types of output (IR vs final)
Step 1: Source code -> Ambients syntax
Compile source code from JavaScript (other languages TBD) to Ambient ASCII syntax. Users can choose to output ambient syntax by passing the --format ambient
option to ambc
For example:
() => "hello"
⬇
func[
open_|
string[hello[]]
]|
open func
Step 2a: Ambients Syntax to intermediate representation (IR) AST
Users can choose to display an IR AST by passing the --format ir
option to ambc
.
func[
open_|
string[hello[]]
]|
open func
⬇
{ "type": "Parallel", "children": [
{ "type": "Ambient", "id": "func", "children":[
{ "type": "Parallel", "children": [
{ "type": "Open_", "id": "*" },
{ "type": "Ambient", "id": "string", "children": [
{ "type": "Noop", "id": "hello" }
]
}
] },
{ "type": "Open", "id": "func" }
] }
Step 2b: Ambients Syntax to final AST
This is the default output of the compiler, which encodes protocol primitives into the JSON.
func[
open_|
string[hello[]]
]|
open func
⬇
{
"name": "",
"children": [],
"capabilities": [
"in_ call",
"open call",
"create"
],
"create": [
{
"name": "",
"children": [],
"capabilities": [
"open return",
"open_"
],
"create": []
}
]
}
Intermediate abstract syntax tree format
The IR AST exceedingly and intentionally naive. It simply encodes the ambient syntax directly using a recursive structure of nodes.
Each node has three fields:
type
: Required - the type of the ambient, a string enum which can be one of:- Parallel
- Serial
- Group
- Ambient
- In_
- In
- Out_
- Open
- Open_
id
: Optional - a string identifierchildren
Optional - array of more child nodes
The idea here is that it is the simplest possible encoding that does not lose any of the data presented in the original ASCII syntax. Once the tree is generated it can be stored as a DAG on any compatible store. In development we simply use the in-memory structures to work with, but in practice we will likely use IPFS or IPLD.
Final abstract syntax tree format
The final AST format encodes protocol primitives into the JSON and is more meant for machine consumption. It has the following format. Note that all fields are required but initialized with default blank values.
Each node in the structure has three fields:
name
: The name of the ambientcapabilities
: The capabilities and co-capabilitie of the ambient. Each capability has three fields:op
: The operation to take, one of:- in
- in_
- out
- out_
- open
- open_
target
: The name of the ambient the capability refers tonext
: The action to take after the capability has completed
children
: array of one or more child ambients.create
: used to encode group execution,( )
in the ambient syntax.
Parallel computation is simply encoded using arrays, and serial computation is encoded using a tree structure, using the children
field.
Compiler Output
If no output -o
is specified, and the --display
flag is not used, ambc
will return
a multihash from an ipfs dag put
operation.
This hash will be used by the execution engine to run the code on a distributed, peer to peer network.
Contributing
Please do! Issues and PRs are very welcome.
If you're at all interested in this topic you should definitely seek us out on Gitter, open issues, and submit PRs.
To run the tests:
$ npm install
% npm test
Contribution Notes:
npm test
is mapped tomake test
and either command should produce identical output.- To edit the IR parser syntax, edit the grammar at
src/ir/ambients.pegjs
and then runmake build
to build theparser.js
file (optimized for speed) and its little buddy theparser-tiny.js
file, optimized for size. - To edit the final parser syntax, edit the js file at
src/parser/index.js
directly.
License
MIT © Haja Networks Oy