$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r69337 - trunk/libs/spirit/example/qi/compiler_tutorial/calc7
From: joel_at_[hidden]
Date: 2011-02-27 11:30:54
Author: djowel
Date: 2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
New Revision: 69337
URL: http://svn.boost.org/trac/boost/changeset/69337
Log:
almost working
Text files modified: 
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp           |     5 +                                       
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp      |   102 +++++++++++++++++++++++++++++++++++---- 
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp      |    41 +++++++++++++--                         
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp    |     2                                         
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp          |    75 ++++++++++++++--------------            
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp |     2                                         
   trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp            |     2                                         
   7 files changed, 171 insertions(+), 58 deletions(-)
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -10,6 +10,7 @@
 #include <boost/config/warning_disable.hpp>
 #include <boost/variant/recursive_variant.hpp>
 #include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
 #include <list>
 
 namespace client { namespace ast
@@ -78,6 +79,10 @@
             assignment>
         >
     statement;
+
+    // print functions for debugging
+    inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+    inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
 }}
 
 BOOST_FUSION_ADAPT_STRUCT(
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -8,36 +8,66 @@
 #include "vm.hpp"
 #include <boost/foreach.hpp>
 #include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <iostream>
+#include <string>
 
 namespace client
 {
-    void compiler::op(int a) const
+    void program::op(int a)
     {
         code.push_back(a);
     }
 
-    void compiler::op(int a, int b) const
+    void program::op(int a, int b)
     {
         code.push_back(a);
         code.push_back(b);
     }
 
-    void compiler::op(int a, int b, int c) const
+    void program::op(int a, int b, int c)
     {
         code.push_back(a);
         code.push_back(b);
         code.push_back(c);
     }
 
+    int const* program::find_var(std::string const& name) const
+    {
+        std::map<std::string, int>::const_iterator i = variables.find(name);
+        if (i == variables.end())
+            return 0;
+        return &i->second;
+    }
+
+    void program::add_var(std::string const& name)
+    {
+        variables[name] = variables.size();
+    }
+
+    void program::print_variables(std::vector<int> const& stack) const
+    {
+        typedef std::pair<std::string, int> pair;
+        BOOST_FOREACH(pair const& p, variables)
+        {
+            std::cout << "    " << p.first << ": " << stack[p.second] << std::endl;
+        }
+    }
+
     void compiler::operator()(unsigned int x) const
     {
-        op(op_int, x);
+        program.op(op_int, x);
     }
 
     void compiler::operator()(ast::variable const& x) const
     {
-        // $$$ TODO $$$
-        op(op_int, 555); // for now
+        int const* p = program.find_var(x.name);
+        if (p == 0)
+        {
+            // $$$ undefined variable throw exception
+            std::cout << "undefined variable: " << x.name << std::endl;
+        }
+        program.op(op_load, *p);
     }
 
     void compiler::operator()(ast::operation const& x) const
@@ -45,10 +75,10 @@
         boost::apply_visitor(*this, x.operand_);
         switch (x.operator_)
         {
-            case '+': op(op_add); break;
-            case '-': op(op_sub); break;
-            case '*': op(op_mul); break;
-            case '/': op(op_div); break;
+            case '+': program.op(op_add); break;
+            case '-': program.op(op_sub); break;
+            case '*': program.op(op_mul); break;
+            case '/': program.op(op_div); break;
             default: BOOST_ASSERT(0); break;
         }
     }
@@ -58,7 +88,7 @@
         boost::apply_visitor(*this, x.operand_);
         switch (x.sign)
         {
-            case '-': op(op_neg); break;
+            case '-': program.op(op_neg); break;
             case '+': break;
             default: BOOST_ASSERT(0); break;
         }
@@ -72,5 +102,55 @@
             (*this)(oper);
         }
     }
+
+    void compiler::operator()(ast::assignment const& x) const
+    {
+        (*this)(x.rhs);
+        int const* p = program.find_var(x.lhs.name);
+        if (p == 0)
+        {
+            // $$$ undefined variable throw exception
+            std::cout << "undefined variable: " << x.lhs.name << std::endl;
+        }
+        program.op(op_store, *p);
+    }
+
+    void compiler::operator()(ast::variable_declaration const& x) const
+    {
+        int const* p = program.find_var(x.assign.lhs.name);
+        if (p != 0)
+        {
+            // $$$ duplicate variable throw exception
+            std::cout << "duplicate variable: " << x.assign.lhs.name << std::endl;
+        }
+        program.add_var(x.assign.lhs.name);
+        (*this)(x.assign);
+    }
+
+    void compiler::operator()(ast::statement const& x) const
+    {
+        typedef
+            boost::variant<
+                ast::variable_declaration,
+                ast::assignment>
+        statement;
+
+        try
+        {
+            program.clear();
+
+            // op_adstk 0 for now. we'll know how many variables we'll have later
+            program.op(op_adstk, 0);
+            BOOST_FOREACH(statement const& s, x)
+            {
+                boost::apply_visitor(*this, s);
+            }
+            program[1] = program.nvars(); // now store the actual number of variables
+        }
+        catch(...)
+        {
+            program.clear();
+        }
+    }
 }
 
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -9,23 +9,45 @@
 
 #include "ast.hpp"
 #include <vector>
