[Solved -Workaround] How to disable the BASIC Compile stage?

The Application Programming Interface and the OASIS Open Document Format

[Solved -Workaround] How to disable the BASIC Compile stage?

Postby irs » Sat Jul 27, 2013 4:02 am

How to disable the BASIC Compile stage, or modify the Compile stage so that errors it detects do not the halt program flow?

A BASIC script is used to create a new module that contains a BASIC subroutine, and the original BASIC script then makes a Call to execute the code in this newly created subroutine.

The Call to the newly created code appears to be subjected first to a “Compile” phase and then to the “Run” phase.

If errors (e.g. parentheses do not match, or divide by zero) are detected during the “run” stage then, through the use of “on local error goto...” error handler, the code can recover from the error and code execution can continue.

If errors are detected during the “compile” stage, then these are non-recoverable and code execution is halted. The syntax error must be manually corrected and the program re-started.

Is there a way to set the “compile” stage to report the errors that it detects in a way that is recoverable through an error handler?

I am also wondering if there might be some sort of OpenOffice global parameters that can be set to adjust the way the compile phase is performed?

Perhaps there is a way to turn off the compile phase so that there is only the Run phase?

I am creating a “formula calculator and plotter” for school students. The idea is that they create their own equations, and then submit the equations to calculate plotting points that are then used to draw a curve. I create a new module to execute the code that includes the equation the student created. If the equations syntax is OK then I have no problems. If the equation has a syntax error, then the compile phase halts the program with an unrecoverable error. I want to be able to evaluate the equation and if it has a syntax error then I want the program to recover and warn the student to re-enter the equation, but with the correct syntax.

I appreciate all ideas and alternative options on how to get this self modifying style of code working.

thanks, ian.
Attachments
Demo of Compile and Runtime Error.odt
Attached is a Writer doc that has two buttons that run code in module1. One button creates module2 with a subroutine that will fail during compile with a non-recoverable error. The other button creates module3 with a subroutine that will pass the compile phase, but fail with an error that can be recovered from during the run-time phase.
(15.36 KiB) Downloaded 221 times
Last edited by irs on Wed Aug 07, 2013 3:57 am, edited 1 time in total.
OpenOffice 4.0 on ubuntu and winxp
irs
 
Posts: 9
Joined: Fri Jul 26, 2013 1:37 pm

Re: How to disable the BASIC Compile stage?

Postby Villeroy » Sat Jul 27, 2013 8:18 am

This would be the perfect use case for an object oriented programming language where you can instanciate multiple instances of the very same module (class).

In Basic terms that would be a class module "MyClass" with:
Code: Select all   Expand viewCollapse view
obj1 = MyClass
obj2 = MyClass
obj3 = MyClass

obj1.PropertyA = 1
obj2.PropertyA = 2
obj3.PropertyA = 3

x1 = obj1.someFunction(1,2,3)
x2 = obj2.someFunction(3,2,1)
x3 = obj3.someFunction(4,5,6)


Any macro language other than stupid Basic works like this.

For educational purposes in the 21st century you must not use any kind of Basic lingo.
Edsger W. Dijkstra wrote:It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.

http://en.wikiquote.org/wiki/Edsger_W._Dijkstra
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04, no OpenOffice, LibreOffice 6.4
User avatar
Villeroy
Volunteer
 
Posts: 28451
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: How to disable the BASIC Compile stage?

Postby irs » Sun Jul 28, 2013 2:42 am

Hi Villeroy, Many thanks for your response.

I'd like to provide some more background. The Students have computers at home that are either Windows, Mac, or Linux based systems. The Students install the appropriate flavour of OpenOffice on their computer. The Teacher has a Draw document which includes an embedded BASIC program that launches a dialog window. In a control of the dialog window the student creates equations, which are then plotted as a curve on a grid on a Draw document sheet. The objective is for the Student to learn about mathematical equations. The Student is not learning how to write programs in BASIC, and should not need to access the BASIC IDE or even need to know it exists. ...so Mr. Dijkstra can rest in peace as I'm not about to corrupt young minds beyond repair ;)

