Exemple #1
0
uptr_t eval(uptr_t *env, uptr_t form) {
  if (IS_INT(form) || IS_NIL(form))
    return form;

  if (IS_SYM(form))
    return get(*env, form);

  if (IS_CONS(form)) {
    uptr_t *form_p = refer(form),
      *fn_p = refer(eval(env, CAR(*form_p))),
      rval;

    if (IS_SYM(*fn_p)) {
      rval = exec_special(env, *form_p);
    } else if (IS_CONS(*fn_p) && SVAL(CAR(*fn_p)) == S_FN) {
      rval = _fn(env, *fn_p, eval_list(env, CDR(*form_p)));
    } else {
      printf_P(PSTR("ERROR: "));
      print_form(CAR(*form_p));
      printf_P(PSTR(" cannot be in function position.\n"));

      rval = NIL;
    }

    release(2); // form_p, fn_p
    return rval;
  }

  return NIL;
}
Exemple #2
0
int main() {

  init_env(); // Poorly named. Has nothing to do with env alist.
  init_mem();

  uptr_t *env = refer(NIL);
  init_syms(env);

  uptr_t *form_p = refer(NIL);
  while(1) {
    print_env(env);
    print_mem();

    printf_P(PSTR("> "));
    *form_p = read_form(stdin);
    while(getc(stdin) != '\r');
    print_form(eval(env, *form_p));
    printf_P(PSTR("\n"));

    //    print_mem();
    __GC__();
  }

  release(2); // Just a formality really...

  return 0;
}
Exemple #3
0
int main (void)
{
  A alpha, *aap, *abp;
  B beta, *bbp;
  empty e;

  alpha.a1 = 100;
  beta.a1 = 200; beta.b1 = 201; beta.b2 = 202;

  aap = α refer (aap);
  abp = β  refer (abp);
  bbp = β  refer (bbp);
  refer (&e);

  return 0;  // marker return 0
} // marker close brace
Exemple #4
0
int main (int argc, char **argv)
{ 
  if (argc != 1) {
    nthreads = atoi(argv[1]);
    degree = nthreads; // flat phaser by default
    if (argc > 2)
      degree = atoi(argv[2]);

    delaylength = 0;
    innerreps = 1000000;

    if (argc > 3)
      delaylength = atoi(argv[3]);
  } else {
    // TODO should get number of workers here
    int nthreads = 3;
    degree = nthreads; // flat phaser by default
    delaylength = 0;
    innerreps = 1000000;
  }

  printf(" Running phaser barrier benchmark on %d thread(s) and phaser tree degree %d\n", nthreads, degree); 

  /* GENERATE REFERENCE TIME */ 
  refer();   

  /* TEST BARRIER */
  hclib_init(&argc, argv);
  testbar();
  hclib_finalize();

  return 0;
} 
    void HttpDownloader::Start(bool is_support_start)
    {
        if (is_running_ == true)
            return;

        is_running_ = true;

        string refer(url_info_.refer_url_);
        assert(download_driver_->GetStatistic());

        statistic_ = download_driver_->GetStatistic()->AttachHttpDownloaderStatistic(url_info_.url_);

        assert(statistic_);
        statistic_->SetReferUrl(refer);
        statistic_->SetIsDeath(false);

        is_support_start_ = is_support_start;

        if (http_request_demo_)
            http_connection_ = HttpConnection::Create(io_svc_, http_request_demo_, shared_from_this(), url_info_, is_to_get_header_, is_head_only_);
        else
            http_connection_ = HttpConnection::Create(io_svc_, shared_from_this(), url_info_, is_head_only_);

        if (is_original_)
        {
            http_connection_->Start(is_support_start, is_open_service_, download_driver_->GetOpenServiceHeadLength());
        }
    }
