Version 1.0.0
A scripting language by Jack Eisenmann
- Very cute
- Adorable
- Maybe actually useful
LogiScript is compatible with Linux and macOS. To compile and install:
make
sudo make install
Every value in LogiScript has one of the following data types:
- Number – Double-precision floating point number
- String – Mutable sequence of ASCII characters
- List – Mutable sequence of values with any data types
- Function – Function handle which may be invoked
- Void – The absence of any value
A number literal may contain numeric digits and a decimal point. Ex: 18
, 20.5
A character literal consists of an ASCII character enclosed in apostrophes. Character literals have the number data type. Ex: 'A'
, '$'
A string literal consists of ASCII characters enclosed in quotation marks. Characters in a string literal may be escaped with a backslash. Ex: "Hello world!"
, "Did you just say \"hello\" to me?"
A list literal consists of comma-separated expressions enclosed in brackets. Ex: [10, 20, 30, "Very cool"]
Every function literal must have the following format:
{<arg name>, <arg name>, <arg name>...
<statement>
<statement>
<statement>
...
}
Note that newlines are syntactically significant in function literals, but other whitespace is not. The example function literal below accepts two numbers and prints their sum:
{inputNum1, inputNum2
SET @result, inputNum1 + inputNum2
PRINT result
}
Only two kinds of statements are possible in LogiScript:
- Function invocation statement – Invokes a function with a list of arguments
- Import statement – Imports a namespace or list of variables
Statements are separated from each other by a newline. Comments are initiated with a number sign and are terminated by a newline.
A function invocation statement may have one of the following formats:
# Calls a function with no arguments.
<function>
# Calls a function with one or more arguments.
<function> <arg>, <arg>, <arg>...
For example, the statement below retrieves the size of the given string:
SIZE @dest, "Please measure me"
If fewer arguments are provided to the function than expected, the missing arguments will contain the void value.
An import statement may have one of the following formats:
# Uses the specified namespace to reference
# all global variables in the given script.
$<namespace> <path>
# Imports the specified global variables from
# the given script.
$(<name>, <name>, <name>...) <path>
For example, the statement below imports two global variables from the given script:
$(SUM, AVERAGE) "./mathLib.logi"
The unary at operator (@
) declares a variable in the current scope. For example:
# Declares variable myNum, and stores 5 in myNum.
SET @myNum, 5
# Stores a new value in myNum.
SET myNum, 12
Variables in function invocations are passed by reference. For example:
SET @INCREMENT, {num
SET num, num + 1
}
SET @count, 1
# The variable count is passed by reference.
INCREMENT count
# The value of count is now 2.
Imported namespaces and variables are global, regardless of where import statements are placed.
The binary period operator (.
) accesses a member variable of a namespace. For example:
$MATH "./mathLib.logi"
SET @radius, 3.5
# PI is a global variable defined in mathLib.logi.
SET @circumference, 2 * MATH.PI * radius
LogiScript has the following arithmetic operators:
+
– Addition-
– Subtraction or negation*
– Multiplication/
– Division%
– Remainder after division
The following operators manipulate numbers converted to 32-bit unsigned integers:
~
– Bitwise NOT|
– Bitwise OR&
– Bitwise AND^
– Bitwise XOR<<
– Bitshift left>>
– Bitshift right
Boolean values are represented by numbers in LogiScript. Zero is false, and all non-zero numbers are true. The following operators manipulate boolean values:
!
– Logical NOT||
– Logical OR&&
– Logical AND^^
– Logical XOR
LogiScript has the following comparison operators:
==
– Value equality!=
– Value inequality===
– Identity equality!==
– Identity inequality>
– Greater than>=
– Greater than or equal to<
– Less than<=
– Less than or equal to
A list element or string character may be accessed with the syntax below:
<sequence>[<index>]
List indices begin at zero. For example:
SET @myList, [90, 91, 92]
# Prints the second element, which is 91.
PRINT myList[1]
A function may be invoked in an expression by using this syntax:
<function>(<arg>, <arg>, <arg>...)
In this case, the first function argument provides the return value to be consumed by the parent expression. The first function argument is excluded from the parentheses in the function invocation. For example, the pieces of code below are equivalent:
SET @CALCULATE, {dest, x, y
SET dest, x + y * 2
}
CALCULATE @value, 3, 4
# Prints the number 11.
PRINT value
SET @CALCULATE, {dest, x, y
SET dest, x + y * 2
}
# Also prints the number 11.
PRINT CALCULATE(3, 4)
SET dest, value
Stores value
in dest
.
TYPE dest, value
Stores the type of value
in dest
as a number.
CONVERT dest, value, type
Changes the type of value
to type
, and stores the result in dest
.
SIZE dest, sequence
Stores the size of string or list sequence
in dest
.
RESIZE sequence, size
Changes the size of string or list sequence
to size
. Either truncates or appends extra elements at the end of sequence
.
IF condition, function
Invokes function
with no arguments if condition
is true.
LOOP function
Invokes function
repeatedly with no arguments until function
throws an uncaught value.
THROW channel, value
Throws value
on channel number channel
. Interrupts invocation of the current function.
CATCH dest, channel, function
Invokes function
with no arguments, and stores the value thrown on channel number channel
in dest
. If no value is thrown on the specified channel, dest
will be void.
PRINT value
Prints value
as text to standard output.
PROMPT dest
Pauses execution until the user inputs text through standard input. Stores the input text in dest
.
The void constant is VOID
.
The following boolean value constants are available:
TRUE
FALSE
The constants below are used by the built-in TYPE
and CONVERT
functions:
NUMBER_TYPE
STRING_TYPE
LIST_TYPE
FUNCTION_TYPE
VOID_TYPE
Built-in errors have the format [<error number>, <error message>]
. The channel number for built-in errors zero, and is available as the constant ERROR_CHANNEL
.
The following error number constants are used in built-in errors:
PARSE_ERROR
– Thrown when a script could not be parsedTYPE_ERROR
– Thrown when a value has the wrong typeNUMBER_ERROR
– Thrown when a number is not in an acceptable rangeDATA_ERROR
– Thrown when a data structure contains malformed dataSTATE_ERROR
– Thrown when a resource is in the wrong state or missing
The script below prints the prime numbers below 100:
SET @MY_CHANNEL, 1
# Defines a function which determines
# whether the given number is prime.
SET @IS_PRIME, {dest, number
SET @factor, 2
CATCH dest, MY_CHANNEL, {
LOOP {
IF factor >= number, {
THROW MY_CHANNEL, TRUE
}
IF number % factor == 0, {
THROW MY_CHANNEL, FALSE
}
SET factor, factor + 1
}
}
}
# Iterates from 2 to 99.
SET @number, 2
CATCH @bupkis, MY_CHANNEL, {
LOOP {
IF number >= 100, {
THROW MY_CHANNEL
}
IF IS_PRIME(number), {
PRINT number
}
SET number, number + 1
}
}
This script sorts the variable numberList
:
SET @numberList, [20, 15, 300, 4, 50, 0]
PRINT "Before sorting:"
PRINT numberList
# Defines a function which calls HANDLE
# from startIndex to endIndex.
SET @ITERATE, {startIndex, endIndex, HANDLE
SET @BREAK_CHANNEL, 1
SET @index, startIndex
CATCH @dummy, BREAK_CHANNEL, {
LOOP {
IF index >= endIndex, {
THROW BREAK_CHANNEL
}
HANDLE index
SET index, index + 1
}
}
}
# Performs selection sort.
ITERATE 0, SIZE(numberList) - 1, {index1
# Finds the minimum number in the rest of numberList.
SET @minNumberIndex, index1
SET @minNumber, numberList[minNumberIndex]
ITERATE index1 + 1, SIZE(numberList), {index2
SET @tempNumber, numberList[index2]
IF tempNumber < minNumber, {
SET minNumberIndex, index2
SET minNumber, tempNumber
}
}
# Swaps the minimum number into the correct place.
SET numberList[minNumberIndex], numberList[index1]
SET numberList[index1], minNumber
}
PRINT "After sorting:"
PRINT numberList