Rewriting Yabasic from scratch in C++

Recently, a number of things have been frustrating me about the way Yabasic currently works.

  1. Yabasic is too slow. For example, Perl is often significantly faster than Yabasic, despite having a much larger and more complex implementation, and languages like Lua outperform Yabasic in almost every situation. I’m not saying that Yabasic needs to be faster than every other programming language implementation out there (although that would be nice!), but in light of its simplicity and small size it should certainly be more efficient than it currently is. So the virtual machine needs to be simplified and improved. Using a more flexible language than C (the language in which Yabasic is currently written) would facilitate optimisations and simpler, more powerful internal workings.
  2. Parts of the language (symbol handling in particular) are a complete mess at present. That is simply the consequence of many changes and extensions being made throughout Yabasic’s history. There are parts of “symbol.c” which I still don’t fully understand, even after working slowly on Yabasic for over a year.
  3. Building on point 2, I feel that it would be almost impossible to implement efficient, flexible associative arrays (and, hence, proper user-defined types and structures) in Yabasic as the language currently stands.
  4. Yabasic lacks good garbage collection at present. Memory should be freed when it is no longer required, and—for aesthetic purposes, and practical reasons on some systems—all allocated space should ideally have been freed by the time the program exits (including when it exits due to an error). C++ facilitates this, I understand, with “destructors” and a cleaner memory management system in general. In C, all garbage collection must be done manually—something that is hard to do well and frequently risky and bug-prone.
  5. I’m sure there have been other things that I’ve found quite problematic in the current C implementation, but I can’t recall them at present.

Therefore, Pedro and I have decided to rewrite Yabasic from scratch in C++. The overall syntax for, and interface to, Yabasic will not change much, if at all, in this process. And there will be other benefits to (hopefully) correcting the problems mentioned above when we switch to C++ as the language for Yabasic’s implementation: in particular, better organisation of Yabasic’s source code, which will allow us to find and eliminate bugs more quickly.

One of our main concerns is portability: we really want Yabasic to run on as many systems (even really obscure ones) as possible, while having a minimum of system-dependent code. This may mean that, for example, we need to write the “lexer” (scanner) and parser by hand; but, if we need to do this to make Yabasic compile and function properly on all kinds of systems, we will.

I realise you folks may find this setback a little annoying or frustrating, and I quite understand your feelings. I never expected development of Yabasic 3 to take this long myself! But I hope you can see that a change to C++ is the best road to go down now; and, if you don’t, we would like to hear from you (see below). It is my hope that, with both Pedro and I working on this, we will be able to get more work done in a shorter space of time than before.

If you really have an objection to this change, or if you support it, or if you are able to help in any way, then we would like to hear from you! Well, basically, we’d love to hear from you regardless of what you think. Pedro and I plan to run a real-time discussion about Yabasic on the #basicprogramming.org channel on Freenode (yes, there actually is an IRC channel for Basicprogramming.org!) sometime in the near future, and people will be free to ask questions, make suggestions, and discuss implementation details then.

Until then, feel free to comment on this blog or on the forums!

Associative arrays—what do you think?

“Associative arrays” are just like normal arrays, except that they can be indexed by any type of value—a character string, for example—not just an integer. For example:

person ("Tom").place$ = "Australia"   // indexed by a string: "Tom"
person (1).place$ = "Australia"   // indexed by a number: 1

At the moment, I’m considering the possibility of re-writing Yabasic’s entire variable-handling system to improve speed and flexibility, particularly in order to facilitate the proper implementation of structures and user-defined types. If I went ahead with this, I’d probably be able to introduce associative arrays.

So what do you think? And if you’d like associative arrays to be implemented, what syntax would you prefer?

Yabasic 2.9.15

Hello all! Yabasic 2.9.15 is available for you to download and experiment with if you feel compelled to do so.

What’s new in this release? Not as much as I originally intended:

  • A couple of bugs (the recursion bug that Derek reported, and another comparatively minor issue) have been fixed.
  • The commands data, read, and restore have been (re-)implemented, although their syntax is different to what it was in Yabasic 2.763 and earlier versions:
    DATA collection
       data
    END DATA
    
    READ variable FROM collection
    
    RESTORE collection
    

    Here’s an example:

    // Data example by Thomas Larsen (2010).
    //
    // Output should be:
    //    1 2 3 4 5 6 7 8 9 10
    
    restore odd, even   // not really necessary, as data is used once only
    
    for number = 1 to 5
       read odd from odd   // must specify data read point
       read even from even   // multiple data read points are allowed
       print odd, even, "";
    next
    print
    
    data odd
       1, 3, 5, 7, 9
    end data
    
    data even
       2, 4, 6, 8, 10
    end data

    I want to stress that this is just a preliminary implementation of data and the other commands associated with it. If people like it, we’ll keep it; but I’m open to suggestions and comments.

Enjoy!

Program “snapshots” are your friends

Recently, Derek reported a bug in Yabasic’s handling of subroutine recursion. I was rather worried by it, since such bugs are often extremely arcane and very difficult to locate.

