BASIC FOR loops

Discuss all aspects of programming here. From 8-bit through to modern architectures.
Post Reply
Coeus
Posts: 827
Joined: Mon Jul 25, 2016 11:05 am
Contact:

BASIC FOR loops

Post by Coeus » Mon Jul 09, 2018 4:27 pm

I mentioned in another thread in which a Mandelbrot program in BASIC was included that brandy basic does not handle FOR loops where a NEXT statement occurs for anything other than the innermost FOR loop. I had a look in original BBC Micro User guide and it advises against "bady nested" FOR loops but does give an example of what would happen when you nest them this way:

Code: Select all

5 FOR H = 1 TO 4
10   FOR X = 1 TO 2
20     PRINT "HELLO",H,X
40     NEXT H
50   END
would give the output:

Code: Select all

HELLO  1  1
HELLO  2  1
HELLO  3  1
HELLO  4  1
So that means upon finding the NEXT for an outer loop with an inner loop still in progress, exit the inner loop early discarding its state and go to the next iteration of the outer loop.

Did this change with the introduction of BASIC V?
Last edited by Coeus on Mon Jul 09, 2018 4:28 pm, edited 1 time in total.

User avatar
flaxcottage
Posts: 3092
Joined: Thu Dec 13, 2012 8:46 pm
Location: Derbyshire
Contact:

Re: BASIC FOR loops

Post by flaxcottage » Mon Jul 09, 2018 5:11 pm

No.
- John

Why do I keep collecting Acorn gear? I'm going to need a considerably bigger man-cave. :?

Coeus
Posts: 827
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: BASIC FOR loops

Post by Coeus » Mon Jul 09, 2018 6:11 pm

Ok, then in that case here is a patch to brandy basic that makes it behave like Acorn BASIC with these loops:

Code: Select all

--- brandy-1.21.2-orig/src/mainstate.c	2013-06-28 15:23:16.000000000 +0100
+++ brandy-1.21.2-patched/src/mainstate.c	2018-07-09 18:49:29.975604126 +0100
@@ -1301,6 +1301,20 @@
 /*
 ** 'exec_next' handles what is really the business end of a 'FOR' loop.
 */
