Share My Creation Device Basic language IDE

Unfortunately without a Device IDE it is no longer possible to whip up quick and dirty programs on an Android device like we could with Basic4ppc on Windows Mobile.

I realised that my BasicLib script interpreter library only lacked one thing that stopped it being used as the basis for an interpreter for a device IDE and that was that it didn't support any means of responding to external events so all it could do was run linear code then exit. Fine for scripts but not for a user driven application that spends most of its time suspended waiting for events to happen. So I added it!

As well as being able to respond to events a program needs to be able to interact with the platform to add controls and access the GUI, file system and other OS services. Unlike previous versions of BasicIDE, which used the normal BasicLib library and relied upon the "Sys" function to call methods, version 2.2, and future, versions use a new BasicLibIDE library that "knows" about the methods in Script.bas so the platform functions are now embedded in the script language. It is important that the version of Script.bas matches that of the BasicLibIDE library as both need to be modified in parallel to add new functions to the language.

The previous Sys and CallHostSub functionality is of course still available.

The demo program here supports the most important views, and their events, for small programs and has graphics and file handling support. Look at Readme.txt for instructions and the comments in the Script module to see what is implemented there.

EDIT :- See post #7 for a suggestion to add Invalidate to the Script module

EDIT :- Version 2.0 posted. See post #8 for details.

EDIT :- Version 2.1 posted. See post #9 for details.

EDIT :- Version 2.2 posted. See post #15 for details.

EDIT :- Version 2.2a posted with the BasicLibIDE library included. See post #17 for details.

EDIT :- Version 2.3 posted. See post #18 for details.

EDIT :- Version 2.4 posted. See post #20 for details.

EDIT :- Version 2.5 posted. See post #23 for details.

EDIT :- JesseW has posted his improved version of the IDE itself, see post #32 for details. You will still need the BasicLibIDE jar and xml from the archive in this post.

EDIT :- Version 2.6 posted. See post #47 for details.

EDIT :- Version 2.7 posted. See post #51 for details.

EDIT :- Version 2.8 posted. See post #52 for details.

EDIT :- Version 2.9 posted. See post #79 for details.

EDIT :- Version 2.91 posted. See post #87 for details.

EDIT :- Version 2.92 posted. See post #92 for details.

EDIT :- Version 2.93 posted. See post #95 for details.

EDIT :- Version 2.94 posted. See post #100 for details.

EDIT :- Version 2.95 posted. See post #118 for details.

EDIT :- Version 2.96 posted. See post #138 for details.

EDIT :- Version 2.97 posted. See post #140 for details.

EDIT :- Version 1.98 of BasicLibIDE is posted below. Use this instead of the version in BasicIDE2.97.zip. It fixes a problem with Call and CallSub.
 

Attachments

  • BasicLibIDE.jpg
    BasicLibIDE.jpg
    12 KB · Views: 30,522
  • BasicIDE2.97.zip
    118 KB · Views: 2,175
  • BasicLibIDE_1.98.zip
    44.1 KB · Views: 1,065
Last edited:

agraham

Expert
Licensed User
Longtime User
I've downloaded the archive and the right files are in it. Have you restarted the IDE or done a right-click and Refresh on the library pane after replacing the library files? The IDE caches libraries so needs to be told they have changed if you don't exit and restart.
 

JesseW

Active Member
Licensed User
Longtime User
I've downloaded the archive and the right files are in it. Have you restarted the IDE or done a right-click and Refresh on the library pane after replacing the library files? The IDE caches libraries so needs to be told they have changed if you don't exit and restart.

Yes, I've done all that. I even restarted the pc, and then cleared the cache on my browser and downloaded it again, and replaced the library files again, recompiled, and it still gives the error :(

Edit

I've been downloading the jar and xml files from the basicide thread download, not the basiclib thread download. Let me try that...
 
Last edited:

JesseW

Active Member
Licensed User
Longtime User
Still giving the error. It seems to error on the 8th level. Here is a test code

B4X:
if true then
  for I = 1 to 1
    if true then
      do
        if true then
          if true then
            if true then
              if true then   <--- errors here
              endif
            endif
          endif
        endif
      loop until true
    endif
  next
endif

I am supposed to be redownloading the archive in post 1 of THIS thread, correct?
 
Last edited:

agraham

Expert
Licensed User
Longtime User
Yes, the archive in post #1 of this thread. You haven't told me exactly what the error is but I assume it is
Error - If : stack depth exceeded, increase the StackDepth property
To make absolutely sure I've downloaded and used the archive library files and invoked a deeply nested If. I can get that error with the standard StackDepth and then cure it by increasing the StackDepth. Look carefully where you have placed your "Blib.StackDepth = whatever".
 

JesseW

Active Member
Licensed User
Longtime User
by 'patch' I thought you meant you increased the standard stackdepth. now that I uncommented the blob.stackdepth=16 line, all is well :D

thank you again, kind sir
 

JesseW

Active Member
Licensed User
Longtime User
Andrew, I just noticed Strsplit doesn't like the period as a separator. the example script will stop with an index out of bounds error even when element 0 is accessed

B4X:
 dim t(1)
