Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

more/lang/cx_expr.h

Go to the documentation of this file.
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: cx_expr.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_CX_EXPR_H
00033 #define MORE_LANG_CX_EXPR_H
00034 
00035 #include <more/lang/ct_type.h>
00036 #include <more/lang/ct_proto.h>
00037 #include <list>
00038 #include <utility>
00039 #include <stdarg.h>
00040 
00041 namespace more {
00042 namespace lang {
00043 
00044   /** \class cx_expr cx_expr.h more/lang/cx_expr.h
00045    **
00046    ** The base class for expressions which can be directly coded into
00047    ** C source and possibly evaluated runtime.  Client code does not
00048    ** need to use this a the base class for expression (e.g. if
00049    ** virtual functions are undesirable).  Instead the client
00050    ** expressions may be transformed into C cx_expr instances. */
00051   struct cx_expr : gc
00052   {
00053       virtual ~cx_expr();
00054 
00055       /** Print the C source code of this expression.  The default
00056           implementation thows a logic error.  This function may be
00057           overloaded to extend the backend, otherwise it may be easier
00058           to transform the source code. */
00059       virtual void print_as_expr(std::ostream& os) const;
00060 
00061       /** Print this expression as a C statement.  The default
00062           implementation calls print_source and then appends a
00063           semicolon. */
00064       virtual void print_as_stmt(std::ostream& os) const;
00065 
00066       /** Append constructors of this expression to \a blk. */
00067       virtual void append_ctors_to(cx_block* blk) = 0;
00068 
00069       /** Append destructors of this expression to \a blk.
00070           Implementations of this function shall not declare variables
00071           in \a blk. */
00072       virtual void append_dtors_to(cx_block* blk) = 0;
00073 
00074     protected:
00075       explicit cx_expr(ct_type const* t) : m_rtt(t) {}
00076 
00077     public:
00078       /** Return the type of the expression. */
00079       ct_type const* type_of() const { return m_rtt; }
00080 
00081       /** Change the type of the expression. */
00082       void set_type(ct_type const* rtt) { m_rtt = rtt; }
00083 
00084     private:
00085       ct_type const* m_rtt;
00086   };
00087 
00088 
00089   /** \class cx_block cx_expr.h more/lang/cx_expr.h
00090    **
00091    ** The representation of a C block containing declarations and
00092    ** statements. */
00093   struct cx_block : cx_expr
00094   {
00095       cx_block()
00096           : cx_expr(ct_type_of<void>()) {}
00097 
00098       /** Declare a variable of type \a rtt, and return it. */
00099       cx_identifier* declare(ct_type const* rtt);
00100 
00101       /** Bind \a e to a variable in this block, and return the
00102           variable.  The initialization of the variable will be pushed
00103           onto the end of statement container. */
00104       cx_identifier* append_definition(cx_expr* e);
00105 
00106       /** Push a statement onto the end of the statement container. */
00107       void append_stmt(cx_expr* e);
00108 
00109       /** Push a statement onto the front of the statement
00110           container. \a e shall not have constructors or destructors,
00111           use an \c cx_block in such cases. */
00112       void prepend_stmt(cx_expr* e);
00113 
00114       /** Append declarations of \a blk to this block. */
00115       void append_decls_from(cx_block const* blk);
00116 
00117       /** Append statements of \a blk to this block. */
00118       void append_stmts_from(cx_block const* blk);
00119 
00120       /** True if no code is inserted into the block. */
00121       bool empty() const { return m_vars.empty() && m_stmts.empty(); }
00122 
00123       virtual void print_as_expr(std::ostream& os) const;
00124       virtual void print_as_stmt(std::ostream& os) const;
00125       void print_as_stmt_seq(std::ostream& os) const;
00126       virtual void append_ctors_to(cx_block* blk);
00127       virtual void append_dtors_to(cx_block* blk);
00128 
00129     private:
00130 #ifdef MORE_LANG_USE_GC
00131       typedef std::list< cx_identifier*, gen::gc_allocator<cx_identifier*> >
00132               var_container;
00133       typedef std::list< cx_expr*, gen::gc_allocator<cx_expr*> >
00134               stmt_container;
00135 #else
00136       typedef std::list<cx_identifier*> var_container;
00137       typedef std::list<cx_expr*>       stmt_container;
00138 #endif
00139       var_container     m_vars;
00140       stmt_container    m_stmts;
00141   };
00142 
00143   inline cx_block*
00144   make_block()
00145   {
00146       return new(UseGC) cx_block();
00147   }
00148 
00149   /** \class cx_expr_with_ctor_dtor cx_expr.h more/lang/cx_expr.h
00150    **
00151    ** The representation of an expression with attached constrution an
00152    ** destruction code.  If the expression appears as a subexpression
00153    ** the constructor is added before and the destructor is added
00154    ** after the statement of which it is a subexpression. */
00155   struct cx_expr_with_ctor_dtor : cx_expr
00156   {
00157       cx_expr_with_ctor_dtor(ct_type const* t)
00158           : cx_expr(t), m_ctor_dtor(0) {}
00159 
00160       virtual void append_ctors_to(cx_block* blk);
00161       virtual void append_dtors_to(cx_block* blk);
00162 
00163       cx_identifier* ctor_declare(ct_type const* t);
00164       void ctor_append_stmt(cx_expr* e);
00165       void dtor_append_stmt(cx_expr* e);
00166 
00167     private:
00168       struct ctor_dtor_type {
00169           cx_block m_ctors;
00170           cx_block m_dtors;
00171       };
00172       ctor_dtor_type* m_ctor_dtor;
00173   };
00174 
00175 
00176   /** \class cx_identifier cx_expr.h more/lang/cx_expr.h
00177    **
00178    ** The representation of a variable (auto, global, or function
00179    ** name). */
00180   struct cx_identifier : cx_expr_with_ctor_dtor
00181   {
00182       /** Construct a unique variable. */
00183       explicit cx_identifier(ct_type const* r)
00184           : cx_expr_with_ctor_dtor(r) {}
00185 
00186       /** Construct a variable with the name given by \a id. */
00187       cx_identifier(ct_type const* r, identifier id)
00188           : cx_expr_with_ctor_dtor(r),
00189             m_id(id) {}
00190 
00191       virtual ~cx_identifier();
00192 
00193       identifier name() const { return m_id; }
00194 
00195       void set_name(identifier idr) { m_id = idr; }
00196 
00197       virtual void print_as_expr(std::ostream& os) const;
00198 
00199     private:
00200       identifier        m_id;
00201   };
00202 
00203   /** \class cx_literal cx_expr.h more/lang/cx_expr.h
00204    **
00205    ** The representation of a C literal.  Don't use this directly, use
00206    ** make_literal, which performs float and integer promotion to
00207    ** limit the number of template instances of this class.
00208    ** Otherwise, undefined references may occur. */
00209   template <typename T>
00210     struct cx_literal : cx_expr
00211     {
00212         explicit cx_literal(T const& value)
00213             : cx_expr(ct_type_of<T>()),
00214               m_value(value) {}
00215 
00216         virtual void print_as_expr(std::ostream& os) const;
00217         virtual void append_ctors_to(cx_block* blk);
00218         virtual void append_dtors_to(cx_block* blk);
00219 
00220       private:
00221         T m_value;
00222     };
00223 
00224   template cx_literal<char>;
00225   template cx_literal<int>;
00226   template cx_literal<unsigned int>;
00227   template cx_literal<long>;
00228   template cx_literal<unsigned long>;
00229 #ifdef CXX_HAVE_LONG_LONG
00230   template cx_literal<long long>;
00231   template cx_literal<unsigned long long>;
00232 #endif
00233   template cx_literal<long double>;
00234   template cx_literal<char const*>;
00235 
00236   inline cx_expr* make_literal(char x)
00237   { return new(UseGC) cx_literal<char>(x); }
00238   inline cx_expr* make_literal(int x)
00239   { return new(UseGC) cx_literal<int>(x); }
00240   inline cx_expr* make_literal(unsigned int x)
00241   { return new(UseGC) cx_literal<unsigned int>(x); }
00242   inline cx_expr* make_literal(long x)
00243   { return new(UseGC) cx_literal<long>(x); }
00244   inline cx_expr* make_literal(unsigned long x)
00245   { return new(UseGC) cx_literal<unsigned long>(x); }
00246 #ifdef CXX_HAVE_LONG_LONG
00247   inline cx_expr* make_literal(long long x)
00248   { return new(UseGC) cx_literal<long long>(x); }
00249   inline cx_expr* make_literal(unsigned long long x)
00250   { return new(UseGC) cx_literal<unsigned long long>(x); }
00251 #endif
00252   inline cx_expr* make_literal(long double x)
00253   { return new(UseGC) cx_literal<long double>(x); }
00254   inline cx_expr* make_literal(char const* x)
00255   { return new(UseGC) cx_literal<char const*>(x); }
00256 
00257 
00258 
00259   /** \class cx_call cx_expr.h more/lang/cx_expr.h
00260    **
00261    ** The representation of a C function call. */
00262   struct cx_call : cx_expr
00263   {
00264       /** Consturct a call to \a fn with arugments from \a va.  \a va
00265           must be initialized to iterate over \c cx_expr* terminated
00266           by <tt>(cx_expr*)0</tt>. */
00267       cx_call(cx_expr* fn, va_list va);
00268 
00269       /** Construct a call to \a fn from a pre-built argument list \a
00270           args.  \a args need not be 0-terminated, and should persist
00271           (use GC).  */
00272       cx_call(cx_expr* fn, cx_expr** args);
00273 
00274       virtual void print_as_expr(std::ostream& os) const;
00275       virtual void append_ctors_to(cx_block* blk);
00276       virtual void append_dtors_to(cx_block* blk);
00277 
00278     private:
00279       cx_expr*  m_fn;
00280       cx_expr** m_args;
00281   };
00282 
00283   /** Return the representation of a function call to \a fn.  The
00284    ** arguments is a <tt>(cx_expr*)0</tt>-terminated VA list of
00285    ** <tt>cx_expr*</tt>. */
00286   cx_call* make_call(cx_expr* fn, ...);
00287 
00288 
00289   /** \class cx_switch cx_expr.h more/lang/cx_expr.h
00290    **
00291    ** The representation of a C switch block. */
00292   struct cx_switch : cx_block
00293   {
00294       explicit cx_switch(cx_expr* cond)
00295           : m_cond(cond) {}
00296 
00297       virtual void print_as_stmt(std::ostream& os) const;
00298       virtual void append_ctors_to(cx_block* blk);
00299       virtual void append_dtors_to(cx_block* blk);
00300 
00301     private:
00302       cx_expr*                  m_cond;
00303   };
00304 
00305   /** \class cx_lambda cx_expr.h more/lang/cx_expr.h
00306    **
00307    ** A lambda expression used as the definiens of a function
00308    ** definition. */
00309   struct cx_lambda : cx_expr
00310   {
00311       /** Iterator over the range of arguments. */
00312       typedef cx_identifier const* const* arg_const_iterator;
00313       typedef cx_identifier** arg_iterator;
00314 
00315       /** Create a named function with the given prototype. */
00316       cx_lambda(ct_proto const* proto, identifier self);
00317 
00318       /** Create an anonymous function with the give prototype. */
00319       cx_lambda(ct_proto const* proto);
00320 
00321       /** Return the prototype of the function. */
00322       ct_proto const* type_of() const
00323       {
00324           return static_cast<ct_proto const*>(cx_expr::type_of());
00325       }
00326 
00327       /** Return the expression of argument number i, counting from 0. */
00328       cx_identifier* arg(size_t i);
00329 
00330       /** Return the lower bound of the argument range. */
00331       arg_const_iterator arg_begin() const { return m_args; }
00332       arg_iterator arg_begin() { return m_args; }
00333 
00334       /** Return the upper bound of the argument range. */
00335       arg_const_iterator arg_end() const { return m_args+arg_count(); }
00336       arg_iterator arg_end() { return m_args + arg_count(); }
00337 
00338       /** Return the number of formal arguments. */
00339       size_t arg_count() const
00340       {
00341           return static_cast<ct_proto const*>(type_of())->arg_count();
00342       }
00343 
00344       /** Return a block on which to append the statements of the
00345           function body. */
00346       cx_block* body() { return &m_body; }
00347 
00348       /** Return the block of the function body. */
00349       cx_block const* body() const { return &m_body; }
00350 
00351       virtual void append_ctors_to(cx_block* blk);
00352       virtual void append_dtors_to(cx_block* blk);
00353       virtual void print_as_expr(std::ostream& os) const;
00354 
00355     private:
00356       cx_identifier**   m_args;
00357       cx_block          m_body;
00358       unsigned int      m_inline_p : 1;
00359   };
00360 
00361   /** \class cx_cond cx_expr.h more/lang/cx_expr.h
00362    **
00363    ** The representation of a sequence of if/else statements using a
00364    ** Scheme like interface. */
00365   struct cx_cond : cx_expr
00366   {
00367       cx_cond() : cx_expr(ct_type_of<void>()), m_counter_conseq(0) {}
00368 
00369       /** Append an (\a condition, \a consequence) pair.  The first
00370           call creates an <tt>if (...) ...</tt>, succeeding calls
00371           creates else <tt>if (...) ...</tt>.  The final <tt>else
00372           ...</tt> is created by calling <tt>append(0,
00373           conter_consequence)</tt>. */
00374       void append(cx_expr* condition, cx_expr* consequence);
00375 
00376       virtual void print_as_expr(std::ostream& os) const;
00377       virtual void print_as_stmt(std::ostream& os) const;
00378       virtual void append_ctors_to(cx_block* blk);
00379       virtual void append_dtors_to(cx_block* blk);
00380 
00381     private:
00382       struct cond_conseq
00383       {
00384           cx_expr* m_cond;
00385           cx_expr* m_conseq;
00386           cx_block* m_cond_ctors;
00387           cx_block* m_cond_dtors;
00388       };
00389 #ifdef MORE_LANG_USE_GC
00390       typedef std::list<cond_conseq, gen::gc_allocator<cond_conseq> >
00391               case_container;
00392 #else
00393       typedef std::list<cond_conseq> case_container;
00394 #endif
00395 
00396       mutable case_container    m_cases;
00397       cx_expr*                  m_counter_conseq;
00398   };
00399 
00400   /** \class cx_pattern cx_expr.h more/lang/cx_expr.h
00401    **
00402    ** The representation of a named function call or arbitrary C
00403    ** expression.  Don't use this for logic and and logic or, as this
00404    ** will produce code that runs constructor and destructors
00405    ** regardless of the result of the LHS. */
00406   struct cx_pattern : cx_expr
00407   {
00408       /** Construct an expression of the form pattern which evaluates
00409           to \a result_type and with arguments from \a va.  Occurances
00410           of "%!" in \a pattern are substituted with argument
00411           expressions.  If \a pattern is not a string literal, you
00412           must make sure it outlives this object, e.g. by copying it
00413           to a GC allocated segment.
00414 
00415           By convention the whole expression in \a pattern is
00416           surrounded by parentheses, rather than each sub-expression.
00417           That is, it is assumed that all code that is printed is
00418           printed such that it has top-level precedence.
00419       */
00420       cx_pattern(char const* pattern, ct_type const* result_type, va_list va);
00421 
00422       virtual void print_as_expr(std::ostream& os) const;
00423       virtual void append_ctors_to(cx_block* blk);
00424       virtual void append_dtors_to(cx_block* blk);
00425 
00426     private:
00427       void init(va_list va);
00428 
00429       char const*       m_pattern;
00430       int               m_arity;
00431       cx_expr**         m_args;
00432   };
00433 
00434   /** The representation af a sequential conjunction.  NOT FINISHED,
00435       USE cx_cond. */
00436   struct cx_and : cx_expr
00437   {
00438       cx_and(size_t n_arg, cx_expr** arg_arr);
00439       virtual void print_as_expr(std::ostream& os) const;
00440       virtual void append_ctors_to(cx_block* blk);
00441       virtual void append_dtors_to(cx_block* blk);
00442 
00443     private:
00444       size_t m_n;
00445       cx_expr** m_argv;
00446   };
00447 
00448   /** Create a C expression.  For each "%!" in \a pattern, there shall
00449       be one \c cx_expr* VA argument.  The VA list need not be
00450       0-terminated, and is not checked.  Use a more specific \c
00451       make_... function if available. */
00452   cx_expr* make_expr(char const* pattern, ct_type const*, ...);
00453 
00454   /** Same as <tt>make_expr(pattern, ct_type_of<void>(), ...)</tt>.
00455       Use a more specific \c make_... function if available. */
00456   cx_expr* make_stmt(char const* pattern, ...);
00457 
00458   cx_expr* make_deref_expr(cx_expr*);
00459   cx_expr* make_element_expr(cx_expr*, cx_expr*);
00460   cx_expr* make_cast(ct_type const*, cx_expr*);
00461 
00462   cx_expr* make_not(cx_expr*);
00463   cx_expr* make_equal(cx_expr*, cx_expr*);
00464   cx_expr* make_less(cx_expr*, cx_expr*);
00465   cx_expr* make_lesseq(cx_expr*, cx_expr*);
00466 
00467   cx_expr* make_assignment(cx_expr* dst, cx_expr* src);
00468 
00469   cx_expr* make_negation(cx_expr* x);
00470   cx_expr* make_sum(cx_expr* x, cx_expr* y);
00471   cx_expr* make_difference(cx_expr* x, cx_expr* y);
00472   cx_expr* make_product(cx_expr* x, cx_expr* y);
00473   cx_expr* make_quotient(cx_expr* x, cx_expr* y);
00474   cx_expr* make_modulus(cx_expr* x, cx_expr* y);
00475 
00476   cx_expr* make_bitnot(cx_expr*);
00477   cx_expr* make_bitand(cx_expr*, cx_expr*);
00478   cx_expr* make_bitor(cx_expr*, cx_expr*);
00479   cx_expr* make_bitxor(cx_expr*, cx_expr*);
00480   cx_expr* make_bitlsh(cx_expr*, cx_expr*);
00481   cx_expr* make_bitrsh(cx_expr*, cx_expr*);
00482 
00483   cx_expr* make_return(cx_expr* x);
00484   cx_expr* make_return();
00485   cx_expr* make_break();
00486   cx_expr* make_while(cx_expr* cond, cx_expr* blk);
00487   cx_expr* make_do_while(cx_expr* blk, cx_expr* cond);
00488 
00489 }}
00490 
00491 #endif

Generated on Sat Sep 7 19:11:17 2002 for more with Doxygen 1.2.13.1. Doxygen 1.2.13.1 is written and copyright 1997-2002 by Dimitri van Heesch.