https://github.com/gosuperscript/axiom
https://github.com/gosuperscript/axiom
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/gosuperscript/axiom
- Owner: gosuperscript
- License: mit
- Created: 2025-05-02T12:23:06.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2026-01-07T10:35:18.000Z (6 months ago)
- Last Synced: 2026-01-11T17:44:51.777Z (6 months ago)
- Language: PHP
- Size: 186 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Axiom Library
A powerful PHP library for data transformation, type validation, and expression evaluation. This library provides a flexible framework for defining data schemas, transforming values, and evaluating complex expressions with type safety.
## Features
- **Type System**: Robust type validation and transformation for numbers, strings, booleans, lists, and dictionaries
- **Expression Evaluation**: Support for infix expressions with custom operators
- **Resolver Pattern**: Pluggable resolver system for different data sources
- **Symbol Registry**: Named value resolution and reuse
- **Operator Overloading**: Extensible operator system for custom evaluation logic
- **Monadic Error Handling**: Built on functional programming principles using Result and Option types
## Requirements
- PHP 8.4 or higher
- ext-intl extension
## Installation
```bash
composer require gosuperscript/axiom
```
## Quick Start
### Basic Type Transformation
```php
resolve($source);
$value = $result->unwrap()->unwrap(); // 42 (as integer)
```
### Expression Evaluation
```php
instance(SymbolRegistry::class, new SymbolRegistry([
'PI' => new StaticSource(3.14159),
'radius' => new StaticSource(5),
]));
// Calculate: PI * radius * radius (area of circle)
$expression = new InfixExpression(
left: new SymbolSource('PI'),
operator: '*',
right: new InfixExpression(
left: new SymbolSource('radius'),
operator: '*',
right: new SymbolSource('radius')
)
);
$result = $resolver->resolve($expression);
$area = $result->unwrap()->unwrap(); // ~78.54
```
### Using Namespaced Symbols
The `SymbolRegistry` supports namespaces to organize related symbols:
```php
new StaticSource('1.0.0'),
'debug' => new StaticSource(true),
// Math namespace
'math' => [
'pi' => new StaticSource(3.14159),
'e' => new StaticSource(2.71828),
'phi' => new StaticSource(1.61803),
],
// Constants namespace
'physics' => [
'c' => new StaticSource(299792458), // Speed of light
'g' => new StaticSource(9.80665), // Gravitational acceleration
],
]);
// Access global symbols
$version = $registry->get('version'); // Some('1.0.0')
// Access namespaced symbols
$pi = $registry->get('pi', 'math'); // Some(3.14159)
$c = $registry->get('c', 'physics'); // Some(299792458)
// Using with SymbolSource
$symbolSource = new SymbolSource('pi', 'math');
$result = $resolver->resolve($symbolSource); // ~3.14159
// Namespaces provide isolation
$registry->get('pi'); // None (no global 'pi')
$registry->get('c', 'math'); // None (no 'c' in math namespace)
```
## Core Concepts
### Types
The library provides several built-in types for data validation and coercion:
#### NumberType
Validates and coerces values to numeric types (int/float):
- Numeric strings: `"42"` → `42`
- Percentage strings: `"50%"` → `0.5`
- Numbers: `42.5` → `42.5`
#### StringType
Validates and coerces values to strings:
- Numbers: `42` → `"42"`
- Stringable objects: converted to string representation
- Special handling for null and empty values
#### BooleanType
Validates and coerces values to boolean:
- Truthy/falsy evaluation
- String representations: `"true"`, `"false"`
#### ListType and DictType
For collections and associative arrays with nested type validation.
### Type API: Assert vs Coerce
The `Type` interface provides two methods for value processing, following the [@azjezz/psl](https://github.com/azjezz/psl) pattern:
- **`assert(T $value): Result>`** - Validates that a value is already of the correct type
- **`coerce(mixed $value): Result>`** - Attempts to convert a value from any type to the target type
**When to use:**
- Use `assert()` when you expect a value to already be the correct type and want strict validation
- Use `coerce()` when you want to transform values from various input types (permissive conversion)
**Example:**
```php
$numberType = new NumberType();
// Assert - only accepts int/float
$result = $numberType->assert(42); // Ok(Some(42))
$result = $numberType->assert('42'); // Err(TransformValueException)
// Coerce - converts compatible types
$result = $numberType->coerce(42); // Ok(Some(42))
$result = $numberType->coerce('42'); // Ok(Some(42))
$result = $numberType->coerce('45%'); // Ok(Some(0.45))
```
Both methods return `Result, Throwable>` where:
- `Ok(Some(value))` - successful validation/coercion with a value
- `Ok(None())` - successful but no value (e.g., empty strings)
- `Err(exception)` - failed validation/coercion
**Note:** The `coerce()` method provides the same functionality as the previous `transform()` method.
### Sources
Sources represent different ways to provide data:
- **StaticSource**: Direct values
- **SymbolSource**: Named references to other sources (with optional namespace support)
- **TypeDefinition**: Combines a type with a source for validation and coercion
- **InfixExpression**: Mathematical/logical expressions
- **UnaryExpression**: Single-operand expressions
### Symbol Registry
The `SymbolRegistry` provides a centralized way to manage named values and organize them using namespaces:
**Key Features:**
- **Global Symbols**: Direct symbol registration without namespace isolation
- **Namespaced Symbols**: Group related symbols under namespaces for better organization
- **Isolation**: Symbols in different namespaces are isolated from each other
- **Type Safety**: Only `Source` instances can be registered
**Registration Format:**
```php
new SymbolRegistry([
'globalSymbol' => new StaticSource(value), // Global scope
'namespace' => [ // Namespaced scope
'symbol1' => new StaticSource(value1),
'symbol2' => new StaticSource(value2),
],
])
```
**Use Cases:**
- Organize constants by category (math, physics, config)
- Prevent naming conflicts between different domains
- Create clear separation between different symbol contexts
- Improve code maintainability with logical grouping
### Resolvers
Resolvers handle the evaluation of sources:
- **StaticResolver**: Resolves static values
- **ValueResolver**: Applies type coercion using the `coerce()` method
- **InfixResolver**: Evaluates binary expressions
- **SymbolResolver**: Looks up named symbols
- **DelegatingResolver**: Chains multiple resolvers together
### Operators
The library supports various operators through the overloader system:
- **Binary**: `+`, `-`, `*`, `/`, `%`, `**`
- **Comparison**: `==`, `!=`, `<`, `<=`, `>`, `>=`
- **Logical**: `&&`, `||`
- **Special**: `has`, `in`, `intersects`
## Advanced Usage
### Custom Types
Implement the `Type` interface to create custom data validations and coercions:
```php
, Throwable>` types:
- `Result::Ok(Some(value))`: Successful validation/coercion with value
- `Result::Ok(None())`: Successful validation/coercion with no value (null/empty)
- `Result::Err(exception)`: Validation/coercion failed with error
This approach ensures:
- No exceptions for normal control flow
- Explicit handling of success/failure cases
- Type-safe null handling
## License
This library is open-sourced software licensed under the [MIT license](LICENSE).
## Contributing
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.
## Security
If you discover any security-related issues, please review our [Security Policy](SECURITY.md) for information on how to responsibly report vulnerabilities.