a = "2,4"
strsplit(t, a, ".")
l = arraylen(t())
msgbox(t(0), l)
activityfinish

if the period is replaced with a comma, it behaves correctly.

if two periods are used, element 0 can be accessed, but element 0 is blank
 

JesseW

Active Member
Licensed User
Longtime User
I also just noticed strsplit dimensions one less array element than it should if the last element is a zero length string.

B4X:
dim t(0)
strsplit(t, ",12,", ",")
showtoast(arraylen(t), false)
activityfinish

shows two array elements instead of 3. trying to access t(2) (the third element) causes an error. hope this helps.
 

JesseW

Active Member
Licensed User
Longtime User
This is the way that the Java string split method works.

thanks for responding... were you referring to the period escaping issue or the incorrect number of array elements issue? I hope the java string split method doesn't intentionally act that way...
 

JesseW

Active Member
Licensed User
Longtime User
I was afraid of that. :(

I can't thank you enough for your assistance... ;D
 

JesseW

Active Member
Licensed User
Longtime User
I will have to examine your script.bas code to see how you handle array passing and write my own split and join routines :)
 

JesseW

Active Member
Licensed User
Longtime User
Andrew, got two questions

1. May I have your consent to take off with BasicIDE on my own and start a new project called B4Script, in honor of the scripting language it supports? You would of course receive all due and proper credit for the interpreter library and starting the original project, BasicIDE. I might at some point like to place it on the market as a 'living advertisement' for B4A. I would of course consult with you and Erel before I did so. I might even split the profits with you :D

2. I would like to implement a Chain("program.src"). It looks easy enough: Inside the b4a script.bas file, in Sub Chain, it looks like I would save the name of the chained file in a global var (this would be a flag as well, as the var would now not be zero len) and issue a blib.Halt command. In the blib_Ended event, I would check the global var and if it isn't a zero string, load the file into a string, set the var to zero len, then issue a blib.LoadCodeAsString, then a blib.Run. If I'm not mistaken, the SavedData b4a array would remain intact between programs, and would provide an excellent way to pass data between them. I see this concept as script activities, and the reason for implementation is developement is always easier when a project can be chunked up into smaller pieces. An example would be the checkbook program I'm writing for my wife would have a main script to run the checkbook itself, and utility scripts for updating the database, reconciling, etc... Just wanted to check with you and see if this seems plausible. And to avoid any pitfalls. Don't want to blow up anything...

Thank you Andrew. Much respect! :sign0188:
 

JesseW

Active Member
Licensed User
Longtime User
I don't see a way to tell the interpreter from script.bas to flag an error. Is this possible, in the case the chained program script file doesn't exist?

I can see right away, I probably don't want to call blib.run from inside the blib.ended event... But I don't see another way...

Wait. I see a way. Instead of using SavedData array in script.bas, I need an array in Main called ChainVars which I can save data to and retrieve from, chained programs, and place the chain program filename in Main as well and let script.bas activity.finish as normal, then just restart the activity from Main from within btnRun_click, except I'm not sure btnRun_click ends as soon as starting the activity, or if it waits for the activity to completely finish. grrrrrrr
 
Last edited:

JesseW

Active Member
Licensed User
Longtime User
I think I got it figured out. How's this?

Script.bas
B4X:
Sub Chain(dir As String, prg As String, argsarray As String)
   If File.Exists(dir, prg) Then
      Main.ChainFile = dir & "/" & prg
      Main.ChainVars = Blib.GetArray(argsarray)   
      Blib.Halt
   End If
End Sub

Main
B4X:
Sub Process_Globals
   ... added these two lines at the bottom
   Dim ChainFile As String
   Dim ChainVars(0) As String
End Sub
B4X:
Sub Activity_Create(FirstTime as Boolean)
   ... added this line at the bottom
   ChainFile = ""
End Sub
B4X:
Sub Activity_Resume
   edtSource.Text = SaveSource
   'this line removed to enable value to survive orientation change
   'SourceChanged = False   'moved to activity_create/firsttime by JesseW
   chkBreak.Checked = SaveBreak
   chkStep.Checked = SaveStep
   SetFont(SaveFont)
   edtSource.TextSize = SaveFontSize
   Activity.Title = SaveTitle
   svFling.ScrollPosition = svPos
   edtSource.SelectionStart = edtCursor
   If ChainFile.Length > 0 Then
      If File.Exists("/", ChainFile) Then
         Dim istream As InputStream
         Dim reader As TextReader
         Dim src As String
         istream = File.OpenInput("/", ChainFile)
         reader.Initialize(istream)
         src = reader.ReadAll
         src = src.Replace(Chr(BOM), "") ' remove BOM if present in case file is from Windows
         src = src.Replace(Chr(13), "") ' remove CR in case file is from Windows
         Script.Program = src
         Script.FirstRunFlag = True
         ChainFile = ""
         StartActivity("Script")
      End If
   End If
End Sub

That's all the modifications. It makes sense, and I think it'll run, although I haven't tried it yet. Waiting on your response.

I also have a question: in the docs for BasicLibIDE, it says
Run (args() As String) As Boolean

