microScript 2.0 is coming!
Actually, it is already available, still in 'alpha' status because not 100% feature-complete yet. But progress is being made everyday and we should reach 'beta' soon. To try it out, just go in the advanced project settings and pick "microScript v2 - alpha" as project language.
You already know microScript 2.0!
Fear not: everything you have learnt to do in microScript 1.0 still works in microScript 2.0. You can easily switch to microScript 2.0 already and make no change to your programming habits. You might even activate microScript 2.0 on a project you have started in 1.0. In most cases, it will work flawlessly.
In some edge cases, you could encounter one of the following problems though:
- maybe your project uses a variable name which is now a keyword (do, every, after, sleep, type) ; if it does, you will have to rename such variables
- The scoping of local variables in microScript v1 was a bit too fuzzy and too permissive. A local variable could still be visible after the end of the block where it was defined. This is no longer the case and depending on how you were using local variables, could necessitate a slight rework of your code to make it work with microScript 2.0
- microScript 2.0 still may have bugs. If you encounter some strange situation, please contact me and let me have a look!
Design goals
The design goals of microScript haven't changed: a language which is simple to learn,
forgiving, that cannot break at runtime and can be edited live. microScript 2.0 is still
very much that and
some of the new features it brings make it even simpler to use ("threads" may sound scary but
just ignore that and think that you can now use sleep 1 second
!).
Implementation
microScript 2.0 is a full reimplementation of the microScript engine. The new engine is based on a stack machine which reads and interprets a bytecode representation of your code, generated by a compiler. This design alone makes it much more efficient compared to the v1 interpreter (about 3x performance boost). But this is not enough and the new engine is also capable of transpiling whole chunks of code to JavaScript, allowing it to match or even outperform the v1 transpiler in some cases!
Note that currently, the transpiler is turned off, time to get a first stable version of microScript 2.0. Then I will start activating transpilation incrementally (each bytecode instruction is set to be transpilable or not and transpilation is only triggered when a sequence of such instructions is encountered).
This new microScript engine opens many more possibilities: the most obvious one is the introduction of preemptive threads / coroutines, providing much easier ways to control the timing of events in your game (see below). It also makes it possible to create a full step-by-step debugger or to implement some advanced performance profiling. Do not take this as a promise though, it will take a lot of time to get there! Another possibility I am thinking of is to make a port of the language engine to C or Nim or maybe C# ; the new engine design would make that much easier.
What is new and how to use it
But enough of blah blah and let's see what you can already do with microScript 2.0 today ;-)
Non-ASCII identifiers are now allowed
This has been discussed on Discord and I finally decided to go for it. What convinced me was to read the reasons why Python went for it too: https://peps.python.org/pep-3131/
Easily handle time in your game
Simple things like waiting 2 seconds before returning to the main menu or taking damage every second were not so easy to do in microScript 1. Many beginners had to struggle with the idea of creating an incremental counter and checking its value until it reaches value x. It is much easier now:
Sleep
You can pause execution of your code for a specified amount of time. Example:
if gameover() then
sleep 2 seconds
backToMainMenu()
end
The sleeping time can be given just as a number in milliseconds, or you can append a time unit. Accepted units are: millisecond, milliseconds, second, seconds, minute, minutes, hour, hours, day and days.
Note: doing this (sleeping in the "main thread") implies that the screen will stop being refreshed during that time. If you just want to delay the execution by 2 seconds without stopping your screen animations, check other methods below.
Schedule something for the future
Here is another way to return to the main menu after 2 seconds:
if gameover() then
after 2 seconds do
backToMainMenu()
end
end
You can put any number of instructions between do
and end
, consider it a function body - that is exactly what it is!
Do something periodically
As someone once suggested, you can now do:
every 500 milliseconds do
if player.isInLava() then
player.takeDamage()
end
end
Do some heavy work in background
If you want to do heavy computations without affecting the main rendering loop, you can start it in a new "thread" like this:
do
while not world_ready
generateMoreChunksOfMyProceduralWorld()
end
worldIsReady()
end
Embedding any code like this into a do .. end
has the effect of creating a separate, new execution thread, just like after
and every
do.
Threads
Each use of after
, every
or just do .. end
creates a new execution thread and returns a thread object. Threads can
be paused, resumed or stopped.
score_counter = every 100 milliseconds do
score += 1
end
// when you want to stop scoring
score_counter.pause()
// when you want to restart counting score
score_counter.resume()
Function | Description |
---|---|
thread.pause() | Pauses the execution of the thread until resume() is called |
thread.resume() | Resumes execution of the thread |
thread.stop() | Stops and discards the thread definitely |
system.threads
retains a list of currently active secondary threads (running or paused).
Note about threads
- The default thread, or "main thread" is dedicated to loading your source code files and to executing
update()
anddraw()
. This thread has a higher priority than secondary threads, to prevent your code from being interrupted in the middle of a screen refresh.- microScript "Threads" are not matched with system-level threads. They all share time slices of a single real thread (the browser's JavaScript execution loop).
- Periodic threads created with
every
will follow their pace with great accuracy, down to the millisecond.- Interrupting a thread with
sleep
is not as accurate, expect variations up to 16 milliseconds.
Preemptiveness (is that even a word?)
The threading system in microScript is preemptive by default. It means that if you have some level of concurrency (several different tasks running at the same time and consuming CPU time), the system will take care of sharing the computing time, giving each task a chance to run at any moment, by interrupting other tasks whenever necessary. This is the best and recommended setting for everyone.
You can switch to a non-preemptive scheduling if you wish to, by setting system.preemptive = 0
. If you do this, the system
will never interrupt a running task before it is complete, unless the task explicitly calls sleep 0
(or any other value), from time to time, to give a chance to other tasks to use their share of the CPU.
Dynamic type checking
You can now check if a variable exists, if an object property exists and which type they have. my_variable.type
will return:
0
(no type) ifmy_variable
is not defined"number"
ifmy_variable
is a number"string"
ifmy_variable
is a string"function"
ifmy_variable
is a function"list"
ifmy_variable
is a list"object"
ifmy_variable
is an object
Numbers
- You can now write numbers with exponential notation, e.g.
5.0e+10
- You can write hexadecimal numbers e.g.
0xFF
Binary ops
They were requested a long time ago, so here they are:
- Binary and:
&
- Binary or:
|
- Binary shift left:
<<
- Binary shift right:
>>
More string escapes
Strings can span on multiple lines in microScript, the syntax highlighter in microScript 2.0 was fixed to correctly reflect this. Also there is a number of new escape characters you can include in your strings:
\n
is a newline character\'
single quote\"
double quote\\
backslash""
within a double-quoted string value, a pair of double quotes is parsed as one double-quote''
within a single-quoted string value, a pair of single quotes is parsed as one single-quote
Multi-line comments
/* You can now
insert
multiple-lines comments */
Upcoming features
This is what remains to be done for microScript 2.0:
- capture outer local as const values in function def, including function itself when assigned as local
- capture
this
in function def as well - more complete String functions and Array functions
- parse number / convert string from and to number
- operator overloading
Possible upcoming features
Also remaining on my list:
- add functions to List prototype, allowing to augment the functionality of the lists
- prototypes for String, List, Object?, Function?