Wednesday, July 20, 2016

A dictionary lookup mini application

Here is a simple demo application for our keyed lookup library in development.  It opens a window with keys on the left, and a text editor on the right.  You can add new keys and edit the values for those keys by changing text on the right.  The values are saved to the file dictionary.dat.

We will enhance this code for a couple more blog entries before we move on to some other project.  :-)

Enjoy!

    nomainwin
    WindowWidth = 555
    WindowHeight = 438

    dim keys$(1000)
    dim info$(10, 10)
    global dictionary$, keyCount, lastKey$
    call readDictionary


    texteditor #main.value, 175, 7, 360, 365
    listbox #main.keys, keys$(), [keySelected], 5, 7, 160, 365

    menu #main, "Key", "New", [newKey], "Delete", [deleteKey]
    menu #main, "Edit"

    open "Dictionary inspector" for window as #main
    #main "trapclose [quit]"
    #main.keys "singleclickselect"
    #main.value "!autoresize";
    call loadKeys


[main.inputLoop]   'wait here for input event
    wait


[newKey]   'ask the user for a new key
    call saveValue
    prompt "Enter a name for the key."; newKey$
    if newKey$ <> "" then
        call setValueByName newKey$, ""
        call loadKeys
        #main.keys "select "; newKey$
        #main.value "!cls";
        #main.value "!setfocus";
        call writeDictionary
        lastKey$ = newKey$
    end if
    wait


[deleteKey]  'left for later
    notice "Delete not implemented yet."
    wait


[keySelected] 'a key in the list was selected
    call saveValue
    #main.keys "selection? selectedKey$"
    selectedValue$ = getValue$(selectedKey$)
    #main.value "!contents selectedValue$";
    lastKey$ = selectedKey$
    wait


[quit] 'End the program
    call saveValue
    close #main
    end


sub saveValue   'if the value is changed, save it
    if lastKey$ <> "" then
        #main.value "!modified? modified$";
        if modified$ = "true" then
            #main.value "!contents? saveThisValue$";
            call setValueByName lastKey$, saveThisValue$
            call collectGarbage
            call writeDictionary
        end if
    end if
end sub


function getKeys$(delimiter$)
  global keyCount
  pointer = 1
  while pointer > 0
    'get the next key
    pointer = instr(dictionary$, "~key~", pointer)
    if pointer then
      keyPointer = pointer + 5
      pointer = instr(dictionary$, "~value~", pointer)
      key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)
      if instr(keyList$, "~key~" + key$) = 0 then
        getKeys$ = getKeys$ + key$ + delimiter$
        keyList$ = keyList$ + "~key~" + key$
        keyCount = keyCount + 1
      end if
    end if
  wend
end function


sub writeDictionary
  open "dictionary.dat" for output as #writeDict
    print #writeDict, dictionary$
  close #writeDict
end sub


sub readDictionary
  if fileExists(DefaultDir$, "dictionary.dat") then
      open "dictionary.dat" for input as #readDict
    length = lof(#readDict)
    dictionary$ = input$(#readDict, length)
    close #readDict
  end if
end sub


sub collectGarbage
  pointer = 1
  while pointer > 0
    'get the next key
    pointer = instr(dictionary$, "~key~", pointer)
    if pointer then
      keyPointer = pointer + 5
      pointer = instr(dictionary$, "~value~", pointer)
      key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)
      if instr(keyList$, key$) = 0 then
        value$ = getValue$(key$)
        newDictionary$ = "~key~" + key$ + "~value~" + value$ + newDictionary$
        keyList$ = keyList$ + key$
      end if
    end if
  wend
  dictionary$ = newDictionary$
end sub


sub setValueByName key$, value$
  dictionary$ = "~key~"+key$+"~value~"+value$+dictionary$
end sub


function getValue$(key$)
  getValue$ = chr$(0)
  keyPosition = instr(dictionary$, "~key~"+key$)
  if keyPosition > 0 then
    keyPosition = keyPosition + 5  'skip over key tag
    valuePosition = instr(dictionary$, "~value~",  keyPosition)
    if valuePosition > 0 then
      valuePosition = valuePosition + 7   'skip over value tag
      endPosition = instr(dictionary$, "~key~", valuePosition)
      if endPosition > 0 then
        getValue$ = mid$(dictionary$, valuePosition, endPosition - valuePosition)
      else
        getValue$ = mid$(dictionary$, valuePosition)
      end if
    end if
  end if
end function


sub loadKeys
    keyList$ = getKeys$("~")
    redim keys$(keyCount)
    for item = 1 to keyCount
      keys$(item-1) = word$(keyList$, item, "~")
    next item
    #main.keys "reload"
end sub


function fileExists(path$, filename$) ' Does file exist?
    files path$, filename$, info$(
    fileExists = val(info$(0, 0)) > 0
end function


Friday, July 15, 2016

Dictionary lookup - getting the keys

When you have an array you can simply loop through the contents to examine what's there, but when you have a dictionary you need to have the list of keys so that you can look up each value in the dictionary.  For that, we need a getKeys$() function.  The following function returns a single string with the keys from our global dictionary$ variable, each separated by a delimiter that we can specify.

function getKeys$(delimiter$)
  pointer = 1
  while pointer > 0
    'get the next key
    pointer = instr(dictionary$, "~key~", pointer)
    if pointer then
      keyPointer = pointer + 5
      pointer = instr(dictionary$, "~value~", pointer)
      key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)
      if instr(keyList$, "~key~" + key$) = 0 then
        getKeys$ = getKeys$ + key$ + delimiter$
        keyList$ = keyList$ + "~key~" + key$
      end if
    end if
  wend
end function

Once have this string we can tease out each key.  Here is an quick example that shows how to do this.  The variable allKeys$ will hold all the keys, each separated by "~".  Then we use the word$() function to get each key.

global dictionary$

call setValueByName "first", "Tom"
call setValueByName "last", "Thumb"
call setValueByName "phone", "555-555-1234"

allKeys$ = getKeys$("~")
print allKeys$

key = 1
while word$(allKeys$, key, "~") <> ""
  key$ = word$(allKeys$, key, "~")
  print "Key number "; key; " is "; key$
  print "    value = "; getValue$(key$)
  key = key + 1
wend


Here is what the resulting output looks.

phone~last~first~
Key number 1 is phone
    value = 555-555-1234
Key number 2 is last
    value = Thumb
Key number 3 is first
    value = Tom


Notice that the keys do not come out in the order that we put them in.  This is typical in dictionary style lookup mechanisms.  The ordering of keys is not guaranteed.

Wednesday, July 13, 2016

Dictionary lookup - saving to disk

One advantage of using our single string dictionary lookup technique is that saving to and reading from a disk file is amazingly simple.  Just open the file and write the string.

sub writeDictionary
  open "dictionary.dat" for output as #writeDict
    print #writeDict, dictionary$
  close #writeDict
end sub

Reading on the other hand requires a slightly more sophisticated technique.  For example, if any of the keys or values have return characters in them then we want to make sure we read the whole file all the way to the end.  For this we will use the input$() function.

sub readDictionary
  open "dictionary.dat" for input as #readDict
  length = lof(#readDict)
  dictionary$ = input$(#readDict, length)
  close #readDict
end sub

The ability to preserve return characters is useful more for the values than for the keys, which for most applications will probably just be short one or two word names.

Tuesday, July 12, 2016

Liberty BASIC on the Rosetta Code site

One of the members of our community forum posted about some graphics code that he wrote on the Rosetta Code site.

Here is his post.
http://libertybasic.conforums.com/index.cgi?board=LB3&action=display&num=1468265910

I'm glad he posted about it just as a reminder to what a great resource the Rosetta Code site is.  There are many, many code samples there to learn from.  Check out this link.

http://rosettacode.org/wiki/Category:Liberty_BASIC

And, if you'd like to get in on the action there are many Rosetta Code examples which have not yet been implemented in Liberty BASIC.  For a list try this link:

http://rosettacode.org/wiki/Reports:Tasks_not_implemented_in_Liberty_BASIC

These are implemented in other language on the Rosetta Code site so if you'd like to try your hand at writing one or more in Liberty BASIC there are examples to glean inspiration from.

Monday, July 11, 2016

Dictionary lookup - Garbage collection

If we need to use our keyed dictionary lookup functions for a purpose where we will change the values for any or all keys the string we save in dictionary$ will get larger each time we set a key and value.  This is because the setValueByName subroutine sets a key and value by adding onto the front of the dictionary$ variable but it does not remove any preexisting value for that key.  So if for example I set a key of "storeFolder" and a value of "c:\myStoreFolder" and then later I change the value to "c:\myOtherFolder" I will have two different entries for the key "storeFolder".  Only the latest value will be returned by the getValue$() function.

So, how do we fix this?  We implement a garbage collector.  We can create a subroutine that makes a copy of dictionary$ that only has the latest value for each key.

Here is a first stab at a garbage collector subroutine.

sub collectGarbage
  pointer = 1
  while pointer > 0
    'get the next key
    pointer = instr(dictionary$, "~key~", pointer)
    if pointer then
      keyPointer = pointer + 5
      pointer = instr(dictionary$, "~value~", pointer)
      key$ = mid$(dictionary$, keyPointer, pointer - keyPointer)
      if instr(keyList$, key$) = 0 then
        value$ = getValue$(key$)
        newDictionary$ = "~key~" + key$ + "~value~" + value$ + newDictionary$
        keyList$ = keyList$ + key$
      end if
    end if
  wend
  dictionary$ = newDictionary$
end sub

Friday, July 08, 2016

Keyed dictionary lookup in Liberty BASIC

Liberty BASIC has a way to manage collections of data by using arrays and you look up the information by numeric position.  You can do a lot with this but it doesn't let you look up information by name.

We can provide an easy to use way to do this in Liberty BASIC by using the string functions of Liberty BASIC.  By using a single string we can have easy lookup of values by name and also have the ability to store the collection of values in a file and retrieve it simply.  In some versions of BASIC this is only useful for small lists of information because of string size limitations of 255.  Liberty BASIC permits strings of millions of characters so this is not a problem.

Here is a very simple demo of the concept just to get us started.  In future postings we will explain and enhance the way this works.

global dictionary$

call setValueByName "first", "Tom"
call setValueByName "last", "Thumb"
call setValueByName "phone", "555-555-1234"

print getValue$("last")
print getValue$("blah")
print getValue$("phone")
print getValue$("first")

sub setValueByName key$, value$
  dictionary$ = "~key~"+key$+"~value~"+value$+dictionary$
end sub

function getValue$(key$)
  getValue$ = chr$(0)
  keyPosition = instr(dictionary$, "~key~"+key$)
  if keyPosition > 0 then
    keyPosition = keyPosition + 5  'skip over key tag
    valuePosition = instr(dictionary$, "~value~",  keyPosition)
    if valuePosition > 0 then
      valuePosition = valuePosition + 7   'skip over value tag
      endPosition = instr(dictionary$, "~key~", valuePosition)
      if endPosition > 0 then
        getValue$ = mid$(dictionary$, valuePosition, endPosition - valuePosition)
      else
        getValue$ = mid$(dictionary$, valuePosition)
      end if
    end if
  end if
end function

Friday, July 01, 2016

Leveraging the lesson browser

Liberty BASIC has a cool feature that many people don't take advantage of.  It's called the lesson browser.  It allows you to create a collection of different programs in a single file arranged in an outline fashion along with comments for each program.

This is great for:
  1. Creating lessons (yeah)
  2. Sharing ideas with others
  3. Grouping related programs in a project
  4. Tracking the evolution of a program (a kind of versioning)
Here is a screenshot of the lesson browser in action.  It is used to provide a tutorial and also example of new features of Liberty BASIC, but it can be used by users to create any collection of programs along with documentation.


Thursday, June 30, 2016

GETCLIENTRECT - Gettting the dimensions of the inside of a window

Sometimes it comes in really handy to know exactly what the limits of the inside of a window are.  For example, if your Liberty BASIC program opens a window that is 500x400 pixels and you want to draw graphics that fit precisely or you are creating a game.. Think of Space Invaders where the aliens march back and forth on the screen!  You need to know the precise inner dimensions of the window so you need to know how thick the window frame is and also the title bar on top of the window.

The trouble is, these measurements are not going to be the same from one version of Windows to another, and they change if you modify your system font sizes.

So what to do?  Windows provides us a way to get the dimensions of the inside of the window by using the GETWINRECT function.

    WindowWidth = 500
    WindowHeight = 400
    open "get client rectangle" for window as #w

    'Get the window handle
    hndl = hwnd(#w)

    'Declare the struct which will be used to get the window client rectangle
    struct winRect, orgX as long, orgY as long, cornerX as long, cornerY as long

    'Make the GetClientRect call
    calldll #user32, "GetClientRect", hndl as ulong, winRect as struct, result as Boolean

    'Grab the width and height from the struct
    wide=winRect.cornerX.struct-winRect.orgX.struct
    high=winRect.cornerY.struct-winRect.orgY.struct

    notice "inside of window frame width = "; wide; " height = "; high


Tuesday, January 19, 2016

Copying a folder full of files in Liberty BASIC

Over on the Liberty BASIC forum at conforums.com one member was asking how to copy all the files in a folder for a database.

The hard way is to use the FILES statement and to write a bunch of code that tests and loops.

But is there an easier way?

One solution is to use the SHFileOperationA API call.

CallDLL #shell32, "SHFileOperationA", SHFILEOPSTRUCT as struct, CopyFolder as long
Chris Iverson shows how in his post.  That and more in this thread.  Click to read.



Friday, January 15, 2016

Date is between function in Liberty BASIC

Someone recently asked me if Liberty BASIC can answer the question about whether a date is between two other dates.  Yes it can!

The following is my quick solution to his question.

answer = isDateBetween("12/21/2015", "12/15/2015", "12/30/2015")
if answer then print "yes" else print "no"


answer = isDateBetween("11/21/2015", "12/15/2015", "12/30/2015")
if answer then print "yes" else print "no"


function isDateBetween(aDate$, firstDate$, lastDate$)
    aDays = date$(aDate$)
    firstDays = date$(firstDate$)
    lastDays = date$(lastDate$)
    isDateBetween = firstDays < aDays and aDays < lastDays
end function


Enjoy!

Thursday, January 14, 2016

Tiny BASIC part 5 - Adding color to PSET

It's much more fun to draw in color than with only a black pen, so let's add a third parameter to the PSET statement for color, for example:
PSET x, y, "color"
To do this we need to add some code to our  case "pset"  block:
 CASE "pset"
  IF GWINOPEN = 0 THEN
    E$ = "PSET error - Graphic window is not open"
    GOTO [Ready]
  END IF
  GOSUB [GetExpression]
  IF E$<>"" THEN [Ready]
  PSETX = N
  GOSUB [GetChar]
  IF C$ <> "," THEN
   E$= "Comma expected after x parameter"
   GOTO [Ready]
  END IF
  C = C + 1
  GOSUB [GetExpression]
  IF E$<>"" THEN [Ready]
  PSETY = N
  PSETCOLOR$ = "black"
  GOSUB [GetChar]
  IF C$ = "," THEN
   C = C + 1
   GOSUB [GetStringLiteral]
   IF E$ <> "" THEN [Ready]
   PSETCOLOR$ = B$
  END IF
  #GWIN "color "; PSETCOLOR$

  #GWIN "down ; set "; PSETX; " "; PSETY
  GOTO [FinishStatement]

The way this works is that it will look for a comma and a string expression after it sets PSETX and PSETYIf there is no comma it will skip over the part that gets a color parameter, so the default color will be black in that case.

The string will be the name of a valid Liberty BASIC color, for example red, blue, green, black, etc.    The following code is stolen from the routine that parses for the PRINT statement.  In a later post we will incorporate this into the PRINT code by calling it as a subroutine so that we won't have the same code twice.
[GetStringLiteral]
  GOSUB [SkipSpace]
  GOSUB [GetChar]
  IF C$=G$ THEN
   B$=""
[NextStringMember]
   C = C + 1 : C$=MID$(A$,C,1)
   IF C$="" THEN
    E$="Unterminated string"
    RETURN
   ELSE
   IF C$<>G$ THEN
    B$=B$+C$
    GOTO [NextStringMember]
   END IF
  END IF
  C = C + 1 : C$=MID$(A$,C,1)
  IF C$=G$ THEN
   B$=B$+C$
   GOTO [NextStringMember]
  END IF
 END IF
 RETURN

So we call the [GetStringLiteral] subroutine and check E$ for an error.  If there is none then we set PSETCOLOR$ to the value of B$ as shown here.

   GOSUB [GetStringLiteral]
   IF E$ <> "" THEN [Ready]
   PSETCOLOR$ = B$
  END IF
  #GWIN "color "; PSETCOLOR$


Then we add a drawing command like so to set the color:

  #GWIN "color "; PSETCOLOR$

Here is a sample that uses PSET with color!


5 graphicwin
10 pset x, y, "red"
20 pset x + 10, y, "blue"
30 pset x + 20, y, "green"
40 x = x + 1
50 y = y + 2
60 if x < 100 then goto 10

And here is a screenshot!



Wednesday, January 13, 2016

Liberty BASIC file type association

Liberty BASIC doesn't map the BAS file extension to itself when it is installed.  This is because I didn't want to be so presumptuous as to steal a common file type away from another version of BASIC that might be installed.

So, because there is a bug in Windows which makes it really hard to remap a file extension and there have been discussions about this in the Liberty BASIC forum at conforums.com one of our member Chris Iverson (thanks Chris!) has contributed some Liberty BASIC code to solve this problem.

  Click to see thread in the forum

Enjoy!

Sunday, January 10, 2016

Lunar lander revisited

Liberty BASIC comes with a nice introduction to video games called lander.bas.
  • It's a good example of a timer driven game.
  • It uses sprites which are actually generated on the fly using turtle graphics.
  • It also shows proper technique of structured programming.
So I have some ideas that I am thinking about implementing to update it and make it an even more complete video game example:
  • Add sound effects including ambient sounds, rocket motor noise and crash explosion.
  • Animate the rocket motor so you can see rocket exhaust coming out.
  • Add some flying space junk sprites that you need to avoid while trying to land.
  • Add a colored starfield in the background.
Looking forward to this!  Check back for updates!

Friday, January 08, 2016

Tiny BASIC part 4 - Adding a PSET statement


Okay, now we are ready to add a PSET statement for drawing pixels.  Today we will simply add the ability to draw a single black pixel at a time.  Next time we will add color!

Here is the code to accomplish this.  This is just another SELECT CASE block to add after the one we added for the GRAPHICWIN command.
 CASE "pset"
  IF GWINOPEN = 0 THEN
    E$ = "PSET error - Graphic window is not open"
    GOTO [Ready]
  END IF
  GOSUB [GetExpression]
  IF E$<>"" THEN [Ready]
  PSETX = N
  GOSUB [GetChar]
  IF C$ <> "," THEN
   E$= "Comma expected after x parameter"
   GOTO [Ready]
  END IF
  C = C + 1
  GOSUB [GetExpression]
  IF E$<>"" THEN [Ready]
  PSETY = N
  #GWIN "down ; set "; PSETX; " "; PSETY
  GOTO [FinishStatement]
This was a bit tricky to write because there isn't really any documentation with the original Tiny BASIC source code, but by looking at the code for the other statements I think I figured it out correctly.  It does seem to work.

The syntax for the new statement is PSET x, y

Let me explain what it does.
  • First check to see if the graphic window is open.  If it isn't then set E$ to be an error string.  Then GOTO [Ready].  This will display the error.
  • Then get the next expression using GOSUB [GetExpression].  This unleashes the expression parser which is easily the largest and most complex part of the Tiny BASIC source code.  Then it checks for an error using IF E$<>"".  If E$ does contain an error, then GOTO [Ready].
  • Okay so got this far, so set PSETX to be what was in N, which is the result of the call to [GetExpression].
  • Now get the next character, which we expect to be a comma to separate the x and y values.  If the next character is not a comma, set E$ to be an error and GOTO [Ready].
  • Now advance C one character by adding 1 to it.  We do this because we found the expected comma, and now we need to skip over that so that we can get the next expression for our y value.
  • Get the next expression using GOSUB [GetExpression].  Test E$ for an error and GOTO [Ready] if there is one.
  • Get the value of N and put it into the variable PSETY.
  • Finally, draw the pixel in the graphics window!
Here is the sample Tiny BASIC program that uses the PSET statement:

10 graphicwin
20 pset x, y
30 x = x + 1
40 y = y + 2
50 if x < 200 then goto 20

And here is the output of the program!

Thursday, January 07, 2016

Run BASIC Revisited - The easiest web development system on Earth

I got an inquiry yesterday about Run BASIC asking about what is special about it.  The essential concept is that it is an all-in-one BASIC web application server.  You can use it to create a dynamic web site, or to host in-house applications for your business or school, or use it to control your home.  The possibilities are pretty much endless.

Here is a link to a white paper about Run BASIC.
    http://www.libertybasic.com/RunBASICBreakthrough.pdf

Here is a link to the Run BASIC community forum.
    http://runbasic.proboards.com/

Wednesday, January 06, 2016

Tiny BASIC part 3 - Adding GRAPHICWIN statement


We are going to add GRAPHICWIN and PSET statements to Tiny BASIC.

Let's start with the really easy one.  We will add a  case "graphicwin"  block to the end of the select case blocks that we examined in the last post.  Here is what it looks like.  The new code is in bold red.
 CASE "let"
  GOSUB [GetLabel]
  IF E$<>"" THEN [Ready]
 CASE "graphicwin"
  IF GWINOPEN = 1 THEN
    PRINT "Graphics window is already open."
  ELSE
    GWINOPEN = 1
    OPEN "Graphics" FOR graphics AS #GWIN
  END IF
  GOTO [FinishStatement]

 END SELECT
So when you run Tiny BASIC and type the command graphicwin and press Enter it will open a small graphics window.  When it does this it also sets the GWINOPEN flag to 1 to that we can check it if the program tries to open another graphics window.  Only one graphics window will be allowed at a time.

The other thing that we want to do it close the graphics window and reset GWINOPEN to 0 if the program is started using the RUN statement.

So, we need to add the following code into the  case "run"  block.  Here is how that code should look.  The new code is in bold red.

 CASE "run"
  IF GWINOPEN = 1 THEN
    CLOSE #GWIN
    GWINOPEN = 0
  END IF

  FOR I=27 TO 52 : A(I)=0 : NEXT I
  L=27 : C=1
  GOTO [FinishStatement2]
So now the program will always start off in a clean state each time it is run!

In our next post we will figure out how to add a PSET statement so we can draw some graphics!


Monday, January 04, 2016

Tiny BASIC part 2 - Adding new statements

This is part 2 of a series on extending tiny basic.bas which is an example that comes with Liberty BASIC v4.5.0.

In order to add some graphics capability I want to suggest two new commands just to start.

GRAPHICWIN width, height     and    PSET x, y, color$

These will enable us to open a window to draw in, and also to draw pixels of a specific color at a given x, y position.  This will be a crude start, but it will be instructive because it will show the reader how to extend Tiny BASIC to do what is desired.

The first thing to do is figure out where in the code Tiny BASIC parses commands so we can add some more.  The code below is the routine that does this.  If you look carefully you will see a SELECT CASE statement and then a CASE statement for each Tiny BASIC command.

More later.
[NextStatement]
 GOSUB [GetLabel]
 IF E$<>"" THEN [Ready]
 SELECT CASE D$
 CASE "if"
  GOSUB [GetExpression]
  IF E$<>"" THEN [Ready]
  IF N<1 font="" then="">
   B$=A$(L) : C=LEN(B$)+1
   GOTO [FinishStatement]
  END IF
  GOSUB [GetLabel]
  IF E$<>"" THEN [Ready]
  IF D$<>"then" THEN
   E$="'THEN' expected"
   GOTO [Ready]
  END IF
  GOTO [NextStatement]
 CASE "rem"
  B$=A$(L) : C=LEN(B$)+1
  GOTO [FinishStatement]
 CASE "input"
  GOSUB [GetVar]
  IF E$<>"" THEN [Ready]
  INPUT N : A(V)=N
  GOTO [FinishStatement]
 CASE "print"
[Print]
  GOSUB [SkipSpace]
  GOSUB [GetChar]
  IF C$=G$ THEN
   B$=""
[NextChar]
   C = C + 1 : C$=MID$(A$,C,1)
   IF C$="" THEN
    E$="Unterminated string"
    GOTO [Ready]
   ELSE
    IF C$<>G$ THEN
     B$=B$+C$
     GOTO [NextChar]
    END IF
   END IF
   C = C + 1 : C$=MID$(A$,C,1)
   IF C$=G$ THEN
    B$=B$+C$
    GOTO [NextChar]
   END IF
   PRINT B$;
  ELSE
   GOSUB [GetExpression]
   IF E$<>"" THEN [Ready]
   B=N1
   IF B=N THEN
    PRINT N;"*";
   ELSE
    PRINT N;
   END IF
  END IF
  GOSUB [SkipSpace]
  GOSUB [GetChar]
  IF C$="," THEN C = C + 1 : GOTO [Print]
  GOSUB [SkipSpace]
  GOSUB [GetChar]
  IF C$<>";" THEN
   PRINT
  ELSE
   C = C + 1
  END IF
  GOTO [FinishStatement]
 CASE "clear"
  FOR I=27 TO 52 : A(I)=0 : NEXT I
  GOTO [FinishStatement]
 CASE "run"
  FOR I=27 TO 52 : A(I)=0 : NEXT I
  L=27 : C=1
  GOTO [FinishStatement2]
 CASE "goto"
  GOSUB [GetExpression]
  IF E$<>"" THEN [Ready]
  IF E>=N THEN L=27
  C=1 : T=N
[NextGoto]
  IF L=126 THEN
   E$="Line not found"
   GOTO [Ready]
  END IF
  GOSUB [GetNumber]
  IF N=T THEN E=N : GOTO [NextStatement]
  L = L + 1 : C=1
  GOTO [NextGoto]
 CASE "new"
  FOR I=27 TO 125 : A$(I)="" : NEXT I
  FOR I=27 TO 52 : A(I)=0 : NEXT I
  IF E=0 THEN [FinishStatement]
  GOTO [Ready]
 CASE "cls"
  CLS : GOTO [FinishStatement]
 CASE "help"
  FOR I=9 TO 18
   B$=A$(I) : PRINT B$
  NEXT I
  GOTO [FinishStatement]
 CASE "mem"
  B=126
  FOR I=27 TO 125
   diffI = 152 - I  'Cheating here
   B$=A$(diffI) : IF B$="" THEN B=diffI
  NEXT I
  B=126-B : PRINT B;"*";
  PRINT " lines free"
  GOTO [FinishStatement]
 CASE "end"
  GOTO [Ready]
 CASE "bye"
  GOTO [ExitTinyBAS]
 CASE "list"
  GOSUB [GetNumber] : T=N : A=L : I=C
  IF T=0 THEN
   GOSUB [GetLabel]
   IF E$="" AND D$="pause" THEN I=C
   E$=""
  END IF
  FOR L=27 TO 125
   C=1 : GOSUB [GetNumber]
   B=(T=0) OR (N=T)
   IF B=TRUE THEN
    IF A$<>"" THEN
     PRINT A$
     IF D$="pause" THEN
      B = (L-26) mod 10
      IF B=0 THEN PRINT "Pause..."; : INPUT AAA$
     END IF
    END IF
   END IF
  NEXT L
  L=A : C=I
  GOTO [FinishStatement]
 CASE "save"
 PRINT "SAVE, TBD"
 CASE "load"
 PRINT "LOAD, TBD"
 CASE "let"
  GOSUB [GetLabel]
  IF E$<>"" THEN [Ready]
 END SELECT




Thursday, December 31, 2015

More on getting started with Liberty BASIC

In addition to the resources I mentioned the other day, please do not overlook our great online community of users.

There are two large forums where you can learn a lot from friendly, knowledgeable people about all kinds of things.

First the forum at Conforms.  This great forum is organized by topic, which is really nice.  Here's the link:

   http://libertybasic.conforums.com

Secondly there is Yahoo Groups!  What's nice about this site is that you can subscribe to get emails, and you post to the group by email.  Here is the link:

    http://groups.yahoo.com/group/libertybasic

People do amazing things with Liberty BASIC, and these are the places where these people hang out.

See you there!

Tiny BASIC revisited

Liberty BASIC comes with an implementation of Tiny BASIC which is extremely similar to the BASIC that came with the old Radio Shack TRS-80.  Remember that computer?  Some of us do.  :-)

This is a very limited version of BASIC, but it has some strengths.


  • Simplicity - Not much to learn
  • Interpreted - This is an interactive interpreter
  • Source code - You can modify the language
So, since Tiny BASIC can be modified by pretty much anyone who knows a little BASIC, I am starting a series where I will extend the language and show how to do it.

First we will focus on graphics!  More to come so stay tuned!

Wednesday, December 30, 2015

Doing pixel manipulation in Liberty BASIC

One of the members of the Liberty BASIC community posted a cool example of doing pixel graphics in Liberty BASIC.  It is instructive because it is short and it shows how to effectively use Windows API calls to work with graphical images.

Here is a link to the post including a code example and a screenshot of the output.

Tuesday, December 29, 2015

How to get started with Liberty BASIC

I got an email today from someone who was frustrated trying to figure out how to get started with Liberty BASIC.  This seemed like good blogging material.  :-)

Here is a start on the subject of getting started.

Try it - Download the trial software and install it.  It works on pretty much all versions of Windows that run on laptops and desktop PCs.  We don't support Windows Server but it may run.

  Here's the download link http://www.libertybasic.com/download.html

Liberty BASIC comes with a tutorial.  Once you start up Liberty BASIC look at the Help menu for the tutorial and the help documentation

There is a softcover book that you can purchase at Amazon's site.

  Here is the link for the book:
    http://www.amazon.com/Beginning-Programming-Liberty-BASIC-Gundel/dp/0557228115

Monday, December 28, 2015

New features of Liberty BASIC v4.5.0

This exciting new release of Liberty BASIC increases memory available 14x over the previous version, adds new string functions, the ability to fetch web pages, and new code editor enhancements.  Download your copy now!  Click here.

New features of Liberty BASIC v4.5.0
  • Memory space raised to 1GB from 70MB
  • Ctrl+click on a branch label or SUB name to jump to that place in the code
  • Double click on a variable name or handle to highlight other occurences of that item in yellow
  • New httpget$() function so now you can get a file from a webserver without API calls
  • New string functions make it easier to do some things and with faster performance.
    • upto$(sourceString$, search$
    • after$(sourceString$, search$
    • afterlast$(sourceString$, search$)
    • endswith(sourceString$, search$)
    • remchar$(sourceString$, removeThese$)
  • Removed arbitrary limitations on the baud rates that can be specified when opening a serial port.
  • Upgraded to NTPort v2.8 from v2.3 to add compatibility for 64-bit versions of Windows.
  • The Liberty BASIC editor now remembers its size and location when you start LB.
  • Added a filter bad characters feature in the LB editor help the compiler, especially when code is pasted in from a web browser.
  • Increased the FILEDIALOG length of the file path from 128 to 260 which is the Windows file dialog maximum path length.
  • Added FIND, FINDBACK, and RESETFIND commands to the text window and texteditor control.
  • Added !backcolor and !forecolor commands to texteditor controls and text windows
  • Several bug fixes

Thursday, October 18, 2012

Referral Campaign - Win a free copy of Liberty BASIC!

Until the end of October 2012 we are running a word of mouth referral campaign. For a free copy of Liberty BASIC, refer at least 5 friends with an interest in programming. If you want to qualify for the free copy, your friend need to send an email to freeoffer@libertybasic.com and mention that you referred them. They must include your name and email address. We will send you a download link and registration code. Please try to refer friends that you think would be interested in Liberty BASIC. Thanks!

Wednesday, October 03, 2012

Regarding How to Teach Programming

Andres Valloud posted "...The goal of this improved teaching is to allow everyone to take advantage of programming, not just CS oriented people..." http://blogten.blogspot.com/2012/10/regarding-how-to-teach-programming.html

Friday, April 27, 2012

Before Make Magazine

In the corner of the factory there was a rather large machine sitting there unused. There was a sort of hodgepodgeness (if that's a word) about it. My boss Bob explained to me that this was a CNC machine that he had built himself. Wow! So before the company had money to purchase the industry standard Excellon drilling and routing machines he had decided it was possible to build his own, and it worked. I think that's really impressive!

Tuesday, April 03, 2012

BASIC for the Raspberry Pi?

What's Raspberry Pi? It is a cool new single board computer about the size of a credit card. It runs Linux (it can run other things) and it only costs $35, or $25 if you don't care about networking. You only need a micro USB charger or batteries to power it, a keyboard and mouse, and an HDMI compatible monitor or TV set.

This new device is aimed at schools, but the appeal of such a device is obviously very broad. I went to their forum and mentioned the idea of producing a version of BASIC for the RP. The reactions were mixed. Seems like that crowd is strongly committed to Python. That's okay, I've got my hands full right now with Liberty BASIC and Run BASIC.

Perhaps in the future I will have a chance to do something. It would probably be my first open source project, based on Squeak Smalltalk.

Tuesday, March 13, 2012

The Arduino Phenomenon

Seems like there is a lot of interest lately in using microcontrollers such as the BASIC Stamp and the new Arduino products. To my surprise, even a long retired electrical engineer friend knew about Arduino when I asked him. I get email from users of these products asking if they can use Liberty BASIC to program them. The answer is no, and yes.

These devices come with their own programming tools. Liberty BASIC is a Windows only (and soon also Mac and Linux) language, so it cannot be used to program microcontrollers. However I've been told that they have found a use for Liberty BASIC with microcontrollers. Some people have created a GUI control panel (including running graphics for example) for their microcontroller projects using Liberty BASIC because Liberty BASIC can be used to monitor devices using serial, parallel and network ports.

For more information about this, see the following link (you will need to register with the forum to read the posts).

http://libertybasic.conforums.com/index.cgi?board=comport

Saturday, March 12, 2011

Automatic file backup - using a timer

Once our file backup utility is running and our window is open we need to be able to use the start and stop buttons to control the activity of program.

Here is the code for the start action. It ties into the [start] label in the Start button.

[start] 'startup the backup timer
#main.start "!disable"
#main.stop "!enable"
gosub [checkInitialFiles]
#main.statusLog "Starting backup"
#main.interval "!contents? interval"
timer interval * 1000, [checkFiles]
wait

When the button is clicked we disable the Start button and enable the Stop button to show which operations are valid. We call [checkInitialFiles] which we haven't written yet (we'll get into that later). We show in the statusLog texteditor that we are starting the backup process. Then we get the contents of the interval textbox and start the timer. The reason we multiply the interval by 1000 is that the timer measures time in milliseconds so if we want 5 a second interval we need to give the timer a value of 5000. Finally we stop and wait for a timer tick or for user interaction.

Once our timer is running we need to be able to stop it. Here is our stop handler:

[stop] 'stop the backup timer
timer 0
#main.start "!enable"
#main.stop "!disable"
#main.statusLog "Stopping backup"
wait

This is real simple. First thing is to stop the timer with timer 0. Then we reverse the enabling of the Start and Stop buttons. Compare this to the way that [start] does it. Then we log to the statusLog texteditor that we are stopping. Finally we wait.

The purpose of the [checkInitialFiles] subroutine is to create a description of the files we are interested in and the time and date they were last modified. Then each time the timer ticks after this we create a new description of these files. If the date and time changes on any of these files then it's time to make a new backup.

Just for now let's just create an empty [checkInitialFiles] subroutine:

[checkInitialFiles] 'snapshot of filenames and timestamps
return

The routine doesn't do anything yet, so we only have a RETURN statement.

Now we'll create a [checkFiles] routine which will be called each time the timer ticks. For now the routine will not do much. We will write the full routine in a later section.

[checkFiles] 'are there new files
#main.statusLog "tick"
'temporarily disable the timer
timer 0
'perform the check here
'reenable the timer
timer interval * 1000, [checkFiles]
wait

The first thing we do is log the word "tick" to the statusLog. This is for instructive purposes only and will be removed later. We do this so that we can see that the timer is working. After this we disable the timer. This might seem like a strange idea, but the reason we do it is because the next thing we do is check the files to see if they changed (we'll write this part later). If they change we don't want the timer to be running because if it takes a while to backup the files and the timer is still running then the timer events can build up. Once the file check and possible backup are finished we reenable the timer.

The entire listing so far is posted below. Try running it. When you click Start it will begin logging its activity. Notice that the word tick gets logged every five seconds. Click the Stop button and change the interval to 1. Start it again and the logging will happen once per second.


dim info$(10,10)
setupPath$ = DefaultDir$+"\backupsetup.ini"

WindowWidth = 560
WindowHeight = 460
statictext #main, "Files to backup:", 5, 5, 94, 20
texteditor #main.listOfFiles, 5, 26, 530, 95
statictext #main, "Destination folder:", 5, 132, 107, 20
textbox #main.destination, 115, 127, 420, 25
statictext #main, "Backup interval in seconds:", 5, 157, 163, 20
textbox #main.interval, 170, 152, 100, 25
button #main.save,"Save",[save], UL, 495, 152, 42, 25
button #main.start,"Start",[start], UL, 5, 187, 75, 25
button #main.stop,"Stop",[stop], UL, 90, 187, 70, 25
statictext #main, "Backup status log", 5, 217, 106, 20
texteditor #main.statusLog, 5, 237, 530, 160
menu #main, "Edit"
open "Backup Utility" for window_nf as #main
#main.stop "!disable"
gosub [loadSetup]
wait

[loadSetup]
#main.listOfFiles "!cls";
if fileExists(setupPath$) then
open setupPath$ for input as #setup
while filename$ <> "end!"
line input #setup, filename$
if filename$ <> "end!" then
#main.listOfFiles filename$
end if
wend
line input #setup, destination$
#main.destination destination$
line input #setup, interval
#main.interval interval
close #setup
end if
return

[start] 'startup the backup timer
#main.start "!disable"
#main.stop "!enable"
#main.interval "!contents? interval"
gosub [checkInitialFiles]
#main.statusLog "Starting backup"
timer interval * 1000, [checkFiles]
wait

[stop] 'stop the backup timer
timer 0
#main.start "!enable"
#main.stop "!disable"
#main.statusLog "Stopping backup"
wait

[checkInitialFiles] 'snapshot of filenames and timestamps
return

[checkFiles] 'are there new files
#main.statusLog "tick"
'temporarily disable the timer
timer 0
'perform the check here
'reenable the timer
timer interval * 1000, [checkFiles]
wait

'return a true if the file in fullPath$ exists, else return false
function fileExists(fullPath$)
files pathOnly$(fullPath$), filenameOnly$(fullPath$), info$()
fileExists = val(info$(0, 0)) > 0
end function

'return just the directory path from a full file path
function pathOnly$(fullPath$)
pathOnly$ = fullPath$
while right$(pathOnly$, 1) <> "\" and pathOnly$ <> ""
pathOnly$ = left$(pathOnly$, len(pathOnly$)-1)
wend
end function

'return just the filename from a full file path
function filenameOnly$(fullPath$)
pathLength = len(pathOnly$(fullPath$))
filenameOnly$ = right$(fullPath$, len(fullPath$)-pathLength)
end function

Thursday, March 03, 2011

Automatic file backup - loading setup

Now that we've got a simple GUI designed, let's write some code which will load the files we want to backup, the destination path, and the interval of our automatic backup.

We need a subroutine to load the setup which we will call using GOSUB. We can call this right after we open the window.

open "Backup Utility" for window_nf as #main
gosub [loadSetup]
wait


We want to know if the setup file exists. There is an example program called fileExists.bas that comes with the functions we need to check for file existence. We'll just grab those. Here they are:

'return a true if the file in fullPath$ exists, else return false
function fileExists(fullPath$)
files pathOnly$(fullPath$), filenameOnly$(fullPath$), info$()
fileExists = val(info$(0, 0)) > 0
end function

'return just the directory path from a full file path
function pathOnly$(fullPath$)
pathOnly$ = fullPath$
while right$(pathOnly$, 1) <> "\" and pathOnly$ <> ""
pathOnly$ = left$(pathOnly$, len(pathOnly$)-1)
wend
end function

'return just the filename from a full file path
function filenameOnly$(fullPath$)
pathLength = len(pathOnly$(fullPath$))
filenameOnly$ = right$(fullPath$, len(fullPath$)-pathLength)
end function


We will call the fileExists( ) function from our [loadSetup] subroutine. A really simple example of the data in our setup file would have a list of file paths, and end! marker for the end of that list of files, a single line with the desired destination path, and another line with the interval in seconds between backup attempts.

Example backupSetup.ini
c:\myfolder\test.txt
c:\myfolder\backMeUp.dat
c:\myfolder\SillyPutty.exe
end!
c:\backupFolder\files
5


Once we know the file exists we can open it up and read it, placing the information into the different fields in our GUI.

[loadSetup]
#main.listOfFiles "!cls";
if fileExists(setupPath$) then
open setupPath$ for input as #setup
while filename$ <> "end!"
line input #setup, filename$
if filename$ <> "" then
#main.listOfFiles filename$
end if
wend
line input #setup, destination$
#main.destination destination$
line input #setup, interval
#main.interval interval
close #setup
end if
return


Here is the complete listing so far:

dim info$(10,10)
setupPath$ = DefaultDir$+"\backupsetup.ini"

WindowWidth = 560
WindowHeight = 460
statictext #main, "Files to backup:", 5, 5, 94, 20
texteditor #main.listOfFiles, 5, 26, 530, 95
statictext #main, "Destination folder:", 5, 132, 107, 20
textbox #main.destination, 115, 127, 420, 25
statictext #main, "Backup interval in seconds:", 5, 157, 163, 20
textbox #main.interval, 170, 152, 100, 25
button #main.save,"Save",[save], UL, 495, 152, 42, 25
button #main.start,"Start",[start], UL, 5, 187, 75, 25
button #main.stop,"Stop",[stop], UL, 90, 187, 70, 25
statictext #main, "Backup status log", 5, 217, 106, 20
texteditor #main.statusLog, 5, 237, 530, 160
menu #main, "Edit"
open "Backup Utility" for window_nf as #main
gosub [loadSetup]
wait

[loadSetup]
#main.listOfFiles "!cls";
if fileExists(setupPath$) then
open setupPath$ for input as #setup
while filename$ <> ""
line input #setup, filename$
if filename$ <> "end!" then
#main.listOfFiles filename$
end if
wend
line input #setup, destination$
#main.destination destination$
line input #setup, interval
#main.interval interval
close #setup
end if
return

'return a true if the file in fullPath$ exists, else return false
function fileExists(fullPath$)
files pathOnly$(fullPath$), filenameOnly$(fullPath$), info$()
fileExists = val(info$(0, 0)) > 0
end function

'return just the directory path from a full file path
function pathOnly$(fullPath$)
pathOnly$ = fullPath$
while right$(pathOnly$, 1) <> "\" and pathOnly$ <> ""
pathOnly$ = left$(pathOnly$, len(pathOnly$)-1)
wend
end function

'return just the filename from a full file path
function filenameOnly$(fullPath$)
pathLength = len(pathOnly$(fullPath$))
filenameOnly$ = right$(fullPath$, len(fullPath$)-pathLength)
end function

Tuesday, March 01, 2011

Automatic file backup UI design

Here's what I'm thinking. The back utility GUI will be a simple window with a text area that contains a list of file paths. There will be start and stop buttons, an interval for a timer in seconds, and a field with a destination path.

When the timer is started the backup utility will examine each file that is specified in the text area and collect modification date and time. Later when the timer ticks we will check them again to see if any of them has changed. If even one of the files is different we will back them up as a set.

To perform the backup the program will take the destination path and use it to create a unique folder by adding a number to it. Then it will copy all the files into newly created folder.

There will also be a status area in the window where the user will be kept informed about backup activities.

The configuration for the backup utility will be stored in a file. When the program is started it will be loaded and displayed in the GUI, and there will be a save button to save the configuration back to the configuration file.

More than likely this design will evolve as we actually build the program code.

Here is the beginning of our program, just the GUI code to start.

WindowWidth = 560
WindowHeight = 460
statictext #main, "Files to backup:", 5, 5, 94, 20
texteditor #main.listOfFiles, 5, 26, 530, 95
statictext #main, "Destination folder:", 5, 132, 107, 20
textbox #main.destination, 115, 127, 420, 25
statictext #main, "Backup interval in seconds:", 5, 157, 163, 20
textbox #main.interval, 170, 152, 100, 25
button #main.save,"Save",[save], UL, 495, 152, 42, 25
button #main.start,"Start",[start], UL, 5, 187, 75, 25
button #main.stop,"Stop",[stop], UL, 90, 187, 70, 25
statictext #main, "Backup status log", 5, 217, 106, 20
texteditor #main.statusLog, 5, 237, 530, 160
menu #main, "Edit"
open "Backup Utility" for window as #main
wait

Saturday, February 26, 2011

Automatic file backup

I'm inspired by a real world need I have to create utility in Liberty BASIC which will do the following:

1) Periodically examine a list of files in a folder to see if they have changed
2) Make a new folder with a unique name somewhere else to contain the updated files
3) Copy the changed files to the new folder

We can keep a list of paths and files in a file, create a simple gui for maintaining this list and starting and stopping the timer, and for displaying a log of activity.

In our next installment we will write the GUI code.

Thursday, February 24, 2011

Projects

I've decided to start some small projects which show how to do various things in Liberty BASIC. This will be a good way to demonstrate how easy programming in BASIC can be, and it will help people to learn specific programming techniques.

Tuesday, December 01, 2009

Words of wisdom

I've always been a big fan of the Forth programming language. It is nothing like BASIC, but here is a page from forth.com with some words of wisdom from Chuck Moore that I figure are just good food for thought no matter what language you prefer.

http://www.forth.com/resources/evolution/evolve_1.html

Sunday, October 11, 2009

BASIC and Space Flight!

The same fellow who created an OpenGL flight simulator in Liberty BASIC has taken it a step further by creating a spaceflight simulator with a map editor. Very neat!

Check it out

Monday, September 28, 2009

BASIC, Lasers, and you

Here's an interesting example of the perfect use for BASIC. If you're into laser tag and programming this may be your ticket. It's cool that the makers of this device decided to write the config tool in Liberty BASIC, and that they make the code available so the average Joe can customize it. That's in the spirit of BASIC. Programming for the non-programmer.

http://www.lasertagparts.com/mtmicro.htm

Friday, September 18, 2009

Fractals in a page of code

What's great about BASIC and languages like it is that you don't have a write a lot of code that has nothing to do with what you're trying to create (like Java for example). It should be really easy to throw together a little code and play with graphics. Programming should be fun, not a burden.

Here is a thread that shows how to draw fractals in less than a page of BASIC.

Click to read the thread

Friday, September 11, 2009

Levity and Programming

BASIC is the perfect programming language to a lighthearted programming challenge, and I'm about to prove it to you. What better matchup between BASIC than Paper, Rock, Scissors?

Check it out. It's great to see people programming just for fun.

Programming tools in BASIC

Alyce Watson has updated her CodeAChrome widget, which is a syntax coloring editor specially made for editing BASIC source code. It's small, simple to use, and free! Check out her announcement here.

Thursday, September 03, 2009

Earth shaking!

Here's a neat example of BASIC programming which plots earthquake data graphically.  What's cool about this is that it demonstrates graphics, interfacing with VBScript, and getting information off the Internet.  Add to this that it's not a large program.



Tuesday, September 01, 2009

Who says you can't do that in BASIC?

Over at the Liberty BASIC forum on Conforums they've announced a programmer of the month for September.  Chung, a prolific Liberty BASIC programmer has created an OpenGL flight simulator in Liberty BASIC.   Very, very nice!

  Click to read the announcement and make sure to follow the link to Chung's site to see the flight simulator!


Saturday, July 25, 2009

Searching for BASIC

When people search for BASIC online using Google or Bing, or whatever, what keywords do they search with? Some of the obvious choices to me are:

  • basic
  • basic for windows
  • qbasic
  • visual basic
  • vb

How would you search for BASIC?

Monday, June 01, 2009

Joy in Programming

I responded to a post on another blog (http://blogten.blogspot.com/2009/05/wards-comment.html) about how someone complained that the Smalltalk programming language permits the programmer too much freedom and that it's "too easy." The argument against being easy is that if it's too easy the programmer will be able to rush into creating software that is designed poorly. I have a hard time believing it is ever a benefit that something is hard to do. I think this applies to languages like BASIC so I'm copying what I posted there below.
Freedom is essential if you want to live life to the full, and not just in software development. We need to teach what is the best way to live in freedom, not impose a tyranny of suffocating "safety". If we don't build a culture of discipline and excellence then we deserve what we get. If we impose tons of rules to in an effort to prevent people from making mistakes we risk making software development such a burden that few people will want to do it anymore. It should be possible for software development to be an enjoyable activity, and for innovation and discovery to be experienced by newbies and experts. Joy is important in life.

Perhaps I oversimplify, but I hope this communicates an important idea effectively.

Saturday, January 03, 2009

Easter Eggs?

Here's a link to a fun article about how Microsoft added Easter Eggs to their original BASIC implementations.


It never even occurred to me to do this.  ;-)

Monday, December 15, 2008

Imposter?

I found an article named Web programming is hard to do right by a fellow named Bert Hubert. He does a nice job of explaining what is so hard about web programming and then goes on to describe how it could be done right. He even includes some BASIC code as an example. I like the questions he asks:
  • How did we arrive at this mess?
  • That's just the way it works, isn't it?
  • How should it be then?
  • Why not go back to the old days?
This article really resonates with the ideas that inspired Run BASIC. We need more people who think this way.

He provides some C-like code implementing what the BASIC code does. I guess that this new scripting language is code for a language called Imposter by Gabor Vitez which he mentions in a note at the top of his article.

I did a quick search for information about Imposter and its author but it seems to have withdrawn from the Internet. Does anyone know where to get a copy of Imposter to have a look?

Friday, December 12, 2008

Getting the word out about Run BASIC

I've been working on a whitepaper for a while now that tries to explain what it is that makes Run BASIC special and I've finally published it. It's titled "Run BASIC - A Breakthrough Web Application Server." Check it out here

It isn't usually wise to toot one's own horn too loud but I really believe that Run BASIC is unique. The trouble is that people are so overexposed to hype that they don't really easily believe that Run BASIC is different. In fact one person who helped me edit the whitepaper recently contacted me after trying Run BASIC and explained that he didn't realize how easy it really is until he tried it out.

Monday, December 08, 2008

Run BASIC v1.01!

I'm excited to announce that we've released Run BASIC v1.01. In addition to the Windows version, this is our first release for the Macintosh and also for Linux. Now we also have a free edition (not time limited!) so you can go and try it on your own computer. Run (don't walk) immediately to http://www.runbasic.com/ and get your own copy.

Friday, November 21, 2008

Teaching an old dog new tricks

One reader commented, "So should a basic language add object-oriented features? For me, it would simplify things. Inheritance and polymorphism produces much less code, and FOR ME, much more simplicity. However, for a procedure-oriented person, only complexity has been added."

This is an excellent point. One way that I've tried to add objects to Run BASIC is to have some built right in. You don't have to create them and you don't need to import them, but you can start using them. This is hopefully one way to begin to help procedural programmers warm up to objects and there's no reason why the rest of the program cannot be written in a procedural style.

The other thing that Run BASIC does is take the RUN statement and adapt it so that other BASIC programs that you run can be optionally treated as objects, or if that's too far of a leap you can think of it as a modular library of code, like so:

run "mymodule.bas", #module
#module doMyWork("some string")


Thursday, October 09, 2008

Flight Simulator in BASIC

I remember years ago that there was an instrument-only flight simulator written in BASIC and ported to different computers.  It wasn't much to look at because it was all character based.  Tom Nally has just released an open source flight simulator written in Liberty BASIC.  This one blows the doors off that old classic.  Check it out here.

Monday, October 06, 2008

BASIC for the web a killer app?

If you ask the average geek worth his salt what was the killer app that launched the microcomputer revolution the answer would probably be "Visicalc, of course!"

I take issue with this answer. Long before the spreadsheet application Visicalc was a gleam in Dan Bricklin's eye the most important and powerful application for small computers was the BASIC programming language. Without Microsoft BASIC (and this is Microsoft's real and lasting legacy if you ask me) very few people would have been able to do anything useful with computers. Most versions of BASIC back then were variations on Bill Gates' original BASIC interpreter.

Without BASIC we would not have seen so many kids grow up to be programmers, myself included. This is the very reason why I work on BASIC language products because I believe that there's no good reason why anyone with a little desire and time shouldn't be able to create software.

Run BASIC is very much in the same spirit as the early BASIC, but for the web. Now anyone can create web applications. :-)

Run BASIC - Killer app for the Internet age!

Sunday, September 28, 2008

Run BASIC for Windows, Mac and Linux

Tonight I am pleased to mention that we posted Run BASIC v1.0.1 beta 3 for Windows, Mac OS X, and Linux (tested on Ubuntu). This is our first ever release of software for Linux, although people have been successfully using the Windows version using Wine.

It shouldn't take more than a couple of weeks to finalize v1.0.1 and release it. If you haven't had a look at Run BASIC check out the site. Make sure to watch the videos posted there to get a complete sense of just how easy web programming can be.

Thursday, September 25, 2008

Eating my own dog food

Run BASIC comes with a bunch of example programs, one of which is a wiki called runWiki. It's about two pages long and is remarkable for what it does in those two pages, including the use of the SQLite database to store pages.

One of my customers (Neal) took that wiki and added a bunch of cool stuff to it like user accounts and many more formatting tags.

Now I've decided to take Neal's version of my original runWiki and use it to host a site for a civic group in the town of Ashland, Massachusetts where I live. It went live last weekend to coincide with the annual Ashland Day faire. Check it out at http://www.weloveashland.com

It's a pretty simple site which will get more sophisticated as we go. The beautiful thing is that it acts as a vehicle for producing runWiki3. I can customize it to my hearts content since I have all the source code in BASIC, the people's language. ;-)

Wednesday, September 24, 2008

Free version of Run BASIC

One thing that has been lacking in our effort to promote our Run BASIC web programming system is a free version. In fact there is no time limited trial either. This has been mostly because we have been unsure what would be the best way to do it.

What we've decided on is when Run BASIC v1.0.1 is released soon for Windows, Mac and Linux we will also release a free version. This free version will be for personal use instead of being a web application server. Users of the free Run BASIC will be able to create projects and use any features of the language, but they will not be able to serve applications. This will allow them to experiment and see if Run BASIC meets their needs. If it does and hosting the application is in the cards then an upgrade to the server version is available for $59.95, or hosting service can be purchased at http://www.runbasicnet.com

Comments and suggestions are most welcome.