1 /**
2  ** Ucfun.h - Usecode compiler function.
3  **
4  ** Written: 1/2/01 - JSF
5  **/
6 
7 /*
8 Copyright (C) 2000 The Exult Team
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 */
24 
25 #ifndef INCL_UCFUN
26 #define INCL_UCFUN
27 
28 #include <set>
29 #include "ucsym.h"
30 #include "opcodes.h"
31 
32 class Uc_location;
33 class Uc_statement;
34 
35 #include <iosfwd>
36 
37 /*
38  *  This represents a usecode function:
39  */
40 class Uc_function : public Uc_design_unit {
41 	static Uc_scope globals;    // For finding intrinsics, funs.
42 	// Intrinsics, indexed by number:
43 	static std::vector<Uc_intrinsic_symbol *> intrinsics;
44 	// Some intrinsic numbers:
45 	static int add_answer, remove_answer, push_answers, pop_answers,
46 	       show_face, remove_face, get_item_shape, get_usecode_fun;
47 	static int num_global_statics;
48 	Uc_scope top;           // Top-level scope.
49 	Uc_function_symbol *proto;  // Function declaration.
50 	Uc_scope *cur_scope;        // Current scope.
51 	int num_parms;          // # parameters.
52 	int num_locals;         // Counts locals.
53 	int num_statics;        // Counts local statics.
54 	// Links to called functions:
55 	std::vector<Uc_function_symbol *> links;
56 	std::set<std::string> labels;
57 	char *text_data;        // All strings.
58 	int text_data_size;
59 	// Map string to its offset.
60 	std::map<std::string, int> text_map;
61 	Uc_statement *statement;    // Statement(s) in function.
62 public:
63 	enum Intrinsic_type {
64 	    unset,
65 	    bg,         // Black gate.
66 	    si,         // Serpent isle.
67 	    sib         // Serpent Isle Beta.
68 	};
69 private:
70 	static Intrinsic_type intrinsic_type;
71 public:
72 	Uc_function(Uc_function_symbol *p, Uc_scope *parent = nullptr);
73 	~Uc_function() override;
74 	static void set_intrinsics();
setup_intrinsics()75 	static void setup_intrinsics() {    // Init. the 1st time.
76 		if (intrinsics.empty())
77 			set_intrinsics();
78 	}
set_intrinsic_type(Intrinsic_type ty)79 	static void set_intrinsic_type(Intrinsic_type ty) {
80 		intrinsic_type = ty;
81 		if (ty != Uc_function::unset)
82 			set_intrinsics();
83 	}
set_statement(Uc_statement * s)84 	void set_statement(Uc_statement *s) {
85 		statement = s;
86 	}
get_name()87 	const char *get_name() {
88 		return proto->get_name();
89 	}
is_externed()90 	bool is_externed() {
91 		return proto->is_externed();
92 	}
is_inherited()93 	bool is_inherited() {
94 		return proto->is_inherited();
95 	}
set_inherited()96 	void set_inherited() {
97 		proto->set_inherited();
98 	}
get_usecode_num()99 	int get_usecode_num() {
100 		return proto->get_usecode_num();
101 	}
set_method_num(int n)102 	void set_method_num(int n) {
103 		proto->set_method_num(n);
104 	}
get_method_num()105 	int get_method_num() {
106 		return proto->get_method_num();
107 	}
has_ret()108 	bool has_ret() const {
109 		return proto->has_ret();
110 	}
get_ret_type()111 	Uc_function_symbol::Function_ret get_ret_type() const {
112 		return proto->get_ret_type();
113 	}
get_cls()114 	Uc_class *get_cls() const {
115 		return proto->get_cls();
116 	}
get_struct()117 	Uc_struct_symbol *get_struct() const {
118 		return proto->get_struct();
119 	}
get_function_type()120 	Uc_function_symbol::Function_kind get_function_type() const {
121 		return proto->get_function_type();
122 	}
get_parent()123 	Uc_scope *get_parent() {
124 		return cur_scope->get_parent();
125 	}
push_scope()126 	void push_scope() {     // Start a new scope.
127 		cur_scope = cur_scope->add_scope();
128 	}
pop_scope()129 	void pop_scope() {      // End scope.
130 		cur_scope = cur_scope->get_parent();
131 	}
search(const char * nm)132 	Uc_symbol *search(const char *nm) { // Search current scope.
133 		return cur_scope->search(nm);
134 	}
search_up(const char * nm)135 	Uc_symbol *search_up(const char *nm) {
136 		Uc_symbol *sym = cur_scope->search_up(nm);
137 		if (sym)
138 			return sym;
139 		setup_intrinsics();
140 		return globals.search(nm);
141 	}
search_globals(const char * nm)142 	static Uc_symbol *search_globals(const char *nm) {
143 		return globals.search(nm);
144 	}
get_intrinsic(int i)145 	static Uc_intrinsic_symbol *get_intrinsic(int i) {
146 		setup_intrinsics();
147 		return (i >= 0 && static_cast<unsigned>(i) < intrinsics.size()) ? intrinsics[i] : nullptr;
148 	}
get_add_answer()149 	static Uc_intrinsic_symbol *get_add_answer() {
150 		return get_intrinsic(add_answer);
151 	}
get_remove_answer()152 	static Uc_intrinsic_symbol *get_remove_answer() {
153 		return get_intrinsic(remove_answer);
154 	}
get_push_answers()155 	static Uc_intrinsic_symbol *get_push_answers() {
156 		return get_intrinsic(push_answers);
157 	}
get_pop_answers()158 	static Uc_intrinsic_symbol *get_pop_answers() {
159 		return get_intrinsic(pop_answers);
160 	}
get_show_face()161 	static Uc_intrinsic_symbol *get_show_face() {
162 		return get_intrinsic(show_face);
163 	}
get_remove_face()164 	static Uc_intrinsic_symbol *get_remove_face() {
165 		return get_intrinsic(remove_face);
166 	}
get_get_usecode_fun()167 	static Uc_intrinsic_symbol *get_get_usecode_fun() {
168 		return get_intrinsic(get_usecode_fun);
169 	}
get_get_item_shape()170 	static Uc_intrinsic_symbol *get_get_item_shape() {
171 		return get_intrinsic(get_item_shape);
172 	}
173 	Uc_var_symbol *add_symbol(char *nm);// Add var. to current scope.
174 	Uc_var_symbol *add_symbol(char *nm, Uc_class *c);// Add var. to current scope.
175 	Uc_var_symbol *add_symbol(char *nm, Uc_struct_symbol *s);// Add var. to current scope.
176 	Uc_var_symbol *add_symbol(Uc_var_symbol *var);// Add var. to current scope.
177 	// Add alias to current scope.
178 	Uc_var_symbol *add_alias(char *nm, Uc_var_symbol *var);
179 	// Add class alias to current scope.
180 	Uc_var_symbol *add_alias(char *nm, Uc_var_symbol *var, Uc_class *c);
181 	// Add struct alias to current scope.
182 	Uc_var_symbol *add_alias(char *nm, Uc_var_symbol *var, Uc_struct_symbol *s);
183 	void add_static(char *nm);  // Add static var. to current scope.
184 	void add_static(char *nm, Uc_struct_symbol *type);  // Add static struct to current scope.
185 	void add_static(char *nm, Uc_class *c); // Add static cls. to current scope.
186 	int add_function_symbol(Uc_function_symbol *fun, Uc_scope *parent = nullptr) {
187 		return cur_scope->add_function_symbol(fun, parent);
188 	}
189 	static int add_global_function_symbol(Uc_function_symbol *fun,
190 	                                      Uc_scope *parent = nullptr) {
191 		return globals.add_function_symbol(fun, parent);
192 	}
add_global_class_symbol(Uc_class_symbol * c)193 	static void add_global_class_symbol(Uc_class_symbol *c) {
194 		globals.add(c);
195 	}
add_global_struct_symbol(Uc_struct_symbol * s)196 	static void add_global_struct_symbol(Uc_struct_symbol *s) {
197 		globals.add(s);
198 	}
199 	// Add string constant.
200 	Uc_symbol *add_string_symbol(char *nm, char *text);
201 	// Add int constant.
202 	Uc_symbol *add_int_const_symbol(char *nm, int value, int opcode = UC_PUSHI);
203 	static Uc_symbol *add_global_int_const_symbol(char *nm, int val,
204 	        int opcode = UC_PUSHI);
205 	static void add_global_static(char *nm);
206 	static void add_global_static(char *nm, Uc_struct_symbol *type);
207 	static void add_global_static(char *nm, Uc_class *c);
208 	int add_string(char *text);
209 	int find_string_prefix(Uc_location &loc, const char *text);
210 	// Start/end loop.
add_label(char * nm)211 	void add_label(char *nm) {
212 		labels.insert(nm);
213 	}
search_label(char * nm)214 	bool search_label(char *nm) {
215 		return labels.find(nm) != labels.end();
216 	}
217 
218 	int link(Uc_function_symbol *fun);
219 	void gen(std::ostream &out) override;        // Generate Usecode.
220 	Usecode_symbol *create_sym() override;
221 };
222 
223 #endif
224