@@ -159,6 +159,106 @@ def _try_execute(engine: TinyEngine, source: str) -> None:
159159engine .output_text ()
160160print ()
161161
162+ def handle_meta_command (engine :TinyEngine ,cmd :str ,debug :list [bool ])-> bool :
163+ # normalize to lowercase, and collapse whitespace
164+ lower = " " .join (cmd .lower ().split ())
165+ line = cmd .strip ()
166+
167+ if lower == "help" :
168+ print (f"TINY REPL v{ TINY_VERSION } " )
169+ print ("Commands:" )
170+ print (" help - list commands and descriptions" )
171+ print (" quit - exit the REPL" )
172+ print (" import <file> - load functions from a .tiny file" )
173+ print (" reimport <file> - load functions, overwriting existing" )
174+ print (" clear vars - clear current local variables" )
175+ print (" clear all - reset engine state (all vars, funcs)" )
176+ print (" list - list variables and functions" )
177+ print (" list vars - list only current variables" )
178+ print (" list functions - list defined function names" )
179+ print (" debug on - show full Python tracebacks" )
180+ print (" debug off - concise errors; hide tracebacks" )
181+ return True
182+
183+ if lower == "quit" :
184+ return True
185+
186+ if lower in ("list" ,"list vars" ,"list functions" ):
187+ # Listing helpers
188+ def _print_vars ()-> None :
189+ frame = engine .current_frame
190+ vars_dict = getattr (frame ,"_vars" , {})# type: ignore[attr-defined]
191+ names = sorted (vars_dict .keys ())
192+ if not names :
193+ print ("[variables] (none)" )
194+ else :
195+ print ("[variables]" )
196+ for name in names :
197+ dtype ,value = vars_dict [name ]
198+ print (f"{ name } ={ value !r} :{ dtype } " )
199+
200+ def _print_functions ()-> None :
201+ funcs = engine .get_functions ()
202+ names = sorted (funcs .keys ())
203+ if not names :
204+ print ("[functions] (none)" )
205+ else :
206+ print ("[functions]" )
207+ sigs = engine .get_function_signatures ()
208+ for name in names :
209+ fn_ret_type ,fn_params = sigs [name ]
210+ print (f"{ fn_ret_type } { name } ({ ', ' .join (' ' .join (p )for p in fn_params )} )" )
211+
212+ if lower in ("list" ,"list vars" ):
213+ _print_vars ()
214+ if lower in ("list" ,"list functions" ):
215+ _print_functions ()
216+ return True
217+
218+ # Debug mode commands
219+ if lower == "debug on" :
220+ debug [0 ]= True
221+ print ("[debug: on]" )
222+ return True
223+ if lower == "debug off" :
224+ debug [0 ]= False
225+ print ("[debug: off]" )
226+ return True
227+
228+ # import commands
229+ if cmd .startswith ("import " ):
230+ try :
231+ _ ,rest = line .split (None ,1 )
232+ except ValueError :
233+ print ("usage: import <file>" )
234+ return True
235+ _load_functions_from_file (engine ,rest .strip (),overwrite = False ,debug = debug [0 ])
236+ return True
237+ if line .lower ().startswith ("reimport " ):
238+ try :
239+ _ ,rest = line .split (None ,1 )
240+ except ValueError :
241+ print ("usage: reimport <file>" )
242+ return True
243+ _load_functions_from_file (engine ,rest .strip (),overwrite = True ,debug = debug [0 ])
244+ return True
245+
246+ # clear/reset commands
247+ if lower == "clear vars" :
248+ if engine ._frames :# type: ignore[attr-defined]
249+ engine ._frames [- 1 ]= TinyFrame ()# type: ignore[attr-defined]
250+ else :
251+ engine .push_frame ()
252+ print ("[locals cleared]" )
253+ return True
254+
255+ if lower == "clear all" :
256+ engine = TinyEngine ()
257+ engine .push_frame ()
258+ print ("[engine reset]" )
259+ return True
260+
261+ return False
162262
163263def repl ()-> int :
164264print (f"TINY REPL v{ TINY_VERSION } — enter statements on one or more lines. Ctrl-C to cancel current input; `quit` to exit." )
@@ -187,99 +287,14 @@ def repl() -> int:
187287# If starting fresh, allow immediate REPL commands
188288if not buffer_lines :
189289cmd = line .strip ()
190- lower = cmd .lower ()
191290if not cmd :
192291# ignore empty input
193292continue
194- if lower == "help" :
195- print (f"TINY REPL v{ TINY_VERSION } " )
196- print ("Commands:" )
197- print (" help - list commands and descriptions" )
198- print (" quit - exit the REPL" )
199- print (" import <file> - load functions from a .tiny file" )
200- print (" reimport <file> - load functions, overwriting existing" )
201- print (" clear vars - clear current local variables" )
202- print (" clear all - reset engine state (all vars, funcs)" )
203- print (" list - list variables and functions" )
204- print (" list vars - list only current variables" )
205- print (" list functions - list defined function names" )
206- print (" debug on - show full Python tracebacks" )
207- print (" debug off - concise errors; hide tracebacks" )
208- continue
209- if lower == "quit" :
210- break
211- if lower == "list" or lower == "list vars" or lower == "list functions" :
212- # Listing helpers
213- def _print_vars ()-> None :
214- frame = engine .current_frame
215- vars_dict = getattr (frame ,"_vars" , {})# type: ignore[attr-defined]
216- names = sorted (vars_dict .keys ())
217- if not names :
218- print ("[variables] (none)" )
219- else :
220- print ("[variables]" )
221- for name in names :
222- dtype ,value = vars_dict [name ]
223- print (f"{ name } ={ value !r} :{ dtype } " )
224-
225- def _print_functions ()-> None :
226- funcs = getattr (engine ,"_functions" , {})# type: ignore[attr-defined]
227- names = sorted (funcs .keys ())
228- if not names :
229- print ("[functions] (none)" )
230- else :
231- print ("[functions]" )
232- for name in names :
233- print (f"{ name } " )
234-
235- if lower == "list" :
236- _print_vars ()
237- _print_functions ()
238- continue
239- if lower == "list vars" :
240- _print_vars ()
241- continue
242- if lower == "list functions" :
243- _print_functions ()
244- continue
245293
246- # Debug mode commands
247- if lower == "debug on" :
248- debug = True
249- print ("[debug: on]" )
250- continue
251- if lower == "debug off" :
252- debug = False
253- print ("[debug: off]" )
254- continue
294+ if handle_meta_command (engine ,cmd , [debug ]):
295+ if cmd .strip ().lower ()== "quit" :
296+ break
255297
256- if line .lower ().startswith ("import " ):
257- try :
258- _ ,rest = line .split (None ,1 )
259- except ValueError :
260- print ("usage: import <file>" )
261- continue
262- _load_functions_from_file (engine ,rest .strip (),overwrite = False ,debug = debug )
263- continue
264- if line .lower ().startswith ("reimport " ):
265- try :
266- _ ,rest = line .split (None ,1 )
267- except ValueError :
268- print ("usage: reimport <file>" )
269- continue
270- _load_functions_from_file (engine ,rest .strip (),overwrite = True ,debug = debug )
271- continue
272- if lower == "clear vars" :
273- if engine ._frames :# type: ignore[attr-defined]
274- engine ._frames [- 1 ]= TinyFrame ()# type: ignore[attr-defined]
275- else :
276- engine .push_frame ()
277- print ("[locals cleared]" )
278- continue
279- if lower == "clear all" :
280- engine = TinyEngine ()
281- engine .push_frame ()
282- print ("[engine reset]" )
283298continue
284299
285300# Treat as part of TINY input