The main features of using Basic in an OpenOffice document is that the Teacher can distribute one Draw document to all students and know that:

1. The embedded BASIC script will work on all students computers irrespective of their computers OS platform.
2. There is no other dependency software required to be loaded onto the Students computer (apart from OpenOffice).
3. There is no dependency on the computer being connected to the internet.
4. OpenOffice is legally free for the students.
5. While OpenOffice, as a dependency, is necessary to provide the functionality for the program that the Teacher supplied, it also has the bonus of providing the Student with an office suite of applications.

In summary it keeps things simple for the Students, the Teacher, and the process of the Teacher distributing the program to the Students.

There are many aspects of the BASIC IDE that are not ideal, but if I want a solution to meet these above features then I don't think I have much choice. You stated, "This would be the perfect use case for an object oriented programming language". Perhaps I could embed Python script in the Draw document, however it then becomes an overhead of being required to do a dependency check and ensure that all the Students systems have a version of a Python interpreter installed that is compatible with the Python script embedded in the Draw document, etc.

In theory I could write, in BASIC, a script syntax checker that is the equivalent of the BASIC IDE compile syntax checker. This would ensure that when a student generates an equation, then, if it passes my syntax checking, it will pass BASIC's compile checker. However I would prefer to use the syntax checker that already exists with AOO BASIC. What I don't know is how to pass an equation as a string to the BASIC compile syntax checker in a way that I can recover should an error be detected.

I was hoping there might be some OpenOffice API method, like "IsSyntaxOK", and I would be able to write code something like this...

sub Get_Equation_And_Check_Syntax()
dim x as double
dim y as double
x = 1

stringEquation = InputBox ("y = ", "Enter an Equation for x:")
stringEquation = “y = “ & stringEquation

BooleanReturn = BasicLibraries.Compile.IsSyntaxOK( stringEquation )
if BooleanReturn then
... create a new module that includes a subroutine with the equation and execute it, etc.
else
... Send message to the User that the equations syntax is incorrect and can not be processed.
endif
end sub

I've looked at the BASIC code example that you provided, but I cant understand how I could apply that code such that it gets around BASIC's compile phase apparently being mandatory and its error detection always forcing a halt.

regards, ian.
OpenOffice 4.0 on ubuntu and winxp
irs
 
Posts: 9
Joined: Fri Jul 26, 2013 1:37 pm

Re: How to disable the BASIC Compile stage?

Postby Villeroy » Sun Jul 28, 2013 11:28 am

What you are doing here looks so incredible ugly, clumsy and obscure that you must not expect that anybody will delve into this solution.

This might be the platform independend tool of choice: http://www.r-project.org/
Please, edit this topic's initial post and add "[Solved]" to the subject line if your problem has been solved.
Ubuntu 18.04, no OpenOffice, LibreOffice 6.4
User avatar
Villeroy
Volunteer
 
Posts: 28451
Joined: Mon Oct 08, 2007 1:35 am
Location: Germany

Re: How to disable the BASIC Compile stage?

Postby JPL » Tue Jul 30, 2013 1:16 pm

Villeroy wrote:
This would be the perfect use case for an object oriented programming language where you can instanciate multiple instances of the very same module (class).
For educational purposes in the 21st century you must not use any kind of Basic lingo.
Edsger W. Dijkstra wrote:
It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.


Mr. Dijkstra was right when he made above statement, but it was in 1984.
While c++ as a complete object-oriented language emerged only in the nineties !

By the way StarBasic has also in certain aspects object-oriented characteristics: please read [Basic] Object-oriented programming.

irs wrote:
I was hoping there might be some OpenOffice API method, like "IsSyntaxOK", ...


There is no such API available.

What you need is provided by VBA.
The
Code: Select all   Expand viewCollapse view
Eval()

