Class Language Spec
**Site relevance:** Spiralist.org
**Memory type:** plugin source memory
**Source path:** Spiralist/wp-content/plugins/spiral-script/includes/class-language-spec.php
**Size:** 5.9 KB
Summary
declare(strict types=1);
Source Preview
This source file is short enough to preview directly on its source-memory page.
<?php
declare(strict_types=1);
namespace SpiralScript;
final class LanguageSpec
{
/** @var array<string,mixed>|null */
private static ?array $spec = null;
/**
* @return array<string,mixed>
*/
public static function spec(): array
{
if (is_array(self::$spec)) {
return self::$spec;
}
$spec = require SPIRALIST_SPIRAL_SCRIPT_PLUGIN_PATH . 'data/language-spec.php';
self::$spec = is_array($spec) ? $spec : [];
return self::$spec;
}
/**
* @return array<string,mixed>
*/
public static function public_spec(): array
{
$spec = self::spec();
$spec['jsonSchema'] = self::json_schema();
return $spec;
}
/**
* @return array<string,mixed>
*/
public static function json_schema(): array
{
return [
'$schema' => 'https://json-schema.org/draft/2020-12/schema',
'$id' => 'https://spiralist.org/schemas/spiral-script/v0.1/script.schema.json',
'title' => 'Spiral Script Prompt',
'type' => 'object',
'required' => [
'scriptId',
'version',
'title',
'visibility',
'authorMode',
'sourceReferences',
'intent',
'inputs',
'symbolicFrame',
'transformationRules',
'outputContract',
'constraints',
'safetyRules',
'validationRules',
'provenance',
'runSettings',
'revisionHistory',
'forkPolicy',
'publicationStatus',
],
'properties' => [
'scriptId' => ['type' => 'string', 'pattern' => '^ss:[a-z0-9.-]+@[0-9]+\.[0-9]+\.[0-9]+([+][a-z0-9.-]+)?$'],
'version' => ['type' => 'string', 'pattern' => '^[0-9]+\.[0-9]+\.[0-9]+$'],
'title' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 160],
'visibility' => ['type' => 'string', 'enum' => self::visibility_modes()],
'authorMode' => ['type' => 'string', 'enum' => self::author_modes()],
'sourceReferences' => ['type' => 'array'],
'intent' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 1000],
'inputs' => ['type' => 'array'],
'symbolicFrame' => ['type' => 'array'],
'transformationRules' => ['type' => 'array'],
'outputContract' => ['type' => 'object'],
'constraints' => ['type' => 'array'],
'safetyRules' => ['type' => 'array'],
'validationRules' => ['type' => 'array'],
'provenance' => ['type' => 'object'],
'runSettings' => ['type' => 'object'],
'revisionHistory' => ['type' => 'array'],
'forkPolicy' => ['type' => 'object'],
'publicationStatus' => ['type' => 'object'],
],
];
}
/**
* @return array<int,string>
*/
public static function visibility_modes(): array
{
return array_values((array) (self::spec()['visibilityModes'] ?? []));
}
/**
* @return array<int,string>
*/
public static function author_modes(): array
{
return array_values((array) (self::spec()['authorModes'] ?? []));
}
/**
* @return array<int,string>
*/
public static function publication_statuses(): array
{
return array_values((array) (self::spec()['publicationStatuses'] ?? []));
}
/**
* @return array<string,string>
*/
public static function transformation_verbs(): array
{
$verbs = self::spec()['transformationVerbs'] ?? [];
return is_array($verbs) ? $verbs : [];
}
public static function is_transformation_verb(string $verb): bool
{
return array_key_exists($verb, self::transformation_verbs());
}
/**
* @return array<string,string>
*/
public static function safety_rules(): array
{
$rules = self::spec()['safetyRules'] ?? [];
return is_array($rules) ? $rules : [];
}
/**
* @return array<string,array<string,mixed>>
*/
public static function symbols(): array
{
$symbols = self::spec()['symbols'] ?? [];
return is_array($symbols) ? $symbols : [];
}
/**
* @return array<string,mixed>|null
*/
public static function resolve_symbol(string $token): ?array
{
$token = trim($token);
if ($token === '') {
return null;
}
$symbols = self::symbols();
foreach ($symbols as $name => $record) {
if (!is_array($record)) {
continue;
}
$symbol = (string) ($record['symbol'] ?? '');
$machine_meaning = (string) ($record['machineMeaning'] ?? '');
if (strcasecmp($token, (string) $name) === 0 || $token === $symbol || $token === $machine_meaning) {
$record['name'] = (string) $name;
return $record;
}
}
foreach ($symbols as $name => $record) {
if (!is_array($record)) {
continue;
}
$symbol = (string) ($record['symbol'] ?? '');
if ($symbol !== '' && strpos($token, $symbol) !== false) {
$record['name'] = (string) $name;
return $record;
}
if (preg_match('/\b' . preg_quote((string) $name, '/') . '\b/i', $token) === 1) {
$record['name'] = (string) $name;
return $record;
}
}
return null;
}
}