1 /* 2 This file is part of GNU APL, a free implementation of the 3 ISO/IEC Standard 13751, "Programming Language APL, Extended" 4 5 Copyright (C) 2008-2015 Dr. Jürgen Sauermann 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #ifndef __STATE_INDICATOR_HH_DEFINED__ 22 #define __STATE_INDICATOR_HH_DEFINED__ 23 24 #include "Common.hh" 25 #include "DerivedFunction.hh" 26 #include "Executable.hh" 27 #include "Error.hh" 28 #include "Function.hh" 29 #include "Parser.hh" 30 #include "Prefix.hh" 31 #include "PrintOperator.hh" 32 33 //----------------------------------------------------------------------------- 34 /** 35 One entry of the state indicator (SI) of the APL interpreter. 36 Compared to e.g. C++, the state indicator is (one element of) the 37 function call stack of the interpreter. 38 */ 39 /// One entry of the state indicator (SI) of the APL interpreter 40 class StateIndicator 41 { 42 friend class XML_Loading_Archive; 43 friend class XML_Saving_Archive; 44 45 public: 46 /// constructor 47 StateIndicator(Executable * exec, StateIndicator * _par); 48 49 /// destructor 50 ~StateIndicator(); 51 52 /// continue this StateIndicator (to line N after →N back into it) 53 void goon(Function_Line N, const char * loc); 54 55 /// retry this StateIndicator (after →'') 56 void retry(const char * loc); 57 58 /// return true iff 59 /// (1) this SI entry is executing \b funname, or 60 /// (2) has resolved \b funname on its prefix parser stack 61 bool uses_function(const UserFunction * ufun) const; 62 63 /// Return the function name, or "*" for an immediate execution context 64 UCS_string function_name() const; 65 66 /// list the stack entry (for commands ]SI, )SI, and )SIS) 67 void list(ostream & out, SI_mode mode) const; 68 69 /// list the stack entry (for command ]SI) 70 void print(ostream & out) const; 71 72 /// print spaces according to level 73 ostream & indent(ostream & out) const; 74 75 /// return pointer to the current user function, statements, or execute get_executable()76 Executable * get_executable() 77 { return executable; } 78 79 /// return pointer to the current user function, statements, or execute get_executable() const80 const Executable * get_executable() const 81 { return executable; } 82 83 /// return the name of the parse mode 84 Unicode get_parse_mode_name() const; 85 86 /// return the current PC get_PC() const87 Function_PC get_PC() const 88 { return current_stack.get_PC(); } 89 90 /// set the current PC set_PC(Function_PC new_pc)91 void set_PC(Function_PC new_pc) 92 { current_stack.set_PC(new_pc); } 93 94 /// return the mode of this entry get_parse_mode() const95 ParseMode get_parse_mode() const 96 { return executable->get_parse_mode(); } 97 98 /// evaluate a →N statement. Update pc, return true iff context has changed 99 Token jump(Value_P val); 100 101 /// return the nesting level (oldest SI has level 0, next has level 1, ...) get_level() const102 SI_level get_level() const { return level; }; 103 104 /// return the current line number 105 Function_Line get_line() const; 106 107 /// Maybe print B (according to tag) and erase B 108 void statement_result(Token & result, bool trace); 109 110 /// Escape from \b user function (exit from each invocation until 111 /// immediate execution is reached) 112 void escape(); 113 114 /// execute token in body... 115 Token run(); 116 117 /// clear the marked bit in all parsers 118 void unmark_all_values() const; 119 120 /// print all owners of \b value 121 int show_owners(ostream & out, const Value & value) const; 122 123 /// print a short debug info 124 void info(ostream & out, const char * loc) const; 125 126 /// return the error related info in this context get_error(StateIndicator * si)127 static Error & get_error(StateIndicator * si) 128 { return si ? si->error : top_level_error; } 129 130 /// return the error related info in this context get_error(const StateIndicator * si)131 static const Error & get_error(const StateIndicator * si) 132 { return si ? si->error : top_level_error; } 133 134 /// return left arg 135 Value_P get_L(); 136 137 /// change left arg 138 void set_L(Value_P value); 139 140 /// return right arg 141 Value_P get_R(); 142 143 /// change right arg 144 void set_R(Value_P value); 145 146 /// return axis arg 147 Value_P get_X(); 148 149 /// change axis arg 150 void set_X(Value_P value); 151 152 /// return true if this SI entry has entered safe execution mode (via ⎕EC) is_safe_execution_start() const153 bool is_safe_execution_start() const 154 { if (!parent) return safe_execution_count > 0; 155 return safe_execution_count > parent->safe_execution_count; 156 } 157 158 /// return the number of pending ⎕ECs (or other safe execution contexts) get_safe_execution() const159 int get_safe_execution() const 160 { return safe_execution_count; } 161 162 /// set safe_execution mode set_safe_execution()163 void set_safe_execution() 164 { 165 if (parent) safe_execution_count = parent->safe_execution_count + 1; 166 else safe_execution_count = 1; 167 } 168 169 /// clear safe_execution mode clear_safe_execution()170 void clear_safe_execution() 171 { 172 if (parent) safe_execution_count = parent->safe_execution_count; 173 else safe_execution_count = 0; 174 } 175 176 /// get the current prefix parser get_prefix()177 Prefix & get_prefix() 178 { return current_stack; } 179 180 /// get the current prefix parser get_prefix() const181 const Prefix & get_prefix() const 182 { return current_stack; } 183 184 /// return the SI that has called this one get_parent() const185 StateIndicator * get_parent() const 186 { return parent; } 187 188 /// return the level at which sym is pushed for the nth. time 189 SI_level nth_push(const Symbol * sym, int from_tos) const; 190 191 /// a small storage for DerivedFunction objects. 192 DerivedFunctionCache fun_oper_cache; 193 194 /// error when )SI is empty 195 static Error top_level_error; 196 197 protected: 198 /// the user function that is being executed 199 Executable * executable; 200 201 /// the number of pending ⎕EC calles 202 int safe_execution_count; 203 204 /// The nesting level (of sub-executions) 205 const SI_level level; 206 207 /// details of the last error in this context. 208 Error error; 209 210 /// the current-stack of this context. 211 Prefix current_stack; 212 213 /// the StateIndicator that has called this one 214 StateIndicator * parent; 215 }; 216 //----------------------------------------------------------------------------- 217 218 #endif // __STATE_INDICATOR_HH_DEFINED__ 219