# cf_client
###### A Cuneiform client implementation.
[![hex.pm](https://img.shields.io/hexpm/v/cf_client.svg?style=flat-square)](https://hex.pm/packages/cf_client) [![Build Status](https://travis-ci.org/joergen7/cf_client.svg?branch=master)](https://travis-ci.org/joergen7/cf_client)
cf_client is a client implementation for the common runtime environment (CRE) instantiating an interpreter for the Cuneiform functional language for large-scale data analysis.
This application packages a Cuneiform scanner and parser, as well as an interpreter that distributes tasks by sending it to a CRE instance. The Cuneiform client can be used to consume a Cuneiform source file from the file system or to start an interactive shell.
## Usage
### Adding the CRE to a Project
Although the Cuneiform client application can be imported also directly from GitHub, we recommend adding a dependency via [hex.pm](https://hex.pm). Here, we show how this can be done using the build tools [rebar3](https://www.rebar3.org) or mix.
#### rebar3
To integrate the Cuneiform client application into a rebar3-managed project change the `deps` entry in your application's `rebar.config` file to include the tuple `{cf_client, "0.1.6"}`.
```erlang
{deps, [{cf_client, "0.1.6"}]}.
```
#### mix
```elixir
{:cf_client, "~> 0.1.6"}
```
### Compiling
Having rebar3 available on your system, compile the project as an Erlang project by entering
rebar3 compile
If you want to drive the project from the command line please compile the project by entering
rebar3 escriptize
### Starting the Cuneiform Client
The Cuneiform client can be started in several different ways. It can be started from the command line, as an Erlang application, as a supervision tree hosting a single client process, or directly as a process. In all cases there has to be a way for the client to find the CRE instance it connects to.
#### Starting from the Command Line
Compiling the Cuneiform client using `escriptize` creates an Erlang script file `cf_client` which allows starting the Cuneiform client via the command line.
To display a help text enter
./cf_client --help
This will show the command line synopsis, which looks like the following:
Usage: cf_worker [-v] [-h] [-s <suppl_file>] [-c <cre_node>]
-v, --version Show cf_worker version.
-h, --help Show command line options.
-s, --suppl_file Supplementary configuration file.
-c, --cre_node Erlang node running the CRE application.
To start the client from the command line and connect with a running CRE instance enter
./cf_client -c cre@my_node
Here, we assume that the CRE runs on an Erlang node identified as `cre@my_node`.
#### Starting as an Erlang Application
If a CRE instance is already running on the same Erlang node you can start the Cuneiform client application by calling
```erlang
cf_client:start().
```
Which is exactly the same as calling
```erlang
application:start( cf_client ).
```
#### Starting Under the Default Supervisor
To start the Cuneiform client default supervisor under a custom supervision tree enter
```erlang
CreNode = node().
cf_client_sup:start_link( CreNode ).
```
This will register the Cuneiform client locally under the name `cf_client`.
#### Starting Directly
The Cuneiform client process can be started directly. There are several ways to do this. The first is to start the process with a function that allows it to locate the CRE:
```erlang
CreNode = node().
F = fun() -> cre:pid( CreNode ) end.
{ok, ClientPid} = cf_client_process:start_link( F ).
```
Giving a function instead of a plain Cre process identifier has the advantage, that if the CRE crashes, taking the Cuneiform client with it, the restarted client instance connects uses the output of the function, which offers the possibility of locating the CRE under its new process identifier.
If this is too tedious, one can start it giving the CRE process identifier directly:
```erlang
CrePid = cre:pid( node() ).
{ok, ClientPid} = cf_client_process:start_link( CrePid ).
```
Both previous direct starting methods do not register the Cuneiform client with any registry service. However, one can register the client process by starting it either with a function:
```erlang
ClientName = cf_client.
CreNode = node().
F = fun() -> cre:pid( CreNode ) end.
{ok, ClientPid} = cf_client_process:start_link( {local, ClientName}, F ).
```
or with the CRE process identifier:
```erlang
ClientName = cf_client.
CrePid = cre:pid( node() ).
{ok, ClientPid} = cf_client_process:start_link( {local, ClientName}, CrePid ).
```
### Interacting with a Cuneiform Client
After starting the Cuneiform client instance one can interact with it by sending it expressions conforming the Cuneiform intermediate representation. The client will reply with the value that corresponds to the expression or with an error term. Communication with the client is synchronous.
#### Sending Cuneiform Expressions
E.g., since strings are values which evaluate to themselves we can give the client a string expression, which it will parrot:
```erlang
E = cuneiform_lang:str( <<"bla">> ).
cre_client:eval( cf_client, E ).
```
Here we assume, that a Cuneiform client instance is running registered locally under `cf_client`.
#### Connecting a Shell
The Cuneiform client comes with an interactive shell which can be connected to a client instance registered under `cf_client` by entering
```erlang
cuneiform_shell:shell( cf_client ).
```
Which will start a shell that should look like the following:
___
@@WB Cuneiform
@@E_____
_g@@@@@WWWWWWL Type help for usage info
g@@#*`3@B quit to exit shell
@@P 3@B
@N____ 3@B http://www.cuneiform-lang.org
"W@@@WF3@B
1>
## System Requirements
- [Erlang](https://www.erlang.org) OTP 18.0 or higher
- [Rebar3](https://www.rebar3.org) 3.0.0 or higher
## Resources
- [joergen7/cre](https://github.com/joergen7/cre). A common runtime environment (CRE) for distributed workflow languages.
- [joergen7/cuneiform](https://github.com/joergen7/cuneiform). A functional language for large-scale data analysis whose distributed execution environment is implemented on top of the CRE.
## Authors
- Jörgen Brandt ([@joergen7](https://github.com/joergen7/)) [joergen.brandt@onlinehome.de](mailto:joergen.brandt@onlinehome.de)
## License
[Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0.html)