Fortunately, I archive “snapshots” of Yabasic whenever I make significant changes to the code (yes, I should start using revision control software). As a consequence, when someone reports a bug that didn’t appear in Yabasic 2.763, pinning it down is usually just a simple matter of running through these archived snapshots until I find the version where the bug was introduced. Then I can compare the code between the working and the buggy version, and see what changes might have brought the bug into existence.

I must say I’m very glad that I do this; if I hadn’t, I estimate that I would have had to spend at least a day’s worth of work trying to track down the subroutine recursion bug that Derek reported. As it was, it only took me roughly half an hour.

The moral of this brief anecdote is this: if you’re rewriting a complex piece of software, continually archive versions of it every time you make major changes. That way, you’ll be able to find bugs that you introduce more quickly and more effectively.

Edit: Corrected embarrassing grammatical mistake.

Yabasic 2.9.14

I finally managed to fix the bug that Derek reported a little while ago. To celebrate Because it’s rather overdue, I’d like to release Yabasic 2.9.14. Here’s a concise list of what’s new in this version.

  • Fixed a bug caused by stack entries of type stFREE not being popped by structure-related code. For example,
    test ()
    
    sub test ()
       struct items (1)
          item
       end struct
    
       return
    end sub

    is now parsed and executed properly.

  • Disallowed empty structures. For example,
    struct items (1)
    end struct

    will cause Yabasic to report an error and exit immediately.

  • Added a signal handler for the signals SIGABRT (abort), SIGFPE (floating point exception), SIGHUP (hang-up), SIGINT (interrupt), SIGQUIT (quit), SIGSEGV (segmentation fault), and SIGTERM (terminate).
  • Artifacts from switch are now cleared properly when goto is used inside a switch construct. (Other loops and conditional statements are fine, as they do not have “artifacts”.)
  • Most restrictions regarding goto, gosub, and label have been lifted. The only restriction that is still in effect pertains to label, which cannot be used inside an if statement or a switch construct.

If you can, please download Yabasic 2.9.14 and test it. Have fun!

Still chasing after the elusive bug

A little while ago, Derek reported a strange bug. Code like the following, despite being in theory entirely palatable to the interpreter, causes Yabasic to spit out an error and exit immediately:

test ()

sub test ()
   struct items (1)
      item
   end struct
end sub

The exact error message is yabasic: program.yab:7: RETURN from a subroutine without CALL.

I suspect that somehow the “byte-code” generated by the structure is popping too many, or perhaps too few, elements from Yabasic’s internal stack. However, the bug hunt continues. Let’s hope I track the problem down this weekend.

Yabasic’s website has a new look!

Hello there! As you may already have observed, Yabasic’s website has changed significantly. Previously, the site consisted of hand-edited HTML files; now, it uses the WordPress blogging platform for content management.

There are a number of positive outcomes as a result of this switch. The site looks much more aesthetic, even if I do say myself; it’s easier to navigate, and more centralised and organised. The blog is now integrated properly with the rest of the site. And people with Editor access on the blog (currently Pedro, Elmar, and I) will be able to edit Yabasic’s website without having to go through the painful process of logging in to the FTP server and downloading, changing, and uploading HTML files.

We’d love to hear your feedback and suggestions regarding the new website. Feel free to contact us!

New development section on the website

I’ve finally gotten around to creating a “developers’ patch” on Yabasic’s website. You can find it here: yabasic.basicprogramming.org/development.

At the moment, the to-do list for Yabasic 3 is the only thing that’s up there. If you’ve got suggestions or ideas, please let me know.

Mere words… yet how inescapable, how terrifying they were…

Hi all,

Just to make sure you keep following this blog: I haven’t been idle in the meantime, trying to keep up with Thomas and Pedro, and have fleshed out a little more of the Yabasic Vademecum. Most significantly, I’ve begun to write the reference section (which is going to be a tough piece of work…), and also included a few of the new V3 features as they emerge from the various betas.

You can download it here, it’s about 850k on 70 pages, and of course still very much a work-in-progress.

Yabasic Vademecum

Enjoy!

Yabasic 2.9.13

Yabasic 2.9.13 is out.

The statement compile, and the functions execute () and execute$ (), have been re-implemented. I tested them but probably didn’t manage to squeeze out every single little bug; reports are welcome.

_” is now a line continuation character like “\“.

A message is no longer displayed when Yabasic reads from standard input. It is no longer possible to make Yabasic stop parsing and start running code by entering two blank lines while Yabasic is reading from standard input. You can use an EOF sequence instead, like Ctrl-D (on Unix-like systems at least), or provide a file as input. This is consistent with the behaviour of most other command-line programming language interpreters.

Other changes are essentially cosmetic.

I have ideas about module error-handling, entry and exit functions, and installation. Because this weekend is a long one for me, I plan to work on these things over the next couple of days and then get Pedro to make sure I haven’t broken anything too badly. :-)