Quick intro to MKM Script language

Scripts for MKM and MIDI macros
Forum rules
This forum is locked.
We should look for some other (managed) home for the Scripts if we need one, but this has been mostly a place for spam, so no.
Site Admin
Posts: 771
Joined: Fri Oct 22, 2010 9:54 am

Quick intro to MKM Script language

Post by Oscar »

The script language used in MKM and MIDI KM is a brand new scripting language and I must say one of the fines I ever made.

A full and very detailed description of the language is in the software PDF file. Every function is described with many examples.


Here is a quick intro to the language, that is also part of the pdf file:

The language is based on BASIC for the simplicity but it avoids some of the old BASIC idiosyncrasies and instead takes parts from C, Java, LUA.

The core language has only minimum of commands, like if-then, for-next loop etc.. Those are really just handful to keep it clean. The rest of the language is extended by functions for everything possible, string functions, arithmetic functions, clipboard, keyboard etc...

The language is build such way that regardless what programming you have done, it should be familiar.
ddimage0.jpg (59.59 KiB) Viewed 3348 times
The script also allows for more advanced approach using references or using extended array arithmetic.

Comments are standard c comments:

Code: Select all

// This is line comment
/* These are comments too
End of commands is as with BASIC - no special characters:

Code: Select all

a = RND(0, 100)
Because I write a lot of code in c, I made the script ignore ; if put at the end of command line - because I was putting it there all the time .

Core command set is all written in lowercase.

Code: Select all

print "Oscar script is alive"
All extended functions (for example for strings) are used in mixed capitals.

Code: Select all

newstring = FindNumbers(string)
Variable types:

(Lets just forget about reference now)

all normal variables are local - that is they exist only within each script.
But you can create global variable by prefixing it with GLB_
A global variable will be shared between all scripts - so one script can talk to another script through global variables (which can be also arrays)
In terms of macros, think for example of a key modifier scenario: pressing macro key A will modify what other macro key which you press next does. So the key A will set a global variable to 1, then other keys will check if that global variable has been set to 1 and if yes it will do one action, if not it will do another action. Then reset the global variable to 0. that is just one of millions of examples where global variables can be used.

Code: Select all

normalBVariable = 100
GLB_global_variable = 200
All variables are auto assigned when first used - there is no declaration of variable.
Variables are case sensitive.

Code: Select all

nVariable = 123
fVariable = 3.1415
sVariable = "Oscar Script"
You can also use HEX and BIN numbers as typical in other languages with prefix 0x or 0b respectively

Code: Select all

nHex = 0xFF
nBin = 0b100000000
A string can have escape characters as typical in other languages such as c

Code: Select all

sEscapeCorrect = "Files\\text.txt"
but I also borrowed the _R literal prefix from modern c for RAW string option

Code: Select all

sNoEscape = _R"Files\text.txt"
Type reassign
In some cases the script will automatically re-assign a type if there is a possible loss of data (for example assigning float to integer)

Code: Select all

//we started with 'a' as integer
a = 23
b = 1.23
//script will auto reassign 'a' to FLOAT
a = a+b
In this case script started with 'a' as integer but then re-assigned it to float to prevent loss of data when we added
float number to it.

The script has the most free form arrays out there.

Not only the arrays don't need to be declared, they can be mixed types, non sequential, even the index can be negative and they can be infinite dimensions.

Code: Select all

k[6] = 12
sString[1] = "test"
sString[k[6]*1000] = "test 1000"
integer[0] = 1234
integer[-200] = 4325
array[x][y] = 20
somebigarray[0][100][23][45][2] = 100
There is a whole fat section about arrays in manual, mostly because the script has in-build array arithmetic which is a very clever thing.
so you can write directly for example

Code: Select all

D[] = A[]* B[]+C[]*2
which in this example multiplies members of two arrays, then add another array where each member is multiplied by 2 - all in one simple line.
Looks clever, now imagine that also works for strings.
It goes even deeper, every function in the script can use the arrays directly. So finding a substring in a single string is as easy as finding that substring in array of strings -no need for a loop.

Constants and macros
Basically lifted from c language

#const IDENTIFIER expression
#define IDENTIFIER macro

Code: Select all

#const DEG_MULT 3.1415926/180
#define MY_PRINT println "Value of a: ", a
What are the core commands

Code: Select all

if condition then
Note, the endif is always mandatory regardless if statements is one line or multiple.
condition operators: == != <> < <= > >=
Note: *equal* condition is used as in c, == to avoid confusion with assign =

Nested if then else:
The rule is there must be same number of endif than if
So the nested commands look a bit hairy, but avoid logical errors.

Code: Select all

a = 3
if a<1 then print "a<1"
	if a<2 then print "a<2"
		if a<3 then print "a<3"
			print "a=3"
for next loop

for counter = nStart to nEnd step nStep
next counter

Code: Select all

for a = 0 to 5
   print a
next a

for a = 5 to 1 step -1
   print a
next a
no surprises here. Well, except in this script you can actually override "step" within the loop if you want to be super clever and create non-linear loops:

Code: Select all

for a = 1 to 256 step 1
   print a,","
   step = a //this changes the step of the loop inside the loop
next a
The result of this would be: 1,2,4,8,16,32,64,128,256

The loops also can have break and continue statements inside loops as it is typical in c;

goto and gosub commands
Yes favorite of old programmers and pretty much discouraged , there is still goto command

goto label

the label definition is in c fashion label:

Code: Select all

  if (c>-1) then
   goto finish

println "done"
gosub is similar, but the end of subroutine expect to return with unsurprisingly "return" command.
This also requires the main part of program (before the subroutines) will end with "end"
This basically makes a poor mans function (the script has also user defined functions as well)

Code: Select all

gosub subroutine
DisplayText("We are in Main program")

DisplayText("We are in Subroutine")
print and println
basically used for debugging, these command will display text or variables in the output window during script editing.
In actual use of the script in macros - they will do nothing at first but can be cleverly used to print to file or format strings
println is a print with carriage return

Code: Select all

print "a=",a,", b=",b
The clever part of using print in actual macro is that whenever you use print or println the commands are also added to a variable called OUTPUT
So this actually saves on formatting strings the "cheap" way. You can actually create rather complex strings, for example before saving them to file without too much of needed string operations.
A good example may be creating a xml file

Code: Select all

//clears OUTPUT in case we used print before this line
bookid = "0021313"
TAB = "\t"
QT = "\""
println "<?xml version=\"1.0\"?>"
println "<catalog>"
println TAB,"<book id =",QT,bookid,QT,">"
println TAB,TAB,"<author>Misc, Jones</author>"
println TAB,TAB,"<title>How to compute</title>"
println TAB,"</book>"
println "</catalog>"
Conditional operator - borrowed from languages as c
Every programmers favorite tool when writing obfuscated and hard to read code. No seriously conditional operator saves a lot of if-then-else commands that can be expressed as a single line.

operand ? expressionYes : expressionNo

Code: Select all

b = a>5 ? a*2 : a/2
When operand is true the expressionYes will be evaluated
when false the expression after : will be evaluated

The power comes from the fact that they can be just part of longer expression:

a = 32 + (a>5 ? a*2 : a/2) * 4

They became pretty hard to read when nested.

result = ( a == "B" )? "blue" : ( a == "R") ? "red" : "green"

The last part of the core language is definition of user functions

Code: Select all

function MyFunction(var1,var2,var3)
return nret
When using function, you need to use end in your main (also called root) program: The program
execution should never get to the function declaration itself.

Code: Select all

//calling function
rnd = RandomFL()
println rnd


// function declaration
function RandomFL()
   A = RND(0,100)/100.0
return A
Function Parameters
The arguments list the input parameters. They can be from 0 to 9 arguments
function Test(nVar1,nVar2)
There is no type declaration in Oscar Script and so the function arguments will be assigned the type on run-time
depending what you will pass into the function
Function should return a value using return command. While return value is not mandatory, you should specify
return of 0 or nil even in function that doesn't return value just to keep warning off.

An important property of function is:
Variables (except Global variables) inside functions are local to the function instance only. You may think of function as a whole separate script and can communicate to other parts only through function parameters, return value and global variables.
Variables declared in main program will not be visible in the functions, unless they are passed through the function arguments
Variables declared in functions will not be visible in other functions or main program unless passed as return value

There is much more to the function, for example recursive calling or reference to arrays as function parameter. Those are advanced topics and are in detail described in the manual.
That is the core of language.

Now the language is extended by many, many functions from string operations, string tokenizers, regex to clipboard functions etc...much more than could be found in other languages which allows for creating scripts that can do almost anything.
The manual has every single function explained.