1 /* Basic ops on symbols.
2 */
3
4 /*
5
6 Copyright (C) 1991-2003 The National Gallery
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along
19 with this program; if not, write to the Free Software Foundation, Inc.,
20 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22 */
23
24 /*
25
26 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27
28 */
29
30 #include "ip.h"
31
32 /* All debug
33 #define DEBUG
34 */
35
36 /* Just trace create/destroy.
37 #define DEBUG_MAKE
38 */
39
40 /* Time recomputes.
41 #define DEBUG_TIME
42 */
43
44 /* Show symbols as we recalc
45 #define DEBUG_RECALC
46 */
47
48 /* If DEBUG is on, make sure other debugs are on too.
49 */
50 #ifdef DEBUG
51 # ifndef DEBUG_MAKE
52 # define DEBUG_MAKE
53 # endif
54 # ifndef DEBUG_TIME
55 # define DEBUG_TIME
56 # endif
57 # ifndef DEBUG_RECALC
58 # define DEBUG_RECALC
59 # endif
60 #endif
61
62 /* Our signals.
63 */
64 enum {
65 SIG_NEW_VALUE, /* new value for sym->expr */
66 SIG_LAST
67 };
68
69 static guint symbol_signals[SIG_LAST] = { 0 };
70
71 /* Global symbol - top-level definitions are locals to this symbol.
72 */
73 Symbol *symbol_root = NULL;
74
75 /* Set of dirty top-level symbols with no dirty children which do not contain
76 * errors. Used to generate next-to-recalc.
77 */
78 static GSList *symbol_leaf_set = NULL;
79
80 static FilemodelClass *parent_class = NULL;
81
82 /* Apply a function to a symbol ... and any locals.
83 */
84 Symbol *
symbol_map_all(Symbol * sym,symbol_map_fn fn,void * a,void * b)85 symbol_map_all( Symbol *sym, symbol_map_fn fn, void *a, void *b )
86 {
87 Symbol *res;
88
89 /* Apply to this sym.
90 */
91 if( (res = fn( sym, a, b, NULL )) )
92 return( res );
93
94 /* And over any locals of those locals.
95 */
96 if( sym->expr && sym->expr->compile &&
97 (res = icontainer_map3( ICONTAINER( sym->expr->compile ),
98 (icontainer_map3_fn) symbol_map_all,
99 (void *) fn, a, b )) )
100 return( res );
101
102 return( NULL );
103 }
104
105 /* Find a symbol's enclosing sym.
106 */
107 Symbol *
symbol_get_parent(Symbol * sym)108 symbol_get_parent( Symbol *sym )
109 {
110 if( !ICONTAINER( sym )->parent )
111 return( NULL );
112
113 return( COMPILE( ICONTAINER( sym )->parent )->sym );
114 }
115
116 /* Find the enclosing workspace, if any.
117 */
118 Workspace *
symbol_get_workspace(Symbol * sym)119 symbol_get_workspace( Symbol *sym )
120 {
121 if( !sym->expr || !sym->expr->row )
122 return( NULL );
123
124 return( row_get_workspace( sym->expr->row ) );
125 }
126
127 /* Find the enclosing tool, if any.
128 */
129 Tool *
symbol_get_tool(Symbol * sym)130 symbol_get_tool( Symbol *sym )
131 {
132 Symbol *i;
133
134 for( i = sym; i && !i->tool; i = symbol_get_parent( i ) )
135 ;
136 if( i )
137 return( i->tool );
138
139 return( NULL );
140 }
141
142 /* Get the enclosing scope for a sym.
143 */
144 Symbol *
symbol_get_scope(Symbol * sym)145 symbol_get_scope( Symbol *sym )
146 {
147 Symbol *i;
148
149 for( i = sym; i && !is_scope( i ); i = symbol_get_parent( i ) )
150 ;
151
152 return( i );
153 }
154
155 /* Make a fully-qualified symbol name .. eg fred.jim, given jim. Don't print
156 * static scopes.
157 */
158 void
symbol_qualified_name(Symbol * sym,VipsBuf * buf)159 symbol_qualified_name( Symbol *sym, VipsBuf *buf )
160 {
161 Symbol *parent = symbol_get_parent( sym );
162
163 if( parent && !is_scope( parent ) ) {
164 symbol_qualified_name( parent, buf );
165 vips_buf_appends( buf, "." );
166 }
167
168 vips_buf_appends( buf, NN( IOBJECT( sym )->name ) );
169 }
170
171 /* Make a symbol name relative to a scope context ... ie. from the point of
172 * view of a local of context, what name will find sym.
173 */
174 void
symbol_qualified_name_relative(Symbol * context,Symbol * sym,VipsBuf * buf)175 symbol_qualified_name_relative( Symbol *context, Symbol *sym, VipsBuf *buf )
176 {
177 Symbol *parent = symbol_get_parent( sym );
178
179 if( parent && !is_ancestor( context, parent ) ) {
180 symbol_qualified_name_relative( context, parent, buf );
181 vips_buf_appends( buf, "." );
182 }
183
184 vips_buf_appends( buf, NN( IOBJECT( sym )->name ) );
185 }
186
187 /* As above, but include stuff about where the symbol is defined, handy for
188 * building error messages.
189 */
190 void *
symbol_name_error(Symbol * sym,VipsBuf * buf)191 symbol_name_error( Symbol *sym, VipsBuf *buf )
192 {
193 Tool *tool;
194
195 symbol_qualified_name( sym, buf );
196 if( (tool = symbol_get_tool( sym )) )
197 tool_error( tool, buf );
198
199 vips_buf_appends( buf, " " );
200
201 return( NULL );
202 }
203
204 /* Handy for error messages ... but nowt else. Return string overwritten on
205 * next call.
206 */
207 const char *
symbol_name(Symbol * sym)208 symbol_name( Symbol *sym )
209 {
210 static char txt[200];
211 static VipsBuf buf = VIPS_BUF_STATIC( txt );
212
213 vips_buf_rewind( &buf );
214 symbol_qualified_name( sym, &buf );
215
216 return( vips_buf_all( &buf ) );
217 }
218
219 /* Convenience ... print a qual name to stdout.
220 */
221 void *
symbol_name_print(Symbol * sym)222 symbol_name_print( Symbol *sym )
223 {
224 printf( "%s ", symbol_name( sym ) );
225
226 return( NULL );
227 }
228
229 /* Print a symbol's name, including the enclosing static scope. Return value
230 * is a pointer to a static buffer :(
231 */
232 const char *
symbol_name_scope(Symbol * sym)233 symbol_name_scope( Symbol *sym )
234 {
235 Symbol *scope = symbol_get_scope( sym );
236
237 static char txt[200];
238 static VipsBuf buf = VIPS_BUF_STATIC( txt );
239
240 vips_buf_rewind( &buf );
241 vips_buf_appends( &buf, NN( IOBJECT( scope )->name ) );
242 vips_buf_appends( &buf, "." );
243 symbol_qualified_name_relative( scope, sym, &buf );
244
245 return( vips_buf_all( &buf ) );
246 }
247
248 /* Convenience ... print a qual name to stdout.
249 */
250 void
symbol_name_scope_print(Symbol * sym)251 symbol_name_scope_print( Symbol *sym )
252 {
253 printf( "%s", symbol_name_scope( sym ) );
254 }
255
256 void
symbol_new_value(Symbol * sym)257 symbol_new_value( Symbol *sym )
258 {
259 g_signal_emit( G_OBJECT( sym ), symbol_signals[SIG_NEW_VALUE], 0 );
260 }
261
262 /* Add a pointer to a patch list.
263 */
264 void *
symbol_patch_add(void ** pnt,Symbol * sym)265 symbol_patch_add( void **pnt, Symbol *sym )
266 {
267 g_assert( sym->type == SYM_ZOMBIE );
268
269 sym->patch = g_slist_prepend( sym->patch, pnt );
270
271 return( NULL );
272 }
273
274 static void
symbol_clear(Symbol * sym)275 symbol_clear( Symbol *sym )
276 {
277 sym->type = SYM_ZOMBIE;
278
279 sym->patch = NULL;
280
281 sym->expr = NULL;
282
283 sym->base.type = ELEMENT_NOVAL;
284 sym->base.ele = (void *) 15; /* handy for debugging */
285
286 sym->dirty = FALSE;
287 sym->parents = NULL;
288
289 sym->topchildren = NULL;
290 sym->topparents = NULL;
291 sym->ndirtychildren = 0;
292 sym->leaf = FALSE;
293
294 sym->generated = FALSE;
295 sym->placeholder = FALSE;
296
297 sym->tool = NULL;
298
299 sym->function = NULL;
300
301 sym->builtin = NULL;
302
303 sym->wsr = NULL;
304
305 sym->ws = NULL;
306 }
307
308 /* Initialise root symbol.
309 */
310 Symbol *
symbol_root_init(void)311 symbol_root_init( void )
312 {
313 Symbol *root = SYMBOL( g_object_new( TYPE_SYMBOL, NULL ) );
314
315 symbol_clear( root );
316 iobject_set( IOBJECT( root ), "$$ROOT", NULL );
317 root->type = SYM_ROOT;
318 root->expr = expr_new( root );
319 (void) compile_new_local( root->expr );
320
321 symbol_root = symbol_new( root->expr->compile, "root" );
322 symbol_root->type = SYM_ROOT;
323 symbol_root->expr = expr_new( symbol_root );
324 (void) compile_new( symbol_root->expr );
325
326 return( root );
327 }
328
329 /* Should a symbol be in the leaf set?
330 */
331 static gboolean
symbol_is_leafable(Symbol * sym)332 symbol_is_leafable( Symbol *sym )
333 {
334 if( is_top( sym ) &&
335 sym->dirty &&
336 sym->expr &&
337 !sym->expr->err &&
338 sym->ndirtychildren == 0 )
339 return( TRUE );
340
341 return( FALSE );
342 }
343
344 #ifdef DEBUG
345 /* Do a sanity check on a symbol.
346 */
347 void *
symbol_sanity(Symbol * sym)348 symbol_sanity( Symbol *sym )
349 {
350 if( is_top( sym ) ) {
351 if( symbol_ndirty( sym ) != sym->ndirtychildren )
352 error( "sanity failure #1 for sym \"%s\"",
353 symbol_name( sym ) );
354 }
355
356 if( symbol_is_leafable( sym ) && !sym->leaf )
357 error( "sanity failure #2 for sym \"%s\"", symbol_name( sym ) );
358 if( !symbol_is_leafable( sym ) && sym->leaf )
359 error( "sanity failure #3 for sym \"%s\"", symbol_name( sym ) );
360 if( sym->leaf && !g_slist_find( symbol_leaf_set, sym ) )
361 error( "sanity failure #6 for sym \"%s\"", symbol_name( sym ) );
362 if( !sym->leaf && g_slist_find( symbol_leaf_set, sym ) )
363 error( "sanity failure #7 for sym \"%s\"", symbol_name( sym ) );
364
365 return( NULL );
366 }
367 #endif/*DEBUG*/
368
369 #ifdef DEBUG
370 /* Test the leaf set for sanity.
371 */
372 void
symbol_leaf_set_sanity(void)373 symbol_leaf_set_sanity( void )
374 {
375 slist_map( symbol_leaf_set, (SListMapFn) symbol_sanity, NULL );
376 icontainer_map( ICONTAINER( symbol_root->expr->compile ),
377 (icontainer_map_fn) symbol_sanity, NULL, NULL );
378
379 /* Commented out to reduce spam
380 *
381 printf( "Leaf set: " );
382 slist_map( symbol_leaf_set, (SListMapFn) dump_tiny, NULL );
383 printf( "\n" );
384 */
385 }
386 #endif /*DEBUG*/
387
388 /* Strip a symbol down, ready for redefinition.
389 */
390 void *
symbol_strip(Symbol * sym)391 symbol_strip( Symbol *sym )
392 {
393 #ifdef DEBUG_MAKE
394 printf( "symbol_strip: " );
395 symbol_name_print( sym );
396 printf( "\n" );
397 #endif /*DEBUG_MAKE*/
398
399 /* Anything that refers to us will need a recomp.
400 */
401 if( is_top( sym ) )
402 symbol_dirty_intrans( sym, link_serial_new() );
403
404 /* Clean out old exprinfo.
405 */
406 icontainer_map( ICONTAINER( sym ),
407 (icontainer_map_fn) expr_strip, NULL, NULL );
408
409 /* Free any top-links we made.
410 */
411 (void) slist_map( sym->topchildren, (SListMapFn) link_destroy, NULL );
412
413 /* Can free the patch list. We should not have to resolve off this
414 * name again.
415 */
416 IM_FREEF( g_slist_free, sym->patch );
417
418 /* Workspaceroot? Unlink from wsr.
419 */
420 if( sym->wsr ) {
421 sym->wsr->sym = NULL;
422 sym->wsr = NULL;
423 }
424
425 /* Workspace? Unlink from ws.
426 */
427 if( sym->ws ) {
428 sym->ws->sym = NULL;
429 sym->ws = NULL;
430 }
431
432 /* It's a ZOMBIE now.
433 */
434 sym->type = SYM_ZOMBIE;
435
436 #ifdef DEBUG
437 symbol_sanity( sym );
438 #endif /*DEBUG*/
439
440 return( NULL );
441 }
442
443 static void *
symbol_made_error_clear(Link * link)444 symbol_made_error_clear( Link *link )
445 {
446 expr_error_clear( link->parent->expr );
447
448 return( NULL );
449 }
450
451 /* Finish creating a symbol. Sequence is: symbol_new(), specialise ZOMBIE
452 * into a particular symbol type, symbol_made(). Do any final tidying up.
453 */
454 void
symbol_made(Symbol * sym)455 symbol_made( Symbol *sym )
456 {
457 #ifdef DEBUG_MAKE
458 printf( "symbol_made: " );
459 symbol_name_print( sym );
460 printf( "\n" );
461 #endif /*DEBUG_MAKE*/
462
463 if( is_top( sym ) ) {
464 /* Remake all top-level dependencies.
465 */
466 (void) symbol_link_build( sym );
467
468 /* Clear error on every symbol that refs us, then mark dirty.
469 * This lets us replace refed-to syms cleanly.
470 */
471 slist_map( sym->topparents,
472 (SListMapFn) symbol_made_error_clear, NULL );
473
474 /* Real dirrrrty.
475 */
476 if( sym->expr )
477 expr_dirty( sym->expr, link_serial_new() );
478 }
479
480 #ifdef DEBUG
481 dump_symbol( sym );
482 #endif /*DEBUG*/
483 }
484
485 static void *
symbol_not_defined_sub(Link * link,VipsBuf * buf)486 symbol_not_defined_sub( Link *link, VipsBuf *buf )
487 {
488 symbol_name_error( link->parent, buf );
489
490 return( NULL );
491 }
492
493 /* Make a "not defined" error message. Can be called before symbol is removed,
494 * so don't assume it's a ZOMBIE.
495 */
496 void
symbol_not_defined(Symbol * sym)497 symbol_not_defined( Symbol *sym )
498 {
499 char txt[256];
500 VipsBuf buf = VIPS_BUF_STATIC( txt );
501
502 error_top( _( "Not found." ) );
503 vips_buf_appendf( &buf, _( "Symbol %s is not defined." ),
504 symbol_name( sym ) );
505 if( sym->topparents ) {
506 vips_buf_appends( &buf, "\n" );
507 vips_buf_appendf( &buf, _( "%s is referred to by" ),
508 symbol_name( sym ) );
509 vips_buf_appends( &buf, ": " );
510 slist_map2( sym->topparents,
511 (SListMap2Fn) symbol_not_defined_sub, &buf, NULL );
512 vips_buf_appends( &buf, "\n" );
513 }
514 error_sub( "%s", vips_buf_all( &buf ) );
515 }
516
517 /* Compile refers to sym, which is going ... mark compile as containing an
518 * error.
519 */
520 static void *
symbol_destroy_error(Compile * compile,Symbol * sym)521 symbol_destroy_error( Compile *compile, Symbol *sym )
522 {
523 symbol_not_defined( sym );
524 compile_error_set( compile );
525
526 return( NULL );
527 }
528
529 static void
symbol_dispose(GObject * gobject)530 symbol_dispose( GObject *gobject )
531 {
532 Symbol *sym;
533 Compile *compile;
534
535 g_return_if_fail( gobject != NULL );
536 g_return_if_fail( IS_SYMBOL( gobject ) );
537
538 sym = SYMBOL( gobject );
539 compile = COMPILE( ICONTAINER( sym )->parent );
540
541 #ifdef DEBUG_MAKE
542 printf( "symbol_dispose: " );
543 symbol_name_print( sym );
544 printf( "(%p)\n", sym );
545 #endif /*DEBUG_MAKE*/
546
547 /* Make sure we're not leaving last_sym dangling.
548 */
549 if( compile && compile->last_sym == sym )
550 compile->last_sym = NULL;
551
552 /* Clear state.
553 */
554 if( is_top( sym ) ) {
555 /* All stuff that depends on this sym is now dirty.
556 */
557 symbol_dirty_intrans( sym, link_serial_new() );
558
559 /* This will knock this sym off the leaf set as well.
560 */
561 symbol_dirty_clear( sym );
562 }
563
564 /* Strip it down.
565 */
566 (void) symbol_strip( sym );
567 IDESTROY( sym->tool );
568
569 /* Any exprs which refer to us must have errors.
570 */
571 (void) slist_map( sym->parents,
572 (SListMapFn) symbol_destroy_error, sym );
573
574 /* Remove links from any expr which refer to us.
575 */
576 (void) slist_map( sym->parents, (SListMapFn) compile_link_break, sym );
577
578 /* No other syms should have toplinks to us.
579 */
580 (void) slist_map( sym->topparents, (SListMapFn) link_destroy, NULL );
581
582 /* Unregister value with GC.
583 */
584 reduce_unregister( sym );
585
586 /* Free other stuff.
587 */
588 sym->type = SYM_ZOMBIE;
589
590 g_assert( !sym->tool );
591 g_assert( !sym->parents );
592 g_assert( !sym->topparents );
593 g_assert( !sym->topchildren );
594
595 IM_FREEF( g_slist_free, sym->patch );
596 IM_FREEF( g_slist_free, sym->parents );
597
598 G_OBJECT_CLASS( parent_class )->dispose( gobject );
599 }
600
601 static void
symbol_changed(iObject * iobject)602 symbol_changed( iObject *iobject )
603 {
604 Symbol *sym = SYMBOL( iobject );
605
606 /* If we have a tool, signal changed on that as well.
607 */
608 if( sym->tool )
609 iobject_changed( IOBJECT( sym->tool ) );
610
611 IOBJECT_CLASS( parent_class )->changed( iobject );
612 }
613
614 static void
symbol_real_new_value(Symbol * symbol)615 symbol_real_new_value( Symbol *symbol )
616 {
617 }
618
619 static void
symbol_class_init(SymbolClass * class)620 symbol_class_init( SymbolClass *class )
621 {
622 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
623 iObjectClass *iobject_class = (iObjectClass *) class;
624
625 parent_class = g_type_class_peek_parent( class );
626
627 gobject_class->dispose = symbol_dispose;
628
629 iobject_class->changed = symbol_changed;
630
631 symbol_signals[SIG_NEW_VALUE] = g_signal_new( "new_value",
632 G_OBJECT_CLASS_TYPE( gobject_class ),
633 G_SIGNAL_RUN_FIRST,
634 G_STRUCT_OFFSET( SymbolClass, new_value ),
635 NULL, NULL,
636 g_cclosure_marshal_VOID__VOID,
637 G_TYPE_NONE, 0 );
638
639 class->new_value = symbol_real_new_value;
640 }
641
642 static void
symbol_init(Symbol * sym)643 symbol_init( Symbol *sym )
644 {
645 symbol_clear( sym );
646
647 #ifdef DEBUG_MAKE
648 printf( "symbol_init: (%p)\n", sym );
649 #endif /*DEBUG_MAKE*/
650 }
651
652 GtkType
symbol_get_type(void)653 symbol_get_type( void )
654 {
655 static GtkType symbol_type = 0;
656
657 if( !symbol_type ) {
658 static const GTypeInfo info = {
659 sizeof( SymbolClass ),
660 NULL, /* base_init */
661 NULL, /* base_finalize */
662 (GClassInitFunc) symbol_class_init,
663 NULL, /* class_finalize */
664 NULL, /* class_data */
665 sizeof( Symbol ),
666 32, /* n_preallocs */
667 (GInstanceInitFunc) symbol_init,
668 };
669
670 symbol_type = g_type_register_static( TYPE_FILEMODEL,
671 "Symbol", &info, 0 );
672 }
673
674 return( symbol_type );
675 }
676
677 /* Make a new symbol on an expr. If it's already there and a ZOMBIE, just
678 * return it. If it's not a ZOMBIE, turn it into one. Otherwise make and
679 * link on a new symbol.
680 */
681 Symbol *
symbol_new(Compile * compile,const char * name)682 symbol_new( Compile *compile, const char *name )
683 {
684 Symbol *sym;
685
686 if( (sym = compile_lookup( compile, name )) ) {
687 if( sym->type != SYM_ZOMBIE )
688 /* Already exists: strip it down.
689 */
690 (void) symbol_strip( sym );
691
692 #ifdef DEBUG_MAKE
693 printf( "symbol_new: redefining " );
694 symbol_name_print( sym );
695 printf( "(%p)\n", sym );
696 #endif /*DEBUG_MAKE*/
697 }
698 else {
699 sym = SYMBOL( g_object_new( TYPE_SYMBOL, NULL ) );
700 iobject_set( IOBJECT( sym ), name, NULL );
701 icontainer_child_add( ICONTAINER( compile ),
702 ICONTAINER( sym ), -1 );
703
704 #ifdef DEBUG_MAKE
705 printf( "symbol_new: creating " );
706 symbol_name_print( sym );
707 printf( "(%p)\n", sym );
708 #endif /*DEBUG_MAKE*/
709 }
710
711 return( sym );
712 }
713
714 gboolean
symbol_rename(Symbol * sym,const char * new_name)715 symbol_rename( Symbol *sym, const char *new_name )
716 {
717 Compile *compile = COMPILE( ICONTAINER( sym )->parent );
718 Symbol *old_sym;
719
720 if( strcmp( IOBJECT( sym )->name, new_name ) == 0 )
721 return( TRUE );
722
723 if( (old_sym = compile_lookup( compile, new_name )) ) {
724 error_top( "%s", _( "Name in use." ) );
725 error_sub( _( "Can't rename %s \"%s\" as \"%s\". "
726 "The name is already in use." ),
727 decode_SymbolType_user( sym->type ),
728 IOBJECT( sym )->name,
729 new_name );
730 return( FALSE );
731 }
732
733 /* Everything that depends on us will break.
734 */
735 symbol_dirty_intrans( sym, link_serial_new() );
736
737 g_object_ref( sym );
738
739 icontainer_child_remove( ICONTAINER( sym ) );
740 iobject_set( IOBJECT( sym ), new_name, NULL );
741 icontainer_child_add( ICONTAINER( compile ), ICONTAINER( sym ),
742 ICONTAINER( sym )->pos );
743
744 g_object_unref( sym );
745
746 return( TRUE );
747 }
748
749 void
symbol_error_redefine(Symbol * sym)750 symbol_error_redefine( Symbol *sym )
751 {
752 static char txt[200];
753 static VipsBuf buf = VIPS_BUF_STATIC( txt );
754
755 vips_buf_rewind( &buf );
756 vips_buf_appendf( &buf, _( "Redefinition of \"%s\"." ),
757 IOBJECT( sym )->name );
758 if( sym->tool && sym->tool->lineno != -1 ) {
759 vips_buf_appendf( &buf, "\n" );
760 vips_buf_appendf( &buf, _( "Previously defined at line %d." ),
761 sym->tool->lineno );
762 }
763
764 yyerror( vips_buf_all( &buf ) );
765 }
766
767 /* Name in defining occurence. If this is a top-level definition, clean the
768 * old symbol and get ready to attach a user function to it. If its not a top-
769 * level definition, we flag an error. Consider repeated parameter names,
770 * repeated occurence of names in locals, local name clashes with parameter
771 * name etc.
772 * We make a ZOMBIE: our caller should turn it into a blank user definition, a
773 * parameter etc.
774 */
775 Symbol *
symbol_new_defining(Compile * compile,const char * name)776 symbol_new_defining( Compile *compile, const char *name )
777 {
778 Symbol *sym;
779
780 /* Block definition of "root" anywhere ... too confusing.
781 */
782 if( strcmp( name, IOBJECT( symbol_root )->name ) == 0 )
783 nip2yyerror( _( "Attempt to redefine root symbol \"%s\"." ),
784 name );
785
786 /* Is this a redefinition of an existing symbol?
787 */
788 if( (sym = compile_lookup( compile, name )) ) {
789 /* Yes. Check that this redefinition is legal.
790 */
791 switch( sym->type ) {
792 case SYM_VALUE:
793 /* Redef of existing symbol? Only allowed at top
794 * level.
795 */
796 if( !is_scope( compile->sym ) )
797 symbol_error_redefine( sym );
798 break;
799
800 case SYM_ZOMBIE:
801 /* This is the definition for a previously referenced
802 * symbol. Just return the ZOMBIE we made.
803 */
804 break;
805
806 default:
807 /* Parameter, workspace, etc.
808 */
809 nip2yyerror( _( "Can't redefine %s \"%s\"." ),
810 decode_SymbolType_user( sym->type ), name );
811 /*NOTREACHED*/
812 }
813
814 /* This is the defining occurence ... move to the end of the
815 * traverse order.
816 */
817 icontainer_child_move( ICONTAINER( sym ), -1 );
818 }
819
820 /* Get it ready.
821 */
822 sym = symbol_new( compile, name );
823
824 return( sym );
825 }
826
827 /* Make a reference to a symbol. Look on the local table for the name - if
828 * it's not there, make a ZOMBIE. Note that ZOMBIEs etc. need patch lists
829 * attached to them for all pointers to them we make. Responsibility of
830 * caller!
831 */
832 Symbol *
symbol_new_reference(Compile * compile,const char * name)833 symbol_new_reference( Compile *compile, const char *name )
834 {
835 Symbol *sym = compile_lookup( compile, name );
836
837 if( !sym )
838 sym = symbol_new( compile, name );
839
840 /* Note the new dependency.
841 */
842 compile_link_make( compile, sym );
843
844 return( sym );
845 }
846
847 /* Compile refers to child ... break link.
848 */
849 void *
symbol_link_break(Symbol * child,Compile * compile)850 symbol_link_break( Symbol *child, Compile *compile )
851 {
852 compile_link_break( compile, child );
853
854 return( NULL );
855 }
856
857 /* Specialise into a user definition.
858 */
859 gboolean
symbol_user_init(Symbol * sym)860 symbol_user_init( Symbol *sym )
861 {
862 g_assert( sym->type == SYM_ZOMBIE );
863
864 sym->type = SYM_VALUE;
865 reduce_register( sym );
866 if( !sym->expr )
867 sym->expr = expr_new( sym );
868
869 /* We don't symbol_made() yet, wait until we have finished building
870 * sym->expr.
871 */
872
873 return( TRUE );
874 }
875
876 /* Specialise into a parameter on an expression.
877 */
878 gboolean
symbol_parameter_init(Symbol * sym)879 symbol_parameter_init( Symbol *sym )
880 {
881 Compile *parent = COMPILE( ICONTAINER( sym )->parent );
882
883 g_assert( sym->type == SYM_ZOMBIE );
884
885 sym->type = SYM_PARAM;
886 parent->param = g_slist_append( parent->param, sym );
887 parent->nparam = g_slist_length( parent->param );
888 symbol_made( sym );
889
890 return( TRUE );
891 }
892
893 /* Specialise into a builtin parameter (eg. "this").
894 */
895 gboolean
symbol_parameter_builtin_init(Symbol * sym)896 symbol_parameter_builtin_init( Symbol *sym )
897 {
898 g_assert( sym->type == SYM_ZOMBIE );
899
900 sym->type = SYM_PARAM;
901 symbol_made( sym );
902
903 return( TRUE );
904 }
905
906 /* Get the next dirty leaf symbol.
907 */
908 static Symbol *
symbol_leaf_next(void)909 symbol_leaf_next( void )
910 {
911 if( symbol_leaf_set )
912 return( (Symbol *) symbol_leaf_set->data );
913 else
914 return( NULL );
915 }
916
917 /* Are there symbols we can recalculate? Used to display "Calculating ..."
918 * status.
919 */
920 gboolean
symbol_busy(void)921 symbol_busy( void )
922 {
923 return( symbol_leaf_set != NULL );
924 }
925
926 /* Set leaf state.
927 */
928 static void
symbol_set_leaf(Symbol * sym,gboolean leaf)929 symbol_set_leaf( Symbol *sym, gboolean leaf )
930 {
931 if( sym->leaf != leaf ) {
932 gboolean changed;
933
934 sym->leaf = leaf;
935
936 changed = FALSE;
937 if( leaf ) {
938 if( !symbol_leaf_set )
939 changed = TRUE;
940
941 symbol_leaf_set =
942 g_slist_prepend( symbol_leaf_set, sym );
943 }
944 else {
945 g_assert( symbol_leaf_set );
946
947 symbol_leaf_set =
948 g_slist_remove( symbol_leaf_set, sym );
949
950 if( !symbol_leaf_set )
951 changed = TRUE;
952 }
953
954 if( changed )
955 iobject_changed( IOBJECT( reduce_context->heap ) );
956
957 if( sym->expr && sym->expr->row )
958 iobject_changed( IOBJECT( sym->expr->row ) );
959 }
960 }
961
962 /* State of a symbol has changed ... update!
963 */
964 void
symbol_state_change(Symbol * sym)965 symbol_state_change( Symbol *sym )
966 {
967 g_assert( sym->ndirtychildren >= 0 );
968
969 /* Used to do more ... now we just set leaf.
970 */
971 symbol_set_leaf( sym, symbol_is_leafable( sym ) );
972 }
973
974 /* Recalculate a symbol. We know we are dirty and have no dirty ancestors.
975 */
976 static gboolean
symbol_recalculate_sub(Symbol * sym)977 symbol_recalculate_sub( Symbol *sym )
978 {
979 gboolean result = TRUE;
980
981 #ifdef DEBUG_TIME
982 static GTimer *timer = NULL;
983
984 if( !timer )
985 timer = g_timer_new();
986 g_timer_reset( timer );
987 #endif /*DEBUG_TIME*/
988
989 g_assert( is_value( sym ) );
990
991 if( sym->expr->row ) {
992 /* This is the root of a display ... use that recomp
993 * mechanism.
994 */
995 row_recomp( sym->expr->row );
996
997 /* Stuff may have been removed.
998 */
999 if( sym->expr &&
1000 sym->expr->row &&
1001 sym->expr->row->err )
1002 result = FALSE;
1003 }
1004 else if( sym->expr->compile->nparam == 0 ) {
1005 /* No params: this ought to have a value.
1006 */
1007 if( !reduce_regenerate( sym->expr, &sym->expr->root ) )
1008 result = FALSE;
1009 }
1010
1011 #ifdef DEBUG_TIME
1012 printf( "symbol_recalculate_sub: " );
1013 symbol_name_scope_print( sym );
1014 printf( " %g\n", g_timer_elapsed( timer, NULL ) );
1015 #endif /*DEBUG_TIME*/
1016
1017 return( result );
1018 }
1019
1020 /* Note the name of the last thing we calced here, for progress to display.
1021 */
1022 static char symbol_last_calc_txt[256];
1023 static VipsBuf symbol_last_calc_buf = VIPS_BUF_STATIC( symbol_last_calc_txt );
1024
1025 static void
symbol_note_calc_name(Symbol * sym)1026 symbol_note_calc_name( Symbol *sym )
1027 {
1028 Symbol *scope = symbol_get_scope( sym );
1029 VipsBuf *buf = &symbol_last_calc_buf;
1030
1031 vips_buf_rewind( buf );
1032 vips_buf_appends( buf, NN( IOBJECT( scope )->name ) );
1033 vips_buf_appends( buf, "." );
1034 symbol_qualified_name_relative( scope, sym, buf );
1035 }
1036
1037 const char *
symbol_get_last_calc(void)1038 symbol_get_last_calc( void )
1039 {
1040 return( vips_buf_all( &symbol_last_calc_buf ) );
1041 }
1042
1043 /* We can get called recursively .. eg. we do an im_tiff2vips(), that
1044 * pops a progress box, that triggers idle, that tries to recalc a
1045 * leaf again.
1046 */
1047 static gboolean symbol_running = FALSE;
1048
1049 /* Recalc a symbol ... with error checks.
1050 */
1051 static void *
symbol_recalculate_leaf_sub(Symbol * sym)1052 symbol_recalculate_leaf_sub( Symbol *sym )
1053 {
1054 #ifdef DEBUG_RECALC
1055 printf( "symbol_recalculate_leaf_sub: %s\n", symbol_name_scope( sym ) );
1056
1057 /* We can symbol_recalculate_leaf_sub() syms which are not dirty.
1058 */
1059 g_assert( !sym->dirty || symbol_is_leafable( sym ) );
1060
1061 g_assert( symbol_ndirty( sym ) == 0 );
1062 #endif /*DEBUG_RECALC*/
1063
1064 error_clear();
1065 if( sym->expr->err ) {
1066 expr_error_get( sym->expr );
1067
1068 #ifdef DEBUG_RECALC
1069 printf( "\t(error: previous error)\n" );
1070 #endif /*DEBUG_RECALC*/
1071
1072 return( sym );
1073 }
1074 if( !sym->dirty )
1075 return( NULL );
1076 if( !is_value( sym ) ) {
1077 symbol_dirty_clear( sym );
1078 return( NULL );
1079 }
1080 if( symbol_running )
1081 return( NULL );
1082
1083 reduce_context->heap->filled = FALSE;
1084 symbol_running = TRUE;
1085 progress_begin();
1086 symbol_note_calc_name( sym );
1087 if( !symbol_recalculate_sub( sym ) ||
1088 reduce_context->heap->filled ) {
1089 expr_error_set( sym->expr );
1090 symbol_running = FALSE;
1091 progress_end();
1092
1093 #ifdef DEBUG_RECALC
1094 printf( "\t(error: %s %s)\n",
1095 sym->expr->error_top, sym->expr->error_sub );
1096 #endif /*DEBUG_RECALC*/
1097
1098 return( sym );
1099 }
1100 symbol_running = FALSE;
1101 progress_end();
1102
1103 /* Have we discovered any dirty children? If not, we've cleaned this
1104 * sym.
1105 */
1106 if( !sym->ndirtychildren ) {
1107 symbol_dirty_clear( sym );
1108 if( sym->expr ) {
1109 expr_new_value( sym->expr );
1110
1111 #ifdef DEBUG_RECALC
1112 printf( "\tsuccess: " );
1113 graph_pointer( &sym->expr->root );
1114 #endif /*DEBUG_RECALC*/
1115 }
1116 }
1117 #ifdef DEBUG_RECALC
1118 else {
1119 printf( "\t(found dirty children)\n" );
1120 }
1121 #endif /*DEBUG_RECALC*/
1122
1123 return( NULL );
1124 }
1125
1126 /* Recalculate a symbol. FALSE if no symbols can be recalced.
1127 */
1128 static gboolean
symbol_recalculate_leaf(void)1129 symbol_recalculate_leaf( void )
1130 {
1131 gboolean recalculated;
1132 Symbol *sym;
1133
1134 recalculated = FALSE;
1135
1136 #ifdef DEBUG
1137 printf( "symbol_recalculate_leaves: Leaf set: " );
1138 slist_map( symbol_leaf_set, (SListMapFn) dump_tiny, NULL );
1139 printf( "\n" );
1140 #endif /*DEBUG*/
1141
1142 /* Grab stuff off the leaf set.
1143 */
1144 if( (sym = symbol_leaf_next()) ) {
1145 /* Should be dirty with no dirty children. Unless it's a
1146 * function, in which case dirty kids are OK.
1147 */
1148 g_assert( sym->dirty );
1149 g_assert( !sym->expr->err );
1150 g_assert( is_top( sym ) );
1151 g_assert( symbol_ndirty( sym ) == 0 || is_value( sym ) );
1152
1153 /* Found a symbol!
1154 */
1155 (void) symbol_recalculate_leaf_sub( sym );
1156
1157 /* Note a pending GC.
1158 */
1159 (void) heap_gc_request( reduce_context->heap );
1160
1161 /* We have recalculated a symbol.
1162 */
1163 recalculated = TRUE;
1164 }
1165
1166 return( recalculated );
1167 }
1168
1169 /* Our idle recomp callback.
1170 */
1171 static gint symbol_idle_id = 0;
1172
1173 static gboolean
symbol_recalculate_idle_cb(void)1174 symbol_recalculate_idle_cb( void )
1175 {
1176 static GTimer *timer = NULL;
1177
1178 gboolean run_again;
1179
1180 #ifdef DEBUG_RECALC
1181 printf( "symbol_recalculate_idle_cb:\n" );
1182 #endif /*DEBUG_RECALC*/
1183
1184 if( symbol_running )
1185 /* We've been run from a nested main loop, perhaps from the
1186 * progress bar. Just run again and perhaps next time we'll be
1187 * back in the top-level main loop.
1188 */
1189 return( TRUE );
1190
1191 if( !timer )
1192 timer = g_timer_new();
1193
1194 g_timer_reset( timer );
1195
1196 run_again = TRUE;
1197
1198 if( !mainw_auto_recalc )
1199 /* Auto-calc has been turned off during a recomp.
1200 */
1201 run_again = FALSE;
1202 else
1203 while( g_timer_elapsed( timer, NULL ) < 0.1 )
1204 if( !symbol_recalculate_leaf() ) {
1205 run_again = FALSE;
1206 break;
1207 }
1208
1209 if( !run_again ) {
1210 #ifdef DEBUG_RECALC
1211 printf( "symbol_recalculate_idle_cb: bg recalc done\n" );
1212 #endif /*DEBUG_RECALC*/
1213
1214 symbol_idle_id = 0;
1215 progress_end();
1216 }
1217
1218 return( run_again );
1219 }
1220
1221 /* Recalculate ... either nudge the idle recomp, or in batch mode, do a recomp
1222 * right now.
1223 */
1224 void
symbol_recalculate_all_force(gboolean now)1225 symbol_recalculate_all_force( gboolean now )
1226 {
1227 #ifdef DEBUG
1228 icontainer_map( ICONTAINER( symbol_root->expr->compile ),
1229 (icontainer_map_fn) symbol_sanity, NULL, NULL );
1230 #endif /*DEBUG*/
1231
1232 /* In case we're called directly.
1233 */
1234 (void) view_scan_all();
1235
1236 if( symbol_running )
1237 /* Do nothing.
1238 */
1239 ;
1240 else if( main_option_batch ||
1241 now ) {
1242 progress_begin();
1243
1244 while( symbol_recalculate_leaf() )
1245 ;
1246
1247 progress_end();
1248 }
1249 else if( !symbol_idle_id ) {
1250 #ifdef DEBUG_RECALC
1251 printf( "symbol_recalculate_all_force: "
1252 "starting bg recalc ...\n" );
1253 #endif /*DEBUG_RECALC*/
1254
1255 progress_begin();
1256 symbol_idle_id = g_idle_add(
1257 (GSourceFunc) symbol_recalculate_idle_cb, NULL );
1258 }
1259 }
1260
1261 /* Recalculate the symbol table.
1262 */
1263 void
symbol_recalculate_all(void)1264 symbol_recalculate_all( void )
1265 {
1266 /* Do a scan, even if we don't recomp. We need to pick up edits before
1267 * views get refreshed.
1268 */
1269 (void) view_scan_all();
1270
1271 if( mainw_auto_recalc )
1272 symbol_recalculate_all_force( FALSE );
1273 }
1274
1275 /* Recalc a symbol ... with error checks.
1276 */
1277 gboolean
symbol_recalculate_check(Symbol * sym)1278 symbol_recalculate_check( Symbol *sym )
1279 {
1280 gboolean result;
1281
1282 result = symbol_recalculate_leaf_sub( sym ) == NULL;
1283
1284 return( result );
1285 }
1286