#ifndef ACTOR_HPP__ #define ACTOR_HPP__ /** * \file actor.hpp * \author Mason Smith * This file contains the Actor class, which holds * the instruction set and global state of a BMD program, * as well as the virtual machine which runs the program. */ #include #include #include #include #include #include "instr.hpp" using std::string; using std::vector; using std::map; using std::multimap; using std::ostream; using boost::shared_ptr; using boost::weak_ptr; namespace BMD { /**** forward declarations ****/ class VM; class assert_test; /** structure that contains information about each function */ struct function_info { function_info(); function_info(int _addr, uint _num_args); int addr; uint num_args; }; /**** typedefs ****/ typedef map LabelMap; typedef map FunctionMap; typedef multimap > AssertionMap; typedef unsigned int uint; /** * An actor is an independent agent with machine code and global state, * as well as a virtual machine that it runs on. */ class Actor { public: Actor(unsigned int num_fields = 0); Actor(string filename, unsigned int num_fields = 0); //! Loads the instructions from a file void load_from_file(string filename); //! Returns the address associated with a label int get_label_address(string label, bool use_functions = true); //! returns the function with the given name function_info get_function(string name); //! grab the instruction at a particular address InstructionRef get_instruction(int addr); int get_num_instructions() const { return instructions.size(); } //! check the validity of the instruction pointer bool is_valid_ip(int ip) const { return (ip < (int)instructions.size()) and (ip >= 0); } /**** testing only ****/ void add_instruction(InstructionRef in); void add_instruction(Instruction* in) { add_instruction(InstructionRef(in)); } void add_label(string& str, int addr); bool should_throw_error() const { return should_throw; } /*** END testing only ****/ //! checks the assertions at the current ip, throwing errors if any fail void validate_assertions(); /* field accessors */ Value get_field(int i) const { return fields.at(i); } void set_field(int i, Value f) { fields[i] = f; } void alloc_fields(unsigned int num) { fields.resize(num); } void set_linked_actor(shared_ptr i) { linked_actor = weak_ptr(i); } shared_ptr get_linked_actor() const { return linked_actor.lock(); } /**** VM-linked operations ****/ void set_debug_output(bool debug); void run(); void run_with_assertions(); bool is_running() const; Value call_function(string func_name, const vector& args, bool debug = false); VM* get_vm() const { return vm; } /** Flags the VM as currently running, but does *not* start any instructions. */ void start(); ~Actor(); static const int NO_LABEL; private: //! remove all instructions and other data void clear(); bool is_comment(string line); //< returns true if a line is a comment bool is_label(string line); //< returns true if a line is a label bool is_execution_signal(string line); // parse an execution signal void parse_execution_signal(string line, int op_num); //! Parse and create a single instruction Instruction* parse_instruction(string instr); //! parse a nonnegative integer unsigned int parse_nonnegative_integer(string arg, string name); //! Parse a numeric value Value parse_numeric_value(string s); //! Parse a generic argument Value parse_value(string s); // list of instructions for the actor vector instructions; // label map LabelMap label_map; // function map FunctionMap function_map; // name of the initialization function string init_func; // global fields vector fields; // assertions AssertionMap assertions; // actor link weak_ptr linked_actor; // indicates whether the actor should throw bool should_throw; // underlying virtual machine VM* vm; }; typedef shared_ptr ActorRef; } #endif