Ejemplo n.º 1
0
expr_type make_expr_from_id(id_type id)
{
   expr_type e = (expr_type) SafeMalloc(sizeof(expr_struct));
   
   /* Id must be a parameter, local, property, constant, or resource */
   lookup_id(id);		
   switch(id->type)
   {
   case I_LOCAL:
   case I_PROPERTY:
   case I_CLASSVAR:
      e->type = E_IDENTIFIER;
      e->value.idval = id;
      break;

   case I_RESOURCE:
   {
      const_type c = (const_type) SafeMalloc(sizeof(const_struct));

      /* Turn resource id reference into the resource # itself */
      c->type = C_RESOURCE;
      c->value.numval = id->idnum; 

      e->type = E_CONSTANT;
      e->value.constval = c;
      return e;
   }

   case I_CONSTANT:
   {
      const_type c = (const_type) SafeMalloc(sizeof(const_struct));
      id_type temp;

      /* Turn constant id reference into the constant itself */
      c->type = C_NUMBER;

      temp = (id_type) list_find_item(st.constants, id, id_compare);
      c->value.numval = temp->source; /* Value is stored in source field */

      e->type = E_CONSTANT;
      e->value.constval = c;
      break;
   }
   case I_UNDEFINED:
   case I_MISSING:
      action_error("Unknown identifier %s", id->name);
      /* Put in something so that compilation can continue */
      e = make_expr_from_constant(make_nil_constant());
      break;

   default:
      action_error("Identifier %s in expression has wrong type", id->name);
      /* Put in something so that compilation can continue */
      e = make_expr_from_constant(make_nil_constant());
      break;
   }
   e->lineno = lineno;
   return e;
}
Ejemplo n.º 2
0
/*
 * codegen_foreach: Generate code for a for loop statement.
 *    numlocals should be # of local variables for message excluding temps.
 *   Returns highest # local variable used in code for statement.
 * Here is how code is generated for a FOR statement:
 *  for i in list ===>       temp = list              1
 *  {body}             top:  if (temp = $) goto end   2
 *                           i = First(temp)          3
 *                           { body }
 *                           temp = Rest(temp)        4
 *                           goto top                 5
 *                     end:
 *
 * Note that continue statements need to jump to statement 4.
 */
int codegen_foreach(foreach_stmt_type s, int numlocals)
{
   opcode_type opcode;
   int our_maxlocal, numtemps;
   stmt_type temp_stmt = (stmt_type) SafeMalloc(sizeof(stmt_struct));
   expr_type temp_expr = (expr_type) SafeMalloc(sizeof(expr_struct));
   expr_type temp2_expr = (expr_type) SafeMalloc(sizeof(expr_struct));
   assign_stmt_type assign_stmt = (assign_stmt_type) SafeMalloc(sizeof(assign_stmt_struct));
   call_stmt_type call_stmt = (call_stmt_type) SafeMalloc(sizeof(call_stmt_struct));
   arg_type arg = (arg_type) SafeMalloc(sizeof(arg_struct));
   id_type temp_id, temp2_id;
   long toppos;
   list_type p;

   /* Make variable "temp" */
   temp_id = make_temp_var(numlocals + 1);
   
   /**** Statement #1:   temp = list ****/
   assign_stmt->lhs = temp_id;
   assign_stmt->rhs = s->condition;
   temp_stmt->type = S_ASSIGN;
   temp_stmt->value.assign_stmt_val = assign_stmt;
   temp_stmt->lineno = 0;
   numtemps = codegen_statement(temp_stmt, numlocals);

   /* Reserve variable "temp" through entire loop by incrementing numlocals */
   our_maxlocal = ++numlocals;
   if (numtemps > our_maxlocal)
      our_maxlocal = numtemps;

   toppos = FileCurPos(outfile);
   codegen_enter_loop();

   /**** Statement #2:   if (temp = $) goto end ****/
   /* First put result of temp = $ into temp2 */
   temp2_id = make_temp_var(numlocals + 1);
   if (numlocals + 1 > our_maxlocal)
      our_maxlocal = numlocals + 1;

   temp2_expr->type = E_IDENTIFIER;
   temp2_expr->value.idval = temp_id;

   temp_expr->type = E_BINARY_OP;
   temp_expr->value.binary_opval.op = EQ_OP;
   temp_expr->value.binary_opval.left_exp = temp2_expr;
   temp_expr->value.binary_opval.right_exp = make_expr_from_constant(make_nil_constant());
   
   assign_stmt->lhs = temp2_id;
   assign_stmt->rhs = temp_expr;
   temp_stmt->type = S_ASSIGN;
   temp_stmt->value.assign_stmt_val = assign_stmt;  /* YECHHH! */
   temp_stmt->lineno = 0;
   codegen_statement(temp_stmt, numlocals);  /* Won't require more temps */
   
   /* Now perform jump if temp = $ is true */
   memset(&opcode, 0, sizeof(opcode));  /* Set opcode to all zeros */
   opcode.command = GOTO;
   opcode.source1 = LOCAL_VAR;
   opcode.dest = GOTO_IF_TRUE;
   OutputOpcode(outfile, opcode);

   /* Make believe goto is a break statement & leave space for backpatching */
   current_loop->break_list = 
      list_add_item(current_loop->break_list, (void *) FileCurPos(outfile));
   OutputInt(outfile, 0);
   OutputInt(outfile, temp2_id->idnum);   /* Jump if temp2 = TRUE */ 

   /**** Statement #3:    i = First(temp) ****/
   temp_expr->type = E_IDENTIFIER;
   temp_expr->value.idval = temp_id;
   arg->type = ARG_EXPR;
   arg->value.expr_val = temp_expr;
   call_stmt->function = FIRST;
   call_stmt->args = list_create(arg);
   codegen_call(call_stmt, s->id, numlocals);  /* Won't require more temps */

   /* Write code for loop body */
   for (p = s->body; p != NULL; p = p->next)
   {
      numtemps = codegen_statement( (stmt_type) p->data, numlocals);
      if (numtemps > our_maxlocal)
	 our_maxlocal = numtemps;
   }

   /* Backpatch continue statements in loop body */
   for (p = current_loop->for_continue_list; p != NULL; p = p->next)
      BackpatchGoto(outfile,  (int) p->data, FileCurPos(outfile));

   /**** Statement #4:    temp = Rest(temp) ****/
   /* Can reuse most of statement #3 above */
   call_stmt->function = REST;
   codegen_call(call_stmt, temp_id, numlocals);  /* Won't require more temps */

   /**** Statement #5:    goto top ****/
   opcode.source1 = 0;
   opcode.source2 = GOTO_UNCONDITIONAL;
   opcode.dest = 0;
   OutputOpcode(outfile, opcode);
   OutputGotoOffset(outfile, FileCurPos(outfile), toppos);

   codegen_exit_loop();  /* Takes care of break statements */

   return our_maxlocal;
}