[Tool]LILIDE, scripting + IDE on Pokitto

release
open-source
tool

#1

I’ve split my recent work into two posts: this one and PokiPad.


LILIDE is a Pokitto “IDE”, or rather a text editor with an embedded interpreter of a small scripting language named LIL. It is based on PokiPad text editor. It is a toy, not something to do serious development with!

lilide

To get started, check out the example programs by selecting example from the menu.

For controls, see the PokiPad thread.

This project comes with additional modules and programs you can make use of. See the PokiPad project page and/or the repository to learn more.

The current LILIDE features are:

  • Those of PokiPad.
  • Ability to execute currently edited document with the LIL interpreter. Go to the menu and select run LIL.
  • A few built-in LIL example programs. Go to the menu and select example.

The limitations:

  • Smaller supported file size of 2 1 KiB compared to PokiPad. This is to leave more RAM for the interpreter.
  • No way to kill the interpreter. If it gets in an infinite loop, the only thing you can do is restart Pokitto. So be careful, save your progress.
  • Lack of advanced IDE features, such as syntax highlight, completion, line numbering etc. These are left for a project of its own.
  • The ported interpreter module is reusable, but pretty basic and can only present visual output, not return actual computed values to your C++ code. However, it should be next to trivial to make this happen if you need it. Just take a look at the code.
  • Errors’ position in code is not shown, they’re only reported via a pop up window. The reason is that this particular LIL implementation only reports a local position of the error. With a bit of efforts this could be fixed.

WARNING: back up your SD card if you value the content! The Pokitto SD card library I used is a WIP and has bugs. I may also have bugs in my code. It is therefore not impossible your files will get corrupted and/or lost.

Also: some SD cards may not work with this program. I experienced this with my own card – it’s an issue with the SD library. At the moment you can do nothing but switch to another card.

This program is free software released under CC0 1.0 waiver, except for the LIL source files, which are released under a different permissive free license (see the code). This means my work is in the public domain and you can do absolutely anything with it (including commercial use) without any burden (including giving me credit). If you include the LIL files, you have to respect the terms of its license (document changes). If you like the program and want to thank me, the best way is to share your own software as free and open source as well, using an appropriate license.

Here is the code and the binary:

lilide.bin (191.0 KB)

About LIL

LIL (little interpreted language, not to be confused with another LIL) is a tiny programming language I’ve found and that very pleasantly surprised me – its design is one of a few that get close to what I’d call beautiful.

It reduces the program to two basic elements: strings (data) and functions (program). Functions are actually strings too, so you might just say everything is a string in LIL. In this sense LIL’s structure is similar to Lisp’s s-expressions. This seemingly primitive system allows implementation of advanced concepts such as prototype-based OOP or exception handling – hence the beauty. (Demonstration programs are included with LIL.)

It’s very easy to learn the language (but difficult to get accommodated to – easy to learn, hard to master). Since all actions are functions (even variable assignments, flow control etc.), it’s enough to learn about functions and you’re set.

You can learn the language from LIL’s readme and examples:

http://runtimeterror.com/tech/lil/

Here is an additional small cheatsheet I’ve made for myself, if it helps you. It also documents the extra functions for Pokitto:

