示例#1
0
    def access_id(self, id_, lineno, 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_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)

        return result
示例#2
0
    def access_func(self, id_, lineno, 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
示例#3
0
 def test_offset(self):
     gl.SYMBOL_TABLE.declare_array('test', 1, symbols.TYPEREF(self.arr.type_, 1),
                                   bounds=self.bounds)
     aa = symbols.ARRAYACCESS.make_node('test', self.arg, lineno=2)
     self.assertIsInstance(aa, symbols.ARRAYACCESS)
     self.assertIsNotNone(aa.offset)
     self.assertEqual(aa.offset, 2)
示例#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)
     aa = symbols.ARRAYACCESS.make_node('test', self.arg, lineno=2)
     self.assertIsNotNone(aa)
     self.assertEqual(self.OUTPUT, "(stdin):2: warning: Array 'test' subscript out of range\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))
     aa = symbols.ARRAYACCESS.make_node('test', self.arg, lineno=2)
     self.assertIsNone(aa)
     self.assertEqual(self.OUTPUT, "(stdin):2: Array 'test' has 2 dimensions, not 1\n")
示例#6
0
    def declare(self, id_: str, lineno: int, entry):
        """ 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[self.current_scope][id2] is not None:
            return None

        entry.caseins = OPTIONS.case_insensitive.value
        self[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.forwarded = False  # True for a function header
        entry.mangled = '%s%s%s' % (self.mangle, global_.MANGLE_CHR, entry.name
                                    )  # Mangled name
        entry.type_ = type_  # type_ now reflects entry sigil (i.e. a$ => 'string' type) if any
        entry.scopeRef = self[self.current_scope]

        return entry
示例#7
0
 def btyperef(self, type_):
     assert TYPE.is_valid(type_)
     return symbols.TYPEREF(symbols.BASICTYPE(type_), 0)