Test Coverage
<p align="center">
  <img src="" 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 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.


Code Climate | Packagist
--- | ---
[![Maintainability](]( [![Test Coverage](]( | [![Latest Stable Version](]( [![License](]( [![Total Downloads](](


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

# 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` *(standalone use)*
- `composer require smuuf/primi` *(using Primi as a library in your own project)*

## a) Standalone installation

1. Clone this repo.
    - `git clone`
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 && 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)*:

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

## b) Using Primi as a library

1. First, install [Primi Composer package]( `composer require smuuf/primi`
2. Then use it like this:

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) {


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]( 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](

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: