hippy
Posts: 5335
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: ScriptBasic

Mon May 13, 2019 3:31 pm

ScriptBasic wrote:
Mon May 13, 2019 12:52 pm
Once you use GOTO to exit a stack controlled structure, jumping back into the 'expired' structure would cause a stack error.
I would say that if you can't jump out of a FOR-NEXT and then jump back into it, or jump into it while bypassing the FOR, you have a 'design flaw' in the sense that you aren't allowing the things which you permit to be done.

If you're going to permit it you ought to support the doing of it.

This below may be a horrible, horrible mess, but there's no reason to not allow it if you've embraced GOTO and spaghetti coding, and, if you are going to allow it, IMO you owe the programmer an obligation of doing what they want done.

Code: Select all

Start:
  var = 10
  Goto JumpIn

MyLoop:
  For var = 0 To 20
  Goto Adjust  
JumpIn:
    Print var
  Next
  Goto Start

Adjust:
  var = var + 2
  Goto JumpIn
The only reason that wouldn't work is if you have taken a decision to implement things in a way which means it cannot work and I would say that's an implementation done in the wrong way. It should be done some other way.

If you give an error on the "Goto JumpIn" commands at compile time I would accept that as fair enough. But if you don't then you are failing to deliver what a programmer would expect to be delivered. You are creating an ambiguous ' you can do that, and I'm not going to complain if you do, but I'm not going to allow it to work when you run it'.

The programmer shouldn't have to guess what implementation decisions you took which prevent things working.

Bottom line is, IMO, if you are going to allow GOTO you shouldn't introduce stack controlled structures, you need to find a way to do it without a stack. If you are going to use stack structures then things which patently or obviously break that stack shouldn't be allowed to get through compilation.

Now I do agree it's a viewpoint issue. Some may say it's okay to let that through and have it crash as much as it is to let 'var=var/0' through and let that crash; it's the programmer's fault for getting it wrong. But I see compilers as there to save programmers from themselves, not leave them to be surprised when code passes syntax checking and then fails at run-time when the compiler knows it would, or should know that.

Heater
Posts: 12629
Joined: Tue Jul 17, 2012 3:02 pm

Re: ScriptBasic

Mon May 13, 2019 3:47 pm

I'm confused as well.

From a BASIC language semantics perspective a FOR loop (or any loop) is not something that uses a stack. Unlike subroutines/functions/procedures. As such one should be able to GOTO out of a loop and GOTO back into it however one likes.

One would expect a BASIC dialect to support code like hippy's example so as to be somewhat compatible with all the other BASICs.

I'm still not clear what ScriptBasic will do in t his case.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 4:19 pm

I rarely use GOTO in code I write. Where it does come into play is when I port retro BASIC code. As mentioned in my previous post, ScriptBasic GOTO also maintains the stack if used in a structure that uses it.

Line numbers, GOTO, GOSUB, LET and using $ to indicate strings or their functions is retro syntax support.
Last edited by ScriptBasic on Mon May 13, 2019 4:27 pm, edited 1 time in total.

jalih
Posts: 60
Joined: Mon Apr 15, 2019 3:54 pm

Re: ScriptBasic

Mon May 13, 2019 4:26 pm

hippy wrote:
Mon May 13, 2019 3:31 pm
This below may be a horrible, horrible mess, but there's no reason to not allow it if you've embraced GOTO and spaghetti coding, and, if you are going to allow it, IMO you owe the programmer an obligation of doing what they want done.
You are right, it's a horrible mess... :shock:

I really hope, there exist no compiler or interpreter that allows code like that. Even PL/I compiler with support for labels, label variables and label arrays disallow it:

Code: Select all

5724-B67 IBM(R) PL/I for Windows   6.0
Copyright (C) IBM Corporation 1996,2005
Licensed Material - Property of IBM. All rights reserved.

C:\temp\g.pli(10:1) : IBM1847I S GOTO target is inside a (different) DO loop.
C:\temp\g.pli(20:1) : IBM1847I S GOTO target is inside a (different) DO loop.

User avatar
RichardRussell
Posts: 501
Joined: Thu Jun 21, 2012 10:48 am

Re: ScriptBasic

