NAME

Venus::Type - Type Class

ABSTRACT

Type Class for Perl 5

SYNOPSIS

package main;

use Venus::Type;

my $type = Venus::Type->new;

# bless({}, "Venus::Type")

DESCRIPTION

This package provides a mechanism for parsing, generating, and validating data type expressions and subroutine signatures.

Types

The following types are supported by the parser:

Simple Types

Simple types are basic types supported directly without requiring parameters or nested structures. They include:

any

Accepts any value.

Example expression: any

Example parsed output: ["any"]

array

Accepts array references.

Example expression: array

Example parsed output: ["array"]

arrayref

Accepts array references.

Example expression: arrayref

Example parsed output: ["arrayref"]

bool

Accepts boolean values (true or false).

Example expression: bool

Example parsed output: ["bool"]

boolean

Accepts boolean values (true or false).

Example expression: boolean

Example parsed output: ["boolean"]

code

Accepts code references.

Example expression: code

Example parsed output: ["code"]

coderef

Accepts code references.

Example expression: coderef

Example parsed output: ["coderef"]

defined

Accepts any value that is defined (not undefined).

Example expression: defined

Example parsed output: ["defined"]

dirhandle

Accepts dirhandle values.

Example expression: dirhandle

Example parsed output: ["dirhandle"]

filehandle

Accepts filehandle values.

Example expression: filehandle

Example parsed output: ["filehandle"]

float

Accepts floating-point values.

Example expression: float

Example parsed output: ["float"]

glob

Accepts typeglob values.

Example expression: glob

Example parsed output: ["glob"]

hash

Accepts hash references.

Example expression: hash

Example parsed output: ["hash"]

hashref

Accepts hash references.

Example expression: hashref

Example parsed output: ["hashref"]

identity

Accepts objects of the specified type.

Example expression: identity[Example]

Example parsed output: ["identity", "Example"]

number

Accepts numeric values (integers and floats).

Example expression: number

Example parsed output: ["number"]

object

Accepts package (or class) instances.

Example expression: object

Example parsed output: ["object"]

package

Accepts package names.

Example expression: package

Example parsed output: ["package"]

reference

Accepts any reference type.

Example expression: reference

Example parsed output: ["reference"]

regexp

Accepts regular expression objects.

Example expression: regexp

Example parsed output: ["regexp"]

scalar

Accepts scalar references.

Example expression: scalar

Example parsed output: ["scalar"]

scalarref

Accepts scalar references.

Example expression: scalarref

Example parsed output: ["scalarref"]

string

Accepts string values.

Example expression: string

Example parsed output: ["string"]

undef

Accepts undefined values.

Example expression: undef

Example parsed output: ["undef"]

value

Accepts defined, non-reference, scalar values.

Example expression: value

Example parsed output: ["value"]

yesno

Accepts a string value, case-insensitive, that is either y, yes, 1, n, no, or 0.

Example expression: yesno

Example parsed output: ["yesno"]

Complex Types

Complex types are types that can take one or more type expressions as arguments or involve nesting. These include:

attributes

Accepts objects with attributes matching the specified names and types.

Example expression: attributes[name, string]

Example parsed output: ["attributes", "name", "string"]

consumes

Accepts objects that consume the specified role.

Example expression: consumes[Example::Role]

Example parsed output: ["consumes", "Example::Role"]

either

Accepts one of the provided type expressions.

Example expression: string | number

Example parsed output: ["either", "string", "number"]

hashkeys

Accepts hashes containing keys whose values match the specified types.

Example expression: hashkeys[name, string]

Example parsed output: ["hashkeys", "name", "string"]

includes

Accepts all of the provided type expressions.

Example expression: string + number

Example parsed output: ["includes", "string", "number"]

inherits

Accepts objects that inherit from the specified type.

Example expression: inherits[Example]

Example parsed output: ["inherits", "Example"]

integrates

Accepts objects that support the "does" behavior and consume the specified role.

Example expression: integrates[Example::Role]

Example parsed output: ["integrates", "Example::Role"]

maybe

Accepts the provided type or an undefined value.

Example expression: maybe[string]

Example parsed output: ["maybe", "string"]

routines

Accepts an object having all of the routines specified.

