Exemplo n.º 1
0
    def access_id(self, id_: str, lineno: int, scope=None, default_type=None, default_class=CLASS.unknown):
        """ Access a symbol by its identifier and checks if it exists.
        If not, it's supposed to be an implicit declared variable.

        default_class is the class to use in case of an undeclared-implicit-accessed id
        """
        if isinstance(default_type, symbols.BASICTYPE):
            default_type = symbols.TYPEREF(default_type, lineno, implicit=False)
        assert default_type is None or isinstance(default_type, symbols.TYPEREF)

        if not check.check_is_declared_explicit(lineno, id_):
            return None

        result = self.get_entry(id_, scope)
        if result is None:
            if default_type is None:
                default_type = symbols.TYPEREF(self.basic_types[global_.DEFAULT_IMPLICIT_TYPE],
                                               lineno, implicit=True)

            result = self.declare_variable(id_, lineno, default_type)
            result.declared = False  # It was implicitly declared
            result.class_ = default_class
            return result

        # The entry was already declared. If it's type is auto and the default type is not None,
        # update its type.
        if default_type is not None and result.type_ == self.basic_types[TYPE.auto]:
            result.type_ = default_type
            warning_implicit_type(lineno, id_, default_type.name)

        return result
Exemplo n.º 2
0
    def access_func(self,
                    id_: str,
                    lineno: int,
                    scope=None,
                    default_type=None):
        """
        Since ZX BASIC allows access to undeclared functions, we must allow
        and *implicitly* declare them if they are not declared already.
        This function just checks if the id_ exists and returns its entry if so.
        Otherwise, creates an implicit declared variable entry and returns it.
        """
        assert default_type is None or isinstance(default_type,
                                                  symbols.TYPEREF)

        result = self.get_entry(id_, scope)
        if result is None:
            if default_type is None:
                if global_.DEFAULT_IMPLICIT_TYPE == TYPE.auto:
                    default_type = symbols.TYPEREF(self.basic_types[TYPE.auto],
                                                   lineno,
                                                   implicit=True)
                else:
                    default_type = symbols.TYPEREF(
                        self.basic_types[global_.DEFAULT_TYPE],
                        lineno,
                        implicit=True)

            return self.declare_func(id_, lineno, default_type)

        if not self.check_class(id_, CLASS.function, lineno, scope):
            return None

        return result
Exemplo n.º 3
0
 def test_make_node(self):
     gl.SYMBOL_TABLE.declare_array('test',
                                   1,
                                   symbols.TYPEREF(self.arr.type_, 1),
                                   bounds=self.bounds)
     self.aa2 = symbols.ARRAYACCESS.make_node('test',
                                              self.arg,
                                              lineno=2,
                                              filename='fake-filename')
     self.assertIsInstance(self.aa2, symbols.ARRAYACCESS)
Exemplo n.º 4
0
 def test_make_node_warn(self):
     gl.SYMBOL_TABLE.declare_array('test',
                                   1,
                                   symbols.TYPEREF(self.arr.type_, 1),
                                   bounds=self.bounds)
     self.arg[1] = symbols.ARGUMENT(symbols.NUMBER(9, 1), 1)
     self.aa2 = symbols.ARRAYACCESS.make_node('test',
                                              self.arg,
                                              lineno=2,
                                              filename='fake-filename')
     self.assertIsNotNone(self.aa2)
     self.assertEqual(
         self.OUTPUT,
         "(stdin):2: warning: Array 'test' subscript out of range\n")
Exemplo n.º 5
0
 def test_make_node_fail(self):
     gl.SYMBOL_TABLE.declare_array('test',
                                   1,
                                   symbols.TYPEREF(self.arr.type_, 1),
                                   bounds=self.bounds)
     self.arg = symbols.ARGLIST(symbols.ARGUMENT(symbols.NUMBER(2, 1), 1))
     self.aa2 = symbols.ARRAYACCESS.make_node('test',
                                              self.arg,
                                              lineno=2,
                                              filename='fake-filename')
     self.assertIsNone(self.aa2)
     self.assertEqual(
         self.OUTPUT,
         "(stdin):2: error: Array 'test' has 2 dimensions, not 1\n")
Exemplo n.º 6
0
    def declare(self, id_: str, lineno: int, entry) -> Optional[SymbolVAR]:
        """ Check there is no 'id' already declared in the current scope, and
            creates and returns it. Otherwise, returns None,
            and the caller function raises the syntax/semantic error.
            Parameter entry is the SymbolVAR, SymbolVARARRAY, etc. instance
            The entry 'declared' field is leave untouched. Setting it if on
            behalf of the caller.
        """
        id2 = id_
        type_ = entry.type_

        if id2[-1] in DEPRECATED_SUFFIXES:
            id2 = id2[:-1]  # Remove it
            type_ = symbols.TYPEREF(self.basic_types[SUFFIX_TYPE[id_[-1]]],
                                    lineno)  # Overrides type_
            if entry.type_ is not None and not entry.type_.implicit and type_ != entry.type_:
                syntax_error(
                    lineno, "expected type {2} for '{0}', got {1}".format(
                        id_, entry.type_.name, type_.name))

        # Checks if already declared
        if self.current_scope[id2] is not None:
            return None

        entry.caseins = OPTIONS.case_insensitive
        self.current_scope[id2] = entry
        entry.name = id2  # Removes DEPRECATED SUFFIXES if any

        if isinstance(entry, symbols.TYPE):
            return entry  # If it's a type declaration, we're done

        # HINT: The following should be done by the respective callers!
        # entry.callable = None  # True if function, strings or arrays
        # entry.class_ = None  # TODO: important

        entry.mangled = self.make_child_namespace(self.current_namespace,
                                                  entry.name)  # Mangled name
        entry.type_ = type_  # type_ now reflects entry sigil (i.e. a$ => 'string' type) if any
        entry.scopeRef = self.current_scope

        return entry
Exemplo n.º 7
0
 def btyperef(self, type_):
     assert TYPE.is_valid(type_)
     return symbols.TYPEREF(symbols.BASICTYPE(type_), 0)