Flex/Bison based compiler and interpreter written in C++ (using Boost)
File detail
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 */