SCiPL

= SCiPL (SCi Programming Language) =
The SCi programming language is a high-level, interpreted, dynamically typed programming language created by User:Alx.
== SCiPL - Data Types ==
NULL 	Initialized at runtime under names (nil, NULL). This is the NULL object.
bool 	Represented in code as 'true' or 'false'.
string 	Represented in code as single or double-quoted literals.
int 	Represented in code as either a hexadecimal literal, or base-10.
map 	Spawned via the 'map' function. Allows for key-value tables, aka the map.
table 	Represented in code with opening curly braces and closing curly braces.
function	Type for function protos.
float 	32-bit floating-point numbers.
extern 	External types, like char-arrays.
== SCiPL - Syntax ==
The SCiPL syntax follows the Lua (5.1) syntax, however functions very differently from Lua.
=== Differences ===
1. SCiPL has only one scope, being the global scope. Local assignments have no effect on the scope.
2. locally assigning in SCiPL, assigns x-amount of immediate variables to a singular value, whereas normal assignment usually requires the same amount of values to pair the variables. It is also worth noting that if there is no value given for the local assignment, they will all be assigned to the value in the metavariable called '__setslot', which is initialized as NULL. i.e;
local a, b, c -- a, b, and c are all assigned to the contents of the metavariable __setslot
local a, b, c = 1 -- a, b and c are all assigned to 1.
a, b, c = 1 -- invalid - there must be more values to match the sequence.
3. Function proto parameter names are set as global variables, once called. i.e;
function a_function(a, b)
 return a + b
end
a_function(1, 2)
'a' and 'b' are both now global variables, assigned to 1 and 2.
4. Non-builtin function calls (if a value is returned explicitly in the function body) will return the values inside a table. However, if there is no return statement, the function will not return a table, but instead return NULL. If a function body has a return statement, there must be a value to return. i.e;
function ex() -- valid syntax
 result = 1 + 1
 return result
end
function ex() -- invalid syntax
 result = 1 + 1
 return
end
5. If statements cannot have elseif-else clauses. i.e;
if conditions then
 print(NULL, 1)
end
is the only accepted form of if statement.
6. Table indexes start at 0, not 1. Tables also do not support key-value pairing. i.e;
a_table = { -- valid table
 1,
 2,
 3,
 4
}
a_table = { -- invalid table
 ["key"] = 1,
 ["key2"] = 2,
}
7. Key-value paired tables (aka the map type) can be spawned using builtin 'map' function, which takes tables paired with key-values as key and value pairs. i.e;
my_map = map(
 {"key1", 555},
 {2, "value"}
)
8. Function call argument unpacking is very different. In order to call a function with variable-sized arguments, you cannot use the 'unpack' function, you must comment --[[UNPACK]] before the function call, and the last argument will be unpacked for the function call, which is assumed to be a table. i.e;
--[[UNPACK]]vararg_call(1, {2, 3, 4})
9. f-strings are supported. f-strings are almost pythonic, but are quite different to python's f-strings, as they are just function calls. You can make one look pythonic by a non-parenthesized function call, i.e;
formatted_string = f{"{} + {} is {}", 1, 1, 2}
print(NULL, formatted_string)
10. There is no 'break' keyword to break out of loops.
More...
There are also many more differences from Lua to SCiPL, such as builtin libraries, builtin functions, and said data types. A list of builtin functions, and their descriptions are below.
Name 	Type 	Description 	Parameter Type(s)
__include 	Builtin 	Includes a SCi module file (compiled .(csci), or plain (.sci)) into the current namespace. 	string;
__discard 	Special Builtin	Discard the topmost item on the stack. 	
__delref 	Special Builtin	Deletes a reference or variable by name. 	string;
__getenv 	Special Builtin	Returns the current namespace. 	
__base 	Builtin 	Returns a list of all builtins. 	
__incrref 	Special Builtin	Increments a variable if variable is an int by 1. Used for optimization. 	string;
__decrref 	Special Builtin	Decrements a variable if variable is an int by 1. Used for optimization. 	string;
map 	Builtin 	The function that allows spawning key-value tables, aka the map type. 	*table;
print 	Builtin 	Prints an object. First argument is an end specifier, if NULL, the end is a newline. 	...; *...
type 	Builtin 	Returns the type of the argument as it's name, as a string. 	...
math 	Library 	A map library of mathematical functions. 	
string 	Library 	A map library for string operations. 	
table 	Library 	A map library for table operations. 	
iter 	Builtin 	Spawns an iterator, usually used for 'for' iterations in an iterable. 	(table, map);
input 	Builtin 	Captures stdin with a prompt as the first argument. No prompt if empty. 	string; bool;
stoi 	Builtin 	Typecasts a string into an int. 	string;
tostring 	Builtin 	Typecasts an object into its string representation. 	...;
bit32 	Library 	A map library for bitwise operations. (32-bit) 	
range 	Builtin 	A numerical-range iterator, usually used in for-loops. 	int; int; int;
f 	Builtin 	Returns a formatted string. 	table;
b 	Builtin 	Encodes a string into a byte-string, or char array. 	string;
unpack 	Special Builtin	Unpacks table items onto the stack. 	table;
io 	Library 	A map library for file operations. 	
dump 	Builtin 	Compiles and returns the bytecode of provided code in string representation. 	string;
fpairs 	Builtin 	Calls a function on every value inside the provided table, and returns an equivalent table with the new items.	function; table;
return_call	Builtin 	Calls a function with a table of arguments, and returns the first item in the return table. 	function; table;
== SCiPL - Internals ==
The current SCiPL interpreter is a stack-based virtual machine. There are currently (as of SCiPL version v0-m6 b) 40 opcodes. The instruction notation is explained below:
The instructions are a fixed size of 40 bits / 5 bytes.
Instruction Type A
First Bit (0)
Operand A: 32 bits
 Opcode: 6 bits
 Opmode: 2 bits
