Exemple #1
0
void NodeTree::handleException(NodeID nodeID, const NodeSocketTracer& tracer)
{
    // Exception dispatcher pattern
    try
    {
        _executeListDirty = true;
        throw;
    }
    catch(ExecutionError&)
    {
        // Dummy but a must - if not std::exception handler would catch it
        throw;
    }
    catch(BadConnectionException& ex)
    {
        if (tracer.isLastOutput())
            // Means node tried to acquired socket
            // with different type than declared in config
            throw BadConfigException();
        ex.node = tracer.lastNode();
        ex.socket = tracer.lastSocket();
        throw;
    }
    catch(cv::Exception& ex)
    {
        throw ExecutionError(nodeName(nodeID), nodeTypeName(nodeID), 
            std::string("OpenCV exception - ") + ex.what());
    }
    catch(std::exception& ex)
    {
        throw ExecutionError(nodeName(nodeID), nodeTypeName(nodeID), ex.what());
    }
}
Exemple #2
0
/** 
*	Checks whether the top 2 elements are of type boolean and then performs the OR operation on them. The boolean result replaces the result on the top of the stack.
*	@return			none
*	@param stack	the machine on which the addition is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Or::execute(StackMachine *stack) 
{
	// check if the stack contains at least two entries
	if(stack->fSP < 1)
		throw ExecutionError("instruction or: requires 2 stackelements to be present.");
		
	StackBoolean p1;
	
	if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
		throw ExecutionError("instruction or: SP does not point to element of type boolean.");
	if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
		throw ExecutionError("instruction or: SP - 1 does not point to element of type boolean.");

	
	// actual or-operation
	stack->fStore[stack->fSP - 1]->ori(stack->fStore[stack->fSP]);
	
	// SP := SP - 1
	delete stack->fStore[stack->fSP];
	stack->fStore[stack->fSP] = 0;
	stack->fStore.pop_back();
	--stack->fSP;
	
	// adding cost of this instruction
	stack->fTime.count("or");

}
Exemple #3
0
/** 
*	Saves the PC at STORE[MP+4] and sets the PC to the right startaddress for the procedure
*	@return			none
*	@param stack	the machine on which the operation is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Cupi::execute(StackMachine *stack)
{	
	/*
	if(stack->fMP + 4 > stack->fSP)
	{
		for(int i = 0; i < stack->fMP + 4 - stack->fSP; ++i)
		{
			stack->fStore.push_back(new StackElement());
			++stack->fSP;
		}
	}
	else
	{
		delete stack->fStore[stack->fMP + 4];
		stack->fStore[stack->fMP + 4] = 0;
	}
	*/
	
	stack->fStore[stack->fMP + 4] = new StackAddress(stack->fPC);
	
	if(stack->base(fP, stack->fStore[stack->fMP + 2]->getValue()) + fQ > stack->fSP)
	{
		throw ExecutionError("instruction cupi: trying to access a memorylocation above STORE[SP]");
	}
	stack->fPC = stack->fStore[stack->base(fP, stack->fStore[stack->fMP + 2]->getValue()) + fQ]->getValue();
	
	// adding cost of this instruction
	stack->fTime.count("cupi");
}
Exemple #4
0
/** 
*	Breaks down the stack and sets all internal variables of the stackmachine back to their previous state
*	@return			none
*	@param stack	the machine on which the addition is performed (StackMachine*)
*	@exception		none
*/
void Retp::execute(StackMachine *stack)
{	
	StackAddress p;
	if((typeid(p) != typeid(*(stack->fStore[stack->fMP + 2]))
		|| (typeid(p) != typeid(*(stack->fStore[stack->fMP + 3])))
		|| (typeid(p) != typeid(*(stack->fStore[stack->fMP + 4])))))
	{
		throw ExecutionError("instruction retp: stackframe has been compromised.");
	}
	
	int oldSP = stack->fSP;
	
	// proper procedure with no results
	stack->fSP = stack->fMP - 1;
	
	// return branch
	stack->fPC = stack->fStore[stack->fMP + 4]->getValue();
	
	// restore EP
	stack->fEP = stack->fStore[stack->fMP + 3]->getValue();

	// dynamic link
	stack->fMP = stack->fStore[stack->fMP + 2]->getValue();
	
	for(int i = oldSP; i > stack->fSP; --i)
	{
		delete stack->fStore[i];
		stack->fStore.pop_back();
	}
	
	// adding cost of this instruction
	stack->fTime.count("retp");

}
Exemple #5
0
Value Interpreter::handleFunction(const SourceLocation &sourceLocation, const Value &value, Stack &stack, Bindings &bindings)
{
	unsigned argc = getArgumentCount(value);
	if(stack.size() < argc + 1)
	{
		throw CompilerBug("Need " + str(argc + 1) + " values on stack to call function, but only have " + str(stack.size()));
	}

	Value top = pop(stack);
	if(!top.isFunction())
	{
		throw ExecutionError(sourceLocation, "Call instruction expects top of the stack to be functional value, but got: " + str(top));
	}

	Arguments arguments;
	while(argc --> 0)
	{
		arguments.push_back(pop(stack));
	}

	const Function &function = top.function();
	try
	{
		CallContext callContext(&globals_, arguments, this);
		return function.call(callContext);
	}
	catch (RaspError &error)
	{
		error.buildStackTrace(" at function: " + function.name(), function.sourceLocation());
		throw;
	}
}
Exemple #6
0
/** 
*	Checks the contents of the stack and then performs the addition.
*	@return			none
*	@param stack	the machine on which the addition is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Add::execute(StackMachine *stack) 
{
	// check if the stack contains at least two entries
	if(stack->fSP < 1)
		throw ExecutionError("instruction add: requires 2 stackelements to be present.");
		
	switch(fType)
	{
		case integer:
		{
			StackInteger p1;

			// check if the two uppermost stackentries are of type integer
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction add: SP does not point to element of type integer.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction add: SP - 1 does not point to element of type integer.");

			break;
		}	
		case real:
		{
			StackReal p1;
			// check if the two uppermost stackentries are of type real
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction add: SP does not point to element of type real.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction add: SP - 1 does not point to element of type real.");
			break;
		}
		default:
			cerr << "operation not supported for this type" << endl;
	}
	
	// actual addition
	stack->fStore[stack->fSP - 1]->add(stack->fStore[stack->fSP]);
	
	// SP := SP - 1
	delete stack->fStore[stack->fSP];
	stack->fStore[stack->fSP] = 0;
	stack->fStore.pop_back();
	--stack->fSP;
	
	// adding cost of this instruction
	stack->fTime.count("add");
}
Exemple #7
0
/** 
*	Reads from stdin and creates an appropriate StackElement-derived-class
*	@return			none
*	@param stack	the machine on which the operation is performed (StackMachine*)
*	@exception		none
*/
void In::execute(StackMachine *stack) 
{	
	switch(fType)
	{
		case integer:
		{
			int inputvalue;
			cin >> inputvalue;
			stack->fStore.push_back(new StackInteger(inputvalue));
			break;
		}	
		case real:
		{
			double inputvalue;
			cin >> inputvalue;
			stack->fStore.push_back(new StackReal(inputvalue));
			break;
		}
		case character:
		{
			char inputvalue;
			cin >> inputvalue;
			stack->fStore.push_back(new StackCharacter(inputvalue));
			break;
		}
		case boolean:
		{
			bool inputvalue;
			cin >> inputvalue;
			stack->fStore.push_back(new StackBoolean(inputvalue));
			break;
		}
		case address:
		{
			throw ExecutionError("instruction in: input of address at runtime is not allowed");
		}
	}
	
	// SP := SP + 1
	++stack->fSP;
	
	// adding cost of this instruction
	stack->fTime.count("in");

}
Exemple #8
0
/** 
*	Checks whether the element at STORE[SP] is of the right type and then increments it
*	@return			none
*	@param stack	the machine on which the operation is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Inc::execute(StackMachine *stack)
{
	// check if the stack contains at least one entry
	
	if(stack->fSP < 0)
		throw ExecutionError("instruction inc: requires 1 stackelement to be present.");
		
	switch(fType)
	{
		case integer:
		{
			StackInteger p1;

			// check if the  uppermost stackentry is of type integer
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction inc: SP does not point to element of type integer.");

			break;
		}	
		case real:
		{
			StackReal p1;
			// check if the  uppermost stackentry is of type real
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction inc: SP does not point to element of type real.");

			break;
		}
		case boolean:
		{
			StackBoolean p1;
			// check if the  uppermost stackentry is of type boolean
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction inc: SP does not point to element of type boolean.");

			break;
		}
		case character:
		{
			StackCharacter p1;
			// check if the  uppermost stackentriy is of type character
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction inc: SP does not point to element of type character.");

			break;
		}
		case address:
		{
			StackAddress p1;
			// check if the uppermost stackentry is of type address
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction inc: SP does not point to element of type address.");

			break;
		}
	}
	
	// actual increment
	stack->fStore[stack->fSP]->inc(fP);
	
	// adding cost of this instruction
	stack->fTime.count("inc");

}
Exemple #9
0
/** 
*	Checks whether the indicated type is the same as the loaded type and then loads it.
*	@return			none
*	@param stack	the machine on which the operation is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Ldc::execute(StackMachine *stack)
{
	switch(fType)
	{
		case integer:
		{
			StackInteger p1;

			// check if constant is of type integer
			if(typeid(p1) != typeid(*fConstant))
			{
				throw ExecutionError("instruction ldc: type of constant is not of type integer.");
			}
			else
			{
				stack->fStore.push_back(new StackInteger(*(dynamic_cast<StackInteger*>(fConstant))));
			}
				
			break;
		}	
		case real:
		{
			StackReal p1;
			// check if constant is of type real
			if(typeid(p1) != typeid(*fConstant))
			{
				throw ExecutionError("instruction ldc: type of constant is not of type real.");
			}
			else
			{
				stack->fStore.push_back(new StackReal(*(dynamic_cast<StackReal*>(fConstant))));
			}

			break;
		}
		case boolean:
		{
			StackBoolean p1;
			
			// check if constant is of type boolean
			if(typeid(p1) != typeid(*fConstant))
			{
				throw ExecutionError("instruction ldc: type of constant is not of type boolean.");
			}
			else
			{
				stack->fStore.push_back(new StackBoolean(*(dynamic_cast<StackBoolean*>(fConstant))));
			}

			break;
		}
		case character:
		{
			StackCharacter p1;
			
			// check if constant is of type character
			if(typeid(p1) != typeid(*fConstant))
			{
				throw ExecutionError("instruction ldc: type of constant is not of type character.");
			}
			else
			{
				stack->fStore.push_back(new StackCharacter(*(dynamic_cast<StackCharacter*>(fConstant))));
			}

			break;
		}
		case address:
		{
			StackAddress p1;

			// check if constant is of type address
			
			if(typeid(p1) != typeid(*fConstant))
			{
				throw ExecutionError("instruction ldc: type of constant is not of type address.");
			}
			else
			{
				stack->fStore.push_back(new StackAddress(*(dynamic_cast<StackAddress*>(fConstant))));
			}

			break;
		}
	}
	
	// fSP = fSP + 1
	++stack->fSP;
	
	// adding cost of this instruction
	stack->fTime.count("ldc");

}
Exemple #10
0
/** 
*	Checks whether the 2 uppermost stackpositions are of the right type and then performs the neq-operation.
*	@return			none
*	@param stack	the machine on which the operation is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Neq::execute(StackMachine *stack) 
{
	// check if the stack contains at least two entries
	if(stack->fSP < 1)
		throw ExecutionError("instruction neq: requires 2 stackelements to be present.");

	switch(fType)
	{
		case integer:
		{
			StackInteger p1;
			// check if the two uppermost stackentries are of type integer
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction neq: SP does not point to element of type integer.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction neq: SP - 1 does not point to element of type integer.");

			break;
		}	
		case real:
		{
			StackReal p1;
			// check if the two uppermost stackentries are of type real
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction neq: SP does not point to element of type real.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction neq: SP - 1 does not point to element of type real.");
			break;
		}
		case boolean:
		{
			StackBoolean p1;
			// check if the two uppermost stackentries are of type real
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction neq: SP does not point to element of type boolean.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction neq: SP - 1 does not point to element of type boolean.");
			break;
		}
		case character:
		{
			StackCharacter p1;
			// check if the two uppermost stackentries are of type real
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction neq: SP does not point to element of type character.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction neq: SP - 1 does not point to element of type character.");
			break;
		}
		case address:
		{
			StackAddress p1;
			// check if the two uppermost stackentries are of type real
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
				throw ExecutionError("instruction neq: SP does not point to element of type address.");
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP - 1])))
				throw ExecutionError("instruction neq: SP - 1 does not point to element of type address.");
			break;
		}

	}
		
	// compare
	StackBoolean *result;
	if(*(stack->fStore[stack->fSP - 1]) != *(stack->fStore[stack->fSP]))
		result = new StackBoolean(true);
	else
		result = new StackBoolean(false);
		
	// remove operands
	delete stack->fStore[stack->fSP];
	stack->fStore[stack->fSP] = 0;
	delete stack->fStore[stack->fSP - 1];
	stack->fStore[stack->fSP - 1] = 0;
	stack->fStore.pop_back();
	stack->fStore.pop_back();
	--stack->fSP;

	// put result on top of stack
	stack->fStore.push_back(result);
	
	// adding cost of this instruction
	stack->fTime.count("neq");

}
Exemple #11
0
  void Executor::run() {
    int status;
    bool firstExec = false;

    /* construct arguments vector */
    std::vector<char*> cargv;
    std::vector<std::string> eargv;
    cargv.push_back((char*)command.c_str());
    if (argv.ptr() != Py_None) {
      int l = len(argv);
      for (int i=0;i<l;i++) {
        extract<std::string> str(argv[i]);
        eargv.push_back(str());
        cargv.push_back((char*)eargv[i].c_str());
      }
    }
    cargv.push_back(NULL);
	
    /* convert filenames into C strings */
    const char* file_input = NULL;
    const char* file_output = NULL;
    const char* file_errput = NULL;
    if (input.ptr() != Py_None) {
      extract<std::string> str(input);
      file_input = str().c_str();
      eargv.push_back(str);
    }
    if (output.ptr() != Py_None) {
      extract<std::string> str(output);
      file_output = str().c_str();
      eargv.push_back(str);
    }
    if (errput.ptr() != Py_None) {
      extract<std::string> str(errput);
      file_errput = str().c_str();
      eargv.push_back(str);
    }

    /* zapamietujemy startowy rusage */
    if (getrusage(RUSAGE_CHILDREN, &startusage)) {
      throw ExecutionError("Could not get starter rusage");
    }

    if ((proc = vfork()) == 0) {

      /* zamykamy wejscia / wyjscia */
      /*if (data->flags & PLF_CLOSESTDIN)
        if (close(STDIN_FILENO) != 0)
        _exit(2);

        if (data->flags & PLF_CLOSESTDOUT)
        if (close(STDOUT_FILENO) != 0)
        _exit(2);

        if (data->flags & PLF_CLOSESTDERR)
        if (close(STDERR_FILENO) != 0)
        _exit(2);*/

      /*  przekierowanie wyjscia / wejscia */
      int fd;
      if (file_input) {
        fd = open(file_input, O_RDONLY);
        if (fd < 0) _exit(2);
        dup2(fd, STDIN_FILENO);
      }
      if (file_output) {
        fd = open(file_output, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR);
        if (fd < 0) _exit(2);
        dup2(fd, STDOUT_FILENO);
      }
      if (file_errput > 0) {
        fd = open(file_errput, O_RDWR | O_CREAT | O_TRUNC, S_IWUSR | S_IRUSR);
        if (fd < 0) _exit(2);
        dup2(fd, STDERR_FILENO);
      }

      /* ustawiamy limit pamieci wirtualnej jesli byl wskazany */
      if (memoryLimit != -1) {
        struct rlimit vmlimit;
        if (getrlimit(RLIMIT_AS, &vmlimit) != 0) {
          _exit(1);
        }
        vmlimit.rlim_cur = memoryLimit;
        if (setrlimit(RLIMIT_AS, &vmlimit) != 0) {
          _exit(1);
        }
      }

      // TODO: mozna jeszcze ustawiac limity na stos

      /* limit wyjscia (laczna wielkosc wszystkich plikow po ktorych piszemy) */
      if (outputLimit != -1) {
        struct rlimit foutlimit;
        if (getrlimit(RLIMIT_FSIZE, &foutlimit) != 0) {
          _exit(3);
        }
        foutlimit.rlim_cur = outputLimit;
        if (setrlimit(RLIMIT_FSIZE, &foutlimit) != 0) {
          _exit(3);
        }
      }

      /* ustawiamy limit czasu wkonania (jesli byl wybrany) */
      if (timeLimit != -1) {
        struct rlimit tmlimit;
        if (getrlimit(RLIMIT_CPU, &tmlimit) != 0) {
          _exit(4);
        }
        tmlimit.rlim_cur = (timeLimit + 1000) / 1000;
        if (setrlimit(RLIMIT_CPU, &tmlimit) != 0) {
          _exit(4);
        }
      }

      /* ten proces bedzie sledzony: */
      if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0) {
        _exit(5);
      }

      /* wywolujemy program */
      execv(command.c_str(), &(cargv.front()));
      _exit(3);
    } else if (proc > 0) {

      int waitflags = 0;
      if (flags & PYZA_TRACE_CHILDS) {
        waitflags = WUNTRACED | __WALL;
        ptrace(PTRACE_SETOPTIONS, proc, NULL, PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE
               | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACEEXIT);
      }
		
      try {
        while (1) {
          /* czekamy na kolejne zatrzymanie przez ptrace */
          if ((pid = wait4(-1, &status, waitflags, 0)) <= 0) {
            throw ExecutionError("Wait fault");
          }

          if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
            /* pobieramy wartosci rejestrow */
            if (ptrace(PTRACE_GETREGS, pid, NULL, &regs) != 0) {
              throw ExecutionError("Ptrace getregs fault");
            }
					
            if (!firstExec) {
              /* czekamy na pierwszy execv */
              if (regs.ORIG_REG == SYS_execve)
                firstExec = true;
            } else {
              if (callback.ptr() != Py_None)
                callback(regs.ORIG_REG);
            }

          } else if (WIFSTOPPED(status)) {
            int stopsig = WSTOPSIG(status);
            if (stopsig == SIGXCPU) {
              throw TimeLimitError();
            } else if (stopsig == SIGXFSZ) {
              throw RuntimeError("OutputSizeLimit");
            } else if (stopsig == SIGSEGV) {
              throw RuntimeError("SIGSEGV");
            } else if (stopsig == SIGFPE) {
              throw RuntimeError("SIGFPE");
            }
          } else if (WIFEXITED(status)) {
            if (!firstExec) {
              throw ExecutionError("Initial error");
            }
            returnCode = WEXITSTATUS(status);
            if (pid == proc) break;
            else continue;
          } else { /* signalled */
            throw RuntimeError("SIGNALLED");
          }
				
          /* puszczamy proces sledzony dalej */
          if (ptrace(PTRACE_SYSCALL, pid, NULL, NULL) != 0) {
            throw ExecutionError("Ptrace syscall fault");
          }
        }
      } catch (const TimeLimitError& ex) {
        cleanup();
        throw ex;
      }
      catch (const RuntimeError& ex) {
        cleanup();
        throw ex;
      } catch (const ExecutionError& ex) {
        cleanup();
        throw ex;
      } catch(const error_already_set& ex) {
        cleanup();
        throw ex;
      }
      cleanup();
      if (timeLimit > -1 && executionTime > timeLimit) {
        throw TimeLimitError();
      }
    } else {
      /* nie moze wykonac fork'a */
      throw ExecutionError("Fork error");
    }

    return;
  }