Example expression: routines[new]

Example parsed output: ["routines", "new"]

tuple

Accepts array references that conform to a tuple specification.

Example expression: tuple[string, number]

Example parsed output: ["tuple", "string", "number"]

within

Accepts array references, hash references, or mappables (i.e. objects derived from classes which consume the "mappable" role, see Venus::Role::Mappable), whose values match the specified type expression.

Example expression: within[arrayref, string]

Example parsed output: ["within", "arrayref", "string"]

Type Expressions

A type expression is a combination of one or more simple or complex types, optionally with parameters, that describes a data structure or value expected by the system.

Expression Components

  • either - Denoted by a pipe symbol, |, and used to accept one of multiple types. For example: string | number.

  • includes - Denoted by a plus symbol, +, and used to require all of the specified types. For example: string + number.

  • string-simple - A simple string is an unquoted string matching the regular expression: ^\w+$.

  • string-quoted - A quoted string is either single-quoted or double-quoted. For example: 'name' or "name".

  • string-package - A string-package refers to a Perl package name, following the regular expression: ^[A-Z](?:(?:\w|::)*[a-zA-Z0-9])?$.

  • parameterized - A parameterized type includes a type followed by an open square bracket, [, followed by one or more type expressions separated by commas, and a closing square bracket, ]. For example, within[arrayref, string] means an array reference where each element is a string.

Subroutine Signatures

A subroutine signature is a string that defines the name of a subroutine, its input types, and its output types. The parser supports subroutine signatures in the following format: name(input_type $variable, ...) (output_type).

  • name - The name of the subroutine.

  • () - Parentheses enclosing the input type expressions.

  • input_type - Each input is a type expression followed by a Perl variable (e.g., $variable).

  • , - If more than one input exists, they are separated by a comma.

  • () - Parentheses enclosing the output type expression.

  • output_type - The type expression for the output of the subroutine.

Signature Examples

chmod(string $mode) (Venus::Path)

A subroutine chmod takes a single argument: a string variable $mode, and returns a Venus::Path.

copy(string | Venus::Path $path) (Venus::Path)

A subroutine copy takes an argument $path, which can be either a string or a Venus::Path object, and returns a Venus::Path.

directories() (within[arrayref, Venus::Path])

A subroutine directories takes no arguments and returns a list of Venus::Path objects contained in an array reference.

find(string | regexp $expr) (within[arrayref, Venus::Path])

A subroutine find takes a string or regular expression as input and returns a list of Venus::Path objects contained in an array reference.

mkdir(maybe[string] $mode) (Venus::Path)

A subroutine mkdir accepts an optional string argument $mode (or undef) and returns a Venus::Path object.

root(string $spec, string $base) (maybe[Venus::Path])

A subroutine root accepts two string arguments and may return a Venus::Path object or undef.

Usage Examples

Parsing an "includes" expression
my $parsed = $type->expression('object + within[arrayref, either[string, number]]');

# ['includes', 'object', ['within', 'arrayref', ['either', 'string', 'number']]]
Generating an "includes" expression
my $generated = $type->expression(['includes', 'object', ['within', 'arrayref', ['either', 'string', 'number']]]);

# object + within[arrayref, either[string, number]]
Parsing an "either" expression
my $parsed = $type->expression('string | number | within[arrayref, string | number]');

# ['either', 'string', 'number', ['within', 'arrayref', ['either', 'string', 'number']]]
Generating an "either" expression
my $generated = $type->expression(['either', 'string', 'number', ['within', 'arrayref', ['either', 'string', 'number']]]);

# string | number | within[arrayref, string | number]
Parsing a subroutine signature
my $parsed = $type->signature('copy(string | Venus::Path $path) (Venus::Path)');

# ['copy', [['string | Venus::Path', '$path']], ['Venus::Path']]
Generating a subroutine signature
my $generated = $type->signature(['copy', [['string | Venus::Path', '$path']], ['Venus::Path']]);

# copy(string | Venus::Path $path) (Venus::Path)

INHERITS

This package inherits behaviors from:

Venus::Kind::Utility

INTEGRATES

This package integrates behaviors from:

Venus::Role::Buildable

METHODS

This package provides the following methods:

assert

