Closed andydotxyz closed 5 years ago
Sorry this looks huge as I had to reverse a bunch of local stuff. If you can do a Squash and Merge it should be just what you were looking for.
Thanks
Thanks for your contribution, once again.
Is there anything else you have pending, for your emulator project? If not I'll make a new release before the weekend.
I see from testing that I need to remove your addition of the newline in the PRINT function, but otherwise things seem to work well between this and the previous pull-request. (To be honest I could probably drop DUMP as a function, as that was for my own use and was never documented. But if it is useful I guess it could remain.)
Without this removal:
out.WriteRune('\n')
The output from our example-programs are all doubled:
frodo ~/go/src/github.com/skx/gobasic $ go build . && ./gobasic ./examples/00-print.bas
Hello, world
The contents of the variable 'a' are 3
The contents of the variable 'a$' are My name is String
String 'Steve' is 5 characters long
'Steve' is STILL 5 characters long
'Steve' is STILL 5 characters long
Thanks. That is all I have pending - I want to add “AUTO” support for line numbering but I suspect that will be in my emulator not this library.
DUMP is not something I am using and could be confused with *DUMP.
PRINT is complex. In my emulator the new line is quite important and, as far as I can tell to print without a new line should use PRINT “Inline”; (I.e. trailing semi-colon). http://www.riscos.com/support/developers/bbcbasic/part2/outputting.html
Happy to discuss further
You can run the UI that I’ve been building at https://github.com/andydotxyz/beebui/
The download from the previous release matches the bahaviour I've come to expect - which is that if you want a newline you add "\n". Without that you don't get one.
So this shows one line:
10 PRINT "HELLO"
20 PRINT " "
30 PRINT "WORLD"
frodo ~ $ gobasic t.bas
HELLO WORLDfrodo ~ $
But this does the right thing:
10 PRINT "HELLO, WORLD\n"
That might surprise some old sample programs, but I do recall having to use things like this, back in the past, so perhaps not:
10 PRINT "Steve", CHR$ 13
In conclusion I think I'll remove the mandatory newline, and I'll drop the DUMP primitive which was basically me testing that the builtin-stuff worked, when I moved as much as I could out of the core.
I trued to build your UI the other night, but it failed due to Glx issues. I'll try again later, because it seems like it will be a fun project when you get a little further along - I see the todo regarding I/O for example :)
(I did consider a renumber-utility, but never got round to it. Rewriting the lines is trivial, but having to parse the code to update the GOTO/GOSUB instructions would be fiddly and annoying :) )
I appreciate that this project has a history and that needs to be considered - but I didn't realise that you were expecting a PRINT declaration to always be inline. Check out the JSBeeb example at https://bbc.godbolt.org/ which does what I had understood.
If you need to keep the old behaviour then let's document it clearly and I can make a wrapper PRINT on my end that handles newline and ";" in the other way.
--
On the "TODO" side of things - should I add support for error output as well before release? i.e. an Environment.StdError() bufio.Writer?
I can definitely see that embedded users will have different preferences, and needs.
So I'd be happy with either :
\n
when you want it.Whichever you prefer is fine.
As for the error-handling, yes that is probably a good idea. At the moment there are a few places in the core where we output debugging information via fmt.Printf - but the only one that seems like it will be user-visible is:
fmt.Printf("WARN: Line %s is duplicated - GOTO/GOSUB behaviour is undefined\n", line)
The rest of the error-handling comes from catching the err
parameter from the lexer/parser/interpreter. So I guess you could handle that specially if you were embedded.
In short: I don't think there's more to fix than one obvious case, but adding a stderr wrapper/default and using it is probably sane and reasonable.
It's interesting to note that the INPUT command does require a newline, rather than just terminating on nil or other termination event - should we try to make them consistent? Sorry that I missed the example files - I was just running the tests and they all passed. Should we be running some examples within a test and validating the output?
I can make a PR that addresses the PRINT newline, and adds the error out stream - more for future use or external commands than the builtins I suspect. I'll have that in a day or s
It's interesting to note that the INPUT command does require a newline, rather than just terminating on nil or other termination event - should we try to make them consistent?
I'm not sure I understand your point here? I thought you were talking about the prompt but the the mention of termination event / nil confuses me ..
Sorry that I missed the example files - I was just running the tests and they all passed. Should we be running some examples within a test and validating the output?
That's not a bad idea. I'm in the github actions beta and can add it there. Though of course a naive go test ./...
won't run them.
I can make a PR that addresses the PRINT newline, and adds the error out stream - more for future use > or external commands than the builtins I suspect. I'll have that in a day or s[o]
Wonderful. Thank-you :)
I'm not sure I understand your point here? I thought you were talking about the prompt but the the mention of termination event / nil confuses me ..
Apologies I was meaning this: https://github.com/skx/gobasic/blob/master/eval/eval.go#L1707 - it requires a newline on the input, so the INPUT vs PRINT feels mismatched?
Now I understand, thanks.
In my view PRINT
's newline handling and the requirement of a newline for INPUT
aren't the same thing. After all input
reads a line of input in all BASIC implementations I'm familiar with, so it must read until the user presses return. If you wanted to read just a single character you'd usually use use INKEY
/INKEY$
instead.
(I haven't implemented INKEY
because I have no real-time/interactive utility/program in the repository. I setup the HTTP-server as a compromise between writing a UI, as you have, and having it all be file-based. I figured writing a decent interactive system/emulator of something would be more work than I wanted, because I just wanted to experiment with a-BASIC rather than dedicate a lot of time to sorting out the UI niggles and extra compatibility with a real-system. Right now I pretend I'm ZX Spectrum, but there are enough quirks and omissions that's only broadly true.)
Sorry I'm not trying to prolong this discussion - but your response made me think more about this... "reading until the user presses return" assumes an input/output stream in the same way that I was assuming newline would be used for the output :). In the examples you have "\n" at the end of every line so it's clearly a common requirement.
I think this is an artefact of the way that the tests needed a stin for running tests and were not able to verify the equivalent output. Should that be proliferated - or should it be change to be consistent one way or the other (either with, or without, trailing \n)...
Just a thought
I hope that #101 addresses these issues - apologies for the delay. I did not touch the INPUT as that seems to be less related to PRINT newlines than I had thought.
Replaces PR #99