Example #1
0
static void process_dowhile(ast_node node){
  // indicate that its a dowhile loop
  quad dowhile_quad = create_quad(dowhileloop); 
  add_quad(node, dowhile_quad); 

  // add the compound (body of dowhile loop)
  add_quad_list(node, node->left_child->code); 
  int beginning = node->code->first->next->num;
  
  quad end_loop = create_quad(end_dowhileloop); 
  add_quad(node, end_loop); 

  // add the code for the condition
  add_quad_list(node, node->left_child->right_sibling->code); 

  // test the condition (move on if it fails) and add its quad to code
  quad if_false = create_quad(ifFalse); 
  char * loc = strdup(node->left_child->right_sibling->location); 
  if_false->address1 = loc; 
  add_quad(node, if_false); 

  // unconditional jump to top of compound
  quad jump_to = create_quad(jumpTo); 
  char * buffer = malloc(10); 
  sprintf(buffer, "%d", beginning); 
  jump_to->address1 = buffer; 
  add_quad(node, jump_to); 
  
  // backpatch the if_false quad
  buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  if_false->address2 = buffer; 
}
Example #2
0
/* builds the code for a compound: 
 * enter scope
 * code of its children
 * leave scope
 */ 
static void process_cmpd(ast_node node){
  quad enter_scope = create_quad(enter); 
  quad exit_scope = create_quad(leave); 

  add_quad(node, enter_scope); 
  build_code(node, exit_scope, NULL, NULL, NULL); 
}
Example #3
0
static void process_if(ast_node node){
  quad ifFalse_quad = create_quad(ifFalse); 
  char * loc = strdup(node->left_child->location); 
  ifFalse_quad->address1 = loc; 

  // indicate that this is an if-statement
  quad if_false = create_quad(ifstmt); 
  add_quad(node, if_false); 

  // add the code for the condition
  add_quad_list(node, node->left_child->code); 

  // add the ifFalse quad
  add_quad(node, ifFalse_quad); 

  // add the compound 
  if (node->left_child->right_sibling != NULL){
    add_quad_list(node, node->left_child->right_sibling->code); 
  }

  // indicate that the if ends here
  quad if_end = create_quad(end_ifstmt); 
  add_quad(node, if_end); 

  // Backpatch if_quad by filling in the number of the quad it should go to
  // if it is false. 
  char * buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  ifFalse_quad->address2 = buffer; 
}
Example #4
0
// process float math
static void process_float_math(ast_node node){
  quad new_quad = NULL; 

  switch (node->node_type){
  case OP_PLUS:
    new_quad = create_quad(f_add);
    break;
  case OP_MINUS: 
    new_quad = create_quad(f_sub); 
    break; 
  case OP_TIMES: 
    new_quad = create_quad(f_mult); 
    break;
  case OP_DIVIDE:
    new_quad = create_quad(f_divide); 
    break;
  case OP_EQUALS: 
    new_quad = create_quad(f_eq); 
    break;
  case OP_NEQUALS: 
    new_quad = create_quad(f_neq); 
    break;
  case OP_LT: 
    new_quad = create_quad(f_lt); 
    break;
  case OP_LEQ: 
    new_quad = create_quad(f_leq); 
    break;
  case OP_GT: 
    new_quad = create_quad(f_gt); 
    break;
  case OP_GEQ: 
    new_quad = create_quad(f_geq); 
    break;
  }

  // location being assigned to is new!
  char *target = new_address(); 
  char * left = process_left(node); 
  char *right = process_right(node); 

  if (new_quad != NULL && target != NULL && left != NULL && right != NULL){
    build_code(node, new_quad, target, left, right);
  }
  else {
    destroy_quad(new_quad);
    error("process_float_math");
  }
}
Example #5
0
void generate_traverse(ast_node node){
  generate_traverse_recurse(node); 
  
  // add the end quad
  quad end_quad = create_quad(end);
  add_quad(node, end_quad);
}
Example #6
0
/* processes a call 
 * 1. push the params onto the stack
 * 2. goto_sub the function (location will be stored in symbol table maybe?) 
 * 3. get the return value (will be in a register) 
 */ 