assert(string $expr) (Venus::Assert)

Returns a Venus::Assert object based on the type expression provided.

Since 4.15

assert example 1
# given: synopsis;

my $assert = $type->assert('string | number');

# bless(..., "Venus::Assert")

check

check(string $expr) (Venus::Check)

Returns a Venus::Check object based on the type expression provided.

Since 4.15

check example 1
# given: synopsis;

my $check = $type->check('string | number');

# bless(..., "Venus::Check")

coercion

coercion(string $expr) (Venus::Coercion)

Returns a Venus::Coercion object based on the type expression provided.

Since 4.15

coercion example 1
# given: synopsis;

my $coercion = $type->coercion('string | number');

# bless(..., "Venus::Coercion")

constraint

constraint(string $expr) (Venus::Constraint)

Returns a Venus::Constraint object based on the type expression provided.

Since 4.15

constraint example 1
# given: synopsis;

my $constraint = $type->constraint('string | number');

# bless(..., "Venus::Constraint")

generate_expression

generate_expression(arrayref $expr) (string)

Returns the type expression for the data structure (representing a type expression) provided.

Since 4.15

generate_expression example 1
# given: synopsis;

my $generate_expression = $type->generate_expression(["string"]);

# "string"
generate_expression example 2
# given: synopsis;

my $generate_expression = $type->generate_expression(["either", "string", "number"]);

# "string | number"
generate_expression example 3
# given: synopsis;

my $generate_expression = $type->generate_expression([
  "tuple", "number", ["either", ["within", "arrayref", "hashref"], "arrayref"], "coderef",
]);

# "tuple[number, within[arrayref, hashref] | arrayref, coderef]"

generate_signature

generate_signature(arrayref $expr) (string)

Returns the subroutine signature for the data structure (representing a subroutine signature) provided.

Since 4.15

generate_signature example 1
# given: synopsis;

my $generate_signature = $type->generate_signature(["output", [], []]);

# "output() ()"
generate_signature example 2
# given: synopsis;

my $generate_signature = $type->generate_signature(["count", [], [["number"]]]);

# "count() (number)"
generate_signature example 3
# given: synopsis;

my $generate_signature = $type->generate_signature(["count", [["coderef", "\$filter"]], [["number"]]]);

# "count(coderef $filter) (number)"

generate_signature_input

generate_signature_input(arrayref $expr) (string)

Returns the subroutine signature input expression for the data structure (representing a subroutine signature input expression) provided.

Since 4.15

generate_signature_input example 1
# given: synopsis;

my $generate_signature_input = $type->generate_signature_input([["string", "\$string"]]);

# "string $string"
generate_signature_input example 2
# given: synopsis;

my $generate_signature_input = $type->generate_signature_input([["string", "\$string"], ["number", "\$number"]]);

# "string $string, number $number"
generate_signature_input example 3
# given: synopsis;

my $generate_signature_input = $type->generate_signature_input([
  ["string", "\$string"], ["coderef", "\$filter"]
]);

# "string $string, coderef $filter"

generate_signature_output

generate_signature_output(arrayref $expr) (string)

Returns the subroutine signature output expression for the data structure (representing a subroutine signature output expression) provided.

Since 4.15

generate_signature_output example 1
# given: synopsis;

my $generate_signature_output = $type->generate_signature_output([["string", "\$string"]]);

# "string $string"
generate_signature_output example 2
# given: synopsis;

my $generate_signature_output = $type->generate_signature_output([["string", "\$string"], ["number", "\$number"]]);

# "string $string, number $number"
generate_signature_output example 3
# given: synopsis;

my $generate_signature_output = $type->generate_signature_output([
  ["string", "\$string"], ["coderef", "\$filter"]
]);

# "string $string, coderef $filter"

new

new(hashref $data) (Venus::Type)

Constructs a new object.

Since 4.15

new example 1
package main;

use Venus::Type;

my $type = Venus::Type->new;

# bless({}, "Venus::Type")

parse_expression

parse_expression(string $expr) (arrayref)

Returns the parsed data structure based on the type expression provided.

Since 4.15

parse_expression example 1
# given: synopsis;

my $parse_expression = $type->parse_expression('string | number | Example');

