示例#1
0
PUBLIC OVECTOR newcompilertemplate(int argc, uint8_t *code, int codelen, VECTOR littab) {
  OVECTOR s = newovector(ME_MAXSLOTINDEX, T_METHOD);
  BVECTOR b = newbvector_noinit(codelen);

  memcpy(b->vec, code, codelen);

  ATPUT(s, ME_NAME, (OBJ) newsym("anonymous-method"));
  ATPUT(s, ME_NEXT, NULL);
  ATPUT(s, ME_FLAGS, MKNUM(O_PERMS_MASK));
  ATPUT(s, ME_CODE, (OBJ) b);
  ATPUT(s, ME_OWNER, NULL);
  ATPUT(s, ME_LITS, (OBJ) littab);
  ATPUT(s, ME_ENV, NULL);
  ATPUT(s, ME_ARGC, MKNUM(argc));

  return s;
}
示例#2
0
文件: vm.c 项目: giantfishy/3-move
PRIVATE INLINE void fillframe(VMSTATE vms, OVECTOR f, uint32_t newip) {
  ATPUT(f, FR_CODE, (OBJ) vms->r->vm_code);
  ATPUT(f, FR_IP, MKNUM(newip));
  ATPUT(f, FR_SELF, (OBJ) vms->r->vm_self);
  ATPUT(f, FR_LITS, (OBJ) vms->r->vm_lits);
  ATPUT(f, FR_ENV, (OBJ) vms->r->vm_env);
  ATPUT(f, FR_FRAME, (OBJ) vms->r->vm_frame);
  ATPUT(f, FR_METHOD, (OBJ) vms->r->vm_method);
  ATPUT(f, FR_EFFUID, (OBJ) vms->r->vm_effuid);
}
示例#3
0
PRIVATE OBJ strSearchBody(VMSTATE vms, VECTOR argvec, int case_matters) {
  OBJ str = ARG(0);
  OBJ pat = ARG(1);
  uint8_t const *pos;

  TYPEERRIF(!BVECTORP(str) || !BVECTORP(pat));

  if (case_matters)
    pos = strSearchAux(((BVECTOR) str)->vec, str->length,
		       ((BVECTOR) pat)->vec, pat->length);
  else
    pos = strSearchAuxCI(((BVECTOR) str)->vec, str->length,
			 ((BVECTOR) pat)->vec, pat->length);

  if (pos == NULL)
    return false;
  else
    return MKNUM(pos - ((BVECTOR) str)->vec);
}
示例#4
0
  ATPUT(s, ME_FLAGS, MKNUM(O_PERMS_MASK));
  ATPUT(s, ME_CODE, (OBJ) b);
  ATPUT(s, ME_OWNER, NULL);
  ATPUT(s, ME_LITS, (OBJ) littab);
  ATPUT(s, ME_ENV, NULL);
  ATPUT(s, ME_ARGC, MKNUM(argc));

  return s;
}

PUBLIC void addmethod(OBJECT obj, OVECTOR namesym, OBJECT owner, OVECTOR template) {
  OVECTOR s = newovector(ME_MAXSLOTINDEX, T_METHOD);

  ATPUT(s, ME_NAME, (OBJ) namesym);
  ATPUT(s, ME_NEXT, NULL);
  ATPUT(s, ME_FLAGS, MKNUM(O_PERMS_MASK | O_SETUID));
  ATPUT(s, ME_CODE, (OBJ) AT(template, ME_CODE));
  ATPUT(s, ME_OWNER, (OBJ) owner);
  ATPUT(s, ME_LITS, (OBJ) AT(template, ME_LITS));
  ATPUT(s, ME_ENV, (OBJ) AT(template, ME_ENV));
  ATPUT(s, ME_ARGC, (OBJ) AT(template, ME_ARGC));

  hashtable_put(obj->methods, namesym, s);
}

