Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55908 - in trunk/tools/quickbook: detail doc test
From: daniel_james_at_[hidden]
Date: 2009-08-31 07:36:48


Author: danieljames
Date: 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
New Revision: 55908
URL: http://svn.boost.org/trac/boost/changeset/55908

Log:
Implement static/lexical scoping for 1.5. Refs #2034.
Added:
   trunk/tools/quickbook/test/fail-template-lookup1.quickbook (contents, props changed)
   trunk/tools/quickbook/test/templates_1_5.gold (contents, props changed)
   trunk/tools/quickbook/test/templates_1_5.quickbook (contents, props changed)
Text files modified:
   trunk/tools/quickbook/detail/actions.cpp | 28 ++++++++++++++++++++++++----
   trunk/tools/quickbook/detail/template_stack.cpp | 22 +++++++++++++++++++---
   trunk/tools/quickbook/detail/template_stack.hpp | 30 +++++++++++++++++++++++++-----
   trunk/tools/quickbook/doc/quickbook.qbk | 1 +
   trunk/tools/quickbook/test/Jamfile.v2 | 2 ++
   trunk/tools/quickbook/test/templates_1_4.quickbook | 2 +-
   6 files changed, 72 insertions(+), 13 deletions(-)

Modified: trunk/tools/quickbook/detail/actions.cpp
==============================================================================
--- trunk/tools/quickbook/detail/actions.cpp (original)
+++ trunk/tools/quickbook/detail/actions.cpp 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -512,7 +512,7 @@
         actions.template_info.push_back(std::string(first, last));
         actions.templates.add(
             actions.template_info[0]
- , boost::make_tuple(actions.template_info, first.get_position()));
+ , template_symbol(actions.template_info, first.get_position()));
         actions.template_info.clear();
     }
 
@@ -565,6 +565,7 @@
         get_arguments(
             std::vector<std::string>& template_info
           , std::vector<std::string> const& template_
+ , template_scope const& scope
           , boost::spirit::classic::file_position const& pos
           , quickbook::actions& actions
         )
@@ -578,7 +579,7 @@
                 std::vector<std::string> tinfo;
                 tinfo.push_back(*tpl);
                 tinfo.push_back(*arg);
- template_symbol template_(tinfo, pos);
+ template_symbol template_(tinfo, pos, &scope);
 
                 if (actions.templates.find_top_scope(*tpl))
                 {
@@ -665,6 +666,17 @@
             return;
         }
 
