This post was featured on the Scala website. It is advised to jump there first and then sneak back here … eventually.
A couple weeks back I came across a post on creating the simplest
possible BASIC DSL written in Scala by Szymon Jachim. The
implementation itself was dead simple to understand, but I suspected it
was due to the fact that it only provided GOTO
and
PRINT
. The title of the post was ease of making DSLs in
Scala - nobody cares, which was unfortunate because I think that
many people care, including myself, so I took it upon myself to extend
the DSL to be a pseudo-implementation of Tiny
BASIC. In a nutshell, I found that it was simple to create an
internal DSL providing a simple dialect of BASIC using Scala. There were
some sticking points, which I will touch on later, but overall it was a
joy. The code is
available for public consumption, so feel free to try it, criticize
it, and/or improve it. I find it retains its simplicity even after
extending the original to provide additional forms and functions.
Here is a simple Lunar Lander game written in Baysick.
[sourcecode lang=“bas” gist=“122994”] object Lunar extends Baysick { def main(args:Array[String]) = { 10 PRINT “Welcome to Baysick Lunar Lander v0.9” 20 LET (’dist := 100) 30 LET (’v := 1) 40 LET (’fuel := 1000) 50 LET (’mass := 1000)
60 PRINT "You are drifting towards the moon."
70 PRINT "You must decide how much fuel to burn."
80 PRINT "To accelerate enter a positive number"
90 PRINT "To decelerate a negative"
100 PRINT "Distance " % 'dist % "km, " % "Velocity " % 'v % "km/s, " % "Fuel " % 'fuel
110 INPUT 'burn
120 IF ABS('burn) <= 'fuel THEN 150
130 PRINT "You don't have that much fuel"
140 GOTO 100
150 LET ('v := 'v + 'burn * 10 / ('fuel + 'mass))
160 LET ('fuel := 'fuel - ABS('burn))
170 LET ('dist := 'dist - 'v)
180 IF 'dist > 0 THEN 100
190 PRINT "You have hit the surface"
200 IF 'v < 3 THEN 240
210 PRINT "Hit surface too fast (" % 'v % ")km/s"
220 PRINT "You Crashed!"
230 GOTO 250
240 PRINT "Well done"
250 END
RUN
} } [/sourcecode]
:=
PRINT
form is
%
ABS
SQRT
+
-
*
and
/
As has been mentioned by innumerable programmers advocating (and deriding) DSLs, you are often constrained by the host language in the grammar, error reporting, and hosting capabilities of your DSL. While Scala allows you to support bizarre grammars without significantly increasing the complexity, it does not necessarily facilitate a simple way to provide solid error reporting and hosting. This is not necessarily a limitation of Scala per se, but instead for general purpose languages. In order to effectively build a wide range of DSLs divorced from their underlying host we need a language that is especially geared toward building DSLs. The two important language features that Scala provides that makes it especially conducive for DSLs are operator notation and implicits. Usually, a language is considered DSL-friendly if it allows you to omit the dot on a method call, but a really powerful DSL metalanguage would have to go much much further than that.
For some strange reason I could not coax Scala into allowing my
LET
forms to be parenthesis free. I assume that it is an
error on my part, but I was never able to solve it before my artificial
deadline expired.
GOSUB
and
RETURN
So there you have it – Baysick: A Scala DSL Implementing BASIC.
-m