Prolix

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;