1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 package com.unitesk.atp.treedl;
33
34 import java.io.File;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Map;
39
40 import com.unitesk.atp.tool.PluginClass;
41 import com.unitesk.atp.tree.Node;
42 import com.unitesk.atp.messages.*;
43 import com.unitesk.atp.treedl.TDL.*;
44
45 public class Checker implements TDL_Visitor
46 {
47 /***
48 * Returns checker version.
49 */
50 public static String getVersion()
51 {
52 return PluginClass.getRevision( "$Revision: 1.69 $" ) + "-beta";
53 }
54
55 /***
56 * Returns localized entity name.
57 *
58 * @param cls Class with that provides localized entity name.
59 * Often this class implements entity.
60 * @param name Name of resource containing localized entity name.
61 * @return Localized entity name
62 */
63 private String getString( Class cls, String name )
64 {
65 return mbox.getStringManager().getString( cls, name );
66 }
67
68 /***
69 * Register loaded module in map.
70 *
71 * @param module Module to be registered.
72 */
73 private void registerModule( TDL_Module module )
74 {
75 QID name = module.getRoot().getName();
76 TDL_Module oldModule = moduleMap.getModule( name );
77 if( oldModule != null )
78 {
79 throw new InternalError( "Impossible to register module with the same name twice" );
80 }
81 moduleMap.putModule( module );
82 module.getRoot().setModuleMap( moduleMap );
83 }
84
85 /***
86 * Check semantics of module. Module will be registered in map.
87 *
88 * @param moduleMap Map of loaded modules.
89 * @param module Module to be chacked.
90 */
91 public static void check( TDL_ModuleMap moduleMap, TDL_Module module )
92 {
93 Module moduleRoot = module.getRoot();
94 switch( moduleRoot.getState().key() )
95 {
96 case CheckState.Key.NOT_CHECKED:
97 moduleRoot.setState( CheckState.CHECKING );
98 break;
99 case CheckState.Key.CHECKING:
100 module.getMessageBox().fatal( new Message.ModuleCircularDependence
101 ( module.getFile()
102 , moduleRoot.getName().getValue()
103 )
104 );
105 return;
106 case CheckState.Key.CHECKED:
107 return;
108 default:
109 throw new IllegalArgumentException( "checkStatus = " + moduleRoot.getState() );
110 }
111
112
113
114 Checker checker = new Checker( moduleMap, module );
115
116 module.getMessageBox().info( new FileStatusMessage
117 ( CheckFileStatus.status
118 , module.getFile().toString()
119 )
120 );
121 checker.registerModule( module );
122
123 moduleRoot.accept( checker );
124
125 moduleRoot.setState( CheckState.CHECKED );
126 }
127
128 private TDL_ModuleMap moduleMap;
129 private TDL_Module module;
130 private MessageBox mbox;
131 private File file;
132
133 public MessageBox getMessageBox() { return mbox; }
134
135 public File getFile() { return file; }
136
137 protected Checker( TDL_ModuleMap moduleMap, TDL_Module module )
138 {
139 this.moduleMap = moduleMap;
140 this.module = module;
141 mbox = module.getMessageBox();
142 file = module.getFile();
143 }
144
145 private void visit( Node node )
146 {
147 if( node != null ) node.accept( this );
148 }
149
150 private void visit( List
151 {
152 for( int i = 0; i < list.size(); i++ )
153 {
154 ((Node)(list.get( i ))).accept( this );
155 }
156 }
157
158 private void registerType( ModuleTypeMember member )
159 {
160 ID name = member.getName();
161 String nameStr = name.getValue();
162 NodeTypeDecl rootNodeType = TDL_Module.getRootNodeType();
163 if( member != rootNodeType
164 && name.equals( rootNodeType.getName() )
165 )
166 {
167 mbox.error( new Message.ReservedNameNode
168 ( file
169 , name.getPosition()
170 )
171 );
172 return;
173 }
174 Map
175 if( memberMap.containsKey( nameStr ) )
176 {
177 mbox.error( new Message.ModuleMemberAlreadyDefined
178 ( file
179 , name.getPosition()
180 , nameStr
181 , ((ModuleMember)memberMap.get( nameStr )).getName().getPosition()
182 )
183 );
184 return;
185 }
186 memberMap.put( nameStr, member );
187 }
188
189 private void registerOperation( OperationDecl operationDecl )
190 {
191 ID name = operationDecl.getName();
192 for( int i = 0; i < operationDecl.sizeOptParameterDeclList(); i++ )
193 {
194 ParameterDecl parDecl = operationDecl.getOptParameterDeclList(i);
195 if( parDecl instanceof VirtualParameterDecl )
196 {
197 visit( ((VirtualParameterDecl)parDecl).getType() );
198 } else {
199 visit( ((NonVirtualParameterDecl)parDecl).getType() );
200 }
201 }
202 StringBuffer sb = new StringBuffer();
203 sb.append( "(" );
204 for( int i = 0; i < operationDecl.sizeOptParameterDeclList(); i++ )
205 {
206 if( i > 0 ) sb.append( "," );
207 ParameterDecl parDecl = operationDecl.getOptParameterDeclList(i);
208 if( parDecl instanceof VirtualParameterDecl )
209 {
210 sb.append( TDL.toString( ((VirtualParameterDecl)parDecl).getType() ) );
211 } else {
212 sb.append( TDL.toString( ((NonVirtualParameterDecl)parDecl).getType() ) );
213 }
214 }
215 sb.append( ")" );
216 String nameStr = sb.toString();
217 operationDecl.setParameters( nameStr );
218 nameStr = name.getValue() + nameStr;
219
220 Map
221 if( memberMap.containsKey( nameStr ) )
222 {
223 mbox.error( new Message.ModuleMemberAlreadyDefined
224 ( file
225 , name.getPosition()
226 , nameStr
227 , ((ModuleMember)memberMap.get( nameStr )).getName().getPosition()
228 )
229 );
230 return;
231 }
232 memberMap.put( nameStr, operationDecl );
233 }
234
235 private Map
236 = new HashMap
237
238 /***
239 * Register synonym of module.
240 * @param synonym
241 * @param module
242 */
243 private void registerBaseModule( ID synonym, TDL_Module module )
244 {
245 if( synonymToBaseModuleMap.containsKey( synonym ) )
246 {
247 mbox.error( new Message.SynonymAlreadyDefined
248 ( file
249 , synonym.getPosition()
250 , synonym.getValue()
251 , ((TDL_Module)synonymToBaseModuleMap.get( synonym ))
252 .getRoot().getName().getFirst().getPosition()
253 )
254 );
255 return;
256 }
257 synonymToBaseModuleMap.put( synonym, module );
258 }
259
260 /***
261 * Find module by synonym.
262 *
263 * @param synonym Synonym for module.
264 * @return Module for given synonym or null if this synonym is not defined.
265 */
266 private TDL_Module findBaseModule( ID synonym )
267 {
268 return (TDL_Module)synonymToBaseModuleMap.get( synonym );
269 }
270
271 public void visitModule( Module node )
272 {
273
274 registerBaseModule( node.getName().getLast(), module );
275 NodeTypeDecl rootNodeType = TDL_Module.getRootNodeType();
276
277 registerType( rootNodeType );
278
279
280 int ec = mbox.getErrorCount();
281 visit( node.getOptBaseModuleList() );
282 if( mbox.getErrorCount() > ec ) return;
283 addReferencedModule( node );
284
285
286 for( int i = 0; i < node.sizeOptMemberList(); i++ )
287 {
288 ModuleMember member = node.getOptMemberList( i );
289 if( member instanceof ModuleTypeMember )
290 {
291 registerType( (ModuleTypeMember)member );
292 if( member instanceof NodeTypeDecl
293 && ((NodeTypeDecl)member).isRoot()
294 )
295 {
296 NodeTypeDecl nodeType = (NodeTypeDecl)member;
297 if( node.getOptRootNodeType() != null )
298 {
299 mbox.error( new Message.RootNodeTypeAlreadyDefined
300 ( file
301 , nodeType.getName().getPosition()
302 , node.getOptRootNodeType().getName().getPosition()
303 )
304 );
305 } else {
306 node.setOptRootNodeType( nodeType );
307 }
308 }
309 }
310 }
311
312 for( int i = 0; i < node.sizeOptMemberList(); i++ )
313 {
314 ModuleMember member = node.getOptMemberList( i );
315 if( member instanceof OperationDecl )
316 {
317 registerOperation( (OperationDecl)member );
318 }
319 }
320
321 visit( node.getOptMemberList() );
322 }
323
324 private Map
325 fullNameToBaseModuleMap = new HashMap
326
327 public void visitBaseModule( BaseModule node )
328 {
329 QID name = node.getName();
330 String nameStr = name.getValue();
331 TDL_Module baseModule = moduleMap.loadModule( name );
332 if( baseModule == null || !name.equals( baseModule.getRoot().getName() ) )
333 {
334 mbox.error( new Message.BaseModuleNotFound
335 ( file
336 , name.getFirst().getPosition()
337 , name.getValue()
338 )
339 );
340 return;
341 }
342 node.setModule( baseModule );
343
344 if( fullNameToBaseModuleMap.containsKey( nameStr ) )
345 {
346 mbox.error( new Message.BaseModuleAlreadyReferenced
347 ( file
348 , name.getFirst().getPosition()
349 , nameStr
350 , ((BaseModule)fullNameToBaseModuleMap.get( nameStr ))
351 .getName().getFirst().getPosition()
352 )
353 );
354 return;
355 }
356 fullNameToBaseModuleMap.put( nameStr, node );
357
358 ID synonym = node.getOptSynonym();
359 if( synonym == null )
360 {
361 synonym = name.getLast();
362 }
363
364 registerBaseModule( synonym, baseModule );
365
366 String baseLanguage
367 = baseModule.getRoot().getProperty( Module.PROPERTY_TREEDL_LANGUAGE
368 , Module.DEFAULT_TREEDL_LANGUAGE
369 );
370 String language
371 = module.getRoot().getProperty( Module.PROPERTY_TREEDL_LANGUAGE
372 , Module.DEFAULT_TREEDL_LANGUAGE
373 );
374 if( !language.equals( baseLanguage )
375 && !baseLanguage.equals( Module.DEFAULT_TREEDL_LANGUAGE )
376 )
377 {
378 mbox.error( new Message.IncompatibleBaseModuleLanguage
379 ( file
380 , ((Module)node.getParent()).getName().getFirst().getPosition()
381 , language
382 , baseLanguage
383 , node.getName().getValue()
384 )
385 );
386 }
387
388 check( moduleMap, baseModule );
389 List
390 for( int i = 0; i < ml.size(); i++ )
391 {
392 addReferencedModule( (Module)ml.get(i) );
393 }
394 }
395
396 private void addReferencedModule( Module m )
397 {
398 if( findReferencedModule( m.getName().getValue() ) >= 0 ) return;
399 module.getRoot().getReferencedModuleList().add( m );
400 module
401 .getRoot()
402 .getReferencedModuleMap()
403 .put( m.getName().getValue()
404 , new Integer( module.getRoot().sizeReferencedModuleList() - 1 )
405 );
406 }
407
408 private int findReferencedModule( String name )
409 {
410 Integer index = (Integer)module.getRoot().getReferencedModuleMap().get( name );
411 if( index == null ) return -1;
412 return index.intValue();
413 }
414
415 public void visitModuleMember( ModuleMember node )
416 {
417 switch( node.getState().key() )
418 {
419 case CheckState.Key.NOT_CHECKED:
420 node.setState( CheckState.CHECKING );
421 break;
422 case CheckState.Key.CHECKING:
423 mbox.error( new Message.TypeCircularDependence
424 ( module.getFile()
425 , node.getName().getPosition()
426 , getString( TDL.class
427 , node instanceof NodeTypeDecl
428 ? "message.node_type"
429 : ((ConstTypeDecl)node).isFlags()
430 ? "message.flags_type"
431 : "message.enum_type"
432 )
433 , node.getName().getValue()
434 )
435 );
436 node.setState( CheckState.CHECKED );
437 break;
438 case CheckState.Key.CHECKED:
439 break;
440 }
441 }
442
443 public void visitModuleTypeMember( ModuleTypeMember node )
444 {
445 visitModuleMember( node );
446 if( node.getState() == CheckState.CHECKED ) return;
447
448 node.getOptInheritorList().add( node );
449
450 TypeRef baseTypeRef = node.getOptBaseType();
451 if( baseTypeRef != null )
452 {
453
454 visit( baseTypeRef );
455 ModuleTypeMember baseType = baseTypeRef.getType();
456 if( baseType != null )
457 {
458 baseType.getOptInheritorList().add( node );
459 }
460 }
461 }
462
463 public void visitConstTypeDecl( ConstTypeDecl node )
464 {
465 visitModuleTypeMember( node );
466 if( node.getState() == CheckState.CHECKED ) return;
467
468 TypeRef baseTypeRef = node.getOptBaseType();
469 if( baseTypeRef != null )
470 {
471 ModuleTypeMember baseType = baseTypeRef.getType();
472 if( baseType != null )
473 {
474 if( baseType instanceof ConstTypeDecl )
475 {
476 ConstTypeDecl baseConstType = (ConstTypeDecl)baseType;
477 if( node.isFlags() == ((ConstTypeDecl)baseType).isFlags() )
478 {
479 visit( baseConstType );
480 node.getFullConstantList().addAll( baseConstType.getFullConstantList() );
481 node.getConstToTypeMap().putAll( baseConstType.getConstToTypeMap() );
482 } else {
483 mbox.error( new Message.IncompatibleBaseType
484 ( file
485 , node.getName().getPosition()
486 , getString( TDL.class
487 , node.isFlags()
488 ? "message.flags_type"
489 : "message.enum_type"
490 )
491 , node.getName().getValue()
492 )
493 );
494 }
495 } else {
496 mbox.error( new Message.IncompatibleBaseType
497 ( file
498 , node.getName().getPosition()
499 , getString( TDL.class
500 , node.isFlags()
501 ? "message.flags_type"
502 : "message.enum_type"
503 )
504 , node.getName().getValue()
505 )
506 );
507 }
508 }
509 }
510 for( int i = 0; i < node.sizeOptConstantList(); i++ )
511 {
512 ID constant = node.getOptConstantList( i );
513 if( node.getConstToTypeMap().containsKey( constant ) )
514 {
515 mbox.error( new Message.ConstantAlreadyDefined
516 ( file
517 , constant.getPosition()
518 , constant.getValue()
519 )
520 );
521 } else {
522 node.getConstToTypeMap().put( constant, node );
523 }
524 }
525 node.getFullConstantList().addAll( node.getOptConstantList() );
526 node.setState( CheckState.CHECKED );
527 }
528
529 public void visitNodeTypeDecl( NodeTypeDecl node )
530 {
531 visitModuleTypeMember( node );
532 if( node.getState() == CheckState.CHECKED ) return;
533
534 Module module = (Module)node.getParent();
535 if( !module.isTree() )
536 {
537 mbox.error( new Message.NodeTypeCantBeInModule
538 ( file
539 , node.getName().getPosition()
540 )
541 );
542 }
543
544 TypeRef baseTypeRef = node.getOptBaseType();
545 NodeTypeDecl baseNodeType = null;
546 if( baseTypeRef != null )
547 {
548 ModuleTypeMember baseType = baseTypeRef.getType();
549 if( baseType != null )
550 {
551 if( baseType instanceof NodeTypeDecl )
552 {
553 baseNodeType = (NodeTypeDecl)baseType;
554 } else {
555 mbox.error( new Message.IncompatibleBaseType
556 ( file
557 , node.getName().getPosition()
558 , getString( TDL.class, "message.node_type" )
559 , node.getName().getValue()
560 )
561 );
562 }
563 }
564 }
565 if( baseNodeType == null )
566 {
567 baseNodeType = TDL_Module.getRootNodeType();
568 }
569 visit( baseNodeType );
570 node.setBaseNodeType( baseNodeType );
571 if( node.isAbstract() && !baseNodeType.isAbstract() )
572 {
573 mbox.error( new Message.AbstractBaseNodeRequired
574 ( file
575 , node.getName().getPosition()
576 , node.getName().getValue()
577 )
578 );
579 }
580 Map
581 nameToFieldMap.putAll( baseNodeType.getNameToFieldMap() );
582 node.getFullFieldList().addAll( baseNodeType.getFullFieldList() );
583 visit( node.getOptMemberList() );
584 if( !node.isAbstract() )
585 {
586 for( Iterator i = nameToFieldMap.values().iterator();
587 i.hasNext();
588 )
589 {
590 Field field = (Field)i.next();
591 if( field.getParent() != node
592 && field.checkModifiers( Modifiers.ABSTRACT )
593 )
594 {
595 mbox.error( new Message.AbstractAttributeShouldBeOverridden
596 ( file
597 , node.getName().getPosition()
598 , node.getName().getValue()
599 )
600 );
601 }
602 }
603 }
604 node.setState( CheckState.CHECKED );
605 }
606
607 public void visitConstructorCodeMember( ConstructorCodeMember node )
608 {
609 }
610
611 public void visitBodyCodeMember( BodyCodeMember node )
612 {
613 }
614
615 public void visitField( Field node )
616 {
617 NodeTypeDecl nodeType = (NodeTypeDecl)node.getParent();
618 ID name = node.getName();
619
620 if( nodeType.getNameToFieldMap().containsKey( name ) )
621 {
622 Field baseField = (Field)nodeType.getNameToFieldMap().get( name );
623 if( baseField.getParent() == nodeType )
624 {
625 mbox.error( new Message.NodeMemberAlreadyDefined
626 ( file
627 , name.getPosition()
628 , name.getValue()
629 )
630 );
631 return;
632 }
633 node.setBaseField( baseField );
634 }
635 nodeType.getNameToFieldMap().put( name, node );
636 nodeType.getFullFieldList().add( node );
637
638 visit( node.getType() );
639
640 if( node.getType() instanceof TDL.NodeType )
641 {
642
643 if( ((TDL.NodeType)node.getType()).getType().getType() == null ) return;
644
645
646 TDL_Module.insert( ((TDL.NodeType)node.getType())
647 .getType()
648 .getType()
649 .getOptParentTypeList()
650 , nodeType
651 );
652 }
653
654 if( node.isChild() )
655 {
656 if( node.checkModifiers( Modifiers.ABSTRACT )
657 || node.checkModifiers( Modifiers.CUSTOM )
658 || node.checkModifiers( Modifiers.NOSET )
659 )
660 {
661 mbox.error( new Message.ChildCantBeAbstractCustomNoSet
662 ( file
663 , node.getName().getPosition()
664 , node.getName().getValue()
665 )
666 );
667 }
668 }
669
670 Field baseField = node.getBaseField();
671 if( baseField != null )
672 {
673
674 if( node.isChild() != baseField.isChild() )
675 {
676 mbox.error( new Message.IncompatibleBaseField
677 ( file
678 , node.getName().getPosition()
679 , getString( TDL.class
680 , node.isChild()
681 ? "message.child"
682 : "message.attribute"
683 )
684 , node.getName().getValue()
685 )
686 );
687 }
688
689 if( !node.getType().equals( baseField.getType() ) )
690 {
691 mbox.error( new Message.IncompatibleBaseFieldType
692 ( file
693 , node.getName().getPosition()
694 , getString( TDL.class
695 , node.isChild()
696 ? "message.child"
697 : "message.attribute"
698 )
699 , node.getName().getValue()
700 )
701 );
702 }
703
704 if( !baseField.checkModifiers( Modifiers.ABSTRACT ) )
705 {
706 if( !node.checkModifiers( Modifiers.OVERRIDE ) )
707 {
708 mbox.error( new Message.OverrideModifierRequired
709 ( file
710 , node.getName().getPosition()
711 , getString( TDL.class
712 , node.isChild()
713 ? "message.child"
714 : "message.attribute"
715 )
716 , node.getName().getValue()
717 )
718 );
719 }
720
721 if( node.checkModifiers( Modifiers.ABSTRACT ) )
722 {
723 mbox.error( new Message.AbstractAttributeCantOverrideNonAbstract
724 ( file
725 , node.getName().getPosition()
726 , node.getName().getValue()
727 )
728 );
729 }
730
731 if( node.checkModifiers( Modifiers.CUSTOM ) )
732 {
733 mbox.error( new Message.CustomModifierNotAllowedWhenOverridingNonAbstract
734 ( file
735 , node.getName().getPosition()
736 , node.getName().getValue()
737 )
738 );
739 }
740 }
741
742 if( node.checkModifiers( Modifiers.LATE )
743 && !baseField.checkModifiers( Modifiers.LATE )
744 )
745 {
746 mbox.error( new Message.NonLateAttributeCantOverrideLate
747 ( file
748 , node.getName().getPosition()
749 , node.getName().getValue()
750 )
751 );
752 }
753 if( node.checkModifiers( Modifiers.NOSET )
754 && !baseField.checkModifiers( Modifiers.NOSET )
755 )
756 {
757 mbox.error( new Message.NoSetAttributeCanOverrideOnlyNoSet
758 ( file
759 , node.getName().getPosition()
760 , node.getName().getValue()
761 )
762 );
763 }
764 if( node.checkModifiers( Modifiers.SETONCE )
765 != baseField.checkModifiers( Modifiers.SETONCE )
766 )
767 {
768 mbox.error( new Message.IncompatibleSetOnceModifiers
769 ( file
770 , node.getName().getPosition()
771 , node.getName().getValue()
772 )
773 );
774 }
775 }
776
777 if( node.checkModifiers( Modifiers.ABSTRACT ) )
778 {
779 if( !nodeType.isAbstract() )
780 {
781 mbox.error( new Message.AbstractAttributeShouldBeInAbstractNode
782 ( file
783 , node.getName().getPosition()
784 , node.getName().getValue()
785 )
786 );
787 return;
788 }
789 if( node.getOptGetCode() != null || node.getOptSetCode() != null )
790 {
791 mbox.error( new Message.CustomCodeNotAllowedForAbstractAttribute
792 ( file
793 , node.getName().getPosition()
794 , node.getName().getValue()
795 )
796 );
797 }
798 }
799 if( node.checkModifiers( Modifiers.CUSTOM )
800 && node.checkModifiers( Modifiers.ABSTRACT )
801 )
802 {
803 mbox.error( new Message.AbstractAttributeCantBeCustom
804 ( file
805 , node.getName().getPosition()
806 , node.getName().getValue()
807 )
808 );
809 }
810 if( !TDL_Module.hasGet( node )
811 && !nodeType.isAbstract()
812 )
813 {
814 mbox.error( new Message.GetOperationNotDefined
815 ( file
816 , node.getName().getPosition()
817 , node.getName().getValue()
818 )
819 );
820 }
821 if( !node.checkModifiers( Modifiers.NOSET )
822 && !TDL_Module.hasSet( node )
823 && !nodeType.isAbstract()
824 )
825 {
826 mbox.error( new Message.SetOperationNotDefined
827 ( file
828 , node.getName().getPosition()
829 , node.getName().getValue()
830 )
831 );
832 }
833 if( node.checkModifiers( Modifiers.NOSET ) )
834 {
835 if( !node.checkModifiers( Modifiers.LATE ) )
836 {
837 mbox.error( new Message.NoSetAttributeShouldBeLate
838 ( file
839 , node.getName().getPosition()
840 , node.getName().getValue()
841 )
842 );
843 }
844 if( node.getOptInitCode() != null )
845 {
846 mbox.error( new Message.InitializerNotAllowedForNoSetAttribute
847 ( file
848 , node.getName().getPosition()
849 , node.getName().getValue()
850 )
851 );
852 }
853 if( node.getOptSetCode() != null )
854 {
855 mbox.error( new Message.SetCodeNotAllowedForNoSetAttribute
856 ( file
857 , node.getName().getPosition()
858 , node.getName().getValue()
859 )
860 );
861 }
862 if( node.checkModifiers( Modifiers.SETONCE ) )
863 {
864 mbox.error( new Message.SetOnceNotAllowedForNoSetAttribute
865 ( file
866 , node.getName().getPosition()
867 , node.getName().getValue()
868 )
869 );
870 }
871 }
872 }
873
874 public void visitOperationDecl( OperationDecl node )
875 {
876
877 int ec = mbox.getErrorCount();
878 visit( node.getOptOperationRefList() );
879 if( mbox.getErrorCount() > ec ) return;
880
881
882 visit( node.getReturnType() );
883
884
885 if( node.isVirtual()
886 && !((Module)node.getParent()).isTree()
887 )
888 {
889 mbox.error( new Message.VirtualOperationCantBeInModule
890 ( file
891 , node.getName().getPosition()
892 , node.getName().getValue()
893 )
894 );
895 }
896
897
898 Map
899 for( int i = 0; i < node.sizeOptParameterDeclList(); i++ )
900 {
901 ParameterDecl param = node.getOptParameterDeclList( i );
902 ID name = param.getName();
903 if( nameToParameterMap.containsKey( name ) )
904 {
905 mbox.error( new Message.ParameterAlreadyDeclared
906 ( file
907 , node.getName().getPosition()
908 , node.getName().getValue()
909 )
910 );
911 return;
912 }
913 nameToParameterMap.put( name, param );
914 }
915
916
917 visit( node.getOptParameterDeclList() );
918
919 if( mbox.getErrorCount() > 0 ) return;
920
921 ModuleMatrix moduleMatrix = new ModuleMatrix( node, mbox, file );
922
923
924 visit( node.getOptCaseList() );
925
926 if( mbox.getErrorCount() > 0 ) return;
927
928
929 for( Index mi = moduleMatrix.createIndex()
930 ; mi.has()
931 ; mi.next()
932 )
933 {
934 ParameterVariantMatrix paramMatrix = moduleMatrix.getParamMatrix( mi );
935
936 if( paramMatrix == null ) continue;
937 for( Index pi = paramMatrix.createIndex()
938 ; pi.has()
939 ; pi.next()
940 )
941 {
942 if( paramMatrix.get( pi ) == null )
943 {
944 mbox.error( new Message.CaseNotDefined
945 ( file
946 , node.getName().getPosition()
947 , paramMatrix.getVariantString( pi )
948 )
949 );
950 }
951 }
952 }
953 }
954
955 public void visitNonVirtualParameterDecl( NonVirtualParameterDecl node )
956 {
957
958
959 }
960
961 public void visitVirtualParameterDecl( VirtualParameterDecl node )
962 {
963
964
965
966 ModuleTypeMember type = node.getType().getType();
967 if( type == null ) return;
968
969 if( type instanceof ConstTypeDecl && ((ConstTypeDecl)type).isFlags() )
970 {
971 mbox.error( new Message.VirtualParameterCantBeOfFlagsType
972 ( file
973 , node.getName().getPosition()
974 , node.getName().getValue()
975 )
976 );
977 }
978 }
979
980 public void visitOperationRef( OperationRef node )
981 {
982 TDL_Module module;
983 ID optModuleName = node.getOptModuleName();
984 if( optModuleName != null )
985 {
986 module = findBaseModule( optModuleName );
987 if( module == null )
988 {
989 mbox.error( new Message.SynonymNotDefined
990 ( file
991 , optModuleName.getPosition()
992 , optModuleName.getValue()
993 )
994 );
995 return;
996 }
997 } else {
998 module = this.module;
999 }
1000 node.setModule( module );
1001 String signature = node.getName().getValue()
1002 + ((OperationDecl)node.getParent()).getParameters();
1003 OperationDecl opDecl = module.findOperation( signature );
1004 if( opDecl == null )
1005 {
1006 mbox.error( new Message.OperationNotFound
1007 ( file
1008 , node.getName().getPosition()
1009 , optModuleName != null ? optModuleName.getValue() : null
1010 , signature
1011 )
1012 );
1013 return;
1014 }
1015 OperationDecl operationDecl = (OperationDecl)node.getParent();
1016 if( !operationDecl.getReturnType().equals( opDecl.getReturnType() ) )
1017 {
1018 mbox.error( new Message.IncompatibleReturnTypes
1019 ( file
1020 , node.getName().getPosition()
1021 , opDecl
1022 )
1023 );
1024 }
1025
1026 for( int i = 0; i < operationDecl.sizeOptParameterDeclList(); i++ )
1027 {
1028 ParameterDecl pd = operationDecl.getOptParameterDeclList( i );
1029 if( (pd instanceof VirtualParameterDecl ? 1 : 0)
1030 + (opDecl.getOptParameterDeclList(i) instanceof VirtualParameterDecl ? 1 : 0)
1031 == 1
1032 )
1033 {
1034 mbox.error( new Message.InconsistentVirtualParameters
1035 ( file
1036 , pd.getName().getPosition()
1037 , opDecl
1038 , pd
1039 )
1040 );
1041 }
1042 }
1043
1044 node.setOperationDecl( opDecl );
1045 }
1046
1047 public void visitCase( Case node )
1048 {
1049 visit( node.getCaseSignatureList() );
1050 }
1051
1052 public void visitCaseSignature( CaseSignature node )
1053 {
1054 OperationDecl operationDecl = (OperationDecl)node.getParent().getParent();
1055
1056 if( operationDecl.sizeOptParameterDeclList() != node.sizeParameterList() )
1057 {
1058 mbox.error( new Message.IncorrectNumberOfParameters
1059 ( file
1060 , node.getPosition()
1061 , operationDecl.getName().getValue()
1062 , operationDecl.getName().getPosition()
1063 )
1064 );
1065 return;
1066 }
1067
1068 boolean typeNotFound = false;
1069 for( int i = 0; i < node.sizeParameterList(); i++ )
1070 {
1071 ParameterDecl paramDecl = operationDecl.getOptParameterDeclList( i );
1072 Parameter param = node.getParameterList( i );
1073
1074 visit( param );
1075
1076 ModuleTypeMember paramType = null;
1077 if( param.getOptType() != null )
1078 {
1079 paramType = param.getOptType().getType();
1080 if( paramType == null )
1081 {
1082 typeNotFound = true;
1083 continue;
1084 }
1085 }
1086
1087 if( paramDecl instanceof VirtualParameterDecl )
1088 {
1089 ModuleTypeMember paramDeclType
1090 = ((VirtualParameterDecl)paramDecl).getType().getType();
1091 if( paramDeclType instanceof ConstTypeDecl )
1092 {
1093 if( param.getOptType() != null )
1094 {
1095 mbox.error( new Message.TypeNotAllowedForVirtualEnumParameter
1096 ( file
1097 , node.getPosition()
1098 , paramDecl.getName().getValue()
1099 )
1100 );
1101 return;
1102 }
1103
1104 if( !TDL_Module.isConstantOfType( param.getName()
1105 , (ConstTypeDecl)paramDeclType
1106 )
1107 )
1108 {
1109 mbox.error( new Message.ConstantRequiredForVirtualEnumParameter
1110 ( file
1111 , node.getPosition()
1112 , param.getName().getValue()
1113 , paramDeclType.getName().getValue()
1114 , paramDecl.getName().getValue()
1115 )
1116 );
1117 return;
1118 }
1119 continue;
1120 }
1121 if( param.getOptType() == null )
1122 {
1123 mbox.error( new Message.TypeRequiredForVirtualNodeParameter
1124 ( file
1125 , node.getPosition()
1126 , paramDecl.getName().getValue()
1127 )
1128 );
1129 return;
1130 }
1131 if( !TDL_Module.isBaseTypeOf( paramDeclType, paramType ) )
1132 {
1133 mbox.error( new Message.CaseParameterTypeShouldBeInheritor
1134 ( file
1135 , node.getPosition()
1136 , param.getOptType().getName().getValue()
1137 , param.getName().getValue()
1138 , paramDeclType.getName().getValue()
1139 )
1140 );
1141 return;
1142 }
1143 if( ((NodeTypeDecl)paramType).isAbstract() )
1144 {
1145 mbox.error( new Message.CaseParameterTypeShouldNotBeAbstract
1146 ( file
1147 , node.getPosition()
1148 , paramType.getName().getValue()
1149 , param.getName().getValue()
1150 )
1151 );
1152 return;
1153 }
1154 if( !paramDecl.getName().equals( param.getName() ) )
1155 {
1156 mbox.error( new Message.CaseParameterNameDiffers
1157 ( file
1158 , node.getPosition()
1159 , operationDecl.getName().getValue()
1160 , param.getName().getValue()
1161 , paramDecl.getName().getValue()
1162 , paramDecl.getName().getPosition()
1163 )
1164 );
1165 return;
1166 }
1167 } else {
1168 if( param.getOptType() != null )
1169 {
1170 mbox.error( new Message.CaseParameterTypeNotAllowed
1171 ( file
1172 , node.getPosition()
1173 , param.getName().getValue()
1174 )
1175 );
1176 return;
1177 }
1178 if( !paramDecl.getName().equals( param.getName() ) )
1179 {
1180 mbox.error( new Message.CaseParameterNameDiffers( file
1181 , node.getPosition()
1182 , operationDecl.getName().getValue()
1183 , param.getName().getValue()
1184 , paramDecl.getName().getValue()
1185 , paramDecl.getName().getPosition()
1186 )
1187 );
1188 return;
1189 }
1190 }
1191 }
1192 if( typeNotFound ) return;
1193 CaseSignature signature = operationDecl.getModuleMatrix().addCase( node );
1194 if( signature != null )
1195 {
1196 mbox.error( new Message.CaseAlreadyDefined
1197 ( file
1198 , node.getPosition()
1199 , signature
1200 )
1201 );
1202 return;
1203 }
1204 }
1205
1206 public void visitParameter( Parameter node )
1207 {
1208 visit( node.getOptType() );
1209 }
1210
1211 public void visitNodeType( NodeType node )
1212 {
1213 visit( node.getType() );
1214 }
1215
1216 public void visitPredefinedType( PredefinedType node )
1217 {
1218
1219 }
1220
1221 public void visitNameType( NameType node )
1222 {
1223
1224 }
1225
1226 public void visitTypeRef( TypeRef node )
1227 {
1228 TDL_Module module;
1229 ID optModuleName = node.getOptModuleName();
1230 if( optModuleName != null )
1231 {
1232 module = findBaseModule( optModuleName );
1233 if( module == null )
1234 {
1235 mbox.error( new Message.SynonymNotDefined( file
1236 , optModuleName.getPosition()
1237 , optModuleName.getValue()
1238 )
1239 );
1240 return;
1241 }
1242 } else {
1243 module = this.module;
1244 }
1245 node.setModule( module );
1246 ModuleTypeMember member = module.findModuleTypeMember( node.getName().getValue() );
1247 if( member == null )
1248 {
1249 mbox.error( new Message.TypeNotFound( file
1250 , node.getName().getPosition()
1251 , optModuleName != null ? optModuleName.getValue() : null
1252 , node.getName().getValue()
1253 )
1254 );
1255 return;
1256 }
1257 node.setType( member );
1258 }
1259
1260 public void visitID( ID node )
1261 {
1262 throw new UnsupportedOperationException();
1263 }
1264
1265 public void visitQID( QID node )
1266 {
1267 throw new UnsupportedOperationException();
1268 }
1269
1270 public void visitCode( Code node )
1271 {
1272 throw new UnsupportedOperationException();
1273 }
1274 }