# ["either", "string", "number", "Example"]
parse_expression example 2
# given: synopsis;

my $parse_expression = $type->parse_expression('scalarref | object + string');

# ["either", "scalarref", ["includes", "object", "string"]]
parse_expression example 3
# given: synopsis;

my $parse_expression = $type->parse_expression('within[arrayref, string | number]');

# ["within", "arrayref", ["either", "string", "number"]]
parse_expression example 4
# given: synopsis;

my $parse_expression = $type->parse_expression('attributes[name, string, age, number]');

# ["attributes", "name", "string", "age", "number"]
parse_expression example 5
# given: synopsis;

my $parse_expression = $type->parse_expression('tuple[string, arrayref, code]');

# ["tuple", "string", "arrayref", "code"]
parse_expression example 6
# given: synopsis;

my $parse_expression = $type->parse_expression('inherits[Example] + attributes[value, string]');

# ["includes", ["inherits", "Example"], ["attributes", "value", "string"]]
parse_expression example 7
# given: synopsis;

my $parse_expression = $type->parse_expression('consumes[Example::Role] | identity[Example]');

# ["either", ["consumes", "Example::Role"], ["identity", "Example"]]
parse_expression example 8
# given: synopsis;

my $parse_expression = $type->parse_expression('either[tuple[string, number], coderef]');

# ["either", ["tuple", "string", "number"], "coderef"]
parse_expression example 9
# given: synopsis;

my $parse_expression = $type->parse_expression('within[hashref, attributes["name", string]]');

# ["within", "hashref", ["attributes", "name", "string"]]
parse_expression example 10
# given: synopsis;

my $parse_expression = $type->parse_expression('maybe[arrayref] | either[scalar, code]');

# ["either", ["maybe", "arrayref"], ["either", "scalar", "code"]]

parse_signature

parse_signature(string $expr) (arrayref)

Returns the parsed data structure based on the subroutine signature provided.

Since 4.15

parse_signature example 1
# given: synopsis;

my $parse_signature = $type->parse_signature('print(string @values) (boolean)');

# ["print", [["string", "\@values"]], [["boolean"]]]
parse_signature example 2
# given: synopsis;

my $parse_signature = $type->parse_signature('chmod(string $mode) (Venus::Path)');

# ["chmod", [["string", "\$mode"]], [["Venus::Path"]]]
parse_signature example 3
# given: synopsis;

my $parse_signature = $type->parse_signature('copy(string | Venus::Path $path) (Venus::Path)');

# ["copy", [["string | Venus::Path", "\$path"]], [["Venus::Path"]]]
parse_signature example 4
# given: synopsis;

my $parse_signature = $type->parse_signature('find(string | regexp $expr) (within[arrayref, Venus::Path])');

# ["find", [["string | regexp", "\$expr"]], [["within[arrayref, Venus::Path]"]]]
parse_signature example 5
# given: synopsis;

my $parse_signature = $type->parse_signature('mkdir(maybe[string] $mode) (Venus::Path)');

# ["mkdir", [["maybe[string]", "\$mode"]], [[ "Venus::Path" ]]]
parse_signature example 6
# given: synopsis;

my $parse_signature = $type->parse_signature('open(any @data) (FileHandle)');

# ["open", [["any", "\@data"]], [["FileHandle"]]]
parse_signature example 7
# given: synopsis;

my $parse_signature = $type->parse_signature('root(string $spec, string $base) (maybe[Venus::Path])');

# ["root", [["string", "\$spec"], ["string", "\$base"]], [["maybe[Venus::Path]"]]]
parse_signature example 8
# given: synopsis;

my $parse_signature = $type->parse_signature('extension(string $name) (string | Venus::Path)');

# ["extension", [["string", "\$name"]], [["string | Venus::Path"]]]
parse_signature example 9
# given: synopsis;

my $parse_signature = $type->parse_signature('count()');

# Exception! isa Venus::Type::Error (see error_on_signature_parse)
may raise Venus::Type::Error on.signature.parse
package main;

use Venus::Type;

my $type = Venus::Type->new;

$type->parse_signature('count()');

# Error! (on.signature.parse)

parse_signature_input

parse_signature_input(string $expr) (arrayref)

Returns the parsed data structure for the input type expressions in the subroutine signature provided.