Last Bit (40)
Instruction Type B
First Bit (0)
Operand A: 8 bits
Operand B: 8 bits
Operand C: 16 bits
 Opcode: 6 bits
 Opmode: 2 bits
Last Bit (40)
The current instruction set is described in the following table.
Opcode 	Description
LOAD_GBL 	Loads a global variable onto the stack.
LOAD_KST 	Loads a constant from the constants pool onto the stack.
LOAD_UL 	Loads an unsigned-long integer onto the stack.
IJMP 	Incremental absolute jump.
DJMP 	Decremental absolute jump.
MKTBL 	Creates a table consuming x-amount of items from the stack.
MKMAP 	Creates a key-value pair map consuming x-amount of items from the stack. Obsolete opcode.
SUBSCR 	Performs subscription on a table.
SET_GBL 	Pops an item off the stack, and sets it under a global variable.
SET_SUBSCR	Subscripts a table or map, and assigns the key/index as a value.
ADD 	Pops two items off the stack, and performs addition.
MUL 	Pops two items off the stack, and performs multiplication.
DIV 	Pops two items off the stack, and performs division.
POW 	Pops two items off the stack, and performs exponentiation.
MOD 	Pops two items off the stack, and performs modulo.
SUB 	Pops two items off the stack, and performs subtraction.
DISCARD 	Pops the topmost stack item off the stack.
CALL 	Consumes x-amount of items off the stack as arguments, +1 extra as the callable, and calls.
NADD 	Equivalent to ADD, except with variables. Used for optimization.
NMUL 	Equivalent to MUL, except with variables. Used for optimization.
NDIV 	Equivalent to DIV, except with variables. Used for optimization.
NPOW 	Equivalent to POW, except with variables. Used for optimization.
NMOD 	Equivalent to MOD, except with variables. Used for optimization.
NSUB 	Equivalent to SUB, except with variables. Used for optimization.
MKFUNC 	Creates a callable function from TOS, which is assumed to be the function proto.
IJMP_FALSE	Conditional incremental jump.
DJMP_FALSE	Conditional decremental jump.
NOT 	Performs a logical NOT on the topmost stack item.
LAND 	Pops two items off the stack and performs a logical AND.
LOR 	Pops two items off the stack and performs a logical OR.
RETURN_NUL	Returns NULL. This is at the end of every code body.
RETURN 	Returns x-amount of items from the stack, in a table.
CMP 	Pops two items off the stack, and performs one of the following actions: <, >, <=, >=, ~=, ==.
LOAD_NUL 	Loads NULL onto the stack.
LOAD_BOOL 	Loads a boolean onto the stack, either being true or false.
CONCAT 	Pops two items off the stack which are typecasted to strings, and concatenates them together.
GET_LEN 	Gets the length of TOS, which is assumed to be either a string, table map or other iterable.
FORJMP 	For-iterator conditional jump. Jumps to offset x once iterator is exhausted.
NEG 	Inverts the topmost stack item.
LD_FLOAT32	Loads a float onto the stack.
== SCiPL - Extras ==
=== Example Programs ===
1 - Guess the Number Game
__include("librandom")
min = stoi(input("Pick a number: "))
max = stoi(input("Pick another: "))
n = unpack(randint(min, max))
guesses = 1
print(NULL, f{"I'm thinking of a number between {} and {}. Good luck!", min, max})
while true do
 check = stoi(input("Your guess: "))
 if (check == n) then
 return print(NULL, f{"You guessed my number in {} tries!", guesses})
 end
 if (check < n) then
 print(NULL, "Too low!")
 end
 if (check > n) then
 print(NULL, "Too high!")
 end
 guesses = guesses + 1