Mon May 13, 2019 4:59 pm

hippy wrote:
Mon May 13, 2019 3:31 pm
This below may be a horrible, horrible mess, but there's no reason to not allow it if you've embraced GOTO and spaghetti coding
BBC BASIC doesn't like it (after necessary changes to suit the dialect) because it encounters a NEXT without ever having seen a FOR and doesn't know what to do. As a result it throws a 'Not in a FOR loop' error at the NEXT statement.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 5:03 pm

As a result it throws a 'Not in a FOR loop' error at the NEXT statement.
I would assume something similar if executing a RETURN and never using GOSUB.

User avatar
RichardRussell
Posts: 501
Joined: Thu Jun 21, 2012 10:48 am

Re: ScriptBasic

Mon May 13, 2019 5:10 pm

Heater wrote:
Mon May 13, 2019 3:47 pm
From a BASIC language semantics perspective a FOR loop (or any loop) is not something that uses a stack.
Both BBC BASIC and Liberty BASIC do use a stack for loops, in order to support nesting and use in a recursive function. I thought that was common in the case of interpreted BASICs.

hippy
Posts: 5335
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: ScriptBasic

Mon May 13, 2019 5:13 pm

jalih wrote:
Mon May 13, 2019 4:26 pm
I really hope, there exist no compiler or interpreter that allows code like that.
There is. And more than one. And to be honest; if that's what the programmer wants to do then why shouldn't they be allowed to do it ?

It's not how I would do it, not how I'd recommend anyone to do it, but if that's how they want to do it, and it's functionally valid, syntactically and semantically valid, in the language they have chosen, then why should it not be allowed or not run or not do as that programmer expects ?

But you have hit on an issue which is quite important. Is a compiler or interpreter there to facilitate whatever a programmer chooses to do in their language of choice, or is it there to implement a language defined by the compiler designer to which a programmer must be compliant ?

Both are acceptable approaches. The problem arises when a compiler or interpreter is the second but gives the impression it is the first. In the context of GOTO here, where what the compiler implements and allows is not the same as the programmer expects to be allowed.

A programmer writing the above horrible mess would rightly argue that their code for a GOTO-supporting language which allows spaghetti code is entirely valid and should be executed as it is written and deliver the results as would be expected. It doesn't matter that anyone thinks it's horrible, a mess, it is valid and should be treated as such.

And IMO they would not be wrong.

So, if it doesn't work, it's not the programmer who is wrong, but any compiler which claims to implement that language but doesn't which is wrong.

User avatar
RichardRussell
Posts: 501
Joined: Thu Jun 21, 2012 10:48 am

Re: ScriptBasic

Mon May 13, 2019 5:19 pm

hippy wrote:
Mon May 13, 2019 3:31 pm
If you give an error on the "Goto JumpIn" commands at compile time
What is this "compile time" of which you speak?! I thought ScriptBasic was interpreted, like BBC BASIC.

Heater
Posts: 12629
Joined: Tue Jul 17, 2012 3:02 pm

Re: ScriptBasic

Mon May 13, 2019 5:27 pm

Horrible mess or not this is fun...

There is such a BASIC that runs hippy's code as is, the FreeBASIC compiler with the "-lang qb" option. So I guess QuickBASIC does as well.

It's also rather elegant to do that kind of thing in C:

Code: Select all

int main (int argc, char* argv[]) {
        int i = 0;

        for (i = 0; i < 10; i++) {
                goto out;
in:
                printf("I'm in! %d\n", i);
        }

out:
        printf("I'm out! %d\n", i);
        goto in;

        return 0;
}
Mind you, it does not execute quite the way you might expect!

RichardRussell,
Both BBC BASIC and Liberty BASIC do use a stack for loops, in order to support nesting and use in a recursive function. I thought that was common in the case of interpreted BASICs.
Interesting. There is nothing about the "loop" concept that requires a stack. Even when nesting loops inside each other.

I'm guessing a stack becomes useful if the blocks inside the loops define new scopes. Which is a whole different language feature.

Seems the BASIC guys go out of their way to be incompatible with each other :)

User avatar
RichardRussell
Posts: 501
Joined: Thu Jun 21, 2012 10:48 am