cheatsheet
  LIL functions for Pokitto:

    p_write what [x] [y] [color]       write value to screen
    p_read                             waits for pokitto button press and returns
                                       its value (ABCURDL = 0123456)
    p_pressed button                   returns 1 if given button is being held,
                                       otherwise a false value (codes are same
                                       as for p_read)
    p_clear [color]                    clear screen with given color
    p_wait n                           wait (sleep) for n frames
    p_rect x y w h color [filled]      draw a rectangle
    p_circle x y d color [filled]      draw a circle
    p_line x1 y1 x2 y2 color           draw a line
    p_pixel x y color                  draw a pixel
    p_update                           wait for the next frame, makes drawn graphic appear
    p_frame                            return Pokitto frame number
    p_time                             return elapsed time in ms
    p_rand                             return random byte value (0 - 255)
    p_sin x                            return sin of integer x (percents of a full circle, max = 100) as
                                       a value from -100 to 100

  general LIL cheatsheet (find more in lil's readme.txt)
  
    Everything is a string.
    case-sensitive
    separate with ; or newlines

    ## comment ##
    [...]                        execute what's inside square brackets and substitute the result, e.g.: print [expr 1 + 1]   
    if ["not"] val then [else]   branching, e.g.: if 1 {print one} {print noone}, returns evaluated branch result
    while ["not"] val code       while loop
    for init expr step code      for loop
    foreach [name] l code        executes code for each list item (its value will be in "name"), returns list of evaluations,
                                 e.g.: foreach i [list a b c] {print $i}
    return [val]                 returns from function with optional value

    set var val                  set given variable to given value
    $var                         get variable value (same as set with only one argument)
    expr a b c ...               combines arguments into one math epression, evaluates and returns the result
    func fname args body         define a new function, e.g.: func myfunc {a b} {print $a $b}
    list a b c ...               returns a new list with arguments as items
    count l                      returns number of items in a LIL list
    index l i                    returns ith item in a LIL list (0-based)
    indexof l v                  returns index of first occurence of value in a LIL list, or empty string
    append l v                   appends a value to a LIL list
    slice l i1 [i2]              returns a slice of a LIL list
    eval a b c ...               combines argument into a single string and evaluates as LIL code
    char n                       converts int to char (one-character string)
    rand                         returns a random number between 0.0 and 1.0
    inc name [val]               increment variable (or add given value)

The whole language consists of only two source files: lil.c and lil.h. Along with these comes an interpreter (REPL and an uninteractive interpreter in one program) that you can compile (just type make) and try out. There is also a number of examples in the repository.

I have added a Pokitto interpreter pokittolil.hpp that allows you to use the language on Pokitto. It adds a few essential functions (starting with p_) to LIL that are bound to PokittoLib’s functions. The functions allow writing text on screen, drawing primitives and getting some basic info about Pokitto… there are no functions for drawing bitmaps, playing sound or writing files, as this would be a lot more work to do… but it’s still fun.

What is this good for when we already have C++? For scripting. The programs in LIL can be constructed right on Pokitto, at runtime, and can be even changed (even by themselves) as they’re running. This is extremely flexible and allows you to avoid hardcoding functionality in your games. You can treat LIL scripts as the game’s “assets” that can be changed without recompiling the game.


#2

Oh goody goody. Now its time to try out this baby :hugs:

EDIT:

But, but, but… it’s so responsive :open_mouth:

That is one handy scripting language


#3

@drummyfish : I can’t get floats to work. For example [expr 1 / 100]


#4

Oh wow. LIL originates from the PDP-11. Awesome.


#5

TBH I haven’t tried floats at all, I thought no one would need them for these small programs. If anyone really needs fractions, they can use fixed point, which is just integer. Initially I had to make some data type and print format adjustments to make even integer expressions work – I may need to do the same for float. If I can’t make them work, I’ll at least explicitly disable them.

Thanks for pointing this out, I forgot to address it.


#6

Well, I was coding breakout an ran into this. Floats would make LIL much more useful, if you ask me, because rates of change (vx vy) would be a lot easier to handle.

Like I said, I am surprised at how well this runs and want to use it


#7

I’ll look at those floats in a while. If you want to try programs more quickly, just type them on PC into the source as a replacement for the default start program – that’s how I made the examples.

EDIT:

LIL uses sprintf to convert floats to string, but on Pokitto %f somehow doesn’t work in *printf functions. I switched to gcvt and it seems to work. I’ll test it and if it’s okay, I’ll push a new version.


#8

Ah, that’s my mistake then. I used the cut-down version of printf.

I probably need to add the %f support as well


#9

out

I’ll add one more example program on sorting and push this.


#10

Please make the examples load in sequence, not random


#11

Mkay, here it is

lilide.bin (191.0 KB)

But I think I hit the memory limits when trying the sort example, it just freezed a lot of times. The algorithm had nested loops in which it called functions in functions and I think that filled the memory – when I cut the document buffer to half, it helped a bit, but still I ended up not adding the sort example yet. I guess this is simply the price for that flexibility of directly executing the source and the everything as a string paradigm – we can’t go too far with the programs. A language that compiles to bytecode and does some optimizations would definitely perform better, so for a bigger project consider a “smarter” language. @Pharap could make this happen with LUA and/or other languages he suggested.

EDIT:

How do I check out how much RAM I’m using? The getFreeRam() function seems to only be there for GB compatibility and do nothing?


#12

I had a lot of problems with Python, that the stack was growing too big due the deep call chains or recursions in the Python interpreter implementation. That can be catched by calling CheckStack() in some code that is called in many places. I put that in the python memory allocation function (Python reserved an own heap for programs).


#13

But no way to check dynamic allocation? I suppose LIL is doing that a lot with strings.


#14

To check dynamic allocation, you can do something like this (untested, just an idea):

  • In the compiler flags, add: -Wl,--wrap,malloc and all calls to malloc with be redirected to __wrap_malloc instead.
  • implement a malloc wrapper that checks if something went wrong and calls a crash screen:
extern "C" void *__wrap_malloc( size_t size ){ 
  void *p = __real_malloc(size); 
  if( !p ) crash("out of memory");
  return p;
}