2 * Copyright (c) 2010 Jiri Svoboda
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
29 /** @file Builtin symbol binding.
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
42 #include "builtin/bi_boxed.h"
43 #include "builtin/bi_error.h"
44 #include "builtin/bi_char.h"
45 #include "builtin/bi_console.h"
46 #include "builtin/bi_int.h"
47 #include "builtin/bi_task.h"
48 #include "builtin/bi_textfile.h"
49 #include "builtin/bi_string.h"
65 static builtin_t
*builtin_new(void);
67 /** Declare builtin symbols in the program.
69 * Declares symbols that will be hooked to builtin interpreter procedures.
71 * @param program Program in which to declare builtin symbols.
73 void builtin_declare(stree_program_t
*program
)
78 bi
->program
= program
;
79 program
->builtin
= bi
;
82 * Declare grandfather class.
85 builtin_code_snippet(bi
,
88 bi
->gf_class
= builtin_find_lvl0(bi
, "Object");
91 * Declare other builtin classes/functions.
96 bi_console_declare(bi
);
99 bi_textfile_declare(bi
);
100 bi_string_declare(bi
);
103 /** Bind internal interpreter references to symbols in the program.
105 * This is performed in separate phase for several reasons. First,
106 * symbol lookups do not work until ancestry is processed. Second,
107 * this gives a chance to process the library first and thus bind
108 * to symbols defined there.
110 void builtin_bind(builtin_t
*bi
)
118 bi_textfile_bind(bi
);
122 /** Get grandfather class.
124 * Grandfather class is the class from which all other classes are
125 * (directly or indirectly) derived.
127 * @param builtin Builtin context (corresponsds to program).
128 * @return Grandfather class (CSI).
130 stree_csi_t
*builtin_get_gf_class(builtin_t
*builtin
)
132 if (builtin
->gf_class
== NULL
)
135 return symbol_to_csi(builtin
->gf_class
);
138 /** Allocate new builtin context object.
140 * @return Builtin context object.
142 static builtin_t
*builtin_new(void)
146 builtin
= calloc(1, sizeof(builtin_t
));
147 if (builtin
== NULL
) {
148 printf("Memory allocation failed.\n");
155 /** Parse a declaration code snippet.
157 * Parses a piece of code from a string at the module level. This can be
158 * used to declare builtin symbols easily and without need for an external
161 void builtin_code_snippet(builtin_t
*bi
, const char *snippet
)
167 input_new_string(&input
, snippet
);
168 lex_init(&lex
, input
);
169 parse_init(&parse
, bi
->program
, &lex
);
170 parse_module(&parse
);
173 /** Simplifed search for a global symbol.
175 * The specified symbol must exist.
177 * @param bi Builtin context object.
178 * @param sym_name Name of symbol to find.
181 stree_symbol_t
*builtin_find_lvl0(builtin_t
*bi
, const char *sym_name
)
184 stree_ident_t
*ident
;
186 ident
= stree_ident_new();
188 ident
->sid
= strtab_get_sid(sym_name
);
189 sym
= symbol_lookup_in_csi(bi
->program
, NULL
, ident
);
195 /** Simplifed search for a level 1 symbol.
197 * The specified symbol must exist.
199 * @param bi Builtin context object.
200 * @param csi_name CSI in which to look for symbol.
201 * @param sym_name Name of symbol to find.
204 stree_symbol_t
*builtin_find_lvl1(builtin_t
*bi
, const char *csi_name
,
205 const char *sym_name
)
207 stree_symbol_t
*csi_sym
;
210 stree_symbol_t
*mbr_sym
;
211 stree_ident_t
*ident
;
213 ident
= stree_ident_new();
215 ident
->sid
= strtab_get_sid(csi_name
);
216 csi_sym
= symbol_lookup_in_csi(bi
->program
, NULL
, ident
);
217 assert(csi_sym
!= NULL
);
218 csi
= symbol_to_csi(csi_sym
);
221 ident
->sid
= strtab_get_sid(sym_name
);
222 mbr_sym
= symbol_lookup_in_csi(bi
->program
, csi
, ident
);
223 assert(mbr_sym
!= NULL
);
228 /** Bind level 1 member function to external implementation.
230 * Binds a member function (of a global class) to external implementation.
231 * The specified CSI and member function must exist.
233 * @param bi Builtin context object.
234 * @param csi_name CSI which contains the function.
235 * @param sym_name Function name.
236 * @param bproc Pointer to C function implementation.
238 void builtin_fun_bind(builtin_t
*bi
, const char *csi_name
,
239 const char *sym_name
, builtin_proc_t bproc
)
241 stree_symbol_t
*fun_sym
;
244 fun_sym
= builtin_find_lvl1(bi
, csi_name
, sym_name
);
245 assert(fun_sym
!= NULL
);
246 fun
= symbol_to_fun(fun_sym
);
249 fun
->proc
->bi_handler
= bproc
;
252 /** Execute a builtin procedure.
254 * Executes a procedure that has an external implementation.
256 * @param run Runner object.
257 * @param proc Procedure that has an external implementation.
259 void builtin_run_proc(run_t
*run
, stree_proc_t
*proc
)
261 stree_symbol_t
*fun_sym
;
262 builtin_proc_t bproc
;
264 #ifdef DEBUG_RUN_TRACE
265 printf("Run builtin procedure.\n");
267 fun_sym
= proc
->outer_symbol
;
269 bproc
= proc
->bi_handler
;
271 printf("Error: Unrecognized builtin function '");
272 symbol_print_fqn(fun_sym
);
277 /* Run the builtin procedure handler. */
281 /** Get pointer to member var of current object.
283 * Returns the var node that corresponds to a member of the currently
284 * active object with the given name. This member must exist.
286 * @param run Runner object.
287 * @param mbr_name Name of member to find.
288 * @return Var node of the member.
290 rdata_var_t
*builtin_get_self_mbr_var(run_t
*run
, const char *mbr_name
)
292 run_proc_ar_t
*proc_ar
;
293 rdata_object_t
*object
;
295 rdata_var_t
*mbr_var
;
297 proc_ar
= run_get_current_proc_ar(run
);
298 assert(proc_ar
->obj
->vc
== vc_object
);
299 object
= proc_ar
->obj
->u
.object_v
;
301 mbr_name_sid
= strtab_get_sid(mbr_name
);
302 mbr_var
= intmap_get(&object
->fields
, mbr_name_sid
);
303 assert(mbr_var
!= NULL
);
308 /** Return string value from builtin procedure.
310 * Makes it easy for a builtin procedure to return value of type @c string.
312 * @param run Runner object
313 * @param str String value. Must be allocated from heap and its
314 * ownership is hereby given up.
316 void builtin_return_string(run_t
*run
, const char *astr
)
318 rdata_string_t
*rstring
;
323 run_proc_ar_t
*proc_ar
;
325 #ifdef DEBUG_RUN_TRACE
326 printf("Return string '%s' from builtin function.\n", astr
);
328 rstring
= rdata_string_new();
329 rstring
->value
= astr
;
331 rvar
= rdata_var_new(vc_string
);
332 rvar
->u
.string_v
= rstring
;
333 rval
= rdata_value_new();
336 ritem
= rdata_item_new(ic_value
);
337 ritem
->u
.value
= rval
;
339 proc_ar
= run_get_current_proc_ar(run
);
340 proc_ar
->retval
= ritem
;
343 /** Declare a static builtin function in @a csi.
345 * Declare a builtin function member of CSI @a csi. Deprecated in favor
346 * of builtin_code_snippet().
348 * @param csi CSI in which to declare function.
349 * @param name Name of member function to declare.
350 * @return Symbol of newly declared function.
352 stree_symbol_t
*builtin_declare_fun(stree_csi_t
*csi
, const char *name
)
354 stree_ident_t
*ident
;
356 stree_fun_sig_t
*sig
;
357 stree_csimbr_t
*csimbr
;
358 stree_symbol_t
*fun_sym
;
359 stree_symbol_attr_t
*sym_attr
;
361 ident
= stree_ident_new();
362 ident
->sid
= strtab_get_sid(name
);
364 fun
= stree_fun_new();
366 fun
->proc
= stree_proc_new();
367 fun
->proc
->body
= NULL
;
368 sig
= stree_fun_sig_new();
371 list_init(&fun
->sig
->args
);
373 csimbr
= stree_csimbr_new(csimbr_fun
);
376 fun_sym
= stree_symbol_new(sc_fun
);
377 fun_sym
->u
.fun
= fun
;
378 fun_sym
->outer_csi
= csi
;
380 sym_attr
= stree_symbol_attr_new(sac_static
);
381 list_append(&fun_sym
->attr
, sym_attr
);
383 fun
->symbol
= fun_sym
;
384 fun
->proc
->outer_symbol
= fun_sym
;
386 list_append(&csi
->members
, csimbr
);
391 /** Add one formal parameter to function.
393 * Used to incrementally construct formal parameter list of a builtin
394 * function. Deprecated in favor of builtin_code_snippet(). Does not
395 * support type checking.
397 * @param fun_sym Symbol of function to add parameters to.
398 * @param name Name of parameter to add.
400 void builtin_fun_add_arg(stree_symbol_t
*fun_sym
, const char *name
)
402 stree_proc_arg_t
*proc_arg
;
405 fun
= symbol_to_fun(fun_sym
);
408 proc_arg
= stree_proc_arg_new();
409 proc_arg
->name
= stree_ident_new();
410 proc_arg
->name
->sid
= strtab_get_sid(name
);
411 proc_arg
->type
= NULL
; /* XXX */
413 list_append(&fun
->sig
->args
, proc_arg
);