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 __USERFUNCTION__HEADER_HH_DEFINED__
22 #define __USERFUNCTION__HEADER_HH_DEFINED__
23 
24 #include <sys/types.h>
25 #include <vector>
26 
27 #include "Error.hh"
28 #include "Executable.hh"
29 #include "Function.hh"
30 #include "Symbol.hh"
31 #include "UTF8_string.hh"
32 
33 //-----------------------------------------------------------------------------
34 /// The (symbols in the) header of a defined function
35 class UserFunction_header
36 {
37 public:
38    /// constructor from first line in \b txt (for normal defined functions)
39    UserFunction_header(const UCS_string & txt, bool macro);
40 
41    /// constructor from signature (for lambdas)
42    UserFunction_header(Fun_signature sig, int lambda_num);
43 
44    /// return the number of value arguments
get_fun_valence() const45    int get_fun_valence() const
46       {
47         if (sym_A)    return 2;   // dyadic function
48         if (sym_B)    return 1;   // monadic function
49         return 0;                 // niladic function
50       }
51 
52    /// return the number of operator arguments
get_oper_valence() const53    int get_oper_valence() const
54       {
55         if (sym_RO)   return 2;   // dyadic operator
56         if (sym_LO)   return 1;   // monadic operator
57         return 0;                 // niladic function
58       }
59 
60    /// return source location where error was detected
get_error_info() const61    const char * get_error_info() const   { return error_info; }
62 
63    /// return true if the header indicates a result (Z←)
has_result() const64    bool has_result() const   { return sym_Z != 0; }
65 
66    /// return true if the header contains variables (result, arguments,
67    /// or local variables
has_vars() const68    bool has_vars() const
69       { return sym_Z || sym_A || sym_LO || sym_X || sym_RO || sym_B ||
70                local_vars.size(); }
71 
72    /// return true iff the function returns a value
has_axis() const73    int has_axis() const   { return sym_X != 0; }
74 
75    /// return true if this defined function header is an operator
is_operator() const76    bool is_operator() const   { return sym_LO != 0; }
77 
78    /// return the name of the function
get_name() const79    UCS_string get_name() const   { return function_name; }
80 
81    /// return the Symbol for the function result
Z() const82    Symbol * Z()   const   { return sym_Z; }
83 
84    /// return the Symbol for the left argument
A() const85    Symbol * A()   const   { return sym_A; }
86 
87    /// return the Symbol for the left function argument
LO() const88    Symbol * LO()   const   { return sym_LO; }
89 
90    /// return the Symbol for the left function argument
FUN() const91    Symbol * FUN()   const   { return sym_FUN; }
92 
93    /// return the Symbol for the right argument
X() const94    Symbol * X()   const   { return sym_X; }
95 
96    /// return the Symbol for the right function argument
RO() const97    Symbol * RO()   const   { return sym_RO; }
98 
99    /// return the Symbol for the right argument
B() const100    Symbol * B()   const   { return sym_B; }
101 
102    /// return error if header was not parsed successfully
get_error() const103    ErrorCode get_error() const   { return error; }
104 
105    /// print local vars etc.
106    void print_properties(ostream & out, int indent) const;
107 
108    /// add a local variable
109    void add_local_var(Symbol * sym);
110 
111    /// pop all local vars, labels, and parameters
112    void pop_local_vars() const;
113 
114    /// print the local variables for command )SINL
115    void print_local_vars(ostream & out) const;
116 
117    /// reverse the order of the local vars (if parsed back-to-front)
118    void reverse_local_vars();
119 
120    /// add a label
add_label(Symbol * sym,Function_Line line)121    void add_label(Symbol * sym, Function_Line line)
122       {
123         labVal label = { sym, line };
124         label_values.push_back(label);
125       }
126 
127    /// Check that all function params, local vars. and labels are unique.
128    void remove_duplicate_local_variables();
129 
130    /// the header (as per SIG_xxx and local_vars)
131    static UCS_string lambda_header(Fun_signature sig, int lambda_num);
132 
133    /// push Z (if defined), local variables, and labels.
134    void eval_common();
135 
136    /// return the number of local variables
local_var_count() const137    ShapeItem local_var_count() const
138       { return local_vars.size(); }
139 
140    /// return the idx'th local variable
get_local_var(ShapeItem idx) const141    const Symbol * get_local_var(ShapeItem idx) const
142       { return local_vars[idx]; }
143 
144 protected:
145    /// remove \b sym from local_vars if it occurs at pos or above
146    void remove_duplicate_local_var(const Symbol * sym, size_t pos);
147 
148    /// error if header was not parsed successfully
149    ErrorCode error;
150 
151    /// source location where error was detected
152    const char * error_info;
153 
154    /// the name of this function
155    UCS_string function_name;
156 
157    /// optional result
158    Symbol * sym_Z;
159 
160    /// optional left function arg
161    Symbol * sym_A;
162 
163    /// optional left operator function
164    Symbol * sym_LO;
165 
166    /// optional symbol for function name (0 for lambdas)
167    Symbol * sym_FUN;
168 
169    /// optional right operator function
170    Symbol * sym_RO;
171 
172    /// optional right operator function axis
173    Symbol * sym_X;
174 
175    /// optional right function arg
176    Symbol * sym_B;
177 
178    /// The local variables of \b this function.
179    std::vector<Symbol *> local_vars;
180 
181    /// The labels of \b this function.
182    std::vector<labVal> label_values;
183 };
184 //-----------------------------------------------------------------------------
185 
186 #endif // __USERFUNCTION__HEADER_HH_DEFINED__
187