#include <cstdio>
#include <cctype>
#include <cstdlib>
#include "consts.h"
#include "builtin.h"
#include "model.h"
#include "exc.h"
#include "types.h"
using std::stringstream;
extern EmptyList *empty_list;
SpecialOptIf::SpecialOptIf() : SpecialOptObj("if") {}
void SpecialOptIf::prepare(Pair *pc) {
#define IF_EXP_ERR \
throw TokenError(name, RUN_ERR_WRONG_NUM_OF_ARGS)
Pair *first, *second, *third;
if (pc->cdr == empty_list)
IF_EXP_ERR;
first = TO_PAIR(pc->cdr);
if (first->cdr == empty_list)
IF_EXP_ERR;
second = TO_PAIR(first->cdr);
if (second->cdr != empty_list)
{
third = TO_PAIR(second->cdr);
if (third->cdr != empty_list) IF_EXP_ERR;
}
pc->next = NULL;
}
Pair *SpecialOptIf::call(Pair *args, Environment * &envt,
Continuation * &cont, FrameObj ** &top_ptr) {
RetAddr *ret_info = static_cast<RetAddr*>(*top_ptr);
Pair *ret_addr = ret_info->addr;
if (ret_info->state)
{
if (ret_info->state == empty_list)
{
*top_ptr++ = TO_PAIR(args->cdr)->car;
return ret_addr->next; // Move to the next instruction
}
else
{
Pair *pc = TO_PAIR(ret_addr->car);
Pair *first = TO_PAIR(pc->cdr);
Pair *second = TO_PAIR(first->cdr);
Pair *third = TO_PAIR(second->cdr);
if (TO_PAIR(args->cdr)->car->is_true())
{
second->next = NULL;
// Undo pop and invoke again
top_ptr += 2;
ret_info->state = empty_list;
return second;
}
else if (third != empty_list)
{
third->next = NULL;
// Undo pop and invoke again
top_ptr += 2;
ret_info->state = empty_list;
return third;
}
else