+
+static stack_for *find_for(void)
+{
+  stack_for *fp;
+
+  if (GET_TOPITEM == STACK_INTFOR || GET_TOPITEM == STACK_FLOATFOR) /* FOR control block is top of stack */
+    fp = basicvars.stacktop.forsp;
+  else {	/* Discard entries until FOR control block is found */
+    fp = get_for();
+  }
+  if (fp == NIL) error(ERR_NOTFOR);	/* Not in a FOR loop */
+  return fp;
+}
+  
 void exec_next(void) {
   stack_for *fp;
   lvalue nextvar;
@@ -1309,17 +1323,16 @@
   static float64 floatvalue;
   if (basicvars.escape) error(ERR_ESCAPE);
   do {
-    if (GET_TOPITEM == STACK_INTFOR || GET_TOPITEM == STACK_FLOATFOR) /* FOR control block is top of stack */
-      fp = basicvars.stacktop.forsp;
-    else {	/* Discard entries until FOR control block is found */
-       fp = get_for();
-    }
-    if (fp == NIL) error(ERR_NOTFOR);	/* Not in a FOR loop */
+    fp = find_for();
     basicvars.current++;	/* Skip NEXT token */
     if (!ateol[*basicvars.current]) {	/* There is a control variable (or two) here */
       if (*basicvars.current != ',') {
         get_lvalue(&nextvar);
-        if (nextvar.address.intaddr != fp->forvar.address.intaddr) error(ERR_WRONGFOR);	/* Cannot match 'FOR' loop variable */
+        while (nextvar.address.intaddr != fp->forvar.address.intaddr) {
+          /* top for loop is an inner one - pop the stack to find the one that matches the NEXT */
+          pop_for();
+          fp = find_for();
+        }          
       }
     }
 /*
--- brandy-1.21.2-orig/src/errors.h	2013-06-28 15:23:16.000000000 +0100
+++ brandy-1.21.2-patched/src/errors.h	2018-07-09 19:05:55.698578957 +0100
@@ -26,157 +26,157 @@
 
 /* Basic error numbers */
 
-#define ERR_NONE	0	/* No error */
+typedef enum {
+    ERR_NONE,           /* No error */
+    ERR_UNSUPPORTED,    /* Unsupported feature */
+    ERR_UNSUPSTATE,     /* Unsupported statement type */
+    ERR_NOGRAPHICS,     /* No graphics available */
+    ERR_NOVDUCMDS,      /* VDU commands cannot be used here */
+    ERR_SYNTAX,         /* General purpose error */
+    ERR_SILLY,          /* A silly error */
+    ERR_BADPROG,        /* Corrupted program */
+    ERR_ESCAPE,         /* Escape key pressed */
+    ERR_STOP,           /* STOP statement */
+    ERR_STATELEN,       /* Statement > 1024 chars long */
+    ERR_LINENO,         /* Line number out of range */
+    ERR_LINEMISS,       /* Line number not found */
+    ERR_VARMISS,        /* Unknown variable */
+    ERR_ARRAYMISS,      /* Unknown array */
+    ERR_FNMISS,         /* Unknown function */
+    ERR_PROCMISS,       /* Unknown procedure */
+    ERR_TOOMANY,        /* Too many parameters in FN or PROC call */
+    ERR_NOTENUFF,       /* Not enough parameters in FN or PROC call */
+    ERR_FNTOOMANY,      /* Too many parameters in call to built-in function */
+    ERR_FNNOTENUFF,     /* Not enough parameters in call to built-in function */
+    ERR_BADRET,         /* Parameter is not a valid 'return' parameter */
+    ERR_CRASH,          /* Run into procedure or function */
+    ERR_BADDIM,         /* Not enough room to create an array */
+    ERR_BADBYTEDIM,     /* Not enough room to create a byte array */
+    ERR_NEGDIM,         /* Array dimension is negative */
+    ERR_DIMCOUNT,       /* Array has too many dimensions */
+    ERR_DUPLDIM,        /* Array already defined */
+    ERR_BADINDEX,       /* Array index is out of range */
+    ERR_INDEXCO,        /* Wrong number of array dimension */
+    ERR_DIMRANGE,       /* Array dimension number is out of range */
+    ERR_NODIMS,         /* Array dimensions not defined */
+    ERR_ADDRESS,        /* Addressing exception */
+    WARN_BADTOKEN,      /* Bad token value entered */
+    WARN_BADHEX,        /* Bad hexadecimal constant */
+    WARN_BADBIN,        /* Bad binary constant */
+    WARN_EXPOFLO,       /* Exponent is too large */
+    ERR_NAMEMISS,       /* Variable name expected */
+    ERR_EQMISS,         /* '=' missing */
+    ERR_COMISS,         /* ',' missing */
+    ERR_LPMISS,         /* '(' missing */
+    ERR_RPMISS,         /* ')' missing */
+    WARN_QUOTEMISS,     /* '"' missing (warning) */
+    ERR_QUOTEMISS,      /* '"' missing */
+    ERR_HASHMISS,       /* '#' missing */
+    ERR_ENDIF,          /* ENDIF missing */
+    ERR_ENDWHILE,       /* ENDWHILE missing */
+    ERR_ENDCASE,        /* ENDCASE missing */
+    ERR_OFMISS,         /* OF missing */
+    ERR_TOMISS,         /* 'TO' missing */
+    ERR_CORPNEXT,       /* ',' or ')' expected */
+    ERR_NOTWHILE,       /* Not in a 'WHILE' loop */
+    ERR_NOTREPEAT,      /* Not in a 'REPEAT' loop */
+    ERR_NOTFOR,         /* Not in a 'FOR' loop */
+    ERR_DIVZERO,        /* Divide by zero */
+    ERR_NEGROOT,        /* Square root of a negative number */
+    ERR_LOGRANGE,       /* Log of zero or a negative number */
+    ERR_RANGE,          /* General number out of range error */
+    ERR_ONRANGE,        /* 'ON' index is out of range */
+    ERR_ARITHMETIC,     /* Floating point exception */
+    ERR_STRINGLEN,      /* String is too long */
+    ERR_BADOPER,        /* Unrecognisable operand */
+    ERR_TYPENUM,        /* Type mismatch: number wanted */
+    ERR_TYPESTR,        /* Type mismatch: string wanted */
+    ERR_PARMNUM,        /* Parameter type mismatch: number wanted */
+    ERR_PARMSTR,        /* Parameter type mismatch: string wanted */
+    ERR_VARNUM,         /* Type mismatch: numeric variable wanted */
+    ERR_VARSTR,         /* Type mismatch: string variable wanted */
+    ERR_VARNUMSTR,      /* Integer or string value wanted */
+    ERR_VARARRAY,       /* Type mismatch: array wanted */
+    ERR_INTARRAY,       /* Type mismatch: integer array wanted */
+    ERR_FPARRAY,        /* Type mismatch: floating point array wanted */
+    ERR_STRARRAY,       /* Type mismatch: string array wanted */
+    ERR_NUMARRAY,       /* Type mismatch: numeric array wanted */
+    ERR_NOTONEDIM,      /* Array must have only one dimension */
+    ERR_TYPEARRAY,      /* Type mismatch: arrays must be the same size */
+    ERR_MATARRAY,       /* Type mismatch: cannot perform matrix multiplication on these arrays */
+    ERR_NOSWAP,         /* Type mismatch: cannot swap variables of different types */
+    ERR_BADCOMP,        /* Cannot compare these types of operand */
+    ERR_BADARITH,       /* Cannot perform arithmetic operations on these types of operand */
+    ERR_BADEXPR,        /* Syntax error in expression */
+    ERR_RETURN,         /* RETURN encountered outside a subroutine */
+    ERR_NOTAPROC,       /* Cannot use a function as a procedure */
+    ERR_NOTAFN,         /* Cannot use a procedure as a function */
+    ERR_ENDPROC,        /* ENDPROC encountered outside a PROC */
+    ERR_FNRETURN,       /* Function return encountered outside a FN */
+    ERR_LOCAL,          /* LOCAL found outside a PROC or FN */
+    ERR_DATA,           /* Out of data */
+    ERR_NOROOM,         /* Out of memory */
+    ERR_WHENCOUNT,      /* Too many WHEN clauses in CASE statement */
+    ERR_SYSCOUNT,       /* Too many parameters found in a SYS statement */
+    ERR_STACKFULL,      /* Arithmetic stack overflow */
+    ERR_OPSTACK,        /* Operator stack overflow */
+    WARN_BADHIMEM,      /* Attempted to set HIMEM to a bad value */
+    WARN_BADLOMEM,      /* Attempted to set LOMEM to a bad value */
+    WARN_BADPAGE,       /* Attempted to set PAGE to a bad value */
+    ERR_NOTINPROC,      /* Cannot change HIMEM in a function or procedure */
+    ERR_HIMEMFIXED,     /* Cannot change HIMEM here */
+    ERR_BADTRACE,       /* Bad TRACE option */
+    ERR_ERRNOTOP,       /* Error block not on top of stack */
+    ERR_DATANOTOP,      /* DATA pointer not on top of stack */
+    ERR_BADPLACE,       /* SPC() or TAB() found outside INPUT or PRINT */
+    ERR_BADMODESC,      /* Bad mode descriptor */
+    ERR_BADMODE,        /* Screen mode unavailable */
+    WARN_LIBLOADED,     /* Library already loaded */
+    ERR_NOLIB,          /* Cannot find library */
+    ERR_LIBSIZE,        /* Not enough memory available to load library */
+    ERR_NOLIBLOC,       /* LIBRARY LOCAL not at start of library */
+    ERR_FILENAME,       /* File name missing */
+    ERR_NOTFOUND,       /* Cannot find file */
+    ERR_OPENWRITE,      /* Cannot open file for write */
+    ERR_OPENUPDATE,     /* Cannot open file for update */
+    ERR_OPENIN,         /* File is open for reading, not writing */
+    ERR_CANTREAD,       /* Unable to read from file */
+    ERR_CANTWRITE,      /* Unable to write to file */
+    ERR_HITEOF,         /* Have hit end of file */
+    ERR_READFAIL,       /* Cannot read file */
+    ERR_NOTCREATED,     /* Cannot create file */
+    ERR_WRITEFAIL,      /* Could not finish writing to file */
+    ERR_EMPTYFILE,      /* Basic program file is empty */
+    ERR_FILEIO,         /* Some other I/O error */
+    ERR_UNKNOWN,        /* Unexpected signal received */
+    ERR_CMDFAIL,        /* OS command failed */
+    ERR_BADHANDLE,      /* Handle is invalid or file associated with it is closed */
+    ERR_SETPTRFAIL,     /* File pointer cannot be changed */
+    ERR_GETPTRFAIL,     /* File pointer cannot be read */
+    ERR_GETEXTFAIL,     /* File size cannot be found */
+    ERR_MAXHANDLE,      /* Maximum number of files are already open */
+    ERR_NOMEMORY,       /* Not enough memory available to run interpreter */
+    ERR_BROKEN,         /* Basic program is corrupt or interpreter logic error */
+    ERR_COMMAND,        /* Basic command found in program */
+    ERR_RENUMBER,       /* RENUMBER failed */
+    WARN_LINENO,        /* Line number too large (warning) */
+    WARN_LINEMISS,      /* Line number missing (warning) */
+    WARN_RENUMBERED,    /* Program renumbered */
+    WARN_RPMISS,        /* ')' missing (warning) */
+    WARN_RPAREN,        /* Too many ')' (warning) */
+    WARN_PARNEST,       /* '()' nested incorrectly */
+    WARN_NEWSIZE,       /* Size of workspace changed */
+    WARN_ONEFILE,       /* One file closed */
+    WARN_MANYFILES,     /* Many files closed */
+    ERR_EDITFAIL,       /* Edit session failed */
+    ERR_OSCLIFAIL,      /* OSCLI failed */
+    ERR_NOGZIP,         /* gzip support not available */
+    WARN_FUNNYFLOAT,    /* Unknown floating point format */
+    ERR_EMUCMDFAIL,     /* Emulated RISC OS command failed */
+    ERR_SDL_TIMER       /* SDL Timer Error */
+} errnum;
 
-#define ERR_UNSUPPORTED	1	/* Unsupported feature */
-#define ERR_UNSUPSTATE	2	/* Unsupported statement type */
-#define ERR_NOGRAPHICS	3	/* No graphics available */
-#define ERR_NOVDUCMDS	4	/* VDU commands cannot be used here */
-#define ERR_SYNTAX	5	/* General purpose error */
-#define ERR_SILLY	6	/* A silly error */
-#define ERR_BADPROG	7	/* Corrupted program */
-#define ERR_ESCAPE	8	/* Escape key pressed */
-#define ERR_STOP	9	/* STOP statement */
-#define ERR_STATELEN	10	/* Statement > 1024 chars long */
-#define ERR_LINENO	11	/* Line number out of range */
-#define ERR_LINEMISS	12	/* Line number not found */
-#define ERR_VARMISS	13	/* Unknown variable */
-#define ERR_ARRAYMISS	14	/* Unknown array */
-#define ERR_FNMISS	15	/* Unknown function */
-#define ERR_PROCMISS	16	/* Unknown procedure */
-#define ERR_TOOMANY	17	/* Too many parameters in FN or PROC call */
-#define ERR_NOTENUFF	18	/* Not enough parameters in FN or PROC call */
-#define ERR_FNTOOMANY	19	/* Too many parameters in call to built-in function */
-#define ERR_FNNOTENUFF	20	/* Not enough parameters in call to built-in function */
-#define ERR_BADRET	21	/* Parameter is not a valid 'return' parameter */
-#define ERR_CRASH	22	/* Run into procedure or function */
-#define ERR_BADDIM	23	/* Not enough room to create an array */
-#define ERR_BADBYTEDIM	24	/* Not enough room to create a byte array */
-#define ERR_NEGDIM	25	/* Array dimension is negative */
-#define ERR_DIMCOUNT	26	/* Array has too many dimensions */
-#define ERR_DUPLDIM	27	/* Array already defined */
-#define ERR_BADINDEX	28	/* Array index is out of range */
-#define ERR_INDEXCO	29	/* Wrong number of array dimension */
-#define ERR_DIMRANGE	30	/* Array dimension number is out of range */
-#define ERR_NODIMS	31	/* Array dimensions not defined */
-#define ERR_ADDRESS	32	/* Addressing exception */
-#define WARN_BADTOKEN	33	/* Bad token value entered */
-#define WARN_BADHEX	34	/* Bad hexadecimal constant */
-#define WARN_BADBIN	35	/* Bad binary constant */
-#define WARN_EXPOFLO	36	/* Exponent is too large */
-#define ERR_NAMEMISS	37	/* Variable name expected */
-#define ERR_EQMISS	38	/* '=' missing */
-#define ERR_COMISS	39	/* ',' missing */
-#define ERR_LPMISS	40	/* '(' missing */
-#define ERR_RPMISS	41	/* ')' missing */
-#define WARN_QUOTEMISS	42	/* '"' missing (warning) */
-#define ERR_QUOTEMISS	43	/* '"' missing */
-#define ERR_HASHMISS	44	/* '#' missing */
-#define ERR_ENDIF	45	/* ENDIF missing */
-#define ERR_ENDWHILE	46	/* ENDWHILE missing */
-#define ERR_ENDCASE	47	/* ENDCASE missing */
-#define ERR_OFMISS	48	/* OF missing */
-#define ERR_TOMISS	49	/* 'TO' missing */
-#define ERR_CORPNEXT	50	/* ',' or ')' expected */
-#define ERR_NOTWHILE	51	/* Not in a 'WHILE' loop */
-#define ERR_NOTREPEAT	52	/* Not in a 'REPEAT' loop */
-#define ERR_NOTFOR	53	/* Not in a 'FOR' loop */
-#define ERR_WRONGFOR	54	/* Cannot match 'FOR' loop */
-#define ERR_DIVZERO	55	/* Divide by zero */
-#define ERR_NEGROOT	56	/* Square root of a negative number */
-#define ERR_LOGRANGE	57	/* Log of zero or a negative number */
-#define ERR_RANGE	58	/* General number out of range error */
-#define ERR_ONRANGE	59	/* 'ON' index is out of range */
-#define ERR_ARITHMETIC	60	/* Floating point exception */
-#define ERR_STRINGLEN	61	/* String is too long */
-#define ERR_BADOPER	62	/* Unrecognisable operand */
-#define ERR_TYPENUM	63	/* Type mismatch: number wanted */
-#define ERR_TYPESTR	64	/* Type mismatch: string wanted */
-#define ERR_PARMNUM	65	/* Parameter type mismatch: number wanted */
-#define ERR_PARMSTR	66	/* Parameter type mismatch: string wanted */
-#define ERR_VARNUM	67	/* Type mismatch: numeric variable wanted */
-#define ERR_VARSTR	68	/* Type mismatch: string variable wanted */
-#define ERR_VARNUMSTR	69	/* Integer or string value wanted */
-#define ERR_VARARRAY	70	/* Type mismatch: array wanted */
-#define ERR_INTARRAY	71	/* Type mismatch: integer array wanted */
-#define ERR_FPARRAY	72	/* Type mismatch: floating point array wanted */
-#define ERR_STRARRAY	73	/* Type mismatch: string array wanted */
-#define ERR_NUMARRAY	74	/* Type mismatch: numeric array wanted */
-#define ERR_NOTONEDIM	75	/* Array must have only one dimension */
-#define ERR_TYPEARRAY	76	/* Type mismatch: arrays must be the same size */
-#define ERR_MATARRAY	77	/* Type mismatch: cannot perform matrix multiplication on these arrays */
-#define ERR_NOSWAP	78	/* Type mismatch: cannot swap variables of different types */
-#define ERR_BADCOMP	79	/* Cannot compare these types of operand */
-#define ERR_BADARITH	80	/* Cannot perform arithmetic operations on these types of operand */
-#define ERR_BADEXPR	81	/* Syntax error in expression */
-#define ERR_RETURN	82	/* RETURN encountered outside a subroutine */
-#define ERR_NOTAPROC	83	/* Cannot use a function as a procedure */
-#define ERR_NOTAFN	84	/* Cannot use a procedure as a function */
-#define ERR_ENDPROC	85	/* ENDPROC encountered outside a PROC */
-#define ERR_FNRETURN	86	/* Function return encountered outside a FN */
-#define ERR_LOCAL	87	/* LOCAL found outside a PROC or FN */
-#define ERR_DATA	88	/* Out of data */
-#define ERR_NOROOM	89	/* Out of memory */
-#define ERR_WHENCOUNT	90	/* Too many WHEN clauses in CASE statement */
-#define ERR_SYSCOUNT	91	/* Too many parameters found in a SYS statement */
-#define ERR_STACKFULL	92	/* Arithmetic stack overflow */
-#define ERR_OPSTACK	93	/* Operator stack overflow */
-#define WARN_BADHIMEM	94	/* Attempted to set HIMEM to a bad value */
-#define WARN_BADLOMEM	95	/* Attempted to set LOMEM to a bad value */
-#define WARN_BADPAGE	96	/* Attempted to set PAGE to a bad value */
-#define ERR_NOTINPROC	97	/* Cannot change HIMEM in a function or procedure */
-#define ERR_HIMEMFIXED	98	/* Cannot change HIMEM here */
-#define ERR_BADTRACE	99	/* Bad TRACE option */
-#define ERR_ERRNOTOP	100	/* Error block not on top of stack */
-#define ERR_DATANOTOP	101	/* DATA pointer not on top of stack */
-#define ERR_BADPLACE	102	/* SPC() or TAB() found outside INPUT or PRINT */
-#define ERR_BADMODESC	103	/* Bad mode descriptor */
-#define ERR_BADMODE	104	/* Screen mode unavailable */
-#define WARN_LIBLOADED	105	/* Library already loaded */
-#define ERR_NOLIB	106	/* Cannot find library */
-#define ERR_LIBSIZE	107	/* Not enough memory available to load library */
-#define ERR_NOLIBLOC	108	/* LIBRARY LOCAL not at start of library */
-#define ERR_FILENAME	109	/* File name missing */
-#define ERR_NOTFOUND	110	/* Cannot find file */
-#define ERR_OPENWRITE	111	/* Cannot open file for write */
-#define ERR_OPENUPDATE	112	/* Cannot open file for update */
-#define ERR_OPENIN	113	/* File is open for reading, not writing */
-#define ERR_CANTREAD	114	/* Unable to read from file */
-#define ERR_CANTWRITE	115	/* Unable to write to file */
-#define ERR_HITEOF	116	/* Have hit end of file */
-#define ERR_READFAIL	117	/* Cannot read file */
-#define ERR_NOTCREATED	118	/* Cannot create file */
-#define ERR_WRITEFAIL	119	/* Could not finish writing to file */
-#define ERR_EMPTYFILE	120	/* Basic program file is empty */
-#define ERR_FILEIO	121	/* Some other I/O error */
-#define ERR_UNKNOWN	122	/* Unexpected signal received */
-#define ERR_CMDFAIL	123	/* OS command failed */
-#define ERR_BADHANDLE	124	/* Handle is invalid or file associated with it is closed */
-#define ERR_SETPTRFAIL	125	/* File pointer cannot be changed */
-#define ERR_GETPTRFAIL	126	/* File pointer cannot be read */
-#define ERR_GETEXTFAIL	127	/* File size cannot be found */
-#define ERR_MAXHANDLE	128	/* Maximum number of files are already open */
-#define ERR_NOMEMORY	129	/* Not enough memory available to run interpreter */
-#define ERR_BROKEN	130	/* Basic program is corrupt or interpreter logic error */
-#define ERR_COMMAND	131	/* Basic command found in program */
-#define ERR_RENUMBER	132	/* RENUMBER failed */
-#define WARN_LINENO	133	/* Line number too large (warning) */
-#define WARN_LINEMISS	134	/* Line number missing (warning) */
-#define WARN_RENUMBERED	135	/* Program renumbered */
-#define WARN_RPMISS	136	/* ')' missing (warning) */
-#define WARN_RPAREN	137	/* Too many ')' (warning) */
-#define WARN_PARNEST	138	/* '()' nested incorrectly */
-#define WARN_NEWSIZE	139	/* Size of workspace changed */
-#define WARN_ONEFILE	140	/* One file closed */
-#define WARN_MANYFILES	141	/* Many files closed */
-#define ERR_EDITFAIL	142	/* Edit session failed */
-#define ERR_OSCLIFAIL	143	/* OSCLI failed */
-#define ERR_NOGZIP	144	/* gzip support not available */
-#define WARN_FUNNYFLOAT	145	/* Unknown floating point format */
-#define ERR_EMUCMDFAIL	146	/* Emulated RISC OS command failed */
-#define ERR_SDL_TIMER   147     /* SDL Timer Error */
-
-#define HIGHERROR	147
+#define HIGHERROR	ERR_SDL_TIMER
 
 /* Other interpreter errors */
 
--- brandy-1.21.2-orig/src/errors.c	2018-07-06 15:42:46.000000000 +0100
+++ brandy-1.21.2-patched/src/errors.c	2018-07-09 19:06:18.121902893 +0100
@@ -371,7 +371,6 @@
   {NONFATAL, NOPARM,  46, "Not in a 'WHILE' loop"},
   {NONFATAL, NOPARM,  43, "Not in a 'REPEAT' loop"},
   {NONFATAL, NOPARM,  32, "Not in a 'FOR' loop"},
-  {NONFATAL, NOPARM,  33, "Variable after 'NEXT' is not the control variable of the current 'FOR' loop"},
   {NONFATAL, NOPARM,  18, "Division by zero"},
   {NONFATAL, NOPARM,  21, "Tried to take square root of a negative number"},
   {NONFATAL, NOPARM,  22, "Tried to take log of zero or a negative number"},
The interesting bit is in the first patched file mainstate.c, the rest is removing the now unused error from the table.

User avatar
jgharston
Posts: 3091
Joined: Thu Sep 24, 2009 11:22 am
Location: Whitby/Sheffield
Contact:

Re: BASIC FOR loops

Post by jgharston » Mon Jul 09, 2018 8:03 pm

Coeus wrote:
Mon Jul 09, 2018 4:27 pm
I mentioned in another thread in which a Mandelbrot program in BASIC was included that brandy basic does not handle FOR loops where a NEXT statement occurs for anything other than the innermost FOR loop. I had a look in original BBC Micro User guide and it advises against "bady nested" FOR loops but does give an example of what would happen when you nest them this way:

Code: Select all

5 FOR H = 1 TO 4
10   FOR X = 1 TO 2
20     PRINT "HELLO",H,X
40     NEXT H
50   END
Officially, it's implementation defined behavior. You have zero defined certainty what it may do in any particular instance. It is perfectly valid for it to cause the computer to catch fire and strangle your cat.

Code: Select all

$ bbcbasic
PDP11 BBC BASIC IV Version 0.25
(C) Copyright J.G.Harston 1989,2005-2015
>_

User avatar
BigEd
Posts: 1891
Joined: Sun Jan 24, 2010 10:24 am
Location: West
Contact:

Re: BASIC FOR loops

Post by BigEd » Mon Jul 09, 2018 8:30 pm

I'm surprised - I thought it was an official feature to be able to bale out of an inner loop by resuming an outer loop.

p273 of the user guide (pdf):
If a variable is given after NEXT then the computer will ‘pop’ other FOR...NEXT loops off the ‘stack’ until it finds a matching variable. If none is found, an error will be reported.

Coeus
Posts: 827
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: BASIC FOR loops

Post by Coeus » Mon Jul 09, 2018 9:11 pm

The phrase "Implementation defined behaviour" sounds like what you'd expect to in a language standard but I was not aware of any effort to produce a proper language standard for BASIC. As a practical matter, across BASIC implementations in general this does seem to vary. For example on CP/M Microsoft BASIC 5.29:

Code: Select all

10 FOR I = 1 TO 4
20 FOR J = 1 TO 2
30 PRINT "Hello",I,J
40 NEXT J
50 NEXT I
RUN
Hello          1             1 
Hello          1             2 
Hello          2             1 
Hello          2             2 
Hello          3             1 
Hello          3             2 
Hello          4             1 
Hello          4             2 
Ok
40
RUN
FOR Without NEXT in 10
Ok
so this one objects. Also on CP/M, XYBASIC from the Mark Williams Company:

Code: Select all

LIST
10 FOR I = 1 TO 4
20 FOR J = 1 TO 2
30 PRINT "Hello",I,J
40 NEXT J
50 NEXT I

OK
RUN
Hello          1             1 
Hello          1             2 
Hello          2             1 
Hello          2             2 
Hello          3             1 
Hello          3             2 
Hello          4             1 
Hello          4             2 

OK
40
RUN
Hello          1             1 
Hello          2             1 
Hello          3             1 
Hello          4             1 

OK
so this one behaves more like BBC BASIC. In the case of Brandy, I was expecting something that was backwards compatible with BBC BASIC as on the original BBC micro, though I note it actually implements BASIC V as found under RiscOS so I thought I'd ask. If BASIC V on RiscOS POPs the inner loops and continues with the outer ones then it seems Brandy should probably to that too.
Last edited by Coeus on Mon Jul 09, 2018 9:12 pm, edited 1 time in total.

Coeus
Posts: 827
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: BASIC FOR loops

Post by Coeus » Mon Jul 09, 2018 9:24 pm

Ok, so to follow up my post it seems there is an ANSI standard for BASIC, I just wasn't aware of it. That doesn't make any material difference, though, as I was specifically asking about Acorn BASICs.

Soruk
Posts: 15
Joined: Mon Jul 09, 2018 10:31 am
Contact:

Re: BASIC FOR loops

Post by Soruk » Mon Jul 09, 2018 10:18 pm

Hi,

Your patch works a treat for that Mandelbrot thing over in the other thread.

May I include it in my fork of Brandy?

User avatar
1024MAK
Posts: 7566
Joined: Mon Apr 18, 2011 4:46 pm
Location: Looking forward to summer in Somerset, UK...
Contact:

Re: BASIC FOR loops

Post by 1024MAK » Mon Jul 09, 2018 10:27 pm

Many BASIC implementations generate an error if there are mis-matched FOR-NEXT loops.

IMHO, that appears to be the best way of handling the problem.

Mark
For a "Complete BBC Games Archive" visit www.bbcmicro.co.uk NOW!
BeebWiki‬ - for answers to many questions...

cmorley
Posts: 522
Joined: Sat Jul 30, 2016 7:11 pm
Location: Oxford
Contact:

Re: BASIC FOR loops

Post by cmorley » Tue Jul 10, 2018 6:45 am

1024MAK wrote:
Mon Jul 09, 2018 10:27 pm
Many BASIC implementations generate an error if there are mis-matched FOR-NEXT loops.

IMHO, that appears to be the best way of handling the problem.
I disagree. Perhaps it is a little confusing for the beginner but it is the equivalent to "break [n];" in C. A very useful feature for more advanced program flow control.

Soruk
Posts: 15
Joined: Mon Jul 09, 2018 10:31 am
Contact:

Re: BASIC FOR loops

Post by Soruk » Tue Jul 10, 2018 6:59 am

cmorley wrote:
Tue Jul 10, 2018 6:45 am
1024MAK wrote:
Mon Jul 09, 2018 10:27 pm
Many BASIC implementations generate an error if there are mis-matched FOR-NEXT loops.

IMHO, that appears to be the best way of handling the problem.
I disagree. Perhaps it is a little confusing for the beginner but it is the equivalent to "break [n];" in C. A very useful feature for more advanced program flow control.
I agree with this - and since it was Brandy that got this going, since it's aim is an implementation of BBC BASIC, then its behaviour should be the same as existing "real" BBC BASIC versions.

(For the same reason, my Teletext implementation does one thing that's against the teletext spec, but it's what the SAA5050 and RISC OS's emulation of it both do.)

Coeus
Posts: 827
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: BASIC FOR loops

Post by Coeus » Tue Jul 10, 2018 9:06 am

Soruk wrote:
Mon Jul 09, 2018 10:18 pm
Hi,

Your patch works a treat for that Mandelbrot thing over in the other thread.

May I include it in my fork of Brandy?
Yes, that's fine.

Coeus
Posts: 827
Joined: Mon Jul 25, 2016 11:05 am
Contact:

Re: BASIC FOR loops

Post by Coeus » Tue Jul 10, 2018 9:51 am

cmorley wrote:
Tue Jul 10, 2018 6:45 am
I disagree. Perhaps it is a little confusing for the beginner but it is the equivalent to "break [n];" in C. A very useful feature for more advanced program flow control.
In the the case of the Mandelbrot program that started this, it is only a single level of break in equivalent C. Here's the part of that BASIC program converted into C:

Code: Select all

for (i = 1; i < n; i++) {
    x2 = x * x;
    y2 = y * y;
    if ((x2 + y2) >= 4)
        break;
    xy = x * y;
    x = x2 - y2 + r;
    y = 2 * xy + j;
 }
Loops with two tests that have some work to do in between the tests definitely come up in the real world and in this case it is a kind of search within bounds so the index at which x2+y2 reached 4 is the result of the search. Setting this to n+1 to exit the loop doesn't work. To re-work that with the constraint that loops must not be exited by doing NEXT on the outer loop gives this:

Code: Select all

   90FOR k=1 TO n:x2=x*x:y2=y*y:i=k:IF x2+y2>=4 THEN k=n+1 ELSE xy=x*y:x=x2-y2+r
:y=2*xy+j
  100NEXT
  110d(c,s%)=i:IF i<n THEN:PLOT 69,4*s%,800-4*t%

User avatar
Elminster
Posts: 2416
Joined: Wed Jun 20, 2012 8:09 am
Location: Essex, UK
Contact:

Re: BASIC FOR loops

Post by Elminster » Tue Jul 10, 2018 10:16 am

Soruk wrote:
Tue Jul 10, 2018 6:59 am
cmorley wrote:
Tue Jul 10, 2018 6:45 am
1024MAK wrote:
Mon Jul 09, 2018 10:27 pm
Many BASIC implementations generate an error if there are mis-matched FOR-NEXT loops.

IMHO, that appears to be the best way of handling the problem.
I disagree. Perhaps it is a little confusing for the beginner but it is the equivalent to "break [n];" in C. A very useful feature for more advanced program flow control.
I agree with this - and since it was Brandy that got this going, since it's aim is an implementation of BBC BASIC, then its behaviour should be the same as existing "real" BBC BASIC versions.

(For the same reason, my Teletext implementation does one thing that's against the teletext spec, but it's what the SAA5050 and RISC OS's emulation of it both do.)
I agree with the sentiment but not how it is done (from the year 2018 not from the year 1982).

I would much prefer a proper 'Break' command, and not rely on closing the FOR correctly with a NEXT, as it makes the code much easier to read. But with the lack of space BITD I would rather have the harder to read method than nothing. These days I see no reason not to have a proper 'break' (but I guess you would have to leave the old method in for backwards compatability).

I put this 'missing' NEXT in the same camp as 'GOTO'. A neccessary evil for the time.

Edit: Summary. I agree with everyone, even if they dont agree with each other :)
Last edited by Elminster on Tue Jul 10, 2018 10:16 am, edited 1 time in total.

Soruk
Posts: 15
Joined: Mon Jul 09, 2018 10:31 am
Contact:

Re: BASIC FOR loops

Post by Soruk » Tue Jul 10, 2018 10:26 am

Coeus wrote:
Tue Jul 10, 2018 9:06 am
Soruk wrote:
Mon Jul 09, 2018 10:18 pm
Hi,

Your patch works a treat for that Mandelbrot thing over in the other thread.

May I include it in my fork of Brandy?
Yes, that's fine.
Thank you. Patch committed (along with some other fixes), and new update rolled out: V1.21.3 :)

User avatar
1024MAK
Posts: 7566
Joined: Mon Apr 18, 2011 4:46 pm
Location: Looking forward to summer in Somerset, UK...
Contact:

Re: BASIC FOR loops

Post by 1024MAK » Tue Jul 10, 2018 12:35 pm

But if you want a more complex loop structure, a different form of loop rather than a FOR - NEXT loop should be used, one that has a command that can cleanly break out of a loop.

And yes, many BASIC versions don't have such structures. Hence FOR - NEXT loops being pressed into service and used in unusual ways.

However, personally, if you are emulating BBC BASIC II, then that's fine. As with all these things, the important thing is that the details are documented.

Mark
For a "Complete BBC Games Archive" visit www.bbcmicro.co.uk NOW!
BeebWiki‬ - for answers to many questions...

Post Reply