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-func.hpp"
28
29 #include <klib/symbol.h>
30 #include <klib/printf.h>
31
32 #include "../vdb/schema-parse.h"
33 #include "../vdb/dbmgr-priv.h"
34 #include "../vdb/schema-expr.h"
35
36 using namespace ncbi::SchemaParser;
37 #define YYDEBUG 1
38 #include "schema-ast-tokens.h"
39
40 using namespace std;
41
FunctionDeclaration(ASTBuilder & p_builder)42 FunctionDeclaration :: FunctionDeclaration ( ASTBuilder & p_builder )
43 : m_builder ( p_builder ),
44 m_self ( m_builder . Alloc < SFunction > () ),
45 m_destroy ( true )
46 {
47 if ( m_self != 0 )
48 {
49 VectorInit ( & m_self -> fact . parms, 0, 8 );
50 }
51 }
52
FunctionDeclaration(ASTBuilder & p_builder,SFunction & p_func)53 FunctionDeclaration :: FunctionDeclaration ( ASTBuilder & p_builder, SFunction & p_func )
54 : m_builder ( p_builder ),
55 m_self ( & p_func ),
56 m_destroy ( false )
57 {
58 memset ( m_self, 0, sizeof * m_self );
59 VectorInit ( & m_self -> fact . parms, 0, 8 );
60 m_self -> script = true;
61 }
62
~FunctionDeclaration()63 FunctionDeclaration :: ~FunctionDeclaration ()
64 {
65 if ( m_self != 0 && m_destroy )
66 {
67 SFunctionWhack ( m_self, 0 );
68 }
69 }
70
71 bool
HandleOverload(const AST_FQN & p_fqn,const KSymbol * p_priorDecl)72 FunctionDeclaration :: HandleOverload ( const AST_FQN & p_fqn, const KSymbol * p_priorDecl )
73 {
74 assert ( p_priorDecl != 0 );
75
76 Vector & functions = m_builder . GetSchema () -> func;
77
78 SNameOverload *name = ( SNameOverload* ) p_priorDecl -> u . obj;
79 assert ( name != 0 );
80
81 SFunction *exist = static_cast < SFunction * > ( VectorGet ( & name -> items, 0 ) );
82 assert ( exist != 0 );
83 if ( exist -> script )
84 {
85 if ( ! m_self -> script)
86 {
87 m_builder . ReportError ( p_fqn . GetLocation (), "Overload has to have a body", p_priorDecl -> name );
88 }
89 }
90 else if ( m_self -> script)
91 {
92 m_builder . ReportError ( p_fqn . GetLocation (), "Overload cannot have a body", p_priorDecl -> name );
93 }
94
95 uint32_t idx;
96 rc_t rc = VectorInsertUnique ( & name -> items, m_self, & idx, SFunctionSort );
97 if ( rc == 0 ) // overload added
98 {
99 return m_builder . VectorAppend ( functions, & m_self -> id, m_self );
100 }
101 if ( GetRCState ( rc ) == rcExists )
102 { /* an overload with the same major version exists */
103 /* see if new function trumps old */
104 SFunction *exist = static_cast < SFunction * > ( VectorGet ( & name -> items, idx ) );
105 if ( m_self -> version > exist -> version )
106 {
107 /* insert our function in name overload */
108 void * prior;
109 VectorSwap ( & name -> items, idx, m_self, & prior );
110
111 /* if existing is in the same schema... */
112 if ( ( const void* ) name == exist -> name -> u . obj )
113 {
114 /* need to swap with old */
115 assert ( exist -> id >= VectorStart ( & functions ) );
116 VectorSwap ( & functions, exist -> id, m_self, & prior );
117 m_self -> id = exist -> id;
118 SFunctionWhack ( (SFunction*)prior, 0 );
119 }
120 return true;
121 }
122 }
123 else if ( rc != 0 )
124 {
125 m_builder . ReportRc ( "VectorInsertUnique", rc );
126 }
127 return false;
128 }
129
130 bool
SetName(const AST_FQN & p_fqn,uint32_t p_type,bool p_canOverload,bool p_validate)131 FunctionDeclaration :: SetName ( const AST_FQN & p_fqn,
132 uint32_t p_type,
133 bool p_canOverload,
134 bool p_validate )
135 {
136 if ( m_self == 0 )
137 {
138 return false;
139 }
140
141 m_self -> script = p_type == eScriptFunc;
142 m_self -> untyped = p_type == eUntypedFunc;
143 m_self -> row_length = p_type == eRowLengthFunc;
144 m_self -> validate = p_validate;
145
146 const KSymbol * priorDecl = m_builder . Resolve ( p_fqn, false );
147
148 m_self -> version = p_fqn . GetVersion ();
149 if ( ( m_self -> version & 0xFFFF ) != 0 && priorDecl != 0 && priorDecl -> type == eFunction )
150 {
151 m_builder . ReportError ( "Changing release number is not allowed", p_fqn );
152 return false;
153 }
154
155 if ( priorDecl == 0 )
156 {
157 m_self -> name = m_builder . CreateFqnSymbol ( p_fqn, p_type, m_self );
158 if ( m_self -> name != 0 )
159 {
160 if ( m_builder . CreateOverload ( m_self -> name,
161 m_self,
162 SFunctionSort,
163 m_builder . GetSchema () -> func,
164 m_builder . GetSchema () -> fname,
165 & m_self -> id ) )
166 {
167 m_destroy = false;
168 return true;
169 }
170 }
171 }
172 else
173 {
174 if ( ! p_canOverload || priorDecl -> type == eFactory )
175 {
176 m_builder . ReportError ( "Declared earlier and cannot be overloaded", p_fqn );
177 return false;
178 }
179
180 if ( HandleOverload ( p_fqn, priorDecl ) )
181 { // declared previously, this version not ignored
182 m_self -> name = priorDecl;
183 m_destroy = false;
184 return true;
185 }
186 }
187
188 return false;
189 }
190
191 void
SetReturnType(STypeExpr * p_retType)192 FunctionDeclaration :: SetReturnType ( STypeExpr * p_retType )
193 {
194 if ( m_self != 0 && p_retType != 0 )
195 {
196 m_self -> rt = & p_retType -> dad;
197 }
198 }
199
200 void
AddFactoryParams(Vector & p_sig,const AST & p_params)201 FunctionDeclaration :: AddFactoryParams ( Vector& p_sig, const AST & p_params )
202 {
203 uint32_t count = p_params . ChildrenCount ();
204 for ( uint32_t i = 0; i < count; ++i )
205 {
206 SIndirectConst * param = m_builder . Alloc < SIndirectConst > ();
207 if ( param == 0 )
208 {
209 return;
210 }
211 const AST * p = p_params . GetChild ( i );
212 assert ( p != 0 );
213 assert ( p -> ChildrenCount () == 3 ); // type, ident, control or PT_EMPTY
214
215 STypeExpr * type = m_builder . MakeTypeExpr ( * p -> GetChild ( 0 ) );
216 if ( type != 0 )
217 {
218 param -> td = & type -> dad;
219 }
220
221 param -> name = m_builder . CreateLocalSymbol ( * p -> GetChild ( 1 ),
222 p -> GetChild ( 1 ) -> GetTokenValue (),
223 eFactParam,
224 param );
225
226 if ( m_builder . VectorAppend ( p_sig, & param -> pos, param ) )
227 {
228 param -> expr_id = ++ ( m_builder . GetSchema () -> num_indirect );
229 }
230 else
231 {
232 SIndirectConstWhack ( param, NULL );
233 }
234 }
235 }
236
237 void
SetFactoryParams(const AST & p_sig)238 FunctionDeclaration :: SetFactoryParams ( const AST & p_sig )
239 {
240 if ( m_self != 0 && p_sig . GetTokenType () != PT_EMPTY )
241 { // children: mandatory, optional, isVariadic
242 assert ( p_sig . ChildrenCount () == 3 );
243 m_self -> fact . mand = p_sig . GetChild ( 0 ) -> ChildrenCount ();
244 AddFactoryParams ( m_self -> fact . parms, * p_sig . GetChild ( 0 ) );
245 AddFactoryParams ( m_self -> fact . parms, * p_sig . GetChild ( 1 ) );
246 m_self -> fact . vararg = p_sig . GetChild ( 2 ) -> GetTokenType () != PT_EMPTY;
247 }
248 }
249
250 void
AddFormalParams(Vector & p_sig,const AST & p_params)251 FunctionDeclaration :: AddFormalParams ( Vector& p_sig, const AST & p_params )
252 {
253 uint32_t count = p_params . ChildrenCount ();
254 for ( uint32_t i = 0; i < count; ++i )
255 {
256 SProduction * param = m_builder . Alloc < SProduction > ();
257 if ( param == 0 )
258 {
259 return;
260 }
261 const AST * p = p_params . GetChild ( i );
262 assert ( p != 0 );
263 assert ( p -> ChildrenCount () == 3 ); // type, ident, control or PT_EMPTY
264
265 STypeExpr * type = m_builder . MakeTypeExpr ( * p -> GetChild ( 0 ) );
266 if ( type != 0 )
267 {
268 param -> fd = & type -> dad;
269 }
270
271 param -> name = m_builder . CreateLocalSymbol ( * p -> GetChild ( 1 ),
272 p -> GetChild ( 1 ) -> GetTokenValue (),
273 eFuncParam,
274 param );
275
276 param -> control = p -> GetChild ( 2 ) -> GetTokenType () != PT_EMPTY;
277
278 if ( ! m_builder . VectorAppend ( p_sig, & param -> cid . id, param ) )
279 {
280 SProductionWhack ( param, NULL );
281 }
282 }
283 }
284
285 void
SetFormalParams(const AST & p_sig)286 FunctionDeclaration :: SetFormalParams ( const AST & p_sig )
287 {
288 if ( m_self != 0 && p_sig . GetTokenType () != PT_EMPTY )
289 { // children: mandatory, optional, isVariadic
290 assert ( p_sig . ChildrenCount () == 3 );
291 m_self -> func . mand = p_sig . GetChild ( 0 ) -> ChildrenCount ();
292 AddFormalParams ( m_self -> func . parms, * p_sig . GetChild ( 0 ) );
293 AddFormalParams ( m_self -> func . parms, * p_sig . GetChild ( 1 ) );
294 m_self -> func . vararg = p_sig . GetChild ( 2 ) -> GetTokenType () != PT_EMPTY;
295 }
296 }
297
298 void
SetPhysicalParams()299 FunctionDeclaration :: SetPhysicalParams ()
300 {
301 if ( m_self != 0 )
302 {
303 VectorInit ( & m_self -> func . parms, 0, 1 );
304 m_self -> func . mand = 1;
305 m_self -> func . vararg = false;
306
307 /* create special input symbol */
308 SProduction * parm = m_builder . Alloc < SProduction > ();
309 if ( parm != 0 && m_builder . VectorAppend ( m_self -> func . parms, & parm -> cid . id, parm ) )
310 {
311 /* create special input symbol */
312 String symstr;
313 CONST_STRING ( & symstr, "@" );
314 rc_t rc = KSymTableCreateConstSymbol ( & m_builder . GetSymTab (), & parm -> name, & symstr, eFuncParam, parm );
315 if ( rc == 0 )
316 {
317 VectorInit ( & m_self -> u . script . prod, 0, 8 );
318 }
319 else
320 {
321 m_builder . ReportRc ( "KSymTableCreateConstSymbol", rc );
322 }
323 }
324 else
325 {
326 SProductionWhack ( parm, 0 );
327 }
328 }
329 }
330
331 SIndirectType *
MakeSchemaParamType(const AST_FQN & p_name)332 FunctionDeclaration :: MakeSchemaParamType ( const AST_FQN & p_name )
333 {
334 SIndirectType *ret = m_builder . Alloc < SIndirectType > ();
335 if ( ret != 0 )
336 { /* create symbol */
337 String nameStr;
338 p_name . GetIdentifier ( nameStr );
339 rc_t rc = KSymTableCreateConstSymbol ( & m_builder . GetSymTab (), & ret -> name, & nameStr, eSchemaType, ret );
340 if ( rc == 0 )
341 {
342 if ( m_builder . VectorAppend ( m_builder . GetSchema () -> pt, & ret -> id, ret ) )
343 {
344 /* initialize to raw format,
345 undefined type, and no dimension */
346 ret -> type_id = ++ ( m_builder . GetSchema () -> num_indirect );
347 return ret;
348 }
349 }
350 else
351 {
352 m_builder . ReportRc ( "KSymTableCreateConstSymbol", rc );
353 }
354 SIndirectTypeWhack ( ret, 0 );
355 }
356 return 0;
357 }
358
359 SIndirectConst *
MakeSchemaParamConst(const AST_FQN & p_name)360 FunctionDeclaration :: MakeSchemaParamConst ( const AST_FQN & p_name )
361 {
362 SIndirectConst * ret = m_builder . Alloc < SIndirectConst > ();
363 if ( ret != 0 )
364 { /* create symbol */
365 String nameStr;
366 p_name . GetIdentifier ( nameStr );
367 rc_t rc = KSymTableCreateConstSymbol ( & m_builder . GetSymTab (), & ret -> name, & nameStr, eSchemaParam, ret );
368 if ( rc == 0 )
369 {
370 ret -> expr_id = ++ ( m_builder . GetSchema () -> num_indirect );
371 return ret;
372 }
373 else
374 {
375 m_builder . ReportRc ( "KSymTableCreateConstSymbol", rc );
376 }
377 SIndirectConstWhack ( ret, 0 );
378 }
379 return 0;
380 }
381
382 void
SetSchemaParams(const AST & p_sig)383 FunctionDeclaration :: SetSchemaParams ( const AST & p_sig )
384 {
385 uint32_t count = p_sig . ChildrenCount ();
386 for ( uint32_t i = 0; i < count; ++i )
387 {
388 const AST & p = * p_sig . GetChild ( i );
389 if ( p . ChildrenCount () == 1 ) // type
390 {
391 SIndirectType * formal = MakeSchemaParamType ( * ToFQN ( p . GetChild ( 0 ) ) );
392 if ( formal != 0 )
393 {
394 /* record positional */
395 if ( m_builder . VectorAppend ( m_self -> type, 0, formal ) )
396 {
397 formal -> pos = i;
398 continue;
399 }
400 SIndirectTypeWhack ( formal, 0 );
401 }
402 break;
403 }
404 else // value
405 {
406 STypeExpr * type = m_builder . MakeTypeExpr ( * p . GetChild ( 0 ) );
407 if ( type != 0 )
408 {
409 const AST_FQN & ident = * ToFQN ( p . GetChild ( 1 ) );
410 // scalar unsigned int type required
411 if ( type -> dt != 0 &&
412 type -> dt -> domain == ddUint &&
413 type -> fd . td. dim == 1 )
414 {
415 SIndirectConst * formal = MakeSchemaParamConst ( ident );
416 if ( formal != 0 )
417 {
418 /* record positional */
419 if ( m_builder . VectorAppend ( m_self -> schem, 0, formal ) )
420 {
421 formal -> td = & type -> dad;
422 formal -> pos = i;
423 continue; // success
424 }
425 SIndirectConstWhack ( formal, 0 );
426 }
427 }
428 else
429 {
430 String nameStr;
431 ident . GetIdentifier ( nameStr );
432 m_builder . ReportError ( ident . GetLocation (), "Not a scalar unsigned integer", nameStr );
433 }
434 SExpressionWhack ( & type -> dad );
435 }
436 break;
437 }
438 }
439 }
440
441 void
HandleStatement(const AST & p_stmt)442 FunctionDeclaration :: HandleStatement ( const AST & p_stmt )
443 {
444 switch ( p_stmt . GetTokenType () )
445 {
446 case KW_return:
447 {
448 if ( m_self -> u . script . rtn == 0 )
449 {
450 assert ( p_stmt . ChildrenCount () == 1 );
451 m_self -> u . script . rtn = ToExpr ( p_stmt . GetChild ( 0 ) ) -> MakeExpression ( m_builder );
452 }
453 else
454 {
455 m_builder . ReportError ( p_stmt . GetLocation (),
456 "Multiple return statements in a function",
457 m_self -> name -> name );
458 }
459 }
460 break;
461 case PT_PRODSTMT:
462 {
463 assert ( p_stmt . ChildrenCount () == 3 );
464 const AST * ident = p_stmt . GetChild ( 1 );
465 assert ( ident -> ChildrenCount () == 1 );
466 m_builder . AddProduction ( * ident,
467 m_self -> u . script . prod,
468 ident -> GetChild ( 0 ) -> GetTokenValue (),
469 * ToExpr ( p_stmt . GetChild ( 2 ) ),
470 p_stmt . GetChild ( 0 ) );
471 }
472 break;
473 case PT_EMPTY:
474 break;
475 default:
476 m_builder . ReportError ( p_stmt . GetLocation (), "Unsupported statement type", p_stmt . GetTokenType () );
477 break;
478 }
479 }
480
481 void
HandleScript(const AST & p_body,const String & p_funcName)482 FunctionDeclaration :: HandleScript ( const AST & p_body, const String & p_funcName )
483 {
484 uint32_t stmtCount = p_body . ChildrenCount ();
485 for ( uint32_t i = 0 ; i < stmtCount; ++ i )
486 {
487 HandleStatement ( * p_body . GetChild ( i ) );
488 }
489 if ( m_self -> script && m_self -> u . script . rtn == 0 )
490 {
491 m_builder . ReportError ( p_body . GetLocation (), "Schema function does not contain a return statement", p_funcName );
492 }
493 }
494
495 void
SetPrologue(const AST & p_prologue)496 FunctionDeclaration :: SetPrologue ( const AST & p_prologue )
497 {
498 switch ( p_prologue . GetTokenType () )
499 {
500 case PT_IDENT:
501 { // renaming
502 const AST_FQN & fqn = * ToFQN ( & p_prologue );
503 const KSymbol * priorDecl = m_builder . Resolve ( fqn, false );
504 if ( priorDecl != 0 )
505 {
506 if ( priorDecl -> type == eFunction || priorDecl -> type == eFactory )
507 {
508 m_self -> u. ext . fact = priorDecl;
509 }
510 else
511 {
512 m_builder . ReportError ( "Cannot be used as factory", fqn );
513 }
514 }
515 else
516 {
517 m_self -> u. ext . fact = m_builder . CreateFqnSymbol ( fqn, eFactory, 0 );
518 }
519 }
520 break;
521 case PT_EMPTY:
522 { // function body
523 if ( p_prologue . ChildrenCount () > 0 )
524 {
525 if ( m_self -> fact . vararg )
526 {
527 m_builder . ReportError ( p_prologue . GetLocation (),
528 "Function with factory varargs cannot have a body",
529 m_self -> name -> name );
530 }
531 else
532 {
533 rc_t rc = KSymTablePushScope ( & m_builder . GetSymTab (), SchemaScope () );
534 if ( rc == 0 )
535 {
536 rc = KSymTablePushScope ( & m_builder . GetSymTab (), FunctionScope () );
537 if ( rc == 0 )
538 {
539 HandleScript ( p_prologue, m_self -> name -> name );
540 KSymTablePopScope ( & m_builder . GetSymTab () );
541 }
542 else
543 {
544 m_builder . ReportRc ( "KSymTablePushScope", rc );
545 }
546 KSymTablePopScope ( & m_builder . GetSymTab () );
547 }
548 else
549 {
550 m_builder . ReportRc ( "KSymTablePushScope", rc );
551 }
552 }
553 }
554 }
555 break;
556 default:
557 assert (false);
558 }
559 }
560
561 // Function-building methods from ASTBuilder
562
563 AST *
UntypedFunctionDecl(const Token * p_token,AST_FQN * p_name)564 ASTBuilder :: UntypedFunctionDecl ( const Token* p_token, AST_FQN* p_name )
565 {
566 AST * ret = new AST ( p_token, p_name );
567 FunctionDeclaration ( *this ) . SetName ( * p_name, eUntypedFunc, false, false );
568 return ret;
569 }
570
571 AST *
RowlenFunctionDecl(const Token * p_token,AST_FQN * p_name)572 ASTBuilder :: RowlenFunctionDecl ( const Token* p_token, AST_FQN* p_name )
573 {
574 AST * ret = new AST ( p_token, p_name );
575 FunctionDeclaration ( *this ) . SetName ( * p_name, eRowLengthFunc, false, false );
576 return ret;
577 }
578
579 AST *
FunctionDecl(const Token * p_token,bool p_script,AST * p_schema,AST * p_returnType,AST_FQN * p_name,AST * p_fact,AST * p_params,AST * p_prologue)580 ASTBuilder :: FunctionDecl ( const Token * p_token,
581 bool p_script,
582 AST * p_schema,
583 AST * p_returnType,
584 AST_FQN * p_name,
585 AST * p_fact,
586 AST * p_params,
587 AST * p_prologue )
588 {
589 AST * ret = new AST ( p_token, p_schema, p_returnType, p_name, p_fact, p_params, p_prologue );
590
591 bool isValidate = p_token -> GetType () == PT_VALIDATE;
592
593 FunctionDeclaration func ( *this );
594 if ( func . SetName ( * p_name,
595 ( p_script || ( p_prologue -> GetTokenType () == PT_EMPTY && p_prologue -> ChildrenCount () > 0 ) )? eScriptFunc : eFunction,
596 true,
597 isValidate ) )
598 {
599 rc_t rc = 0;
600 bool hasSchemaParms = p_schema -> ChildrenCount () != 0;
601 if ( hasSchemaParms )
602 {
603 rc = KSymTablePushScope ( & m_symtab, func . SchemaScope () );
604 if ( rc == 0 )
605 {
606 func . SetSchemaParams ( * p_schema );
607 }
608 else
609 {
610 ReportRc ( "KSymTablePushScope", rc );
611 hasSchemaParms = false; // do not pop later on
612 }
613 }
614
615 // if hasSchemaParms, we are still in its scope, in order to evaluate the return type
616 bool isVoid = p_returnType -> ChildrenCount () == 0;
617 if ( isValidate )
618 { // require return type to be void, 2 mandatory parameters, no optional or varargs
619 if ( ! isVoid )
620 {
621 ReportError ( "Validate functions have to return void", * p_name );
622 }
623 if ( p_params -> GetChild ( 0 ) -> ChildrenCount () != 2 )
624 {
625 ReportError ( "Validate functions have to have 2 mandatory parameters", * p_name);
626 }
627 if ( p_params -> GetChild ( 1 ) -> ChildrenCount () != 0 )
628 {
629 ReportError ( "Validate functions cannot have optional parameters", * p_name);
630 }
631 if ( p_params -> GetChild ( 2 ) -> GetTokenType () != PT_EMPTY )
632 {
633 ReportError ( "Validate functions cannot have variable parameters", * p_name);
634 }
635 }
636 else if ( isVoid )
637 {
638 ReportError ( "Only validate functions can return void", * p_name );
639 }
640 else
641 {
642 func . SetReturnType ( MakeTypeExpr ( * p_returnType ) );
643 }
644
645 rc = KSymTablePushScope ( & m_symtab, func . FunctionScope () );
646 if ( rc == 0 )
647 {
648 if ( p_fact -> GetTokenType () != PT_EMPTY )
649 {
650 func . SetFactoryParams ( * p_fact );
651 }
652
653 func . SetFormalParams ( * p_params );
654
655 KSymTablePopScope ( & m_symtab );
656 }
657 else
658 {
659 ReportRc ( "KSymTablePushScope", rc );
660 }
661
662 if ( hasSchemaParms )
663 { // now, can pop schema params' scope
664 KSymTablePopScope ( & m_symtab );
665 }
666
667 if ( p_prologue != 0 )
668 {
669 func . SetPrologue ( * p_prologue );
670 }
671 }
672
673 return ret;
674 }
675