Exemple #12
0
Value Interpreter::exec(const InstructionList &instructions, Bindings &bindings)
{
	Stack stack;
	ClosureValues closureValues;

	for(InstructionList::const_iterator it = instructions.begin() ; it != instructions.end() ; ++it)
	{
		Instruction::Type type = it->type();
		const Value &value = it->value();
		switch(type)
		{
		case Instruction::PUSH:
			if(settings_.trace)
			{				
				std::cout << "DEBUG: " << it->sourceLocation() << " push " << value << '\n';
			}
			stack.push_back(value);
			break;
		case Instruction::CALL:
			{
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " call " << value << '\n';
				}
				Value result = handleFunction(it->sourceLocation(), value, stack, bindings);
				stack.push_back(result);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " return value " << result << '\n';
				}
			}
			break;
		case Instruction::JUMP:
			{
				int instructionsToSkip = getInstructionsToSkip(type, value);
				int remaining = instructions.end() - it;
				if(remaining < instructionsToSkip)
				{
					throw CompilerBug("insufficient instructions available to skip! (remaining: " + str(remaining) + " < instructionsToSkip: " + str(instructionsToSkip) + ")");
				}

				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " jumping back " << instructionsToSkip << '\n';
				}
				it += instructionsToSkip;
			}
			break;
		case Instruction::LOOP:
			{
				int instructionsToSkip = getInstructionsToSkip(type, value);
				int instructionsAvailable = instructions.size(); // Note: signed type is important!
				if(instructionsAvailable < instructionsToSkip)
				{
					throw CompilerBug("insufficient instructions available to loop! (instructionsToSkip: " + str(instructionsToSkip) + " > instructions.size(): " + str(instructions.size()) + ")");
				}

				if(settings_.trace)
				{				
					std::cout << "DEBUG: " << it->sourceLocation() << " looping back " << instructionsToSkip << " instructions\n";
				}
				it -= instructionsToSkip;
			}
			break;
		case Instruction::CLOSE:
			{
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " close " << value << '\n';
				}
				Value result = handleClose(value, stack, closureValues, bindings);
				stack.push_back(result);
			}
			break;
		case Instruction::COND_JUMP:
			{
				if(stack.empty())
				{
					throw CompilerBug("empty stack when testing conditional jump");
				}
				int instructionsToSkip = getInstructionsToSkip(type, value);
				int remaining = instructions.end() - it;
				if(remaining < instructionsToSkip)
				{
					throw CompilerBug("insufficient instructions available to skip! (remaining: " + str(remaining) + " < instructionsToSkip: " + str(instructionsToSkip) + ")");
				}

				Value top = pop(stack);
				if(settings_.trace)
				{				
					std::cout << "DEBUG: " << it->sourceLocation() << " jumping back " << instructionsToSkip << " if " << top << '\n';
				}

				if(top.isFalsey())
				{
					it += instructionsToSkip;
				}
			}
			break;
		case Instruction::REF_LOCAL:
			handleRef(Bindings::Local, value, stack, bindings);
			if(settings_.trace)
			{
				std::cout << "DEBUG: " << it->sourceLocation() << " local ref '" << value.string() << "' is " << stack.back() << '\n';
			}
			break;
		case Instruction::INIT_LOCAL:
			{
				const Value &intialisedValue = handleInit(Bindings::Local, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " local init '" << value.string() << "' to " << intialisedValue << '\n';
				}
			}
			break;
		case Instruction::ASSIGN_LOCAL:
			{
				const Value &assignedValue = handleAssign(Bindings::Local, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " local assign '" << value.string() << "' to " << assignedValue << '\n';
				}
			}
			break;
		case Instruction::REF_GLOBAL:
			handleRef(Bindings::Global, value, stack, bindings);
			if(settings_.trace)
			{
				std::cout << "DEBUG: " << it->sourceLocation() << " global ref '" << value.string() << "' is " << stack.back() << '\n';
			}
			break;
		case Instruction::INIT_GLOBAL:
			{
				const Value &intialisedValue = handleInit(Bindings::Global, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " global init '" << value.string() << "' to " << intialisedValue << '\n';
				}
			}
			break;
		case Instruction::ASSIGN_GLOBAL:
			{
				const Value &assignedValue = handleAssign(Bindings::Global, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " global assign '" << value.string() << "' to " << assignedValue << '\n';
				}
			}
			break;
		case Instruction::REF_CLOSURE:
			handleRef(Bindings::Closure, value, stack, bindings);
			if(settings_.trace)
			{
				std::cout << "DEBUG: " << it->sourceLocation() << " closure ref '" << value.string() << "' is " << stack.back() << '\n';
			}
			break;
		case Instruction::INIT_CLOSURE:
			{
				Identifier identifier = Identifier(value.string());
				Bindings::ValuePtr &binding = bindings.getPointer(identifier);
				closureValues.push_back(ClosedNameAndValue(identifier, binding));
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " closure init '" << value.string() << "' is " << *binding << '\n';
				}
			}
			break;
		case Instruction::ASSIGN_CLOSURE:
			{
				const Value &assignedValue = handleAssign(Bindings::Closure, value, stack, bindings);
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " closure assign '" << value.string() << "' to " << assignedValue << '\n';
				}
			}
			break;
		case Instruction::MEMBER_ACCESS:
			{
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " member access " << value << '\n';
				}
				assert(value.isString());
				const std::string &memberName = value.string();

				Value top = pop(stack);
				if(!top.isObject())
				{
					throw ExecutionError(it->sourceLocation(), "Member access instruction requires an object but got " + str(top));
				}
				const Value::Object &object = top.object();
				Value::Object::const_iterator memberIterator = object.find(memberName);
				if (memberIterator == object.end())
				{
					throw ExecutionError(it->sourceLocation(), "Unknown member name " + memberName + " for " + str(top));
				}
				if(settings_.trace)
				{
					std::cout << "DEBUG: " << it->sourceLocation() << " member access " << value.string() << "." << memberName << " was " << memberIterator->second << '\n';
				}
				stack.push_back(memberIterator->second);
			}
			break;
		default:
			throw CompilerBug("unhandled instruction type: " + str(type));
		}

		if (settings_.trace)
		{
			if (stack.empty())
			{
				std::cout << "Stack is empty\n";
			}
			else
			{
				std::cout << "Stack contains " << stack.size() << " entries:\n";
				int index = 0;
				for(Stack::const_iterator it = stack.begin() ; it != stack.end() ; ++it)
				{
					++index;
					std::cout << index << ":  " << *it << '\n';
				}
			}

			if (closureValues.empty())
			{
				std::cout << "closureValues is empty\n";
			}
			else
			{
				std::cout << "closureValues contains " << closureValues.size() << " entries:\n";
				int index = 0;
				for(const ClosedNameAndValue &closedValue: closureValues)
				{
					++index;
					std::cout << index << ":  " << closedValue.first << " -> " << *closedValue.second << " @ " << closedValue.second << '\n';
				}
			}
		}
	}
	
	return stack.empty() ? Value::nil() : pop(stack);
}
Exemple #13
0
/** 
*	Checks the contents of the stack and then performs the store operation.
*	@return			none
*	@param stack	the machine on which the instruction is performed (StackMachine*)
*	@exception		ExecutionError
*/
void Sto::execute(StackMachine *stack)
{
	StackAddress p;
	
	if(stack->fSP < 1)
		throw ExecutionError("instruction sto: at least 2 stackelements are required for this operation");
		
	if(typeid(p) != typeid(*(stack->fStore[stack->fSP - 1])))
		throw ExecutionError("instruction sto: type pointed to by SP - 1 is not of type address.");
				
	switch(fType)
	{
		case integer:
		{
			StackInteger p1;

			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
			{
				throw ExecutionError("instruction sto: type pointed to by SP is not of type integer.");
			}
				
			break;
		}	
		case real:
		{
			StackReal p1;

			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
			{
				throw ExecutionError("instruction sto: type pointed to by SP is not of type real.");
			}

			break;
		}
		case boolean:
		{
			StackBoolean p1;
			
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
			{
				throw ExecutionError("instruction sto: type pointed to by SP is not of type boolean.");
			}

			break;
		}
		case character:
		{
			StackCharacter p1;
			
			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
			{
				throw ExecutionError("instruction sto: type pointed to by SP is not of type character.");
			}


			break;
		}
		case address:
		{
			StackAddress p1;

			if(typeid(p1) != typeid(*(stack->fStore[stack->fSP])))
			{
				throw ExecutionError("instruction sto: type pointed to by SP is not of type address.");
			}
				
			break;
		}
	}
	
	if(stack->fStore[stack->fSP - 1]->heapAddress())
	{
		if(stack->fStore[stack->fSP - 1]->getValue() < stack->fNP)
		{
			throw ExecutionError("instruction sto: invalid heap address.");
		}
		else
		{
			delete stack->fHeap[-stack->fStore[stack->fSP - 1]->getValue() - 1];
			stack->fHeap[-stack->fStore[stack->fSP - 1]->getValue() - 1] = stack->fStore[stack->fSP];
		}
	}
	else
	{
		if(stack->fStore[stack->fSP - 1]->getValue() > stack->fSP - 2) 	
		{
			// -2 because the SP will be decreased by 2 as a result of this operation
			
			throw ExecutionError("instruction sto: invalid stack address.");
		}
		else
		{
			delete stack->fStore[stack->fStore[stack->fSP - 1]->getValue()];
			stack->fStore[stack->fStore[stack->fSP - 1]->getValue()] = stack->fStore[stack->fSP];
		}
	}
	
	stack->fStore.pop_back();
	delete stack->fStore[stack->fSP - 1];
	stack->fStore[stack->fSP - 1] = 0;
	stack->fStore.pop_back();

	stack->fSP -= 2;
	
	// adding cost of this instruction
	stack->fTime.count("sto");
}