Beispiel #1
0
code_t* var_block(code_t*body, dict_t*vars) 
{
    code_t*c = 0;
    code_t*k = 0;
    int t;
    DICT_ITERATE_DATA(vars, variable_t*, v) {
        if(v->type && v->init) {
            c = defaultvalue(c, v->type);
            c = abc_setlocal(c, v->index);
        }
        if(v->type && v->kill) {
            k = abc_kill(k, v->index); 
        }
    }

    if(k) {
        code_t*x = body;
        while(x) {
            if(x->opcode== OPCODE___BREAK__ ||
               x->opcode== OPCODE___CONTINUE__) {
               /* link kill code before break/continue */
                code_t*e = code_dup(k);
                code_t*s = code_start(e);
                s->prev = x->prev;
                if(x->prev) {
                    x->prev->next = s;
                }
                e->next = x;
                x->prev = e;
            }
            x = x->prev;
        }
    }
    
    c = code_append(c, body);
    c = code_append(c, k);
    return c;
}
Beispiel #2
0
code_t* cut_last_push(code_t*c)
{
    assert(!c->next);
    while(c) {
        if(!c) break;
        opcode_t*op = opcode_get(c->opcode);
        /* cut conversion type operations */
        if(op->stack_minus == -1 && op->stack_plus == 1 && !(op->flags)) {
            c = code_cutlast(c);
            continue;
        }
        /* cut any type of push */
        else if(op->stack_minus == 0 && op->stack_plus == 1 && !(op->flags)) {
            return code_cutlast(c);
        }
        /* cut register lookups */
        else if(c->opcode == OPCODE_GETLOCAL ||
           c->opcode == OPCODE_GETLOCAL_0 ||
           c->opcode == OPCODE_GETLOCAL_1 ||
           c->opcode == OPCODE_GETLOCAL_2 ||
           c->opcode == OPCODE_GETLOCAL_3) {
            return code_cutlast(c);
        }
        /* discard function call values */
        else if(c->opcode == OPCODE_CALLPROPERTY) {
            c->opcode = OPCODE_CALLPROPVOID;
            return c;
        } else if(c->opcode == OPCODE_CALLSUPER) {
            c->opcode = OPCODE_CALLSUPERVOID;
            return c;
        } else if((c->opcode == OPCODE_NEWOBJECT ||
                   c->opcode == OPCODE_NEWARRAY) &&
                   !c->data[0]) {
            // we can discard these if they're not eating up stack parameters
            return code_cutlast(c);
        } else if(op->stack_minus ==0 && op->stack_plus == 0 && 
                !(op->flags&~(OP_REGISTER|OP_SET_DXNS)) && c->prev) {
            // trim code *before* the kill, inclocal, declocal, dxns
            code_t*p = c->prev; 
            p->next = 0;
            c->prev = 0;
            return code_append(cut_last_push(p), c);
        } else
            break;
    }
    c = abc_pop(c);
    return c;
}
Beispiel #3
0
code_t* method_header(methodstate_t*m)
{
    code_t*c = 0;

    c = add_scope_code(c, m, 1);

    methodstate_list_t*l = m->innerfunctions;
    while(l) {
        as3_assert(l->methodstate->abc);
        if(m->uses_slots && l->methodstate->is_a_slot) {
            c = abc_getscopeobject(c, 1);
            c = abc_newfunction(c, l->methodstate->abc);
            c = abc_dup(c);
            c = abc_setlocal(c, l->methodstate->var_index);
            c = abc_setslot(c, l->methodstate->slot_index);
        } else {
            c = abc_newfunction(c, l->methodstate->abc);
            c = abc_setlocal(c, l->methodstate->var_index);
        }
        free(l->methodstate);l->methodstate=0;
        l = l->next;
    }
    if(m->header) {
        c = code_append(c, m->header);
        m->header = 0;
    }
    if(m->is_constructor && !m->has_super) {
        // call default constructor
        c = abc_getlocal_0(c);
        c = abc_constructsuper(c, 0);
    }

    if(m->slots) {
        /* all parameters that are used by inner functions
           need to be copied from local to slot */
        as3_assert(m->activation_var);
        DICT_ITERATE_ITEMS(m->slots,char*,name,variable_t*,v) {
            if(v->is_parameter) {
                c = abc_getlocal(c, m->activation_var); 
                c = abc_getlocal(c, v->index); 
                c = abc_setslot(c, v->index); 
            }
        }
    }
Beispiel #4
0
void eval_block(code *block, map* vars) {
  while (true) {
    code_skip_whitespace(block);

    if (block->source[block->pos] == '?') {
      uint8_t brackets = 0;
      size_t start, length = 0;
      mpz_t value;
      mpz_init(value);

      block->pos++;

      code_skip_whitespace(block);
      _parse_value(block, value, vars);
      code_skip_whitespace(block);

      start = block->pos + 1;

      while (true) {
        length++;

        if (block->source[block->pos] == '{') {
          brackets++;
          block->pos++;
        } else if (block->source[block->pos] == '}') {
          brackets--;
          block->pos++;
          if (brackets == 0) break;
        } else {
          block->pos++;
        }
      }

      if (mpz_sgn(value) == 0) {
        code subblock;

        code_init(&subblock);
        code_append(&subblock, block->source + start * sizeof(char), length - 2);
        eval_block(&subblock, vars);
        code_free(&subblock);
      }

      mpz_clear(value);
    } else if (block->source[block->pos] == '!') {
      mpz_t value;
      mpz_init(value);

      block->pos++;
      code_skip_whitespace(block);
      _parse_value(block, value, vars);

      mpz_out_str(stdout, 10, value);
      printf("\n");

      mpz_clear(value);
    } else {
      char *var = malloc(1024 * sizeof(char));
      mpz_t value;
      mpz_init(value);

      _parse_variable_name(block, var);

      code_skip_whitespace(block);
      switch (block->source[block->pos]) {
        case '=':
          block->pos++;
          code_skip_whitespace(block);

          _parse_value(block, value, vars);
          map_set(vars, var, value, false);

          break;

        case '+':
          block->pos += 2;
          code_skip_whitespace(block);

          _parse_value(block, value, vars);
          map_set(vars, var, value, true);

          break;

        case '-':
          block->pos += 2;
          code_skip_whitespace(block);

          _parse_value(block, value, vars);
          mpz_neg(value, value);
          map_set(vars, var, value, true);

          break;

        default:
          fprintf(stderr, "Parse error\n");
      }

      free(var);
      mpz_clear(value);
    }

    code_skip_whitespace(block);

    if (block->pos >= block->length) return;

    if (block->source[block->pos] == ';') {
      block->pos++;
    } else {
      fprintf(stderr, "Missing ;\n");
      return;
    }
  }
}