+ // The template arguments should have the scope that the template was
+ // called from, not the template's own scope.
+ //
+ // Note that for quickbook 1.4- this value is just ignored when the
+ // arguments are expanded.
+ template_scope const& call_scope = actions.templates.top_scope();
+
+ template_symbol const* symbol =
+ actions.templates.find(actions.template_info[0]);
+ BOOST_ASSERT(symbol);
+
         std::string result;
         actions.push(); // scope the actions' states
         {
@@ -672,6 +684,13 @@
                 actions.templates.find(actions.template_info[0]);
             BOOST_ASSERT(symbol);
 
+ // Quickbook 1.4-: When expanding the tempalte continue to use the
+ // current scope (the dynamic scope).
+ // Quickbook 1.5+: Use the scope the template was defined in
+ // (the static scope).
+ if (qbk_version_n >= 105)
+ actions.templates.set_parent_scope(*boost::get<2>(*symbol));
+
             std::vector<std::string> template_ = boost::get<0>(*symbol);
             boost::spirit::classic::file_position template_pos = boost::get<1>(*symbol);
 
@@ -693,7 +712,8 @@
             bool get_arg_result;
             std::vector<std::string>::const_iterator tpl;
             boost::tie(get_arg_result, tpl) =
- get_arguments(template_info, template_, pos, actions);
+ get_arguments(template_info, template_,
+ call_scope, pos, actions);
 
             if (!get_arg_result)
             {
@@ -1069,7 +1089,7 @@
         std::vector<std::string> tinfo;
         tinfo.push_back(id);
         tinfo.push_back(snippet);
- storage.push_back(boost::make_tuple(tinfo, first.get_position()));
+ storage.push_back(template_symbol(tinfo, first.get_position()));
 
         callout_id += callouts.size();
         callouts.clear();

Modified: trunk/tools/quickbook/detail/template_stack.cpp
==============================================================================
--- trunk/tools/quickbook/detail/template_stack.cpp (original)
+++ trunk/tools/quickbook/detail/template_stack.cpp 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -23,7 +23,7 @@
     
     template_symbol* template_stack::find(std::string const& symbol) const
     {
- for (deque::const_iterator i = scopes.begin(); i != scopes.end(); ++i)
+ for (template_scope const* i = &*scopes.begin(); i; i = i->parent_scope)
         {
             if (template_symbol* ts = boost::spirit::classic::find(i->symbols, symbol.c_str()))
                 return ts;
@@ -41,22 +41,38 @@
         BOOST_ASSERT(!scopes.empty());
         return scopes.front().symbols;
     }
+
+ template_scope const& template_stack::top_scope() const
+ {
+ BOOST_ASSERT(!scopes.empty());
+ return scopes.front();
+ }
     
+ // TODO: Should symbols defined by '[import]' use the current scope?
     void template_stack::add(std::string const& symbol, template_symbol const& ts)
     {
         BOOST_ASSERT(!scopes.empty());
- boost::spirit::classic::add(scopes.front().symbols, symbol.c_str(), ts);
- }
+ boost::spirit::classic::add(scopes.front().symbols, symbol.c_str(),
+ boost::get<2>(ts) ? ts :
+ template_symbol(boost::get<0>(ts), boost::get<1>(ts), &top_scope()));
+ }
     
     void template_stack::push()
     {
+ template_scope const& old_front = scopes.front();
         scopes.push_front(template_scope());
+ set_parent_scope(old_front);
     }
 
     void template_stack::pop()
     {
         scopes.pop_front();
     }
+
+ void template_stack::set_parent_scope(template_scope const& parent)
+ {
+ scopes.front().parent_scope = &parent;
+ }
 }
 
 

Modified: trunk/tools/quickbook/detail/template_stack.hpp
==============================================================================
--- trunk/tools/quickbook/detail/template_stack.hpp (original)
+++ trunk/tools/quickbook/detail/template_stack.hpp 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -21,6 +21,8 @@
 
 namespace quickbook
 {
+ struct template_scope;
+
     // template symbols with N arguments are stored as follows:
     //
     // vector<std::string>
@@ -28,21 +30,34 @@
     // 1: template param name[0]
     // 2: template param name[1]
     // ...
- // template param name[N]
- // template body
     // N: template param name[N-1]
     // N+1: template body
     // file position
+ // template scope (only used for 1.5+, 1.4- uses the dynamic scope)
 
     typedef boost::tuple<
             std::vector<std::string>
- , boost::spirit::classic::file_position>
+ , boost::spirit::classic::file_position
+ , template_scope const*>
     template_symbol;
 
     typedef boost::spirit::classic::symbols<template_symbol> template_symbols;
     
+ // template scope
+ //
+ // 1.4-: parent_scope is the previous scope on the stack
+ // (the template's dynamic parent).
+ // 1.5+: parent_scope is the template's lexical parent.
+ //
+ // This means that a search along the parent_scope chain will follow the
+ // correct lookup chain for that version of quickboook.
+ //
+ // symbols contains the templates defined in this scope.
+
     struct template_scope
     {
+ template_scope() : parent_scope() {}
+ template_scope const* parent_scope;
         template_symbols symbols;
     };
 
@@ -64,8 +79,7 @@
                 // search all scopes for the longest matching symbol.
                 typename Scanner::iterator_t f = scan.first;
                 std::ptrdiff_t len = -1;
- for (template_stack::deque::const_iterator i = ts.scopes.begin();
- i != ts.scopes.end(); ++i)
+ for (template_scope const* i = &*ts.scopes.begin(); i; i = i->parent_scope)
                 {
                     boost::spirit::classic::match<> m = i->symbols.parse(scan);
                     if (m.length() > len)
@@ -84,10 +98,16 @@
         template_symbol* find(std::string const& symbol) const;
         template_symbol* find_top_scope(std::string const& symbol) const;
         template_symbols const& top() const;
+ template_scope const& top_scope() const;
+ // Add the given template symbol to the current scope.
+ // If it doesn't have a scope, sets the symbol's scope to the current scope.
         void add(std::string const& symbol, template_symbol const& ts);
         void push();
         void pop();
 
+ // Set the current scope's parent.
+ void set_parent_scope(template_scope const&);
+
         boost::spirit::classic::functor_parser<parser> scope;
 
     private:

Modified: trunk/tools/quickbook/doc/quickbook.qbk
==============================================================================
--- trunk/tools/quickbook/doc/quickbook.qbk (original)
+++ trunk/tools/quickbook/doc/quickbook.qbk 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -176,6 +176,7 @@
 * Improved handling of unmatched escape in code blocks.
 * Support for python snippets.
 * `teletype` source mode.
+* Use static scoping in templates, should be a lot more intuitive.
 
 [endsect]
 

Modified: trunk/tools/quickbook/test/Jamfile.v2
==============================================================================
--- trunk/tools/quickbook/test/Jamfile.v2 (original)
+++ trunk/tools/quickbook/test/Jamfile.v2 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -22,6 +22,7 @@
     [ quickbook-test escape ]
     [ quickbook-test templates ]
     [ quickbook-test templates_1_4 ]
+ [ quickbook-test templates_1_5 ]
     [ quickbook-test xinclude ]
     [ quickbook-test import ]
     [ quickbook-fail-test fail-include ]
@@ -33,6 +34,7 @@
     [ quickbook-fail-test fail-post-process ]
     [ quickbook-fail-test fail-parse-error1 ]
     [ quickbook-fail-test fail-parse-error2 ]
+ [ quickbook-fail-test fail-template-lookup1 ]
     ;
 
 

Added: trunk/tools/quickbook/test/fail-template-lookup1.quickbook
==============================================================================
--- (empty file)
+++ trunk/tools/quickbook/test/fail-template-lookup1.quickbook 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -0,0 +1,7 @@
+[article Fail Template Lookup 1
+ [quickbook 1.5]
+]
+
+[template test1[] [a]]
+[template test2[a] [test1]]
+[test2 1]
\ No newline at end of file

Modified: trunk/tools/quickbook/test/templates_1_4.quickbook
==============================================================================
--- trunk/tools/quickbook/test/templates_1_4.quickbook (original)
+++ trunk/tools/quickbook/test/templates_1_4.quickbook 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -13,4 +13,4 @@
 
 [template y new]
 [template foo3[a y] [a]]
-[foo3 [y] old]
\ No newline at end of file
+[foo3 [y] old]

Added: trunk/tools/quickbook/test/templates_1_5.gold
==============================================================================
--- (empty file)
+++ trunk/tools/quickbook/test/templates_1_5.gold 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
+<article id="template_1_5" last-revision="DEBUG MODE Date: 2000/12/20 12:00:00 $"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+ <title>Template 1.5</title>
+ <articleinfo>
+ </articleinfo>
+ <para>
+ static scoping
+ </para>
+ <para>
+ new
+ </para>
+ <para>
+ foo foo
+ </para>
+</article>

Added: trunk/tools/quickbook/test/templates_1_5.quickbook
==============================================================================
--- (empty file)
+++ trunk/tools/quickbook/test/templates_1_5.quickbook 2009-08-31 07:36:47 EDT (Mon, 31 Aug 2009)
@@ -0,0 +1,23 @@
+[article Template 1.5
+ [quickbook 1.5]
+]
+
+[/ 1.5 uses static scoping ]
+
+[template x static scoping]
+[template foo1[] [x]]
+[template foo2[x] [foo1]]
+[foo2 dynamic scoping]
+
+[/ In 1.5 template arguments are scoped at the point they are defined]
+
+[template y new]
+[template foo3[a y] [a]]
+[foo3 [y] old]
+
+[/ From https://svn.boost.org/trac/boost/ticket/2034 ]
+
+[template same[x] [x]]
+[template echo[a b] [a] [b]]
+[template echo_twice[x] [echo [same [x]]..[same [x]]]]
+[echo_twice foo]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk