• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * copyright 2004, Jean-Christophe Hoelt <jeko@ios-software.com>
3  *
4  * This program is released under the terms of the GNU Lesser General Public Licence.
5  */
6 %{
7     #include <stdio.h>
8     #include <stdlib.h>
9     #include <string.h>
10     #include <glib.h>
11     #include "goomsl.h"
12     #include "goomsl_private.h"
13 
14 #define STRUCT_ALIGNMENT 16
15 /* #define VERBOSE  */
16 
17     int yylex(void);
18     void yyerror(char *);
19     extern GoomSL *currentGoomSL;
20 
21     static NodeType *nodeNew(const char *str, int type, int line_number);
22     static NodeType *nodeClone(NodeType *node);
23     static void nodeFreeInternals(NodeType *node);
24     static void nodeFree(NodeType *node);
25 
26     static void commit_node(NodeType *node, int releaseIfTemp);
27     static void precommit_node(NodeType *node);
28 
29     static NodeType *new_constInt(const char *str, int line_number);
30     static NodeType *new_constFloat(const char *str, int line_number);
31     static NodeType *new_constPtr(const char *str, int line_number);
32     static NodeType *new_var(const char *str, int line_number);
33     static NodeType *new_nop(const char *str);
34     static NodeType *new_op(const char *str, int type, int nbOp);
35 
36     static int  allocateLabel();
37     static int  allocateTemp();
38     static void releaseTemp(int n);
39     static void releaseAllTemps();
40 
is_tmp_expr(NodeType * node)41     static int is_tmp_expr(NodeType *node) {
42         if (node->str) {
43             return (!strncmp(node->str,"_i_tmp_",7))
44               || (!strncmp(node->str,"_f_tmp_",7))
45               || (!strncmp(node->str,"_p_tmp",7));
46         }
47         return 0;
48     }
49     /* pre: is_tmp_expr(node); */
get_tmp_id(NodeType * node)50     static int get_tmp_id(NodeType *node)  { return atoi((node->str)+5); }
51 
is_commutative_expr(int itype)52     static int is_commutative_expr(int itype)
53     { /* {{{ */
54         return (itype == INSTR_ADD)
55             || (itype == INSTR_MUL)
56             || (itype == INSTR_ISEQUAL);
57     } /* }}} */
58 
GSL_PUT_LABEL(char * name,int line_number)59     static void GSL_PUT_LABEL(char *name, int line_number)
60     { /* {{{ */
61 #ifdef VERBOSE
62       printf("label %s\n", name);
63 #endif
64       currentGoomSL->instr = gsl_instr_init(currentGoomSL, "label", INSTR_LABEL, 1, line_number);
65       gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
66     } /* }}} */
GSL_PUT_JUMP(char * name,int line_number)67     static void GSL_PUT_JUMP(char *name, int line_number)
68     { /* {{{ */
69 #ifdef VERBOSE
70       printf("jump %s\n", name);
71 #endif
72       currentGoomSL->instr = gsl_instr_init(currentGoomSL, "jump", INSTR_JUMP, 1, line_number);
73       gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
74     } /* }}} */
75 
GSL_PUT_JXXX(char * name,char * iname,int instr_id,int line_number)76     static void GSL_PUT_JXXX(char *name, char *iname, int instr_id, int line_number)
77     { /* {{{ */
78 #ifdef VERBOSE
79       printf("%s %s\n", iname, name);
80 #endif
81       currentGoomSL->instr = gsl_instr_init(currentGoomSL, iname, instr_id, 1, line_number);
82       gsl_instr_add_param(currentGoomSL->instr, name, TYPE_LABEL);
83     } /* }}} */
GSL_PUT_JZERO(char * name,int line_number)84     static void GSL_PUT_JZERO(char *name,int line_number)
85     { /* {{{ */
86       GSL_PUT_JXXX(name,"jzero.i",INSTR_JZERO,line_number);
87     } /* }}} */
GSL_PUT_JNZERO(char * name,int line_number)88     static void GSL_PUT_JNZERO(char *name, int line_number)
89     { /* {{{ */
90       GSL_PUT_JXXX(name,"jnzero.i",INSTR_JNZERO,line_number);
91     } /* }}} */
92 
93     /* Structures Management */
94 
95 #define ALIGN_ADDR(_addr,_align) {\
96    if (_align>1) {\
97        int _dec = (_addr%_align);\
98        if (_dec != 0) _addr += _align - _dec;\
99    }}
100 
101     /* */
gsl_prepare_struct(GSL_Struct * s,int s_align,int i_align,int f_align)102     void gsl_prepare_struct(GSL_Struct *s, int s_align, int i_align, int f_align)
103     {
104       int i;
105       int consumed = 0;
106       int iblk=0, fblk=0;
107 
108       s->iBlock[0].size = 0;
109       s->iBlock[0].data = 0;
110       s->fBlock[0].size = 0;
111       s->fBlock[0].data = 0;
112 
113       /* Prepare sub-struct and calculate space needed for their storage */
114       for (i = 0; i < s->nbFields; ++i)
115       {
116         if (s->fields[i]->type < FIRST_RESERVED)
117         {
118           int j=0;
119           GSL_Struct *substruct = currentGoomSL->gsl_struct[s->fields[i]->type];
120           consumed += sizeof(int); /* stocke le prefix */
121           ALIGN_ADDR(consumed, s_align);
122           s->fields[i]->offsetInStruct = consumed;
123           gsl_prepare_struct(substruct, s_align, i_align, f_align);
124           for(j=0;substruct->iBlock[j].size>0;++j) {
125             s->iBlock[iblk].data = consumed + substruct->iBlock[j].data;
126             s->iBlock[iblk].size = substruct->iBlock[j].size;
127             iblk++;
128           }
129           for(j=0;substruct->fBlock[j].size>0;++j) {
130             s->fBlock[fblk].data = consumed + substruct->fBlock[j].data;
131             s->fBlock[fblk].size = substruct->fBlock[j].size;
132             fblk++;
133           }
134           consumed += substruct->size;
135         }
136       }
137 
138       /* Then prepare integers */
139       ALIGN_ADDR(consumed, i_align);
140       for (i = 0; i < s->nbFields; ++i)
141       {
142         if (s->fields[i]->type == INSTR_INT)
143         {
144           if (s->iBlock[iblk].size == 0) {
145             s->iBlock[iblk].size = 1;
146             s->iBlock[iblk].data = consumed;
147           } else {
148             s->iBlock[iblk].size += 1;
149           }
150           s->fields[i]->offsetInStruct = consumed;
151           consumed += sizeof(int);
152         }
153       }
154 
155       iblk++;
156       s->iBlock[iblk].size = 0;
157       s->iBlock[iblk].data = 0;
158 
159       /* Then prepare floats */
160       ALIGN_ADDR(consumed, f_align);
161       for (i = 0; i < s->nbFields; ++i)
162       {
163         if (s->fields[i]->type == INSTR_FLOAT)
164         {
165           if (s->fBlock[fblk].size == 0) {
166             s->fBlock[fblk].size = 1;
167             s->fBlock[fblk].data = consumed;
168           } else {
169             s->fBlock[fblk].size += 1;
170           }
171           s->fields[i]->offsetInStruct = consumed;
172           consumed += sizeof(int);
173         }
174       }
175 
176       fblk++;
177       s->fBlock[fblk].size = 0;
178       s->fBlock[fblk].data = 0;
179 
180       /* Finally prepare pointers */
181       ALIGN_ADDR(consumed, i_align);
182       for (i = 0; i < s->nbFields; ++i)
183       {
184         if (s->fields[i]->type == INSTR_PTR)
185         {
186           s->fields[i]->offsetInStruct = consumed;
187           consumed += sizeof(int);
188         }
189       }
190       s->size = consumed;
191     }
192 
193     /* Returns the ID of a struct from its name */
gsl_get_struct_id(const char * name)194     int gsl_get_struct_id(const char *name) /* {{{ */
195     {
196       HashValue *ret = goom_hash_get(currentGoomSL->structIDS, name);
197       if (ret != NULL) return ret->i;
198       return -1;
199     } /* }}} */
200 
201     /* Adds the definition of a struct */
gsl_add_struct(const char * name,GSL_Struct * gsl_struct)202     void gsl_add_struct(const char *name, GSL_Struct *gsl_struct) /* {{{ */
203     {
204       /* Prepare the struct: ie calculate internal storage format */
205       gsl_prepare_struct(gsl_struct, STRUCT_ALIGNMENT, STRUCT_ALIGNMENT, STRUCT_ALIGNMENT);
206 
207       /* If the struct does not already exists */
208       if (gsl_get_struct_id(name) < 0)
209       {
210         /* adds it */
211         int id = currentGoomSL->nbStructID++;
212         goom_hash_put_int(currentGoomSL->structIDS, name, id);
213         if (currentGoomSL->gsl_struct_size <= id) {
214           currentGoomSL->gsl_struct_size *= 2;
215           currentGoomSL->gsl_struct = (GSL_Struct**)realloc(currentGoomSL->gsl_struct,
216                                                             sizeof(GSL_Struct*) * currentGoomSL->gsl_struct_size);
217         }
218         currentGoomSL->gsl_struct[id] = gsl_struct;
219       }
220     } /* }}} */
221 
222     /* Creates a field for a struct */
gsl_new_struct_field(const char * name,int type)223     GSL_StructField *gsl_new_struct_field(const char *name, int type)
224     {
225       GSL_StructField *field = (GSL_StructField*)malloc(sizeof(GSL_StructField));
226       strcpy(field->name, name);
227       field->type = type;
228       return field;
229     }
230 
231     /* Create as field for a struct which will be a struct itself */
gsl_new_struct_field_struct(const char * name,const char * type)232     GSL_StructField *gsl_new_struct_field_struct(const char *name, const char *type)
233     {
234       GSL_StructField *field = gsl_new_struct_field(name, gsl_get_struct_id(type));
235       if (field->type < 0) {
236         g_assert_not_reached ();
237 #if 0
238         fprintf(stderr, "ERROR: Line %d, Unknown structure: '%s'\n",
239                 currentGoomSL->num_lines, type);
240         exit(1);
241 #endif
242       }
243       return field;
244     }
245 
246     /* Creates a Struct */
gsl_new_struct(GSL_StructField * field)247     GSL_Struct *gsl_new_struct(GSL_StructField *field)
248     {
249       GSL_Struct *s = (GSL_Struct*)malloc(sizeof(GSL_Struct));
250       s->nbFields = 1;
251       s->fields[0] = field;
252       return s;
253     }
254 
255     /* Adds a field to a struct */
gsl_add_struct_field(GSL_Struct * s,GSL_StructField * field)256     void gsl_add_struct_field(GSL_Struct *s, GSL_StructField *field)
257     {
258       s->fields[s->nbFields++] = field;
259     }
260 
gsl_type_of_var(GoomHash * ns,const char * name)261     int gsl_type_of_var(GoomHash *ns, const char *name)
262     {
263         char type_of[256];
264         HashValue *hv;
265         sprintf(type_of, "__type_of_%s", name);
266         hv = goom_hash_get(ns, type_of);
267         if (hv != NULL)
268           return hv->i;
269         fprintf(stderr, "ERROR: Unknown variable type: '%s'\n", name);
270         return -1;
271     }
272 
gsl_declare_var(GoomHash * ns,const char * name,int type,void * space)273     static void gsl_declare_var(GoomHash *ns, const char *name, int type, void *space)
274     {
275         char type_of[256];
276         if (name[0] == '@') { ns = currentGoomSL->vars; }
277 
278         if (space == NULL) {
279           switch (type) {
280             case INSTR_INT:
281             case INSTR_FLOAT:
282             case INSTR_PTR:
283               space = goom_heap_malloc_with_alignment(currentGoomSL->data_heap,
284                   sizeof(int), sizeof(int));
285             break;
286 #if 0
287             case -1:
288               fprintf(stderr, "What the fuck!\n");
289               exit(1);
290 #endif
291             default: /* On a un struct_id */
292               space = goom_heap_malloc_with_alignment_prefixed(currentGoomSL->data_heap,
293                   currentGoomSL->gsl_struct[type]->size, STRUCT_ALIGNMENT, sizeof(int));
294           }
295         }
296         goom_hash_put_ptr(ns, name, (void*)space);
297         sprintf(type_of, "__type_of_%s", name);
298         goom_hash_put_int(ns, type_of, type);
299 
300         /* Ensuite le hack: on ajoute les champs en tant que variables. */
301         if (type < FIRST_RESERVED)
302         {
303           int i;
304           GSL_Struct *gsl_struct = currentGoomSL->gsl_struct[type];
305           ((int*)space)[-1] = type; /* stockage du type dans le prefixe de structure */
306           for (i = 0; i < gsl_struct->nbFields; ++i)
307           {
308             char full_name[256];
309             char *cspace = (char*)space + gsl_struct->fields[i]->offsetInStruct;
310             sprintf(full_name, "%s.%s", name, gsl_struct->fields[i]->name);
311             gsl_declare_var(ns, full_name, gsl_struct->fields[i]->type, cspace);
312           }
313        }
314     }
315 
316     /* Declare a variable which will be a struct */
gsl_struct_decl(GoomHash * namespace,const char * struct_name,const char * name)317     static void gsl_struct_decl(GoomHash *namespace, const char *struct_name, const char *name)
318     {
319         int  struct_id = gsl_get_struct_id(struct_name);
320         gsl_declare_var(namespace, name, struct_id, NULL);
321     }
322 
gsl_float_decl_global(const char * name)323     static void gsl_float_decl_global(const char *name)
324     {
325         gsl_declare_var(currentGoomSL->vars, name, INSTR_FLOAT, NULL);
326     }
gsl_int_decl_global(const char * name)327     static void gsl_int_decl_global(const char *name)
328     {
329         gsl_declare_var(currentGoomSL->vars, name, INSTR_INT, NULL);
330     }
gsl_ptr_decl_global(const char * name)331     static void gsl_ptr_decl_global(const char *name)
332     {
333         gsl_declare_var(currentGoomSL->vars, name, INSTR_PTR, NULL);
334     }
gsl_struct_decl_global_from_id(const char * name,int id)335     static void gsl_struct_decl_global_from_id(const char *name, int id)
336     {
337         gsl_declare_var(currentGoomSL->vars, name, id, NULL);
338     }
339 
340     /* FLOAT */
gsl_float_decl_local(const char * name)341     static void gsl_float_decl_local(const char *name)
342     {
343         gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_FLOAT, NULL);
344     }
345     /* INT */
gsl_int_decl_local(const char * name)346     static void gsl_int_decl_local(const char *name)
347     {
348         gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_INT, NULL);
349     }
350     /* PTR */
gsl_ptr_decl_local(const char * name)351     static void gsl_ptr_decl_local(const char *name)
352     {
353         gsl_declare_var(currentGoomSL->namespaces[currentGoomSL->currentNS], name, INSTR_PTR, NULL);
354     }
355     /* STRUCT */
gsl_struct_decl_local(const char * struct_name,const char * name)356     static void gsl_struct_decl_local(const char *struct_name, const char *name)
357     {
358         gsl_struct_decl(currentGoomSL->namespaces[currentGoomSL->currentNS],struct_name,name);
359     }
360 
361 
362     static void commit_test2(NodeType *set,const char *type, int instr);
363     static NodeType *new_call(const char *name, NodeType *affect_list);
364 
365     /* SETTER */
new_set(NodeType * lvalue,NodeType * expression)366     static NodeType *new_set(NodeType *lvalue, NodeType *expression)
367     { /* {{{ */
368         NodeType *set = new_op("set", OPR_SET, 2);
369         set->unode.opr.op[0] = lvalue;
370         set->unode.opr.op[1] = expression;
371         return set;
372     } /* }}} */
commit_set(NodeType * set)373     static void commit_set(NodeType *set)
374     { /* {{{ */
375       commit_test2(set,"set",INSTR_SET);
376     } /* }}} */
377 
378     /* PLUS_EQ */
new_plus_eq(NodeType * lvalue,NodeType * expression)379     static NodeType *new_plus_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
380     {
381         NodeType *set = new_op("plus_eq", OPR_PLUS_EQ, 2);
382         set->unode.opr.op[0] = lvalue;
383         set->unode.opr.op[1] = expression;
384         return set;
385     }
commit_plus_eq(NodeType * set)386     static void commit_plus_eq(NodeType *set)
387     {
388         precommit_node(set->unode.opr.op[1]);
389 #ifdef VERBOSE
390         printf("add %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
391 #endif
392         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "add", INSTR_ADD, 2, set->line_number);
393         commit_node(set->unode.opr.op[0],0);
394         commit_node(set->unode.opr.op[1],1);
395     } /* }}} */
396 
397     /* SUB_EQ */
new_sub_eq(NodeType * lvalue,NodeType * expression)398     static NodeType *new_sub_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
399     {
400         NodeType *set = new_op("sub_eq", OPR_SUB_EQ, 2);
401         set->unode.opr.op[0] = lvalue;
402         set->unode.opr.op[1] = expression;
403         return set;
404     }
commit_sub_eq(NodeType * set)405     static void commit_sub_eq(NodeType *set)
406     {
407         precommit_node(set->unode.opr.op[1]);
408 #ifdef VERBOSE
409         printf("sub %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
410 #endif
411         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "sub", INSTR_SUB, 2, set->line_number);
412         commit_node(set->unode.opr.op[0],0);
413         commit_node(set->unode.opr.op[1],1);
414     } /* }}} */
415 
416     /* MUL_EQ */
new_mul_eq(NodeType * lvalue,NodeType * expression)417     static NodeType *new_mul_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
418     {
419         NodeType *set = new_op("mul_eq", OPR_MUL_EQ, 2);
420         set->unode.opr.op[0] = lvalue;
421         set->unode.opr.op[1] = expression;
422         return set;
423     }
commit_mul_eq(NodeType * set)424     static void commit_mul_eq(NodeType *set)
425     {
426         precommit_node(set->unode.opr.op[1]);
427 #ifdef VERBOSE
428         printf("mul %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
429 #endif
430         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "mul", INSTR_MUL, 2, set->line_number);
431         commit_node(set->unode.opr.op[0],0);
432         commit_node(set->unode.opr.op[1],1);
433     } /* }}} */
434 
435     /* DIV_EQ */
new_div_eq(NodeType * lvalue,NodeType * expression)436     static NodeType *new_div_eq(NodeType *lvalue, NodeType *expression) /* {{{ */
437     {
438         NodeType *set = new_op("div_eq", OPR_DIV_EQ, 2);
439         set->unode.opr.op[0] = lvalue;
440         set->unode.opr.op[1] = expression;
441         return set;
442     }
commit_div_eq(NodeType * set)443     static void commit_div_eq(NodeType *set)
444     {
445         precommit_node(set->unode.opr.op[1]);
446 #ifdef VERBOSE
447         printf("div %s %s\n", set->unode.opr.op[0]->str, set->unode.opr.op[1]->str);
448 #endif
449         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "div", INSTR_DIV, 2, set->line_number);
450         commit_node(set->unode.opr.op[0],0);
451         commit_node(set->unode.opr.op[1],1);
452     } /* }}} */
453 
454     /* commodity method for add, mult, ... */
455 
precommit_expr(NodeType * expr,const char * type,int instr_id)456     static void precommit_expr(NodeType *expr, const char *type, int instr_id)
457     { /* {{{ */
458         NodeType *tmp, *tmpcpy;
459         int toAdd;
460 
461         /* compute "left" and "right" */
462         switch (expr->unode.opr.nbOp) {
463         case 2:
464           precommit_node(expr->unode.opr.op[1]);
465         case 1:
466           precommit_node(expr->unode.opr.op[0]);
467         }
468 
469         if (is_tmp_expr(expr->unode.opr.op[0])) {
470             tmp = expr->unode.opr.op[0];
471             toAdd = 1;
472         }
473         else if (is_commutative_expr(instr_id) && (expr->unode.opr.nbOp==2) && is_tmp_expr(expr->unode.opr.op[1])) {
474             tmp = expr->unode.opr.op[1];
475             toAdd = 0;
476         }
477         else {
478             char stmp[256];
479             /* declare a temporary variable to store the result */
480             if (expr->unode.opr.op[0]->type == CONST_INT_NODE) {
481                 sprintf(stmp,"_i_tmp_%i",allocateTemp());
482                 gsl_int_decl_global(stmp);
483             }
484             else if (expr->unode.opr.op[0]->type == CONST_FLOAT_NODE) {
485                 sprintf(stmp,"_f_tmp%i",allocateTemp());
486                 gsl_float_decl_global(stmp);
487             }
488             else if (expr->unode.opr.op[0]->type == CONST_PTR_NODE) {
489                 sprintf(stmp,"_p_tmp%i",allocateTemp());
490                 gsl_ptr_decl_global(stmp);
491             }
492             else {
493                 int type = gsl_type_of_var(expr->unode.opr.op[0]->vnamespace, expr->unode.opr.op[0]->str);
494                 if (type == INSTR_FLOAT) {
495                     sprintf(stmp,"_f_tmp_%i",allocateTemp());
496                     gsl_float_decl_global(stmp);
497                 }
498                 else if (type == INSTR_PTR) {
499                     sprintf(stmp,"_p_tmp_%i",allocateTemp());
500                     gsl_ptr_decl_global(stmp);
501                 }
502                 else if (type == INSTR_INT) {
503                     sprintf(stmp,"_i_tmp_%i",allocateTemp());
504                     gsl_int_decl_global(stmp);
505                 }
506                 else if (type == -1) {
507                     g_assert_not_reached ();
508 #if 0
509                     fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
510                             expr->line_number, expr->unode.opr.op[0]->str);
511                     exit(1);
512 #endif
513                 }
514                 else { /* type is a struct_id */
515                     sprintf(stmp,"_s_tmp_%i",allocateTemp());
516                     gsl_struct_decl_global_from_id(stmp,type);
517                 }
518             }
519             tmp = new_var(stmp,expr->line_number);
520 
521             /* set the tmp to the value of "op1" */
522             tmpcpy = nodeClone(tmp);
523             commit_node(new_set(tmp,expr->unode.opr.op[0]),0);
524             toAdd = 1;
525 
526             tmp = tmpcpy;
527         }
528 
529         /* add op2 to tmp */
530 #ifdef VERBOSE
531         if (expr->unode.opr.nbOp == 2)
532           printf("%s %s %s\n", type, tmp->str, expr->unode.opr.op[toAdd]->str);
533         else
534           printf("%s %s\n", type, tmp->str);
535 #endif
536         currentGoomSL->instr = gsl_instr_init(currentGoomSL, type, instr_id, expr->unode.opr.nbOp, expr->line_number);
537         tmpcpy = nodeClone(tmp);
538         commit_node(tmp,0);
539         if (expr->unode.opr.nbOp == 2) {
540           commit_node(expr->unode.opr.op[toAdd],1);
541         }
542 
543         /* redefine the ADD node now as the computed variable */
544         nodeFreeInternals(expr);
545         *expr = *tmpcpy;
546         free(tmpcpy);
547     } /* }}} */
548 
new_expr1(const char * name,int id,NodeType * expr1)549     static NodeType *new_expr1(const char *name, int id, NodeType *expr1)
550     { /* {{{ */
551         NodeType *add = new_op(name, id, 1);
552         add->unode.opr.op[0] = expr1;
553         return add;
554     } /* }}} */
555 
new_expr2(const char * name,int id,NodeType * expr1,NodeType * expr2)556     static NodeType *new_expr2(const char *name, int id, NodeType *expr1, NodeType *expr2)
557     { /* {{{ */
558         NodeType *add = new_op(name, id, 2);
559         add->unode.opr.op[0] = expr1;
560         add->unode.opr.op[1] = expr2;
561         return add;
562     } /* }}} */
563 
564     /* ADD */
new_add(NodeType * expr1,NodeType * expr2)565     static NodeType *new_add(NodeType *expr1, NodeType *expr2) { /* {{{ */
566         return new_expr2("add", OPR_ADD, expr1, expr2);
567     }
precommit_add(NodeType * add)568     static void precommit_add(NodeType *add) {
569         precommit_expr(add,"add",INSTR_ADD);
570     } /* }}} */
571 
572     /* SUB */
new_sub(NodeType * expr1,NodeType * expr2)573     static NodeType *new_sub(NodeType *expr1, NodeType *expr2) { /* {{{ */
574         return new_expr2("sub", OPR_SUB, expr1, expr2);
575     }
precommit_sub(NodeType * sub)576     static void precommit_sub(NodeType *sub) {
577         precommit_expr(sub,"sub",INSTR_SUB);
578     } /* }}} */
579 
580     /* NEG */
new_neg(NodeType * expr)581     static NodeType *new_neg(NodeType *expr) { /* {{{ */
582         NodeType *zeroConst = NULL;
583         if (expr->type == CONST_INT_NODE)
584           zeroConst = new_constInt("0", currentGoomSL->num_lines);
585         else if (expr->type == CONST_FLOAT_NODE)
586           zeroConst = new_constFloat("0.0", currentGoomSL->num_lines);
587         else if (expr->type == CONST_PTR_NODE) {
588           g_assert_not_reached ();
589 #if 0
590           fprintf(stderr, "ERROR: Line %d, Could not negate const pointer.\n",
591             currentGoomSL->num_lines);
592           exit(1);
593 #endif
594         }
595         else {
596             int type = gsl_type_of_var(expr->vnamespace, expr->str);
597             if (type == INSTR_FLOAT)
598               zeroConst = new_constFloat("0.0", currentGoomSL->num_lines);
599             else if (type == INSTR_PTR) {
600               g_assert_not_reached ();
601 #if 0
602               fprintf(stderr, "ERROR: Line %d, Could not negate pointer.\n",
603                 currentGoomSL->num_lines);
604               exit(1);
605 #endif
606             }
607             else if (type == INSTR_INT)
608               zeroConst = new_constInt("0", currentGoomSL->num_lines);
609             else if (type == -1) {
610                 g_assert_not_reached ();
611 #if 0
612                 fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
613                         expr->line_number, expr->unode.opr.op[0]->str);
614                 exit(1);
615 #endif
616             }
617             else { /* type is a struct_id */
618                 g_assert_not_reached ();
619 #if 0
620                 fprintf(stderr, "ERROR: Line %d, Could not negate struct '%s'\n",
621                         expr->line_number, expr->str);
622                 exit(1);
623 #endif
624             }
625         }
626         return new_expr2("sub", OPR_SUB, zeroConst, expr);
627     }
628     /* }}} */
629 
630     /* MUL */
new_mul(NodeType * expr1,NodeType * expr2)631     static NodeType *new_mul(NodeType *expr1, NodeType *expr2) { /* {{{ */
632         return new_expr2("mul", OPR_MUL, expr1, expr2);
633     }
precommit_mul(NodeType * mul)634     static void precommit_mul(NodeType *mul) {
635         precommit_expr(mul,"mul",INSTR_MUL);
636     } /* }}} */
637 
638     /* DIV */
new_div(NodeType * expr1,NodeType * expr2)639     static NodeType *new_div(NodeType *expr1, NodeType *expr2) { /* {{{ */
640         return new_expr2("div", OPR_DIV, expr1, expr2);
641     }
precommit_div(NodeType * mul)642     static void precommit_div(NodeType *mul) {
643         precommit_expr(mul,"div",INSTR_DIV);
644     } /* }}} */
645 
646     /* CALL EXPRESSION */
new_call_expr(const char * name,NodeType * affect_list)647     static NodeType *new_call_expr(const char *name, NodeType *affect_list) { /* {{{ */
648         NodeType *call = new_call(name,affect_list);
649         NodeType *node = new_expr1(name, OPR_CALL_EXPR, call);
650         node->vnamespace = gsl_find_namespace(name);
651         if (node->vnamespace == NULL)
652           /* fprintf(stderr, "ERROR: Line %d, No return type for: '%s'\n", currentGoomSL->num_lines, name); */
653         return node;
654     }
precommit_call_expr(NodeType * call)655     static void precommit_call_expr(NodeType *call) {
656         char stmp[256];
657         NodeType *tmp,*tmpcpy;
658         int type = gsl_type_of_var(call->vnamespace, call->str);
659         if (type == INSTR_FLOAT) {
660           sprintf(stmp,"_f_tmp_%i",allocateTemp());
661           gsl_float_decl_global(stmp);
662         }
663         else if (type == INSTR_PTR) {
664           sprintf(stmp,"_p_tmp_%i",allocateTemp());
665           gsl_ptr_decl_global(stmp);
666         }
667         else if (type == INSTR_INT) {
668           sprintf(stmp,"_i_tmp_%i",allocateTemp());
669           gsl_int_decl_global(stmp);
670         }
671         else if (type == -1) {
672           g_assert_not_reached ();
673 #if 0
674           fprintf(stderr, "ERROR: Line %d, Could not find variable '%s'\n",
675                   call->line_number, call->str);
676           exit(1);
677 #endif
678         }
679         else { /* type is a struct_id */
680           sprintf(stmp,"_s_tmp_%i",allocateTemp());
681           gsl_struct_decl_global_from_id(stmp,type);
682         }
683         tmp = new_var(stmp,call->line_number);
684         commit_node(call->unode.opr.op[0],0);
685         tmpcpy = nodeClone(tmp);
686         commit_node(new_set(tmp,new_var(call->str,call->line_number)),0);
687 
688         nodeFreeInternals(call);
689         *call = *tmpcpy;
690         free(tmpcpy);
691     } /* }}} */
692 
commit_test2(NodeType * set,const char * type,int instr)693     static void commit_test2(NodeType *set,const char *type, int instr)
694     { /* {{{ */
695         NodeType *tmp;
696         char stmp[256];
697         precommit_node(set->unode.opr.op[0]);
698         precommit_node(set->unode.opr.op[1]);
699         tmp = set->unode.opr.op[0];
700 
701         stmp[0] = 0;
702         if (set->unode.opr.op[0]->type == CONST_INT_NODE) {
703             sprintf(stmp,"_i_tmp_%i",allocateTemp());
704             gsl_int_decl_global(stmp);
705         }
706         else if (set->unode.opr.op[0]->type == CONST_FLOAT_NODE) {
707             sprintf(stmp,"_f_tmp%i",allocateTemp());
708             gsl_float_decl_global(stmp);
709         }
710         else if (set->unode.opr.op[0]->type == CONST_PTR_NODE) {
711             sprintf(stmp,"_p_tmp%i",allocateTemp());
712             gsl_ptr_decl_global(stmp);
713         }
714         if (stmp[0]) {
715             NodeType *tmpcpy;
716             tmp = new_var(stmp, set->line_number);
717             tmpcpy = nodeClone(tmp);
718             commit_node(new_set(tmp,set->unode.opr.op[0]),0);
719             tmp = tmpcpy;
720         }
721 
722 #ifdef VERBOSE
723         printf("%s %s %s\n", type, tmp->str, set->unode.opr.op[1]->str);
724 #endif
725         currentGoomSL->instr = gsl_instr_init(currentGoomSL, type, instr, 2, set->line_number);
726         commit_node(tmp,instr!=INSTR_SET);
727         commit_node(set->unode.opr.op[1],1);
728     } /* }}} */
729 
730     /* NOT */
new_not(NodeType * expr1)731     static NodeType *new_not(NodeType *expr1) { /* {{{ */
732         return new_expr1("not", OPR_NOT, expr1);
733     }
commit_not(NodeType * set)734     static void commit_not(NodeType *set)
735     {
736         commit_node(set->unode.opr.op[0],0);
737 #ifdef VERBOSE
738         printf("not\n");
739 #endif
740         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "not", INSTR_NOT, 1, set->line_number);
741         gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
742     } /* }}} */
743 
744     /* EQU */
new_equ(NodeType * expr1,NodeType * expr2)745     static NodeType *new_equ(NodeType *expr1, NodeType *expr2) { /* {{{ */
746         return new_expr2("isequal", OPR_EQU, expr1, expr2);
747     }
commit_equ(NodeType * mul)748     static void commit_equ(NodeType *mul) {
749         commit_test2(mul,"isequal",INSTR_ISEQUAL);
750     } /* }}} */
751 
752     /* INF */
new_low(NodeType * expr1,NodeType * expr2)753     static NodeType *new_low(NodeType *expr1, NodeType *expr2) { /* {{{ */
754         return new_expr2("islower", OPR_LOW, expr1, expr2);
755     }
commit_low(NodeType * mul)756     static void commit_low(NodeType *mul) {
757         commit_test2(mul,"islower",INSTR_ISLOWER);
758     } /* }}} */
759 
760     /* WHILE */
new_while(NodeType * expression,NodeType * instr)761     static NodeType *new_while(NodeType *expression, NodeType *instr) { /* {{{ */
762         NodeType *node = new_op("while", OPR_WHILE, 2);
763         node->unode.opr.op[0] = expression;
764         node->unode.opr.op[1] = instr;
765         return node;
766     }
767 
commit_while(NodeType * node)768     static void commit_while(NodeType *node)
769     {
770         int lbl = allocateLabel();
771         char start_while[1024], test_while[1024];
772         sprintf(start_while, "|start_while_%d|", lbl);
773         sprintf(test_while, "|test_while_%d|", lbl);
774 
775         GSL_PUT_JUMP(test_while,node->line_number);
776         GSL_PUT_LABEL(start_while,node->line_number);
777 
778         /* code */
779         commit_node(node->unode.opr.op[1],0);
780 
781         GSL_PUT_LABEL(test_while,node->line_number);
782         commit_node(node->unode.opr.op[0],0);
783         GSL_PUT_JNZERO(start_while,node->line_number);
784     } /* }}} */
785 
786     /* FOR EACH */
new_static_foreach(NodeType * var,NodeType * var_list,NodeType * instr)787     static NodeType *new_static_foreach(NodeType *var, NodeType *var_list, NodeType *instr) { /* {{{ */
788         NodeType *node = new_op("for", OPR_FOREACH, 3);
789         node->unode.opr.op[0] = var;
790         node->unode.opr.op[1] = var_list;
791         node->unode.opr.op[2] = instr;
792         node->line_number = currentGoomSL->num_lines;
793         return node;
794     }
commit_foreach(NodeType * node)795     static void commit_foreach(NodeType *node)
796     {
797         NodeType *cur = node->unode.opr.op[1];
798         char tmp_func[256], tmp_loop[256];
799         int lbl = allocateLabel();
800         sprintf(tmp_func, "|foreach_func_%d|", lbl);
801         sprintf(tmp_loop, "|foreach_loop_%d|", lbl);
802 
803         GSL_PUT_JUMP(tmp_loop, node->line_number);
804         GSL_PUT_LABEL(tmp_func, node->line_number);
805 
806         precommit_node(node->unode.opr.op[2]);
807         commit_node(node->unode.opr.op[2], 0);
808 
809         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "ret", INSTR_RET, 1, node->line_number);
810         gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
811 #ifdef VERBOSE
812         printf("ret\n");
813 #endif
814 
815         GSL_PUT_LABEL(tmp_loop, node->line_number);
816 
817         while (cur != NULL)
818         {
819           NodeType *x, *var;
820 
821           /* 1: x=var */
822           x   = nodeClone(node->unode.opr.op[0]);
823           var = nodeClone(cur->unode.opr.op[0]);
824           commit_node(new_set(x, var),0);
825 
826           /* 2: instr */
827           currentGoomSL->instr = gsl_instr_init(currentGoomSL, "call", INSTR_CALL, 1, node->line_number);
828           gsl_instr_add_param(currentGoomSL->instr, tmp_func, TYPE_LABEL);
829 #ifdef VERBOSE
830           printf("call %s\n", tmp_func);
831 #endif
832 
833           /* 3: var=x */
834           x   = nodeClone(node->unode.opr.op[0]);
835           var = cur->unode.opr.op[0];
836           commit_node(new_set(var, x),0);
837           cur = cur->unode.opr.op[1];
838         }
839         nodeFree(node->unode.opr.op[0]);
840     } /* }}} */
841 
842     /* IF */
new_if(NodeType * expression,NodeType * instr)843     static NodeType *new_if(NodeType *expression, NodeType *instr) { /* {{{ */
844         NodeType *node = new_op("if", OPR_IF, 2);
845         node->unode.opr.op[0] = expression;
846         node->unode.opr.op[1] = instr;
847         return node;
848     }
commit_if(NodeType * node)849     static void commit_if(NodeType *node) {
850 
851         char slab[1024];
852         sprintf(slab, "|eif%d|", allocateLabel());
853         commit_node(node->unode.opr.op[0],0);
854         GSL_PUT_JZERO(slab,node->line_number);
855         /* code */
856         commit_node(node->unode.opr.op[1],0);
857         GSL_PUT_LABEL(slab,node->line_number);
858     } /* }}} */
859 
860     /* BLOCK */
new_block(NodeType * lastNode)861     static NodeType *new_block(NodeType *lastNode) { /* {{{ */
862         NodeType *blk = new_op("block", OPR_BLOCK, 2);
863         blk->unode.opr.op[0] = new_nop("start_of_block");
864         blk->unode.opr.op[1] = lastNode;
865         return blk;
866     }
commit_block(NodeType * node)867     static void commit_block(NodeType *node) {
868         commit_node(node->unode.opr.op[0]->unode.opr.next,0);
869     } /* }}} */
870 
871     /* FUNCTION INTRO */
new_function_intro(const char * name)872     static NodeType *new_function_intro(const char *name) { /* {{{ */
873         char stmp[256];
874         if (strlen(name) < 200) {
875            sprintf(stmp, "|__func_%s|", name);
876         }
877         return new_op(stmp, OPR_FUNC_INTRO, 0);
878     }
commit_function_intro(NodeType * node)879     static void commit_function_intro(NodeType *node) {
880         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "label", INSTR_LABEL, 1, node->line_number);
881         gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_LABEL);
882 #ifdef VERBOSE
883         printf("label %s\n", node->str);
884 #endif
885     } /* }}} */
886 
887     /* FUNCTION OUTRO */
new_function_outro()888     static NodeType *new_function_outro() { /* {{{ */
889         return new_op("ret", OPR_FUNC_OUTRO, 0);
890     }
commit_function_outro(NodeType * node)891     static void commit_function_outro(NodeType *node) {
892         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "ret", INSTR_RET, 1, node->line_number);
893         gsl_instr_add_param(currentGoomSL->instr, "|dummy|", TYPE_LABEL);
894         releaseAllTemps();
895 #ifdef VERBOSE
896         printf("ret\n");
897 #endif
898     } /* }}} */
899 
900     /* AFFECTATION LIST */
new_affec_list(NodeType * set,NodeType * next)901     static NodeType *new_affec_list(NodeType *set, NodeType *next) /* {{{ */
902     {
903       NodeType *node = new_op("affect_list", OPR_AFFECT_LIST, 2);
904       node->unode.opr.op[0] = set;
905       node->unode.opr.op[1] = next;
906       return node;
907     }
new_affect_list_after(NodeType * affect_list)908     static NodeType *new_affect_list_after(NodeType *affect_list)
909     {
910       NodeType *ret  = NULL;
911       NodeType *cur  =  affect_list;
912       while(cur != NULL) {
913         NodeType *set  = cur->unode.opr.op[0];
914         NodeType *next = cur->unode.opr.op[1];
915         NodeType *lvalue     = set->unode.opr.op[0];
916         NodeType *expression = set->unode.opr.op[1];
917         if ((lvalue->str[0] == '&') && (expression->type == VAR_NODE)) {
918           NodeType *nset = new_set(nodeClone(expression), nodeClone(lvalue));
919           ret  = new_affec_list(nset, ret);
920         }
921         cur = next;
922       }
923       return ret;
924     }
commit_affect_list(NodeType * node)925     static void commit_affect_list(NodeType *node)
926     {
927       NodeType *cur = node;
928       while(cur != NULL) {
929         NodeType *set = cur->unode.opr.op[0];
930         precommit_node(set->unode.opr.op[0]);
931         precommit_node(set->unode.opr.op[1]);
932         cur = cur->unode.opr.op[1];
933       }
934       cur = node;
935       while(cur != NULL) {
936         NodeType *set = cur->unode.opr.op[0];
937         commit_node(set,0);
938         cur = cur->unode.opr.op[1];
939       }
940     } /* }}} */
941 
942     /* VAR LIST */
new_var_list(NodeType * var,NodeType * next)943     static NodeType *new_var_list(NodeType *var, NodeType *next) /* {{{ */
944     {
945       NodeType *node = new_op("var_list", OPR_VAR_LIST, 2);
946       node->unode.opr.op[0] = var;
947       node->unode.opr.op[1] = next;
948       return node;
949     }
commit_var_list(NodeType * node)950     static void commit_var_list(NodeType *node)
951     {
952     } /* }}} */
953 
954     /* FUNCTION CALL */
new_call(const char * name,NodeType * affect_list)955     static NodeType *new_call(const char *name, NodeType *affect_list) { /* {{{ */
956         HashValue *fval;
957         fval = goom_hash_get(currentGoomSL->functions, name);
958         if (!fval) {
959             gsl_declare_task(name);
960             fval = goom_hash_get(currentGoomSL->functions, name);
961         }
962         if (!fval) {
963             g_assert_not_reached ();
964 #if 0
965             fprintf(stderr, "ERROR: Line %d, Could not find function %s\n", currentGoomSL->num_lines, name);
966             exit(1);
967             return NULL;
968 #endif
969         }
970         else {
971             ExternalFunctionStruct *gef = (ExternalFunctionStruct*)fval->ptr;
972             if (gef->is_extern) {
973                 NodeType *node =  new_op(name, OPR_EXT_CALL, 1);
974                 node->unode.opr.op[0] = affect_list;
975                 return node;
976             }
977             else {
978                 NodeType *node;
979                 char stmp[256];
980                 if (strlen(name) < 200) {
981                     sprintf(stmp, "|__func_%s|", name);
982                 }
983                 node = new_op(stmp, OPR_CALL, 1);
984                 node->unode.opr.op[0] = affect_list;
985                 return node;
986             }
987         }
988     }
commit_ext_call(NodeType * node)989     static void commit_ext_call(NodeType *node) {
990         NodeType *alafter = new_affect_list_after(node->unode.opr.op[0]);
991         commit_node(node->unode.opr.op[0],0);
992         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "extcall", INSTR_EXT_CALL, 1, node->line_number);
993         gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_VAR);
994 #ifdef VERBOSE
995         printf("extcall %s\n", node->str);
996 #endif
997         commit_node(alafter,0);
998     }
commit_call(NodeType * node)999     static void commit_call(NodeType *node) {
1000         NodeType *alafter = new_affect_list_after(node->unode.opr.op[0]);
1001         commit_node(node->unode.opr.op[0],0);
1002         currentGoomSL->instr = gsl_instr_init(currentGoomSL, "call", INSTR_CALL, 1, node->line_number);
1003         gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_LABEL);
1004 #ifdef VERBOSE
1005         printf("call %s\n", node->str);
1006 #endif
1007         commit_node(alafter,0);
1008     } /* }}} */
1009 
1010     /** **/
1011 
1012     static NodeType *rootNode = 0; /* TODO: reinitialiser a chaque compilation. */
1013     static NodeType *lastNode = 0;
gsl_append(NodeType * curNode)1014     static NodeType *gsl_append(NodeType *curNode) {
1015         if (curNode == 0) return 0; /* {{{ */
1016         if (lastNode)
1017             lastNode->unode.opr.next = curNode;
1018         lastNode = curNode;
1019         while(lastNode->unode.opr.next) lastNode = lastNode->unode.opr.next;
1020         if (rootNode == 0)
1021             rootNode = curNode;
1022         return curNode;
1023     } /* }}} */
1024 
1025 #if 1
allocateTemp()1026     int allocateTemp() {
1027       return allocateLabel();
1028     }
releaseAllTemps()1029     void releaseAllTemps() {}
releaseTemp(int n)1030     void releaseTemp(int n) {}
1031 #else
1032     static int nbTemp = 0;
1033     static int *tempArray = 0;
1034     static int tempArraySize = 0;
allocateTemp()1035     int allocateTemp() { /* TODO: allocateITemp, allocateFTemp */
1036         int i = 0; /* {{{ */
1037         if (tempArray == 0) {
1038           tempArraySize = 256;
1039           tempArray = (int*)malloc(tempArraySize * sizeof(int));
1040         }
1041         while (1) {
1042           int j;
1043           for (j=0;j<nbTemp;++j) {
1044             if (tempArray[j] == i) break;
1045           }
1046           if (j == nbTemp) {
1047             if (nbTemp == tempArraySize) {
1048               tempArraySize *= 2;
1049               tempArray = (int*)realloc(tempArray,tempArraySize * sizeof(int));
1050             }
1051             tempArray[nbTemp++] = i;
1052             return i;
1053           }
1054           i++;
1055         }
1056     } /* }}} */
releaseAllTemps()1057     void releaseAllTemps() {
1058       nbTemp = 0; /* {{{ */
1059     } /* }}} */
releaseTemp(int n)1060     void releaseTemp(int n) {
1061       int j; /* {{{ */
1062       for (j=0;j<nbTemp;++j) {
1063         if (tempArray[j] == n) {
1064           tempArray[j] = tempArray[--nbTemp];
1065           break;
1066         }
1067       }
1068     } /* }}} */
1069 #endif
1070 
1071     static int lastLabel = 0;
allocateLabel()1072     int allocateLabel() {
1073         return ++lastLabel; /* {{{ */
1074     } /* }}} */
1075 
gsl_commit_compilation()1076     void gsl_commit_compilation()
1077     { /* {{{ */
1078         commit_node(rootNode,0);
1079         rootNode = 0;
1080         lastNode = 0;
1081     } /* }}} */
1082 
precommit_node(NodeType * node)1083     void precommit_node(NodeType *node)
1084     { /* {{{ */
1085         /* do here stuff for expression.. for exemple */
1086         if (node->type == OPR_NODE)
1087             switch(node->unode.opr.type) {
1088                 case OPR_ADD: precommit_add(node); break;
1089                 case OPR_SUB: precommit_sub(node); break;
1090                 case OPR_MUL: precommit_mul(node); break;
1091                 case OPR_DIV: precommit_div(node); break;
1092                 case OPR_CALL_EXPR: precommit_call_expr(node); break;
1093             }
1094     } /* }}} */
1095 
commit_node(NodeType * node,int releaseIfTmp)1096     void commit_node(NodeType *node, int releaseIfTmp)
1097     { /* {{{ */
1098         if (node == 0) return;
1099 
1100         switch(node->type) {
1101             case OPR_NODE:
1102                 switch(node->unode.opr.type) {
1103                     case OPR_SET:           commit_set(node); break;
1104                     case OPR_PLUS_EQ:       commit_plus_eq(node); break;
1105                     case OPR_SUB_EQ:        commit_sub_eq(node); break;
1106                     case OPR_MUL_EQ:        commit_mul_eq(node); break;
1107                     case OPR_DIV_EQ:        commit_div_eq(node); break;
1108                     case OPR_IF:            commit_if(node); break;
1109                     case OPR_WHILE:         commit_while(node); break;
1110                     case OPR_BLOCK:         commit_block(node); break;
1111                     case OPR_FUNC_INTRO:    commit_function_intro(node); break;
1112                     case OPR_FUNC_OUTRO:    commit_function_outro(node); break;
1113                     case OPR_CALL:          commit_call(node); break;
1114                     case OPR_EXT_CALL:      commit_ext_call(node); break;
1115                     case OPR_EQU:           commit_equ(node); break;
1116                     case OPR_LOW:           commit_low(node); break;
1117                     case OPR_NOT:           commit_not(node); break;
1118                     case OPR_AFFECT_LIST:   commit_affect_list(node); break;
1119                     case OPR_FOREACH:       commit_foreach(node); break;
1120                     case OPR_VAR_LIST:      commit_var_list(node); break;
1121 #ifdef VERBOSE
1122                     case EMPTY_NODE:        printf("NOP\n"); break;
1123 #endif
1124                 }
1125 
1126                 commit_node(node->unode.opr.next,0); /* recursive for the moment, maybe better to do something iterative? */
1127                 break;
1128 
1129             case VAR_NODE:         gsl_instr_set_namespace(currentGoomSL->instr, node->vnamespace);
1130                                    gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_VAR); break;
1131             case CONST_INT_NODE:   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_INTEGER); break;
1132             case CONST_FLOAT_NODE: gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_FLOAT); break;
1133             case CONST_PTR_NODE:   gsl_instr_add_param(currentGoomSL->instr, node->str, TYPE_PTR); break;
1134         }
1135         if (releaseIfTmp && is_tmp_expr(node))
1136           releaseTemp(get_tmp_id(node));
1137 
1138         nodeFree(node);
1139     } /* }}} */
1140 
nodeNew(const char * str,int type,int line_number)1141     NodeType *nodeNew(const char *str, int type, int line_number) {
1142         NodeType *node = (NodeType*)malloc(sizeof(NodeType)); /* {{{ */
1143         node->type = type;
1144         node->str  = (char*)malloc(strlen(str)+1);
1145         node->vnamespace = NULL;
1146         node->line_number = line_number;
1147         strcpy(node->str, str);
1148         return node;
1149     } /* }}} */
nodeClone(NodeType * node)1150     static NodeType *nodeClone(NodeType *node) {
1151         NodeType *ret = nodeNew(node->str, node->type, node->line_number); /* {{{ */
1152         ret->vnamespace = node->vnamespace;
1153         ret->unode = node->unode;
1154         return ret;
1155     } /* }}} */
1156 
nodeFreeInternals(NodeType * node)1157     void nodeFreeInternals(NodeType *node) {
1158         free(node->str); /* {{{ */
1159     } /* }}} */
1160 
nodeFree(NodeType * node)1161     void nodeFree(NodeType *node) {
1162         nodeFreeInternals(node); /* {{{ */
1163         free(node);
1164     } /* }}} */
1165 
new_constInt(const char * str,int line_number)1166     NodeType *new_constInt(const char *str, int line_number) {
1167         NodeType *node = nodeNew(str, CONST_INT_NODE, line_number); /* {{{ */
1168         node->unode.constInt.val = atoi(str);
1169         return node;
1170     } /* }}} */
1171 
new_constPtr(const char * str,int line_number)1172     NodeType *new_constPtr(const char *str, int line_number) {
1173         NodeType *node = nodeNew(str, CONST_PTR_NODE, line_number); /* {{{ */
1174         node->unode.constPtr.id = strtol(str,NULL,0);
1175         return node;
1176     } /* }}} */
1177 
new_constFloat(const char * str,int line_number)1178     NodeType *new_constFloat(const char *str, int line_number) {
1179         NodeType *node = nodeNew(str, CONST_FLOAT_NODE, line_number); /* {{{ */
1180         node->unode.constFloat.val = atof(str);
1181         return node;
1182     } /* }}} */
1183 
new_var(const char * str,int line_number)1184     NodeType *new_var(const char *str, int line_number) {
1185         NodeType *node = nodeNew(str, VAR_NODE, line_number); /* {{{ */
1186         node->vnamespace = gsl_find_namespace(str);
1187         if (node->vnamespace == 0) {
1188             g_assert_not_reached ();
1189 #if 0
1190             fprintf(stderr, "ERROR: Line %d, Variable not found: '%s'\n", line_number, str);
1191             exit(1);
1192 #endif
1193         }
1194         return node;
1195     } /* }}} */
1196 
new_nop(const char * str)1197     NodeType *new_nop(const char *str) {
1198         NodeType *node = new_op(str, EMPTY_NODE, 0); /* {{{ */
1199         return node;
1200     } /* }}} */
1201 
new_op(const char * str,int type,int nbOp)1202     NodeType *new_op(const char *str, int type, int nbOp) {
1203         int i; /* {{{ */
1204         NodeType *node = nodeNew(str, OPR_NODE, currentGoomSL->num_lines);
1205         node->unode.opr.next = 0;
1206         node->unode.opr.type = type;
1207         node->unode.opr.nbOp = nbOp;
1208         for (i=0;i<nbOp;++i) node->unode.opr.op[i] = 0;
1209         return node;
1210     } /* }}} */
1211 
1212 
gsl_declare_global_variable(int type,char * name)1213     void gsl_declare_global_variable(int type, char *name) {
1214       switch(type){
1215         case -1: break;
1216         case FLOAT_TK:gsl_float_decl_global(name);break;
1217         case INT_TK:  gsl_int_decl_global(name);break;
1218         case PTR_TK:  gsl_ptr_decl_global(name);break;
1219         default:
1220         {
1221           int id = type - 1000;
1222           gsl_struct_decl_global_from_id(name,id);
1223         }
1224       }
1225     }
1226 
1227 %}
1228 
1229 %union {
1230     int intValue;
1231     float floatValue;
1232     char charValue;
1233     char strValue[2048];
1234     NodeType *nPtr;
1235     GoomHash *namespace;
1236     GSL_Struct *gsl_struct;
1237     GSL_StructField *gsl_struct_field;
1238   };
1239 
1240 %token <strValue>   LTYPE_INTEGER
1241 %token <strValue>   LTYPE_FLOAT
1242 %token <strValue>   LTYPE_VAR
1243 %token <strValue>   LTYPE_PTR
1244 
1245 %token PTR_TK INT_TK FLOAT_TK DECLARE EXTERNAL WHILE DO NOT PLUS_EQ SUB_EQ DIV_EQ MUL_EQ SUP_EQ LOW_EQ NOT_EQ STRUCT FOR IN
1246 
1247 %type <intValue> return_type
1248 %type <nPtr> expression constValue instruction test func_call func_call_expression
1249 %type <nPtr> start_block affectation_list affectation_in_list affectation declaration
1250 %type <nPtr> var_list_content var_list
1251 %type <strValue> task_name ext_task_name
1252 %type <namespace> leave_namespace
1253 %type <gsl_struct> struct_members
1254 %type <gsl_struct_field> struct_member
1255 %left '\n'
1256 %left PLUS_EQ SUB_EQ MUL_EQ DIV_EQ
1257 %left NOT
1258 %left '=' '<' '>'
1259 %left '+' '-'
1260 %left '/' '*'
1261 
1262 %%
1263 
1264 /* -------------- Global architechture of a GSL program ------------*/
1265 
1266 gsl: gsl_code function_outro gsl_def_functions ;
1267 
1268 gsl_code: gsl_code instruction              { gsl_append($2); }
1269    | gsl_code EXTERNAL '<' ext_task_name '>' return_type '\n' leave_namespace             { gsl_declare_global_variable($6,$4); }
1270    | gsl_code EXTERNAL '<' ext_task_name ':' arglist '>' return_type '\n' leave_namespace { gsl_declare_global_variable($8,$4); }
1271    | gsl_code DECLARE '<' task_name '>' return_type  '\n' leave_namespace                 { gsl_declare_global_variable($6,$4); }
1272    | gsl_code DECLARE '<' task_name ':' arglist '>' return_type '\n' leave_namespace      { gsl_declare_global_variable($8,$4); }
1273    | gsl_code struct_declaration
1274    | gsl_code '\n'
1275    |
1276    ;
1277 
1278 /* ------------- Declaration of a structure ------------ */
1279 
1280 struct_declaration: STRUCT  '<' LTYPE_VAR  ':' struct_members '>' '\n' { gsl_add_struct($3, $5); }
1281                   ;
1282 
1283 struct_members: opt_nl struct_member                    { $$ = gsl_new_struct($2);               }
1284               | struct_members ',' opt_nl struct_member { $$ = $1; gsl_add_struct_field($1, $4); }
1285               ;
1286 
1287 struct_member: INT_TK    LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_INT); }
1288              | FLOAT_TK  LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_FLOAT); }
1289              | PTR_TK    LTYPE_VAR { $$ = gsl_new_struct_field($2, INSTR_PTR); }
1290              | LTYPE_VAR LTYPE_VAR { $$ = gsl_new_struct_field_struct($2, $1); }
1291              ;
1292 
1293 /* ------------- Fonction declarations -------------- */
1294 
1295 ext_task_name: LTYPE_VAR { gsl_declare_external_task($1); gsl_enternamespace($1); strcpy($$,$1); }
1296              ;
1297 task_name:     LTYPE_VAR { gsl_declare_task($1); gsl_enternamespace($1); strcpy($$,$1); strcpy($$,$1); }
1298          ;
1299 
1300 return_type:      { $$=-1; }
1301   | ':' INT_TK    { $$=INT_TK; }
1302   | ':' FLOAT_TK  { $$=FLOAT_TK; }
1303   | ':' PTR_TK    { $$=PTR_TK; }
1304   | ':' LTYPE_VAR { $$= 1000 + gsl_get_struct_id($2); }
1305   ;
1306 
1307 arglist: empty_declaration
1308        | empty_declaration ',' arglist
1309        ;
1310 
1311 /* ------------- Fonction definition -------------- */
1312 
1313 gsl_def_functions: gsl_def_functions function
1314                  |
1315                  ;
1316 
1317 function: function_intro gsl_code function_outro { gsl_leavenamespace(); }
1318 
1319 function_intro: '<' task_name '>' return_type '\n'             { gsl_append(new_function_intro($2));
1320                                                                  gsl_declare_global_variable($4,$2); }
1321               | '<' task_name ':' arglist '>' return_type '\n' { gsl_append(new_function_intro($2));
1322                                                                  gsl_declare_global_variable($6,$2); }
1323               ;
1324 function_outro: { gsl_append(new_function_outro()); } ;
1325 
1326 leave_namespace:      { $$ = gsl_leavenamespace();   };
1327 
1328 /* ------------ Variable declaration ---------------- */
1329 
1330 declaration: FLOAT_TK LTYPE_VAR '=' expression { gsl_float_decl_local($2); $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1331            | INT_TK   LTYPE_VAR '=' expression { gsl_int_decl_local($2);   $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1332            | PTR_TK   LTYPE_VAR '=' expression { gsl_ptr_decl_local($2);   $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1333            | LTYPE_VAR LTYPE_VAR '=' expression { gsl_struct_decl_local($1,$2); $$ = new_set(new_var($2,currentGoomSL->num_lines), $4); }
1334            | empty_declaration                { $$ = 0; }
1335            ;
1336 
1337 empty_declaration: FLOAT_TK  LTYPE_VAR { gsl_float_decl_local($2);       }
1338                  | INT_TK    LTYPE_VAR { gsl_int_decl_local($2);         }
1339                  | PTR_TK    LTYPE_VAR { gsl_ptr_decl_local($2);         }
1340                  | LTYPE_VAR LTYPE_VAR { gsl_struct_decl_local($1,$2);   }
1341                  ;
1342 
1343 /* -------------- Instructions and Expressions ------------------ */
1344 
1345 instruction: affectation '\n' { $$ = $1; }
1346            | declaration '\n' { $$ = $1; }
1347            | '(' test ')' '?' opt_nl instruction     { $$ = new_if($2,$6); }
1348            | WHILE test opt_nl DO opt_nl instruction { $$ = new_while($2,$6); }
1349            | '{' '\n' start_block gsl_code '}' '\n'  { lastNode = $3->unode.opr.op[1]; $$=$3; }
1350            | func_call                               { $$ = $1; }
1351            | LTYPE_VAR PLUS_EQ expression { $$ = new_plus_eq(new_var($1,currentGoomSL->num_lines),$3); }
1352            | LTYPE_VAR SUB_EQ expression  { $$ = new_sub_eq(new_var($1,currentGoomSL->num_lines),$3); }
1353            | LTYPE_VAR MUL_EQ expression  { $$ = new_mul_eq(new_var($1,currentGoomSL->num_lines),$3); }
1354            | LTYPE_VAR DIV_EQ expression  { $$ = new_div_eq(new_var($1,currentGoomSL->num_lines),$3); }
1355            | FOR LTYPE_VAR IN var_list DO instruction { $$ = new_static_foreach(new_var($2, currentGoomSL->num_lines), $4, $6); }
1356            ;
1357 
1358 var_list: '(' var_list_content ')'      { $$ = $2; }
1359         ;
1360 var_list_content: LTYPE_VAR             { $$ = new_var_list(new_var($1,currentGoomSL->num_lines), NULL); }
1361            | LTYPE_VAR var_list_content { $$ = new_var_list(new_var($1,currentGoomSL->num_lines), $2);   }
1362            ;
1363 
1364 affectation: LTYPE_VAR '=' expression { $$ = new_set(new_var($1,currentGoomSL->num_lines),$3); } ;
1365 
1366 start_block: { $$ = new_block(lastNode); lastNode = $$->unode.opr.op[0]; }
1367            ;
1368 
1369 expression: LTYPE_VAR   { $$ = new_var($1,currentGoomSL->num_lines); }
1370           | constValue  { $$ = $1; }
1371           | expression '*' expression { $$ = new_mul($1,$3); }
1372           | expression '/' expression { $$ = new_div($1,$3); }
1373           | expression '+' expression { $$ = new_add($1,$3); }
1374           | expression '-' expression { $$ = new_sub($1,$3); }
1375           | '-' expression            { $$ = new_neg($2);    }
1376           | '(' expression ')'        { $$ = $2; }
1377           | func_call_expression      { $$ = $1; }
1378           ;
1379 
1380 test: expression '=' expression { $$ = new_equ($1,$3); }
1381     | expression '<' expression { $$ = new_low($1,$3); }
1382     | expression '>' expression { $$ = new_low($3,$1); }
1383     | expression SUP_EQ expression { $$ = new_not(new_low($1,$3)); }
1384     | expression LOW_EQ expression { $$ = new_not(new_low($3,$1)); }
1385     | expression NOT_EQ expression { $$ = new_not(new_equ($1,$3)); }
1386     | NOT test                  { $$ = new_not($2);    }
1387     ;
1388 
1389 constValue: LTYPE_FLOAT   { $$ = new_constFloat($1,currentGoomSL->num_lines); }
1390           | LTYPE_INTEGER { $$ = new_constInt($1,currentGoomSL->num_lines); }
1391           | LTYPE_PTR     { $$ = new_constPtr($1,currentGoomSL->num_lines); }
1392           ;
1393 
1394 /* ---------------- Function Calls ------------------ */
1395 
1396 func_call:   task_name '\n' leave_namespace                          { $$ = new_call($1,NULL); }
1397            | task_name ':' affectation_list '\n' leave_namespace         { $$ = new_call($1,$3); }
1398            | '[' task_name ']' '\n' leave_namespace                  { $$ = new_call($2,NULL); }
1399            | '[' task_name ':' affectation_list ']' '\n' leave_namespace { $$ = new_call($2,$4); }
1400            ;
1401 
1402 func_call_expression:
1403             '[' task_name leave_namespace ']'                      { $$ = new_call_expr($2,NULL); }
1404           | '[' task_name ':' affectation_list ']' leave_namespace { $$ = new_call_expr($2,$4); }
1405           ;
1406 
1407 affectation_list: affectation_in_list affectation_list     { $$ = new_affec_list($1,$2);   }
1408             | affectation_in_list                          { $$ = new_affec_list($1,NULL); }
1409 
1410 affectation_in_list: LTYPE_VAR '=' leave_namespace expression {
1411                               gsl_reenternamespace($3);
1412                               $$ = new_set(new_var($1,currentGoomSL->num_lines),$4);
1413                             }
1414                    | ':' leave_namespace expression {
1415                               gsl_reenternamespace($2);
1416                               $$ = new_set(new_var("&this", currentGoomSL->num_lines),$3);
1417                             }
1418                    ;
1419 
1420 
1421 /* ------------ Misc ---------- */
1422 
1423 opt_nl: '\n' | ;
1424 
1425 
1426 %%
1427 
1428 
1429 void yyerror(char *str)
1430 { /* {{{ */
1431     g_assert_not_reached ();
1432 #if 0
1433     fprintf(stderr, "ERROR: Line %d, %s\n", currentGoomSL->num_lines, str);
1434     currentGoomSL->compilationOK = 0;
1435     exit(1);
1436 #endif
1437 } /* }}} */
1438 
1439