Prolix

From Esolang
Jump to navigation Jump to search
Prolix
Prolix2.png
Paradigm(s) Multi paradigm: object oriented, procedural (imperative), functional, structured
Designed by User:_morlus
Appeared in 12/16/2023
Computational class Unknown
Major implementations Join discord to download!
Influenced by Bash, sh, Batch, PowerShell, Lua, Self, SNOBOL
File extension(s) .prlx

Prolix (/ˈprəʊ.lɪks/; meaning lengthy, too many words) is an esoteric programming language, lightweight, high-level, multi-paradigm programming language set by @_morlus (Discord) or Morlus. Currently, the Prolix project has modified both the features and syntax of the language, but it remains intact in some keywords and still has a certain difficulty as an esoteric programming language.

In version 2.0 of Prolix (01/02/2024), it changed so much that I'm not sure if it really meant the word "Prolix" or shouldn't have made a new syntax for the programming language "Prolix"!

Prolix is ​​also a dynamically typed programming language (in version 1.1 and earlier, Prolix was a statically typed programming language and it created many programming obstacles) and garbage-collected, especially In particular, Prolix also supports many programming paradigms such as structured (especially procedural), object-oriented, and functional programming.

Join my small discord community here: https://discord.gg/tMaBPAPKca

Features

Prolix is ​​simply an esoteric language that makes it very difficult or complicated for programmers to understand, making a program written in it look very virtual and not understand how it works or make it difficult for you to understand. while writing the program. But even though it is an esoteric programming language, it does not mean it is useless because this is a programming language that only has a few features, but it can be written into a missing feature that Prolix does not have like other current programming languages.

Prolix supports creating objects, classes and functions, and also supports extending Prolix with C/C++. Prolix also ensures the protection of special attributes in an object when outputting the object (including pre-created or modified attributes in the object).

Syntax

The classic "Hello, World!" program can be written as follows:

$io:write "Hello, World!\n";

A comment in Prolix starts with a # and runs to the end of the line, similar to Python, Ruby, Perl, Bash, PHP. But Prolix does not support multi-line comment so you can use a string to make a multi-line comment because Prolix string ignore new lines.

# This is a comment :O

"
This is a multi-line comment :skull:
"

# Or you can make a multi-line comment like Python :moai:
"""
Hello :skull:
"""

# Even like this :skull: (But all the string quotes must be odd)
""""""""""""
:skull::skull::skull::skull::skull::skull::skull:
""""""""""""

Because Prolix does not support function instead of class so a example about function factorial looks like this:

class factorial :__edit__ {
    $math:eq $factorial:key "number";
    if $math:result {
        class vars;
        vars $vars;
        $vars:x 1;
        $vars:i 1;
        $math:sub $factorial:number 2;
        $vars:m $math:result;
        $math:result $vars:i;
        loop $vars:m {
            $math:mul $vars:x $math:result;
        }
        $factorial:result $math:result;
    }
}

More simple version of the above example:

class factorial :__edit__ {
    $math:eq $factorial:key "number";
    if $math:result {
        $math:sub $factorial:number 2;
        class vars :x 1 :i 1 :m $math:result;
        $math:result $vars:i;
        loop $vars:m {
            $math:mul $vars:x $math:result;
        }
        $factorial:result $math:result;
    }
}

Control flow

Prolix has one type of conditional test: if {}

But there's no not or and and even comparison operators also if statement only accept one argument for checking condition and execute expression.

if $something:attribute {
    # statement body
}

if 1 {
    # 1 is true
}

if 0 {
    # 0 is false
}

if "hi" {
    # "hi" is true
}

if "" {
    # "" is false
}

Prolix only has one type of loop is loop {} so there is no infinity loop but you still can make a huge number loop to make the loop repeatly like forever loop (Deprecated):

loop 999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 {
    # INFINITY LOOP!!
}

To make a infinity loop in version 2.0.1+ by this:

loop -1 # if the loop number is negative then it will loop forever {
    # Infinity loop
}

Loops can also be nested (put inside of another loop).

