From: tur b. <mai...@gm...> - 2020-06-08 10:58:38
|
Hi just wished to expand my knowledge base with forth, the stack pointer increases during runtime and does not decrease unless using certain commands if etc, can somebody explain what happens when sp and thus the stack gets full please Thank you |
From: Martin N. <amf...@mg...> - 2020-06-13 11:03:40
|
On Mon, 8 Jun 2020 11:58:15 +0100 tur bine <mai...@gm...> wrote: > Hi just wished to expand my knowledge base with forth, the stack > pointer increases during runtime and does not decrease unless using > certain commands if etc, can somebody explain what happens when sp > and thus the stack gets full please > Thank you Your program will crash! AmForth, certainly on the AVR, makes no run-time checks on stack bounds. In the firing line are: the return stack (RP), the Terminal Input Buffer (TIB), any variables ALLOTed, User Variables (UP), etc. The Forth approach is that it's up to you to test your words as you write them for offending behaviour. The Forth development environment also makes this dead easy. For example to test '+' type: 3 2 + . . The first dot prints the answer of 5. The second dot THROWs error 4 as the stack has under-flowed. Thus you have proven '+' uses two items from the stack and leaves just one. '?stack' checks the Computation Stack only and is part of 'interpret' which is taking what you typed and executing it a word at a time. -- Regards, Martin Nicholas. E-mail: rep...@mg... (Address will be valid throughout 2020). |
From: Erich W. <ew....@na...> - 2020-06-27 08:56:05
|
Hello, tur bine writes: > Hi just wished to expand my knowledge base with forth, the stack pointer > increases during runtime and does not decrease unless using certain > commands if etc, can somebody explain what happens when sp and thus the > stack gets full please Martin has answered your question already. I would like to add a a few bits. 1. The exact region, how memory (RAM) is used, is documented in > http://amforth.sourceforge.net/TG/AVR8.html (similar for the other targets). More precisely > http://amforth.sourceforge.net/TG/AVR8.html#ramfigure shows that in this partcular case, the datastack grows towards the HLD/PAD area. This might be quite some distance, but Martins answer holds: if you overwrite something "important", then most likely your programm will crash. I cannot yet explain the purpose of the two different layouts, but I assume that the latter is needed to accomodate one or more of the other hardware targets. I have not tried to understand this so far. I do have a hifive1 board, so it is on the list to understand better, what the boundary conditions are (beside using a different asm format). 2. When using the multitasker, you will run into finite stack space conditions much sooner. To define a task, you specifiy the size of the data/return stacks explicitly. If your nice programm crashes once in a while, I would strongly recommend to increase stack sizes as a first experiment. Been there, done that. :-) The command " .res " does actually output some information about stack usage. And it's worthwile to study its code. > .../avr8/lib/dot-res.frt 3. When using the multitasker, the above mentioned HLD/PAD area is interesting as well, because currently there is only one such area shared between all tasks. I have been bitten by this: Task A runs the command loop on usart0; Task B runs a function, which writes to an LCDisplay via spi or i2c. Please note: two tasks using different hw periphery with distinct versions of " emit ". However, both tasks used pictured numeric output (this is actually quite hard to avoid :-) And once in a while, the formated output bound for the LCD would overwrite the output bound for the serial interface. It "looked" like amforth was doing calculation errors once in a while ... As I have mentioned a while back, I would like to either provide task-local areas for HLD/PAD or play with semaphores to solve this. However, my days are much too short --- as I'm sure everyone elses are as well :-) ------------------------------------------------------------- While rereading your question, it occurs to me that you might talk about FLASH rather than RAM. When compiling a word, the new word will consume some flash space. DP points to the next available position. The dictionary grows from low flash addresses towards higher ones. On AVR8 it will eventually hit the NRWW section boundary. I expect that compiling will fail at this point, because the NRWW section is kind of protected. I have not tried this. In order to reclaim FLASH memory without erasing/flashing the controller, you can use the word " marker " (which you need to load first) Example: > my_code.frt >| \ maybe more includes needed here ... >| include lib-avr8/forth2012/core-ext/marker.frt >| >| marker --main-- >| >| \ ... your code goes here Now when you don't like your code anymore, you can call > --main-- ok > on the serial connection. This word will reset book-keeping in such a way, that everything from " --main-- " and onward is not available any more. Please note that " --main-- " itself vanishes as well and needs to be set anew. There is one symptom related to this. If you load a lengthy programm for the first time, it takes so long. If you load it again, without reclaiming flash by calling the marker before --- then it will take a little longer every time. This is noticable. This is caused by the increasing length of the wordlist. To find a word at the low end of the list, it will take increasingly longer, because the length of the wordlist increases. And guess what, all the important words stay at the low end of the wordlist. Thanks for reading, and welcome to the list! Cheers, Erich -- May the Forth be with you ... |
From: Tristan W. <ho...@tj...> - 2020-07-06 09:53:19
|
Hello, I have modified amforth-shell.py to run under python3 and put up a patch here https://tjnw.co.uk/new-shell/doc/ as the patch seemed a little too large for a mailing list. Best wishes, Tristan |
From: Mark R. <cab...@gm...> - 2020-07-06 10:15:39
|
Super. I just patched my local repo. All I had to do was to add the python3-serial package (debian buster) and change the defaults for the serial port and it fired right up. I'll try it next time I'm passing files around to see how things go here. Thank you, Mark On Mon, Jul 6, 2020 at 12:53 PM Tristan Williams <ho...@tj...> wrote: > Hello, > > I have modified amforth-shell.py to run under python3 and put up a > patch here > > https://tjnw.co.uk/new-shell/doc/ > > as the patch seemed a little too large for a mailing list. > > Best wishes, > Tristan > > > > > _______________________________________________ > Amforth-devel mailing list for http://amforth.sf.net/ > Amf...@li... > https://lists.sourceforge.net/lists/listinfo/amforth-devel > |
From: Erich W. <ew....@na...> - 2020-08-01 07:53:55
|
Hello Tristan, Tristan Williams writes: > Hello, > > I have modified amforth-shell.py to run under python3 and put up a > patch here > > https://tjnw.co.uk/new-shell/doc/ > > as the patch seemed a little too large for a mailing list. Thanks for the patch. Commit r2447 is yours. The patch is nicely readable (even by a mostly python-illiterate maintainer :) and condenses to a few cases of syntax change: - print -> print() - OBJ.has_key(X) -> X in OBJ - except X, e: -> except X as e: - add encode() decode() to character handling I applied the patch mostly verbatim and checked that the line changed in r2443 did not disappear. It didn't :-) This being said, the patch was something short of 300 lines. It is NOT too big for the mailing list. And in fact, the mailing list is our public archive ... so I add the committed version of the patch below for everyones inspiration. > > Best wishes, > Tristan Happy Forthing, Erich --- patch ---------------------------------------------------------------------- ew@ceres:~/eGeek/sourceforge.net/amforth-code/trunk 45 > svn diff -r2446 tools/amforth-shell.py Password: Index: tools/amforth-shell.py =================================================================== --- tools/amforth-shell.py (revision 2446) +++ tools/amforth-shell.py (working copy) @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # # pySerial based upload & interpreter interaction module for amforth. # @@ -87,7 +87,7 @@ # # #include <file> # Upload the named <file> before proceeding further. -# +# # #require <file> # Like #include but would skip if <file> was already uploaded # during the shell session. @@ -258,7 +258,7 @@ import re import readline import serial -import StringIO +from io import StringIO import subprocess import sys import traceback @@ -388,7 +388,7 @@ interact_directives = [ "#cd", "#edit", "#require", "#include", "#directive", "#ignore-error", "#error-on-output", "#string-start-word", "#quote-char-word", - "#timeout", "#timeout-next", "#update-words", "#exit", + "#timeout", "#timeout-next", "#update-words", "#exit", "#update-cpu", "#update-files" ] # standard words are usually uppercase, but amforth needs @@ -487,7 +487,7 @@ "EDITOR","STATE","[ELSE]","[IF]","[THEN]", # *** Wordset TOOLS-EXT-obsolescent "FORGET", - # *** Tester wordset + # *** Tester wordset "T{", "}T", ] def __init__(self, serial_port="/dev/amforth", rtscts=False, speed=38400): @@ -511,7 +511,7 @@ self._last_error = () self._last_edited_file = None self._config = BehaviorManager() - if os.environ.has_key("AMFORTH_LIB"): + if "AMFORTH_LIB" in os.environ: self._search_list = os.environ["AMFORTH_LIB"].split(":") else: self._search_list=["."] @@ -592,9 +592,9 @@ except AMForthException: return 1 except KeyboardInterrupt: - print "\nBye bye" - except Exception, e: - print "\n---- Unexpected exception ----" + print( "\nBye bye") + except Exception as e: + print( "\n---- Unexpected exception ----") traceback.print_exc() return 1 finally: @@ -605,10 +605,10 @@ def parse_arg(self): "Argument parsing used when module is used as a script" - parser = argparse.ArgumentParser(description="Interact with AMForth", + parser = argparse.ArgumentParser(description="Interact with AMForth", epilog=""" -The environment variable AMFORTH_LIB can be set with to a colon (:) separated -list of directories that are recursivly searched for file names. If not set, +The environment variable AMFORTH_LIB can be set with to a colon (:) separated +list of directories that are recursivly searched for file names. If not set, the current work directory is used instead. The script assumes to be located in the standard amforth installation under @@ -698,7 +698,7 @@ timeout, False, self.serial_rtscts, None, False) - except serial.SerialException, e: + except serial.SerialException as e: raise AMForthException("Serial port connect failure: %s" % str(e)) def serial_disconnect(self): @@ -728,7 +728,7 @@ try: self.send_line("\n") # Get empty line echo to make sure ready self.read_response() # Throw away the response. - except serial.SerialException, e: + except serial.SerialException as e: self.progress_callback("Error", None, str(e)) raise AMForthException("Failed to get prompt: %s" % str(e)) finally: @@ -745,18 +745,18 @@ fpath=filename self.progress_callback("Information", None, "using "+ filename+" verbatim") else: - if not self._filedirs.has_key(filename): + if not filename in self._filedirs: self.progress_callback("Error", None, "file "+ filename+" not found in search path") raise AMForthException("file " + filename + " not found in search path") if len(self._filedirs[filename])!=1: # oops, too many files or no one at all found? - self.progress_callback("Error", None, "Wrong # of file "+ filename+" found in search path") # add this line above the one below + self.progress_callback("Error", None, "Wrong # of file " + filename + " found in search path") # add this line above the one below raise AMForthException("Wrong # of file occurances: " + filename + " ("+str(len(self._filedirs[filename]))+")\n\t"+"\n\t".join(self._filedirs[filename])) self.progress_callback("Information", None, "using "+ filename+" from"+ self._filedirs[filename][0]) fpath = os.path.join(self._filedirs[filename][0], filename) self._config.push_file(fpath) fdir=os.path.dirname(fpath) - print "**** " + self._config.current_behavior.working_directory + print ("**** " + self._config.current_behavior.working_directory) if os.path.isabs(fdir): dirpath = os.path.normpath(fdir) else: @@ -767,7 +767,7 @@ try: try: self.find_prompt() - except AMForthException, e: + except AMForthException as e: self.progress_callback("Error", None, str(e)) raise if self._amforth_cpu=="": @@ -777,17 +777,17 @@ try: with open(fpath, "r") as f: self._send_file_contents(f) - except (OSError, IOError), e: + except (OSError, IOError) as e: self.progress_callback("Error", None, str(e)) raise AMForthException("Unknown file: " + fpath) self._last_error = () finally: - print "**** " + self._config.current_behavior.working_directory + print ("**** " + self._config.current_behavior.working_directory) self._config.pop_file() self._serialconn.timeout = self._config.current_behavior.timeout try: os.chdir(self._config.current_behavior.working_directory) - except OSError, e: + except OSError as e: errmsg = ("Failed to change to directory '%s': %s" % (self._config.current_behavior.working_directory, str(e))) @@ -806,7 +806,7 @@ self._serialconn.timeout = self._config.current_behavior.timeout try: os.chdir(self._config.current_behavior.working_directory) - except OSError, e: + except OSError as e: errmsg = ("Failed to change to directory '%s': %s" % (self._config.current_behavior.working_directory, str(e))) @@ -829,7 +829,7 @@ directive, directive_arg) = self.preprocess_line(full_line, in_comment, self.upload_directives) - except AMForthException, e: + except AMForthException as e: self._record_error(lineno) self.progress_callback("Error", lineno, full_line) self.progress_callback("Error", None, str(e)) @@ -848,7 +848,7 @@ continue try: self.send_line(line) - except AMForthException, e: + except AMForthException as e: self._record_error(lineno) self.progress_callback("Error", lineno, full_line) self.progress_callback("Error", None, str(e)) @@ -875,7 +875,6 @@ raise AMForthException(errmsg) elif self._log: self._log.write(line + "\n") - else: self.progress_callback("Error", None, response) if not self._config.current_behavior.ignore_errors: @@ -1010,7 +1009,7 @@ elif directive == "#timeout": try: timeout = float(directive_arg) - except ValueError, e: + except ValueError as e: self.progress_callback("Error", None, "Invalid timeout") return self._config.current_file_behavior.timeout = timeout @@ -1017,7 +1016,7 @@ elif directive == "#timeout-next": try: timeout = float(directive_arg) - except ValueError, e: + except ValueError as e: self.progress_callback("Error", None, "Invalid timeout") return behavior = copy.deepcopy(self._config.current_behavior) @@ -1078,14 +1077,15 @@ if self.debug: sys.stderr.write(repr(c)[1:-1]+"->") sys.stderr.flush() - self._serialconn.write(c) + self._serialconn.write(c.encode()) self._serialconn.flush() r = self._serialconn.read(1) # Read echo of character we just sent + r=r.decode() while r and (r != c or (c == '\t' and r != ' ')): if self.debug: sys.stderr.write(repr(r)[1:-1]) sys.stderr.flush() - r = self._serialconn.read(1) + r = self._serialconn.read(1).decode() if not r: raise AMForthException("Input character not echoed.") if self.debug: @@ -1098,7 +1098,7 @@ if self.debug: sys.stderr.write("|r( )") response = "" - r = self._serialconn.read(1) + r = self._serialconn.read(1).decode() while r != "": if self.debug: sys.stderr.write(repr(r)[1:-1]) @@ -1111,7 +1111,7 @@ elif self.amforth_error_cre.search(response) is not None: response = response[:-3] # Don't return prompt in response break - r = self._serialconn.read(1) + r = self._serialconn.read(1).decode() if not response: response = "Timed out waiting for ok response" if self.debug: @@ -1120,9 +1120,9 @@ def print_progress(self, type, lineno, info): if not lineno: - print "|%s=%s" % (type[:1], info) + print("|%s=%s" % (type[:1], info)) else: - print "|%s|%5d|%s" % (type[:1], lineno, info) + print ("|%s|%5d|%s" % (type[:1], lineno, info)) def interact(self): self.progress_callback("Interact", None, @@ -1131,7 +1131,7 @@ self._config.push_file(None) try: self.find_prompt() - except AMForthException, e: + except AMForthException as e: self.progress_callback("Error", None, str(e)) self._config.pop_file() raise @@ -1143,15 +1143,15 @@ prompt="("+self._amforth_cpu+")> " else: prompt="> " - full_line = raw_input(prompt) - except EOFError, e: - print "" + full_line = input(prompt) + except EOFError as e: + print("") break self._config.advance_line() self._serialconn.timeout = self._config.current_behavior.timeout try: os.chdir(self._config.current_behavior.working_directory) - except OSError, e: + except OSError as e: errmsg = ("Failed to change to directory '%s': %s" % (self._config.current_behavior.working_directory, str(e))) @@ -1183,7 +1183,7 @@ elif self._last_edited_file: self.edit_file(self._last_edited_file) else: - print "No file to edit" + print("No file to edit") continue self.handle_common_directives(directive, directive_arg) if directive == "#include" or directive == "#require": @@ -1193,14 +1193,14 @@ continue else: self.send_line(line) - print self.read_response() - except AMForthException, e: - print "Error: " + str(e) + print (self.read_response()) + except AMForthException as e: + print ("Error: " + str(e)) self._config.pop_file() self._serialconn.timeout = self._config.current_behavior.timeout try: os.chdir(self._config.current_behavior.working_directory) - except OSError, e: + except OSError as e: errmsg = ("Failed to change to directory '%s': %s" % (self._config.current_behavior.working_directory, str(e))) @@ -1218,7 +1218,7 @@ ".frt-interact.history") try: readline.read_history_file(histfn) - except IOError, e: + except IOError as e: pass self._update_words() self._update_cpu() @@ -1277,7 +1277,7 @@ # print f fpath=os.path.realpath(os.path.join(root, f)) fpathdir=os.path.dirname(fpath) - if self._filedirs.has_key(f): + if f in self._filedirs: # check for duplicates for d in self._filedirs[f]: if d==fpathdir: @@ -1359,7 +1359,7 @@ try: subprocess.call(cmd) self._last_edited_file = filename - except OSError, e: + except OSError as e: raise AMForthException("Could not start editor: "+self.editor) else: raise AMForthException("No editor specified. Use --editor or EDITOR environment variable") -------------------------------------------------------------------------------- -- May the Forth be with you ... |