This document establishes the comprehensive guidelines for the OQS
(Open Quick Script) language. OQS
aims to be a universally adoptable, streamlined, and system-neutral scripting language that integrates effortlessly into diverse platforms. OQS
is not designed to be a feature complete programming language. Rather, it is designed to be a simple, yet powerful, expression engine. It is specifically crafted to process expressions encompassing fundamental types and operations, interpreting a solitary expression—optionally accompanied by a dictionary, map, or JSON containing variables—to yield a consistent and logical outcome.
In creating these guidelines, OQS
has been meticulously designed to empower seamless implementation of scripting across a multitude of systems. It supports straightforward mathematical, logical, list computations, and function invocations within a contained environment, devoid of dependencies on the host system's intricacies. All developers are encouraged to build language engines in compliance with these guidelines to ensure consistency and reliability across implementations.
OQS
engines are required to accept input expressions as strings, incorporating variables, literals, and operators in alignment with the specifications set forth herein.
Engines must be capable of processing an optional input of key-value pairs that represent variable names and corresponding definitions—applicable formats include JSON objects, dictionaries, or maps. This input is not mandatory; engines should default to no variable substitutions if such input is absent.
An efficient OQS
engine should produce outputs in the form of a JSON object or a map that encapsulates the result and any ancillary evaluation data, such as errors encountered during the process.
Engines are mandated to consider an optional boolean parameter string_embedded
, which is false
by default. If set to true
, the engine must interpret the input expression as a string wherein segments framed by <{
and }>
are processed as embedded expressions. Subsequent to evaluation, the resultant expressions replace the original segments, with the modified string being returned.
OQS
supports a core set of types, which are essential for numerous scenarios:
Number
: Including the subtypes:Integer
: Contains any numeric value not in quotations not containing any decimals.
.Decimal
: Contains any numeric value not in quotations containing a single decimal.
. Values not containing a leading number such as.5
are still considered validDecimal
s. The same goes for values ending with a decimal such as5.
Boolean
: Contains the valuestrue
andfalse
.List
: Any number of values surrounded by square brackets[]
and commas seperated when containing more than 1 value. Examples include[1, "5"]
or[1]
. Lists can contain a mixture of types.List
s maintain their order.String
: Values surrounded by double-quotes"value"
or single-quotes'value'
. EmptyString
s are valid strings as well such as''
.Function
:Function
s can be callable using()
after the function name.Function
names must start with an alphabetic character followed by any number of alphanumeric characters and underscores or combination thereof.Null
: Contains only the valuenull
to indicate nothing.Key-Value Store
(KVS
): Enclosed in{}
, keys are strings, values van be any type, including nestedKVS
. It can be empty.Temporal
: Including the subtypes:DateTime
: Represents both date and time - Format:YYYY-MM-DDTHH:MM:SS
, e.g.,2023-12-25T15:30:00
.Date
: Represents only the date - Format:YYYY-MM-DD
, e.g.,2023-12-25
.Time
: Represents only the time - Format:HH:MM:SS
, e.g.,15:30:00
.Duration
: Represents a duration of time - Format:HH:MM:SS
, e.g.,02:15:30
for 2 hours, 15 minutes, and 30 seconds.
Operators, which are foundational to the interaction between types, are clarified below (Using unsupported operators or misapplying operators to incomplete types must trigger an error.):
- Addition
+
, subtraction-
, multiplication*
, division/
: To be used with number types only. - Exponentiation
**
: Used to raise a number to the power of another number. (This is valid so long as the second value is a real number) - Modulus
%
: Used to find the remainder of division of one number by another.
- Less-than
<
, greater-than>
, less-than-or-equal-to<=
, greater-than-or-equal-to>=
, not-equal!=
, equal==
, strictly equal===
, strictly not-equal!==
: Comparisons require identical operand types (for===
and!==
) or equivalent values (for==
and!=
) and return a Boolean value. For==
and!=
, type conversions are allowed (e.g., integer0
equals decimal0.0
, and"0.0"
equals0.0
).
- Logical
AND
(&
): Returnstrue
if both operands are truthy, otherwisefalse
. - Logical
OR
(|
): Returnstrue
if at least one operand is truthy, otherwisefalse
.
Note:
- Logical operators (
&
and|
) evaluate the truthiness of operands. An operand is considered truthy if it is not false, zero, empty, null, or undefined. Otherwise, it is considered falsy. - For example, non-zero numbers, non-empty strings/lists, and
true
are truthy. Zero, null, empty strings/lists, andfalse
are falsy. - Short-circuit evaluation should be implemented for efficiency. For the
&
operator, if the first operand is falsy, the second operand is not evaluated. For the|
operator, if the first operand is truthy, the second operand is not evaluated.
- Concatenation
+
: Required to merge two lists. - Subtraction
-
: Removes elements of the second list from the first one, if they are present.
- Concatenation
+
: Required to merge two KVSs. If there are duplicate keys, it prioritizes the later declaration.
- Concatenation
+
: Combined two strings into one. - Subtraction
-
: Removes all instances of the entirety of the second string from the first string. - Repetition
*
L Repeats a string by the multiplier specified (must be a non-negative integer).
- Addition (
+
):- For
DateTime
+Duration
: Adds the duration to the date-time. - For
Date
+Duration
: Adds the duration to the date. - For
Time
+Duration
: Adds the duration to the time. - For
Duration
+Duration
: Adds two durations together.
- For
- Subtraction (
-
):- For
DateTime
-Duration
: Subtracts the duration from the date-time. - For
Date
-Duration
: Subtracts the duration from the date. - For
Time
-Duration
: Subtracts the duration from the time. - For
Duration
-Duration
: Subtracts one duration from another. - For
DateTime
-DateTime
: Calculates the duration between two date-times. - For
Date
-Date
: Calculates the duration between two dates.
- For
- Comparison (
<
,>
,<=
,>=
,==
,!=
,!==
,!==
):- Less-than (
<
) and Greater-than (>
): Used to determine if oneTemporal
value is chronologically earlier or later than another. - Less-than-or-equal-to (
<=
) and Greater-than-or-equal-to (>=
): Similar to<
and>
, but also returnTrue
if the values are equal. - Equal (
==
) and Not-equal (!=
): Check if twoTemporal
values are exactly the same or not. - Strictly equal (
===
) and Strictly not equal (!==
): Similar to==
and!=
, but also consider the type of temporal values.
- Less-than (
- The syntax for invoking functions is an identifier that starts with a letter followed by any combination of letters, numbers, or underscores, then an opening parenthesis
(
, an optional comma-seperated list of arguments, and a closing parentheses)
.
The OQS
language adheres to a conventional order of operations to ensure predictable and logical results in expressions. This hierarchy is particularly crucial in expressions involving multiple operators:
- Parentheses: Expressions within parentheses are evaluated first.
- Exponentiation: Operations involving exponentiation are next.
- Multiplication and Division: These operations are performed from left to right.
- Addition and Subtraction: Finally, addition and subtraction are performed, also from left to right.
Failing to respect this order will lead to incorrect results and may cause errors in the execution of scripts.
- In
OQS
, parentheses()
play a pivotal role in structuring expressions. They not only clarify the sequence in which operations are performed but also allow for overriding the default order of operations. Parentheses ensure that the enclosed expression is evaluated first, regardless of the types of operations involved.
OQS
includes an unpacking feature using the ***
notation. This allows for the expansion of list items directly into function arguments or for the creation of new lists.
- In function calls, such as
INTEGER(***variable_1)
wherevariable_1
contains["1"]
, it will unpack the list and pass"1"
as an argument to theINTEGER
function, effectively callingINTEGER("1")
. - For lists, the syntax
[***variable_1, ***variable_2]
will combine the elements ofvariable_1
andvariable_2
into a single list. For instance, ifvariable_1 = [1, 2, 3]
andvariable_2 = [4, 5, 6]
, the result would be[1, 2, 3, 4, 5, 6]
. This is functionally equivalent to using the+
operator for list concatenation.OQS
also includes unpacking KVS using the***
notation. This allows for the expansion of KVS items directly into function arguments or for the creation of new KVSs. - In all standard cases such as
LIST(***variable_1)
wherevariable_1
contains{"hello": 5}
, it will unpack the kvs and pass"hello"
and5
as two arguments to theLIST
function effectively callingLIST("hello", 5)
. - For KVS creation, the syntax
{***kvs1, ***kvs_2}
will combine the elements ofkvs1
andkvs2
into a single KVS. For instance iskvs1 = {"hello": 5}
andkvs2 = {"yello": 3}
, the result would be{"hello": 5, "yello": 3}
. This is functionally equivalent to using the+
operator for KVS concatenation.
Interactions between types are explicitly defined within OQS
as follows:
Operator | Operand 1 | Operand 2 | Result |
---|---|---|---|
+ | Number | Number | Number |
+ | List | List | List |
+ | KVS | KVS | KVS |
+ | String | String | String |
+ | DateTime | Duration | DateTime |
+ | Date | Duration | Date |
+ | Time | Duration | Time |
+ | Duration | Duration | Duration |
- | Number | Number | Number |
- | List | List | List |
- | String | String | String |
- | DateTime | Duration | DateTime |
- | Date | Duration | Date |
- | Time | Duration | Time |
- | Duration | Duration | Duration |
- | DateTime | DateTime | Duration |
- | Date | Date | Duration |
* | Number | Number | Number |
* | String | Integer | String |
/ | Number | Number | Number |
** | Number | Number | Number |
% | Number | Number | Number |
< | Number | Number | Boolean |
< | Temporal | Temporal | Boolean |
> | Number | Number | Boolean |
> | Temporal | Temporal | Boolean |
<= | Number | Number | Boolean |
<= | Temporal | Temporal | Boolean |
>= | Number | Number | Boolean |
>= | Temporal | Temporal | Boolean |
== | Any Type | Any Type | Boolean |
!= | Any Type | Any Type | Boolean |
=== | Any Type | Any Type | Boolean |
!== | Any Type | Any Type | Boolean |
& | Any Type | Any Type | Boolean |
| | Any Type | Any Type | Boolean |
("Any Type" indicates compatibility for comparisons between operands sharing a type.)
OQS
language engines must implement comprehensive error handling to ensure robust and predictable scripting experiences. The following error types and their contexts of occurrence are detailed:
- Invalid Argument Quantity Error
- Raised when a function receives fewer or more arguments than expected.
- Example:
ADD(1)
orADD(1, 2, 3, 4, 5)
ifADD
expects two arguments.
- Syntax Error
- Raised for general syntax mistakes in expressions.
- Example:
{"string": variable} 5
(missing operator). - Sub-Errors:
- Unexpected Character Error
- Raised when an unexpected character is encountered in the expression.
- Example:
5, 5
(unexpected,
).
- Missing Expected Character Error
- Raised when an expected character is missing in the expression.
- Example:
ADD(5, 6
(missing closing parenthesis).
- Unexpected Character Error
- Type Error:
- Raised when an operation is performed on incompatible types.
- Example:
"Hello" - 5
(string and integer).
- Value Error:
- Raised when a function or operation receives inputs with invalid values.
- Example:
DATE(2023, 2, 31)
→ "Value Error: Day '31' is not valid for month '2'."
- Undefined Variable Error:
- Raised when an expression refers to a variable that has not been defined.
- Example:
x + 2
wherex
is undefined.
- Undefined Function Error:
- Raised when an expression calls a function that does not exist.
- Example:
NONEXISTENT_FUNCTION(1, 2)
.
- Function Evaluation Error:
- Raised when an error occurs within the execution of a function.
- Division By Zero Error:
- Raised when an attempt is made to divide by zero.
- Example:
10 / 0
.
- Errors must provide clear and informative messages to aid in debugging.
- Errors should be specific to the type of issue encountered to facilitate easier identification and resolution.
- Implementations should include error handling as part of the language engine to maintain consistency across different environments.
- Invalid Argument Quantity:
ADD(1)
→ "Invalid Argument Quantity Error: Expected 2 arguments, but got 1." - Syntax Error:
"Hello" "World"
→ "Syntax Error: Missing operator between expressions." - Type Error:
"Hello" - 5
→ "Type Error: Cannot subtract Integer from String." - Undefined Variable:
x + 2
→ "Undefined Variable Error: Variable 'x' is not defined." - Undefined Function:
NONEXISTENT_FUNCTION(1, 2)
→ "Undefined Function Error: Function 'NONEXISTENT_FUNCTION' is not a valid function." - Function Evaluation:
DIVIDE(1, 0)
inside a function → "Function Evaluation Error: Division by zero in function 'DIVIDE'." - Division By Zero:
10 / 0
→ "Division By Zero Error: Division by zero results in undefined." - Unexpected Character:
2 * 5 @ 3
→ "Unexpected Character Error: '@' is not a valid character in expressions." - Missing Expected Character:
ADD(5, 6
→ "Missing Expected Character Error: Expected ')'."
OQS
should support a set of built-in functions, with each implementation having the freedom to include additional functions. (Functions must handle invalid inputs by raising appropriate errors.)
ADD(argument1, argument2, ...)
- Adds Numbers, concatenates Strings, merges Lists or merges KVSs:- Inputs:
- Amount: A minimum of two inputs with no maximum.
- Types: All input types must be of the same type being one of the following:
Number
Temporal
String
List
KVS
- Outputs: The same type that the inputs were. If one of the inputs was a
Decimal
, it will return aDecimal
.
- Inputs:
SUBTRACT(argument1, argument2)
- Subtracts numbers or removes instances from strings/lists:- Inputs:
- Amount: Exactly two inputs required.
- Types:
- For numbers: Both
Number
. - For strings/lists: Both
String
orList
. - For temporal: First argument should be a
Temporal
and the second argument should be aDuration
.
- For numbers: Both
- Types:
- Amount: Exactly two inputs required.
- Outputs: The same type as the inputs.
- Inputs:
MULTIPLY(argument1, argument2, ...)
- Multiplies numbers or repeats strings/lists:- Inputs:
- Amount: A minimum of two inputs with no maximum.
- Types: Either all
Number
or the firstString
/List
and the restNumber
.
- Outputs: The same type as the first input.
- Inputs:
DIVIDE(argument1, argument2)
- Divides the first number by the second:- Inputs:
- Amount: Exactly two inputs.
- Types: Both inputs must be
Number
. - Error Handling: Raises an error if the second argument is zero.
- Outputs:
Number
.
- Inputs:
EXPONENTIATE(base, exponent)
- Raises a number to the power of another:- Inputs:
- Amount: Exactly two inputs.
- Types: Both inputs must be
Number
.
- Outputs:
Number
.
- Inputs:
MODULO(number1, number2)
- Calculates the remainder of division:- Inputs:
- Amount: Exactly two inputs.
- Types: Both inputs must be
Number
.
- Outputs:
Number
.
- Inputs:
LESS_THAN(argument1, argument2, ...)
- Compares if each preceding argument is less than its following argument:- Inputs:
- Amount: Two or more inputs.
- Types: All inputs must be
Number
or all inputs must be of the sameTemporal
subtype.
- Outputs:
Boolean
- Returnstrue
if each argument is less than the next one, otherwisefalse
.
- Inputs:
GREATER_THAN(argument1, argument2, ...)
- Compares if each preceding argument is greater than its following argument:- Inputs:
- Amount: Two or more inputs.
- Types: All inputs must be
Number
or all inputs must be of the sameTemporal
subtype.
- Outputs:
Boolean
- Returnstrue
if each argument is greater than the next one, otherwisefalse
.
- Inputs:
LESS_THAN_OR_EQUAL(argument1, argument2, ...)
- Compares if each preceding argument is less than or equal to its following argument:- Inputs:
- Amount: Two or more inputs.
- Types: All inputs must be
Number
or all inputs must be of the sameTemporal
subtype.
- Outputs:
Boolean
- Returnstrue
if each argument is less than or equal to the next one, otherwisefalse
.
- Inputs:
GREATER_THAN_OR_EQUAL(argument1, argument2, ...)
- Compares if each preceding argument is greater than or equal to its following argument:- Inputs:
- Amount: Two or more inputs.
- Types: All inputs must be
Number
or all inputs must be of the sameTemporal
subtype.
- Outputs:
Boolean
- Returnstrue
if each argument is greater than or equal to the next one, otherwisefalse
.
- Inputs:
EQUALS(argument1, argument2, ...)
- Compares if all arguments are equal:- Inputs:
- Amount: Two or more inputs.
- Types: Any types, but all must be of the same type.
- Outputs:
Boolean
- Returnstrue
if all arguments are equal, otherwisefalse
.
- Inputs:
NOT_EQUALS(argument1, argument2, ...)
- Compares if any of the arguments are not equal:- Inputs:
- Amount: Two or more inputs.
- Types: Any types, but all must be of the same type.
- Outputs:
Boolean
- Returnstrue
if any argument is not equal to the others, otherwisefalse
.
- Inputs:
STRICTLY_EQUALS(argument1, argument2, ...)
- Compares if all arguments are strictly equal (identical in type and value):- Inputs:
- Amount: Two or more inputs.
- Types: Any types, but all must be of the same type.
- Outputs:
Boolean
- Returnstrue
if all arguments are strictly equal, otherwisefalse
.
- Inputs:
STRICTLY_NOT_EQUALS(argument1, argument2, ...)
- Compares if any of the arguments are strictly not equal (different in type or value):- Inputs:
- Amount: Two or more inputs.
- Types: Any types, but all must be of the same type.
- Outputs:
Boolean
- Returnstrue
if any argument is strictly not equal to the others, otherwisefalse
.
- Inputs:
AND(argument1, argument2, ...)
- Performs a logical AND operation on all provided arguments:- Inputs:
- Amount: Two or more inputs.
- Types: Any types, evaluated for their truthiness.
- Outputs:
Boolean
- Returnstrue
if all arguments are truthy, otherwisefalse
. - Examples:
- Input:
AND(true, 1, "text")
Output:true
- Input:
AND(true, 0)
Output:false
- Input:
- Inputs:
OR(argument1, argument2, ...)
- Performs a logical OR operation on all provided arguments:- Inputs:
- Amount: Two or more inputs.
- Types: Any types, evaluated for their truthiness.
- Outputs:
Boolean
- Returnstrue
if at least one argument is truthy, otherwisefalse
. - Examples:
- Input:
OR(false, 0, null, "text")
Output:true
- Input:
OR(false, 0, "")
Output:false
- Input:
- Inputs:
NOT(argument)
- Performs a logical NOT operation on the provided argument:- Inputs:
- Amount: Exactly one input.
- Types: Any type, evaluated for its truthiness.
- Outputs:
Boolean
- Returnstrue
if the argument is falsy, otherwisefalse
. - Examples:
- Input:
NOT(true)
Output:false
- Input:
NOT(0)
Output:true
- Input:
NOT("text")
Output:false
(since "text" is truthy) - Input:
NOT(null)
Output:true
- Input:
- Inputs:
INTEGER(argument)
- Converts to an integer representation:- Inputs:
- Amount: Exactly one input.
- Types:
Decimal
,String
,Integer
, orBoolean
.
- Outputs:
Integer
.
- Inputs:
DECIMAL(argument)
- Converts to a decimal representation:- Inputs:
- Amount: Exactly one input.
- Types:
Integer
,String
, orDecimal
.
- Outputs:
Decimal
.
- Inputs:
STRING(argument)
- Converts to a string representation:- Inputs:
- Amount: Exactly one input.
- Types: Any single type.
- Outputs:
String
.
- Inputs:
LIST(argument1, argument2, ...)
- Creates a list from provided arguments:- Inputs:
- Amount: One or more inputs.
- Types: Any types.
- Outputs:
List
.
- Inputs:
KVS(key1, value1, key2, value2, ..., keyN, valueN)
- Creates a key-value store:- Inputs:
- Amount: Even number of inputs (pairs of keys and values).
- Types: Keys must be
String
, values can be any type. - Error Handling: Raises an error if an odd number of arguments is provided.
- Outputs:
KVS
.
- Inputs:
BOOLEAN(argument)
/BOOL(argument)
- Evaluates the truthiness of an argument:- Inputs:
- Amount: Exactly one input.
- Types: Any single type.
- Outputs:
Boolean
.Great! To include theAND
andOR
functions in theOQS
language guidelines, we can expand the "Built-in Functions" section. These functions will provide an alternative way to perform logical operations, particularly useful for handling multiple operands or integrating into more complex expressions.
- Inputs:
KEYS(kvs)
- Retrieves a list of all keys in a KVS:- Inputs:
- Amount: Exactly one input.
- Types:
KVS
.
- Outputs:
List
of keys.
- Inputs:
VALUES(kvs)
- Retrieves a list of all values in a KVS:- Inputs:
- Amount: Exactly one input.
- Types:
KVS
.
- Outputs:
List
of values.
- Inputs:
UNIQUE(list)
- Returns a list of unique values:- Inputs:
- Amount: Exactly one input.
- Types:
List
.
- Outputs:
List
containing unique elements.
- Inputs:
REVERSE(list)
- Reverses the order of a list:- Inputs:
- Amount: Exactly one input.
- Types:
List
.
- Outputs:
List
in reverse order.
- Inputs:
MAX(number1, number2, ..., numberN)
- Finds the maximum number:- Inputs:
- Amount: A minimum of two inputs with no maximum.
- Types: All inputs must be
Number
or all inputs must be of the sameTemporal
subtype.
- Outputs:
Number
.
- Inputs:
MIN(number1, number2, ..., numberN)
- Finds the minimum number:- Inputs:
- Amount: A minimum of two inputs with no maximum.
- Types: All inputs must be
Number
or all inputs must be of the sameTemporal
subtype.
- Outputs:
Number
.
- Inputs:
SUM(list)
- Adds up items in a list:- Inputs:
- Amount: Exactly one input.
- Types:
List
with all elements of the same base type. - Error Handling: Raises an error for mixed types.
- Outputs: The sum or concatenation of list items.
- Inputs:
LENGTH(object)
/LEN(object)
- Returns the count of items or characters:- Inputs:
- Amount: Exactly one input.
- Types:
List
,String
,Integer
, orDecimal
.
- Outputs:
Integer
.
- Inputs:
APPEND(list, item)
- Appends an item to a list:- Inputs:
- Amount: Exactly two inputs.
- Types: First input must be a
List
, second can be any type.
- Outputs:
List
.
- Inputs:
UPDATE(kvs/list, key/index, value)
- Updates a KVS or List with a new value:- Inputs:
- Amount: Exactly three inputs.
- Types:
- For lists: First
List
, secondInteger
(index), third any type. - For KVS: First
KVS
, second and third any type (key and value).
- For lists: First
- Error Handling: Raises an error if the index does not exist for lists. For KVS, adds or updates the key.
- Outputs: Updated
List
orKVS
.
- Inputs:
REMOVE_ITEM(list/kvs, item, max_occurrences=unlimited)
- Removes an item from a list or KVS:- Inputs:
- Amount: Two or three inputs.
- Types: First input must be
List
orKVS
, second input is the item to remove, third (optional) isInteger
for maximum occurrences.
- Outputs: Adjusted
List
orKVS
.
- Inputs:
REMOVE(list/kvs, index/key)
- Removes an item from a list or KVS by index or key:- Inputs:
- Amount: Exactly two inputs.
- Types:
- For lists: First
List
, secondInteger
(index). - For KVS: First
KVS
, secondString
(key).
- For lists: First
- Error Handling: Raises an error if the index does not exist for lists; does not raise an error if a key does not exist in KVS.
- Outputs: Adjusted
List
orKVS
.
- Inputs:
ACCESS(list/kvs, index/key, [optional default value])
- Accesses an item in a list or KVS:- Inputs:
- Amount: Two or three inputs.
- Types:
- For lists: First
List
, secondInteger
(index). - For KVS: First
KVS
, secondString
(key), third (optional) any type (default value).
- For lists: First
- Error Handling: Raises an error if the index does not exist for lists; returns null or default value if the key does not exist in KVS.
- Outputs: The accessed item or default value.
- Inputs:
IF(condition1, result1, ..., conditionN, resultN, [else_result])
- Evaluates conditions and returns corresponding results:- Inputs:
- Amount: A minimum of two arguments up to an unlimited amount.
- Types: Alternating between conditions (any type evaluated for truthiness) and results (any type).
- Outputs: The result corresponding to the first true condition or the
else
result.
- Inputs:
TYPE(argument)
- Determines the type of the given argument:- Inputs:
- Amount: Exactly one input.
- Types: Any single type.
- Outputs: A
String
representing the type of the argument, such as "number", "integer", "decimal", "boolean", "list", "string", "function", "null", or "kvs". - Examples:
- Input:
TYPE(5)
Output:"integer"
- Input:
TYPE([1, 2, 3])
Output:"list"
- Input:
- Inputs:
IS_TYPE(argument, type_string)
- Evaluates whether the argument's type matches the specified type string:- Inputs:
- Amount: Exactly two inputs.
- Types: First input of any type, second input a
String
. - Case Insensitivity: The
type_string
input is case-insensitive.
- Outputs: A
Boolean
indicating the type match. - Superiority Rules: Types "integer" and "decimal" are considered subtypes of "number". An argument matching "integer" or "decimal" also returns
true
for "number". - Examples:
- Input:
IS_TYPE(5, "number")
Output:true
- Input:
IS_TYPE("hello", "string")
Output:true
- Input:
- Inputs:
TRY(expression, error_type1, result1, ..., error_typeN, resultN)
- Attempts to evaluate an expression and handles specific errors with corresponding fallback expressions:- Inputs:
- Amount: Minimum of three, odd number, no maximum.
- Types: The first input is an expression of any type, followed by alternating
String
error types and their corresponding expressions. - Case Insensitivity: The
error_type
inputs are case-insensitive. - Superiority Rules: Error types follow a hierarchy, with specific error types taking precedence over general ones.
- Outputs: The result of the first expression if no error occurs, or the result of the corresponding expression for the first true matching error.
- Examples:
- Input:
TRY(1/0, "Division By Zero Error", "Infinity", "Syntax Error", "Check expression")
Output:"Infinity"
- Input:
- Inputs:
RANGE(start, stop, step)
- Generates a list of integers starting fromstart
, ending beforestop
, incrementing bystep
:- Inputs:
- Amount: Between 1 and 3, all integers.
- Defaults: If only one argument is provided, it is considered as
stop
withstart
defaulting to 0 andstep
defaulting to 1.
- Outputs: A
List
of integers. - Examples:
- Input:
RANGE(3)
Output:[0, 1, 2]
- Input:
RANGE(1, 3)
Output:[1, 2]
- Input:
RANGE(2, 10, 2)
Output:[2, 4, 6, 8]
- Input:
- Inputs:
FOR(list, variable_name, expression)
/MAP(list, variable_name, expression)
- Iterates over each item in a list, executing an expression for each item:- Inputs:
- Amount: Exactly three inputs.
- Types: First input must be a
List
, second aString
for the variable name that will be set to the current item from the list, and third an expression. - Variable: During each iteration, the variable with the name set in the second argument is set to the current item from the list.
- Outputs: A
List
of the results from evaluating the expression for each list item. - Examples:
- Input:
FOR([1, 2, 3], FOR_LIST_ITEM * 2)
Output:[2, 4, 6]
- Input:
- Inputs:
RAISE(error_name, error_message)
- Triggers a specified error or creates a custom error:- Inputs:
- Amount: Exactly two inputs, both
String
. - Types: First input for the error name, second for the error message.
- Custom Error Handling: If
error_name
is not a predefined error, a custom error with that name is raised.
- Amount: Exactly two inputs, both
- Outputs: Raises the specified error.
- Examples:
- Input:
RAISE("Syntax Error", "Invalid syntax")
Output: Raises a Syntax Error with the message "Invalid syntax". - Input:
RAISE("NewError", "Custom error occurred")
Output: Raises a custom error named "NewError" with the message "Custom error occurred".
- Input:
- Inputs:
FILTER(list/kvs, variable_name, predicate)
- Filters elements of aList
or key-value pairs of aKVS
based on a provided predicate expression:- Inputs:
- list/kvs: The
List
orKVS
to be filtered. - variable_name: A
String
representing the name of the variable that will be assigned each item or key-value pair during evaluation. - predicate: An expression that returns a
Boolean
value. It is evaluated for each item (or key-value pair in the case ofKVS
) in theList
/KVS
.
- list/kvs: The
- Outputs: A new
List
orKVS
containing only those elements (or key-value pairs) for which the predicate returnstrue
. - Examples:
- Input:
FILTER([1, 2, 3, 4], "x", x > 2)
Output:[3, 4]
- Input:
FILTER({"a": 1, "b": 2, "c": 3}, "value", value == 2)
Output:{"b": 2}
- Input:
- Inputs:
SORT(list, variable_name, key_expression, [descending=false])
- Sorts aList
based on a key generated by an expression for each element:- Inputs:
- list: The
List
to be sorted. - variable_name: A
String
representing the name of the variable that will be assigned each item during evaluation. - key_expression: An expression that computes a key for each element in the
List
. - descending (optional): A
Boolean
indicating whether the sort should be in descending order. Defaults tofalse
.
- list: The
- Outputs: A new
List
sorted based on the keys generated by thekey_expression
. - Examples:
- Input:
SORT([1, 2, 3, 4], "x", x, true)
Output:[4, 3, 2, 1]
- Input:
SORT(["apple", "banana", "cherry"], "fruit", LEN(fruit))
Output:["apple", "cherry", "banana"]
- Input:
- Inputs:
FLATTEN(list)
- Flattens a nestedList
(aList
ofList
s) into a single-levelList
:- Inputs:
- list: A
List
potentially containing otherList
s as elements.
- list: A
- Outputs: A new
List
where all elements are notList
s. - Examples:
- Input:
FLATTEN([[1, 2], [3, 4], [5]])
Output:[1, 2, 3, 4, 5]
- Input:
FLATTEN([[["a", "b"], "c"], ["d"]])
Output:["a", "b", "c", "d"]
- Input:
- Inputs:
SLICE(list/string, start, [end])
- Extracts a subsection of aList
orString
:- Inputs:
- list/string: The
List
orString
from which a subsection is to be extracted. - start: An
Integer
representing the starting index of the subsection (inclusive). - end (optional): An
Integer
representing the ending index of the subsection (exclusive). If omitted, the slice includes all elements from the start to the end of theList
/String
.
- list/string: The
- Outputs: A new
List
orString
that is a subsection of the inputList
/String
. - Examples:
- Input:
SLICE([1, 2, 3, 4, 5], 1, 3)
Output:[2, 3]
- Input:
SLICE("Hello World", 6)
Output:"World"
- Input:
- Inputs:
IN(value, list/kvs)
- Checks if a given value is present in aList
or if a given key exists in aKVS
:- Inputs:
- value: The value or key to be checked. This can be of any type.
- list/kvs: The
List
orKVS
to be searched. If aList
is provided, the function checks for the presence of the value in theList
. If aKVS
is provided, the function checks if the value is a key in theKVS
.
- Outputs:
Boolean
. Returnstrue
if the value is found in theList
or if the value is a key in theKVS
. Returnsfalse
otherwise. - Examples:
- Input:
IN(3, [1, 2, 3, 4])
Output:true
- Input:
IN("b", {"a": 1, "b": 2, "c": 3})
Output:true
- Input:
IN("z", [1, 2, 3, 4])
Output:false
- Input:
IN("d", {"a": 1, "b": 2, "c": 3})
Output:false
- Input:
- Inputs:
DATE(year, month, day)
- Creates aDate
from specified year, month, and day:- Inputs:
- Amount: Exactly three inputs.
- Types: All inputs must be
Integer
.
- Outputs:
Date
.
- Inputs:
TIME(hour, minute, second, [millisecond])
- Creates aTime
from specified hour, minute, second, and optionally millisecond:- Inputs:
- Amount: Three or four inputs.
- Types: All inputs must be
Integer
.
- Outputs:
Time
.
- Inputs:
DATETIME(year, month, day, hour, minute, second, [millisecond])
- Creates aDateTime
from specified year, month, day, hour, minute, second, and optionally millisecond:- Inputs:
- Amount: Six or seven inputs.
- Types: All inputs must be
Integer
.
- Outputs:
DateTime
.
- Inputs:
DURATION(days, hours, minutes, seconds, [milliseconds])
- Creates aDuration
from specified days, hours, minutes, seconds, and optionally milliseconds:- Inputs:
- Amount: Four or five inputs.
- Types: All inputs must be
Integer
.
- Outputs:
Duration
.
- Inputs:
NOW()
- Returns the current UTCDateTime
:- Outputs:
DateTime
.
- Outputs:
TODAY()
- Returns the current UTCDate
.- Outputs:
Date
.
- Outputs:
TIME_NOW()
- Returns the current UTCTime
.- Outputs:
Time
.
- Outputs:
PARSE_TEMPORAL(string, type, [format])
- Converts aString
to the appropriateTemporal
type (DateTime
,Date
,Time
,Duration
), optionally using a specified format. The optional format input will be ignored if the specified type isDuration
:- Inputs:
- Amount: One or two inputs.
- Types: First
String
, secondString
one of the Temporal subtypes (case-insensitive), third (optional)String
(format pattern).
- Outputs: The appropriate
Temporal
type based on the inputString
. - Examples:
- Input:
PARSE_TEMPORAL("2023-12-25T15:30:00", "DateTime")
Output:DateTime(2023, 12, 25, 15, 30, 0)
- Input:
PARSE_TEMPORAL("2023-12-25", "Date")
Output:Date(2023, 12, 25)
- Input:
PARSE_TEMPORAL("15:30:00", "Time")
Output:Time(15, 30, 0)
- Input:
PARSE_TEMPORAL("1 02:15:30", "Duration")
Output:Duration(1, 2, 15, 30)
- Input:
- Inputs:
FORMAT_TEMPORAL(temporal, format)
- Formats aTemporal
(Date
,Time
,DateTime
,Duration
) into aString
using the specified format:- Inputs:
- Amount: Exactly two inputs.
- Types: First
Temporal
(Date
,Time
,DateTime
,Duration
), secondString
(format pattern).
- Outputs:
String
.
- Inputs:
EXTRACT_DATE(datetime)
- Extracts theDate
component from aDateTime
:- Inputs:
- Amount: Exactly one input.
- Types:
DateTime
.
- Outputs:
Date
.
- Inputs:
EXTRACT_TIME(datetime)
- Extracts theTime
component from aDateTime
:- Inputs:
- Amount: Exactly one input.
- Types:
DateTime
.
- Outputs:
Time
.
- Inputs:
Implementation Notes:
- Format Strings: The optional format strings in
PARSE_
andFORMAT_TEMPORAL
functions should conform to standard date-time formatting conventions, allowing for custom date-time representations. It should follow the POSIX specification and the C standard for format codes.
- In
OQS
, function names are case-insensitive. This means that a function can be called using any combination of uppercase and lowercase letters, and it will be interpreted as the same function.- Example:
ADD(1, 2)
,add(1, 2)
, andAdD(1, 2)
will all be interpreted as calls to the same addition function.
- Example:
- This design choice is intended to reduce errors and confusion related to function naming conventions, thereby making the language more user-friendly.
- Unlike function names, variable names in OQS are case-sensitive. This means that variables with the same spelling but different cases will be treated as distinct.
- Example:
Variable
,variable
, andVARIABLE
are considered three separate variables.
- Example:
- Case sensitivity in variable names allows for more precise and controlled scripting, as it enables distinct naming for different variables even with similar spellings.
- Developers implementing
OQS
engines and users writing scripts inOQS
should be mindful of these case sensitivity rules. - It is recommended to follow consistent naming conventions for clarity and maintainability. For instance, using camelCase or snake_case consistently for variable names can enhance readability.
Expressions evaluated in OQS
should yield identical results across different implementations. This consistency is vital, except in cases where custom features or extensions have been introduced. The following are sample expressions and their expected outputs:
- Numerical Operations:
- Input:
2 * 5
Output:10
- Input:
10 / 2
Output:5
- Input:
9 % 2
Output:1
- Input:
- String Operations:
- Input:
"Hello " + "World"
Output:Hello World"
- Input:
"repeat" * 2
Output:"repeatrepeat"
- Input:
"remove" - "move"
Output:"re"
- Input:
- Logical Operations:
- Input:
1 & 0
Output:false
(1 is truthy, 0 is falsy) - Input:
"text" | ""
Output:true
("text" is truthy, "" is falsy) - Input:
(3 > 2) & [1]
Output:true
(both expressions are truthy) - Input:
null | "hello"
Output:true
(null is falsy, "hello" is truthy)
- Input:
- Boolean Operations:
- Input:
true == false
Output:false
- Input:
true != false
Output:true
- Input:
- List Operations:
- Input:
[1, 2] + [3, 4]
Output:[1, 2, 3, 4]
- Input:
[1, 2, 3, 4] - [3]
Output:[1, 2, 4]
- Input:
- Key-Value Store Operations::
- Input:
{ "a": 1, "b": 2 } + { "c": 3 }
Output:{ "a": 1, "b": 2, "c": 3 }
- Input:
{ "name": "OQS", "type": "script" } + { "type": "language" }
Output:{ "name": "OQS", "type": "language" }
- Input:
- Function Examples:
- Input:
ADD(1, 2)
Output:3
- Input:
SUBTRACT(5, 2)
Output:3
- Input:
MULTIPLY(3, 4)
Output:12
- Input:
DIVIDE(8, 4)
Output:2
- Input:
EXPONENTIATE(2, 3)
Output:8
- Input:
MODULO(5, 3)
Output:2
- Input:
- Complex Function Calls and Expressions:
- Input:
INTEGER(3.5)
Output:3
- Input:
DECIMAL("42")
Output:42.0
- Input:
STRING([1, 2, 3])
Output:"[1, 2, 3]"
- Input:
LIST("a", "b", "c")
Output:["a", "b", "c"]
- Input:
KVS("key1", "value1", "key2", "value2")
Output:{ "key1": "value1", "key2": "value2" }
- Input:
BOOLEAN(1)
Output:true
- Input:
KEYS({ "name": "OQS", "type": "script" })
Output:["name", "type"]
- Input:
VALUES({ "name": "OQS", "type": "script" })
Output:["OQS", "script"]
- Input:
UNIQUE([1, 1, 2, 2, 3])
Output:[1, 2, 3]
- Input:
REVERSE([1, 2, 3])
Output:[3, 2, 1]
- Input:
MAX(1, 3, 2)
Output:3
- Input:
MIN(1, 3, 2)
Output:1
- Input:
SUM([1, 2, 3])
Output:6
- Input:
LEN("Hello")
Output:5
- Input:
APPEND([1, 2], 3)
Output:[1, 2, 3]
- Input:
UPDATE([1, 2, 3], 1, 4)
Output:[1, 4, 3]
- Input:
REMOVE_ITEM([1, 2, 3, 2], 2)
Output:[1, 3]
- Input:
REMOVE([1, 2, 3], 0)
Output:[2, 3]
- Input:
ACCESS([1, 2, 3], 1)
Output:2
- Input:
IF(1 > 0, "positive", "negative")
Output:"positive"
- Input:
- Unpacking and KVS Expansion:
- Input:
INTEGER(**["5"])
Output:5
- Input:
{***{"key1": "value1"}, ***{"key2": "value2"}}
Output:{ "key1": "value1", "key2": "value2" }
- Input:
- String Embedded Expressions:
- Input:
<{3 + 5}> is the answer
withstring_embedded
set totrue
Output:"8 is the answer"
- Input:
- Complex Nested Expressions:
- Input:
IF(LEN("test") == 4, "valid", "invalid")
Output:"valid"
- Input:
ADD(*[1, 2, 3, 4])
Output:10
- Input:
MULTIPLY(STRING(2), 3)
Output:"222"
- Input:
- Order of Operations:
- Input: 2 + 3 * 4 Output: 14 (Multiplication is performed before addition)
- Input: (2 + 3) * 4 Output: 20 (Parentheses alter the order, causing addition to be performed first)
- Parentheses:
- Input: 4 * (2 + 3) Output: 20 (Parentheses cause addition to be prioritized over multiplication)
- Input: ((2 + 3) * 4) / 2 Output: 10 (Nested parentheses guide the sequence of operations)
- Temporal Addition and Subtraction:
- Input:
ADD(DATETIME(2023, 12, 25, 10, 30, 0), DURATION(0, 2, 0, 0))
Output:DATETIME(2023, 12, 25, 12, 30, 0)
(Adds 2 hours to the datetime) - Input:
SUBTRACT(DATE(2023, 12, 25), DURATION(1, 0, 0, 0))
Output:DATE(2023, 12, 24)
(Subtracts 1 day from the date)
- Input:
- Temporal Comparisons:
- Input:
LESS_THAN(DATE(2023, 12, 25), DATE(2024, 1, 1))
Output:true
(Checks if one date is earlier than another) - Input:
GREATER_THAN(TIME(15, 30, 0), TIME(14, 30, 0))
Output:true
(Compares two times)
- Input:
- Temporal Formatting and Parsing:
- Input:
FORMAT_TEMPORAL(DATETIME(2023, 12, 25, 10, 30, 0), "%Y-%m-%d %H:%M:%S")
Output:"2023-12-25 10:30:00"
- Input:
PARSE_TEMPORAL("2023-12-25", "Date", "%Y-%m-%d")
Output:DATE(2023, 12, 25)
- Input:
- Advanced Temporal Operations:
- Input:
IF(GREATER_THAN(NOW(), DATETIME(2023, 12, 25, 0, 0, 0)), "After Christmas", "Before Christmas")
(Evaluates current time in relation to a specific datetime) - Input:
LEN(SLICE("2023-12-25T15:30:00", 0, 10))
Output:10
(Extracts the date part from a datetime string and calculates its length)
- Input:
- Using Temporal Types in Complex Expressions:
- Input:
ADD(DURATION(1, 0, 0, 0), IF(LESS_THAN(TIME_NOW(), TIME(12, 0, 0)), DURATION(0, 1, 0, 0), DURATION(0, 2, 0, 0)))
(Adds either 1 or 2 hours to a duration based on the current time) - Input:
STRING(EXTRACT_DATE(NOW())) + " is today's date"
(Extracts the current date and converts it to a string for display)
- Input:
These examples highlight the versatility of OQS
in handling temporal data, providing a clear demonstration of how the new temporal types can be effectively utilized in various scenarios.
- Accessibility of these guidelines is paramount for developers, hence they should be publicly available.
- Adherence to the stipulated type system and operator interactions is obligatory for implementers.
- Error reporting ought to be as transparent and informative as possible without introducing security risks.
- While implementations may be proprietary, open-source contributions are highly encouraged.
- The recommended format for these guidelines is a Markdown (.md) file within a committed GitHub repository for the project.
- Language development should be recorded through systematic versioning of this document.
- Community discourse and proposals for alterations are advised to take place via GitHub issues and pull requests to ensure an open and structured record of evolution.
A model open-source implementation exemplifying these guidelines will be published to offer a standard for comparison and adherence for alternative implementations.
In the future OQS
hopes to build types and functions to interact with the following:
- Phone Number
- Lat-Long (Location)
Additionally, OQS
hopes to implement handling of timezones and we encourage contribution in that area.
The OQS
language is designed to enhance ease of adoption, establish a system-neutral scripting solution, and ensure uniformity and straightforwardness. Your contributions and feedback on these guidelines are warmly welcomed to guarantee that OQS
can adequately satisfy a broad spectrum of applications and remain adaptable for impending developments.