PUBLIC OVECTOR findmethod(OBJECT obj, OVECTOR namesym) {
  OVECTOR s;
  int i;

  while (1) {
    OBJ objparents;
示例#5
0
文件: vm.c 项目: giantfishy/3-move
PUBLIC int run_vm(VMSTATE vms) {
  OBJ vm_hold;	/* Holding register. NOT SEEN BY GC */
  int ticks_left = VM_TIMESLICE_TICKS;

  while (vms->c.vm_state != VM_STATE_DYING && ticks_left-- && vms->r->vm_acc != yield_thread) {
    if (vms->c.vm_state > 0) {
      vms->c.vm_state--;
      if (vms->c.vm_state == 0) {
	/* Quota expired. Warn. */
	vms->c.vm_state = VM_DEFAULT_CPU_QUOTA;
	vm_raise(vms, (OBJ) newsym("quota-expired"), NULL);
	/* Make sure we don't recurse :-) */
	vms->r->vm_trap_closure = NULL;
      }
    }

    gc_reach_safepoint();

#ifdef DEBUG
    debug_dump_instr( vms->r->vm_code->vec , vms->c.vm_ip );
#endif

    switch (CODEAT(vms->c.vm_ip)) {
      case OP_AT: {
	int index = CODEAT(vms->c.vm_ip + 1);

	if (index < 0 || index >= vms->r->vm_acc->length) {
	  vm_raise(vms, (OBJ) newsym("range-check-error"), vms->r->vm_acc);
	  break;
	}

	if (!VECTORP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	vms->r->vm_acc = AT((VECTOR) vms->r->vm_acc, index);
	vms->c.vm_ip += 2;
	break;
      }

      case OP_ATPUT: {
	int index = CODEAT(vms->c.vm_ip + 1);

	vm_hold = PEEK();

	if (index < 0 || index >= vm_hold->length) {
	  vm_raise(vms, (OBJ) newsym("range-check-error"), vm_hold);
	  break;
	}

	if (!VECTORP(vm_hold)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vm_hold);
	  break;
	}

	ATPUT((VECTOR) vm_hold, index, vms->r->vm_acc);
	vms->c.vm_ip += 2;
	break;
      }

      case OP_MOV_A_LOCL: {
	int i = CODEAT(vms->c.vm_ip + 1);
	vm_hold = (OBJ) vms->r->vm_env;
	while (i-- > 0) vm_hold = AT((VECTOR) vm_hold, 0);
	vms->r->vm_acc = AT((VECTOR) vm_hold, CODEAT(vms->c.vm_ip + 2) + 1);
	vms->c.vm_ip += 3;
	break;
      }

      case OP_MOV_A_GLOB:
	vm_hold = AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	vms->r->vm_acc = AT((OVECTOR) vm_hold, SY_VALUE);
	vms->c.vm_ip += 2;
	break;

      case OP_MOV_A_SLOT: {
	OVECTOR slot, slotname;

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	slotname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));

	if (!O_CAN_X((OBJECT) vms->r->vm_acc, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	slot = findslot((OBJECT) vms->r->vm_acc, slotname, NULL);

	if (slot == NULL) {
	  vm_raise(vms, (OBJ) newsym("slot-not-found"), (OBJ) slotname);
	  break;
	}

	if (!MS_CAN_R(slot, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	vms->r->vm_acc = AT(slot, SL_VALUE);
	vms->c.vm_ip += 2;
	break;
      }

      case OP_MOV_A_LITL:
	vms->r->vm_acc = AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	vms->c.vm_ip += 2;
	break;

      case OP_MOV_A_SELF: vms->r->vm_acc = (OBJ) vms->r->vm_self; vms->c.vm_ip++; break;
      case OP_MOV_A_FRAM: vms->r->vm_acc = (OBJ) vms->r->vm_frame; vms->c.vm_ip++; break;

      case OP_MOV_LOCL_A: {
	int i = CODEAT(vms->c.vm_ip + 1);
	vm_hold = (OBJ) vms->r->vm_env;
	while (i-- > 0) vm_hold = AT((VECTOR) vm_hold, 0);
	ATPUT((VECTOR) vm_hold, CODEAT(vms->c.vm_ip + 2) + 1, vms->r->vm_acc);
	vms->c.vm_ip += 3;
	break;
      }

      case OP_MOV_GLOB_A:
	if (!PRIVILEGEDP(vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) newsym("setting-global-value"));
	}
	vm_hold = AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	ATPUT((OVECTOR) vm_hold, SY_VALUE, vms->r->vm_acc);
	vms->c.vm_ip += 2;
	break;

      case OP_MOV_SLOT_A: {
	OVECTOR slot, slotname;
	OBJECT target = (OBJECT) POP();
	OBJECT foundin;

	if (!OBJECTP(target)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), (OBJ) target);
	  break;
	}

	slotname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));

	if (!O_CAN_X(target, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	slot = findslot(target, slotname, &foundin);

	if (slot == NULL) {
	  vm_raise(vms, (OBJ) newsym("slot-not-found"), (OBJ) slotname);
	  break;
	}

	if (!MS_CAN_W(slot, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) slotname);
	}

	if (foundin == target) {
	  ATPUT(slot, SL_VALUE, vms->r->vm_acc);
	} else {
	  OVECTOR newslot = addslot(target, slotname, (OBJECT) AT(slot, SL_OWNER));
	  ATPUT(newslot, SL_FLAGS, AT(slot, SL_FLAGS));
	  ATPUT(newslot, SL_VALUE, vms->r->vm_acc);
	}

	vms->c.vm_ip += 2;
	break;
      }

      case OP_MOV_FRAM_A:
	if (!PRIVILEGEDP(vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) newsym("restoring-vm-frame-pointer"));
	}

	if (!OVECTORP(vms->r->vm_acc) || ((OVECTOR) vms->r->vm_acc)->type != T_FRAME) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	vms->r->vm_frame = (OVECTOR) vms->r->vm_acc;
	vms->c.vm_ip++;
	break;

      case OP_PUSH: PUSH(vms->r->vm_acc); vms->c.vm_ip++; break;
      case OP_POP: vms->r->vm_acc = POP(); vms->c.vm_ip++; break;
      case OP_SWAP:
	vm_hold = POP();
	PUSH(vms->r->vm_acc);
	vms->r->vm_acc = vm_hold;
	vms->c.vm_ip++;
	break;

      case OP_VECTOR:
	vms->r->vm_acc = (OBJ) newvector(CODEAT(vms->c.vm_ip+1));
	vms->c.vm_ip += 2;
	break;
	
      case OP_ENTER_SCOPE:
	vm_hold = (OBJ) newvector(CODEAT(vms->c.vm_ip+1) + 1);
	ATPUT((VECTOR) vm_hold, 0, (OBJ) vms->r->vm_env);
	vms->r->vm_env = (VECTOR) vm_hold;
	vms->c.vm_ip += 2;
	break;

      case OP_LEAVE_SCOPE:
	vms->r->vm_env = (VECTOR) AT(vms->r->vm_env, 0);
	vms->c.vm_ip++;
	break;

      case OP_MAKE_VECTOR: {
	int i = 0;
	int len = CODEAT(vms->c.vm_ip+1);
	VECTOR vec = newvector_noinit(len);

	for (i = len - 1; i >= 0; i--)
	  ATPUT(vec, i, POP());

	vms->r->vm_acc = (OBJ) vec;
	vms->c.vm_ip += 2;
	break;
      }

      case OP_CLOSURE:
	vms->r->vm_acc = make_closure_from((OVECTOR) vms->r->vm_acc,
					   vms->r->vm_self,
					   vms->r->vm_env,
					   vms->r->vm_effuid);
	vms->c.vm_ip++;
	break;

      case OP_METHOD_CLOSURE: {
	OVECTOR methname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	OVECTOR method;

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	method = findmethod((OBJECT) vms->r->vm_acc, methname);

	if (method == NULL) {
	  vm_raise(vms, (OBJ) newsym("method-not-found"), (OBJ) methname);
	  break;
	}

	if (!MS_CAN_R(method, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) methname);
	}

	vm_hold = (OBJ) newovector(CL_MAXSLOTINDEX, T_CLOSURE);
	ATPUT((OVECTOR) vm_hold, CL_METHOD, (OBJ) method);
	ATPUT((OVECTOR) vm_hold, CL_SELF, vms->r->vm_acc);
	vms->r->vm_acc = vm_hold;

	vms->c.vm_ip += 2;
	break;
      }

      case OP_RET:
	if (vms->r->vm_frame != NULL) {
	  restoreframe(vms, vms->r->vm_frame);
	  if (vms->r->vm_code != NULL)
	    break;
	}

	vms->c.vm_state = VM_STATE_DYING;
	return 1;	/* finished, nothing more to run! */
	
      case OP_CALL: {
	OVECTOR methname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	OVECTOR method;

	if (vms->r->vm_acc == NULL || TAGGEDP(vms->r->vm_acc)) {
	  vm_raise(vms,
		   (OBJ) newsym("null-call-error"),
		   AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip+1)));
	  break;
	}

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	method = findmethod((OBJECT) vms->r->vm_acc, methname);

	if (method == NULL) {
	  vm_raise(vms, (OBJ) newsym("method-not-found"), (OBJ) methname);
	  break;
	}

	if (!MS_CAN_X(method, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) methname);
	}

	vm_hold = POP();
	if (vm_hold->length-1 != NUM(AT(method, ME_ARGC))) {
	  vm_raise(vms, (OBJ) newsym("wrong-argc"), (OBJ) methname);
	  break;
	}

	vms->c.vm_ip += 2;
	push_frame(vms);

	vms->r->vm_env = (VECTOR) vm_hold;
	ATPUT(vms->r->vm_env, 0, AT(method, ME_ENV));
	vms->r->vm_code = (BVECTOR) AT(method, ME_CODE);
	vms->r->vm_lits = (VECTOR) AT(method, ME_LITS);
	vms->r->vm_self = (OBJECT) vms->r->vm_acc;
	if (NUM(AT(method, ME_FLAGS)) & O_SETUID)
	  vms->r->vm_effuid = (OBJECT) AT(method, ME_OWNER);
	vms->r->vm_method = method;
	vms->c.vm_ip = 0;
	break;
      }

      case OP_CALL_AS: {
	OVECTOR methname = (OVECTOR) AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip + 1));
	OVECTOR method;

	if (vms->r->vm_self == NULL ||
	    vms->r->vm_acc == NULL || TAGGEDP(vms->r->vm_acc)) {
	  vm_raise(vms,
		   (OBJ) newsym("null-call-error"),
		   AT(vms->r->vm_lits, CODEAT(vms->c.vm_ip+1)));
	  break;
	}

	if (!OBJECTP(vms->r->vm_acc)) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}

	method = findmethod((OBJECT) vms->r->vm_acc, methname);

	if (method == NULL) {
	  vm_raise(vms, (OBJ) newsym("method-not-found"), (OBJ) methname);
	  break;
	}

	if (!MS_CAN_X(method, vms->r->vm_effuid)) {
	  NOPERMISSION((OBJ) methname);
	}

	vm_hold = POP();
	if (vm_hold->length-1 != NUM(AT(method, ME_ARGC))) {
	  vm_raise(vms, (OBJ) newsym("wrong-argc"), (OBJ) methname);
	  break;
	}

	vms->c.vm_ip += 2;
	push_frame(vms);

	vms->r->vm_env = (VECTOR) vm_hold;
	ATPUT(vms->r->vm_env, 0, AT(method, ME_ENV));
	vms->r->vm_code = (BVECTOR) AT(method, ME_CODE);
	vms->r->vm_lits = (VECTOR) AT(method, ME_LITS);

	/* don't set vm_self, this is OP_CALL_AS. */
	/* vms->r->vm_self = vms->r->vm_acc; */

	if (NUM(AT(method, ME_FLAGS)) & O_SETUID)
	  vms->r->vm_effuid = (OBJECT) AT(method, ME_OWNER);
	vms->r->vm_method = method;
	vms->c.vm_ip = 0;
	break;
      }

      case OP_APPLY:
	vms->c.vm_ip++;
	apply_closure(vms, (OVECTOR) vms->r->vm_acc, (VECTOR) POP());
	break;

      case OP_JUMP: vms->c.vm_ip += 3 + ((int16_t) CODE16AT(vms->c.vm_ip+1)); break;

      case OP_JUMP_TRUE:
	vms->c.vm_ip += (vms->r->vm_acc == false) ? 3 :
						    3 + ((int16_t) CODE16AT(vms->c.vm_ip+1));
	break;

      case OP_JUMP_FALSE:
	vms->c.vm_ip += (vms->r->vm_acc != false) ? 3 :
						    3 + ((int16_t) CODE16AT(vms->c.vm_ip+1));
	break;

      case OP_NOT:
	vms->r->vm_acc = (vms->r->vm_acc == false) ? true : false;
	vms->c.vm_ip++;
	break;

      case OP_EQ:
	vms->r->vm_acc = (vms->r->vm_acc == POP()) ? true : false;
	vms->c.vm_ip++;
	break;

      case OP_NE:
	vms->r->vm_acc = (vms->r->vm_acc != POP()) ? true : false;
	vms->c.vm_ip++;
	break;

      NUMOP(OP_GT, vms->r->vm_acc = (NUM(vms->r->vm_acc) < NUM(POP())) ? true : false);
      NUMOP(OP_LT, vms->r->vm_acc = (NUM(vms->r->vm_acc) > NUM(POP())) ? true : false);
      NUMOP(OP_GE, vms->r->vm_acc = (NUM(vms->r->vm_acc) <= NUM(POP())) ? true : false);
      NUMOP(OP_LE, vms->r->vm_acc = (NUM(vms->r->vm_acc) >= NUM(POP())) ? true : false);

      NUMOP(OP_NEG, vms->r->vm_acc = MKNUM(-NUM(vms->r->vm_acc)));
      NUMOP(OP_BNOT, vms->r->vm_acc = MKNUM(~NUM(vms->r->vm_acc)));
      NUMOP(OP_BOR, vms->r->vm_acc = MKNUM(NUM(vms->r->vm_acc)|NUM(POP())));
      NUMOP(OP_BAND, vms->r->vm_acc = MKNUM(NUM(vms->r->vm_acc)&NUM(POP())));

      case OP_PLUS:
	if (vms->r->vm_acc == NULL || PEEK() == NULL) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}
	if (NUMP(vms->r->vm_acc) && NUMP(PEEK()))
	  vms->r->vm_acc = MKNUM(NUM(vms->r->vm_acc)+NUM(POP()));
	else if (TAGGEDP(vms->r->vm_acc) || TAGGEDP(PEEK())) {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	} else if (BVECTORP(vms->r->vm_acc) && BVECTORP(PEEK()))
	  vms->r->vm_acc = (OBJ) bvector_concat((BVECTOR) POP(), (BVECTOR) vms->r->vm_acc);
	else if (VECTORP(vms->r->vm_acc) && VECTORP(PEEK()))
	  vms->r->vm_acc = (OBJ) vector_concat((VECTOR) POP(), (VECTOR) vms->r->vm_acc);
	else {
	  vm_raise(vms, (OBJ) newsym("vm-runtime-type-error"), vms->r->vm_acc);
	  break;
	}
	vms->c.vm_ip++;
	break;

      NUMOP(OP_MINUS, vms->r->vm_acc = MKNUM(NUM(POP())-NUM(vms->r->vm_acc)));
      NUMOP(OP_STAR, vms->r->vm_acc = MKNUM(NUM(POP())*NUM(vms->r->vm_acc)));
      NUMOP(OP_SLASH,
	    if (vms->r->vm_acc == MKNUM(0))
	      vm_raise(vms, (OBJ) newsym("divide-by-zero"), NULL);
	    else
	      vms->r->vm_acc = MKNUM(NUM(POP())/NUM(vms->r->vm_acc)));
      NUMOP(OP_PERCENT,
	    if (vms->r->vm_acc == MKNUM(0))
	      vm_raise(vms, (OBJ) newsym("divide-by-zero"), NULL);
	    else
	      vms->r->vm_acc = MKNUM(NUM(POP())%NUM(vms->r->vm_acc)));

      default:
	fprintf(stderr, "Unknown bytecode reached (%d == 0x%x).\n",
		CODEAT(vms->c.vm_ip),
		CODEAT(vms->c.vm_ip));
	exit(MOVE_EXIT_PROGRAMMER_FUCKUP);
    }
  }

  return vms->c.vm_state == VM_STATE_DYING;
}
示例#6
0
TEST_CASE("render/ueb/Fractions", "[render][UEB][Fractions]") {
  UEBRenderer r;

  // UEB Technical Guideline 6.1 --------------------------------------------
  // "Simple fractions" (those where both the numerator and denominator
  // consist SOLELY of numbers) are rendered simple as [num]/[den].
  //
  // We need to test a variety of number combinations to make sure that
  // the fraction rendering code is detecting 'simple' fractions
  // appropriately.
  //
  // These examples are drawn from Technical Guideline 6.5
  SECTION ("Simple numeric fractions") {
    SECTION ("Simple numbers") {
      TF(MKNUM(POSITIVE, "3", ""), MKNUM(POSITIVE, "4", ""), "#C/D");
      TF(MKNUM(POSITIVE, "73", ""), MKNUM(POSITIVE, "4", ""), "#GC/D");
    }
    SECTION ("Numbers involving decimals") {
      TF(MKNUM(POSITIVE, "3", ""), MKNUM(POSITIVE, "4", "2"), "#C/D4B");
      TF(MKNUM(POSITIVE, "5", "3"), MKNUM(POSITIVE, "4200", ""), "#E4C/DBJJ");
    }
    SECTION ("Numbers involving numeric commas") {
      TF(MKNUM(POSITIVE, "5", "3"), MKNUM(POSITIVE, "4,200", ""), "#E4C/D1BJJ");
    }
    SECTION ("Numbers involving numeric spaces") {
      TF(MKNUM(POSITIVE, "5", "3"), MKNUM(POSITIVE, "4 200", ""), "#E4C/D\"BJJ");
    }
  }

  // UEB Technical Guideline 6.4 --------------------------------------------