Commits

David Boddie committed 0425cae

Changed the instruction argument validation mechanism to use exceptions
instead of boolean return values for type validation.
Added an additional validation mechanism for instructions to further
check argument values.

  • Participants
  • Parent commits e8f7565

Comments (0)

Files changed (2)

ATmega/definitions.py

 definitions.py - Common definitions for the ATmega package.
 """
 
+class ValidationError(Exception):
+    pass
+
 class Operand:
     pass
 
         else:
             return "<Register '"+self.name+"'>"
     
-    def validate(self, value):
-        return 0 <= value <= 31
+    def validate(self, register):
+    
+        # Accept Register objects or integers.
+        
+        if isinstance(register, Register):
+            if 0 <= register.name <= 31:
+                return register.name
+            else:
+                raise ValidationError, "Invalid register specified: %i" % register.name
+        
+        elif isinstance(register, int):
+            if 0 <= register <= 31:
+                return register
+            else:
+                raise ValidationError, "Invalid register specified: %i" % register
+        
+        else:
+            raise ValidationError, "Register expected but non-register specified: %s" % repr(register)
 
 class Constant(Operand):
 
             return "<Constant '"+self.name+"'>"
     
     def validate(self, value):
-        return True
+        return value
 
 class Address(Operand):
 
             return "<Address '"+self.name+"'>"
     
     def validate(self, value):
-        return True
+        return value
 
 class Status(Register):
 

ATmega/instructions.py

         self.match_arguments(args)
     
     def __repr__(self):
-        return "<"+self.text+" "+self.arguments_string+">"
+        if self.arguments_string:
+            return "<"+self.text+" "+self.arguments_string+">"
+        else:
+            return "<"+self.text+">"
     
     def match_arguments(self, args):
     
         
             if isinstance(piece, Operand):
                 try:
-                    valid = piece.validate(args[i])
+                    argument = piece.validate(args[i])
                 except IndexError:
                     raise ParseError, "Insuffient arguments to %s: %s" % (self.text, args)
-                
-                if not valid:
+                except ValidationError:
                     raise ParseError, "Invalid value for %s operand: %s" % (self.text, args[i])
                 
-                arguments_string += str(args[i])
-                values[piece.name] = args[i]
+                arguments_string += str(argument)
+                values[piece.name] = argument
                 i += 1
             else:
                 arguments_string += piece
         if i < len(args):
             raise ParseError, "Too many arguments specified to %s: %s" % (self.text, args)
         
+        self.validate(values)
+        
         self.arguments = arguments
         self.values = values
         self.arguments_string = arguments_string
     
+    def validate(self, values):
+    
+        pass
+    
     def generate(self):
     
         opcode = 0
             
             opcode = opcode | ((value & mask) << shift)
         
-        return opcode
+        length = len(self.opcode.text)/4
+        format = "%%0%ix" % length
+        return format % opcode
 
 class ADC(Instruction):
 
     opcode = Opcode("1110KKKKddddKKKK")
     flags = ()
     syntax = Syntax("Rd,K")
+    
+    def validate(self, values):
+    
+        if not 16 <= values["d"] <= 31:
+            raise ValidationError, "Invalid register (must be 16 <= Rd <= 31) in LDI: %i" % values["d"]
+        elif not 0 <= values["K"] <= 255:
+            raise ValidationError, "Invalid constant (must be 0 <= K <= 255) in LDI: %i" % values["K"]
 
 class LDS(Instruction):