$math:result 0;
loop 5 {
    loop 5 {
        $math:add $math result 1;
    }
}
$io:write $math:result :write "\n";

Classes

Prolix class (or object) is kind of weird because Prolix does not support function so by calling a method of object you must put it all in attribute __edit__ to check if that object attributes got edited and result what attribute edited into __key__

class print :__edit__ {
    $math:eq $output:__key__ "obj";
    if $math:result {
        $io:write $output:obj :write "\n";
    }
}

print $print; # Create new object
$print:obj "Hello, World!"; # Edit object attribute and the class will started call attribute __edit__
# Expected output: Hello, World!

Tables

A table is a collection of key and data pairs, where the data is referenced by key. Tables are created using the object $table or the arguments given to a object attribute:

$table:create; # The table will stored in the $table "result" attribute
$io:write "Hello!" 123 0.5; # Expected output: table: 0x......

Tables are always passed by reference (see Call by sharing). A key (index) can be any value except table:

$table:create;
$table:set $table:result "x" 20;
$table:set $table:result 123 "hi";

# Accessing table entries
$table:get $table:result "x";
$io:write $table:result :write "\n"; # Expected output: 20

Tables are automatically assigned a numerical key, enabling them to be used as an array data type.

class test;
test $test;
$test:table "Hello" "World!" "Sup";
$table:length $test:table;
$io:write $table:result :write "\n"; # Expected output: 3
$table:get $test:table 1;
$io:write $table:result :write "\n"; # Expected output: World!

A table can be an array of groups.

class test;
test $test;
$test:table {$io:write "Hello\n";} {$io:write "Yo!";};
$table:length $test:table;
$io:write $table:result :write "\n"; # Expected output: 2
$table:get $test:table 0;
$utils:do $table:result; # Expected output: Hello

Groups

It is like a function but does not have any arguments, so it is called a group because it is a group of many lines of code.

$utils:do {
    $io:write "Hello, World!\n";
} # Expected output: Hello, World!

Object-oriented programming

Prolix is ​​an esoteric language but has support for object-oriented programming as well as current non-esoteric languages ​​but it has a special syntax as an esoteric language.

Creating a basic vector object:

class Vector :__edit__ {
    $math:eq $Vector:__key__ "set";
    if $math:result {
        $table:get $Vector:set 0;
        $Vector:x $table:result;
        $table:get $Vector:set 1;
        $Vector:y $table:result;
        $table:get $Vector:set 2;
        $Vector:z $table:result;
    }
    
    $math:eq $Vector:__key__ "magnitude";
    if $math:result {
        $math:pow $Vector:x 2 :x $math:result;
        $math:pow $Vector:y 2 :y $math:result;
        $math:pow $Vector:z 2 :z $math:result;
        $math:add $math:x $math:y;
        $math:add $math:result $math:z;
        $math:sqrt $math:result;
        $Vector:result $math:result;
    }
}

Vector $vec :set 0 1 0; # Create a vector
$vec:magnitude; # Call attribute magnitude
$io:write $vec:result :write "\n"; # Expected output: 1.0
$io:write $vec:x :write "\n"; # Access a member object and expected output: 0

Extending Prolix with C or C++

Adding new integrated modules to Prolix is pretty easy if you know how to program in C. Such extensions can do two things that cannot be done directly in Prolix: they can deploy new types of integrated objects, and they can call C library functions and system calls.

Let’s look at an example function in a file called square.c:

int square(int i) {
    return i * i;
}

Before we can call this function from the Prolix code, we need to compile it. When compiling code, we need to move the flag so that we can import the created file. To compile the C code, we run the following command:

gcc -fPIC -o clib.dll square.c

This will produce a file called clib.dll that we can import into our Prolix script. Let's place the square.prlx script in the same directory:

$cdll open "clib.dll";
$cdll load "square" 2;
$io:write $cdll:result :write "\n"; # Expected output: 4