Re: ScriptBasic

Mon May 13, 2019 5:40 pm

Heater wrote:
Mon May 13, 2019 5:27 pm
Interesting. There is nothing about the "loop" concept that requires a stack. Even when nesting loops inside each other.
It seems to me that avoiding a stack would require static (lexical) analysis, which BBC BASIC certainly doesn't do and I would not expect other 'pure' interpreters to do because it implies preprocessing. Specifically, when the interpreter encounters a NEXT it needs to jump back to the FOR (if the loop hasn't completed) and it only knows where the FOR is because that information was stored on the stack when it was executed.

Without a stack how does it know where to jump to, unless some pre-processing step has performed lexical analysis and recorded the location of the FOR in some database? That would work, but it's not what I would call a traditional interpreter, more a kind of hybrid.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 5:40 pm

What is this "compile time" of which you speak?! I thought ScriptBasic was interpreted, like BBC BASIC.
ScriptBasic is an interpreter. Before the code is run ScriptBasic checks syntax and then tokenizes (PCode compiles) the text source before running., You can eliminate the tokenizing step by saving the code in its binary form and running it directly. The difference in execution is so minimal it's not worth the effort during development but does come in handy when distributing your code commercially as closed source.

hippy
Posts: 5335
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: ScriptBasic

Mon May 13, 2019 5:48 pm

RichardRussell wrote:
Mon May 13, 2019 4:59 pm
hippy wrote:
Mon May 13, 2019 3:31 pm
This below may be a horrible, horrible mess, but there's no reason to not allow it if you've embraced GOTO and spaghetti coding
BBC BASIC doesn't like it (after necessary changes to suit the dialect) because it encounters a NEXT without ever having seen a FOR and doesn't know what to do. As a result it throws a 'Not in a FOR loop' error at the NEXT statement.
That isn't unreasonable. The Basic which I know tracks FOR-NEXT and other loop nesting so takes it that the NEXT relates to the FOR earlier.

Some languages might allow this, others not -

Code: Select all

If flag > 0 Then
  For count = 10 To 20 Step 1
Else
  For count = 10 To 0 Step -1
End If
Print count
Next
Note I'm not arguing that any language should. I would expect most languages to reject that for one reason or another. Though it wouldn't surprise me if something very much like it could be created with lambda's in Python.

However it is done, a NEXT needs to know which FOR it relates to, a WEND needs to know which WHILE, etc. A lot depends on whether that's determined through nesting at compile time or through pointers and/or stacks at run-time, and whether one has a single stack or separate, stacks for FOR-NEXT, WHILE-WEND, REPEAT-UNTIL, GOSUB-RETURN, and other things, affects things.

How it is will greatly affect what is allowed and what isn't.

Heater
Posts: 12629
Joined: Tue Jul 17, 2012 3:02 pm

Re: ScriptBasic

Mon May 13, 2019 5:54 pm

