/*=============================================================================
    Copyright (c) 2001-2010 Joel de Guzman

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
=============================================================================*/
///////////////////////////////////////////////////////////////////////////////
//
//  Not a calculator anymore, right? :-)
//
//  [ JDG April 10, 2007 ]       spirit2
//
///////////////////////////////////////////////////////////////////////////////
#include "definitions.hpp"
#include "main.hpp"

///////////////////////////////////////////////////////////////////////////////
//  Main program
///////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
    char const* filename;
    if (argc > 1)
    {
        filename = argv[1];
    }
    else
    {
        std::cerr << "Error: No input file provided." << std::endl;
        return 1;
    }

    std::ifstream in(filename, std::ios_base::in);

    if (!in)
    {
        std::cerr << "Error: Could not open input file: "
            << filename << std::endl;
        return 1;
    }

    std::string source_code; // We will read the contents here.
    in.unsetf(std::ios::skipws); // No white space skipping!
    std::copy(
        std::istream_iterator<char>(in),
        std::istream_iterator<char>(),
        std::back_inserter(source_code));

    typedef std::string::const_iterator iterator_type;
    typedef program<iterator_type> program;

    vmachine mach;              //  Our virtual machine
    code_t code;      //  Our VM code
    program prog(code);         //  Our grammar definition

    if (::compile(prog, source_code))
    {
        std::string fmain("main");
        std::string::iterator fbegin = fmain.begin();
        function_info* f = prog.functions.lookup->find(fbegin, fmain.end());
        if (f == 0)
        {
            std::cerr << "Error: main function not defined" << std::endl;
            return 1;
        }

	//std::cout << "nvars=" << prog.get_nvars() << std::endl;
				
        int nargs = argc-2;
        if (f->arity != nargs)
        {
            std::cerr << "Error: main function requires " << f->arity << " arguments." << std::endl;
            std::cerr << nargs << "supplied." << std::endl;
            return 1;
        }

        for (int i = 0; i < nargs; ++i)
            mach.stack[i] = boost::lexical_cast<operand_t>(argv[i+2]);

        float r = mach.execute(
            code                                // code
          , code.begin() + f->address           // pc
          , mach.stack.begin()                  // frame_ptr
        );

//        std::cout << "-------------------------\n";
//        std::cout << "Result: " << r << std::endl;
//        std::cout << "-------------------------\n\n";
    }

    return 0;
}
