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 __SYSTEM_VARIABLE_HH_DEFINED__
22 #define __SYSTEM_VARIABLE_HH_DEFINED__
23 
24 #include "Id.hh"
25 #include "Parallel.hh"
26 #include "Symbol.hh"
27 
28 #include <sys/time.h>
29 
30 //-----------------------------------------------------------------------------
31 /**
32     Base class for all system variables (Quad variables).
33  */
34 ///  Base class for all APL system variables
35 class SystemVariable : public Symbol
36 {
37 public:
38    /// Construct a \b SystemVariable with \b Id \b id
SystemVariable(Id id)39    SystemVariable(Id id)
40    : Symbol(id)
41    {}
42 
43    /// return the TokenTag for this system variable
get_token()44    Token get_token()
45       { return Token(TokenTag(ID::get_token_tag(get_Id())), this); }
46 
47    /// overloaded Symbol::print().
48    virtual ostream & print(ostream & out) const;
49 
50    /// overloaded Symbol::assign().
51    virtual void assign(Value_P value, bool clone, const char * loc);
52 
53    /// overloaded Symbol::assign_indexed().
54    virtual void assign_indexed(Value_P X, Value_P value);
55 
56    /// overloaded Symbol::get_attributes().
57    virtual void get_attributes(int mode, Cell * dest) const;
58 
59    /// system vars cannot be expunged.
expunge()60    virtual int expunge() { return 0; }
61 
62    /// do not allow (...⎕xxx)←...
resolve_lv(const char * loc)63    virtual Token resolve_lv(const char * loc)
64       { SYNTAX_ERROR; }
65 };
66 //-----------------------------------------------------------------------------
67 /**
68     A system variable that cannot be localized (push and pop have no effect).
69  */
70 /// Base class for all APL system variables that cannot be localized
71 class NL_SystemVariable : public SystemVariable
72 {
73 public:
74 public:
75    /// Constructor.
NL_SystemVariable(Id id)76    NL_SystemVariable(Id id)
77    : SystemVariable(id)
78    {}
79 protected:
80    /// overloaded Symbol::push()
push()81    virtual void push() {}
82 
83    /// overloaded Symbol::push_label()
push_label(Function_Line label)84    virtual void push_label(Function_Line label) {}
85 
86    /// overloaded Symbol::push_function()
push_function(Function * function)87    virtual void push_function(Function * function) {}
88 
89    /// overloaded Symbol::push_value()
push_value(Value_P value)90    virtual void push_value(Value_P value) {}
91 
92    /// overloaded Symbol::pop()
pop()93    virtual void pop() { }
94 };
95 //-----------------------------------------------------------------------------
96 /**
97     A read-only system variable (push, pop, and assign are ignored).
98  */
99 /// Base class for all read-only APL system variables
100 class RO_SystemVariable : public NL_SystemVariable
101 {
102 public:
103    /// Constructor.
RO_SystemVariable(Id id)104    RO_SystemVariable(Id id)
105    : NL_SystemVariable(id)
106    {}
107 
108 protected:
109    /// overloaded Symbol::assign()
assign(Value_P value,bool clone,const char * loc)110    virtual void assign(Value_P value, bool clone, const char * loc) {}
111 
112    /// overloaded Symbol::assign_indexed()
assign_indexed(Value_P X,Value_P value)113    virtual void assign_indexed(Value_P X, Value_P value) {}
114 
115    /// overloaded Symbol::is_readonly()
is_readonly() const116    virtual bool is_readonly() const   { return true; }
117 
118    /// overloaded Symbol::resolve(). Since push(), pop(), and assign()
119    /// do nothing, we can call get_apl_value() directly.
resolve(Token & token,bool left)120    virtual void resolve(Token & token, bool left)
121       { if (!left)   new (&token) Token(TOK_APL_VALUE1, get_apl_value()); }
122 };
123 //-----------------------------------------------------------------------------
124 /**
125    System variable Quad-AI (Account Information)
126  */
127 /// The class implementing ⎕AI
128 class Quad_AI : public RO_SystemVariable
129 {
130 public:
131    /// Constructor.
132    Quad_AI();
133 
134    /// increase the time waiting for user input
add_wait(APL_time_us diff)135    void add_wait(APL_time_us diff)
136    { user_wait += diff; }
137 
138 protected:
139    /// when the interpreter was started
140    const APL_time_us session_start;
141 
142    /// time waiting for user input.
143    APL_time_us user_wait;
144 
145    /// overloaded Symbol::get_apl_value().
146    virtual Value_P get_apl_value() const;
147 };
148 //-----------------------------------------------------------------------------
149 /**
150    System variable Quad-ARG (command line arguments of the interpreter)
151  */
152 /// The class implementing ⎕ARG
153 class Quad_ARG : public RO_SystemVariable
154 {
155 public:
156    /// Constructor.
157    Quad_ARG();
158 
159 protected:
160    /// overloaded Symbol::get_apl_value()
161    virtual Value_P get_apl_value() const;
162 };
163 //-----------------------------------------------------------------------------
164 /**
165    System variable Quad-AV (Atomic Vector)
166  */
167 /// The class implementing ⎕AV
168 class Quad_AV : public RO_SystemVariable
169 {
170 public:
171    /// Constructor.
172    Quad_AV();
173 
174    /// return ⎕AV[pos - ⎕IO]
175    static Unicode indexed_at(uint32_t pos);
176 
177    /// a static ⎕AV
178    static Unicode qav[MAX_AV];
179 };
180 //-----------------------------------------------------------------------------
181 /**
182    System variable Quad-CT (Comparison Tolerance)
183  */
184 /// The class implementing ⎕CT
185 class Quad_CT : public SystemVariable
186 {
187 public:
188    /// constructor
189    Quad_CT();
190 
191    /// return the current comparison tolerance. MUST NOT CALL get_apl_value()
192    /// because it can be called from parallel Cell functions
current() const193    APL_Float current() const
194       { return get_first_cell()->get_real_value(); }
195 
196 protected:
197    /// overloaded Symbol::assign()
198    virtual void assign(Value_P value, bool clone, const char * loc);
199 
200    // overloaded Symbol::push()
push()201    virtual void push()
202       {
203         Symbol::push();
204         Symbol::assign(FloatScalar(DEFAULT_Quad_CT, LOC), false, LOC);
205       }
206 };
207 //-----------------------------------------------------------------------------
208 /**
209    System variable Quad-EM (Event Message)
210  */
211 /// The class implementing ⎕EM
212 class Quad_EM : public RO_SystemVariable
213 {
214 public:
215    /// Constructor.
Quad_EM()216    Quad_EM()
217    : RO_SystemVariable(ID_Quad_EM)
218    {}
219 
220 protected:
221    /// overloaded Symbol::get_apl_value()
222    virtual Value_P get_apl_value() const;
223 };
224 //-----------------------------------------------------------------------------
225 /**
226    System variable Quad-ET (Event Type).
227  */
228 /// The class implementing ⎕ET
229 class Quad_ET : public RO_SystemVariable
230 {
231 public:
232    /// Constructor.
Quad_ET()233    Quad_ET() : RO_SystemVariable(ID_Quad_ET)
234    {}
235 
236 protected:
237    /// overloaded Symbol::get_apl_value().
238    virtual Value_P get_apl_value() const;
239 };
240 //-----------------------------------------------------------------------------
241 /**
242    System variable Quad-FC (Format Control).
243  */
244 /// The class implementing ⎕FC
245 class Quad_FC : public SystemVariable
246 {
247 public:
248    /// Constructor.
249    Quad_FC();
250 
251    /// return the current format control (used by Workspace::get_FC())
current() const252    const UCS_string current() const
253       { return UCS_string(*get_apl_value()); }
254 
255 protected:
256    /// overloaded Symbol::assign().
257    virtual void assign(Value_P value, bool clone, const char * loc);
258 
259    /// overloaded Symbol::assign_indexed().
260    virtual void assign_indexed(Value_P X, Value_P value);
261 
262    /// overloaded Symbol::assign_indexed().
263    virtual void assign_indexed(IndexExpr & IX, Value_P value);
264 
265    // overloaded Symbol::push()
266    virtual void push();
267 };
268 //-----------------------------------------------------------------------------
269 /**
270    System variable Quad-IO (Index Origin).
271  */
272 /// The class implementing ⎕IO
273 class Quad_IO : public SystemVariable
274 {
275 public:
276    /// Constructor.
277    Quad_IO();
278 
279    /// Return the current index origin. MUST NOT CALL get_apl_value()
280    /// because it can be called from parallel Cell functions
current() const281    APL_Integer current() const
282       { return get_first_cell()->get_int_value(); }
283 
284 protected:
285    /// overloaded Symbol::assign().
286    virtual void assign(Value_P value, bool clone, const char * loc);
287 
288    // overloaded Symbol::push()
push()289    virtual void push()
290       {
291         Symbol::push();
292         Symbol::assign(IntScalar(1, LOC), false, LOC);
293       }
294 };
295 //-----------------------------------------------------------------------------
296 /**
297    System variable Quad-L (Left Argument).
298  */
299 /// The class implementing ⎕L
300 class Quad_L : public NL_SystemVariable
301 {
302 public:
303    /// Constructor.
304    Quad_L();
305 
306    /// overloaded Symbol::save()
save(ostream & out) const307    virtual void save(ostream & out) const {}
308 
309 protected:
310    /// overloaded Symbol::assign()
311    virtual void assign(Value_P value, bool clone, const char * loc);
312 
313    /// overloaded Symbol::get_apl_value().
314    virtual Value_P get_apl_value() const;
315 };
316 //-----------------------------------------------------------------------------
317 /**
318    System variable Quad-LC (Line Counter).
319  */
320 /// The class implementing ⎕LC
321 class Quad_LC : public RO_SystemVariable
322 {
323 public:
324    /// Constructor.
325    Quad_LC();
326 
327 protected:
328    /// overloaded Symbol::get_apl_value().
329    virtual Value_P get_apl_value() const;
330 };
331 //-----------------------------------------------------------------------------
332 /**
333    System variable Quad-LX (Latent Expression).
334  */
335 /// The class implementing ⎕LX
336 class Quad_LX : public NL_SystemVariable
337 {
338 public:
339    /// Constructor.
340    Quad_LX();
341 
342 protected:
343    /// overloaded Symbol::assign().
344    virtual void assign(Value_P value, bool clone, const char * loc);
345 
346    /// overloaded Symbol::assign_indexed()
assign_indexed(Value_P X,Value_P value)347    virtual void assign_indexed(Value_P X, Value_P value) {}
348 
349 };
350 //-----------------------------------------------------------------------------
351 /**
352    System variable Quad-PP (Printing Precision).
353  */
354 /// The class implementing ⎕PP
355 class Quad_PP : public SystemVariable
356 {
357 public:
358    /// Constructor.
359    Quad_PP();
360 
361    /// Return the current print precision. MUST NOT CALL get_apl_value()
362    /// because it can be called from parallel Cell functions
current() const363    APL_Integer current() const
364       { return get_first_cell()->get_int_value(); }
365 
366 protected:
367    /// overloaded Symbol::assign().
368    virtual void assign(Value_P value, bool clone, const char * loc);
369 
370    // overloaded Symbol::push()
push()371    virtual void push()
372       {
373         Symbol::push();
374         Symbol::assign(IntScalar(DEFAULT_Quad_PP, LOC), false, LOC);
375       }
376 };
377 //-----------------------------------------------------------------------------
378 /**
379    System variable Quad-PR (Prompt Replacement).
380  */
381 /// The class implementing ⎕PR
382 class Quad_PR : public SystemVariable
383 {
384 public:
385    /// Constructor.
386    Quad_PR();
387 
388    /// Return the current prompt replacement.
current() const389    const UCS_string current() const
390       { return  UCS_string(*get_apl_value()); }
391 
392 protected:
393    /// overloaded Symbol::assign().
394    virtual void assign(Value_P value, bool clone, const char * loc);
395 
396    // overloaded Symbol::push()
push()397    virtual void push()
398       {
399         Symbol::push();
400         Symbol::assign(CharScalar(UNI_ASCII_SPACE, LOC), false, LOC);
401       }
402 };
403 //-----------------------------------------------------------------------------
404 /**
405    System variable Quad-PS (Print Style). This variable controls the formatting
406    of APL values (classical APL or DISPLAY style).
407  */
408 /// The class implementing ⎕PS
409 class Quad_PS : public SystemVariable
410 {
411 public:
412    /// Constructor.
413    Quad_PS();
414 
415    /// Return the current print style. MUST NOT CALL get_apl_value()
416    /// because it can be called from parallel Cell functions
current() const417    PrintStyle current() const
418       { switch (style)
419            {
420              case 0: return PR_APL;
421              case 1: return PR_APL_FUN;
422              case 2: return PR_BOXED_CHAR;
423              case 3: return PR_BOXED_GRAPHIC;
424              default: return PST_NONE;
425            }
426       }
427 
428    /// return the quotient print style
get_print_quotients() const429    bool get_print_quotients() const
430       { return print_quotients; }
431 
432 protected:
433    /// overloaded Symbol::assign().
434    virtual void assign(Value_P value, bool clone, const char * loc);
435 
436    /// overloaded Symbol::assign_indexed()
437    virtual void assign_indexed(Value_P X, Value_P value);
438 
439    /// overloaded Symbol::push()
push()440    virtual void push()
441       {
442         Symbol::push();
443         Symbol::assign(IntScalar(0, LOC), false, LOC);
444       }
445 
446    /// true if quotients shall be printed as A÷B
447    bool print_quotients;
448 
449    /// the current style
450    int style;
451 };
452 //-----------------------------------------------------------------------------
453 /**
454    System variable Quad-PW (Print Width).
455  */
456 /// The class implementing ⎕PW
457 class Quad_PW : public SystemVariable
458 {
459 public:
460    /// Constructor.
461    Quad_PW();
462 
463    /// return the current ⎕PW. MUST NOT CALL get_apl_value()
464    /// because it can be called from parallel Cell functions
current() const465    APL_Integer current() const
466       { return get_first_cell()->get_int_value(); }
467 
468    /// overloaded Symbol::assign().
469    virtual void assign(Value_P value, bool clone, const char * loc);
470 
471 protected:
472    // overloaded Symbol::push()
push()473    virtual void push()
474       {
475         Symbol::push();
476         Symbol::assign(IntScalar(DEFAULT_Quad_PW, LOC), false, LOC);
477       }
478 };
479 //-----------------------------------------------------------------------------
480 /**
481    System variable Quad-Quad (Evaluated Input/Output).
482  */
483 /// The class implementing ⎕
484 class Quad_Quad : public SystemVariable
485 {
486 public:
487    /// Constructor.
488    Quad_Quad();
489 
490    /// overloaded Symbol::resolve().
491    virtual void resolve(Token & token, bool left);
492 
493 protected:
494    virtual void assign(Value_P value, bool clone, const char * loc);
495 
496    // should never be called due to overloaded resolve()
get_apl_value() const497    virtual Value_P get_apl_value() const
498       { Assert(0);   /* not reached */ return Value_P(); }
499 };
500 //-----------------------------------------------------------------------------
501 /**
502    System variable Quote-Quad (Evaluated Input/Output).
503  */
504 /// The class implementing ⍞
505 class Quad_QUOTE : public SystemVariable
506 {
507 public:
508    /// Constructor.
509    Quad_QUOTE();
510 
511    /// end of ⍞ (output, but no input: clear prompt)
512    static void done(bool with_LF, const char * loc);
513 
514 protected:
515    /// overloaded Symbol::assign().
516    virtual void assign(Value_P value, bool clone, const char * loc);
517 
518    /// overloaded Symbol::get_apl_value().
519    virtual Value_P get_apl_value() const;
520 
521    /// last line of output
522    static UCS_string prompt;
523 };
524 //-----------------------------------------------------------------------------
525 /**
526    System variable Quad-R (Right Argment).
527  */
528 /// The class implementing ⎕R
529 class Quad_R : public NL_SystemVariable
530 {
531 public:
532    /// Constructor.
533    Quad_R();
534 
535    /// overloaded Symbol::save()
save(ostream & out) const536    virtual void save(ostream & out) const {}
537 
538 protected:
539    /// overloaded Symbol::assign()
540    virtual void assign(Value_P value, bool clone, const char * loc);
541 
542    /// overloaded Symbol::get_apl_value().
543    virtual Value_P get_apl_value() const;
544 };
545 //-----------------------------------------------------------------------------
546 /**
547    System variable Quad-SYL (System Limits).
548  */
549 /// The class implementing ⎕SYL
550 class Quad_SYL : public NL_SystemVariable
551 {
552 public:
553    /// Constructor.
Quad_SYL()554    Quad_SYL() : NL_SystemVariable(ID_Quad_SYL)
555       { assign(Value_P(), false, LOC); }
556 
557    /// overloaded Symbol::assign()
558    virtual void assign(Value_P value, bool clone, const char * loc);
559 
560    /// overloaded Symbol::assign_indexed()
561    virtual void assign_indexed(Value_P X, Value_P value);
562 
563    /// overloaded Symbol::assign_indexed()
564    virtual void assign_indexed(IndexExpr & IDX, Value_P value);
565 
566    virtual Value_P get_apl_value() const;
567 
568    /// maximum depth of SI stack
569    static ShapeItem si_depth_limit;
570 
571    /// maximum number of values
572    static ShapeItem value_count_limit;
573 
574    /// maximum number of ravel bytes
575    static ShapeItem ravel_count_limit;
576 
577    /// maximum number of ravel bytes in APL printout
578    static ShapeItem print_length_limit;
579 
580    /// the system limits
581    enum SYL_INDEX
582       {
583 #define syl3(n, e, v) syl1(n, e, v)
584 #define syl2(n, e, v) syl1(n, e, v)
585 #define syl1(_n, e, _v) SYL_ ## e, ///< dito
586 #include "SystemLimits.def"
587 
588         SYL_MAX                      ///< max. system limit value (excluding)
589       };
590 
591 protected:
592 };
593 //-----------------------------------------------------------------------------
594 /**
595    System variable Quad-TC (Terminal Control Characters)
596  */
597 /// The class implementing ⎕TC
598 class Quad_TC : public RO_SystemVariable
599 {
600 public:
601    /// Constructor.
602    Quad_TC();
603 };
604 //-----------------------------------------------------------------------------
605 /**
606    System variable Quad-TS (Time Stamp).
607  */
608 /// The class implementing ⎕TS
609 class Quad_TS : public RO_SystemVariable
610 {
611 public:
612    /// Constructor.
613    Quad_TS();
614 
615    /// overloaded Symbol::get_apl_value().
616    virtual Value_P get_apl_value() const;
617 };
618 //-----------------------------------------------------------------------------
619 /**
620    System variable Quad-TZ (Time Zone).
621  */
622 /// The class implementing ⎕TZ
623 class Quad_TZ : public SystemVariable
624 {
625 public:
626    /// Constructor.
627    Quad_TZ();
628 
629    /// return the offset from GMT of the current timezone (in seconds).
630    /// we make this int64_t rather than int so that conversion to usec
631    /// does not overflow
get_offset() const632    int64_t get_offset() const   { return offset_seconds; }
633 
634    /// set the timezone offset
set_offset(int offset)635    void set_offset(int offset)
636       { offset_seconds = offset; }
637 
638    /// compute the offset (in seconds) from GMT
639    static int compute_offset();
640 
641    /// print e.g. 2017-05-17  15:09:12 (GMT+2) to out (no trailing endl)
642    ostream & print_timestamp(ostream & out, APL_time_us when) const;
643 
644 protected:
645    /// overloaded Symbol::assign().
646    virtual void assign(Value_P value, bool clone, const char * loc);
647 
648    // overloaded Symbol::push()
push()649    virtual void push()
650       {
651         Symbol::push();
652         offset_seconds = compute_offset();
653         if (offset_seconds % 3600 == 0)   // full hour
654            Symbol::assign(IntScalar(offset_seconds/3600, LOC), false, LOC);
655         else
656            Symbol::assign(FloatScalar(offset_seconds/3600, LOC), false, LOC);
657       }
658 
pop()659    virtual void pop()
660       {
661         Symbol::pop();
662         offset_seconds = 3600 * get_apl_value()->get_ravel(0).get_int_value();
663       }
664 
665    /// the offset from GMT of the current timezone (in seconds)
666    int offset_seconds;
667 };
668 //-----------------------------------------------------------------------------
669 /**
670    System variable Quad-UL (User Load).
671  */
672 /// The class implementing ⎕UL
673 class Quad_UL : public RO_SystemVariable
674 {
675 public:
676    /// Constructor.
677    Quad_UL();
678 
679 protected:
680    /// overloaded Symbol::get_apl_value().
681    virtual Value_P get_apl_value() const;
682 };
683 //-----------------------------------------------------------------------------
684 /**
685    System variable Quad-X (Axis Argument).
686  */
687 /// The class implementing ⎕X
688 class Quad_X : public NL_SystemVariable
689 {
690 public:
691    /// Constructor.
692    Quad_X();
693 
694    /// overloaded Symbol::save()
save(ostream & out) const695    virtual void save(ostream & out) const {}
696 
697 protected:
698    /// overloaded Symbol::assign()
699    virtual void assign(Value_P value, bool clone, const char * loc);
700 
701    /// overloaded Symbol::get_apl_value().
702    virtual Value_P get_apl_value() const;
703 };
704 //-----------------------------------------------------------------------------
705 #endif // __SYSTEM_VARIABLE_HH_DEFINED__
706