What happens above is we enter cdll so that we can use $cdll:open to load the dynamic link library as a module in Prolix. The loaded clib.dll module is stored in the $cdll:__source__ attribute. Then the C function, or in our case the function, can be called as follows: $cdll:load "square"....

Standard Libraries

In version 2.0 and later, Prolix has tended to have fewer built-in objects to optimize Prolix and the interpreter software. So here is a table of built-in objects:

Built-in Object Description
cdll Used to extend Prolix in C through libraries from C and read C code files through dynamic link library files.
garbagecollect An automatic memory management that uses garbage collection based on certain algorithms that is in-built in Prolix.
io I/O library is used for reading and manipulating standard input/output and files in Prolix.
math This library provides basic mathematical functions. It provides all its mathematical functions and operator functions. Functions with the annotation "integer/float" give integer results for integer arguments and float results for float (or mixed) arguments. Rounding functions ($math:round, $math:ceil, $math:floor, and $math:modf) result an integer when the result fits in the range of an integer, or a float otherwise.
string This library provides generic functions for string manipulation.
table This library provides generic functions for table manipulation. It provides all its functions inside the $table object (or table class).
utils This library provides generic functions for other things like custom error reporting, string execution, getting object type, validation, etc.

cdll

Used to extend Prolix in C through libraries from C and read C code files through dynamic link library files.

cdll:open

Used to read dynamic link library files and convert them into cdll objects and stored in the __source__ attribute so that the cdll:load function can Read and run functions from the C library.

$cdll:open <source : str>;

cdll:load

When a .dll file is read and converted and saved to the __source__ attribute, this function will read and run the function from the converted file.

$cdll load <function : str> <arguments: any...>;

garbagecollect

An automatic memory management that uses garbage collection based on certain algorithms that is in-built in Prolix.

Prolix uses the occasionally running garbage collector to collect dead objects when they are no longer accessible from the prolix program.

All objects including objects, tables, groups, classes, strings, etc. must be managed automatically. Prolix uses a trace collector and incremental scanning that uses two numbers to control its garbage collection cycle, which is to pause the garbagemaker and multiply the step coefficient of the garbulk collector. These values are calculated in percentage terms and values of 100 are usually equal to 1 internally.

garbagecollect:enabled

This is an attribute and not really a function, but it is used to enable/disable automatic garbage collection.

$garbagecollect:enabled <value : boolean (not actual type)>;

garbagecollect:paused

Pause the garbage collector used to control the previous time that the trash collector needs to wait; it is called back by Prolix's automatic memory management feature.

$garbagecollect:paused <value : boolean (not actual type)>;

garbagecollect:count

Result the current collection counts as a table of count0, count1, count2.

$garbagecollect:count;

garbagecollect:pausecount

Result the number of objects in the permanent generation.

$garbagecollect:pausecount;

garbagecollect:collect

Collect and result amount of garbage collection.

$garbagecollect:collect;

garbagecollect:istracked

Result 1 if the object is currently tracked by the garbage collector, 0 otherwise.

$garbagecollect:istracked <object : any>;

io

I/O library is used for reading and manipulating standard input/output and files in Prolix.

io:write

Used to write data to the working file or, if there is no working file, write data to the console.

$io:write <object : any>;

io:append

Similar to function io:write but only has a different use: if there is a working file, it will add data instead of rewriting all the data.

$io:append <object : any>;

io:read

Reading the file and the result of the file data or not will read the user input in the console but there are many different modes.

$io:read;

Reading user input with modes:

Mode Description
%s Read full line of user input
%n Read a number of user input
%c Read a character of user input
integer Read provided characters amount of user input
$io:read <mode>;

You can do read more user inputs like this:

$io read "%s%n";

io:open

Open the file via the provided file path and after being provided it will be converted into a file object and saved into the __cwf__ attribute and if there is an existing working file then will report an error.

$io:open <source : str>;

io:close

Close the working file and if there is no working file, an error message will be reported.

$io:close;

math

