1 /*===========================================================================
2  *
3  *                            PUBLIC DOMAIN NOTICE
4  *               National Center for Biotechnology Information
5  *
6  *  This software/database is a "United States Government Work" under the
7  *  terms of the United States Copyright Act.  It was written as part of
8  *  the author's official duties as a United States Government employee and
9  *  thus cannot be copyrighted.  This software/database is freely available
10  *  to the public for use. The National Library of Medicine and the U.S.
11  *  Government have not placed any restriction on its use or reproduction.
12  *
13  *  Although all reasonable efforts have been taken to ensure the accuracy
14  *  and reliability of the software and data, the NLM and the U.S.
15  *  Government do not and cannot warrant the performance or results that
16  *  may be obtained by using this software or data. The NLM and the U.S.
17  *  Government disclaim all warranties, express or implied, including
18  *  warranties of performance, merchantability or fitness for any particular
19  *  purpose.
20  *
21  *  Please cite the author in any work or product based on this material.
22  *
23  * ===========================================================================
24  *
25  */
26 
27 #include "ASTBuilder.hpp"
28 
29 #include <klib/symbol.h>
30 
31 #include "../vdb/schema-parse.h"
32 #include "../vdb/schema-expr.h"
33 
34 using namespace ncbi::SchemaParser;
35 #define YYDEBUG 1
36 #include "schema-ast-tokens.h"
37 
38 using namespace std;
39 
40 class ViewDeclaration // Wrapper around SView
41 {
42 public:
43     ViewDeclaration ( ASTBuilder & p_builder );
44     ~ViewDeclaration ();
45 
GetSelf() const46     const SView * GetSelf () const { return m_self; }
47 
48     bool SetName ( const AST_FQN &  p_fqn );
49     void HandleParameters ( const AST & p_params );
50     void HandleParents ( const AST & p_parents );
51     void HandleBody ( const AST & p_body );
52 
Scope()53     BSTree * Scope () { return m_self == 0 ? 0 : & m_self -> scope; }
54 
55 private:
56     bool HandleOverload ( const AST_FQN & p_fqn, const KSymbol * p_priorDecl );
57     void AddColumn ( const AST & p_type, const AST & p_ident, const AST_Expr & p_expr );
58     bool Extend ( const Token :: Location & p_loc, const SView *dad, const AST & p_params );
59     bool CheckForCollisions ( const SView & p_table, const String *& p_name );
60     bool CopyColumnNames ( const SNameOverload *orig );
61     bool ScanVirtuals ( const Token :: Location & p_loc, Vector & p_byParent );
62     void HandleStatement ( const AST & p_stmt );
63     bool AddNewColumn ( SColumn & p_col, String & p_name );
64     bool InitParentInstance( SViewInstance * p_self, const SView * p_dad, const AST & p_params );
65 
66     ASTBuilder &    m_builder;
67     SView *         m_self;
68 };
69 
ViewDeclaration(ASTBuilder & p_builder)70 ViewDeclaration :: ViewDeclaration ( ASTBuilder & p_builder )
71 :   m_builder ( p_builder ),
72     m_self ( m_builder . Alloc < SView > () )
73 {
74     // prepare vectors
75     VectorInit ( & m_self -> params, 0, 4 );
76     VectorInit ( & m_self -> parents, 0, 4 );
77     VectorInit ( & m_self -> overrides, 0, 4 );
78     VectorInit ( & m_self -> col, 0, 16 );
79     VectorInit ( & m_self -> cname, 0, 16 );
80     VectorInit ( & m_self -> prod, 0, 64 );
81     VectorInit ( & m_self -> vprods, 1, 16 );
82     VectorInit ( & m_self -> syms, 1, 32 );
83 }
84 
~ViewDeclaration()85 ViewDeclaration :: ~ViewDeclaration ()
86 {
87     // m_self gets added to the schema or freed on error, no need to free here
88 }
89 
90 bool
SetName(const AST_FQN & p_fqn)91 ViewDeclaration :: SetName ( const AST_FQN &  p_fqn )
92 {
93     assert ( m_self != 0 );
94 
95     m_self -> version = p_fqn . GetVersion ();
96 
97     const KSymbol * priorDecl = m_builder . Resolve ( p_fqn, false );
98     if ( priorDecl == 0 )
99     {
100         m_self -> name = m_builder . CreateFqnSymbol ( p_fqn, eView, m_self );
101         if ( m_self -> name != 0 &&
102                 m_builder . CreateOverload ( m_self -> name,
103                                             m_self,
104                                             SViewSort,
105                                             m_builder . GetSchema () -> view,
106                                             m_builder . GetSchema () -> vname,
107                                             & m_self -> id ) )
108         {
109             return true;
110         }
111     }
112     else if ( HandleOverload ( p_fqn, priorDecl ) )
113     {   // declared previously, this declaration not ignored
114         m_self -> name = priorDecl;
115         return true;
116     }
117 
118     SViewWhack ( m_self, 0 );
119     m_self = 0;
120     return false;
121 }
122 
123 bool
HandleOverload(const AST_FQN & p_fqn,const KSymbol * p_priorDecl)124 ViewDeclaration :: HandleOverload ( const AST_FQN & p_fqn, const KSymbol * p_priorDecl )
125 {
126     assert ( p_priorDecl != 0 );
127 
128     Vector & views = m_builder . GetSchema () -> view;
129 
130     SNameOverload *name = ( SNameOverload* ) p_priorDecl -> u . obj;
131     assert ( name != 0 );
132     uint32_t idx;
133     rc_t rc = VectorInsertUnique ( & name -> items, m_self, & idx, SViewSort );
134     if ( rc == 0 ) // overload added
135     {
136         return m_builder . VectorAppend ( views, & m_self -> id, m_self );
137     }
138     if ( GetRCState ( rc ) == rcExists )
139     {   /* an overload with the same major version exists */
140         /* see if new function trumps old */
141         SView *exist = static_cast < SView * > ( VectorGet ( & name -> items, idx ) );
142         if ( m_self -> version == exist -> version )
143         {
144             m_builder . ReportError ( "This version is already declared", p_fqn );
145         }
146         else if ( m_self -> version > exist -> version )
147         {
148             /* insert our function in name overload */
149             void * prior;
150             VectorSwap ( & name -> items, idx, m_self, & prior );
151 
152             /* if existing is in the same schema... */
153             if ( ( const void* ) name == exist -> name -> u . obj )
154             {
155                 /* need to swap with old */
156                 assert ( exist -> id >= VectorStart ( & views ) );
157                 VectorSwap ( & views, exist -> id, m_self, & prior );
158                 m_self -> id = exist -> id;
159                 SViewWhack ( ( SView * ) prior, 0 );
160             }
161             return true;
162         }
163     }
164     else if ( rc != 0 )
165     {
166         m_builder . ReportRc ( "VectorInsertUnique", rc );
167     }
168     return false;
169 }
170 
171 void
HandleParameters(const AST & p_params)172 ViewDeclaration :: HandleParameters ( const AST & p_params )
173 {
174     uint32_t count = p_params . ChildrenCount ();
175     for ( uint32_t i = 0; i < count; ++i )
176     {
177         const AST & p = * p_params . GetChild ( i );
178         assert ( p . GetTokenType () == PT_VIEWPARAM );
179         assert ( p . ChildrenCount () == 2 );
180         // child [ 0 ]: fqn_opt_vers, a table or a view
181         // child [ 1 ]: ident, for the symtab
182         const AST_FQN & fqn = * ToFQN ( p . GetChild ( 0 ) );
183         const AST & nameNode = * p . GetChild ( 1 );
184         assert ( nameNode . GetTokenType () == PT_IDENT );
185         assert ( nameNode . ChildrenCount () == 1 );
186         String name;
187         StringInitCString ( & name, nameNode . GetChild ( 0 ) -> GetTokenValue () );
188         const KSymbol * sym = m_builder . Resolve ( fqn ); // will report unknown name
189         if ( sym != 0 )
190         {
191             const void * versioned = 0;
192             switch ( sym -> type )
193             {
194             case eTable:
195                 versioned = m_builder . SelectVersion ( fqn, * sym, STableCmp );
196                 break;
197             case eView:
198                 versioned = m_builder . SelectVersion ( fqn, * sym, SViewCmp );
199                 break;
200             default:
201                 m_builder . ReportError ( "Cannot be used as a view parameter", fqn );
202                 break;
203             }
204             if ( versioned != 0 )
205             {
206                 KSymbol * local = m_builder . CreateLocalSymbol ( nameNode, name, sym -> type, versioned );
207                 if ( local != 0 )
208                 {
209                     m_builder . VectorAppend ( m_self -> params, 0, local );
210                 }
211             }
212         }
213     }
214 }
215 
216 bool
CheckForCollisions(const SView & p_view,const String * & p_name)217 ViewDeclaration :: CheckForCollisions ( const SView & p_view, const String *& p_name )
218 {
219     /* test column names */
220     uint32_t start = VectorStart ( & p_view . cname );
221     uint32_t count = VectorLength ( & p_view . cname );
222     for ( uint32_t i = 0; i < count; ++ i )
223     {
224         const SNameOverload * no = static_cast < const SNameOverload * > ( VectorGet ( & p_view . cname, start + i ) );
225         if  ( ! m_builder . CheckForColumnCollision ( no -> name ) )
226         {
227             p_name = & no -> name -> name;
228             return false;
229         }
230     }
231 
232     /* test production names */
233     start = VectorStart ( & p_view .prod );
234     count = VectorLength ( & p_view . prod );
235     for ( uint32_t i = 0; i < count; ++ i )
236     {
237         const SProduction * prod = static_cast < const SProduction * > ( VectorGet ( & p_view . prod, start + i ) );
238         if  ( ! m_builder . CheckForColumnCollision ( prod -> name ) )
239         {
240             p_name = & prod -> name -> name;
241             return false;
242         }
243     }
244 
245     return true;
246 }
247 
248 bool
CopyColumnNames(const SNameOverload * orig)249 ViewDeclaration :: CopyColumnNames ( const SNameOverload *orig )
250 {
251     rc_t rc;
252     SView *self= m_self;
253     SNameOverload *copy;
254     const KSymbol *sym = ( const KSymbol* ) BSTreeFind ( & self -> scope, & orig -> name -> name, KSymbolCmp );
255     if ( sym == NULL )
256     {
257         rc = SNameOverloadCopy ( & self -> scope, & copy, orig );
258         if ( rc == 0 )
259         {
260             if ( ! m_builder . VectorAppend ( self -> cname, & copy -> cid . id, copy ) )
261             {
262                 SNameOverloadWhack ( copy, NULL );
263                 return false;
264             }
265         }
266         else
267         {
268             m_builder . ReportRc ( "SNameOverloadCopy", rc );
269             return false;
270         }
271     }
272     else
273     {
274         copy = ( SNameOverload* ) sym -> u . obj;
275         assert ( copy -> cid . ctx == orig -> cid . ctx );
276         rc = VectorMerge ( & copy -> items, true, & orig -> items, SColumnSort );
277         if ( rc != 0 )
278         {
279             m_builder . ReportRc ( "VectorMerge", rc );
280             return false;
281         }
282     }
283 
284     return true;
285 }
286 
287 bool
InitParentInstance(SViewInstance * p_inst,const SView * p_parent,const AST & p_params)288 ViewDeclaration :: InitParentInstance( SViewInstance * p_inst, const SView * p_parent, const AST & p_params )
289 {
290     p_inst -> dad = p_parent;
291     uint32_t count = p_params . ChildrenCount ();
292     VectorInit ( & p_inst -> params, 0, count );
293     if ( count != VectorLength ( & p_parent -> params ) )
294     {
295         m_builder . ReportError ( p_params . GetLocation(), "Wrong number of parameters for a view instantiation" );
296         return false;
297     }
298     for ( uint32_t i = 0; i < count; ++i )
299     {
300         const AST_FQN & ident = * ToFQN ( p_params . GetChild ( i ) );
301         const KSymbol * sym = m_builder . Resolve ( ident );
302         if ( sym != 0 )
303         {
304             switch ( sym -> type )
305             {
306             case eTable:
307             case eView:
308                 {   /* verify type */
309                     const KSymbol * parentsParam = static_cast < const KSymbol * > ( VectorGet ( & p_parent -> params, i ) );
310                     if ( parentsParam -> u . obj != sym -> u . obj )
311                     {
312                         m_builder . ReportError ( "Wrong type of a view's parameter", ident );
313                         return false;
314                     }
315                     if ( ! m_builder . VectorAppend ( p_inst -> params, 0, sym ) )
316                     {
317                         return false;
318                     }
319                 }
320                 break;
321             default:
322                 m_builder . ReportError ( "A view's parameter has to be a table or a view", ident );
323                 return false;
324             }
325         }
326         else
327         {
328             return false;
329         }
330     }
331     return true;
332 }
333 
334 static
335 int64_t
SViewNameCmp(const void * key,const void * n)336 CC SViewNameCmp ( const void * key, const void * n )
337 {
338     const SView * a = ( const SView * ) key;
339     const SViewInstance * b = (const SViewInstance *)n;
340     return StringCompare ( & a -> name -> name, & b -> dad -> name -> name );
341 }
342 
343 bool
Extend(const Token::Location & p_loc,const SView * p_dad,const AST & p_params)344 ViewDeclaration :: Extend ( const Token :: Location & p_loc, const SView * p_dad, const AST & p_params )
345 {
346     /* reject if direct parent already in the ancestry */
347     if ( VectorFind ( & m_self -> parents, p_dad, NULL, SViewNameCmp ) != NULL ||
348          VectorFind ( & m_self -> overrides, & p_dad -> id, NULL, SViewOverridesCmp ) != NULL )
349     {
350         m_builder . ReportError ( p_loc, "Same view inherited from more than once", p_dad -> name -> name );
351         return false;
352     }
353 
354     /* test for any collisions */
355     rc_t rc = push_view_scope ( & m_builder . GetSymTab (), m_self );
356     if ( rc != 0 )
357     {
358         m_builder . ReportRc ( "push_tbl_scope", rc );
359         return false;
360     }
361 
362     const String * name;
363     if ( ! CheckForCollisions ( * p_dad, name ) )
364     {
365         m_builder . ReportError ( p_loc, "Duplicate symbol in parent view hierarchy", * name );
366         pop_view_scope ( & m_builder . GetSymTab (), m_self );
367         return false;
368     }
369 
370     pop_view_scope ( & m_builder . GetSymTab (), m_self );
371 
372     {   /* add "dad" and grandparents to parent list */
373         SViewInstance * parent = m_builder . Alloc < SViewInstance > ();
374         if ( parent == 0 )
375         {
376             return false;
377         }
378         if ( ! InitParentInstance ( parent, p_dad, p_params ) ||
379             ! m_builder . VectorAppend ( m_self -> parents, NULL, parent ) )
380         {
381             SViewInstanceWhack ( parent, 0 );
382             return false;
383         }
384     }
385 
386     { /* copy column names from parent - should already contain all grandparents */
387         uint32_t start = VectorStart ( & p_dad -> cname );
388         uint32_t count = VectorLength ( & p_dad -> cname );
389         for ( uint32_t i = 0; i < count; ++ i )
390         {
391             const SNameOverload * ovl = static_cast < const SNameOverload * > ( VectorGet ( & p_dad -> cname, start + i ) );
392             if ( ! CopyColumnNames ( ovl ) )
393             {
394                 return false;
395             }
396         }
397     }
398 
399     /* add "dad" to overrides */
400     rc = SViewOverridesMake ( & m_self -> overrides, p_dad, & p_dad -> vprods );
401     if ( rc == 0 )
402     {
403         /* add all grandparents */
404         uint32_t start = VectorStart ( & p_dad -> overrides );
405         uint32_t count = VectorLength ( & p_dad -> overrides );
406         for ( uint32_t i = 0; i < count; ++ i )
407         {
408             const SViewOverrides * ovr = static_cast < const SViewOverrides * > ( VectorGet ( & p_dad -> overrides, start + i ) );
409             rc = SViewOverridesMake ( & m_self -> overrides, ovr -> dad, & ovr -> by_parent );
410             if ( rc != 0 && GetRCState ( rc ) != rcExists)
411             {
412                 m_builder . ReportRc ( "STableOverridesMake", rc );
413                 return false;
414             }
415         }
416     }
417     else if ( GetRCState ( rc ) != rcExists )
418     {
419         m_builder . ReportRc ( "STableOverridesMake", rc );
420         return false;
421     }
422 
423     return true;
424 }
425 
426 void
HandleParents(const AST & p_parents)427 ViewDeclaration :: HandleParents ( const AST & p_parents )
428 {
429     if ( p_parents . GetTokenType () == PT_VIEWPARENTS )
430     {
431         assert ( p_parents . ChildrenCount () == 1 );
432         const AST & parents = * p_parents . GetChild ( 0 );
433         uint32_t count = parents . ChildrenCount ();
434         for ( uint32_t i = 0; i < count; ++i )
435         {
436             const AST & viewParent = * parents . GetChild ( i );
437             assert ( viewParent . GetTokenType () == PT_VIEWPARENT );
438             assert ( viewParent . ChildrenCount () == 2 );
439             // PT_VIEWPARENT: fqn_opt_vers view_parent_parms
440             const AST_FQN & parent = * ToFQN ( viewParent . GetChild ( 0 ) );
441             const KSymbol * parentDecl = m_builder . Resolve ( parent ); // will report unknown name
442             if ( parentDecl != 0 )
443             {
444                 if ( parentDecl -> type == eView )
445                 {
446                     const SView * dad = static_cast < const SView * > ( m_builder . SelectVersion ( parent, * parentDecl, SViewCmp ) );
447                     if ( dad != 0 )
448                     {
449                         Extend ( parent . GetLocation (), dad, * viewParent . GetChild ( 1 ) );
450                     }
451                 }
452                 else
453                 {
454                     m_builder . ReportError ( "A view's parent has to be a view", parent );
455                 }
456             }
457         }
458     }
459 }
460 
461 bool
AddNewColumn(SColumn & p_col,String & p_name)462 ViewDeclaration :: AddNewColumn ( SColumn & p_col, String & p_name )
463 {   // new column: add p_col to m_self -> col, a new overload to m_self -> cname
464     rc_t rc = KSymTableCreateConstSymbol ( & m_builder . GetSymTab (), & p_col . name, & p_name, eColumn, & p_col );
465     if ( rc != 0 )
466     {
467         m_builder . ReportRc ( "KSymTableCreateConstSymbol", rc );
468         return false;
469     }
470     return m_builder .CreateOverload ( p_col . name,
471                                        & p_col,
472                                        SColumnSort,
473                                        m_self -> col,
474                                        m_self -> cname,
475                                        & p_col . cid . id );
476 }
477 
478 void
AddColumn(const AST & p_type,const AST & p_ident,const AST_Expr & p_expr)479 ViewDeclaration :: AddColumn ( const AST & p_type, const AST & p_ident, const AST_Expr & p_expr )
480 {
481     assert ( p_ident . GetTokenType () == PT_IDENT );
482 
483     SColumn * c = m_builder . Alloc < SColumn > ();
484     if ( c != 0 )
485     {
486         c -> read_only = true;
487 
488         m_builder . TypeSpec ( p_type, c -> td );
489 
490         const char * ident = p_ident . GetChild ( 0 ) -> GetTokenValue ();
491         String name;
492         StringInitCString ( & name, ident );
493         KSymbol * priorDecl = const_cast < KSymbol * > ( m_builder . Resolve ( p_ident . GetLocation (), ident, false ) );
494         if ( priorDecl == 0 )
495         {
496             if ( ! AddNewColumn ( * c, name ) )
497             {
498                 SColumnWhack ( c, 0 );
499                 return;
500             }
501         }
502         else // column name seen before
503         {
504             switch ( priorDecl -> type )
505             {
506             case eForward:
507                 {
508                     c -> name = priorDecl;
509                     priorDecl -> type = eColumn;
510                     if ( ! m_builder .CreateOverload ( c -> name,
511                                                         c,
512                                                         SColumnSort,
513                                                         m_self -> col,
514                                                         m_self -> cname,
515                                                         0 ) )
516                     {
517                         SColumnWhack ( c, 0 );
518                         return;
519                     }
520                 }
521                 break;
522             case eColumn:
523                 {
524                     SNameOverload * ovl = ( SNameOverload* ) priorDecl -> u . obj;
525                     if ( VectorFind ( & ovl -> items, & c -> td, NULL, SColumnCmp ) != NULL )
526                     {
527                         m_builder . ReportError ( p_ident . GetLocation (), "Column already defined", ident );
528                         SColumnWhack ( c, 0 );
529                         return;
530                     }
531                     c -> name = priorDecl;
532                     // add column to m_self -> col
533                     if ( ! m_builder . VectorAppend ( m_self -> col, 0, c ) )
534                     {
535                         SColumnWhack ( c, 0 );
536                         return;
537                     }
538                     // add a column overload
539                     rc_t rc = VectorInsertUnique ( & ovl -> items, c, NULL, SColumnSort );
540                     if ( rc != 0 )
541                     {
542                         m_builder . ReportRc ( "VectorInsertUnique", rc );
543                         SColumnWhack ( c, 0 );
544                         return;
545                     }
546                 }
547                 break;
548             case eVirtual:
549                 m_builder . ReportError ( p_ident . GetLocation (), "Virtual production defined as a column", ident );
550                 SColumnWhack ( c, 0 );
551                 return;
552             default:
553                 /* allow names defined in scopes other than table and intrinsic */
554                 if ( KSymTableFindShallow ( & m_builder . GetSymTab (), & name ) != 0 ||
555                     KSymTableFindIntrinsic ( & m_builder . GetSymTab (), & name ) )
556                 {
557                     m_builder . ReportError ( p_ident . GetLocation (), "Column name already in use", ident );
558                     SColumnWhack ( c, 0 );
559                     return;
560                 }
561                 else if ( ! AddNewColumn ( * c, name ) )
562                 {
563                     SColumnWhack ( c, 0 );
564                     return;
565                 }
566                 break;
567             }
568         }
569 
570         // type checking/conversion is supposed to be done in the run time, like for v1 tables
571         c -> read = p_expr . MakeExpression ( m_builder );
572     }
573 }
574 
575 void
HandleStatement(const AST & p_stmt)576 ViewDeclaration :: HandleStatement ( const AST & p_stmt )
577 {
578     switch ( p_stmt . GetTokenType () )
579     {
580     case PT_PRODSTMT:
581         {   // typespec ident cond_expr
582             assert ( p_stmt . ChildrenCount () == 3 );
583             const AST * datatype = p_stmt . GetChild ( 0 );
584             const AST * ident = p_stmt . GetChild ( 1 );
585             const AST * expr = p_stmt . GetChild ( 2 );
586             assert ( ident -> ChildrenCount () == 1 );
587             m_builder . AddProduction ( * ident,
588                                         m_self -> prod,
589                                         ident -> GetChild ( 0 ) -> GetTokenValue (),
590                                         * ToExpr ( expr ),
591                                         datatype );
592         }
593         break;
594     case PT_COLUMN:
595         {   // typespec ident cond_expr
596             assert ( p_stmt . ChildrenCount () == 3 );
597             AddColumn ( * p_stmt . GetChild ( 0 ), * p_stmt . GetChild ( 1 ), * ToExpr ( p_stmt . GetChild ( 2 ) ) );
598         }
599         break;
600 
601     case PT_EMPTY:
602         break;
603 
604     default:
605         assert ( false );
606     }
607 }
608 
609 void
HandleBody(const AST & p_body)610 ViewDeclaration :: HandleBody ( const AST & p_body )
611 {
612     rc_t rc = push_view_scope ( & m_builder . GetSymTab (), m_self );
613     if ( rc == 0 )
614     {
615         /* scan override views for virtual symbols */
616         uint32_t start = VectorStart ( & m_self -> overrides );
617         uint32_t count = VectorLength ( & m_self -> overrides );
618         for ( uint32_t i = 0; i < count; ++ i )
619         {
620             SViewOverrides * ov = static_cast < SViewOverrides * > ( VectorGet ( & m_self -> overrides, start + i ) );
621             if ( ! m_builder . ScanVirtuals ( p_body . GetLocation (), ov -> by_parent ) )
622             {
623                 pop_view_scope ( & m_builder . GetSymTab (), m_self );
624                 return;
625             }
626         }
627 
628         /* handle view declarations */
629         count = p_body . ChildrenCount ();
630         for ( uint32_t i = 0 ; i < count; ++ i )
631         {
632             HandleStatement ( * p_body . GetChild ( i ) );
633         }
634 
635         SViewScanData pb;
636         pb . self = m_self;
637         pb . rc = 0;
638 
639         /* scan view scope for unresolved forward references */
640         if ( BSTreeDoUntil ( & m_self -> scope, false, view_fwd_scan, & pb ) )
641         {
642             m_builder . ReportRc ( "view_fwd_scan", pb . rc );
643         }
644 
645         pop_view_scope ( & m_builder . GetSymTab (), m_self );
646 
647         /* fix forward references */
648         if ( rc == 0 )
649         {
650             rc = view_fix_forward_refs ( m_self );
651             if ( rc != 0 )
652             {
653                 m_builder . ReportRc ( "table_fix_forward_refs", rc );
654             }
655         }
656 
657         view_set_context ( m_self, m_builder . NextContextId () );
658     }
659     else
660     {
661         m_builder . ReportRc ( "push_view_scope", rc );
662     }
663 }
664 
665 AST *
ViewDef(const Token * p_token,AST_FQN * p_name,AST * p_params,AST * p_parents,AST * p_body)666 ASTBuilder :: ViewDef ( const Token * p_token, AST_FQN * p_name, AST * p_params, AST * p_parents, AST * p_body )
667 {
668     AST * ret = new AST ( p_token, p_name, p_params, p_parents, p_body );
669 
670     ViewDeclaration view ( * this );
671     assert ( p_name != 0 );
672     if ( view . SetName ( * p_name ) )
673     {
674         rc_t rc = KSymTablePushScope ( & m_symtab, view . Scope () );
675         if ( rc == 0 )
676         {
677             assert ( p_params != 0 );
678             view. HandleParameters ( * p_params );
679             assert ( p_parents != 0 );
680             view. HandleParents ( * p_parents );
681             assert ( p_body != 0 );
682             m_view = view . GetSelf ();
683             view. HandleBody ( * p_body );
684             m_view = 0;
685 
686             KSymTablePopScope ( & m_symtab );
687         }
688         else
689         {
690             ReportRc ( "KSymTablePushScope", rc );
691         }
692     }
693     return ret;
694 }
695 
696