args is an array that may be used to pass arguments to the program to be run.
... but I can find no mention of how that arg() array is caught, accessed or used. Is it used internally, or is that a mechanism I can use to pass the ChainArgs() array to? If so, how would I access it and/or assign it to a blib array for the chained program to use? I still haven't decided how to get the ChainArgs() array to the chained program, and that would be a really sweet way to get it there if possible.

Thank you one more time, sir :)
Jesse

Edit:
Well, I tried it, and the chained file does exist, but it doesn't run as expected. Will work more on it tomorrow...
 
Last edited:

agraham

Expert
Licensed User
Longtime User
1. May I have your consent to ...
Feel free to do whatever you want.
2. .... Main from within btnRun_click, except I'm not sure btnRun_click ends as soon as starting the activity, or if it waits for the activity to completely finish
Yes, btnRun_click has to run to completion and return to the message loop before the Main activity is paused and the Script activity started. BasicIDE is single threaded and everything runs on the application main thread. You will have to do your chaining in Main to avoid possible re-entrancy problems but it should be readily achievable using Process_Globals to maintain state.
.. but I can find no mention of how that arg() array is caught, accessed or used.
It's in B4ScriptHelp under "Programming".

"There is a pre-defined global array, Args(), that contains an argument array passed to the script at runtime."

If there are no passed arguments it is an array of length 1 containing a single empty string. This is to avoid a runtime error when checking if any arguments have been passed. However there is (yet another :() arraylen() problem with args() as the initialisation routine doesn't set the true array length of args in its variable descriptor so it always looks like a length of one. I'll fix that soon but in the meantime you can actually still access all the elements of args as long as you know how long it is so you don't index past the end.

By this time you might be wondering why arraylen() doesn't just look at the array to get the length - the reason is the way that multi-dimensional arrays are implemented in the interpreter. They are synthesised from a single dimension array and the length of each rank of the array is stored in a variable descriptor. This is (sort of) mentioned in B4ScriptHelp under "Variables".
 
Last edited:

JesseW

Active Member
Licensed User
Longtime User
Andrew, got a kink I can't seem to work past. I've uploaded what I've got so far.

It all starts at script.chain() sub. In a nutshell, script.chain() sets main.chainscript to the filename of the program to chain to, and main.chainargs to the args passed. It then calls blib.halt and activity.finish, then exits. Then main.activity_resume catches control and if there is a filename in main.chainscript, it loads and processes it and stores it in script.chainprogram, and sets script.args to the array that was passed to main.chainargs. The next step is calling startactivity("script"), (this is where it fails...) and exit. Then, as described below, if I am stepping through all this, it acts correctly and script.activity_create catches control. It looks for chainprogram having a zero length. If it's not an empty string, it sets the program var from the contents of chainprogram (which was set to the source code of the chained program from main.activity_resume), clears both chainprogram and main.chainscript and exits the conditional block. Control then follows the normal route of loading the code from the program var and running it.

But... activity script never comes back up. The display seems to blink instantly, then the main activity comes back up. But heres the thing: If i'm in debug mode, stepping through main.activity_resume, it works! every time... But not in debug or release mode if it is 'running' instead of 'stepping'. Here's another observation... If I press my devices HOME button, then start B4Script again, it goes right into the script activity as if it's been there the whole time, but just never took focus... I added a log entry just above the startactivity statement, just so I'd know it was making it that far. The last log entry might tell you something, but since there's no error number, I'm lost...

Here are the log entries
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.warsoftapps.b4script/.main bnds=[437,336][535,455] } from pid 808
Unable to create files directory
** Activity (main) Create, isFirst = false **
** Activity (main) Resume **
Displayed com.warsoftapps.b4script/.main: +365ms
Window already focused, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@40976388
Starting: Intent { flg=0x20000 cmp=com.warsoftapps.b4script/.script } from pid 17057
** Activity (main) Pause, UserClosed = false **
** Activity (script) Create, isFirst = true **
Displayed com.warsoftapps.b4script/.script: +466ms
** Activity (script) Resume **
** Activity (script) Pause, UserClosed = true **
Client not active, ignoring focus gain of: com.android.internal.view.IInputMethodClient$Stub$Proxy@4064e988
** Activity (main) Resume **
Attempting to start activity Script for chaining
Starting: Intent { flg=0x20000 cmp=com.warsoftapps.b4script/.script } from pid 17057
Got RemoteException sending setActive(false) notification to pid 16904 uid 10157

I'm pulling my hair out trying to get this 'dance' to go right.

Help???

ps. You may notice from the uploaded project that I'm still on v2.8. I wasn't going to upgrade to 2.9 until I got this all worked out.

ps. here are the scripts I'm testing this with:

prg1.src
B4X:
msgbox("chaining to prg2", "prg1")
chain(filedirrootexternal & "/B4Script", "prg2.src", "")
msgbox("sorry, didn't make it
prg2.src
B4X:
setactivitytitle("prg2")
msgbox("made it!", "prg2")
msgbox(arraylen(args), "")

appreciate you help. again >blush<
 

Attachments

  • B4Script.zip
    53.5 KB · Views: 214
Top