This library provides basic mathematical functions. It provides all its mathematical functions and operator functions. Functions with the annotation "integer/float" give integer results for integer arguments and float results for float (or mixed) arguments. Rounding functions ($math:round, $math:ceil, $math:floor, and $math:modf) result an integer when the result fits in the range of an integer, or a float otherwise.

math:abs

Results the absolute value of x. (integer/float)

$math:abs <x : num>;

math:acos

Results the arc cosine of x (in radians).

$math:acos <x : num>;

math:add

Results the value x + y.

$math:add <x : num> <y : num>;

math:asin

Results the arc sine of x (in radians).

$math:asin <x : num>;

math:atan

Results the arc tangent of y/1 (in radians).

$math:atan <x : num>;

math:ceil

Results the smallest integral value larger than or equal to x.

$math:ceil <x : num>;

math:cos

Results the cosine of x (assumed to be in radians).

$math:cos <x : num>;

math:cosh

Results the hyperbolic cosine of x.

$math:cosh <x : num>;

math:deg

Converts the angle x from radians to degrees.

$math:deg <x : num>;

math:div

Results the value x / y.

$math:div <x : num> <y : num>;

math:eq

Results the value x == y.

$math:eq <x : num> <y : num>;

math:exp

Results the value e^x (where e is the base of natural logarithms).

$math:exp <x : num>;

math:factorial

Returns the factorial of x.

$math:factorial <x : num>;

math:floor

Results the largest integral value smaller than or equal to x.

$math:floor <x : num>;

math:frexp

Returns the mantissa and the exponent, of x.

$math:frexp <x : num>;

math:fmod

Result the remainder of the division of x by y that rounds the quotient towards zero. (integer/float).

$math:fmod <x : num> <y : num>;

math:ge

Results the value x >= y.

$math:ge <x : num> <y : num>;

math:gt

Results the value x > y.

$math:gt <x : num> <y : num>;

math:le

Results the value x <= y.

$math:le <x : num> <y : num>;

math:log

Result the logarithm of x in the given base. The default for base is e (so that the function result the natural logarithm of x).

$math:log <x : num>;

math:log10

Returns the base-10 logarithm of x.

$math:log10 <x : num>;

math:lt

Results the value x < y.

$math:lt <x : num> <y : num>;

math:mod

Result the value x % y.

$math:mod <x : num> <y : num>;

math:modf

Result the integral part of x and the fractional part of x. Its second result is always a float.

$math:modf <x : num>;

math:mul

Results the value x * y.

$math:mul <x : num> <y : num>;

math:ne

Results the value x != y.

$math:ne <x : num> <y : num>;

math:neg

Results the value -x.

$math:neg <x : num>;

math:not

Results the value !x.

$math:not <x : num>;

math:pow

Results the value x^y.

$math:pow <x : num> <y : num>;

math:rad

Converts the angle x from degrees to radians.

$math:rad <x : num>;

math:random

Result inclusive random integer of between x and y.

$math:random <x : num> <y : num>;

math:randomseed

Sets x as the "seed" for the random number generator: equal seeds produce equal sequences of numbers.

$math:randomseed <x : num>;

math:round

Results the rounded value of x.

$math:round <x : num>;

math:sin

Results the sine of x (assumed to be in radians).

$math:sin <x : num>;

math:sinh

Results the hyperbolic sine of x.

$math:sinh <x : num>;

math:sqrt

Results the square root of x.

$math:sqrt <x : num>;

math:sub

Results the value x - y.

$math:sub <x : num> <y : num>;

math:tan

Results the tangent of x (assumed to be in radians).

$math:tan <x : num>;

math:tanh

Results the hyperbolic tangent of x.

$math:tanh <x : num>;

string

This library provides generic functions for string manipulation.

string:concat

Combine all strings into one string and if the given argument is not a string, it will also be converted to a string and then combined.

$string:concat <object : any...>;

string:upper

Converts a string into upper case.

$string:upper <string : str>;

string:lower

Converts a string into lower case.

$string:lower <string : str>;

string:reverse

Converts a string into reversed string.

$string:reverse <string : str>;

string:length (Deprecated in 2.0.1+)

