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