def test_make_node(self): self.clearOutput() l = symbols.NUMBER(2, lineno=1) u = symbols.NUMBER(3, lineno=2) symbols.BOUND.make_node(l, u, 3) self.assertEqual(self.stderr, '') l = symbols.NUMBER(4, lineno=1) symbols.BOUND.make_node(l, u, 3) self.assertEqual( self.stderr, '(stdin):3: Lower array bound must be less or equal to upper one\n' ) self.clearOutput() l = symbols.NUMBER(-4, lineno=1) symbols.BOUND.make_node(l, u, 3) self.assertEqual(self.stderr, '(stdin):3: Array bounds must be greater than 0\n') self.clearOutput() l = symbols.VAR('a', 10) symbols.BOUND.make_node(l, u, 3) self.assertEqual(self.stderr, '(stdin):3: Array bounds must be constants\n')
def declare_variable(self, id_, lineno, type_, default_value=None): """ Like the above, but checks that entry.declared is False. Otherwise raises an error. Parameter default_value specifies an initialized variable, if set. """ assert isinstance(type_, symbols.TYPEREF) if not self.check_is_undeclared(id_, lineno, scope=self.current_scope, show_error=False): entry = self.get_entry(id_) if entry.scope == SCOPE.parameter: syntax_error(lineno, "Variable '%s' already declared as a parameter " "at %s:%i" % (id_, entry.filename, entry.lineno)) else: syntax_error(lineno, "Variable '%s' already declared at " "%s:%i" % (id_, entry.filename, entry.lineno)) return None if not self.check_class(id_, CLASS.var, lineno, scope=self.current_scope): return None entry = (self.get_entry(id_, scope=self.current_scope) or self.declare(id_, lineno, symbols.VAR(id_, lineno, class_=CLASS.var))) __DEBUG__("Entry %s declared with class %s at scope %i" % (entry.name, CLASS.to_string(entry.class_), self.current_scope)) if entry.type_ is None or entry.type_ == self.basic_types[TYPE.unknown]: entry.type_ = type_ if entry.type_ != type_: if not type_.implicit and entry.type_ is not None: syntax_error(lineno, "'%s' suffix is for type '%s' but it was " "declared as '%s'" % (id_, entry.type_, type_)) return None entry.scope = SCOPE.global_ if self.current_scope == self.global_scope else SCOPE.local entry.callable = False entry.class_ = CLASS.var # HINT: class_ attribute could be erased if access_id was used. entry.declared = True # marks it as declared if entry.type_.implicit and entry.type_ != self.basic_types[TYPE.unknown]: warning_implicit_type(lineno, id_, entry.type_.name) if default_value is not None and entry.type_ != default_value.type_: if is_number(default_value): default_value = symbols.TYPECAST.make_node(entry.type_, default_value, lineno) if default_value is None: return None else: syntax_error(lineno, "Variable '%s' declared as '%s' but initialized " "with a '%s' value" % (id_, entry.type_, default_value.type_)) return None entry.default_value = default_value return entry
def setUp(self): zxbpp.init() self.l = symbols.VAR('a', lineno=1, type_=Type.ubyte) self.r = symbols.NUMBER(3, lineno=2) self.b = symbols.BINARY('PLUS', self.l, self.r, lineno=3) self.st = symbols.STRING("ZXBASIC", lineno=1) if OPTIONS.has_option('stderr'): OPTIONS.remove_option('stderr') OPTIONS.add_option('stderr', type_=None, default_value=StringIO())
def test_make_node_wrong(self): bad_index = symbols.VAR( 'a', 0, type_=gl.SYMBOL_TABLE.basic_types[gl.TYPE.string]) s = symbols.STRSLICE.make_node(1, self.str_, bad_index, bad_index) self.assertIsNone(s)
def setUp(self): self.v = symbols.VAR('v', 1) # This also tests __init__