00001 // Copyright (C) 2001 Petter Urkedal (petter.urkedal@matfys.lth.se) 00002 // 00003 // This file is free software; you can redistribute it and/or modify 00004 // it under the terms of the GNU General Public License as published by 00005 // the Free Software Foundation; either version 2 of the License, or 00006 // (at your option) any later version. 00007 // 00008 // This file is distributed in the hope that it will be useful, 00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 // GNU General Public License for more details. 00012 // 00013 // You should have received a copy of the GNU General Public License 00014 // along with this program; if not, write to the Free Software 00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00016 // 00017 // As a special exception, you may use this file as part of a free 00018 // software library without restriction. Specifically, if other files 00019 // instantiate templates or use macros or inline functions from this 00020 // file, or you compile this file and link it with other files to 00021 // produce an executable, this file does not by itself cause the 00022 // resulting executable to be covered by the GNU General Public 00023 // License. This exception does not however invalidate any other 00024 // reasons why the executable file might be covered by the GNU General 00025 // Public License. 00026 // 00027 // $Id: location.h,v 1.1 2002/05/30 18:01:37 petter_urkedal Exp $ 00028 00029 // !! THIS INTERFACE IS NOT STABILIZED !! 00030 00031 00032 #ifndef MORE_LANG_LOCATION_H 00033 #define MORE_LANG_LOCATION_H 00034 00035 #include <more/lang/fwd.h> 00036 #include <more/gen/utility.h> 00037 #include <stdexcept> 00038 00039 namespace more { 00040 namespace lang { 00041 00042 /** \class cx_resolver package.h more/lang/package.h 00043 ** 00044 ** The interface for handling lazy resoltion of value addresses. */ 00045 struct resolver 00046 { 00047 resolver(); 00048 virtual ~resolver(); 00049 00050 /** Return the type of the object returned by resolve. */ 00051 virtual ct_type const* resolve_type_of() const = 0; 00052 00053 /** If m_ptr == 0, this function shall return a pointer to the 00054 object. It may optionally also set m_ptr to speed up later 00055 calls to get(). If the binding can not be resolved, return 00056 0. */ 00057 virtual void* resolve() = 0; 00058 00059 #if 0 00060 /** Provide a pointer to type \a t or 0 if not possible. The 00061 default implementation returns the properly translated \c 00062 location::get() if \a t match the \a rtt argument of the 00063 ctor or is inherited from in, and 0 otherwise. */ 00064 virtual void* resolve(ct_type const* t); 00065 #endif 00066 00067 /** If m_ptr == 0 and type_of() is an ct_proto, this function 00068 shall call the function represented by this value. The 00069 default implementation calls the function returned by 00070 this->resolve() using ct_proto::call. */ 00071 virtual void resolve_call(void* ret, void** args); 00072 00073 /** Return true if equal to \a rhs. */ 00074 virtual bool equal_to(resolver* rhs) = 0; 00075 00076 /** Return the location which uses this resolver. */ 00077 location* client() { return m_client; } 00078 00079 private: 00080 location* m_client; 00081 00082 friend class location; 00083 }; 00084 00085 inline bool 00086 equal(resolver* h0, resolver* h1) 00087 { 00088 return h0->equal_to(h1); 00089 } 00090 00091 00092 /** \class location package.h more/lang/package.h 00093 ** 00094 ** A lazily resolved value. This has low space overhead (two 00095 ** pointers) most stuff goes into the handler. Lookup is fast 00096 ** after the value is resolved, but resolving the value may be 00097 ** slow. */ 00098 struct location : gen::noncopyable 00099 { 00100 /** Construct an undefined location. The only valid methods for 00101 an undefined location are \c is_defined(), \c set(void*) and 00102 \c set_resolver(). */ 00103 location() 00104 : m_ptr(0), m_resolver(0) {} 00105 00106 /** Construct a location handled by \a handler or containing \a 00107 ptr. If \a ptr is non-zero, \a handler will not be used by 00108 \c location, so it is safe to set it to 0 as long as \c set 00109 is not invoked with a 0 argument. */ 00110 explicit location(resolver* handler, void* ptr = 0); 00111 00112 ~location(); 00113 00114 /** True if the location is fixed or if a resolver is provided. */ 00115 bool is_defined() const { return m_ptr != 0 || m_resolver != 0; } 00116 00117 /** Set the handler. */ 00118 void set_resolver(resolver* h) { m_resolver = h; h->m_client = this; } 00119 00120 /** Return the handler of this location. */ 00121 resolver* get_resolver() const { return m_resolver; } 00122 00123 /** Return the type of the data at this location. 00124 \pre A resolver is provided. */ 00125 ct_type const* type_of() const 00126 { 00127 #ifndef MORE_LANG_NDEBUG 00128 if (!m_resolver) 00129 throw std::logic_error("more::lang::location::type_of(): " 00130 "The location is not resolvable."); 00131 #endif 00132 return m_resolver->resolve_type_of(); 00133 } 00134 00135 /** Returns a pointer to the object of the binding. The \c 00136 cx_package_variable resovler will invalidate the returned 00137 pointer upon re-linking, which may be caused by another call 00138 to this method. 00139 \pre Either the location is fixed or a resolver is provided. */ 00140 void* get() const 00141 { 00142 if (m_ptr) 00143 return m_ptr; 00144 #ifndef MORE_LANG_NDEBUG 00145 if (!m_resolver) 00146 throw std::logic_error("more::lang::location::get(): " 00147 "The location is not resolvable."); 00148 #endif 00149 return m_resolver->resolve(); 00150 } 00151 00152 #if 0 00153 /** Return a pointer to the object of the binding projected to \a t. 00154 \pre A resolver is provided. */ 00155 void* get(ct_type const* t) const 00156 { 00157 #ifndef MORE_LANG_NDEBUG 00158 if (!m_resolver) 00159 throw std::logic_error("more::lang::location::" 00160 "get(ct_type const*): " 00161 "The location is not resolvable."); 00162 #endif 00163 return m_resolver->resolve(t); 00164 } 00165 #endif 00166 00167 /** Returns a pointer to the object if it no computaiton is 00168 needed. */ 00169 void* get_if_ready() const { return m_ptr; } 00170 00171 /** If the value is a function, call it, otherwise screw up the 00172 process. In some frameworks this may be equivalent to using 00173 \c ct_proto::call on \c this->get(). This method is 00174 provided in order to allow an interpreted code. */ 00175 void call(void* ret, void** args); 00176 00177 /** To be called from reslove() to set to pointer to the 00178 object. */ 00179 void set(void* ptr) { m_ptr = ptr; } 00180 00181 private: 00182 // A pointer to the object or 0 for undefined or delayed 00183 // binding. 00184 mutable void* m_ptr; 00185 00186 // A hander to resolve m_ptr. 00187 mutable resolver* m_resolver; 00188 }; 00189 00190 inline bool 00191 equal(location* locn0, location* locn1) 00192 { 00193 if (locn0->get_if_ready() && locn1->get_if_ready()) 00194 return locn0->get_if_ready() == locn1->get_if_ready(); 00195 else 00196 return equal(locn0->get_resolver(), locn1->get_resolver()); 00197 } 00198 00199 }} 00200 00201 #endif