static void process_call(ast_node node){
  // 1. push the params onto the stack in reverse order
  ast_node args = node->left_child->right_sibling; 


  quad goto_sub_quad = create_quad(goto_sub);
  goto_sub_quad->address1 = node->left_child->value.string;
  add_quad(node, goto_sub_quad);
   

  ast_node curr; 
  for (curr = args->left_child; curr != NULL; curr = curr->right_sibling){
    quad push_quad = create_quad(push); 
    push_quad->address1 = curr->location;
    
    // it's a literal!
    if (push_quad->address1 == NULL){
      char buffer[MAX_LEN];
      char *val; 
      if (curr->type == Int){
	snprintf(buffer, MAX_LEN, "%d", curr->value.int_value);
        val = strdup(buffer);
	push_quad->address1 = val;
      }
      else{
	snprintf(buffer, MAX_LEN, "%f", curr->value.double_value); 
	val = strdup(buffer); 
	push_quad->address1 = val; 
      }
    }
 
    add_quad_to_beginning(node, push_quad); 
    add_quad_list_to_beginning(node, curr->code); 
    //add_quad_list(node, curr->code); 
  }

  // 2. jump to the function's subroutine
  /* quad goto_sub_quad = create_quad(goto_sub); 
  goto_sub_quad->address1 = node->left_child->value.string; 
  add_quad(node, goto_sub_quad); 
  */
  // 3. get the return value 
  quad get_return = create_quad(get_rtrn); 
  get_return->address1 = new_address(); 
  node->location = get_return->address1; 
  add_quad(node, get_return); 
} 
Example #7
0
// (print, location or string lit, NULL, NULL)
static void process_print(ast_node node){
  quad print_quad = create_quad(print); 
  char *left = process_left(node); 
  print_quad->address1 = left; 

  add_quad_list(node, node->left_child->code); 
  add_quad(node, print_quad); 
} 
Example #8
0
// (read, location, NULL, NULL)
static void process_read(ast_node node){
  quad read_quad = create_quad(read); 
  char * left = process_left(node);
  printf("left: %s\n", left); 
  read_quad->address1 = left; 

  add_quad(node, read_quad); 

  // if it's an array, assign temp to the array
  if (node->left_child->left_child != NULL){
    quad array_quad = create_quad(array_assn); 
    array_quad->address1 = process_left(node->left_child); 
    array_quad->address2 = process_right(node->left_child); 
    array_quad->address3 = left; 
    add_quad(node, array_quad); 
  } 
}
Example #9
0
static void process_or(ast_node node){
  quad or_quad = create_quad(or);
  add_quad(node, or_quad); 

  // the value of the OR will be stored here: 
  char * or_address = new_address(); 
  node->location = or_address; 

  char * left = process_left(node); 
  char * right = process_right(node); 

  // add the code for the left child
  add_quad_list(node, node->left_child->code); 

  // if the left child is false, go to test for right child
  quad if_false = create_quad(ifFalse); 
  char * loc = strdup(left); 
  if_false->address1 = loc; 
  add_quad(node, if_false); 

  // unconditional jump (short circuiting)
  quad short_circuit = create_quad(jumpTo); 
  add_quad(node, short_circuit); 

  // add the code for the right child - if_false jumps here!
  add_quad_list(node, node->left_child->right_sibling->code);
  int if_false_jumps_here = node->left_child->right_sibling->code->first->num; 
  char * buffer = malloc(10); 
  sprintf(buffer, "%d", if_false_jumps_here); 
  if_false->address2 = buffer; 

  // OR gets the value of the right child
  quad assign_from_right = create_quad(assn); 
  assign_from_right->address1 = or_address; 
  assign_from_right->address2 = right; 
  add_quad(node, assign_from_right); 

  // unconditional jump (done) 
  quad done_jump = create_quad(jumpTo); 
  add_quad(node, done_jump); 

  // OR gets the value of the left child - short circuit jumps here!
  quad assign_from_left = create_quad(assn); 
  assign_from_left->address1 = or_address; 
  assign_from_left->address2 = left; 
  add_quad(node, assign_from_left); 
  
  // backpatch short_circuit
  buffer = malloc(10); 
  sprintf(buffer, "%d", assign_from_left->num); 
  short_circuit->address1 = buffer; 

  // backpatch done_jump (goes to next generated quad)
  buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  done_jump->address1 = buffer; 

  quad end_or_quad = create_quad(end_or); 
  add_quad(node, end_or_quad); 
}
Example #10
0
static void process_while(ast_node node){
  quad if_false = create_quad(ifFalse); 
  char * loc = strdup(node->left_child->location); 
  if_false->address1 = loc; 

  // Get the num of the quad that starts the code that computes
  // the condition. 
  int start_of_condition = node->left_child->code->first->num; 
  
  // indicate that it's a while loop
  quad while_quad = create_quad(whileloop); 
  add_quad(node, while_quad); 

  // add the code for the condition
  add_quad_list(node, node->left_child->code); 
  
  // add the ifFalse quad
  add_quad(node, if_false); 

  // add the code for the body
  if (node->left_child->right_sibling != NULL){
    add_quad_list(node, node->left_child->right_sibling->code); 
  }

  // mark the end of the body
  //  quad end_while = create_quad(end_whileloop); 
  //add_quad(node, end_while); 

  // create the jumpTo quad that takes you back to the condition
  // and add it to the code
  quad back_to_condition = create_quad(jumpTo); 
  char *buffer = malloc(10); 
  sprintf(buffer, "%d", start_of_condition); 
  back_to_condition->address1 = buffer; 
  add_quad(node, back_to_condition); 

  // mark the end of the body        
  quad end_while = create_quad(end_whileloop);
  add_quad(node, end_while);

  // backpatch the ifFalse quad
  buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  if_false->address2 = buffer; 
}
Example #11
0
// Format: (array_lkup, target, name, index)
static void process_array(ast_node node){
  quad array_quad = create_quad(array_lkup);

  // where you'll put value of array once you look it up                                                                         
  array_quad->address1 = new_address();

  array_quad->address2 = process_left(node);
  array_quad->address3 = process_right(node);
  add_quad(node, array_quad);
  node->location = array_quad->address1;
}
Example #12
0
/* declare a variable
 * This only happens if it has a left child (otherwise it's saying the type
 * of a function.
 * Format: (vardec, type, name, NULL)
 */  
