Thursday, October 8, 2009

Introduction to Yabasic 3

I indicated in my last post that I would provide some background to Yabasic 3, which I am currently developing, and discuss some of the decisions I have made so far in relation to Yabasic development. I will not delve too far into the history of Yabasic, although that topic may be the subject of a later post.

Marc-Oliver Ihm authored Yabasic and maintained it up to version 2.763. Sadly, in 2007 he came to the conclusion that he would not be able to continue developing Yabasic: "I am really not comfortable with this conclusion, but I have to admit that probably I will not develop Yabasic any further within the foreseeable future." However, Yabasic had a functional, clean code-base and a strong community associated with it.

As an avid Yabasic programmer, I wanted to keep Yabasic "alive" and operational. I wondered whether or not to take on the role of developing Yabasic, but I was reluctant to commit myself at a time when my knowledge of the C programming language (in which Yabasic is written) was fairly minimal. Eventually, after some experimentation, I finally decided to take on the responsibility of developing Yabasic with Pedro Sá. As you can see, I was optimistic about how long it might take to produce Yabasic 3: "...I am working on the syntax parser, and I have not yet started on the various actions for the commands and functions, so the initial release date will be some time from now (hopefully no longer than a few months)." And that was in May 2008.

Originally, I intended to write Yabasic 3 entirely from scratch. I estimate that I attempted a complete re-write about six times; at minimum, each implementation supported basic commands ("print", at the very least). But I considered them all unsatisfactory, for one or more reasons.

Finally, I decided to use the existing code-base of Yabasic. I was determined to pare it down to the bare essentials, correcting existing bugs, implementing clean memory management (which I do not expect will be completed in time for the beta release, but it is certainly one of my goals for the future of Yabasic), improving consistency, and in general improving the language's aesthetics in order to prepare it for the changes I intended to make for Yabasic 3. Much of this process has already been completed, and my major focus has now shifted to implementing new features.

So, what are these "new features"? Well, I've already implemented block comments, which are incredibly convenient when a programmer wishes to comment out a whole block of code. Now you can write the following:

/* This is a block
comment that
extends over
multiple lines. */
print "Hello, world!"

But the real meat of Yabasic 3, I hope, will be modules, libraries, and "user-defined types". At the risk of being too verbose, I would like to discuss each of these features in turn, explaining their benefits and implementation. Because "user-defined types" merit a topic of their own, I will cover them in my next post.

Modules

Previous versions of Yabasic implemented rudimentary graphics and some terminal manipulation. Users could, for example, open a window and draw lines, circles, and triangles or print text at a particular location and with a particular colour to the terminal. However, this functionality was built into the core of Yabasic itself, and a number of issues arose as a result of this design.

There was the issue of compatibility of features across different computer systems. For example, while Marc-Oliver Ihm admirably made graphics handling very similar on both the GNU/Linux and Windows operating systems, there were still a few inconsistencies and incompatibilities that were noticeable in some "graphical" Yabasic programs. Once, I developed a graphical text editor in Yabasic (YATE, or Yet Another Text Editor), and had to spend a significant amount of time addressing compatibility concerns. Clearly, this is not a desirable burden to impose on any casual user.

One way of addressing the issue is to separate Yabasic into a number of modules, with a "core" at the "centre". The Yabasic core is responsible for performing general, system-independent tasks (such as parsing, execution, variable handling, and expression evaluation), while modules are either system-dependent (for instance, graphics or terminal handling) or responsible for performing a specialised task (complex number handling, for example). In general, Yabasic programs written on any one platform should function on all platforms without requiring changes to be made in order to operate correctly or consistently. This implies that modules for performing a particular task should interface consistently with the Yabasic core and Yabasic programs.

For aesthetic reasons there should be a clear division between system-dependent or specialised modules and the, ideally, system-independent Yabasic core. This does not mean, however, that neatness and clarity are more important in the Yabasic core than in Yabasic modules: indeed, this is not the case. Clarity and aesthetic design are important in any program. But a modular design, which divides a program into components with specific purposes, is easier to debug and usually more fail-safe.

Modules should not get in the way of a programmer: they are, supposedly, tools for getting jobs done in a consistent, clear way, not obstructions. So I intend to make them blend pleasantly into Yabasic. It is important to note that modules will be compiled into Yabasic and will, therefore, be part of the compiled Yabasic executable. It is, however, important to distinguish modules from the Yabasic core. A standard for modules may need to be written, but I will look for more community input before resolving to pursue this course of action.

How might modules look? Well, take the following old code which opens a window and displays a red circle in the middle of it:

open window 100, 100
color 255, 0, 0
circle 50, 50, 20

This might (tentatively, very tentatively) be accomplished like this in Yabasic 3:

graphics.set_window (graphics.new_window (100, 100))
graphics.color (255, 0, 0)
graphics.circle (50, 50, 20)
I will not be writing many modules before the Yabasic 3 beta release. I might write a basic terminal-handling module for GNU/Linux, but developing a full, consistent set of modules will take more than a month or two and will require some community effort.

Libraries

In Yabasic, libraries usually are Yabasic programs that contain sets of functions. Users can import these libraries and call the functions defined in them. Thus, libraries can be shared between programs, and much difficult and duplicated effort can be avoided.

Libraries have already existed in older versions of Yabasic. Yabasic 3, however, simplifies the implementation of libraries significantly while embracing and extending the general concept, and to this end library handling has been completely re-written.

As I propose to implement libraries, the "export" statement would disappear, and users would reference imported functions by their name prefixed with the name of the library. For example:

import "number"      // imports library

for number = 1 to 1000
if number.prime (number) then // "number.prime ()"
print number
endif
next

The library file number.yab would contain:

sub prime (number)
local check
for check = 2 to sqrt (number)
if number mod check = 0 then
return false
endif
next
return true
end sub

This is, of course, a conceptual example, and I would like to hear your feedback.

4 comments:

  1. So, I understand that "modules" are system libraries and "libraries" are user libraries? Fine with me, but (late on...) the documentation should make the distinction clear.

    As of now, a user program would have access to *all* procedures of the libraries? I don't think that's a good idea; it would allow (wanted or unwanted) manipulation of the library from the calling program.

    IMHO it would be better to have a clearly-defined interface for the library, by explicitly defining subs in the library as public or private or such.

    Other than that, it looks good to me!

    syzygy

    ReplyDelete
  2. Are the "modules" accessible without being included? Or will there a line like "use graphics" etc. ?
    By the way, if you need the Logo in different sizes just PM me.

    ReplyDelete
  3. @Cybermonkey342: Modules will be accessible without being included, or at least that is my plan.

    @Syzygy: A user-defined function in an imported library would not be "modifiable" (so long as it used local variables) by the importing program. But, for aesthetic and practical reasons, it could very well be desirable to implement "public" and "private" functions (equivalent to what are currently known in Yabasic as exported and non-exported functions respectively).

    ReplyDelete
  4. This is great news!

    I am the programmer of Yabasic for the BeOS and Haiku operating systems (yab, see a screenshot of the IDE (written in yab itself of course ;)) here: http://tinyurl.com/yhybnpq). While I added a lot of system dependend new commands, I never really dared to go into the interpreter details to add features like yours.

    However, I still have a lot of experience with the Yabasic code and I am happy if I can help you in any way (coding, testing, bug fixing...) to get Yabasic 3 going. You can reach me at jan [at] be-logos.org.

    ReplyDelete

Note: Only a member of this blog may post a comment.