Česky
Kamil Dudka

Flex/Bison based compiler and interpreter written in C++ (using Boost)

File detail

Name:Downloadvm.h [Download]
Location: vyp08 > vyp08-1.0pre1 > src
Size:11.9 KB
Last modification:2009-07-04 19:51

Source code

/*
 * Copyright (C) 2008 Kamil Dudka <xdudka00@stud.fit.vutbr.cz>
 *
 * This file is part of vyp08 (compiler and interpreter of VYP08 language).
 *
 * vyp08 is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 *
 * vyp08 is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with vyp08.  If not, see <http://www.gnu.org/licenses/>.
 */
 
#ifndef VM_H
#define VM_H
 
#include "config.h"
#include "scanner.h"
 
#ifndef BUILDING_DOX
#   include <boost/smart_ptr.hpp>
#   include <iostream>
#   include <set>
#   include <string>
#   include <vector>
#endif
 
/**
 * Value coupled with its type.
 */
struct Value {
    enum VType {
        V_NULL = 0,
        V_BOOL,
        V_INT,
        V_DOUBLE,
        V_STRING
    };
    VType           type;                               ///< value type
 
    bool            boolVal;                            ///< valid only if type == V_BOOL
    int             intVal;                             ///< valid only if type == V_INT
    double          doubleVal;                          ///< valid only if type == V_DOUBLE
    std::string     stringVal;                          ///< valid only if type == V_STRING
 
    Value();                                            ///< initialize null value
};
std::ostream& operator<< (std::ostream &, const Value::VType &);
std::ostream& operator<< (std::ostream &, const Value &);
typedef SHARED_PTR(Value) PValue;
typedef SHARED_PTR(const Value) PConstValue;
 
/**
 * static-only factory for Value objects
 */
class ValueFactory {
    public:
        static PValue create();                         ///< create null Value
        static PValue create(bool);                     ///< create bool Value
        static PValue create(int);                      ///< create int Value
        static PValue create(double);                   ///< create double Value
        static PValue create(const std::string &);      ///< create string Value
    private:
        ValueFactory();
};
 
/**
 * variable base object
 * @note used for lcVar, glVar, arg and function
 */
struct Var {
    std::string     name;                               ///< variable (or arg (or fnc)) name
    Value           value;                              ///< variable (or arg (or fnc)) value
    Token           defined;                            ///< Token which defines this variable
 
    /// true if anybody reads value of the variable (make sense in static context)
    bool            used;
 
    /// true if the value has been already initialized (make sense in run-time)
    bool            initialized;
 
    Var();
};
typedef SHARED_PTR(Var) PVar;
 
/**
 * universal container for variables (or args (or fncs))
 */
class VarSet {
    public:
        VarSet();
        ~VarSet();
 
        /// deep copy of container
        VarSet &operator= (const VarSet &);
 
        bool add(PVar);                                 ///< add variable (or arg (or fnc)) to set
        unsigned size() const;                          ///< number of vars (or args (or fncs))
        PVar operator[] (unsigned);                     ///< return Var object by index
        PVar operator[] (const std::string &);          ///< return Var object by name
 
        /// const to non-const wrapper
        const PVar operator[] (unsigned pos) const {
            return const_cast<VarSet *>(this)
                -> operator[] (pos);
        }
        /// const to non-const wrapper
        const PVar operator[] (const std::string &name) const {
            return const_cast<VarSet *>(this)
                -> operator[] (name);
        }
    private:
        struct Private;
        Private *d;
 
        /// disable copy constructor
        VarSet(const VarSet &);
};
 
/**
 * common data for fnc declaration/definition
 */
struct FncDeclaration {
    FncDeclaration();                                   ///< non-declared void anonymous function
    FncDeclaration(const FncDeclaration &);             ///< deep copy
    FncDeclaration& operator= (const FncDeclaration &); ///< deep copy
    virtual ~FncDeclaration();
 
    /// function declaration/definition as Var object
    Var     self;
 
    /// function arguments (names and values make sense only for FncDefinition objects)
    VarSet  args;
};
/// compare only declaration (!!)
bool operator== (const FncDeclaration &, const FncDeclaration &);
/// compare only declaration (!!)
bool operator!= (const FncDeclaration &, const FncDeclaration &);
 
class Vm;
class CmdList;
typedef SHARED_PTR(CmdList) PCmdList;
 
/**
 * fnc data specific for definition only
 */
struct FncDefinition: public FncDeclaration {
    /// @param vm Pointer to related virtual machine.
    FncDefinition(Vm *vm);
 
    /*
     * mixed (shallow/deep) copy
     * Everything is deep copied except cmdList.
     */
    FncDefinition(const FncDefinition &);
    virtual ~FncDefinition();
 
    Vm              *const vm;                          ///< related virtual machine
    VarSet          vars;                               ///< local variables
    const PCmdList  cmdList;                            ///< function "code"
 
    private:
        /// function assignment is not allowed
        FncDefinition& operator= (const FncDefinition &);
};
/// check if all arguments and local variables are used
bool chkUnused(FncDefinition *);
 
/**
 * universal container for fnc declarations/definitions
 * @attention The container is responsible to delete all successfully added objects.
 */
class FncSet {
    public:
        FncSet();
        ~FncSet();
 
        /**
         * add declaration to container
         * If declaration with the same name exists, check if not differs.
         * @return Return true on success.
         */
        bool addDeclaration(FncDeclaration *);
 
        /**
         * function declaration lookup
         * @return Return pointer to declaration if found, NULL otherwise.
         */
        FncDeclaration* getDeclaration(const std::string &);
 
        /**
         * add definition to container
         * If definition with the same name already exists, return false.
         * If declaration with the same name exists, check if not differs.
         * @return Return true on success.
         */
        bool addDefinition(FncDefinition *);
 
        /**
         * function definition lookup
         * @return Return pointer to definition if found, NULL otherwise.
         */
        FncDefinition* getDefinition(const std::string &);
 
        /// vector of pointers to function definitions
        typedef STD_VECTOR(const FncDefinition *) TVector;
 
        /**
         * collect pointer to all definition stored in container
         * @note useful to find unused functions
         * @return vector of pointers to definitions (not cloned)
         */
        void getAllDefinitions(TVector &);
    private:
        struct Private;
        Private *d;
};
 
/**
 * virtual machine command interface
 * The fundamental object of virtual machine...
 */
class ICmd {
    public:
        virtual ~ICmd() { }
 
        /// execute command in the context of calling function
        virtual bool exec(FncDefinition *) = 0;
 
        /// dump command to stream in human-readable format
        virtual void toStream(std::ostream &) const = 0;
};
typedef SHARED_PTR(ICmd) PCmd;
 
/**
 * sequence of executable virtual machine commands
 * @note Commands are executed in the same order as they are added.
 */
class CmdList: public ICmd {
    public:
        CmdList();
        virtual ~CmdList();
        virtual bool exec(FncDefinition *);
        virtual void toStream(std::ostream &) const;
 
        /// add command to sequence
        void add(PCmd);
    private:
        struct Private;
        Private *d;
};
typedef SHARED_PTR(CmdList) PCmdList;
 
/**
 * stack for Value objects
 * @note also called vmStack in Vm terminology
 */
class ValueStack {
    public:
        ValueStack(Vm *vm);                             ///< related virtual machine
        ~ValueStack();
 
        bool isEmpty() const;                           ///< true if stack is empty
        void push(PValue);                              ///< push Value object to stack
        PValue pop();                                   ///< pop Value object from stack, or NULL if stack is empty
 
        /**
         * high-level push
         * @note may print Token-related error messages
         * @return Return true on success
         */
        bool push(PValue, const Token &);
 
        /**
         * high-level push from variable
         * check if variable is initialized, etc.
         * @note may print Token-related error messages
         * @return Return true on success
         */
        bool pushFromVar(const Var &, const Token &);
 
        /**
         * high-level pop
         * @note may print Token-related error messages
         * @return Return true on success
         */
        bool pop(PValue &, const Token &);
 
        /**
         * high-level pop to variable
         * mark variable as initialized, etc.
         * @note may print Token-related error messages
         * @return Return true on success
         */
        bool popToVar(Var &, const Token &);
 
    private:
        struct Private;
        Private *d;
};
 
/**
 * container for function names being called
 * related to all places where are they called from
 * @note there is some effort to sort calls by occurrence
 */
class CalleeSet {
    public:
        typedef STD_VECTOR(std::string) TStringList;
        typedef STD_VECTOR(Token)       TTokenList;
        CalleeSet();
        ~CalleeSet();
 
        /**
         * add function call to container
         * @param name name of function being called
         * @param tCall token corresponding to function call
         */
        void add(std::string name, Token tCall);
 
        /// return true if given function is called somewhere
        bool isCalled(std::string name);
 
        /// dump all names of function being called to vector of strings
        void getNames(TStringList &);
 
        /// dump all call occurrences for function with given name
        bool getCalls(std::string name, TTokenList &);
 
    private:
        struct Private;
        Private *d;
};
 
/**
 * virtual machine with its environment
 */
struct Vm {
    const std::string           fileName;               ///< input file name (useful for error/info messages)
    VarSet                      glVars;                 ///< global variables
    FncSet                      fncSet;                 ///< all function declarations/definitions
    ValueStack                  vmStack;                ///< common value stack (the workspace for commands)
    CalleeSet                   calleeSet;              ///< container for function names being called (and occurrences of their calls)
    int                         callDepth;              ///< current function call depth (make sense in run-time)
    int                         maxCallDepth;           ///< function call depth limit - feel free to change it to any (positive) number
    static const int            DEF_MAX_CALL_DEPTH = 1024;
 
    Vm(std::string fileName_):
        fileName(fileName_),
        vmStack(this),
        callDepth(0),
        maxCallDepth(DEF_MAX_CALL_DEPTH)
    {
    }
};
 
/**
 * virtual machine runner
 * It checks for all pre-runtime errors/warnings during initialization
 */
class VmRunner: public IErrorSensitive {
    public:
        VmRunner(Vm *vm);                               ///< virtual machine to run
        virtual ~VmRunner();
        virtual bool hasError() const;                  ///< true if any error detected
        bool run();                                     ///< run! machine, return true on success
    private:
        struct Private;
        Private *d;
};
 
#endif /* VM_H */