static void process_vardec(ast_node node){
  int assign; 
  ast_node curr = node->left_child; 
  char * address1; 
  char * address2; 

  // get the data type                                                                                 
  if (node->node_type == INT_TYPE)
    address1 = "int";
  else if (node->node_type == DOUBLE_TYPE)
    address1 = "double";

  while (curr != NULL){
    quad vardec_quad = create_quad(vardec);
    vardec_quad->address1 = address1; 

    if (curr->node_type == OP_ASSIGN){
      vardec_quad->address2 = curr->left_child->value.string; 
      assign = 1; 
    }
    
    // process array declaration                                    
    else if (curr->node_type == ARRAY){
      int size; 
      // get the size of the array
      if (curr->left_child->right_sibling == NULL)
	size = 1; 
      else{
	size = curr->left_child->right_sibling->value.int_value; 
      }
      char buffer[MAX_LEN];
      snprintf(buffer, MAX_LEN, "%d", size);
      vardec_quad->address3 = strdup(buffer);

      // get the name of the array     
      vardec_quad->address2 = process_left(curr);
    
    }
    else {
      vardec_quad->address2 = curr->value.string; 
    }

    if (vardec_quad->address2 != NULL)
      node->location = strdup(vardec_quad->address2);
 
    add_quad(node, vardec_quad);
    if (assign){
      add_quad_list(node, curr->code); 
    }
    curr = curr->right_sibling; 
  }
}
Example #13
0
// (rtrn, location, NULL, NULL); 
static void process_return(ast_node node){
  quad return_quad = create_quad(rtrn); 
  
  if (node->left_child != NULL){
    char * left = process_left(node); 
    return_quad->address1 = left; 
    node->location = left; 

    add_quad_list(node, node->left_child->code);
  }
 
  add_quad(node, return_quad); 
}
Example #14
0
static void process_for(ast_node node){
  // add start and condition code
  add_quad_list(node, node->left_child->code); 

  // indicate that it's a for-loop 
  // while loops are the same thing, so pretend it's one! shhhh ... 
  quad for_quad = create_quad(whileloop);
  add_quad(node, for_quad);

  add_quad_list(node, node->left_child->right_sibling->code); 
  int cond_start = node->left_child->right_sibling->code->first->num; 

  // if the condition is false, exit the loop 
  char * condition_location = node->left_child->right_sibling->location; 
  quad if_false = create_quad(ifFalse); 
  if_false->address1 = condition_location; 
  add_quad(node, if_false); 

  // add the code for the compound
  add_quad_list(node, node->left_child->right_sibling->right_sibling->right_sibling->code); 
  
  // add update code
  add_quad_list(node, node->left_child->right_sibling->right_sibling->code); 

  // unconditional jump back to the condition
  quad jump = create_quad(jumpTo); 
  char * buffer = malloc(10); 
  sprintf(buffer, "%d", cond_start); 
  jump->address1 = buffer; 
  add_quad(node, jump); 

  quad end_for = create_quad(end_whileloop);
  add_quad(node, end_for);

  // backpatch the if_false quad
  buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  if_false->address2 = buffer; 
}
Example #15
0
/* builds the code of a function; 
 * 1. Function declaration: (func_dec, type, name, NULL)
 * 2. Code of its children
 */ 