RichardRussell,
, when the interpreter encounters a NEXT it needs to jump back to the FOR (if the loop hasn't completed) and it only knows where the FOR is because that information was stored on the stack
Good point. I'll buy that. Actually I start to think that I did that in my toy compiler years ago. ... I must get back to that sometime...

As it happens neither hippy's BASIC example or my C version actually terminate. The C one runs forever counting up the "i". Clearly that "i" as used as the loop counter is not where one might think...

hippy
Posts: 5335
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: ScriptBasic

Mon May 13, 2019 6:04 pm

RichardRussell wrote:
Mon May 13, 2019 5:40 pm
It seems to me that avoiding a stack would require static (lexical) analysis, which BBC BASIC certainly doesn't do and I would not expect other 'pure' interpreters to do because it implies preprocessing.
You're right.

BBC-style basics tokenise but don't care what a program is, have to figure it all out during run time interpretation.

ScriptBasic-style basics compile to tokens which are then interpreted but some aspects of the program can be determined during linear compilation which can affect what tokens are generated.

Bottom-line is they aren't the same kind of interpreters. The later are really compilers for a virtual instruction set which it then executes in its own VM. The full range of code generation tools available to a compiler are available to ScriptBasic-style basics if they choose to use them.

The question perhaps is, how faithfully a compiled basic should follow what a purely interpreted basic would do.
Last edited by hippy on Mon May 13, 2019 6:09 pm, edited 1 time in total.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 6:07 pm

Code: Select all

If flag <> undef Then
  For count = 10 To 20 Step 1
Else
  For count = 10 To 0 Step -1
End If
Print count
Next
Output

Code: Select all

[email protected]:~/sb/examples/test$ scriba ifor.sb
ifor.sb(3): error &H74:erroneous nesting of constructs like IF/ELSIF/ELSE/ENDIF/REPEAT/LOOP/WHILE and so on
ifor.sb(5): error &H74:erroneous nesting of constructs like IF/ELSIF/ELSE/ENDIF/REPEAT/LOOP/WHILE and so on
ifor.sb(7): error &H74:erroneous nesting of constructs like IF/ELSIF/ELSE/ENDIF/REPEAT/LOOP/WHILE and so on
(0): error &H75:nested construct remained unclosed when local_end
[email protected]:~/sb/examples/test$ 

User avatar
PeterO
Posts: 4727
Joined: Sun Jul 22, 2012 4:14 pm

Re: ScriptBasic

Mon May 13, 2019 6:18 pm

Heater wrote:
Mon May 13, 2019 5:54 pm
hippy's BASIC example or my C version actually terminate. The C one runs forever counting up the "i". Clearly that "i" as used as the loop counter is not where one might think...
Try

Code: Select all

gcc -fverbose-asm -S loopjump.c 
then you'll see why it does what it does !
PeterO
PS: I did that on a X86-64 machine as I'm not familiar with ARM assembler.
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
RichardRussell
Posts: 501
Joined: Thu Jun 21, 2012 10:48 am

Re: ScriptBasic

Mon May 13, 2019 6:22 pm

ScriptBasic wrote:
Mon May 13, 2019 6:07 pm

Code: Select all

If flag <> undef Then
  For count = 10 To 20 Step 1
Else
  For count = 10 To 0 Step -1
End If
Print count
Next
Although code like that would execute in BBC BASIC, the indentation would break (the one kind of static analysis there is!) so I would consider it 'bad code' from one standpoint or the other.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 7:52 pm

If BBC BASIC would execute that code then there is no stack behind it. The rule is every FOR must have a corresponding NEXT in ScriptBasic.

User avatar
RichardRussell
Posts: 501
Joined: Thu Jun 21, 2012 10:48 am

Re: ScriptBasic

Mon May 13, 2019 8:15 pm

ScriptBasic wrote:
Mon May 13, 2019 7:52 pm
If BBC BASIC would execute that code then there is no stack behind it.
I love the way that you (apparently) know better than me how BBC BASIC works! Here is the code adapted to run in any post-1984 BBC BASIC (with indentation disabled because it gets confused). Respond to the prompt with 0 or 1:

Code: Select all

      INPUT flag
      IF flag THEN
      FOR Count = 10 TO 20 STEP 1
      ELSE
      FOR Count = 10 TO 0 STEP -1
      ENDIF
      PRINT Count
      NEXT
If you want to monitor the stack usage add this line at the start, at the end and inside the loop:

Code: Select all

      DIM stack LOCAL -1 : PRINT stack

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 9:38 pm

I love the way that you (apparently) know better than me how BBC BASIC works!
Sorry if you got that impression as I was only confirming your comment about stack use when using FOR / NEXT.

I don't agree that the code presented should be allowed to run. It breaks the rules of BASIC.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Mon May 13, 2019 10:12 pm

Here is how I would write the code keeping with the intended concept.

Code: Select all

IF flag = undef THEN
  FOR count = 10 TO 20 STEP 1
    GOSUB Display_Count
  NEXT
ELSE
  FOR count = 10 TO 0 STEP -1
    GOSUB Display_Count
  NEXT
END IF
END
Display_Count:
PRINT count,"\n"
RETURN
[email protected]:~/sb/examples/test$ scriba ifor.sb
10
11
12
13
14
15
16
17
18
19
20
[email protected]:~/sb/examples/test$

hippy
Posts: 5335
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: ScriptBasic

Tue May 14, 2019 12:45 am

ScriptBasic wrote:
Mon May 13, 2019 9:38 pm
I don't agree that the code presented should be allowed to run. It breaks the rules of BASIC.
What rules of BASIC ? Whose rules of BASIC ?

I don't have any particular problem with any compiler / interpreter rejecting nesting like that, but I wouldn't go so far as to say it shouldn't be allowed, is always invalid. I can even make the case for it being valid.

One could argue that, just as LET sets a variable's value for later use, FOR simply initialises a variable and sets the loop constraints for later use when a NEXT is encountered.

And what if we weren't using IF-ELSE-ENDIF but went back to traditional line numbered BASIC ... ?

Code: Select all

10 IF F% <= 0 GOTO 40
20 FOR c% = 0 TO 10 STEP 1
30 GOTO 50
40 FOR C% = 10 To 0 STEP -1
50 PRINT C%
60 NEXT
If the 40, 50, 60 loop is acceptable, then why shouldn't the 20, 30, 50, 60 loop also be acceptable ?

The 40, 50, 60 loop shouldn't break if I added "45 GOTO 50". As that's then the same as 20, 30, 50, 60 in terms of sequential execution, the above must be acceptable and it should be accepted. If acceptable in that form then why shouldn't it equally be acceptable when in Block-structured form ?

Is rejecting it because it's not deemed correctly block-structured actually a legitimate decision to make ?

What it comes down to in implementation terms, whether either block structured or line-numbered works, is what NEXT does. Whether it is given information at run-time as to where the preceding FOR was and uses that, and errors as we have seen with BBC BASIC if there wasn't a preceding FOR, or NEXT is tied and fixed to some particular FOR during compilation, rather than at run time.

This goes back to what I was saying as to whether an implementation delivers what a programmer wants, or the compiler designer dictates what the programmer gets. if not the same then both are defining the same language but in different ways.

It gets even more insane though, because if FOR within IF-ELSE-ENDIF is accepted then surely this is also valid ...

Code: Select all

While flag = 1
If count = 1 Then
  Wend
  Print "A"
Else
  Wend
  Print "B"
End If

That all makes sense if the WEND is told where the WHILE was at run-time, just like FOR-NEXT. But, if the WHILE condition is initially false, which WEND does it choose to go to ?

That dilemma is possibly why some interpreters only have REPEAT-UNTIL and one needs to create WHILE-WEND using REPEAT-UNTIL inside an IF-ENDIF.

Once one starts to look at all the possibilities there could be one starts to see why particular languages and what they allow are how they are, why there's some peculiar aspects to them at times.

And all that is probably why everyone breathed a huge sigh of relief when we surrendered GOTO and spaghetti code and went for well defined block-structured languages.

User avatar
ScriptBasic
Posts: 1231
Joined: Wed Apr 03, 2019 5:53 pm
Location: Anacortes, WA USA
Contact: Website Twitter

Re: ScriptBasic

Tue May 14, 2019 1:40 am

In ScriptBasic every FOR needs it's own NEXT. I will try the single NEXT in QuickBasic and see if it complains. I view QB as the traditional BASIC standard when question of what is standard comes up.

ejolson
Posts: 3034
Joined: Tue Mar 18, 2014 11:47 am

Re: ScriptBasic

Tue May 14, 2019 2:01 am

hippy wrote:
Mon May 13, 2019 5:13 pm
A programmer writing the above horrible mess would rightly argue that their code for a GOTO-supporting language which allows spaghetti code is entirely valid and should be executed as it is written and deliver the results as would be expected.
All this spaghetti code is making me hungry.

Even with the differences in Basic languages, I find it reassuring that all the interpreters and compilers mentioned so far seem okay with the classic line-numbered Fibonacci code, which was written in blissful ignorance of how a for/next loop might be implemented.

However, I do remember a disappointing discovery around 1978 when I realized something like

Code: Select all

110 for i from 1 to n
120     for a(i) from 1 to 6
130 next i
        ...do stuff...
170 for i from n to 1 step -1
180    next a(i)
190 next i
didn't work the way I wanted it to. While I heard it from the chief developer that this feature is planned for FidoBasic, does it work in any other Basic?

Return to “Other programming languages”