source: mainline/uspace/app/sbi/src/builtin.c@ c5ad226

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c5ad226 was c5cb943d, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Update SBI to rev. 291.

  • Property mode set to 100644
File size: 10.4 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @file Builtin symbol binding.
30 *
31 * 'Builtin' symbols are implemented outside of the language itself.
32 * Here we refer to entities residing within the interpreted universe
33 * as 'internal', while anything implemented outside this universe
34 * as 'external'. This module facilitates declaration of builtin
35 * symbols and the binding of these symbols to their external
36 * implementation.
37 */
38
39#include <stdio.h>
40#include <stdlib.h>
41#include <assert.h>
42#include "builtin/bi_boxed.h"
43#include "builtin/bi_error.h"
44#include "builtin/bi_char.h"
45#include "builtin/bi_fun.h"
46#include "builtin/bi_int.h"
47#include "builtin/bi_textfile.h"
48#include "builtin/bi_string.h"
49#include "input.h"
50#include "intmap.h"
51#include "lex.h"
52#include "list.h"
53#include "mytypes.h"
54#include "os/os.h"
55#include "parse.h"
56#include "rdata.h"
57#include "run.h"
58#include "stree.h"
59#include "strtab.h"
60#include "symbol.h"
61
62#include "builtin.h"
63
64static builtin_t *builtin_new(void);
65
66/** Declare builtin symbols in the program.
67 *
68 * Declares symbols that will be hooked to builtin interpreter procedures.
69 *
70 * @param program Program in which to declare builtin symbols.
71 */
72void builtin_declare(stree_program_t *program)
73{
74 builtin_t *bi;
75
76 bi = builtin_new();
77 bi->program = program;
78 program->builtin = bi;
79
80 /*
81 * Declare grandfather class.
82 */
83
84 builtin_code_snippet(bi,
85 "class Object is\n"
86 "end\n");
87 bi->gf_class = builtin_find_lvl0(bi, "Object");
88
89 /*
90 * Declare other builtin classes/functions.
91 */
92
93 bi_error_declare(bi);
94 bi_char_declare(bi);
95 bi_fun_declare(bi);
96 bi_int_declare(bi);
97 bi_textfile_declare(bi);
98 bi_string_declare(bi);
99}
100
101/** Bind internal interpreter references to symbols in the program.
102 *
103 * This is performed in separate phase for several reasons. First,
104 * symbol lookups do not work until ancestry is processed. Second,
105 * this gives a chance to process the library first and thus bind
106 * to symbols defined there.
107 */
108void builtin_bind(builtin_t *bi)
109{
110 bi_boxed_bind(bi);
111 bi_error_bind(bi);
112 bi_char_bind(bi);
113 bi_fun_bind(bi);
114 bi_int_bind(bi);
115 bi_textfile_bind(bi);
116 bi_string_bind(bi);
117}
118
119/** Get grandfather class.
120 *
121 * Grandfather class is the class from which all other classes are
122 * (directly or indirectly) derived.
123 *
124 * @param builtin Builtin context (corresponsds to program).
125 * @return Grandfather class (CSI).
126 */
127stree_csi_t *builtin_get_gf_class(builtin_t *builtin)
128{
129 if (builtin->gf_class == NULL)
130 return NULL;
131
132 return symbol_to_csi(builtin->gf_class);
133}
134
135/** Allocate new builtin context object.
136 *
137 * @return Builtin context object.
138 */
139static builtin_t *builtin_new(void)
140{
141 builtin_t *builtin;
142
143 builtin = calloc(1, sizeof(builtin_t));
144 if (builtin == NULL) {
145 printf("Memory allocation failed.\n");
146 exit(1);
147 }
148
149 return builtin;
150}
151
152/** Parse a declaration code snippet.
153 *
154 * Parses a piece of code from a string at the module level. This can be
155 * used to declare builtin symbols easily and without need for an external
156 * file.
157 */
158void builtin_code_snippet(builtin_t *bi, const char *snippet)
159{
160 input_t *input;
161 lex_t lex;
162 parse_t parse;
163
164 input_new_string(&input, snippet);
165 lex_init(&lex, input);
166 parse_init(&parse, bi->program, &lex);
167 parse_module(&parse);
168}
169
170/** Simplifed search for a global symbol.
171 *
172 * The specified symbol must exist.
173 *
174 * @param bi Builtin context object.
175 * @param sym_name Name of symbol to find.
176 * @return Symbol.
177 */
178stree_symbol_t *builtin_find_lvl0(builtin_t *bi, const char *sym_name)
179{
180 stree_symbol_t *sym;
181 stree_ident_t *ident;
182
183 ident = stree_ident_new();
184
185 ident->sid = strtab_get_sid(sym_name);
186 sym = symbol_lookup_in_csi(bi->program, NULL, ident);
187 assert(sym != NULL);
188
189 return sym;
190}
191
192/** Simplifed search for a level 1 symbol.
193 *
194 * The specified symbol must exist.
195 *
196 * @param bi Builtin context object.
197 * @param csi_name CSI in which to look for symbol.
198 * @param sym_name Name of symbol to find.
199 * @return Symbol.
200 */
201stree_symbol_t *builtin_find_lvl1(builtin_t *bi, const char *csi_name,
202 const char *sym_name)
203{
204 stree_symbol_t *csi_sym;
205 stree_csi_t *csi;
206
207 stree_symbol_t *mbr_sym;
208 stree_ident_t *ident;
209
210 ident = stree_ident_new();
211
212 ident->sid = strtab_get_sid(csi_name);
213 csi_sym = symbol_lookup_in_csi(bi->program, NULL, ident);
214 assert(csi_sym != NULL);
215 csi = symbol_to_csi(csi_sym);
216 assert(csi != NULL);
217
218 ident->sid = strtab_get_sid(sym_name);
219 mbr_sym = symbol_lookup_in_csi(bi->program, csi, ident);
220 assert(mbr_sym != NULL);
221
222 return mbr_sym;
223}
224
225/** Bind level 1 member function to external implementation.
226 *
227 * Binds a member function (of a global class) to external implementation.
228 * The specified CSI and member function must exist.
229 *
230 * @param bi Builtin context object.
231 * @param csi_name CSI which contains the function.
232 * @param sym_name Function name.
233 * @param bproc Pointer to C function implementation.
234 */
235void builtin_fun_bind(builtin_t *bi, const char *csi_name,
236 const char *sym_name, builtin_proc_t bproc)
237{
238 stree_symbol_t *fun_sym;
239 stree_fun_t *fun;
240
241 fun_sym = builtin_find_lvl1(bi, csi_name, sym_name);
242 assert(fun_sym != NULL);
243 fun = symbol_to_fun(fun_sym);
244 assert(fun != NULL);
245
246 fun->proc->bi_handler = bproc;
247}
248
249/** Execute a builtin procedure.
250 *
251 * Executes a procedure that has an external implementation.
252 *
253 * @param run Runner object.
254 * @param proc Procedure that has an external implementation.
255 */
256void builtin_run_proc(run_t *run, stree_proc_t *proc)
257{
258 stree_symbol_t *fun_sym;
259 builtin_proc_t bproc;
260
261#ifdef DEBUG_RUN_TRACE
262 printf("Run builtin procedure.\n");
263#endif
264 fun_sym = proc->outer_symbol;
265
266 bproc = proc->bi_handler;
267 if (bproc == NULL) {
268 printf("Error: Unrecognized builtin function '");
269 symbol_print_fqn(fun_sym);
270 printf("'.\n");
271 exit(1);
272 }
273
274 /* Run the builtin procedure handler. */
275 (*bproc)(run);
276}
277
278/** Get pointer to member var of current object.
279 *
280 * Returns the var node that corresponds to a member of the currently
281 * active object with the given name. This member must exist.
282 *
283 * @param run Runner object.
284 * @param mbr_name Name of member to find.
285 * @return Var node of the member.
286 */
287rdata_var_t *builtin_get_self_mbr_var(run_t *run, const char *mbr_name)
288{
289 run_proc_ar_t *proc_ar;
290 rdata_object_t *object;
291 sid_t mbr_name_sid;
292 rdata_var_t *mbr_var;
293
294 proc_ar = run_get_current_proc_ar(run);
295 assert(proc_ar->obj->vc == vc_object);
296 object = proc_ar->obj->u.object_v;
297
298 mbr_name_sid = strtab_get_sid(mbr_name);
299 mbr_var = intmap_get(&object->fields, mbr_name_sid);
300 assert(mbr_var != NULL);
301
302 return mbr_var;
303}
304
305/** Return string value from builtin procedure.
306 *
307 * Makes it easy for a builtin procedure to return value of type @c string.
308 *
309 * @param run Runner object
310 * @param str String value. Must be allocated from heap and its
311 * ownership is hereby given up.
312 */
313void builtin_return_string(run_t *run, const char *astr)
314{
315 rdata_string_t *rstring;
316 rdata_var_t *rvar;
317 rdata_value_t *rval;
318 rdata_item_t *ritem;
319
320 run_proc_ar_t *proc_ar;
321
322#ifdef DEBUG_RUN_TRACE
323 printf("Return string '%s' from builtin function.\n", astr);
324#endif
325 rstring = rdata_string_new();
326 rstring->value = astr;
327
328 rvar = rdata_var_new(vc_string);
329 rvar->u.string_v = rstring;
330 rval = rdata_value_new();
331 rval->var = rvar;
332
333 ritem = rdata_item_new(ic_value);
334 ritem->u.value = rval;
335
336 proc_ar = run_get_current_proc_ar(run);
337 proc_ar->retval = ritem;
338}
339
340/** Declare a static builtin function in @a csi.
341 *
342 * Declare a builtin function member of CSI @a csi. Deprecated in favor
343 * of builtin_code_snippet().
344 *
345 * @param csi CSI in which to declare function.
346 * @param name Name of member function to declare.
347 * @return Symbol of newly declared function.
348 */
349stree_symbol_t *builtin_declare_fun(stree_csi_t *csi, const char *name)
350{
351 stree_ident_t *ident;
352 stree_fun_t *fun;
353 stree_fun_sig_t *sig;
354 stree_csimbr_t *csimbr;
355 stree_symbol_t *fun_sym;
356 stree_symbol_attr_t *sym_attr;
357
358 ident = stree_ident_new();
359 ident->sid = strtab_get_sid(name);
360
361 fun = stree_fun_new();
362 fun->name = ident;
363 fun->proc = stree_proc_new();
364 fun->proc->body = NULL;
365 sig = stree_fun_sig_new();
366 fun->sig = sig;
367
368 list_init(&fun->sig->args);
369
370 csimbr = stree_csimbr_new(csimbr_fun);
371 csimbr->u.fun = fun;
372
373 fun_sym = stree_symbol_new(sc_fun);
374 fun_sym->u.fun = fun;
375 fun_sym->outer_csi = csi;
376
377 sym_attr = stree_symbol_attr_new(sac_static);
378 list_append(&fun_sym->attr, sym_attr);
379
380 fun->symbol = fun_sym;
381 fun->proc->outer_symbol = fun_sym;
382
383 list_append(&csi->members, csimbr);
384
385 return fun_sym;
386}
387
388/** Add one formal parameter to function.
389 *
390 * Used to incrementally construct formal parameter list of a builtin
391 * function. Deprecated in favor of builtin_code_snippet(). Does not
392 * support type checking.
393 *
394 * @param fun_sym Symbol of function to add parameters to.
395 * @param name Name of parameter to add.
396 */
397void builtin_fun_add_arg(stree_symbol_t *fun_sym, const char *name)
398{
399 stree_proc_arg_t *proc_arg;
400 stree_fun_t *fun;
401
402 fun = symbol_to_fun(fun_sym);
403 assert(fun != NULL);
404
405 proc_arg = stree_proc_arg_new();
406 proc_arg->name = stree_ident_new();
407 proc_arg->name->sid = strtab_get_sid(name);
408 proc_arg->type = NULL; /* XXX */
409
410 list_append(&fun->sig->args, proc_arg);
411}
Note: See TracBrowser for help on using the repository browser.