+#include <map>
 
 namespace client
 {
     ///////////////////////////////////////////////////////////////////////////
+    //  The Program
+    ///////////////////////////////////////////////////////////////////////////
+    struct program
+    {
+        void op(int a);
+        void op(int a, int b);
+        void op(int a, int b, int c);
+
+        int& operator[](std::size_t i) { return code[i]; }
+        int const& operator[](std::size_t i) const { return code[i]; }
+        void clear() { code.clear(); variables.clear(); }
+        std::vector<int> const& operator()() const { return code; }
+
+        int nvars() const { return variables.size(); }
+        int const* find_var(std::string const& name) const;
+        void add_var(std::string const& name);
+
+        void print_variables(std::vector<int> const& stack) const;
+
+    private:
+
+        std::map<std::string, int> variables;
+        std::vector<int> code;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
     //  The Compiler
     ///////////////////////////////////////////////////////////////////////////
     struct compiler
     {
         typedef void result_type;
 
-        std::vector<int>& code;
-        compiler(std::vector<int>& code)
-          : code(code) {}
-
-        void op(int a) const;
-        void op(int a, int b) const;
-        void op(int a, int b, int c) const;
+        compiler(client::program& program)
+          : program(program) {}
 
         void operator()(ast::nil) const { BOOST_ASSERT(0); }
         void operator()(unsigned int x) const;
@@ -33,6 +55,11 @@
         void operator()(ast::operation const& x) const;
         void operator()(ast::signed_ const& x) const;
         void operator()(ast::expression const& x) const;
+        void operator()(ast::assignment const& x) const;
+        void operator()(ast::variable_declaration const& x) const;
+        void operator()(ast::statement const& x) const;
+
+        client::program& program;
     };
 }
 
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -18,7 +18,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 // Uncomment this if you want to enable debugging
-//#define BOOST_SPIRIT_QI_DEBUG
+// #define BOOST_SPIRIT_QI_DEBUG
 ///////////////////////////////////////////////////////////////////////////////
 
 #include <boost/spirit/include/qi.hpp>
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -18,7 +18,7 @@
 //
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "expression.hpp"
+#include "statement.hpp"
 #include "vm.hpp"
 #include "compiler.hpp"
 
@@ -29,51 +29,52 @@
 main()
 {
     std::cout << "/////////////////////////////////////////////////////////\n\n";
-    std::cout << "Expression parser...\n\n";
+    std::cout << "Statement parser...\n\n";
     std::cout << "/////////////////////////////////////////////////////////\n\n";
-    std::cout << "Type an expression...or [q or Q] to quit\n\n";
-
-    typedef std::string::const_iterator iterator_type;
-    typedef client::expression<iterator_type> expression;
-    typedef client::ast::expression ast_expression;
-    typedef client::compiler compiler;
+    std::cout << "Type some statements... ";
+    std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
 
     std::string str;
+    std::string source;
     while (std::getline(std::cin, str))
     {
-        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+        if (str.empty())
             break;
+        source += str + '\n';
+    }
+
+    typedef std::string::const_iterator iterator_type;
+    iterator_type iter = source.begin();
+    iterator_type end = source.end();
 
-        client::vmachine mach;      // Our virtual machine
-        std::vector<int> code;      // Our VM code
-        expression calc;            // Our grammar
-        ast_expression expression;  // Our program (AST)
-        compiler compile(code);     // Our compiler
-
-        std::string::const_iterator iter = str.begin();
-        std::string::const_iterator end = str.end();
-        boost::spirit::ascii::space_type space;
-        bool r = phrase_parse(iter, end, calc, space, expression);
-
-        if (r && iter == end)
-        {
-            std::cout << "-------------------------\n";
-            std::cout << "Parsing succeeded\n";
-            compile(expression);
-            mach.execute(code);
-            std::cout << "\nResult: " << mach.top() << std::endl;
-            std::cout << "-------------------------\n";
-        }
-        else
-        {
-            std::string rest(iter, end);
-            std::cout << "-------------------------\n";
-            std::cout << "Parsing failed\n";
-            std::cout << "-------------------------\n";
-        }
+    client::vmachine vm;                        // Our virtual machine
+    client::program program;                    // Our VM program
+    client::statement<iterator_type> parser;    // Our parser
+    client::ast::statement ast;                 // Our AST
+    client::compiler compile(program);          // Our compiler
+
+    boost::spirit::ascii::space_type space;
+    bool r = phrase_parse(iter, end, parser, space, ast);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        compile(ast);
+        vm.execute(program());
+
+        std::cout << "Results------------------\n\n";
+        program.print_variables(vm.get_stack());
+        std::cout << "-------------------------\n\n";
+    }
+    else
+    {
+        std::string rest(iter, end);
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
     }
 
-    std::cout << "Bye... :-) \n\n";
     return 0;
 }
 
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -36,7 +36,7 @@
             ;
 
         variable_declaration =
-                ("var" >> !(alnum | '_'))   // make sure we have whole words
+                lexeme["var" >> !(alnum | '_')] // make sure we have whole words
             >   assignment
             ;
 
Modified: trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp
==============================================================================
--- trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp	(original)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp	2011-02-27 11:30:51 EST (Sun, 27 Feb 2011)
@@ -38,8 +38,8 @@
         {
         }
 
-        int top() const { return stack_ptr[-1]; };
         void execute(std::vector<int> const& code);
+        std::vector<int> const& get_stack() const { return stack; };
 
     private: