Added base files, with the basic ability to add/remove variables from the Runtime.

This commit is contained in:
Netkas 2022-12-23 00:10:02 -05:00
parent aef02c4bff
commit 7e5207c45a
19 changed files with 906 additions and 0 deletions

14
Makefile Normal file
View file

@ -0,0 +1,14 @@
debug:
ncc build --config="debug"
release:
ncc build --config="release"
install:
ncc package install --package="build/release/net.nosial.rtex.ncc" --skip-dependencies --reinstall -y
install-debug:
ncc package install --package="build/debug/net.nosial.rtex.ncc" --skip-dependencies --reinstall -y
uninstall:
ncc package uninstall -y --package="net.nosial.rtex"

View file

@ -0,0 +1,6 @@
{
"type": "get",
"_": {
"variable": "foo"
}
}

View file

@ -0,0 +1,7 @@
{
"type": "set",
"_": {
"variable": "foo",
"value": "bar"
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace RTEX\Abstracts;
abstract class InstructionType
{
const Invoke = 'invoke';
const GetVariable = 'get';
const SetVariable = 'set';
}

View file

@ -0,0 +1,30 @@
<?php
namespace RTEX\Abstracts;
abstract class VariableTypes
{
const String = 'string';
const Integer = 'integer';
const Float = 'float';
const Boolean = 'boolean';
const Null = 'null';
const Instruction = 'instruction';
const InstructionList = 'i_instruction';
const All = [
self::String,
self::Integer,
self::Float,
self::Boolean,
self::Null,
self::Instruction,
self::InstructionList
];
}

View file

@ -0,0 +1,43 @@
<?php
namespace RTEX\Classes;
use RTEX\Exceptions\Core\UnsupportedVariableType;
use RTEX\Interfaces\InstructionInterface;
use RTEX\Objects\Program\Instructions\GetVariable;
use RTEX\Objects\Program\Instructions\SetVariable;
class InstructionBuilder
{
/**
* Constructs a new get variable instruction
*
* @param $name
* @return InstructionInterface
* @throws UnsupportedVariableType
*/
public static function getVariable($name): InstructionInterface
{
$instruction = new GetVariable();
$instruction->setVariable($name);
return $instruction;
}
/**
* Constructs a new set variable instruction
*
* @param $name
* @param $value
* @return InstructionInterface
* @throws UnsupportedVariableType
*/
public static function setVariable($name, $value): InstructionInterface
{
$instruction = new SetVariable();
$instruction->setVariable($name);
$instruction->setValue($value);
return $instruction;
}
}

View file

@ -0,0 +1,81 @@
<?php
namespace RTEX\Classes;
use RTEX\Abstracts\InstructionType;
use RTEX\Abstracts\VariableTypes;
use RTEX\Exceptions\Core\MalformedInstructionException;
use RTEX\Exceptions\Core\UnsupportedVariableType;
use RTEX\Interfaces\InstructionInterface;
use RTEX\Objects\Program\Instructions\GetVariable;
use RTEX\Objects\Program\Instructions\SetVariable;
class Utilities
{
/**
* Determines the type of variable, throws an exception if the type is not supported
*
* @param $input
* @return string
* @throws UnsupportedVariableType
*/
public static function determineType($input): string
{
if ($input instanceof InstructionInterface)
return VariableTypes::Instruction;
if (is_string($input))
return VariableTypes::String;
if (is_int($input))
return VariableTypes::Integer;
if (is_float($input))
return VariableTypes::Float;
if (is_bool($input))
return VariableTypes::Boolean;
if (is_null($input))
return VariableTypes::Null;
throw new UnsupportedVariableType(gettype($input));
}
/**
* Returns a supported variable type to an array representation
*
* @param $input
* @return array|mixed
* @throws UnsupportedVariableType
*/
public static function toArray($input)
{
return match (self::determineType($input))
{
VariableTypes::Instruction => $input->toArray(),
default => $input,
};
}
/**
* Constructs an instruction from an array representation
*
* @param array $array
* @return InstructionInterface
* @throws MalformedInstructionException
* @throws UnsupportedVariableType
*/
public static function constructInstruction(array $array): InstructionInterface
{
if(!isset($array['type']))
throw new MalformedInstructionException(sprintf('Instruction type not specified'));
if(!isset($array['_']))
throw new MalformedInstructionException(sprintf('Instruction data not specified'));
switch($array['type'])
{
case InstructionType::GetVariable:
return GetVariable::fromArray($array['_']);
case InstructionType::SetVariable:
return SetVariable::fromArray($array['_']);
default:
throw new MalformedInstructionException(sprintf('Instruction type "%s" not supported', $array['type']));
}
}
}

View file

@ -0,0 +1,31 @@
<?php
namespace RTEX\Classes;
use Exception;
use RTEX\Abstracts\VariableTypes;
use RTEX\Interfaces\InstructionInterface;
class Validate
{
/**
* Determines if the input is a supported variable type
*
* @param $type
* @return bool
*/
public static function supportedVariableType($type): bool
{
try
{
Utilities::determineType($type);
}
catch(Exception $e)
{
unset($e);
return false;
}
return true;
}
}

89
src/RTEX/Engine.php Normal file
View file

@ -0,0 +1,89 @@
<?php
namespace RTEX;
use LogLib\Log;
use RTEX\Abstracts\VariableTypes;
use RTEX\Classes\Utilities;
use RTEX\Exceptions\Core\UnsupportedVariableType;
use RTEX\Interfaces\InstructionInterface;
use RTEX\Objects\Environment;
use RTEX\Objects\Program;
class Engine
{
/**
* @var Program
*/
private $Program;
/**
* @var Environment
*/
private $Environment;
public function __construct(Program $program)
{
$this->Program = $program;
$this->Environment = new Environment();
}
/**
* Executes the program by running the main script of the program
*
* @return void
* @throws UnsupportedVariableType
*/
public function run()
{
foreach($this->Program->getMain()->getInstructions() as $instruction)
{
$this->eval($instruction);
}
}
/**
* Evaluates the variable or instruction and returns the result
*
* @param $input
* @return mixed
* @throws UnsupportedVariableType
* @noinspection PhpMissingReturnTypeInspection
*/
public function eval($input)
{
switch(Utilities::determineType($input))
{
case VariableTypes::Instruction:
/** @var InstructionInterface $input */
return $input->eval($this);
default:
return $input;
}
}
/**
* @return Program
*/
public function getProgram(): Program
{
return $this->Program;
}
/**
* @param Program $Program
*/
public function setProgram(Program $Program): void
{
$this->Program = $Program;
}
/**
* @return Environment
*/
public function getEnvironment(): Environment
{
return $this->Environment;
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace RTEX\Exceptions\Core;
class MalformedInstructionException extends \Exception
{
/**
* MalformedInstructionException constructor.
*
* @param string $message
*/
public function __construct(string $message)
{
parent::__construct($message);
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace RTEX\Exceptions\Core;
class UnsupportedInstructionException extends \Exception
{
/**
* UnsupportedInstructionException constructor.
*
* @param string $message
*/
public function __construct(string $message)
{
parent::__construct($message);
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace RTEX\Exceptions\Core;
use Exception;
class UnsupportedVariableType extends Exception
{
public function __construct($type)
{
parent::__construct("Unsupported variable type: $type");
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace RTEX\Interfaces;
use RTEX\Abstracts\InstructionType;
use RTEX\Engine;
interface InstructionInterface
{
/**
* Returns the type of instruction
*
* @return string
* @see InstructionType
*/
public function getType(): string;
/**
* Returns an array representation of the object
*
* @return array
*/
public function toArray(): array;
/**
* Constructs a new instruction from an array representation
*
* @param array $data
* @return InstructionInterface
*/
public static function fromArray(array $data): InstructionInterface;
/**
* Evaluates the instruction and returns the result of the evaluation
*
* @param Engine $engine
* @return mixed
*/
public function eval(Engine $engine);
}

View file

@ -0,0 +1,81 @@
<?php
namespace RTEX\Objects;
use LogLib\Log;
class Environment
{
/**
* @var array
*/
private $RuntimeVariables;
/**
* Public Constructor
*/
public function __construct()
{
$this->RuntimeVariables = [];
}
/**
* Returns the value of the specified variable
*
* @param string $name
* @return mixed
*/
public function getRuntimeVariable(string $name)
{
Log::debug('net.nosial.rtex', $name);
return $this->RuntimeVariables[$name];
}
/**
* Sets the value of the specified variable
*
* @param string $name
* @param mixed $value
*/
public function setRuntimeVariable(string $name, $value): void
{
Log::debug('net.nosial.rtex', $name);
$this->RuntimeVariables[$name] = $value;
}
/**
* Clears the value of the specified variable
*
* @return void
*/
public function clearRuntimeVariables(): void
{
$this->RuntimeVariables = [];
}
/**
* Returns an array representation of the object
*
* @return array
*/
public function toArray(): array
{
return [
'variables' => $this->RuntimeVariables
];
}
/**
* Constructs a new environment from an array representation
*
* @param array $data
* @return Environment
*/
public static function fromArray(array $data): Environment
{
$environment = new Environment();
$environment->RuntimeVariables = $data['variables'];
return $environment;
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace RTEX\Objects;
use RTEX\Objects\Program\Script;
class Program
{
/**
* The main script of the program to execute
*
* @var Script
*/
private $Main;
/**
* Public Constructor
*/
public function __construct()
{
$this->Main = new Script();
}
/**
* Returns an array representation of the object
*
* @return array
*/
public function toArray(): array
{
return [
'main' => $this->Main->toArray()
];
}
/**
* Constructs a new program from an array representation
*
* @param array $data
* @return Program
*/
public static function fromArray(array $data): Program
{
$program = new Program();
$program->Main = Script::fromArray($data['main']);
return $program;
}
/**
* @return Script
*/
public function getMain(): Script
{
return $this->Main;
}
/**
* Saves the program to a file
*
* @param string $path
* @return void
*/
public function save(string $path): void
{
file_put_contents($path, json_encode($this->toArray()));
}
/**
* Loads a program from a file
*
* @param string $path
* @return Program
*/
public static function load(string $path): Program
{
return self::fromArray(json_decode(file_get_contents($path), true));
}
}

View file

@ -0,0 +1,94 @@
<?php
namespace RTEX\Objects\Program\Instructions;
use RTEX\Abstracts\InstructionType;
use RTEX\Classes\Utilities;
use RTEX\Engine;
use RTEX\Exceptions\Core\UnsupportedVariableType;
use RTEX\Interfaces\InstructionInterface;
class GetVariable implements InstructionInterface
{
/**
* The name of the variable to select
*
* @var string|integer|boolean|float|null|InstructionInterface|InstructionInterface[]
*/
private $Variable;
/**
* Returns the type of instruction
*
* @return string
* @see InstructionType
*/
public function getType(): string
{
return InstructionType::GetVariable;
}
/**
* Returns an array representation of the object
*
* @return array
* @throws UnsupportedVariableType
*/
public function toArray(): array
{
return [
'type' => $this->getType(),
'_' => [
'variable' => Utilities::toArray($this->Variable)
]
];
}
/**
* Returns
*
* @return bool|float|int|InstructionInterface|string|null
* @noinspection PhpMissingReturnTypeInspection
*/
public function getVariable()
{
return $this->Variable;
}
/**
* @param bool|float|int|InstructionInterface|string|null $variable
* @throws UnsupportedVariableType
*/
public function setVariable($variable): void
{
switch(Utilities::determineType($variable))
{
default:
$this->Variable = $variable;
}
}
/**
* Constructs a new GetVariable instruction from an array representation
*
* @throws UnsupportedVariableType
*/
public static function fromArray(array $data): InstructionInterface
{
$instruction = new GetVariable();
$instruction->setVariable($data['variable'] ?? null);
return $instruction;
}
/**
* @inheritDoc
*/
public function eval(Engine $engine)
{
return $engine->getEnvironment()->getRuntimeVariable(
$engine->eval($this->Variable)
);
}
}

View file

@ -0,0 +1,116 @@
<?php /** @noinspection PhpReturnDocTypeMismatchInspection */
namespace RTEX\Objects\Program\Instructions;
use RTEX\Abstracts\InstructionType;
use RTEX\Classes\Utilities;
use RTEX\Engine;
use RTEX\Exceptions\Core\UnsupportedVariableType;
use RTEX\Interfaces\InstructionInterface;
class SetVariable implements InstructionInterface
{
/**
* The name of the variable to set
*
* @var string|integer|boolean|float|null|InstructionInterface
*/
private $Variable;
/**
* The value to set the variable to
*
* @var string|integer|boolean|float|null|InstructionInterface
*/
private $Value;
/**
* The name of the variable to set
*
* @return string
*/
public function getType(): string
{
return InstructionType::SetVariable;
}
/**
* Returns an array representation of the object
*
* @return array
* @throws UnsupportedVariableType
*/
public function toArray(): array
{
return [
'type' => $this->getType(),
'_' => [
'variable' => Utilities::toArray($this->Variable),
'value' => Utilities::toArray($this->Value)
]
];
}
/**
* @inheritDoc
*/
public static function fromArray(array $data): InstructionInterface
{
$instruction = new self();
$instruction->setVariable($data['variable'] ?? null);
$instruction->setValue($data['value'] ?? null);
return $instruction;
}
/**
* @return bool|float|int|InstructionInterface|InstructionInterface[]|string|null
*/
public function getVariable()
{
return $this->Variable;
}
/**
* @param bool|float|int|InstructionInterface|InstructionInterface|string|null $variable
* @throws UnsupportedVariableType
* @noinspection PhpMissingParamTypeInspection
*/
public function setVariable($variable): void
{
Utilities::determineType($variable);
$this->Variable = $variable;
}
/**
* @return bool|float|int|InstructionInterface|InstructionInterface[]|string|null
*/
public function getValue()
{
return $this->Value;
}
/**
* @param bool|float|int|InstructionInterface|InstructionInterface|string|null $value
* @throws UnsupportedVariableType
* @noinspection PhpMissingParamTypeInspection
*/
public function setValue($value): void
{
Utilities::determineType($value);
$this->Value = $value;
}
/**
* @param Engine $engine
* @return mixed|void
* @throws UnsupportedVariableType
*/
public function eval(Engine $engine)
{
$engine->getEnvironment()->setRuntimeVariable(
$engine->eval($this->Variable),
$engine->eval($this->Value)
);
}
}

View file

@ -0,0 +1,133 @@
<?php
namespace RTEX\Objects\Program;
use RTEX\Classes\Utilities;
use RTEX\Exceptions\Core\MalformedInstructionException;
use RTEX\Exceptions\Core\UnsupportedVariableType;
use RTEX\Interfaces\InstructionInterface;
class Script
{
/**
* An array of instructions to execute in order
*
* @var InstructionInterface[]
*/
private $Instructions;
/**
* Public Constructor
*/
public function __construct()
{
$this->Instructions = [];
}
/**
* Adds an instruction to the script and returns the index of the instruction
*
* @param InstructionInterface $instruction
* @return int
*/
public function addInstruction(InstructionInterface $instruction): int
{
return array_push($this->Instructions, $instruction);
}
/**
* Returns the instruction at the specified index
*
* @param int $index
* @return InstructionInterface
*/
public function getInstruction(int $index): InstructionInterface
{
return $this->Instructions[$index];
}
/**
* Returns the number of instructions in the script
*
* @return int
*/
public function getInstructionCount(): int
{
return count($this->Instructions);
}
/**
* Deletes the instruction at the specified index
*
* @param int $index
* @return void
*/
public function deleteInstruction(int $index): void
{
unset($this->Instructions[$index]);
}
/**
* Replaces the instruction at the specified index
*
* @param int $index
* @param InstructionInterface $instruction
* @return void
*/
public function replaceInstruction(int $index, InstructionInterface $instruction): void
{
$this->Instructions[$index] = $instruction;
}
/**
* Clears all instructions from the script
*
* @return void
*/
public function clear()
{
$this->Instructions = [];
}
/**
* Returns an array representation of the object
*
* @return array
*/
public function toArray(): array
{
$instructions = [];
foreach ($this->Instructions as $instruction)
{
$instructions[] = $instruction->toArray();
}
return $instructions;
}
/**
* Constructs a script from an array representation
*
* @param array $data
* @return Script
* @throws MalformedInstructionException
* @throws UnsupportedVariableType
*/
public static function fromArray(array $data): Script
{
$script = new Script();
foreach ($data as $instruction)
$script->addInstruction(Utilities::constructInstruction($instruction));
return $script;
}
/**
* @return array|InstructionInterface[]
*/
public function getInstructions(): array
{
return $this->Instructions;
}
}

7
src/RTEX/RTEX.php Normal file
View file

@ -0,0 +1,7 @@
<?php
namespace RTEX;
class RTEX
{
}