1616from typing import Optional
1717from typing import Union
1818
19+ from src .api import errmsg
1920import src .api .check as check
2021
21- from .debug import __DEBUG__
22- from . import global_
22+ from src . api .debug import __DEBUG__
23+ from src . api import global_
2324
2425from src import symbols
2526from src .symbols .symbol_ import Symbol
@@ -254,7 +255,7 @@ def check_is_undeclared(self, id_: str, lineno: int, classname='identifier',
254255 scope [id_ ].lineno ))
255256 return False
256257
257- def check_class (self , id_ : str , class_ , lineno : int , scope = None , show_error = True ) -> bool :
258+ def check_class (self , id_ : str , class_ : CLASS , lineno : int , scope : Scope = None , show_error = True ) -> bool :
258259 """ Check the id is either undefined or defined with
259260 the given class.
260261
@@ -268,24 +269,13 @@ def check_class(self, id_: str, class_, lineno: int, scope=None, show_error=True
268269 """
269270 assert CLASS .is_valid (class_ )
270271 entry = self .get_entry (id_ , scope )
271- if entry is None or entry .class_ == CLASS .unknown : # Undeclared yet
272+ if entry is None or entry .class_ in ( CLASS .unknown , class_ ) : # Undeclared yet
272273 return True
273274
274- if entry .class_ != class_ :
275- if show_error :
276- if entry .class_ == CLASS .array :
277- a1 = 'n'
278- else :
279- a1 = ''
280- if class_ == CLASS .array :
281- a2 = 'n'
282- else :
283- a2 = ''
284- syntax_error (lineno , "identifier '%s' is a%s %s, not a%s %s" %
285- (id_ , a1 , entry .class_ , a2 , class_ ))
286- return False
275+ if show_error :
276+ check .check_class (entry , class_ , lineno )
287277
288- return True
278+ return False
289279
290280 # -------------------------------------------------------------------------
291281 # Scope Management
@@ -354,7 +344,7 @@ def leave_scope(self, show_warnings=True):
354344 warning_not_used (v .lineno , v .name , kind = kind )
355345
356346 for entry in self .current_scope .values (filter_by_opt = True ): # Symbols of the current level
357- if entry .class_ is CLASS .unknown :
347+ if entry .class_ == CLASS .unknown :
358348 self .move_to_global_scope (entry .name )
359349
360350 offset = self .compute_offsets (self .current_scope )
@@ -428,9 +418,8 @@ def access_id(self, id_: str, lineno: int, scope=None, default_type=None, defaul
428418 default_type = symbols .TYPEREF (self .basic_types [global_ .DEFAULT_IMPLICIT_TYPE ],
429419 lineno , implicit = True )
430420
431- result = self .declare_variable (id_ , lineno , default_type )
421+ result = self .declare_variable (id_ , lineno , default_type , class_ = default_class )
432422 result .declared = False # It was implicitly declared
433- result .class_ = default_class
434423 return result
435424
436425 # The entry was already declared. If it's type is auto and the default type is not None,
@@ -498,9 +487,10 @@ def access_func(self, id_: str, lineno: int, scope=None, default_type=None):
498487 else :
499488 default_type = symbols .TYPEREF (self .basic_types [global_ .DEFAULT_TYPE ], lineno , implicit = True )
500489
501- return self .declare_func (id_ , lineno , default_type )
490+ return self .declare_func (id_ , lineno , default_type , class_ = CLASS . unknown ) # Declare SUB / Func
502491
503- if not self .check_class (id_ , CLASS .function , lineno , scope ):
492+ if result .class_ not in (CLASS .function , CLASS .sub , CLASS .unknown ):
493+ errmsg .syntax_error_unexpected_class (lineno , id_ , result .class_ , CLASS .function )
504494 return None
505495
506496 return result
@@ -549,7 +539,7 @@ def access_label(self, id_: str, lineno: int, scope: Optional[Scope] = None):
549539
550540 return result
551541
552- def declare_variable (self , id_ , lineno , type_ , default_value = None ):
542+ def declare_variable (self , id_ , lineno , type_ , default_value = None , class_ : CLASS = CLASS . var ):
553543 """ Like the above, but checks that entry.declared is False.
554544 Otherwise raises an error.
555545
@@ -567,11 +557,11 @@ def declare_variable(self, id_, lineno, type_, default_value=None):
567557 "%s:%i" % (id_ , entry .filename , entry .lineno ))
568558 return None
569559
570- if not self .check_class (id_ , CLASS . var , lineno , scope = self .current_scope ):
560+ if not self .check_class (id_ , class_ , lineno , scope = self .current_scope ):
571561 return None
572562
573563 entry = (self .get_entry (id_ , scope = self .current_scope ) or
574- self .declare (id_ , lineno , symbols .VAR (id_ , lineno , class_ = CLASS . var )))
564+ self .declare (id_ , lineno , symbols .VAR (id_ , lineno , class_ = class_ )))
575565 __DEBUG__ ("Entry %s declared with class %s at scope %s" % (entry .name , CLASS .to_string (entry .class_ ),
576566 self .current_scope .namespace ))
577567
@@ -588,7 +578,7 @@ def declare_variable(self, id_, lineno, type_, default_value=None):
588578
589579 entry .scope = SCOPE .global_ if self .current_scope == self .global_scope else SCOPE .local
590580 entry .callable = False
591- entry .class_ = CLASS . var # HINT: class_ attribute could be erased if access_id was used.
581+ entry .class_ = class_ # Ensure class_ is set if variable was implicit
592582 entry .declared = True # marks it as declared
593583
594584 if entry .type_ .implicit and entry .type_ != self .basic_types [TYPE .unknown ]:
@@ -644,11 +634,10 @@ def declare_const(self, id_: str, lineno: int, type_, default_value):
644634 "%s:%i" % (id_ , entry .filename , entry .lineno ))
645635 return None
646636
647- entry = self .declare_variable (id_ , lineno , type_ , default_value )
637+ entry = self .declare_variable (id_ , lineno , type_ , default_value , class_ = CLASS . const )
648638 if entry is None :
649639 return None
650640
651- entry .class_ = CLASS .const
652641 return entry
653642
654643 def declare_label (self , id_ : str , lineno : int ) -> Optional [SymbolLABEL ]:
@@ -784,15 +773,13 @@ def declare_array(self, id_: str, lineno: int, type_, bounds, default_value=None
784773 self .current_scope ))
785774 return entry
786775
787- def declare_func (self , id_ : str , lineno : int , type_ = None ):
776+ def declare_func (self , id_ : str , lineno : int , type_ = None , class_ = CLASS . function ):
788777 """ Declares a function in the current scope.
789778 Checks whether the id exist or not (error if exists).
790779 And creates the entry at the symbol table.
791780 """
792- if not self .check_class (id_ , 'function' , lineno ):
793- entry = self .get_entry (id_ ) # Must not exist or have _class = None or Function and declared = False
794- an = 'an' if entry .class_ .lower ()[0 ] in 'aeio' else 'a'
795- syntax_error (lineno , "'%s' already declared as %s %s at %i" % (id_ , an , entry .class_ , entry .lineno ))
781+ assert class_ in (CLASS .function , CLASS .sub , CLASS .unknown )
782+ if not self .check_class (id_ , class_ , lineno ):
796783 return None
797784
798785 entry = self .get_entry (id_ ) # Must not exist or have _class = None or Function and declared = False
@@ -801,18 +788,15 @@ def declare_func(self, id_: str, lineno: int, type_=None):
801788 syntax_error (lineno , "Duplicate function name '%s', previously defined at %i" % (id_ , entry .lineno ))
802789 return None
803790
804- if entry .class_ != CLASS .unknown and entry .callable is False : # HINT: Must use is False here.
805- syntax_error_not_array_nor_func (lineno , id_ )
806- return None
807-
808791 if id_ [- 1 ] in DEPRECATED_SUFFIXES and entry .type_ != self .basic_types [SUFFIX_TYPE [id_ [- 1 ]]]:
809792 syntax_error_func_type_mismatch (lineno , entry )
810793
811794 if entry .token == 'VAR' : # This was a function used in advance
812795 symbols .VAR .to_function (entry , lineno = lineno )
813796 entry .mangled = '%s_%s' % (self .current_namespace , entry .name ) # HINT: mangle for nexted scopes
797+ entry .class_ = class_
814798 else :
815- entry = self .declare (id_ , lineno , symbols .FUNCTION (id_ , lineno , type_ = type_ ))
799+ entry = self .declare (id_ , lineno , symbols .FUNCTION (id_ , lineno , type_ = type_ , class_ = class_ ))
816800
817801 if entry .forwarded :
818802 entry .forwared = False # No longer forwarded
0 commit comments