{"id":18772448,"url":"https://github.com/eftec/minilang","last_synced_at":"2025-08-01T02:11:11.872Z","repository":{"id":56975559,"uuid":"163226016","full_name":"EFTEC/MiniLang","owner":"EFTEC","description":"It is a library","archived":false,"fork":false,"pushed_at":"2024-12-30T21:17:39.000Z","size":320,"stargazers_count":11,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-14T03:43:30.359Z","etag":null,"topics":["php-library","php7","scripting-language"],"latest_commit_sha":null,"homepage":"https://www.eftec.cl","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/EFTEC.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2018-12-26T23:34:50.000Z","updated_at":"2024-12-30T21:17:43.000Z","dependencies_parsed_at":"2024-11-07T19:35:34.125Z","dependency_job_id":"e1906419-27df-4b82-95a2-7b07d2c57e35","html_url":"https://github.com/EFTEC/MiniLang","commit_stats":{"total_commits":50,"total_committers":3,"mean_commits":"16.666666666666668","dds":0.14,"last_synced_commit":"3bbc76b1af358eb603cd409c788a66feeb3fe0b8"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/EFTEC/MiniLang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMiniLang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMiniLang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMiniLang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMiniLang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/EFTEC","download_url":"https://codeload.github.com/EFTEC/MiniLang/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/EFTEC%2FMiniLang/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264726769,"owners_count":23654494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["php-library","php7","scripting-language"],"created_at":"2024-11-07T19:29:09.532Z","updated_at":"2025-07-11T04:04:00.903Z","avatar_url":"https://github.com/EFTEC.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MiniLang\r\nThis library is used to store business logic in a simple and yet powerful definition.\r\n\r\nA mini script language for PHP.  It does three simple tasks.\r\n\r\n1. (optional) It set some initial values **(INIT)**.\r\n2. It evaluates a logic expression **(WHERE)**.\r\n3. If the expression (logic) is true then it executes the SET expression **(SET)**, so we could change the value of a variable, call a function and task like that.\r\n4. (optional) If the expression (logic) is false then it executes the ELSE expression **(INIT)**.\r\n\r\nFor example :\r\n\r\n```\r\nwhen var1\u003e5 and var2\u003e20 then var3=20 // when and then \r\ninit var5=20 when var1\u003e5 and var2\u003e20 then var3=var5  // init, when and then\r\ninit var5=20 when var1\u003e5 and var2\u003e20 then var3=var5 else var3=var20 // init, when, then and else\r\nwhen var1\u003e$abc then var3=var5 // $abc is a PHP variable.\r\n```\r\n\r\n[![Packagist](https://img.shields.io/packagist/v/eftec/minilang.svg)](https://packagist.org/packages/eftec/minilang)\r\n[![Total Downloads](https://poser.pugx.org/eftec/minilang/downloads)](https://packagist.org/packages/eftec/minilang)\r\n[![Maintenance](https://img.shields.io/maintenance/yes/2025.svg)]()\r\n[![composer](https://img.shields.io/badge/composer-%3E2.0-blue.svg)]()\r\n[![php](https://img.shields.io/badge/php-\u003e7.4-green.svg)]()\r\n[![php](https://img.shields.io/badge/php-8.4-green.svg)]()\r\n[![CocoaPods](https://img.shields.io/badge/docs-70%25-yellow.svg)]()\r\n\r\n## Why we need a mini script?\r\n\r\nSometimes we need to execute arbitrary code in the basis of \"if some value equals to, then we set or execute another code.\"\r\n\r\nIn PHP, we could do the next code.\r\n\r\n```php\r\nif($condition) {\r\n    $variable=1;\r\n}\r\n```\r\nHowever, this code is executed at runtime.  What if we need to execute this code at some specific point?.\r\n\r\nWe could do the next code:\r\n\r\n```php\r\n$script='if($condition) {\r\n    $variable=1;\r\n}';\r\n\r\n// and later..\r\neval($script);\r\n```\r\n\r\nThis solution works (and it only executes if we call the command eval). But it is verbose, prone to error, and it's dangerous.\r\n\r\nOur library does the same but safe and clean.\r\n\r\n```php\r\n$mini-\u003eseparate(\"when condition then variable=1\");\r\n```\r\n\r\n## Table of Content\r\n\r\n\u003c!-- TOC --\u003e\r\n* [MiniLang](#minilang)\r\n  * [Why we need a mini script?](#why-we-need-a-mini-script)\r\n  * [Table of Content](#table-of-content)\r\n  * [Getting started](#getting-started)\r\n  * [Methods](#methods)\r\n    * [Constructor](#constructor)\r\n    * [reset()](#reset)\r\n    * [setCaller(\u0026$caller)](#setcallercaller)\r\n    * [setDict(\u0026$dict)](#setdictdict)\r\n    * [function separate($miniScript)](#function-separateminiscript)\r\n    * [evalLogic($index)](#evallogicindex)\r\n    * [evalAllLogic($stopOnFound = true, $start = false)](#evalalllogicstoponfound--true-start--false)\r\n    * [evalSet($idx = 0, $position = 'set')](#evalsetidx--0-position--set)\r\n  * [Fields](#fields)\r\n    * [$throwError](#throwerror-)\r\n    * [$errorLog](#errorlog)\r\n  * [Definition](#definition)\r\n    * [Sintaxis.](#sintaxis)\r\n    * [Variables](#variables)\r\n    * [Variables defined by a PHP Object](#variables-defined-by-a-php-object)\r\n    * [Variables defined by a PHP array](#variables-defined-by-a-php-array)\r\n    * [Global variables](#global-variables)\r\n  * [Literals](#literals)\r\n    * [Examples](#examples)\r\n    * [Reserved methods](#reserved-methods)\r\n  * [init](#init)\r\n    * [Code:](#code)\r\n  * [where](#where-)\r\n    * [Example](#example)\r\n    * [Logical expressions allowed](#logical-expressions-allowed)\r\n  * [set](#set)\r\n    * [Setting expressions allowed](#setting-expressions-allowed)\r\n    * [Example:](#example-1)\r\n    * [Code:](#code-1)\r\n  * [else](#else)\r\n    * [Example](#example-2)\r\n  * [Loop](#loop)\r\n  * [Compiling the logic into a PHP class](#compiling-the-logic-into-a-php-class)\r\n    * [Creating the class](#creating-the-class)\r\n    * [Using the class](#using-the-class)\r\n  * [Benchmark](#benchmark)\r\n      * [(reset+separate+evalAllLogic) x 1000](#resetseparateevalalllogic-x-1000)\r\n      * [evalAllLogic x 1000](#evalalllogic-x-1000)\r\n      * [(reset+separate2+evalAllLogic2) x 1000](#resetseparate2evalalllogic2-x-1000)\r\n      * [(evalAllLogic2) x 1000](#evalalllogic2-x-1000)\r\n      * [PHP method of class x 1000](#php-method-of-class-x-1000)\r\n  * [Documentation](#documentation)\r\n  * [To-do](#to-do)\r\n  * [Version](#version)\r\n\u003c!-- TOC --\u003e\r\n\r\n## Getting started\r\n\r\nInstalling it using composer:\r\n\r\n\u003e composer requires eftec/minilang\r\n\r\nCreating a new project\r\n\r\n```php\r\nuse eftec\\minilang\\MiniLang;\r\ninclude \"../lib/MiniLang.php\"; // or the right path to MiniLang.php\r\n$mini=new MiniLang();\r\n$mini-\u003eseparate(\"when field1=1 then field2=2\"); // we set the logic of the language but we are not executed it yet.\r\n$mini-\u003eseparate(\"when field1=2 then field2=4\"); // we set more logic.\r\n$result=['field1'=\u003e1,'field2'=\u003e0]; // used for variables.\r\n$callback=new stdClass(); // used for callbacks if any\r\n$mini-\u003eevalAllLogic($callback,$result);\r\nvar_dump($result);\r\n```\r\n\r\nAnother example:\r\n\r\n```php\r\nuse eftec\\minilang\\MiniLang;\r\n\r\ninclude \"../lib/MiniLang.php\";\r\n\r\n$result=['var1'=\u003e'hello'];\r\n$global1=\"hello\";\r\n$mini=new MiniLang(null,$result);\r\n$mini-\u003ethrowError=false; // if error then we store the errors in $mini-\u003eerrorLog;\r\n$mini-\u003eseparate('when var1=\"hello\" then var2=\"world\" '); // if var1 is equals \"hello\" then var2 is set \"world\"\r\n$mini-\u003eseparate('when $global1=\"hello\" then $global2=\"world\" '); // we can also use php variables (global)\r\n$mini-\u003eevalAllLogic(false); // false means it continues to evaluate more expressions if any \r\n\t\t\t\t\t\t\t// (true means that it only evaluates the first expression where \"when\" is valid)\r\nvar_dump($result); //  array(2) { [\"var1\"]=\u003e string(5) \"hello\" [\"var2\"]=\u003e string(5) \"world\" }\r\nvar_dump($global2); //  string(5) \"world\"\r\n```\r\n\r\n## Methods\r\n\r\n### Constructor\r\n\r\n\u003e __construct(\u0026$caller,\u0026$dict,array $specialCom=[],$areaName=[],$serviceClass=null)\r\n\r\n* object $caller Indicates the object with the callbacks\r\n* array **$dict** Dictionary with initial values\r\n* array **$specialCom** Special commands. it calls a function of the caller.\r\n* array **$areaName** It marks special areas that could be called as \"\u003cnamearea\u003e somevalue.\"\r\n*null|object $serviceClass A service class. By default, it uses the $caller.\r\n\r\n### reset()\r\n\r\nIt reset the previous definitions but the variables, service and areas.\r\n\r\n### setCaller(\u0026$caller)\r\n\r\nSet a caller object.     The caller object it could be a service class with method that they could be called inside the script.\r\n\r\n### setDict(\u0026$dict)\r\n\r\nSet a dictionary with the variables used by the system.\r\n\r\n### function separate($miniScript)\r\n\r\nIt sends an expression to the MiniLang, and it is decomposed in its parts. The script is not executed but parsed.\r\n\r\n### evalLogic($index)\r\n\r\nIt evaluates a logic. It returns true or false.\r\n\r\n* $index is the number of logic added by separate()\r\n\r\n### evalAllLogic($stopOnFound = true, $start = false)\r\n\r\n* bool $stopOnFound exit if some evaluation matches\r\n* bool $start if true then it always evaluates the \"init\" expression.\r\n\r\n### evalSet($idx = 0, $position = 'set')\r\n\r\nIt sets a value or values. It does not consider if WHERE is true or not.\r\n\r\n* int  $idx number of expression\r\n* string $position =['set','init']\\[$i] It could be set or init\r\n\r\n## Fields\r\n\r\n### $throwError \r\n\r\nBoolean. \r\n\r\n* If true (default value), then the library throw an error when an error is found (for example if a method does not exist).\r\n* If false, then every error is captured in the array $errorLog\r\n\r\n\r\n\r\n### $errorLog\r\n\r\nArray of String. if $throwError is false then every error is stored here.\r\n\r\nExample:\r\n\r\n```php\r\n$this-\u003ethrowError=false;\r\n$mini-\u003eseparate(\"when FIELDDOESNOTEXIST=1 then field2=2\");\r\nvar_dump($this-\u003eerrorLog);\r\n```\r\n\r\n\r\n\r\n## Definition\r\n\r\n### Sintaxis.\r\n\r\nThe syntaxis of the code is separated into four parts. INIT, WHERE (or when), SET (or THEN) and ELSE.\r\n\r\nExample:\r\n\r\n```php\r\n$mini-\u003eseparate(\"when field1=1 then field2=2\");\r\n```\r\n\r\nIt says if field1=1 then we set field2 as 2.\r\n\r\n\r\n### Variables\r\n\r\nA variable is defined by `varname`\r\n\r\nExample:  [examples/examplevariable.php](examples/examplevariable.php)\r\n```php\r\n$mini=new MiniLang();\r\n$mini-\u003eseparate(\"when field1\u003e0 then field2=3\"); // we prepare the language\r\n$variables=['field1'=\u003e1]; // we define regular variables\r\n$callback=new stdClass();\r\n$mini-\u003eevalAllLogic($callback,$variables); // we set the variables and run the languageand run the language\r\nvar_dump($variables); // field1=1, field2=3\r\n```\r\n### Variables defined by a PHP Object\r\n\r\nA variable could host a PHP object, and it is possible to call and to access the fields inside it.\r\n\r\n`varname.field`\r\n\r\n* If the field exists, then it uses it.\r\n* If the field doesn't exist, then it uses a method of the object CALLER.\r\n* If the method of the CALLER doesn't exist then it tries to use the method of the service class \r\n* If the method of the service class doesn't exist then it tries to use the inner method of the class MiniLang (with a prefix _). Example function _param()\r\n* Finally, if everything fails then it triggers an error.\r\n\r\nExample of code [examples/examplevariable2.php](examples/examplevariable2.php)\r\n\r\n```php\r\nclass MyModel {\r\n    var $id=1;\r\n    var $value=\"\";    \r\n    public function __construct($id=0, $value=\"\")\r\n    {\r\n        $this-\u003eid = $id;\r\n        $this-\u003evalue = $value;\r\n    }\r\n}\r\nclass ClassCaller {\r\n    public function Processcaller($arg) {\r\n        echo \"Caller: setting the variable {$arg-\u003eid}\u003cbr\u003e\";\r\n    }\r\n}\r\nclass ClassService {\r\n    public function ProcessService($arg) {\r\n        echo \"Service: setting the variable {$arg-\u003eid}\u003cbr\u003e\";\r\n    }\r\n}\r\n$mini=new MiniLang([],[],new ClassService());\r\n$mini-\u003eseparate(\"when field1.id\u003e0 then \r\n                field2.value=3 \r\n                and field3.processcaller \r\n                and processcaller(field3) \r\n                and processservice(field3)\"); // we prepare the language\r\n$variables=['field1'=\u003enew MyModel(1,\"hi\")\r\n            ,'field2'=\u003enew MyModel(2,'')\r\n            ,'field3'=\u003enew MyModel(3,'')]; // we define regular variables\r\n$callback=new ClassCaller();\r\n$mini-\u003eevalAllLogic($callback,$variables,false); // we set the variables and run the languageand run the language\r\nvar_dump($variables);\r\n```\r\n\r\n* field2.value references the field \"value\" (MyModel)\r\n* field3.processcaller references the method ClassCaller::processcaller()\r\n* processcaller(field3) does the same as field3.processcaller\r\n* processservice(field3) calls the method ClassService::processservice()\r\n\r\n### Variables defined by a PHP array\r\n\r\nA variable could hold an associative/index array, and it is possible to read and to access the elements inside it.\r\n\r\nExample:\r\n\r\n```php\r\n$mini=new MiniLang(null,\r\n                   [\r\n                       'vararray'=\u003e['associindex'=\u003e'hi',0=\u003e'a',1=\u003e'b',2=\u003e'c',3=\u003e'd',4=\u003e'last','a'=\u003e['b'=\u003e['c'=\u003e'nested']]]\r\n                   ]\r\n                  );\r\n```\r\n\r\n```php\r\nvararray.associndex // vararray['associindex'] ('hi')\r\nvararray.4 // vararray[4] 'last'\r\nvararray.123 // it will throw an error (out of index)\r\nvararray.param('a.b.c')) // vararray['a']['b']['c'] ('nested')\r\nparam(vararray,'a.b.c')) // vararray['a']['b']['c'] ('nested')\r\nvararray._first // first element ('hi')\r\nvararray._last // last element ('last')\r\nvararray._count // returns the number of elements. (6)\r\n```\r\n\r\n* If the element exists, then it uses it.\r\n* If the element doesn't exist, then it uses a method of the caller.\r\n* If the method of the caller doesn't exist then it tries to use the method of the service class \r\n* Finally, if everything fails then it triggers an error.\r\n\r\nExample of code [examples/examplevariable_arr.php](examples/examplevariable_arr.php)\r\n\r\n```php\r\nclass ClassCaller {\r\n    public function Processcaller($arg) {\r\n        echo \"Caller: setting the variable {$arg['id']}\u003cbr\u003e\";\r\n    }\r\n}\r\nclass ClassService {\r\n    public function ProcessService($arg) {\r\n        echo \"Service: setting the variable {$arg['id']}\u003cbr\u003e\";\r\n    }\r\n}\r\n\r\n$mini=new MiniLang([],[],new ClassService());\r\n$mini-\u003eseparate(\"when field1.id\u003e0 then \r\n                field2.value=3 \r\n                and field3.processcaller \r\n                and processcaller(field3) \r\n                and processservice(field3)\"); \r\n\r\n$variables=['field1'=\u003e['id'=\u003e1,'value'=\u003e3]\r\n            ,'field2'=\u003e['id'=\u003e2,'value'=\u003e'']\r\n            ,'field3'=\u003e['id'=\u003e3,'value'=\u003e'']\r\n           ]; \r\n$callback=new ClassCaller();\r\n$mini-\u003eevalAllLogic($callback,$variables,false);\r\nvar_dump($variables);\r\n```\r\n\r\n* field2.value references the element \"value\" of the array\r\n* field3.processcaller references the method ClassCaller::processcaller()\r\n* processcaller(field3) does the same as field3.processcaller\r\n* processservice(field3) calls the method ClassService::processservice()\r\n\r\n\r\n### Global variables\r\nA global variable takes the values of the PHP ($GLOBAL), so it doesn't need to be defined or set inside the language\r\n\u003e **Note:** For security purpose. global variables defined by PHP as \"$_namevar\" can't be read or modified.\r\n\u003e So if you want to protect a global variable, then you can rename it with an underscore as prefix.  \r\n\u003e **Example:** If you try to read the variable $_SERVER, then it will return the value of the variable $SERVER which it could be or not defined. \r\n\r\nA global variable is defined by\r\n\r\n`$globalname`\r\n\r\n```php\r\n$globalname.associndex // $globalname['associindex']\r\n$globalname.4 // $globalname[4]\r\n$globalname.param('a.b.c') // $globalname['a']['b']['c']\r\nparam($globalname,'a.b.c') // $globalname['a']['b']['c']\r\n```\r\n\r\nExample:\r\n\r\n`$globalname=30`\r\n\r\nExample Code: [examples/exampleglobal.php](examples/exampleglobal.php)\r\n```php\r\n$field1=1; // our global variable\r\n$mini=new MiniLang();\r\n$mini-\u003eseparate('when $field1\u003e0 then $field1=3'); // we prepare the language\r\n$variables=[]; // local variables\r\n$callback=new stdClass();\r\n$mini-\u003eevalAllLogic($callback,$variables); // we set the variables and run the languageand run the language\r\nvar_dump($field1); // returns 3\r\n```\r\n\r\n## Literals\r\n\r\n| Type     | Example                      |\r\n|----------|------------------------------|\r\n| Number   | 20                           |\r\n| string   | \"hello world\", 'hello world' |\r\n| stringp  | \"my name is {{var}}\"         |\r\n| function | namefunction(arg,arg)        |\r\n\r\n### Examples\r\n\r\n\u003e set var=20 and var2=\"hello\" and var3=\"hello {{var}}\" and var4=fn()\r\n\r\n\r\n\r\n### Reserved methods\r\n\r\n| Reserved word                  | Explanation                                                                                                                                          |\r\n|--------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|\r\n| null()                         | null value                                                                                                                                           |\r\n| false()                        | false value                                                                                                                                          |\r\n| true()                         | true value                                                                                                                                           |\r\n| on()                           | 1                                                                                                                                                    |\r\n| param(var,'l1.l2.l3')          | Separates an array (var) into var['l1']\\['l2']\\['l3']                                                                                                |\r\n| off()                          | 0                                                                                                                                                    |\r\n| undef()                        | -1 (for undefined)                                                                                                                                   |\r\n| flip()                         | (special value). It inverts a value ON\u003c-\u003eOFF\u003cbr\u003eUsed as value=flip()                                                                                 |\r\n| now()                          | returns the current timestamp (integer)                                                                                                              |\r\n| timer()                        | returns the current timestamp (integer)                                                                                                              |\r\n| interval()                     | returns the interval (in seconds) between the last change and now. It uses the field dateLastChange or method dateLastChange() of the callback class |\r\n| fullinterval()                 | returns the interval (in seconds) between the start of the process and now. It uses the field dateInit or method dateInit() of the callback class    |\r\n| contains()/str_contains()      | returns true if the text is contained in another text.Example: str_contains(field1,'hi')                                                             |\r\n| str_starts_with(), startwith() | returns true if the text starts with another text                                                                                                    |\r\n| str_ends_with(),endwith()      | returns true if the text ends with another text.                                                                                                     |\r\n\r\n\r\n\r\n\r\nExample: [examples/examplereserved.php](examples/examplereserved.php)  \r\n```php\r\n$mini=new MiniLang();\r\n$mini-\u003eseparate(\"when true=true then field1=timer()\"); // we prepare the language\r\n$variables=['field1'=\u003e1]; // we define regular variables\r\n$callback=new stdClass();\r\n$mini-\u003eevalAllLogic($callback,$variables); // we set the variables and run the language\r\nvar_dump($variables);\r\n```\r\n\r\n\r\nExample Timer: [examples/examplereservedtimer.php](examples/examplereservedtimer.php)  \r\n```php\r\nclass ClassWithTimer {\r\n    var $dateLastChange;\r\n    public function dateInit() {\r\n        return time();\r\n    }\r\n    public function __construct()\r\n    {\r\n        $this-\u003edateLastChange=time();\r\n        \r\n    }\r\n}\r\n$mini=new MiniLang();\r\n$mini-\u003eseparate(\"when true=true then field1=interval() and field2=fullinterval()\"); // we prepare the language\r\n$variables=['field1'=\u003e0,'field2'=\u003e0]; // we define regular variables\r\n$callback=new ClassWithTimer();\r\n$mini-\u003eevalAllLogic($callback,$variables); // we set the variables and run the language\r\nvar_dump($variables);\r\n```\r\n\r\n## init\r\n\r\nThis part of the expression allows setting a value. This expression is usually optional, and it could be omitted.\r\n\r\n\u003e It is similar to SET, but it is executed before WHERE and no matter if WHERE is valid or not.\r\n\r\n\u003e **init counter=20** where variable1=20 set variable+counter \r\n\r\n* it set the counter to 20.\r\n* And compares: variable1 is equaled to 20\r\n* If yes, then increases a variable by counter\r\n\r\n### Code:\r\n\r\n```php\r\n$mini-\u003eseparate(\"init tmp=50 when condition=1 then field1+10\"); // set tmp to 50. If condition is 1 then it increases the field1 by 10.\r\n```\r\n\r\n\r\n## where \r\n\r\nThis part of the expression adds a condition to the statement.\r\n\r\nWe can also use \"when.\"\r\n\r\n\u003e **where** expression    \r\n\r\nor\r\n\r\n\u003e **when** expression    \r\n\r\nIt's possible to compare more than a condition at the same time by separating by \"and\" or \"or.\"\r\n\r\n\u003e where v1=10 and v2=20 or v3\u003c50\r\n\r\n### Example\r\n\r\n\u003e where variable1=20 and $variable2=variable3 or function(20)=40\r\n\r\n\u003e where $field=20 and field2\u003c\u003e40 or field3=40 // sql syntax\r\n\r\n\u003e where $field==20 \u0026\u0026 field2!=40 || field3=+40 // PHP syntax\r\n\r\n\u003e where 1 // it always true\r\n\r\n### Logical expressions allowed\r\n\r\n* **equals:**  = and ==  (the symbol \"=\" and \"==\" acts similarly).\r\n* **not equals:** \u003c\u003e and !=\r\n* **less than:** \u003c\r\n* **less or equal than:** \u003c=\r\n* **greater than:** \u003e\r\n* **greater or equal than:** \u003e=\r\n* **and logic:** \"and\" and \u0026\u0026\r\n* **or logic:** \"or\" and ||\r\n\r\n\r\n## set\r\n\r\nThis part of the expression allows setting the value of a variable.  It is possible to set more than one variable at the same time by separating by \",\" or \"and.\"\r\n\r\nWe can also use the expression \"set\" or \"then\"\r\n\r\n\u003e **set** expression    \r\n\r\nor\r\n\r\n\u003e **then** expression    \r\n\r\n\u003e This part of the expression is only executed if WHERE is valid\r\n\r\n\r\n\r\n### Setting expressions allowed\r\n\r\nWe could set a variable using the next expressions:\r\n\r\n* variable=20 \r\n* variable=anothervariable\r\n* variable=20+30\r\n* variable=20-30  // it will work\r\n* variable=20+-30 // !!!! **it will not work correctly because it will consider the -30 as a negative number \"-30\" and not \"20 minus 30\"**\r\n* variable=40*50+30\r\n* variable+30 // it increases the variable by 30\r\n* variable+=anothervariable // it will increase the variable by the value of anothervariable\r\n* variable-30 // it decreases the variable by -30  Note: **+variable-30 will not work because the symbol - is an operation so +-20 is a double operator**\r\n* variable=flip() // it flips the value 0-\u003e1 or 1-\u003e0\r\n\r\nThis library does not allow complex instruction such as\r\n\r\n* variable=20+30*(20+30) // is not allowed.\r\n\r\n### Example:\r\n\r\n\u003e set variable1=20 and $variable2=variable3 and function(20)=40\r\n\r\n### Code:\r\n\r\n```php\r\n$mini-\u003eseparate(\"when condition=1 then field1+10\"); // if condition is 1 then it increases the field1 by 10.\r\n```\r\n\r\n## else\r\n\r\nThis optional part of the expression allows setting the value of a variable.  It is possible to set more than one variable at the same time by separating by \",\" or \"and\".\r\n\r\n\u003e This code is only evaluated if \"where\" returns false of if ELSE is called manually.\r\n\r\n### Example\r\n\r\n\u003e else variable1=20 and $variable2=variable3 and function(20)=40\r\n\r\n## Loop\r\n\r\nIt is possible to create a loop using the space \"loop\"\r\n\r\nTo start a loop, you must write \r\n\r\n```php\r\n$this-\u003eseparate('loop variableloop=variable_with_values');\r\n// where variable_with_values is must contains an array of values\r\n// variableloop._key will contain the key of the loop\r\n// variableloop._value will contain the value of the loop    \r\n```\r\n\r\nAnd to end the loop, you must use\r\n\r\n```php\r\n$this-\u003eseparate('loop end');\r\n```\r\n\r\nYou can escape the loop using the operator \"break\" in the \"set\" or \"else\".\r\n\r\n```php\r\n$this-\u003eseparate('when condition set break else break');\r\n```\r\n\r\n\u003e Note: Loops are only evaluated when you evaluate all the logic.  It does not work with evalLogic() and evalLogic2()\r\n\u003e\r\n\u003e Note: You can't add a condition to a loop, however you can skip a loop assigning an empty array\r\n\r\nExample:\r\n\r\n```php\r\n$this-\u003eseparate('loop $row=variable');\r\n\t$this-\u003eseparate('loop $row2=variable');\r\n\t\t$this-\u003eseparate('where op=2 then cc=2');\r\n\t\t$this-\u003eseparate('where op=3 then break'); // ends of the first loop\r\n\t$this-\u003eseparate('loop end');\r\n$this-\u003eseparate('loop end')     \r\n$obj-\u003eevalAllLogic();        \r\n```\r\n\r\n\r\n\r\n## Compiling the logic into a PHP class\r\n\r\nIt is possible to create a class with the logic created in the language.  The goal is to increase the performance of the code.\r\n\r\n### Creating the class\r\n\r\nTo generate the class, first we need to write the logic using the method **separate2()** instead of **separate()**.\r\nIt will store the logic inside an array of the instance of the class. You could use the code directly, or you could\r\nsave inside a class as follows:\r\n\r\n```php\r\n// create an instance of MiniLang\r\n$mini=new MiniLang(null);\r\n// the logic goes here\r\n$mini-\u003eseparate2('when var1=\"hello\" and comp.f=false() then var2=\"world\" '); // if var1 is equals \"hello\" then var2 is set \"world\"\r\n// and the generation of the class\r\n$r=$mini-\u003egenerateClass('ExampleBasicClass','ns\\example','ExampleBasicClass.php');\r\n```\r\n\r\nIt will save a new file called 📄 ExampleBasicClass.php  (you can check the example 📁 [example/genclass/1.examplebasic.php]())\r\n\r\n### Using the class\r\n\r\nWith the class generated, you can use this new class instead of **MiniLang**. Since this class is already compiled, then it is blazing fast. However, if you need to change the logic, then you will need to compile it again. (you can check the example 📁 [example/genclass/2.examplebasic.php]() and 📁 [example/genclass/ExampleBasicClass.php]())\r\n\r\n```php\r\n$result=['var1'=\u003e'hello'];\r\n$obj=new ExampleBasicClass(null,$result); \r\n$obj-\u003eevalAllLogic(true);\r\n```\r\n\r\nThe class will look like:\r\n\r\n```php\r\n\u003c?php\r\nnamespace ns\\example;\r\nuse eftec\\minilang\\MiniLang;\r\nclass ExampleBasicClass extends MiniLang {\r\n   public $numCode=2; // num of lines of code \r\n   public $usingClass=true; // if true then we are using a class (this class) \r\n   public function whereRun($lineCode=0) {\r\n       // ...\r\n   } // end function WhereRun\r\n   public function setRun($lineCode=0) {\r\n       // ...\r\n   } // end function SetRun\r\n   public function elseRun($lineCode=0) {\r\n       // ...\r\n   } // end function ElseRun\r\n   public function initRun($lineCode=0) {\r\n       // ...       \r\n   } // end function InitRun\r\n} // end class\r\n```\r\n\r\nWhere each method evaluates a part of the expression.\r\n\r\n## Benchmark\r\n\r\n[examples/examplebenchmark.php](examples/examplebenchmark.php)\r\n\r\nWe call some operations 1000 times.\r\n\r\n#### (reset+separate+evalAllLogic) x 1000\r\n\r\n* We call the method reset(), separate() and evalAllLogic 1000 times.\r\n* Speed: 0.028973 seconds. Comparison: 46.6% (smaller is better)\r\n\r\n#### evalAllLogic x 1000\r\n\r\n* We call the method reset() and separate() 1 time\r\n* And we call the method evalAllLogic(true) 1000 times.\r\n* Speed: 0.002387 seconds. Comparison: 3.84% (smaller is better)\r\n\r\n#### (reset+separate2+evalAllLogic2) x 1000\r\n\r\n* We call the method reset(), separate2() and evalAllLogic2() 1000 times.\r\n* Speed: 0.06217 seconds. Comparison: 100% (smaller is better). It is the slower.\r\n\r\n#### (evalAllLogic2) x 1000\r\n\r\n* We call the method reset() and separate2() 1 time\r\n* And we call the method evalAllLogic2() 1000 times.\r\n* Speed: 0.013418 seconds. Comparison: 21.58% (smaller is better)\r\n\r\n#### PHP method of class x 1000\r\n\r\n* We create a class with the method $mini-\u003egenerateClass2(); 1 time\r\n* Then, we call the class (as simple php code) 1000 times.\r\n* Speed: 0.000763 seconds. Comparison: 1.23% (smaller is better). It is the fastest method.\r\n\r\n## Documentation\r\n\r\n[Medium-Creating a new scripting language on PHP](https://medium.com/@jcastromail/creating-a-new-scripting-language-on-php-e12b9a2884da)\r\n\r\n\r\n## To-do\r\n\r\n* Documentation.\r\n\r\n## Version\r\n\r\n* 2.29 2024-08-12\r\n  * Blocked the access to system global variables. So this library will be unable to read global variables\r\ndefined as $_namevar\r\n  * Fixed an error where you call a method called \"eval\". Note, it is not possible to call the PHP function eval()\r\nusing this method, however you can define your own eval() function\r\n* 2.28 2024-03-02\r\n  * Updating dependency to PHP 7.4. The extended support of PHP 7.2 ended 3 years ago.\r\n  * Added more type hinting in the code.\r\n* 2.27   2022-09-11\r\n  * added an optional description \r\n* 2.26   2022-09-11\r\n  * added method setDictEntry() \r\n* 2.25   2022-09-03\r\n  * type hinting/validation for most methods. \r\n* 2.24   2022-08-26\r\n  * clean the code.\r\n  * [fix] $this-\u003ecaller could be a null\r\n* 2.23   2022-02-06\r\n  * [fix] update for php 8.1\r\n  * [change] update dependency for php 7.2.5 and higher.\r\n* 2.22   2021-12-05\r\n   * [fix] Added some validations and some small corrections when the value is incorrect.\r\n   * Now, every valued set is a clone and not an instance of an object (runtime)\r\n* 2.21   2021-10-03\r\n   * Now a=b-1 works however a=b+-2 will not work anymore\r\n   * Added loops\r\n   * Fixed a bug when set $var.field=20. Now it sets the value correctly\r\n   * Removed evalAllLogic2() because it is never used. Use instead evalAllLogic()\r\n* 2.20.2 2021-09-26\r\n   * Fixed the generation of the class when the number is negative.\r\n* 2.20.1 2021-09-26\r\n   * Fixed: \"\u003c\u003e\" in comparison.\r\n   * Fixed a comparison with zero. Now, zero are converted (in the PHP class) as \"0\" instead of 0. Why? It is because field==null is equals than field==0. However, field=='0' is not equals\r\n   * Class generated now it is more compressed.\r\n   * Special functions are now correctly stored in the class generated\r\n* 2.20 2021-09-26\r\n   * It allows more features when it uses a class with the values pre-calculated\r\n* 2.19 2021-09-26\r\n   * It allows to save the library into a PHP native class.\r\n* 2.18.1 2021-08-25\r\n   * Fixed a problem where the language calls a custom function and there is not a service class.   \r\n* 2.18 2021-01-16\r\n    * Some cleanups. The operator \"@\" impacts the performance of PHP, so it is better to use isset(x)?x:null rather than @x\r\n* 2.17.1 2020-10-13\r\n    * Fixed a bug when the field is a number variable.30=30    \r\n* 2.17 2020-10-13\r\n    * Added new field **$throwError** and **$errorLog**.  Now the library throws an error (by default) if an error is found, instead of a trigger_error\r\n    * The logic **AND** is optimized, if the first expression is false, then the second expression is never evaluated.\r\n    * Added array.**\\_first**, array.**\\_last** and array.**\\_count**\r\n* 2.16 2020-09-22\r\n    * The code was refactored and optimized.       \r\n* 2.15 2020-01-12\r\n    * fixed the evaluation of 'set variable=function(variable2)' where function is a php function\r\n* 2.14 2019-10-26\r\n  * Fixed the method **callFunction()** when the first argument of the function is an object but the method is defined in the caller or service class\r\n* 2.12 2019-10-21 \r\n  * New method **separate2()** and evalAllLogic2() it works with PHP's eval.\r\n  * New method generateClass2()\r\n  * separate2() and evalAllLogic2() works by parsing the tokens and converting in native PHP code.\r\n  * However, it is from x2 to x5 slower than evalAllLogic(true).\r\n  * This new motor could work by caching the evaluation in fields $setTxt,$whereTxt,$elseTxt,$initTxt\r\n  * See benchmark \r\n* 2.11 2019-10-11 method _param (class).  Also, $a.fn() is allowed.\r\n* 2.10 2019-10-07 method create()\r\n* 2.9 2019-08-28\r\n* * set field.value=20 , where field is an array works.  However, field.1=20 does not work (the parser considers .1 as a decimal)\r\n* 2.8 2019-08-26\r\n* *  if a field (inside where section) is an object. then it is possible to call the method as field.method(arg)\r\n* *  Method getDictEntry() \r\n* 2.7 2019-08-04 \r\n* * Added the methods serialize() and unserialize().\r\n* * setCaller() argument is not a reference anymore (objects are reference by default)\r\n* 2.6 2019-08-03 Now it allows \"else\". Example: \"where exp then exp else exp\"\r\n* 2.5 2019-08-03 Now it allows to reference index of an array (numeric or associative)\r\n* 2.4 2019-08-02 Added more documentation.  Now we allow unitary expression. \r\n* 2.3 2019-05-24 Fixed some bug (if the method is not defined)\r\n* 2.0 2019-05-20 Second version. It uses PHP to parse the file.   \r\n* 1.15 2019-01-06 If we add (+) two values, and they are numeric then we add. Otherwise, it concatenates.  \r\n* 1.14 2018-12-26 First open-source version.   \r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feftec%2Fminilang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feftec%2Fminilang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feftec%2Fminilang/lists"}