Exemple #6
0
uptr_t eval_list(uptr_t *env, uptr_t list) {
  if (IS_NIL(list))
    return NIL;

  uptr_t *list_p = refer(list), rval;
  rval = build_cons(eval(env, CAR(*list_p)), eval_list(env, CDR(*list_p)));
  release(1); // list_p
  return rval;
}
Exemple #7
0
uptr_t let(uptr_t *env, uptr_t args) {
  uptr_t *bindings_p = refer(CAR(args)),
    *body_p = refer(CDR(args)),
    *local_env = refer(*env);

  while (*bindings_p) {
    assoc(local_env, CAR(*bindings_p), eval(local_env, CADR(*bindings_p)));
    *bindings_p = CDDR(*bindings_p);
  }

  uptr_t rval = NIL;
  while(*body_p) {
    rval = eval(local_env, CAR(*body_p));
    *body_p = CDR(*body_p);
  }

  release(3); // bindings_p, body_p, local_env

  return rval;
}
Exemple #8
0
uptr_t _fn(uptr_t *env, uptr_t fn, uptr_t args) {
  uptr_t *lvars_p = refer(CADR(fn)),
    *body_p = refer(CDDR(fn)),
    *args_p = refer(args),
    *local_env = refer(*env);

  while (*lvars_p && *args_p) {
    assoc(local_env, CAR(*lvars_p), CAR(*args_p));
    *lvars_p = CDR(*lvars_p);
    *args_p = CDR(*args_p);
  }

  uptr_t rval = NIL;

  while(*body_p) {
    rval = eval(local_env, CAR(*body_p));
    *body_p = CDR(*body_p);
  }

  release(4); // lvars_p, body_p, args_p, local_env
  return rval;
}
Exemple #9
0
// This message exists to encapsulate the Dialog State into a SIP message.
// It is created on BS1 to send to BS2, which then uses it as a re-invite.
// So fill it out as a re-invite but leaving the parts based on the BS2 address empty, ie, no via or contact.
// Note that when we send it to BS2 the via and contact are BS1, which BS2 must fix.
// We need to pass the the remote proxy address that we derived from the 'contact' from the peer,
// that was passed in in the initial incoming invite or the response to our outgoing invite.
// We place it in the Refer-To header, and BS2 turns the REFER into an INVITE to that URI.
// This goes in the URI of the header, implying that we cannot send this message to BS2 using normal SIP
// unless we move that to another field, eg, Contact.
SipMessageHandoverRefer::SipMessageHandoverRefer(const SipBase *dialog, string peer)
{
	// The request URI will be the BTS we are sending it to...
	this->smInit();
	this->msmReqMethod = string("REFER");
	this->msmReqUri = makeUri("handover",peer);
	this->msmTo = *dialog->dsRequestToHeader();
	this->msmFrom = *dialog->dsRequestFromHeader();
	this->msmCallId = dialog->callId();
	this->msmCSeqMethod = this->msmReqMethod;	// It is "INVITE".
	// The CSeq num of the are-INVITE follows.
	// RFC3261 14.1: The Cseq for re-INVITE follows same rules for in-dialog requests, namely, CSeq num must be
	// incremented by exactly one.  We do not know if BTS-2 is going to send this this re-INVITE or not,
	// so we send the current CSeqNum without incrementing it and let BTS-2 increment it.
	this->msmCSeqNum = dialog->mLocalCSeq;
	SipParam refer("Refer-To",dialog->dsRemoteURI());	// This is the proxy from the Contact or route header.
	this->msmHeaders.push_back(refer);

	// We need to send the SDP answer, which is the local SDP for MTC or the remote SDP for MOC,
	// but we need to send the peer (remote) RTP port in either case.
	// For the re-invite, you can put nearly anything in here, but you must not just use
	// the identical o= line of the original without at least incrementing the version number.
	SdpInfo sdpRefer, sdpRemote;
	//sdpRefer.sdpInitOffer(dialog);
	sdpRemote.sdpParse(dialog->getSdpRemote());

	// Put the remote SIP server port in the REFER message.  BTS-2 will grab it then substitute its own local port.
	//sdpRefer.sdpRtpPort = sdpRemote.sdpRtpPort;

	sdpRefer.sdpInitRefer(dialog, sdpRemote.sdpRtpPort);

	// TODO: Put the remote session id and version, incrementing the version.  Paul at yate says these should be 0

	//SdpInfo sdpRefer; sdpRefer.sdpParse(dialog->mSdpAnswer);
	//sdpRefer.sdpUsername = dialog->sipLocalusername();

	// Update: This did not work for asterisk either.
	//sdpRefer.sdpUsername = dialog->sipLocalUsername(); // This modification was recommended by Paul for Yate.

	//this->smAddBody(string("application/sdp"),sdpRefer.sdpValue());
	// Try just using the sdpremote verbatim?  Gosh, that worked too.
	this->smAddBody(string("application/sdp"),sdpRefer.sdpValue());

	// The via and contact will be filled in by BS2:
	// this->smAddViaBranch(dialog);
	// this->msmContactValue = dialog->dsRemoteURI();
	// TODO: route set.
}
Exemple #10
0
int main (int argv, char **argc)
{
 

#pragma omp parallel
  { 
#pragma omp master 
    {
  nthreads = omp_get_num_threads(); 
    }
  } 
 
  printf("Running OpenMP benchmark on %d thread(s)\n", nthreads); 

  /* TUNE LENGTH OF LOOP BODY */ 
  getdelay(); 
  itersperthr = 1204; /*change from 128 to 256 for more test on guided,Liao*/
  innerreps = 1000;

  /* GENERATE REFERENCE TIME */ 
  refer();   

  /* TEST STATIC */ 
  teststatic(); 

  /* TEST STATIC,n */
  cksz = 1;
  while (cksz <= itersperthr){
    teststaticn();
    cksz *= 2;    
  }

  /* TEST DYNAMIC,n */

  cksz = 1;
  while (cksz <= itersperthr){
    testdynamicn();
    cksz *= 2;    
  }

  /* TEST GUIDED,n */
  cksz = 1;
  while (cksz <= itersperthr*2/nthreads){ /*increase cksz*/
    testguidedn();
    cksz *= 2;    
  }
  
}
Exemple #11
0
/* Calculate the reference time. */
void reference(char *name, void (*refer)(void)) {
    int k;
    double start;

    // Calculate the required number of innerreps
    innerreps = getinnerreps(refer);

    initreference(name);

    for (k = 0; k <= outerreps; k++) {
	start = getclock();
	refer();
	times[k] = (getclock() - start) * 1.0e6 / (double) innerreps;
    }

    finalisereference(name);

}
Exemple #12
0
BOOL SendUrlToEM(LPCTSTR pszUrl, LPCTSTR pszReferer, LPCTSTR pszCookies, LPCTSTR pszPostData)
{
	IIE2EMUrlTaker * taker;
	HRESULT hr;
	if (FAILED(hr = CoCreateInstance (CLSID_IE2EMUrlTaker, NULL, CLSCTX_ALL, IID_IIE2EMUrlTaker, (void**) &taker)))
	{
		TCHAR szMsg[1000];
		_tcscpy(szMsg, _T("easyMule might have not been installed!\nPlease confirm you easyMule installation.\n\nError code: 0x"));
		TCHAR sz[100];
		_itot((UINT)hr, sz, 16);
		_tcscat(szMsg, sz);
		MessageBox(NULL, szMsg, _T("Error"), MB_ICONERROR);
		return FALSE;
	}

	USES_CONVERSION;
	CComBSTR url(pszUrl);
	CComBSTR refer(pszReferer);
	BOOL res;
	if(taker->SendUrl(url.Copy(), _T("\1"), refer.Copy(), &res) != S_OK)
		return FALSE;
	return res;
}
Exemple #13
0
uptr_t loop(uptr_t *env, uptr_t form) {
  uptr_t *bindings_p = refer(CAR(form)),
    *body_p = refer(CDR(form)),
    *form_p = refer(form),
    *local_env = refer(*env);

  while (*bindings_p) {
    assoc(local_env, CAR(*bindings_p), eval(local_env, CADR(*bindings_p)));
    *bindings_p = CDDR(*bindings_p);
  }
  //  print_env(local_env);

  uptr_t rval = NIL,
    *new_env = refer(NIL),
    *new_vals = refer(NIL);
  while (*body_p) {
    rval = eval(local_env, CAR(*body_p));
    *body_p = CDR(*body_p);

    if (IS_CONS(rval) && IS_SYM(CAR(rval)) && SVAL(CAR(rval)) == S_RECUR) {
      *new_env = *env;
      *new_vals = CDR(rval);
      *bindings_p = CAR(*form_p);
      while (*new_vals && *bindings_p) {
        assoc(new_env, CAR(*bindings_p), eval(local_env, CAR(*new_vals)));
        *bindings_p = CDDR(*bindings_p);
        *new_vals = CDR(*new_vals);
      }
      *body_p = CDR(*form_p);
      *local_env = *new_env;
    }
  }

  release(6); // bindings_p, body_p, form_p, local_env, new_env, new_vals
  return rval;
}
Exemple #14
0
void eval(BOOLEAN do_gc)
{
  static unsigned int count = 0;

  OBJECT_PTR exp = car(reg_next_expression);

  OBJECT_PTR opcode = car(exp);

  pin_globals();

  if(do_gc)
  {
    count++;

    if(count == GC_FREQUENCY)
    {
      gc(false, true);
      count = 0;
    }
  }

  if(opcode == APPLY && profiling_in_progress)
  {
    last_operator = reg_accumulator;

    if(prev_operator != NIL)
    {
      OBJECT_PTR operator_to_be_used;

      hashtable_entry_t *e;

      unsigned int count;
      unsigned int mem_alloc;
      double elapsed_wall_time;
      double elapsed_cpu_time;

      double temp1 = get_wall_time();
      clock_t temp2 = clock();
      unsigned int temp3 = memory_allocated();

      profiling_datum_t *pd = (profiling_datum_t *)malloc(sizeof(profiling_datum_t));

      if(IS_SYMBOL_OBJECT(prev_operator))
         operator_to_be_used = prev_operator;
      else
      {
        OBJECT_PTR res = get_symbol_from_value(prev_operator, reg_current_env);
        if(car(res) != NIL)
          operator_to_be_used = cdr(res);
        else
          operator_to_be_used = cons(LAMBDA,
                                     cons(get_params_object(prev_operator),
                                          cons(car(get_source_object(prev_operator)), NIL)));
      }

      e = hashtable_get(profiling_tab, (void *)operator_to_be_used);

      if(e)
      {
        profiling_datum_t *pd = (profiling_datum_t *)e->value;

        count = pd->count + 1;

        elapsed_wall_time = pd->elapsed_wall_time + temp1 - wall_time_var;
        elapsed_cpu_time = pd->elapsed_cpu_time + (temp2 - cpu_time_var) * 1.0 / CLOCKS_PER_SEC;
      
        mem_alloc = pd->mem_allocated + temp3 - mem_alloc_var;

        hashtable_remove(profiling_tab, (void *)operator_to_be_used);
        free(pd);
      }
      else
      {
        count = 1;
        elapsed_wall_time = temp1 - wall_time_var;
        elapsed_cpu_time = (temp2 - cpu_time_var) * 1.0 / CLOCKS_PER_SEC;
        mem_alloc = temp3 - mem_alloc_var;
      }

      pd->count = count;
      pd->elapsed_wall_time = elapsed_wall_time;
      pd->elapsed_cpu_time = elapsed_cpu_time;
      pd->mem_allocated = mem_alloc;

      hashtable_put(profiling_tab, (void *)operator_to_be_used, (void *)pd);
    }

    wall_time_var = get_wall_time();
    cpu_time_var = clock();
    mem_alloc_var = memory_allocated();

    prev_operator = reg_accumulator;
  }

  if(opcode == HALT)
  {
    halt_op();
  }
  else if(opcode == REFER)
  {
    if(refer(CADR(exp)))
       return;
    reg_next_expression = CADDR(exp);
  }
  else if(opcode == CONSTANT)
  {
    if(constant(CADR(exp)))
      return;
    reg_next_expression = CADDR(exp);
  }
  else if(opcode == CLOSE)
  {
    if(closure(exp))
      return;
    reg_next_expression = fifth(exp);
  }
  else if(opcode == MACRO)
  {
    if(macro(exp))
      return;
    reg_next_expression = CADDDDR(exp);
  }
  else if(opcode == TEST)
  {
    if(reg_accumulator != NIL)
      reg_next_expression = CADR(exp);
    else
      reg_next_expression = CADDR(exp);
  }
  //Not using this WHILE; reverting 
  //to macro definition, as this
  //version doesn't handle (BREAK)
  else if(opcode == WHILE)
  {
    OBJECT_PTR cond = CADR(exp);
    OBJECT_PTR body  = CADDR(exp);

    OBJECT_PTR ret = NIL;

    while(1)
    {
      OBJECT_PTR temp = reg_current_stack;

      reg_next_expression = cond;

      while(car(reg_next_expression) != NIL)
      {
        eval(false);
        if(in_error)
          return;
      }

      if(reg_accumulator == NIL)
        break;

      reg_next_expression = body;

      while(car(reg_next_expression) != NIL)
      {
        eval(false);
        if(in_error)
          return;
      }

      //to handle premature exits
      //via RETURN-FROM
      if(reg_current_stack != temp)
        return;

      ret = reg_accumulator;
    }

    reg_accumulator = ret;
    reg_next_expression = CADDDR(exp);
  }
  else if(opcode == ASSIGN)
  {
    if(assign(CADR(exp)))
      return;
    reg_next_expression = CADDR(exp);
  }
  else if(opcode == DEFINE)
  {
    if(define(CADR(exp)))
      return;
    reg_next_expression = CADDR(exp);
  }
  else if(opcode == CONTI)
  {
    if(conti())
      return;
    reg_next_expression = CADR(exp);
  }
  else if(opcode == NUATE) //this never gets called
  {
    reg_current_stack = CADR(exp);
    reg_accumulator = CADDR(exp);
    reg_current_value_rib = NIL;
    reg_next_expression =  cons(CONS_RETURN_NIL, cdr(reg_next_expression));
  }
  else if(opcode == FRAME)
  {
    if(frame(exp))
      return;
    reg_next_expression = CADDR(exp);
  }
  else if(opcode == ARGUMENT)
  {
    if(argument())
      return;
    reg_next_expression = CADR(exp);
  }
  else if(opcode == APPLY)
  {
    apply_compiled();
  }
  else if(opcode == RETURN)
  {
    return_op();
  }
}
Exemple #15
0
void
comline(void)
{
	long c1, c2;

	while(C==' ' || c=='\t')
		;
comx:
	if((c1=c) == '\n')
		return;
	c2 = C;
	if(c1=='.' && c2!='.')
		inmacro = NO;
	if(msflag && c1 == '['){
		refer(c2);
		return;
	}
	if(c2 == '\n')
		return;
	if(c1 == '\\' && c2 == '\"')
		SKIP;
	else
	if (filesp==files && c1=='E' && c2=='Q')
			eqn();
	else
	if(filesp==files && c1=='T' && (c2=='S' || c2=='C' || c2=='&')) {
		if(msflag)
			stbl(); 
		else
			tbl();
	}
	else
	if(c1=='T' && c2=='E')
		intable = NO;
	else if (!inmacro &&
			((c1 == 'd' && c2 == 'e') ||
		   	 (c1 == 'i' && c2 == 'g') ||
		   	 (c1 == 'a' && c2 == 'm')))
				macro();
	else
	if(c1=='s' && c2=='o') {
		if(iflag)
			SKIP;
		else {
			getfname();
			if(fname[0]) {
				if(infile = opn(fname))
					*++filesp = infile;
				else infile = *filesp;
			}
		}
	}
	else
	if(c1=='n' && c2=='x')
		if(iflag)
			SKIP;
		else {
			getfname();
			if(fname[0] == '\0')
				exits(0);
			if(Bfildes(&(infile->Biobufhdr)) != 0)
				Bterm(&(infile->Biobufhdr));
			infile = *filesp = opn(fname);
		}
	else
	if(c1 == 't' && c2 == 'm')
		SKIP;
	else
	if(c1=='h' && c2=='w')
		SKIP; 
	else
	if(msflag && c1 == 'T' && c2 == 'L') {
		SKIP_TO_COM;
		goto comx; 
	}
	else
	if(msflag && c1=='N' && c2 == 'R')
		SKIP;
	else
	if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){
		if(mac==MM)SKIP;
		else {
			SKIP_TO_COM;
			goto comx; 
		}
	} else
	if(msflag && c1=='F' && c2=='S') {
		SKIP_TO_COM;
		goto comx; 
	}
	else
	if(msflag && (c1=='S' || c1=='N') && c2=='H') {
		SKIP_TO_COM;
		goto comx; 
	} else
	if(c1 == 'U' && c2 == 'X') {
		if(wordflag)
			Bprint(&(bout.Biobufhdr), "UNIX\n");
		else
			Bprint(&(bout.Biobufhdr), "UNIX ");
	} else
	if(msflag && c1=='O' && c2=='K') {
		SKIP_TO_COM;
		goto comx; 
	} else
	if(msflag && c1=='N' && c2=='D')
		SKIP;
	else
	if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U'))
		SKIP;
	else
	if(msflag && mac==MM && c2=='L') {
		if(disp || c1=='R')
			sdis('L', 'E');
		else {
			SKIP;
			Bprint(&(bout.Biobufhdr), " .");
		}
	} else
	if(!msflag && c1=='P' && c2=='S') {
		inpic();
	} else
	if(msflag && (c1=='D' || c1=='N' || c1=='K'|| c1=='P') && c2=='S') { 
		sdis(c1, 'E'); 
	} else
	if(msflag && (c1 == 'K' && c2 == 'F')) { 
		sdis(c1,'E'); 
	} else
	if(msflag && c1=='n' && c2=='f')
		sdis('f','i');
	else
	if(msflag && c1=='c' && c2=='e')
		sce();
	else {
		if(c1=='.' && c2=='.') {
			if(msflag) {
				SKIP;
				return;
			}
			while(C == '.')
				;
		}
		inmacro++;
		if(c1 <= 'Z' && msflag)
			regline(YES,ONE);
		else {
			if(wordflag)
				C;
			regline(YES,TWO);
		}
		inmacro--;
	}
}
Exemple #16
0
void UmlFragment::write_ref(FileOut & out, UmlItem * diagram, Q3PtrList< UmlSequenceMessage > & msgs)
{
    static int rank = 0;

    out.indent();
    out << "<fragment xmi:type=\"uml:InteractionUse\"";
    out.id_prefix(diagram, "INTERACTIONUSE", ++rank);

    const Q3PtrVector<UmlClassInstanceReference> & v = UmlBaseFragment::covered();
    unsigned n;
    unsigned index;

    n = v.count();

    if (n != 0) {
        out << " covered=\"";

        index = 0;

        for (;;) {
            out.ref_only(diagram, v.at(index)->lifeline());

            if (++index == n)
                break;

            out << " ";
        }

        out << '"';
    }

    UmlDiagram * d = refer();

    if (d != 0) {
        switch (d->kind()) {
        case aSequenceDiagram:
        case aCollaborationDiagram:
            out.ref(d, "refersTo", "INTERACTION_");

            if (arguments().isEmpty())
                out << "/>\n";
            else {
                static int rank = 0;

                out << ">\n";
                out.indent();
                out << "\t<argument xmi:type=\"uml:OpaqueExpression\"";
                out.id_prefix(d, "INTER_ARG_EXPR_", ++rank);
                out << ">\n";
                out.indent();
                out << "\t\t<body>";
                out.quote(arguments());
                out << "</body>\n";
                out.indent();
                out << "\t</argument>\n";
                out.indent();
                out << "</fragment>\n";
            }

            break;

        default:
            out << "/>\n";
            break;
        }
    }
    else
        out << "/>\n";

    // remove internal messages and compartment

    const Q3PtrVector<UmlFragmentCompartment> & subs = compartments();

    n = subs.size();

    for (index = 0; index != n; index += 1)
        subs.at(index)->bypass(msgs);
}
Exemple #17
0
uptr_t exec_special(uptr_t *env, uptr_t form) {
  uptr_t fn = CAR(form);
  uptr_t args = CDR(form);

  switch(SVAL(fn)) {
  case S_LET:
    return let(env, args);

  case S_FN:
    return form;

  case S_LOOP:
    return loop(env, args);

  case S_DO: {
    uptr_t *body_p = refer(args), rval = NIL;

    while (*body_p) {
      rval = eval(env, CAR(*body_p));
      *body_p = CDR(*body_p);
    }
    release(1); // body_p
    return rval;
  }

  case S_RECUR: {
    uptr_t rval, *fn_p = refer(fn);
    rval = build_cons(*fn_p, eval_list(env, args));
    release(1); // fn_p
    return rval;
  }

  case S_QUOTE:
    return CAR(args);

  case S_CAR:
    return CAR(eval(env, CAR(args)));

  case S_CDR:
    return CDR(eval(env, CAR(args)));

  case S_AND: {
    if (IS_NIL(args)) return PS_TRUE;
    uptr_t *rem_args = refer(args),
      rval = NIL;
    while ((rval = eval(env, CAR(*rem_args))) && (*rem_args = CDR(*rem_args)));
    release(1);
    return rval;
  }

  case S_OR: {
    if (IS_NIL(args)) return NIL;
    uptr_t *rem_args = refer(args),
      rval = NIL;
    while (!(rval = eval(env, CAR(*rem_args))) && (*rem_args = CDR(*rem_args)));
    release(1);
    return rval;
  }

  case S_NOT: {
    if (IS_NIL(args)) return NIL;
    uptr_t rval = eval(env, CAR(args));
    return rval ? NIL : PS_TRUE;
  }

  case S_IF: {
    uptr_t rval = NIL, *clauses = refer(args);

    if (eval(env, CAR(*clauses)) && CDR(*clauses))
      rval = eval(env, CADR(*clauses));
    else if (CDDR(*clauses))
      rval = eval(env, CADDR(*clauses));

    release(1); // clauses
    return rval;
  }

  case S_WHEN: {
    uptr_t rval = NIL, *cond_p = refer(CAR(args)), *body_p = refer(CDR(args));

    if (eval(env, *cond_p))
      while(*body_p) {
        rval = eval(env, CAR(*body_p));
        *body_p = CDR(*body_p);
      }

    release(2); // cond_p, body_p
    return rval;
  }

  case S_CONS: {
    uptr_t rval = NIL, *args_p = refer(args);
    rval = build_cons(eval(env, CAR(*args_p)), eval(env, CADR(*args_p)));
    release(1); // args_p
    return rval;
  }

  case S_PRINT:
    print_form(eval(env, CAR(args)));
    printf_P(PSTR("\n"));
    return NIL;

  case S_DEF: {
    uptr_t *args_p = refer(args),
      *binding = refer(eval(env, CADR(args)));
    assoc(env, CAR(*args_p), *binding);
    release(2); // args_p, binding
    return *binding; // Yeah, it's been "released", but the pointer is still valid.
  }

  case S_EVAL:
    return eval(env, eval(env, CAR(args)));

#define _COMPR(rval) {                                                  \
      if (IS_NIL(args)) return NIL;                                     \
                                                                        \
      uptr_t *args_p = refer(args);                                     \
      while(CDR(*args_p) && (eval(env, CAR(*args_p)) _COMP_OPR eval(env, CADR(*args_p)))) \
        *args_p = CDR(*args_p);                                         \
                                                                        \
      if (IS_NIL(CDR(*args_p)))                                         \
        rval = eval(env, CAR(*args_p));                                 \
      release(1);                                                       \
    }

#define _COMP_OPR ==
  case S_EQL: {
    uptr_t rval = NIL;
    _COMPR(rval);
    return rval;
  }

  case S_NEQL: {
    uptr_t rval = NIL;
    _COMPR(rval);
    return rval ? NIL : PS_TRUE;
  }
#undef _COMP_OPR

#define _COMP_OPR <
  case S_LT: {
    uptr_t rval = NIL;
    _COMPR(rval);
    return rval;
  }
#undef _COMP_OPR

#define _COMP_OPR <=
  case S_LTE: {
    uptr_t rval = NIL;
    _COMPR(rval);
    return rval;
  }
#undef _COMP_OPR

#define _COMP_OPR >
  case S_GT: {
    uptr_t rval = NIL;
    _COMPR(rval);
    return rval;
  }
#undef _COMP_OPR

#define _COMP_OPR >=
  case S_GTE: {
    uptr_t rval = NIL;
    _COMPR(rval);
    return rval;
  }
#undef _COMP_OPR

#define _ARITH(coll) {                                          \
      uptr_t *rem_args = refer(args);                           \
      coll = TO_INT(eval(env, CAR(*rem_args)));                 \
      *rem_args = CDR(*rem_args);                               \
      while (*rem_args) {                                       \
        coll _ARITH_OPR TO_INT(eval(env, CAR(*rem_args)));      \
        *rem_args = CDR(*rem_args);                             \
      }                                                         \
      release(1);                                               \
    }