static void process_function(ast_node node){
  // create a quad with address1 = type and address2 = name
  quad func_dec_node = create_quad(func_dec);
  char * type; 

  if (node->left_child->node_type == INT_TYPE){
    type = "int"; 
  }
  else if (node->left_child->node_type == DOUBLE_TYPE){
    type = "double"; 
  }
  else if (node->left_child->node_type == VOID_TYPE){
    type = "void"; 
  }
  
  char * name = node->left_child->right_sibling->value.string; 
  func_dec_node->address1 = type; 
  func_dec_node->address2 = name;
  add_quad(node, func_dec_node); 

  // enter scope - hackity hack hack hack
  quad enter_quad = create_quad(enter);
  add_quad(node, enter_quad); 

  build_code(node, NULL, NULL, NULL, NULL); 

  // exit hacky scope
  quad leave_quad = create_quad(leave); 
  add_quad(node, leave_quad); 
 
  // JUST ADDED
  // if it's main, add halt   
  if (strcmp(name, "main") == 0){
    quad halt_quad = create_quad(halt);
    add_quad(node, halt_quad);
  }


  // default return
  quad return_quad = create_quad(rtrn); 
  add_quad(node, return_quad); 
  
  // leave subroutine (return addr will be in a register)
  quad exit_sub_quad = create_quad(exit_sub);
  add_quad(node, exit_sub_quad); 

  // if it's main, add halt
  if (strcmp(name, "main") == 0){
    quad halt_quad = create_quad(halt); 
    add_quad(node, halt_quad); 
  }

}
Example #16
0
// Format: (assn, target location, value location, null)
static void process_assign(ast_node node){
  char * target = NULL; 
  // deal with arrays a little differently
  if (node->left_child->node_type == ARRAY){
    quad array_quad = create_quad(array_assn); 
    ast_node array = node->left_child; 

    // (array_assn, array, index, value)
    array_quad->address1 = process_left(array); 
    array_quad->address2 = process_right(array); ; 
    array_quad->address3 = process_right(node); 
    
    // add code to calculuate right hand side, then to find array location
    add_quad_list(node, node->left_child->right_sibling->code); 
    add_quad(node, array_quad); 
  }
  else {
    quad new_quad = create_quad(assn);
    // get location to being assigned
    if (node->left_child != NULL && node->left_child->node_type == IDENT){
      target = strdup(node->left_child->value.string); // DO I NEED TO DUPLICATE THE STRING? 
    }
    else if (node->left_child != NULL){
      target = strdup(node->left_child->location);
    }

    // get location of value               
    char * value = process_right(node);

    if (target != NULL && value != NULL){
      build_code(node, new_quad, target, value, NULL);
    }
    else{
      destroy_quad(new_quad);
      error("process_assign");
    }
  }
}
Example #17
0
// handle increments and decrements
static void process_inc(ast_node node, char * inc){
  quad new_quad = create_quad(add); 
  char * target = process_left(node); 
  char *value = target; 
  char *amount = strdup(inc); 

  if (value != NULL){
    build_code(node, new_quad, target, value, amount); 
  }
  else{
    destroy_quad(new_quad); 
    error("process inc"); 
  }
}
Example #18
0
static void process_negate(ast_node node){
  quad new_quad = create_quad(mult); 
  char * target = new_address(); 

  char * value = process_left(node);
  char * multby = strdup("-1"); 
  
  if (value != NULL){
    build_code(node, new_quad, target, value, multby); 
  }
  else{
    destroy_quad(new_quad); 
    error("process_negate"); 
  }
}
Example #19
0
int main(){
  oprand op1, op2, op3;
  quad qd;

  op1 = create_oprand(OP_TYPE_INT, 1);  
  op2 = create_oprand(OP_TYPE_NA, 1);  
  op3 = create_oprand(OP_TYPE_DOUBLE, 1.5);

  qd = create_quad(FUNC_BODY, op1, op2, op3);
  insert_quad(qd);
  insert_quad(qd);
  insert_quad(qd);

  print_code();
  return 0;
}
Example #20
0
static void process_ifelse(ast_node node){
  quad if_quad = create_quad(ifFalse);
  char * loc = strdup(node->left_child->location);
  if_quad->address1 = loc;

  // indicate that it's an ifelse
  quad ifelse_quad = create_quad(ifelse); 
  add_quad(node, ifelse_quad); 

  // add the code for the condition     
  add_quad_list(node, node->left_child->code);

  // add the ifFalse quad
  add_quad(node, if_quad);

  // add the compound 
  if (node->left_child->right_sibling != NULL){
    add_quad_list(node, node->left_child->right_sibling->code);
  }

  // if part is over
  quad end_if_quad = create_quad(end_ifstmt); 
  add_quad(node, end_if_quad); 

  // do the goto
  quad jump_quad = create_quad(jumpTo); 
  add_quad(node, jump_quad); 
  
  // if part is starting
  quad else_quad = create_quad(elsestmt); 
  add_quad(node, else_quad); 

  // add the else compound
  if (node->left_child->right_sibling->right_sibling != NULL){
    add_quad_list(node, node->left_child->right_sibling->right_sibling->code); 
  }

  // else part is over
  quad end_else = create_quad(end_elsestmt); 
  add_quad(node, end_else); 
  
  // Backpatch if_false
  int ifFalse_backpatch = jump_quad->next->num; 
  char * buffer = malloc(10); 
  sprintf(buffer, "%d", ifFalse_backpatch); 
  if_quad->address2 = buffer; 

  // Backpatch the jump_quad
  buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  jump_quad->address1 = buffer; 
}
Example #21
0
static void process_and(ast_node node){
  quad and_quad = create_quad(and); 
  add_quad(node, and_quad); 

  // address the value of the and will be stored here: 
  char * and_address = new_address(); 
  node->location = and_address; 

  char * left = process_left(node); 
  char * right = process_right(node); 

  // do the code for the left child
  add_quad_list(node, node->left_child->code); 
  
  // if the left child is false, short circuit
  quad if_false = create_quad(ifFalse); 
  char * loc = strdup(left); 
  if_false->address1 = loc; 
  add_quad(node, if_false); 

  // do the code for the right child
  add_quad_list(node, node->left_child->right_sibling->code); 
  quad assign = create_quad(assn); 
  assign->address1 = and_address; 
  assign->address2 = right;
  add_quad(node, assign); 

  // unconditional jump to code after the and
  quad jump_to = create_quad(jumpTo); 
  add_quad(node, jump_to); 

  // first was false, so the value is false (short circuited)
  quad assign2 = create_quad(assn); 
  assign2->address1 = and_address; 
  assign2->address2 = left;
  add_quad(node, assign2); 
  int short_circuit = assign2->num; 

  // backpatch the unconditional jump:
  char * buffer = malloc(10); 
  sprintf(buffer, "%d", num_quads); 
  jump_to->address1 = buffer; 

  // backpatch the short circuit
  buffer = malloc(10); 
  sprintf(buffer, "%d", short_circuit); 
  if_false->address2 = buffer; 

  quad end_and_quad = create_quad(end_and); 
  add_quad(node, end_and_quad); 
}
Example #22
0
static int build_quads(hpquads_t* me, int Nhptotry, il* hptotry, int R) {
	int nthispass = 0;
	int lastgrass = 0;
	int i;

	for (i=0; i<Nhptotry; i++) {
		anbool ok;
		int hp;
		if ((i * 80 / Nhptotry) != lastgrass) {
			printf(".");
			fflush(stdout);
			lastgrass = i * 80 / Nhptotry;
		}
		if (hptotry)
			hp = il_get(hptotry, i);
		else
			hp = i;
		me->hp = hp;
		me->quad_created = FALSE;
		ok = find_stars(me, me->radius2, R);
		if (ok)
			create_quad(me, TRUE);

		if (me->quad_created)
			nthispass++;
		else {
			if (R && me->Nstars && me->retryhps)
				// there were some stars, and we're counting how many times stars are used.
				//il_insert_unique_ascending(me->retryhps, hp);
				// we don't mind hps showing up multiple times because we want to make up for the lost
				// passes during loosening...
				il_append(me->retryhps, hp);
			// FIXME -- could also track which hps are worth visiting in a future pass
		}
	}
	printf("\n");
	return nthispass;
}
Example #23
0
/* Handles mathy operations (all the same pattern)
 * Format: (operation, target location, left argument, right argument)
 */ 
