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-2016 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 __WORKSPACE_HH_DEFINED__ 22 #define __WORKSPACE_HH_DEFINED__ 23 24 #include <vector> 25 26 #include "Command.hh" 27 #include "PrimitiveOperator.hh" 28 #include "PrintContext.hh" 29 #include "QuadFunction.hh" 30 #include "Quad_CR.hh" 31 #include "Quad_DLX.hh" 32 #include "Quad_FIO.hh" 33 #include "Quad_RE.hh" 34 #include "Quad_RL.hh" 35 #include "Quad_SVx.hh" 36 #include "Quad_WA.hh" 37 #include "ScalarFunction.hh" 38 #include "Symbol.hh" 39 #include "SymbolTable.hh" 40 #include "SystemVariable.hh" 41 #include "UTF8_string.hh" 42 43 class Executable; 44 class StateIndicator; 45 46 //----------------------------------------------------------------------------- 47 /** 48 The symbol tables of the Workspace. We put them into a base class for 49 Workspace, so that they are initialized before all the members of Workspace. 50 **/ 51 /// The symbol tables of an APL workspace 52 class Workspace_0 53 { 54 protected: 55 /// the (user-defined) symbol table of this workspace. 56 SymbolTable symbol_table; 57 58 /// the (system aka distinguished name) symbol table of this workspace. 59 SystemSymTab distinguished_names; 60 }; 61 //----------------------------------------------------------------------------- 62 /** 63 An APL workspace. This structure contains everyting (variables, functions, 64 SI stack, etc.) belonging to a single APL workspace. 65 */ 66 /// An APL workspace 67 class Workspace : public Workspace_0 68 { 69 public: 70 /// Construct an empty workspace. 71 Workspace(); 72 73 /// return the current ⎕CT get_CT()74 static APL_Float get_CT() 75 { return the_workspace.v_Quad_CT.current(); } 76 77 /// return element \b pos of the current ⎕FC (pos should be 0..5) get_FC(int p)78 static APL_Char get_FC(int p) 79 { return the_workspace.v_Quad_FC.current()[p]; } 80 81 /// return the current ⎕IO get_IO()82 static APL_Integer get_IO() 83 { return the_workspace.v_Quad_IO.current(); } 84 85 /// return the current ⎕LX get_LX()86 static UCS_string get_LX() 87 { return UCS_string(*the_workspace.v_Quad_LX.get_apl_value()); } 88 89 /// return style and the current ⎕PP, and ⎕PW get_PrintContext(PrintStyle style)90 static PrintContext get_PrintContext(PrintStyle style) 91 { 92 return PrintContext(style, the_workspace.v_Quad_PP.current(), 93 the_workspace.v_Quad_PW.current()); 94 } 95 96 /// return the current ⎕PR get_PR()97 static const UCS_string get_PR() 98 { return the_workspace.v_Quad_PR.current(); } 99 100 /// return the current ⎕PW get_PP()101 static int get_PP() 102 { return the_workspace.v_Quad_PP.current(); } 103 104 /// return the current ⎕PW get_PW()105 static int get_PW() 106 { return the_workspace.v_Quad_PW.current(); } 107 108 /// set the current ⎕PW set_PW(int PW,const char * loc)109 static void set_PW(int PW, const char * loc) 110 { the_workspace.v_Quad_PW.assign(IntScalar(PW, loc), false, loc); } 111 112 /// the number of SI entries SI_entry_count()113 static int SI_entry_count() 114 { return SI_top() ? (SI_top()->get_level() + 1) : 0; } 115 116 /// the top of the SI stack (the SI pushed last) SI_top()117 static StateIndicator * SI_top() 118 { return the_workspace.top_SI; } 119 120 /// copy all allocated symbols into \b table of size \b table_size get_all_symbols()121 static std::vector<const Symbol *> get_all_symbols() 122 { return the_workspace.symbol_table.get_all_symbols(); } 123 124 /// lookup an existing user defined symbol. If not found, create one 125 /// (unless this would be a quad symbol) lookup_symbol(const UCS_string & symbol_name)126 static Symbol * lookup_symbol(const UCS_string & symbol_name) 127 { return the_workspace.symbol_table.lookup_symbol(symbol_name);} 128 129 /// increase the wait time for user input as reported in ⎕AI add_wait(APL_time_us diff)130 static void add_wait(APL_time_us diff) 131 { the_workspace.v_Quad_AI.add_wait(diff); } 132 133 /// return information in SI_top() get_error()134 static Error * get_error() 135 { return &StateIndicator::get_error(SI_top()); } 136 137 /// return reference to more info about last error more_error()138 static UCS_string & more_error() 139 { return the_workspace.more_error_info; } 140 141 /// erase the symbols in \b symbols from the symbol table erase_symbols(ostream & out,const UCS_string_vector & symbols)142 static void erase_symbols(ostream & out, const UCS_string_vector & symbols) 143 { the_workspace.symbol_table.erase_symbols(CERR, symbols); } 144 145 /// list all symbols (of category \b which) with names in \b from_to list(ostream & out,ListCategory which,UCS_string from_to)146 static void list(ostream & out, ListCategory which, UCS_string from_to) 147 { the_workspace.symbol_table.list(out, which, from_to); } 148 149 /// list all symbols with names in \b buf list_symbol(ostream & out,const UCS_string & buf)150 static ostream & list_symbol(ostream & out, const UCS_string & buf) 151 { return the_workspace.symbol_table.list_symbol(out, buf); } 152 153 /// add \b ufun to list of that were ⎕EX'ed while on the SI stack add_expunged_function(const UserFunction * ufun)154 static void add_expunged_function(const UserFunction * ufun) 155 { the_workspace.expunged_functions.push_back(ufun); } 156 157 /// return the symbol table of the current workspace. get_symbol_table()158 static const SymbolTable & get_symbol_table() 159 { return the_workspace.symbol_table; } 160 161 /// return the APL prompt get_prompt()162 static const UCS_string & get_prompt() 163 { return the_workspace.prompt; } 164 165 /// return the name of the current workspace. get_WS_name()166 static const UCS_string & get_WS_name() 167 { return the_workspace.WS_name; } 168 169 /// set the name of the current workspace. set_WS_name(const UCS_string & new_name)170 static void set_WS_name(const UCS_string & new_name) 171 { the_workspace.WS_name = new_name; } 172 173 /// Return all user-defined commands get_user_commands()174 static vector<Command::user_command> & get_user_commands() 175 { return the_workspace.user_commands; } 176 177 /// Create a new SI-entry on the SI stack. 178 static void push_SI(Executable * fun, const char * loc); 179 180 /// Remove the current SI-entry from the SI stack. 181 static void pop_SI(const char * loc); 182 183 /// return the Quad-RL (to be taken % mod) 184 static uint64_t get_RL(uint64_t mod); 185 186 /// clear ⎕EM and ⎕ET related errors (error entries on SI up to (including) 187 /// the next user-defined function 188 static void clear_error(const char * loc); 189 190 /// create and execute one immediate execution context 191 // (leave with TOK_ESCAPE) 192 static Token immediate_execution(bool exit_on_error); 193 194 /// clear the workspace 195 static void clear_WS(ostream & out, bool silent); 196 197 /// clear the SI 198 static void clear_SI(ostream & out); 199 200 /// print the SI on \b out 201 static void list_SI(ostream & out, SI_mode mode); 202 203 /// the topmost SI with parse mode PM_FUNCTION 204 static StateIndicator * SI_top_fun(); 205 206 /// the topmost SI with an error 207 static StateIndicator * SI_top_error(); 208 209 /// lookup an existing name (user defined or ⎕xx, var or function). 210 /// return 0 if not found. 211 static NamedObject * lookup_existing_name(const UCS_string & name); 212 213 /// lookup an existing symbol (user defined or ⎕xx). 214 static Symbol * lookup_existing_symbol(const UCS_string & symbol_name); 215 216 /// return the name to which \b lambda ia assigned (empty if not found) find_lambda_name(const UserFunction * lambda)217 static UCS_string find_lambda_name(const UserFunction * lambda) 218 { return the_workspace.symbol_table.find_lambda_name(lambda); } 219 220 /// save this workspace 221 static void save_WS(ostream & out, LibRef lib, const UCS_string & wsname, 222 bool name_from_WSID); 223 224 /// backup an existing file \b filename, return true on error 225 static bool backup_existing_file(const char * filename); 226 227 /// dump this workspace 228 static void dump_WS(ostream & out, LibRef lib, const UCS_string & wsname, 229 bool html, bool silent); 230 231 /// dump the commands in this workspace 232 static void dump_commands(ostream & out); 233 234 /// set or inquire the workspace ID 235 static void wsid(ostream & out, UCS_string arg, LibRef lib, bool silent); 236 237 /// load )DUMPed file from open file descriptor fd (closes fd) 238 static void load_DUMP(ostream & out, const UTF8_string & filename, int fd, 239 LX_mode with_LX, bool silent, 240 UCS_string_vector * object_filter); 241 242 /// load \b lib_ws into the_workspace, maybe set ⎕LX of the new WS. 243 static void load_WS(ostream & out, LibRef lib, const UCS_string & wsname, 244 UCS_string & quad_lx, bool silent); 245 246 /// copy objects from another workspace 247 static void copy_WS(ostream & out, LibRef lib, const UCS_string & wsname, 248 UCS_string_vector & objects, bool protection); 249 250 /// return a token for system function or variable \b ucs 251 static Token get_quad(const UCS_string & ucs, int & len); 252 253 /// return oldest SI entry that is running \b exex, or 0 if none 254 static StateIndicator * oldest_exec(const Executable * exec); 255 256 /// return true iff function \b funname is on the current call stack 257 static bool is_called(const UCS_string & funname); 258 259 /// write symbols for )OUT command 260 static void write_OUT(FILE * out, uint64_t & seq, 261 const UCS_string_vector & objects); 262 263 /// clear the marked flag in all values known in this workspace 264 static void unmark_all_values(); 265 266 /// print all owners of \b value 267 static int show_owners(ostream & out, const Value & value); 268 269 /// maybe remove functions for which ⎕EX has failed 270 static int cleanup_expunged(ostream & out, bool & erased); 271 272 // access to system variables. 273 // 274 #define ro_sv_def(x, _str, _txt) /** return x **/ static x & get_v_ ## x() \ 275 { return the_workspace.v_ ## x; } 276 #define rw_sv_def(x, _str, _txt) /** return ## x **/ static x & get_v_ ## x() \ 277 { return the_workspace.v_ ## x; } 278 rw_sv_def(Quad_Quad, "", "⎕") 279 rw_sv_def(Quad_QUOTE, "", "⍞") 280 #include "SystemVariable.def" 281 282 /// push a command. This is done when ⍎Command is performed and the command 283 /// would push the SI stack (i.e. )LOAD, )QLOAD, )CLEAR, or )SIC) push_Command(const UCS_string & command)284 static void push_Command(const UCS_string & command) 285 { the_workspace.pushed_command = command; } 286 287 /// return the pushed command get_pushed_Command()288 static const UCS_string & get_pushed_Command() 289 { return the_workspace.pushed_command; } 290 291 protected: 292 /// the name of the workspace 293 UCS_string WS_name; 294 295 // system variables. 296 // 297 #define ro_sv_def(x, _str, _txt) /** x **/ x v_ ## x; 298 #define rw_sv_def(x, _str, _txt) /** x **/ x v_ ## x; 299 rw_sv_def(Quad_Quad, "", "⎕") 300 rw_sv_def(Quad_QUOTE, "", "⍞") 301 #include "SystemVariable.def" 302 303 /// the APL prompt (6 blanks by default) 304 UCS_string prompt; 305 306 /// user defined functions that were ⎕EX'ed while on the SI stack 307 std::vector<const UserFunction *> expunged_functions; 308 309 /// more info about last error 310 UCS_string more_error_info; 311 312 /// the SI stack. Initially top_SI is 0 (empty stack) 313 StateIndicator * top_SI; 314 315 /// )LOAD, )QLOAD, )CLEAR, or )SIC 316 UCS_string pushed_command; 317 318 /// user defined commands 319 std::vector<Command::user_command> user_commands; 320 321 /// the current workspace (for objects that need one but don't have one). 322 static Workspace the_workspace; 323 }; 324 //----------------------------------------------------------------------------- 325 326 #endif // __WORKSPACE_HH_DEFINED__ 327