Results a length of string.

$string:length <string : str>;

string:char

Results a char of string by index.

$string:length <string : str> <index : num>;

string:repeat

Results a repeated string by amount.

$string:repeat <string : str> <amount : num>;

string:replace

Results a string where a specified value is replaced with a specified value.

$string:replace <string : str> <old : str> <new : str>;

string:split

Splits the string at the specified separator, and returns a table.

$string:replace <string : str> <separator : str>;

string:find

Searches the string for a specified value and returns the position of where it was found.

$string:replace <string : str> <value : str>;

string:sub

Returns the substring of string that starts at start and continues until end

$string:sub <string : str> <start : num> <end : num>;

string:format

Returns the formated string.

$string:format <string : str> <arguments : any...>;

The Prolix format string is replaced by all '%' contained in the string of each argument.

$string:format "Hello, %!" "World"; # Expected string: "Hello, World!"
$string:format "My name is % and I am % years old." "John" 21; # Expected string: "My name is John and I am 21 years old."
$string:format "The symbol '\%' is %." "cool"; # Expected string: "The symbol '%' is cool."

string:unicode (Added in 2.0.1)

Used to convert ASCII code into a character.

$string:unicode <char : str>

string:ordinal (Added in 2.0.1)

Used to convert a character into ASCII code.

$string:ordinal 

table

This library provides generic functions for table manipulation. It provides all its functions inside the $table object (or table class).

table:create

Create a new table and put it in attribute result

$table:create;

table:set

Set a new entry for the provided table.

$table:set <object : table> <key : any> <value : any>;

table:remove

Remove a provided entry key in the provided table.

$table:set <object : table> <key : any>;

table:get

Get a entry key from the provided entry key in the provided table then put it into attribute result.

$table:get <object : table> <key : any>;

table:get

Get a entry key from the provided entry key in the provided table then put it into attribute result.

$table:get <object : table> <key : any>;

table:length (Deprecated in 2.0.1+)

Results the length of the provided table.

$table:length <object : table>;

table:push

Push a value into the provided table with index is the old size of the table.

$table:push <object : table> <value : any>;

table:clear

Clear all entry in the provided table.

$table:clear <object : table>;

table:combine

Combine two provided tables.

$table:combine <object : tableA> <object : tableB>;

table:find

Find the entry index from entry value and results in attribute result.

$table:combine <object : table> <value : any>;

table:foreach

Execute group for each entry and it is store key and value in attribute key and value

$table:foreach <object : table> <func : group>;

Here's a example:

$table:create;
$table:set $table:result 0 "Hi";
$table:set $table:result 1 "Yo";
$table:set $table:result 2 "Sup";
$table:set $table:result 3 "Hello";
$table:foreach $table:result {
    $io:write $table:key :write ' ' :write $table:value :write '\n';
}

Expected output:

0 Hi
1 Yo
2 Sup
3 Hello

utils

This library provides generic functions for other things like custom error reporting, string execution, getting object type, validation, etc.

utils:exec

Execute prolix code by string.

$utils:exec <string : str>

utils:tostr

Convert object into string.

$utils:tostr <object : any>

utils:tonum

Convert object into number.

$utils:tonum <object : any>

utils:type

Results the type of the object.

$utils:tonum <object : any>

utils:assert

Assert the object if True, report error otherwise.

$utils:assert <object : any>

utils:error

Report a error with custom message.

$utils:error <message : any>

utils:do

Execute group and if result the table with success and error message.

$utils:do <func : group>

Example:

$utils:do {
    $math:div 2 0;
}
$table:get $utils:result 0;
$io:write $table:result; # Expected output: 0
# Because 2 cannot divide with 0 so the "group" report error but the "$utils:do" ignore it.

utils:exit (Added in 2.0.1)

Exit program instantly.

$utils:exit;

utils:length (Added in 2.0.1)

Get length of the object provided (except num)

$utils:length <object : any>

utils:tick (Added in 2.0.1)

Get how long the program has been running in seconds.

$utils:tick;