function evaluates as a Basic expression the string given as argument and returns its value.
This function is however not available today in StarBasic :(

JPL
KUbuntu 18.04 / LibO 6.4
Access2Base (LibO).
BaseDocumenter extension (LibO)
Documentation on http://www.access2base.com and http://www.access2base.com/basedocumenter
JPL
Volunteer
 
Posts: 107
Joined: Fri Mar 30, 2012 3:14 pm

Re: How to disable the BASIC Compile stage?

Postby irs » Tue Aug 06, 2013 11:11 am

JPL, many thanks for your post highlighting that what I needed was an Eval() function. Its a pity that its not currently available in StarBasic.

As a workaround, I have implemented something similar to "Eval()", which I believe is somewhat less "ugly, clumsy and obscure" than my initial approach...

I am using the Draw application, so I was able to perform object linking and embedding (OLE) of the Calc spreadsheet into a Draw page. I then make use of a spreadsheet Cell and pass a formula to it as a string variable. The formula executes and supplies a result. If there is a problem with the formula (e.g. syntax error, divide by zero error, etc.) then it supplies an error message to the Cell. The error is non-fatal to BASIC's execution flow and can be detected with a .getError() check.

I have attached a Draw document with a BASIC macro example.

regards, ian.
Attachments
Draw Example - Submit equation to OLE Calc cell.odg
BASIC macro that creates an OLE of Calc and then uses a Calc cell to send equations to and retrieve the results (or errors) from.
(14.29 KiB) Downloaded 150 times
OpenOffice 4.0 on ubuntu and winxp
irs
 
Posts: 9
Joined: Fri Jul 26, 2013 1:37 pm

Re: How to disable the BASIC Compile stage?

Postby irs » Wed Aug 07, 2013 3:45 am

To summarize this thread...
In BASIC, while a string variable is suitable for data, it is not suitable for passing formulas for execution.

This works...
Code: Select all   Expand viewCollapse view
sub CircleArea1
   dim r as integer

   for r = 1 to 10
      msgbox ( PI * r^2 )
   next r
end sub


This doesn't work. The formula does not get executed.
Code: Select all   Expand viewCollapse view
sub CircleArea2
   dim r as integer
   dim strFormula as string
   strFormula = "PI * r ^2"
   
   for r = 1 to 10
      msgbox ( strFormula )
   next r
end sub


The “self-modifying code” approach...
In OO, BASIC can access the API to insert, replace and remove modules of BASIC script. This allows a string variable that contains a mathematical formula to be used as part of the creation of a new module, such that when the module is called, it compiles and runs and executes the formula that was supplied as a string variable.

An issue with this approach is that if there are any errors in the formula that result in a failure during the compile phase, then these errors are fatal and the flow of the BASIC program terminates. The formula in the new module must be manually corrected to resume BASIC program flow, or the new module must be manually deleted.

This forum thread was a request for a method of turning off the error checking performed by the compile phase.

From looking at source c++ code in sb.cxx ...
https://svn.apache.org/repos/asf/openof ... ses/sb.cxx
...the following appears to be the code for when an error during the compile forces a stop...

Code: Select all   Expand viewCollapse view
sal_Bool StarBASIC::CError
   ( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 )
{
   vos::OGuard aSolarGuard( Application::GetSolarMutex() );

   // Compiler-Fehler waehrend der Laufzeit -> Programm anhalten
   if( IsRunning() )
   {
      // #109018 Check if running Basic is affected
      StarBASIC* pStartedBasic = pINST->GetBasic();
      if( pStartedBasic != this )
         return sal_False;

      Stop();
   }


Looking at other parts of the source code. e.g runtime.cxx....
https://svn.apache.org/repos/asf/openof ... untime.cxx
...the constant “SbDEBUG_CONTINUE” is defined. Possibly there is debug code that may over-ride the compile stop, but I have not worked out how to get BASIC to call an API that would invoke this debug code. Until this can be resolved, using a program to create new modules and then executing their code is not recommended.

(As an aside: Writing BASIC code that generates a new module containing code is quite a fun exercise. You get lots of practice in putting the right number of double quotes in the right place :D The methods available for manipulating the BasicLibraries scripts created modules are: insertByName, replaceByName and removeByName. I observed that the “insert” works as expected. The “remove” does remove the module, but then exits its subroutine and does not execute any code that follows the line of code with the “remove” in it. The “replace” does replace OK, but the replacement code is not observed in the IDE window. You need to save and reload the document to observe the new module containing the latest replacement of the code in the IDE window.)

The eval() approach...
JPT posted that in VBA there is a function “eval()” which is used to evaluate a string variable that contains a mathematical formula, and, if computable, will return the mathematical result. Unfortunately this function is not currently available in StarBasic.


The Embedded Calc approach...
As mentioned in the post above and observable in its sample code, a Draw or Impress document using embedded Calc can be passed a string variable containing a mathematical formula. If it is computable then the result will be obtained. If the formula contains an error, then the error is reported without interruption to the program flow.

I will update this thread to indicate it is resolved through a workaround.

My thanks to Villeroy and JPT for their postings.
regards, ian.
OpenOffice 4.0 on ubuntu and winxp
irs
 
Posts: 9
Joined: Fri Jul 26, 2013 1:37 pm

Re: [Solved -Workaround] How to disable the BASIC Compile st

Postby hanya » Wed Aug 07, 2013 5:41 am

To use strange behavior:
Code: Select all   Expand viewCollapse view
Const LIBRARY = "Test"
Const MODULE = "Module1"

Sub Test
  doc = ThisComponent
  libs = doc.BasicLibraries
  libs.loadLibrary(LIBRARY)
  if not libs.hasByName(LIBRARY) then libs.createLibrary(LIBRARY)
  tlib = libs.getByName(LIBRARY)
 
  lf = chr(10)
  s = _
"Function Foo() As String" & lf & _
"  On Error GoTo Handler" & lf & _
"  a = 0" & lf & _
"  b = 2/a" & lf & _
"  msgbox a" & lf & _
"  Foo = ""OK""" & lf & _
"  Exit Function" & lf & _
"  Handler:" & lf & _
"  Foo = ""ERROR: "" & Error & chr(10) & ""at line "" & Erl" & lf & _
"End Function"

  if tlib.hasByName(MODULE) then tlib.removeByName(MODULE)
  tlib.insertByName(MODULE, s)
 
  script = doc.getScriptProvider().getScript(_
    "vnd.sun.star.script:" & LIBRARY & "." & MODULE & ".Foo" & _
    "?location=document&language=Basic")
  r = script.invoke(Array(), Array(), Array())
  if r = "" then
    msgbox "Syntax error"
  elseif mid(r, 1, 5) = "ERROR" then
    msgbox r
  end if
End Sub

Please, edit this thread's initial post and add "[Solved]" to the subject line if your problem has been solved.
Apache OpenOffice 4-dev on Xubuntu 14.04
hanya
Volunteer
 
Posts: 885
Joined: Fri Nov 23, 2007 9:27 am
Location: Japan

Re: [Solved -Workaround] How to disable the BASIC Compile st

Postby irs » Sat Aug 10, 2013 2:45 am

Hanya. Interesting to see that if I change the "b = 2/a" to "b = 2/0", then I get the "Syntax Error" message that you coded and I do not get the message, "Inadmissible value of data type. Division by zero". However if I then save the application and reload it then the compiler flags the "inadmissible" error. If someone is planning to use this sort of code, then it would pay to have error handling to remove the module if a syntax error is detected.

One of the "strange behaviour" issues is that on some versions of OpenOffice (including V4.0), every second time that I run your sample code it doesn't work. This is due to a bug in the "removeByName" method. After performing the removal of the module, it halts continuation of the program flow.

Here's a version of your sample code with some warning messages around the point of failure...
Code: Select all   Expand viewCollapse view
Const LIBRARY = "Test"
Const MODULE = "Module1"

Sub Test_with_removeByName_warning()
  dim booHasModule as boolean
  doc = ThisComponent
  libs = doc.BasicLibraries
  'libs.loadLibrary(LIBRARY)
  if not libs.hasByName(LIBRARY) then libs.createLibrary(LIBRARY)
  tlib = libs.getByName(LIBRARY)

  lf = chr(10)
  s = _
"Function Foo() As String" & lf & _
"  On Error GoTo Handler" & lf & _
"  a = 0" & lf & _
"  b = 2/a" & lf & _
"  msgbox a" & lf & _
"  Foo = ""OK""" & lf & _
"  Exit Function" & lf & _
"  Handler:" & lf & _
"  Foo = ""ERROR: "" & Error & chr(10) & ""at line "" & Erl" & lf & _
"End Function"

  boohasModule = tlib.hasByName(MODULE)
  if booHasModule then
    msgbox "The next line of code will execute a removeByName(), and remove the module:  " & _
      MODULE & chr(10) & _
      "On some versons of OpenOffice, after performing the removal of the module, the program flow "&_
      "will exit the subroutine."
  end if

  if tlib.hasByName(MODULE) then tlib.removeByName(MODULE)

  if booHasModule then
    msgbox "If you recieve this message then the removeByName() executed without halting and program " &_
      "flow continued. However in the IDE window you may still see the module. Click OK to continue..."
  end if

  tlib.insertByName(MODULE, s)
  script = doc.getScriptProvider().getScript(_
    "vnd.sun.star.script:" & LIBRARY & "." & MODULE & ".Foo" & _
    "?location=document&language=Basic")
  r = script.invoke(Array(), Array(), Array())
  if r = "" then
    msgbox "Syntax error"
  elseif mid(r, 1, 5) = "ERROR" then
    msgbox r
  end if
End Sub

...I've found this problem occurs on OpenOffice V4.0.0 (and recent versions of LibreOffice). However using OpenOffice V3.2.1 the program flow continues OK after the removeByName(). However in the V3.2.1 case the IDE does not reflect the Module as having been removed.

An alternative to your sample code is to use replaceByName() instead of removeByName().
Code: Select all   Expand viewCollapse view
Const LIBRARY = "Test"
Const MODULE = "Module1"

Sub Test_with_replacebyName
  doc = ThisComponent
  libs = doc.BasicLibraries
  'libs.loadLibrary(LIBRARY)
  if not libs.hasByName(LIBRARY) then libs.createLibrary(LIBRARY)
  tlib = libs.getByName(LIBRARY)

  lf = chr(10)
  s = _
"Function Foo() As String" & lf & _
"  On Error GoTo Handler" & lf & _
"  a = 0" & lf & _
"  b = 2/a" & lf & _
"  msgbox a" & lf & _
"  Foo = ""OK""" & lf & _
"  Exit Function" & lf & _
"  Handler:" & lf & _
"  Foo = ""ERROR: "" & Error & chr(10) & ""at line "" & Erl" & lf & _
"End Function"
   
  if tlib.hasByName(MODULE) then
    tlib.replaceByName(MODULE, s)
  else
    tlib.insertByName(MODULE, s)
  end if
 
  script = doc.getScriptProvider().getScript(_
    "vnd.sun.star.script:" & LIBRARY & "." & MODULE & ".Foo" & _
    "?location=document&language=Basic")
  r = script.invoke(Array(), Array(), Array())
  if r = "" then
    msgbox "Syntax error"
  elseif mid(r, 1, 5) = "ERROR" then
    msgbox r
  end if
End Sub


...however replaceByName() has a bug, in that, while the module executes its replacement code (from cache), the IDE continues to display the original code.

I initially noticed these two bugs when using LibreOffice and reported them as...
https://bugs.freedesktop.org/show_bug.cgi?id=67116
https://bugs.freedesktop.org/show_bug.cgi?id=67118

Should I also report these bugs with OpenOffice?

regards, ian.
OpenOffice 4.0 on ubuntu and winxp
irs
 
Posts: 9
Joined: Fri Jul 26, 2013 1:37 pm


Return to UNO API and ODF

Who is online

Users browsing this forum: No registered users and 1 guest