README.md

Summary

Maintainability
Test Coverage
<p align="center">
  <img src="https://raw.githubusercontent.com/smuuf/primi/master/res/art/logo-sml.png" alt="Primi">
  <h1 align="center">Primi</h1>
  <p align="center">A scripting language <i><b>written in PHP</i></b> & <i><b>interpreted in PHP</b></i>.</p>
</p>

<p align="center">
  Primi is meant for PHP developers who want to <b>allow their clients to write their own custom logic</b>. Primi allows you <i>(the developer)</i> to <b>execute untrusted code</b> <i>(provided simply as a string)</i> inside a sandbox, safely separated from its surroundings.
</p>

---

Code Climate | Packagist
--- | ---
[![Maintainability](https://api.codeclimate.com/v1/badges/bc3d946e32cc30820cc9/maintainability)](https://codeclimate.com/github/smuuf/primi/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/bc3d946e32cc30820cc9/test_coverage)](https://codeclimate.com/github/smuuf/primi/test_coverage) | [![Latest Stable Version](https://poser.pugx.org/smuuf/primi/v/stable)](https://packagist.org/packages/smuuf/primi) [![License](https://poser.pugx.org/smuuf/primi/license)](https://packagist.org/packages/smuuf/primi) [![Total Downloads](https://poser.pugx.org/smuuf/primi/downloads)](https://packagist.org/packages/smuuf/primi)

---

# Quick access
- [Language reference (syntax help)](/docs/language_reference.md)

# Rationale
Primi *- as things sometimes go in life -* began as an answer to a practical problem: I needed some general-purpose *(ie. not too much domain-specific)* scripting language that my other app's users could use to write their simple custom logic. I needed some universally usable and **primi**tive scripting thing, with familiar syntax *(`PHP-like` x `C-like` x `JS-like`)* and one that could be safely executed inside pure PHP environment *(no external depedencies on v8js, v8 and whatnot - meaning Javascript is out of the game...)*.

***Thus, Primi was (mostly as an experiment) created.***

# Installation
You can either use *Primi* as a **[standalone package](#a-standalone-installation)** `(a)` - for its development, making contributions, debugging it, or to just play with it. Or you can use *Primi* **[in your own projects](#b-as-a-library)** `(b)` by installing it as a Composer dependency.

#### You'll want either one of these:
- `git clone https://github.com/smuuf/primi.git` *(standalone use)*
- `composer require smuuf/primi` *(using Primi as a library in your own project)*

## a) Standalone installation

1. Clone this repo.
    - `git clone https://github.com/smuuf/primi.git`
2. Install Composer dependencies.
    - `composer install`
3. Run something with Primi CLI.
    - `chmod +x ./primi && ./primi -s -c "a = 1 + 2 / 3;"`

### Convenient installation Onelinerâ„¢:
```
git clone https://github.com/smuuf/primi.git && cd primi && composer install && chmod +x ./primi && ./primi -s -c "msg = 'Primi works.';"
```

### Extra stuff:
- **Register Primi's CLI executable** for current user so typing `primi` will behave like a binary *(otherwise you'd need to write `./primi` and would have to be in the right directory)*:
    ```
    ./bin/registerbin
    ```

    *Note: This will add an alias in .bashrc for current user.*
- **Run tests** *(tests are located inside `./tests/` directory)*:
    ```
    ./bin/test
    ```
- **Rebuild parser** *(when you modify Primi's grammar definitions, you will want to rebuild the parser to reflect the changes)*:
    ```
    ./bin/buildparser
    ```



## b) Using Primi as a library

1. First, install [Primi Composer package](https://packagist.org/packages/smuuf/primi): `composer require smuuf/primi`
2. Then use it like this:
```php
<?php

require __DIR__ . "/vendor/autoload.php";

$context = new \Smuuf\Primi\Context;
$interpreter = new \Smuuf\Primi\Interpreter($context);

try {

    // Let the interpreter run a source code.
    $interpreter->run('a = 1; b = a + 2; c = "some string"; d = c + " extra thing";');

    // Get defined variables from primary context and print them.
    foreach ($context->getVariables() as $name => $value) {
        printf("%s (%s) ... %s\n", $name, $value::TYPE, $value->getInternalValue());
    }

} catch (\Smuuf\Primi\ErrorException $e) {
    die($e->getMessage());
}

```

Running this code would output:

```
a (number) ... 1
b (number) ... 3
c (string) ... some string
d (string) ... some string extra thing

```

# REPL mode
Primi provides a convenient *"sandbox"* [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) mode which is launched by executing `./primi` without any argument. You can use this for messing around with the language or to test any new stuff you might be trying to implement *(e.g. your own Primi extensions written in PHP)*.

![REPL example usage](https://raw.githubusercontent.com/smuuf/primi/master/res/repl-sample.gif)

In this mode, all statements are executed when entered and the result value of the last expression is returned. REPL commands history is preserved between separate sessions *(history is stored in `~/.primi_history` file)*.

# Language reference
The basics of the language syntax and data types are found here:
https://github.com/smuuf/primi/blob/master/docs/language_reference.md