Since 4.15

parse_signature_input example 1
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('print(string @values) (boolean)');

# ["string"]
parse_signature_input example 2
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('chmod(string $mode) (Venus::Path)');

# ["string"]
parse_signature_input example 3
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('copy(string | Venus::Path $path) (Venus::Path)');

# ["string | Venus::Path"]
parse_signature_input example 4
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('find(string | regexp $expr) (within[arrayref, Venus::Path])');

# ["string | regexp"]
parse_signature_input example 5
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('mkdir(maybe[string] $mode) (Venus::Path)');

# ["maybe[string]"]
parse_signature_input example 6
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('open(any @data) (FileHandle)');

# ["any"]
parse_signature_input example 7
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('root(string $spec, string $base) (maybe[Venus::Path])');

# ["string", "string"]
parse_signature_input example 8
# given: synopsis;

my $parse_signature_input = $type->parse_signature_input('extension(string $name) (string | Venus::Path)');

# ["string"]

parse_signature_output

parse_signature_output(string $expr) (arrayref)

Returns the parsed data structure for the output type expression in the subroutine signature provided.

Since 4.15

parse_signature_output example 1
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('print(string @values) (boolean)');

# ["boolean"]
parse_signature_output example 2
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('chmod(string $mode) (Venus::Path)');

# ["Venus::Path"]
parse_signature_output example 3
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('copy(string | Venus::Path $path) (Venus::Path)');

# ["Venus::Path"]
parse_signature_output example 4
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('find(string | regexp $expr) (within[arrayref, Venus::Path])');

# ["within[arrayref, Venus::Path]"]
parse_signature_output example 5
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('mkdir(maybe[string] $mode) (Venus::Path)');

# ["Venus::Path"]
parse_signature_output example 6
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('open(any @data) (FileHandle)');

# ["FileHandle"]
parse_signature_output example 7
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('root(string $spec, string $base) (maybe[Venus::Path])');

# ["maybe[Venus::Path]"]
parse_signature_output example 8
# given: synopsis;

my $parse_signature_output = $type->parse_signature_output('extension(string $name) (string | Venus::Path)');

# ["string | Venus::Path"]

unpack

unpack(arrayref $args, arrayref $expr) (Venus::Unpack)

Returns a Venus::Unpack object based on the values and data structure (representing type expressions) provided.

Since 4.15

unpack example 1
# given: synopsis;

my $unpack = $type->unpack(["hello world"], ["string"]);

# bless(..., "Venus::Unpack")
unpack example 2
# given: synopsis;

my $unpack = $type->unpack(["hello world"], ["string | number"]);

# bless(..., "Venus::Unpack")

unpack_signature_input

unpack_signature_input(string $signature, arrayref $args) (Venus::Unpack)

Returns a Venus::Unpack object based on the values and data structure (representing a subroutine signature input expression) provided.

Since 4.15

unpack_signature_input example 1
# given: synopsis;

my $unpack_signature_input = $type->unpack_signature_input(
  'output(string $error) (string)', ["hello world"],
);

# bless(..., "Venus::Unpack")
unpack_signature_input example 2
# given: synopsis;

my $unpack_signature_input = $type->unpack_signature_input(
  'output(string | number $error) (string)', ["hello world"],
);

# bless(..., "Venus::Unpack")

unpack_signature_output

unpack_signature_output(string $signature, arrayref $args) (Venus::Unpack)

Returns a Venus::Unpack object based on the values and data structure (representing a subroutine signature output expression) provided.

Since 4.15

unpack_signature_output example 1
# given: synopsis;

my $unpack_signature_output = $type->unpack_signature_output(
  'output(string $error) (string)', ["hello world"],
);

# bless(..., "Venus::Unpack")
unpack_signature_output example 2
# given: synopsis;

my $unpack_signature_output = $type->unpack_signature_output(
  'output(string | number $error) (string)', ["hello world"],
);

# bless(..., "Venus::Unpack")

AUTHORS

Awncorp, awncorp@cpan.org

LICENSE

Copyright (C) 2022, Awncorp, awncorp@cpan.org.

This program is free software, you can redistribute it and/or modify it under the terms of the Apache license version 2.0.