static void process_math(ast_node node){
  // if its a float - process float math
  if (node->type == Double){
    process_float_math(node); 
    return;
  }

  quad new_quad = NULL;   

  if (node->node_type == OP_PLUS){
    new_quad = create_quad(add);       
  }                         
  else if (node->node_type == OP_MINUS){  
    new_quad = create_quad(sub);     
  }                     
  else if (node->node_type == OP_TIMES){  
    new_quad = create_quad(mult);      
  }                       
  else if (node->node_type == OP_DIVIDE){
    new_quad = create_quad(divide);  
  }         
  else if (node->node_type == OP_MOD){
    new_quad = create_quad(mod); 
  }
  else if (node->node_type == OP_EQUALS){
    new_quad = create_quad(eq); 
  }
  else if (node->node_type == OP_NEQUALS){
    new_quad = create_quad(neq); 
  }
  else if (node->node_type == OP_LT){
    new_quad = create_quad(lt); 
  }
  else if (node->node_type == OP_LEQ){
    new_quad = create_quad(leq); 
  }
  else if (node->node_type == OP_GT){
    new_quad = create_quad(gt); 
  }
  else if (node->node_type == OP_GEQ){
    new_quad = create_quad(geq); 
  }
  else if (node->node_type == OP_NOT){
    new_quad = create_quad(not); 
  }
   
  // location being assigned to is new!   
  char * target = new_address();
       
  // get left argument     
  char * left = process_left(node);  
  
  // get right argument (if it's not OP_NOT)
  char * right = NULL; 
  if (node->node_type != OP_NOT)
    right = process_right(node);
  
  if (new_quad != NULL && target != NULL && left != NULL){                
    build_code(node, new_quad, target, left, right);  
  }            
  else {  
    destroy_quad(new_quad);        
    error("process math");                 
  }          
}
Example #24
0
bool H2DReader::load_stream(std::istream &is, Mesh *mesh,
        const char *filename)
{
  int i, j, k, n;
  Node* en;
  bool debug = false;

  mesh->free();

  std::string mesh_str = read_file(is);

  Python p;
  initpython_reader();
  p.exec("from python_reader import read_hermes_format_str");
  p.push_str("s", mesh_str);
  p.exec("vertices, elements, boundaries, curves, refinements"
          " = read_hermes_format_str(s)");

  //// vertices ////////////////////////////////////////////////////////////////

  p.exec("n = len(vertices)");
  n = p.pull_int("n");
  if (n < 0) error("File %s: 'vertices' must be a list.", filename);
  if (n < 2) error("File %s: invalid number of vertices.", filename);

  // create a hash table large enough
  int size = HashTable::H2D_DEFAULT_HASH_SIZE;
  while (size < 8*n) size *= 2;
  mesh->init(size);

  // create top-level vertex nodes
  for (i = 0; i < n; i++)
  {
    Node* node = mesh->nodes.add();
    assert(node->id == i);
    node->ref = TOP_LEVEL_REF;
    node->type = HERMES_TYPE_VERTEX;
    node->bnd = 0;
    node->p1 = node->p2 = -1;
    node->next_hash = NULL;
    p.push_int("i", i);
    p.exec("x, y = vertices[i]");
    node->x = p.pull_double("x");
    node->y = p.pull_double("y");
  }
  mesh->ntopvert = n;

  //// elements ////////////////////////////////////////////////////////////////

  p.exec("n = len(elements)");
  n = p.pull_int("n");
  if (n < 0) error("File %s: 'elements' must be a list.", filename);
  if (n < 1) error("File %s: no elements defined.", filename);

  // create elements
  mesh->nactive = 0;
  for (i = 0; i < n; i++)
  {
    // read and check vertex indices
    p.push_int("i", i);
    p.exec("nv = len(elements[i])");
    int nv = p.pull_int("nv");
    int idx[5];
    std::string el_marker;
    if (!nv) { 
      mesh->elements.skip_slot(); 
      continue; 
    }
    if (nv < 4 || nv > 5)
      error("File %s: element #%d: wrong number of vertex indices.", filename, i);
    if (nv == 4) {
      p.exec("n1, n2, n3, marker = elements[i]");
      idx[0] = p.pull_int("n1");
      idx[1] = p.pull_int("n2");
      idx[2] = p.pull_int("n3");
      p.exec("marker_str = 1 if isinstance(marker, str) else 0");
      if (p.pull_int("marker_str"))
        el_marker = p.pull_str("marker");
      else {
        std::ostringstream string_stream;
        string_stream << p.pull_int("marker");
        el_marker = string_stream.str();
      }
    } 
    else {
      p.exec("n1, n2, n3, n4, marker = elements[i]");
      idx[0] = p.pull_int("n1");
      idx[1] = p.pull_int("n2");
      idx[2] = p.pull_int("n3");
      idx[3] = p.pull_int("n4");
      p.exec("marker_str = 1 if isinstance(marker, str) else 0");
      if (p.pull_int("marker_str"))
        el_marker = p.pull_str("marker");
      else {
        std::ostringstream string_stream;
        string_stream << p.pull_int("marker");
        el_marker = string_stream.str();
      }
    }
    for (j = 0; j < nv-1; j++)
      if (idx[j] < 0 || idx[j] >= mesh->ntopvert)
        error("File %s: error creating element #%d: vertex #%d does not exist.", filename, i, idx[j]);

    Node *v0 = &mesh->nodes[idx[0]], *v1 = &mesh->nodes[idx[1]], *v2 = &mesh->nodes[idx[2]];
    
    int marker;

    // This functions check if the user-supplied marker on this element has been
    // already used, and if not, inserts it in the appropriate structure.
    mesh->element_markers_conversion.insert_marker(mesh->element_markers_conversion.min_marker_unused, el_marker);
    marker = mesh->element_markers_conversion.get_internal_marker(el_marker);

    if(nv == 4) {
        check_triangle(i, v0, v1, v2);
        create_triangle(mesh, marker, v0, v1, v2, NULL);
      }
      else {
        Node *v3 = &mesh->nodes[idx[3]];
        check_quad(i, v0, v1, v2, v3);
        create_quad(mesh, marker, v0, v1, v2, v3, NULL);
      }

    mesh->nactive++;
  }
  mesh->nbase = n;

  //// boundaries //////////////////////////////////////////////////////////////
  p.exec("have_boundaries = 1 if boundaries else 0");
  if (p.pull_int("have_boundaries"))
  {
    p.exec("n = len(boundaries)");
    n = p.pull_int("n");

    // read boundary data
    for (i = 0; i < n; i++)
    {
      int v1, v2, marker;
      p.push_int("i", i);
      p.exec("v1, v2, marker = boundaries[i]");
      v1 = p.pull_int("v1");
      v2 = p.pull_int("v2");

      en = mesh->peek_edge_node(v1, v2);
      if (en == NULL)
        error("File %s: boundary data #%d: edge %d-%d does not exist", filename, i, v1, v2);

      std::string bnd_marker;
      p.exec("marker_str = 1 if isinstance(marker, str) else 0");

      if (p.pull_int("marker_str"))
        bnd_marker = p.pull_str("marker");
      else {
        std::ostringstream string_stream;
        string_stream << p.pull_int("marker");
        bnd_marker = string_stream.str();
      }

      // This functions check if the user-supplied marker on this element has been
      // already used, and if not, inserts it in the appropriate structure.
      mesh->boundary_markers_conversion.insert_marker(mesh->boundary_markers_conversion.min_marker_unused, bnd_marker);
      marker = mesh->boundary_markers_conversion.get_internal_marker(bnd_marker);
      
      en->marker = marker;

      // This is extremely important, as in DG, it is assumed that negative boundary markers are reserved
      // for the inner edges.
      if (marker > 0)
      {
        mesh->nodes[v1].bnd = 1;
        mesh->nodes[v2].bnd = 1;
        en->bnd = 1;
      }
    }
  }

#ifdef HERMES_COMMON_CHECK_BOUNDARY_CONDITIONS
  // check that all boundary edges have a marker assigned
  for_all_edge_nodes(en, mesh)
    if (en->ref < 2 && en->marker == 0) {
      warn("Boundary edge node does not have a boundary marker");
    }
#endif

  //// curves //////////////////////////////////////////////////////////////////
  p.exec("have_curves = 1 if curves else 0");
  if (p.pull_int("have_curves"))
  {
    p.exec("n = len(curves)");
    n = p.pull_int("n");
    if (n < 0) error("File %s: 'curves' must be a list.", filename);

    // load curved edges
    for (i = 0; i < n; i++)
    {
      // load the control points, knot vector, etc.
      Node* en;
      int p1, p2;
      p.push_int("i", i);
      p.exec("curve = curves[i]");
      Nurbs* nurbs = load_nurbs(mesh, p, i, &en, p1, p2);

      // assign the nurbs to the elements sharing the edge node
      for (k = 0; k < 2; k++)
      {
        Element* e = en->elem[k];
        if (e == NULL) continue;

        if (e->cm == NULL)
        {
          e->cm = new CurvMap;
          memset(e->cm, 0, sizeof(CurvMap));
          e->cm->toplevel = 1;
          e->cm->order = 4;
        }

        int idx = -1;
        for (unsigned j = 0; j < e->nvert; j++)
          if (e->en[j] == en) { idx = j; break; }
        assert(idx >= 0);

        if (e->vn[idx]->id == p1)
        {
          e->cm->nurbs[idx] = nurbs;
          nurbs->ref++;
        }
        else
        {
          Nurbs* nurbs_rev = mesh->reverse_nurbs(nurbs);
          e->cm->nurbs[idx] = nurbs_rev;
          nurbs_rev->ref++;
        }
      }
      if (!nurbs->ref) delete nurbs;
    }
  }

  // update refmap coeffs of curvilinear elements
  Element* e;
  for_all_elements(e, mesh)
    if (e->cm != NULL)
      e->cm->update_refmap_coeffs(e);

  //// refinements /////////////////////////////////////////////////////////////
  p.exec("have_refinements = 1 if refinements else 0");
  if (p.pull_int("have_refinements"))
  {
    p.exec("n = len(refinements)");
    n = p.pull_int("n");
    if (n < 0) error("File %s: 'refinements' must be a list.", filename);

    // perform initial refinements
    for (i = 0; i < n; i++)
    {
      int id, ref;
      p.push_int("i", i);
      p.exec("id, ref = refinements[i]");
      id = p.pull_int("id");
      ref = p.pull_int("ref");
      mesh->refine_element_id(id, ref);
    }
  }
  mesh->ninitial = mesh->elements.get_num_items();

  mesh->seq = g_mesh_seq++;


  return true;
}