end
STDOUT:
Pick a number: 1
Pick another: 10
I'm thinking of a number between 1 and 10. Good luck!
Your guess: 1
Too low!
Your guess: 4
Too low!
Your guess: 7
Too high!
Your guess: 6
You guessed my number in 4 tries!
2 - Calculator App
play = true
function add()
 a = stoi(input("Number A > "))
 b = stoi(input("Number B > "))
 print(NULL, "The result of A + B is:", a + b)
end
function multiply()
 a = stoi(input("Number A > "))
 b = stoi(input("Number B > "))
 print(NULL, "The result of A * B is:", a * b)
end
function sub()
 a = stoi(input("Number A > "))
 b = stoi(input("Number B > "))
 print(NULL, "The result of A - B is:", a - b)
end
function get_input(a)
 print(NULL, [[
[A]dd
[M]ultiply
[S]ub
[Q]uit
]])
 test = input(" > ")
 test = string.upper(string.subscript(test, 0, 1))
 if (test == "A") then
 return add()
 end
 if (test == "M") then
 return multiply()
 end
 if (test == "S") then
 return sub()
 end
 if (test == "Q") then
 play = false
 end
end
print(NULL, "Welcome to the Calculator:")
while play do
 get_input()
end
STDOUT:
Welcome to the Calculator:
[A]dd
[M]ultiply
[S]ub
[Q]uit
 > m
Number A > 10
Number B > 5
The result of A * B is: 50
[A]dd
[M]ultiply
[S]ub
[Q]uit
 > q
3 - XOR cipher message
__include("libcodec")
function xor_cipher(plaintext, key)
 r = ""
 for i=0, #plaintext do
 key_byte = string.byte(key, (i % #key))
 plaintxt_byte = string.byte(plaintext, i)
 r = r .. string.char(bit32.bxor(plaintxt_byte, key_byte))
 end
 return r
end
text, key = "here is a message i need ciphered", "and a key"
ciphertext = unpack(xor_cipher(text, key))
print(NULL, tostring(encode(b(ciphertext), "hex"), 1))
plaintext = unpack(xor_cipher(ciphertext, key))
print(NULL, plaintext)
STDOUT:
090b164541491845184103015312410c0059084e0a4504444b0610110601520444
here is a message i need ciphered
4 - Adler32 Checksum Algorithm
function adler32(stream)
 local ctr, B = 0
 A = 1
 while (ctr < #stream) do
 c = string.byte(stream, ctr)
 A = (A + c) % 0xFFF1
 B = (A + B) % 0xFFF1
 ctr = ctr + 1
 end
 result = bit32.bor(bit32.bshl(B, 16), A)
 return result
end
data = {"a very long string, indeed",
"data1",
"data2",
"data",
"dtaa"
}
for i in iter(data) do
 v = unpack(adler32(i))
 print(NULL, v)
 __discard()
end
STDOUT:
2140998020
97255884
97321421
67109275
68354459
=== Update ===
Regarding the `vararg call` in SCiPL Syntax section 8, I mean unpack, not vararg
Category:Languages
Category:Implemented
Category:Turing complete
Category:High-level