Log In  

Cart #pico_repl-17 | 2020-02-21 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

What's this?

A REPL (Read-Eval-Print Loop) for pico-8, in pico-8!

Supports executing most all lua & pico-8 statements. (if statements, for loops, functions - you name it)

While my code does its own parsing and execution of the statements, any functions you call are the real pico-8 functions.

What can I do with it?

Type expressions like 1+3/5 or sqrt(-2) to see the expected results. (Well - perhaps unexpected to some in the case of the sqrt)

Type statements or programs like the one below to do whatever you wish. (That one prints all global functions)

for k, v in pairs(_env) do
  if (type(v) == "function") ?k

Computations that produce lots of results are automatically paged, computations that do nothing indefinitely can be interrupted via escape (escape works in BBS or SPLORE only)

The special variable "_" is set to the value of the last expression you've executed.

The special variable "_env" points to the globals table (just like "_ENV" in standard lua/pico-8, just lower-case, making it easier to type)

Pico-8's globals are not disturbed and are the same as in a blank Pico-8 cart.

You can type "@i=0" to disable all text that "interrupts" the code while its executing, letting the code use up the entire screen. This also disables output paging, but pressing escape to stop execution still works.

What's the point of this? Pico-8 has a REPL already!

The main point of it is that I made it, everything else is up to you.

But for example, you can easily take a look at whatever Pico version happens to be running in the BBS, and see how it differs from your own.

Can I use this to write Pico-8 carts?

No. All this allows you to do is to write and execute some code.

You can't edit sprites/sfx/etc/etc, or export, or import, etc etc etc.

Hopefully that's limited enough to avoid running afoul of any legal concerns.

What are the caveats?

As said, all evaluation other than execution of global functions is implemented by me and may have bugs (feel free to report those), or subtle inconsistencies with real pico8/lua behaviour.

No bugs or missing features are currently known.

How do I copy code into the interpreter?

BBS now supports copy/paste, so it's easy - just use Ctrl+V to paste and Ctrl+X/C to cut/copy.

Well - cut/copy is currently a bit janky on the BBS - you have to press it twice to get it on the clipboard.

Outside the BBS, Ctrl+V still works, but Ctrl+X/C will only work once 0.1.12d hits (most likely).

