Showing posts with label programming languages. Show all posts
Showing posts with label programming languages. Show all posts

Sunday, October 15, 2017

Today a BASIC interpreter, tomorrow a BASIC compiler

A side project is building a compiler for the BASIC programming language. (Why? Because it's fun!)

A previous fun project was a BASIC interpreter. (Two interpreters, actually.) For them, I used Ruby. The projects were a way for me to learn the Ruby language, and I succeeded.

For the compiler, I want a language different from Ruby. I find Ruby is an excellent language for high-level concepts; I don't know that it can read and write individual bytes and I don't know how it can convert integers and real numbers to bytes. (It probably can, perhaps with the assistance of a library.)

If the language will not be Ruby, what will it be? First, a few requirements:

It has to run under Linux. I use Linux for my development work and I don't see that changing.

Specifically, it has to run on my workstation, a venerable Apple PowerBook G4 which runs Ubuntu Server 16.04 LTS. It has to run in text mode (which just about every language does).

My plan is to create a compiler that generates bytecode, or p-code. I'm not going to target a real processor like the Intel 386 or ARM chip; I will write bytecode and use a runtime system to execute them, much like Java and C#.

Some possible languages and thoughts:

C++: Available on Linux. But my day job sees me working with lots of C++ code, and I want something different.

C: Not C++, but not quite different enough. And I am comfortable in C; another language is another opportunity to learn.

C#: Available on Linux, but I'm not sure that the .NET environment is available for the PowerPC architecture. And I would rather have a compiler language, not a bytecode language. (My own bytecodes will be enough, thank you!)

VB.NET: Exact same problems as C#.

Java: Available but uses a bytecode arrangement as C#.

Python: If not Ruby, why not Python? I'm using it for a different project, so not for this one. And it is not a true compiled language.

Perl: Umm... no.

Go: Possible. There is some support for PowerPC, and it may run on my PowerBook.

Swift: Compiled. May be available for the PowerPC. My preference, knowing nothing about either language, is for Go rather than Swift.

Pascal: Compiled. Probably available for PowerPC. A language I know. (Or knew, a long time ago.)

Forth: Interpreted and not compiled. Probably available for Powerbook. The Forth I learned was an operating system and took over the computer. Can modern Forth read and write files?

Objective C or Objective C++: I don't see a future for either of these languages. Learning them now would be... unprofitable.

Fortran: Really no.

Ada: More "no" than Fortran.

* * * * *

Update:

There is a Go compiler for Linux, and it does run on the PowerPC processor. I've installed it and written "Hello, world!".

There is a Pascal compiler for Linux, and it does run on the PowerPC. Almost. The "Free Pascal" package doesn't install on Ubuntu 16.04, and I'm not the only one to experience problems. It also appears that Free Pascal is the only Pascal compiler for Linux. Therefore, Pascal is out.

With no option for Pascal, I'm choosing Go as the language. (In full disclosure, I must admit that I tried very little to resolve the problem with Free Pascal. Maybe I wanted to use Go all along, and the install failure was enough to push me to Go.)

Sunday, June 28, 2015

Building a BASIC interpreter in Ruby

I've been working on a side project: Build a BASIC interpreter in Ruby. The purpose is to help me learn the Ruby language, and to that end the project has worked well.

Learning a new programming language can be difficult. It's easy enough to write a simple "Hello, world!" program, but that simply confirms that the compiler (or interpreter) is installed correctly. What does one do next?

I picked the BASIC interpreter as a task with some complexity, but not too much. The BASIC language gives me a challenge but not one that is insurmountable. Also, I have an early text on programming in BASIC that provides example programs with their expected outputs.

As a bonus, programming a BASIC interpreter is a stroll down memory lane. BASIC was the first programming language that I learned. It is an old friend, one I have not seen in quite some time.

So as a project, the BASIC interpreter is challenging, supported, and fun.

I spell BASIC in all capitals because of the variant I am implementing. The BASIC language had a number of variants over time, from the early Dartmouth implementation in the 1960s to the DEC versions of the 1970s and 1980s, culminating in Visual Basic 6 from Microsoft. (Or perhaps VB.NET, but that seems less BASIC than any of the variants.)

My project is to implement an early version, one that is close to Dartmouth BASIC. It has a simplicity about it, yet it also has its intricacies. Dartmouth BASIC allows one to specify user-defined functions, but only on one line and only with a very limited set of names ('FNA' through 'FNZ'). It supports some elements of structured programming but still allows GOTO statements, and one can 'GOTO' from the inside of a loop to the outside, do some work, and 'GOTO' back into the loop. (One can also 'GOTO' out of a loop and not return into the loop.)

Early version or late, my experience has been a good one. I have been forced to learn the Ruby language. While I am not an expert, I am at least comfortable with the major constructs and classes of the language. And that was the point.

Wednesday, February 22, 2012

Better than FORTRAN

Sniffles and sneezes kept me home. I spent most of the day resting. Yet I had a little time to build an interpreter for the original BASIC language, and I learned a lot.

Writing an interpreter (or a compiler) forces one to learn the language. All of the language, not just the convenient bits. My exercise forced me to learn about BASIC and think like the original designers of the language.

I looked at the original BASIC, also called "Dartmouth BASIC". It is a simpler version of the Visual Basic we know today. There is a limited command set and variable names are much shorter.

I implemented a fraction of Dartmouth BASIC. I'm calling my implementation "BASIC-1965", in reference to the year in which I think it would have been initially implemented. It is Dartmouth BASIC without the matrix operations and constraints on the use of expressions. In Dartmouth BASIC, expressions may appear in LET, PRINT, FOR, and IF statements; in my version, expressions are restricted to the LET command. (That may change in the near future.)

Another change is the position of DATA statements. In the original BASIC, DATA statements may appear anywhere. In my "BASIC-1965", DATA statements are truly interpreted and must appear prior to the corresponding READ statements. (The fact that DATA statements could appear at the bottom of the program always bothered me.)

My implementation is in Ruby, which performs a lot of the "heavy lifting". Ruby has data containers and regular expressions, both of which made the task easy.

I can see how BASIC was better than FORTRAN: no FORMAT statements, no worries about integer or floating point variables, and interaction with the computer. It *was* a significant increase in usability.

Monday, November 28, 2011

The loss of WYSIWYG in programming languages

As programming languages have evolved, we have moved from static languages to dynamic languages. These new languages offer new capabilities, but at a price. That price includes performance (perhaps not a great cost, given advances in hardware) but also the ease of understanding code.

Early programming languages of FORTRAN and COBOL were quite easy to understand. They did not allow for recursion (the early versions, at least), and offered static, up-front at compile/link time memory layout. You knew (or the linker knew) the location of every variable and every subroutine when the program was built. You knew the destination of every jump and the meaning of every statement. (Yes, COBOL had the 'ALTER' keyword, and FORTRAN had the "assigned goto", but they were proscribed in civilized shops.)

Of all languages, BASIC (prior to Visual Basic) was probably the most easily understood. It had a specific set of keywords, no pre-processor, strongly-typed variables, and no dynamic aspects.

The C language was one of the last languages in which "what you saw was what you got". A colleague referred to his "cortex compiler" when discussing the clarity of C code. One could look at source code and know the actions performed by the computer. (I am ignoring the effects of the pre-processor here. Poorly-design -- or even well-designed -- #define macros can change the normal meaning of C code and stymie all but the most careful analysis.)

Things changed with object-oriented languages. In object-oriented languages, one can look at the source code, but the action taken by the computer is not always obvious. To understand polymorphic code one must understand the inheritance hierarchy. To understand operators one must understand the class and its ancestors. Multiple inheritance (multiple implementation inheritance, as in C++) is rife with ambiguity.

(I'm ignoring LISP in this sequence. LISP, which dates back to the days of FORTRAN and COBOL, offered the same flexibility and dynamic constructs that it does today. But most programmers ignored it then, too.)

Java kept object-oriented programming but mercifully implemented multiple interface inheritance (and not multiple implementation inheritance) and eliminated the pre-processor and operator overloading, all which made it more obvious than C++.

Dynamic languages are now in the ascendant. Perl allows for lots of un-obvious constructs (some will snarkily comment that the entire language is un-obvious). Ruby lets one define or modify classes -- even the "standard" classes -- during run-time. (The shades of COBOL's 'ALTER' haunt us still.)

The trend may be towards dynamic languages, but not everything is moving in that direction. The up-and-coming functional programming languages (Haskell, Erlang) take a different approach and enforce strict definitions of functions and their results. Their syntax and organization is different from object-oriented programs, and can be difficult for those trained in O-O programming constructs. Despite the differences, I expect that these languages will, in the long run, be considered the more "obvious".

And we may, once again, have programs that are obviously understood, capable of being processed by our "cortex compilers".

Sunday, February 6, 2011

Housekeeping

In programming, one trend is the removal of "housekeeping" tasks.

The transition from assembly language to high-level languages saw the elimination of register and stack frame management. This was a big change, but not the only change in housekeeping tasks. FORTRAN and COBOL eliminated a lot of housekeeping for files.

The C programming language (and the UNIX operating system) made file operations even easier, allowing the command shell to handle files for the "stdin" and "stdout" channels.

The introduction of Java saw the elimination of memory management. Prior languages (C, C++, and Pascal) forced the programmer to allocate, track, and release memory. (The early Pascal had a very clumsy "mark and release" model.) Every language introduced after Java has included memory management.

Eliminating housekeeping tasks is usually a good thing. There are some specialized applications that require the complete control of memory allocation, file operations, and even register allocation. But these applications are few. For the mainstream, less housekeeping is better. Housekeeping distracts us from the problem at hand.

Once eliminated, we don't re-introduce housekeeping tasks. We're not going to use (with any degree of popularity) a language that requires us to track and free memory, or jump through hoops to perform file operations, or to manually specify register usage. Future languages will keep the automatic transmissions that we have built.

Which means that the hard-won skills for housekeeping in languages -- even modern languages -- has limited usefulness. Memory allocation skills in C++ were not needed in Java or C#. (It may be useful to know them, to understand the actions occurring "under the hood", but it is not necessary.)

Housekeeping skills have limited life. Skills of longer duration are of lasting value. These include algorithm design, simplification of code, understanding business requirements, communicating with team members (technical, artistic, and management members), project management, cost estimating, and problem diagnosis.

So... what kind of skills do you have?