google / wwwbasic

wwwBASIC is an implementation of BASIC that runs on Node.js and the Web.
Apache License 2.0
1.14k stars 61 forks source link

Better error handling for FUNCTION/SUB/GOSUB/RETURN clashes + underflow. #37

Open flagxor opened 6 years ago

flagxor commented 6 years ago

The current implementation of FUNCTION/SUB/GOSUB/RETURN assumes that they are only used in the correct order and never underflow. Someone needs to investigate what the "correct" behavior in various canonical BASICs is when mixing GOTO / GOSUB / RETURN with FUNCTION/SUB. I.e. can you do: FUNCTION Foo(x) GOTO Yikes END FUNCTION

FUNCTION Bar(x) Yikes: Bar = 3 END FUNCTION

And if so, what does it do? Same question with GOSUB/RETURN.

It may be even if allowed in interpreters, that this is just too weird and we should scream with an error. But it would be good to know what's canonical and document if we deviate.

We should probably also check for under/overflow.

FellippeHeitor commented 6 years ago

Labels are scope-dependant in QuickBASIC. The code above will yield a "Label not defined" error in Function Foo(x). If you had another Yikes label in FUNCTION Foo(x) that would be valid too - no duplicate if different scope.

Only case of cross-procedure GOTO is with ON ERROR GOTO, which always requires a label in the main module (unless you consider ON LOCAL ERROR GOTO, which is about another type of BASIC, not historical ones).

flagxor commented 6 years ago

Thanks Fellippe. Labels per function sounds sane.

Do you know offhand how names work in terms of different types of objects? Are variables, subroutines, functions, and labels all in one namespace, or is there some separation? (Things easily answered for one version, but figure QB64 folks have a better sense of over multiple versions etc.?)

FellippeHeitor commented 6 years ago

I couldn't answer about multiple versions. We QB64 folks are all about QBasic/QuickBASIC 4.5 only.

The answer here is: same namespace.

The exception is for SHARED variables. You can have a variable DIM SHARED in the main module, which makes it accessible in sub/functions, but then you can override it and have a local variable of the same name/type that is local to a procedure.

DIM SHARED a AS LONG
a = 1
mySub

SUB mySub
    DIM a AS LONG
    PRINT a
END SUB

That prints 0, not 1, as a is now local to mySub.