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