#define _ARITH_OPR +=
  case S_PLUS: {
    if (! args) return INTERN_INT(0);
    if (! CDR(args)) return eval(env, CAR(args));
    int rval;
    _ARITH(rval);
    return INTERN_INT(rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR -=
  case S_MINUS: {
    if (! args) return NIL;
    if (! CDR(args)) return INTERN_INT(0 - TO_INT(eval(env, CAR(args))));
    int rval;
    _ARITH(rval);
    return INTERN_INT(rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR *=
  case S_MULT: {
    if (! args) return INTERN_INT(1);
    if (! CDR(args)) return eval(env, CAR(args));
    int rval;
    _ARITH(rval);
    return INTERN_INT(rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR /=
  case S_DIV: {
    if (! args) return NIL;
    if (! CDR(args)) return INTERN_INT(eval(env, CAR(args)) == INTERN_INT(1) ? 1 : 0);
    int rval;
    _ARITH(rval);
    return INTERN_INT(rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR &=
  case S_BAND: {
    if (! args) return NIL;
    if (! CDR(args)) return eval(env, CAR(args));
    uint8_t rval;
    _ARITH(rval);
    return INTERN_INT((int)rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR |=
  case S_BOR: {
    if (! args) return NIL;
    if (! CDR(args)) return eval(env, CAR(args));
    uint8_t rval;
    _ARITH(rval);
    return INTERN_INT((int)rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR ^=
  case S_BXOR: {
    if (! args) return NIL;
    if (! CDR(args)) return eval(env, CAR(args));
    uint8_t rval;
    _ARITH(rval);
    return INTERN_INT((int)rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR <<=
  case S_BSL: {
    if (! args) return NIL;
    if (! CDR(args)) return eval(env, CAR(args));
    uint8_t rval;
    _ARITH(rval);
    return INTERN_INT((int)rval);
  }
#undef _ARITH_OPR

#define _ARITH_OPR >>=
  case S_BSR: {
    if (! args) return NIL;
    if (! CDR(args)) return eval(env, CAR(args));
    uint8_t rval;
    _ARITH(rval);
    return INTERN_INT((int)rval);
  }
#undef _ARITH_OPR

  case S_SREG: {
    uptr_t *args_p = refer(args),
      reg = eval(env, CAR(*args_p));
    if (IS_REG(reg))
      *BYTE_PTR(reg) = eval(env, CADR(*args_p));
    else {
      printf_P(PSTR("Invalid register: "));
      print_form(reg);
      printf_P(PSTR("\n"));
    }
    release(1); // args_p
    return NIL;
  }

  case S_SLP:
    _delay_ms(TO_INT(eval(env, CAR(args))));
    return NIL;

  default:
    printf_P(PSTR("ERROR: "));
    print_form(fn);
    printf_P(PSTR(" is not a function.\n"));
    return NIL;
  }
}