The below hidden section is here for historical reasons, to show how one could have laboriously pasted into the BBS without paste support.

  1. Open your browser's console. (Press Ctrl+Shift+I or F12, then switch to Console tab)
  2. Paste "pico8_gpio = new TextEncoder().encode(``)" into the browser's console
  3. Between the two backquotes (`), paste the code you want to transfer to the cart.
  4. Press enter, the first 128 bytes will now be transferred - you should see them appear in the cart.
  5. Paste "pico8_gpio = pico8_gpio.slice(0x80)" into the browser's console.
  6. Press enter, the next 128 bytes will be transferred.
  7. Goto step 5 until all the code is transferred.

Anything else of interest?

There are some special @-prefixed identifiers which act like special variables:

  • @interrupt (or @i) : set this to 0 to disable anything that might interfere with the running code (e.g. prompts while running code, override of print function, etc.) (default: 1)
  • @code (or @c) : a table of the most recently input code (item 1 is the previous code, item 2 is the one before it, and so on. item 0 is the current code). You can use this to store the code you've typed somewhere, e.g. printh(@c[1], "@clip")
  • @max_items (or @mi) : the maximal number of items shown when printing a table. -1 means show all. (default: 10)
  • @colors (or @cl) : a table of the colors used, customization! color meaning: {output, errors, interrupts, prompt, input, input errors, comments, constants, keywords, punctuation, pico functions}

As well as some special @-prefixed functions:

  • @exec (or @x) : a function that takes a string, and executes the string as if it were written in the repl's command line.
  • @eval (or @v) : a function that takes a string, and evaluates the string as a lua expression (with the full power of the repl), returning its result.

And even some special @-prefixed commands (identifiers which perform an action when accessed):

  • @reset (or @rst) : completely resets the cart
  • @run : if _draw/_update/etc were defined, runs them as if from the pico mainloop (not fully compatible)

And some shortcuts:

  • Ctrl+X/C/V - cut/copy/paste.
  • Ctrl+B - insert a line-break. (in lieu of shift+enter...)
  • Ctrl+A/E - move cursor to start/end of line (in lieu of home/end...)


That's not a question.
I mean:


  • Fixed editing of large inputs


  • Added @exec & @eval


  • Fully working trailing-nil handling. (Thanks to JWinslow23 & sparr for ideas in the discord)


  • Ctrl+A/E as a poor linuxman's home/end


  • More trailing-nil handling fixes.


  • Ctrl+B inserts a line break.
  • Added @reset & @run
  • Minor syntax fixies. (Around pico-8's questionably-parsed syntax)


  • Fix time()/t() not working correctly.


  • Supported copying/pasting in BBS. (Now that it's supported by pico)
  • Fixed syntax highlighting in long lines.
  • Fixed some... "security holes" in the repl. (__pairs, global overrides)


  • Syntax highlighting! (Customizable, too - see @cl)


  • Added @c to allow programmatically accessing code.
  • Added table printing ({1,2,3} instead of <table>)
  • Some minor syntax fixies


  • Allow escape to bring up the pause menu when not used to cancel input.


  • Added paste support
  • 2 minor syntax bugfixes


  • Support goto and tailcalls
  • Fix recursion.


  • Fix expressions like 'type(nil)'


  • Support comments, bracket-string literals and all string literal escapes
  • Support dots/colons in function name


  • Added "@i=0" command to disable "interruptions" while executing code.
  • Fixed nasty glitch that would cause code to sometimes appear to be failing by spamming errors.
  • Fixed paging of 20*k+1 output lines


  • Original version, support for almost all pico-8/lua syntax.
P#71429 2019-12-26 23:09 ( Edited 2020-03-25 21:00)

Wow, this is awesome. I'm surprised you didn't take any shortcuts for this.
I even decided to type in (manually) a tweetcart from @theonetruegarbo, with goto replaced by a while loop. And, aside from the framerate, it... Half-works? My only guess is that I made a typo.

P#71436 2019-12-27 15:06
:: dw817

This looks exceedingly complex but it clearly has one thing I really like. And that's a full calculator with parentheses ability.

This will definitely be one of my favorite carts as instrumental as it is. Gold star for you, @thisismypassword.

P#71439 2019-12-27 16:31 ( Edited 2019-12-27 16:31)

@xNoname - thanks for giving it a try!
I've tried inputting this cart myself and it seems to work like in the tweet, so perhaps indeed a typo has been made (any ideas on how to add copy/paste-type support in BBS, or something like it? Or even if I should?)

Looking at your animation - by the way - I've added a new "@i=0" command to the REPL cart to optionally disable the "Running, Press 'esc' to abort" text while a cart is executing. :)

P#71443 2019-12-27 22:43 ( Edited 2019-12-27 22:44)

Neat tool. Reminds me of a project I want to work on, implementing a minimal scripting language and multi-cart access and saving. The intent behind what I want to develop is an expansion to headchant's Pico Monsters. :3

P#71444 2019-12-28 00:10

Just updated it with goto and tailcalls too - they were easier to add to my "AST interpreter" than I thought they'd be.

EDIT: Aaaand I ended up adding pasting as well. (Plus something kinda sorta like pasting on the BBS, using - of course - the good old GPIO)

P#71459 2019-12-28 14:13 ( Edited 2019-12-28 15:20)
:: dw817

@thisismypassword, May I suggest you use CARTDATA() or CSTORE() to save complex commands so they do not need to be typed in manually again later ?

P#71463 2019-12-28 16:46


P#71485 2019-12-29 02:50

How do I get back to SPLORE?

P#71488 2019-12-29 07:06

@sugarflower - hmm - thinking about it, there's no reason I can't show the pause menu when there's nothing typed in and the user presses escape, so I updated the cart to do just that. Now you can go back to SPLORE! :)

P#71489 2019-12-29 10:43 ( Edited 2019-12-29 10:54)

@dw817 - I've added a "@c" table that allows programmatically accessing the code, so now you can store it wherever you wish. (Just don't chase the correct index too long)

EDIT: Also there now seems to be syntax highlighting for some reason.

P#71511 2019-12-29 23:47 ( Edited 2019-12-30 01:30)

great! :D

P#71756 2020-01-04 17:12

I happened to notice zep added copy/paste support in the BBS now, so I went ahead and made it work better with my cart. (copy's a bit janky (oh well), but paste works great!)

This means there's no more need for the gpio trick! (gpio trick retained for sentimental value)

P#72230 2020-01-25 05:40 ( Edited 2020-01-25 05:41)
:: dw817

How does it work ?

@c["print 23"]
@c[0]="print 23"
P#72892 2020-02-08 00:55

@dw817 - @c[1] gives you the previously typed line, for example. (@c[2] gives you the line typed before that, for another).

P#72896 2020-02-08 01:09
:: dw817

Is there a way to do with a string like I listed ? That's what would really be useful.

runcmd["print 23"]

results, 23

P#72897 2020-02-08 01:11

@dw817 - ah, you want a way to execute/evaluate strings at runtime? Sure, that's easy enough - I've added it as @exec and @eval.
E.g: @exec("print(23)")

P#72900 2020-02-08 02:35
:: dw817

It's works here:

@exec("print 23")

But not here:

@exec("print (1+2)*3")

Result is:
Attempt To Call A NIL Value

P#72914 2020-02-08 17:39

@dw817 - you need to put parentheses around the argument you pass to print, of course - same as you would write directly in the repl or in a .p8 file.

So @exec("print(23)") & @exec("print((1+2)3)")*

I'm not entirely sure what you're trying to do, by the way - why pass a literal string to @exec when you can just type the code directly in the repl? Or are you just trying it out?

P#72915 2020-02-08 17:59 ( Edited 2020-02-08 18:03)
:: dw817

Ah ... I see the problem. You can't use the PRINT command with parentheses, you must use ? command.

(1+2)*3 ... 9
@exec("(1+2)*3") ... 9
@exec"(1+2)*3" ... 9
@exec("?(1+2)*3") ... 9
@exec"?(1+2)*3" ... 9
@exec"print (1+2)*3" ... error
@exec("print (1+2)*3") ... error

Yep, I'm trying it out. Want to see if it's possible to calculate complex math entries as a string that is further converted to an @exec command.

You realize if your cart here runs all Pico-8 commands correctly that with @EXEC() you have made an interpreter more powerful than Pico-8 itself. Something definitely worth testing out ...

P#72923 2020-02-09 03:29 ( Edited 2020-02-09 03:49)

The problem is PRINT isn't a command - never was one in lua or pico-8. It's a function, so if you're going to call it - you must use the usual style of calling functions, which normally means using parentheses.

@exec"print((1+2)*3)" ... 9
@exec("print((1+2)*3)") ... 9

(Though yeah - as you found out, "?" is a command and can be used instead if you prefer)
Oh, and note you can also use @eval to return the computation's result instead of printing it:

print(@eval"(1+2)*3" + 10) ... 19
P#72929 2020-02-09 11:18 ( Edited 2020-02-09 11:19)
:: Felice


Not sure if you care about API dependence, but here's a non-PICO-8-specific way to test for empty args:

function empty_args(...)
  return tostr(...) == "[no value]"

(Obviously you don't need a whole function call, it's just there to illustrate usage.)

Edit: Actually... this isn't that great. A string arg of "[no value]" would result in apparent emptiness. Hrm.

It's too bad type() doesn't know about "no value".

Never mind.

P#73235 2020-02-19 17:27 ( Edited 2020-02-19 17:34)

@Felice - additionally, while that works on 0.1.12c - in 0.1.12d (on the BBS), print(tostr()) gives "[nil]" instead for some reason (*).

Yeah, I'm not too happy about the type(btn(...)) thing, but it's the best I (and several people on discord) could come up with.
Definitely interested in hearing other suggestions, though - thanks for them.

(*) _tostr still behaves like in 0.1.12c, interestingly, but that's an undocumented 0.1.12d-only function whose presence also seems like a pico-8 bug (setting it to nil breaks pico-8, and I heard it broke at least one person's existing cart)

P#73269 2020-02-20 02:35 ( Edited 2020-02-20 02:38)
:: Felice


I did think of one small thing, though I'm not sure it's really an improvement:

if isbool[btn(...)] then
  (there are args)
P#73332 2020-02-22 04:02

@Felice - it's the btn that's the questionable part, not the type - so I don't see an improvement either.

By the way, if it wasn't for it not working in 0.1.12d, then your previous suggestion could be used reliably as follows:

function empty_args(...)
    return ... == nil and tostr(...) == "[no value]"

(The "... == nil" operates on just the first element of the ...)

But alas, undocumented behavior never changes the way you expect...

P#73347 2020-02-22 14:57 ( Edited 2020-02-22 15:05)
:: Felice

Yeah, I know. I just liked the idea of eliminating the type() function call and string compare, but that's my cycle-counting brain at work, which often leads me astray in PICO-8, since all kinda of things that should be slow are fast, and sometimes vice-versa. Table lookups are super fast, but I wouldn't be surprised if a string compare is too and/or type() is free.

P#73386 2020-02-23 17:54

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2020-03-30 05:25 | 0.646s | 4194k | Q:124