Exemplo n.º 1
0
    def new_instance(self, instance_class):
        # Allocate a new instance and set its class to be the given class
        result = Object(self._nilObject, instance_class.get_number_of_instance_fields())
        result.set_class(instance_class)
 
        # Return the freshly allocated instance
        return result
Exemplo n.º 2
0
    def setUp(self):
        self.symbol = Symbol(Object(None), "test")
        unary_signature_strings = [
            "size", "addTwo", "use", "call",
            "parse", "hash", "notify", "setUp",
            "weight", "isOk", "isNotOk", "create"
        ]
        self.unary_signature_symbols = [Symbol(Object(None),string) for string in unary_signature_strings]

        binary_signature_chars = [
            "~", "&", "|", "*", "/",
            "@", "+", "-", "=", ">",
            "<", ",", "%", "\\"
        ]
        self.binary_signature_symbols = [Symbol(Object(None),char) for char in binary_signature_chars]

        keyword2_signature_strings = [
            "at:put:", "remove:from:", "add:withKey:",
            "choose:from:", "add:from:", "choose:and:"
        ]
        self.keyword2_signature_symbols = [Symbol(Object(None),string) for string in keyword2_signature_strings]

        keyword3_signature_strings = [
            "at:put:and:", "choose:divide:andAddTo:",
            "add:to:andNotify:", "parse:addTo:export:"
        ]
        self.keyword3_signature_symbols = [Symbol(Object(None),string) for string in keyword3_signature_strings]
Exemplo n.º 3
0
 def __init__(self, universe, number_of_fields=-1):
     Object.__init__(self, universe.nilObject, number_of_fields)
     self._super_class = universe.nilObject
     self._name        = None
     self._instance_fields = None
     self._instance_invokables = None
     self._invokables_table = {}
     self._universe = universe
Exemplo n.º 4
0
    def new_instance(self, instance_class):
        # Allocate a new instance and set its class to be the given class
        result = Object(self._nilObject,
                        instance_class.get_number_of_instance_fields())
        result.set_class(instance_class)

        # Return the freshly allocated instance
        return result
Exemplo n.º 5
0
 def setUp(self):
     # Universe definition
     self.universe = Universe()
     # Array definition, 5 strings "bar"
     self.array = Array(Object(None), 5)
     for i in range(4):
         self.array.set_indexable_field(i, "bar")
     # Extended array definition, 5 strings "bar" followed by a string "foo"
     self.extended_array = Array(Object(None), 6)
     for i in range(4):
         self.extended_array.set_indexable_field(i, "bar")
     self.extended_array.set_indexable_field(5, "foo")
Exemplo n.º 6
0
 def __init__(self, universe, number_of_fields=-1, obj_class=None):
     Object.__init__(self, obj_class, number_of_fields)
     self._super_class = nilObject
     self._name = None
     self._instance_fields = None
     self._instance_invokables = None
     self._invokables_table = {}
     self._universe = universe
     if number_of_fields >= 0:
         self._layout_for_instances = ObjectLayout(number_of_fields, self)
     else:
         self._layout_for_instances = None
Exemplo n.º 7
0
    def __init__(self, signature_string, universe, invoke, is_empty=False):
        Object.__init__(self, universe.nilObject)
        
        # Set the class of this primitive to be the universal primitive class
        self.set_class(universe.primitiveClass)

        # Set the signature of this primitive
        self._set_signature(universe.symbol_for(signature_string))
        
        self.invoke = types.MethodType(invoke, self)
        if is_empty:
            self.is_empty = is_empty
Exemplo n.º 8
0
 def __init__(self, universe, number_of_fields = -1, obj_class = None):
     Object.__init__(self, obj_class, number_of_fields)
     self._super_class = nilObject
     self._name        = None
     self._instance_fields = None
     self._instance_invokables = None
     self._invokables_table = {}
     self._universe = universe
     if number_of_fields >= 0:
         self._layout_for_instances = ObjectLayout(number_of_fields, self)
     else:
         self._layout_for_instances = None
Exemplo n.º 9
0
    def __init__(self, signature_string, universe, invoke, is_empty=False):
        Object.__init__(self, universe.nilObject)

        # Set the class of this primitive to be the universal primitive class
        self.set_class(universe.primitiveClass)

        # Set the signature of this primitive
        self._set_signature(universe.symbol_for(signature_string))

        self.invoke = types.MethodType(invoke, self)
        if is_empty:
            self.is_empty = is_empty
Exemplo n.º 10
0
class ObjectTestCase(unittest.TestCase):
    def setUp(self):
        self.universe = Universe
        self.object_integer = Object(None)
        self.integer_class = Class(self.universe)
        self.integer_class.set_name(Symbol(Object(None), "Integer"))
        self.object_integer._class = self.integer_class

    def test_get_class(self):
        integer_class = Class(self.universe)
        integer_class.set_name(Symbol(Object(None), "Integer"))
        self.assertEqual(integer_class, self.object_integer.get_class())

    def test_set_class(self):
        self.object_integer.set_class(Double)

    def test_get_field_name(self):
        pass

    def test_get_field_index(self):
        pass

    def test_get_number_of_fields(self):
        pass

    def test_get_default_number_of_fields(self):
        self.assertEqual(self.object_integer.NUMBER_OF_OBJECT_FIELDS,
                         self.object_integer._get_default_number_of_fields())

    def test_get_field(self):
        pass

    def test_set_field(self):
        pass

    def test_send(self):
        pass

    def test_send_does_not_understand(self):
        pass

    def test_send_unknown_global(self):
        pass

    def send_escaped_block(self):
        pass

    def test_str(self):
        self.assertEqual("a Integer", str(self.object_integer))
Exemplo n.º 11
0
 def test_copy_indexable_fields_to(self):
     # Populate a destination array with erroneous data to ensure it is overwritten
     destination = Array(Object(None), 5)
     for i in range(4):
         destination.set_indexable_field(i, "foo")
     self.array._copy_indexable_fields_to(destination)
     self.assertEqual(self.array, destination)
Exemplo n.º 12
0
 def new_instance(self, instance_class):
     num_fields = instance_class.get_number_of_instance_fields()
     if num_fields == 0:
         return ObjectWithoutFields(instance_class)
     else:
         return Object(instance_class, num_fields)
Exemplo n.º 13
0
    def _initialize_object_system(self):
        # Allocate the nil object
        self._nilObject = Object(None)

        # Allocate the Metaclass classes
        self._metaclassClass = self.new_metaclass_class()

        # Allocate the rest of the system classes
        self._objectClass     = self.new_system_class()
        self._nilClass        = self.new_system_class()
        self._classClass      = self.new_system_class()
        self._arrayClass      = self.new_system_class()
        self._symbolClass     = self.new_system_class()
        self._methodClass     = self.new_system_class()
        self._integerClass    = self.new_system_class()
        self._bigintegerClass = self.new_system_class()
        self._frameClass      = self.new_system_class()
        self._primitiveClass  = self.new_system_class()
        self._stringClass     = self.new_system_class()
        self._doubleClass     = self.new_system_class()

        # Setup the class reference for the nil object
        self._nilObject.set_class(self._nilClass)

        # Initialize the system classes
        self._initialize_system_class(self._objectClass,                  None, "Object")
        self._initialize_system_class(self._classClass,      self._objectClass, "Class")
        self._initialize_system_class(self._metaclassClass,   self._classClass, "Metaclass")
        self._initialize_system_class(self._nilClass,        self._objectClass, "Nil")
        self._initialize_system_class(self._arrayClass,      self._objectClass, "Array")
        self._initialize_system_class(self._methodClass,      self._arrayClass, "Method")
        self._initialize_system_class(self._symbolClass,     self._objectClass, "Symbol")
        self._initialize_system_class(self._integerClass,    self._objectClass, "Integer")
        self._initialize_system_class(self._bigintegerClass, self._objectClass, "BigInteger")
        self._initialize_system_class(self._frameClass,       self._arrayClass, "Frame")
        self._initialize_system_class(self._primitiveClass,  self._objectClass, "Primitive")
        self._initialize_system_class(self._stringClass,     self._objectClass, "String")
        self._initialize_system_class(self._doubleClass,     self._objectClass, "Double")

        # Load methods and fields into the system classes
        self._load_system_class(self._objectClass)
        self._load_system_class(self._classClass)
        self._load_system_class(self._metaclassClass)
        self._load_system_class(self._nilClass)
        self._load_system_class(self._arrayClass)
        self._load_system_class(self._methodClass)
        self._load_system_class(self._symbolClass)
        self._load_system_class(self._integerClass)
        self._load_system_class(self._bigintegerClass)
        self._load_system_class(self._frameClass)
        self._load_system_class(self._primitiveClass)
        self._load_system_class(self._stringClass)
        self._load_system_class(self._doubleClass)

        # Load the generic block class
        self._blockClass = self.load_class(self.symbol_for("Block"))

        # Setup the true and false objects
        self._trueObject  = self.new_instance(self.load_class(self.symbol_for("True")))
        self._falseObject = self.new_instance(self.load_class(self.symbol_for("False")))

        # Load the system class and create an instance of it
        self._systemClass = self.load_class(self.symbol_for("System"))
        system_object = self.new_instance(self._systemClass)

        # Put special objects and classes into the dictionary of globals
        self.set_global(self.symbol_for("nil"),    self._nilObject)
        self.set_global(self.symbol_for("true"),   self._trueObject)
        self.set_global(self.symbol_for("false"),  self._falseObject)
        self.set_global(self.symbol_for("system"), system_object)
        self.set_global(self.symbol_for("System"), self._systemClass)
        self.set_global(self.symbol_for("Block"),  self._blockClass)
        return system_object
Exemplo n.º 14
0
class Universe(object):
    def __init__(self, avoid_exit=False):
        self._interpreter = Interpreter(self)
        self._symbol_table = SymbolTable()

        self._globals = {}

        self._nilObject = None
        self._trueObject = None
        self._falseObject = None
        self._objectClass = None
        self._classClass = None
        self._metaclassClass = None

        self._nilClass = None
        self._integerClass = None
        self._bigintegerClass = None
        self._arrayClass = None
        self._methodClass = None
        self._symbolClass = None
        self._frameClass = None
        self._primitiveClass = None
        self._systemClass = None
        self._blockClass = None
        self._stringClass = None
        self._doubleClass = None

        self._last_exit_code = 0
        self._avoid_exit = avoid_exit
        self._classpath = None
        self._dump_bytecodes = False

    @property
    def nilObject(self):
        return self._nilObject

    @property
    def trueObject(self):
        return self._trueObject

    @property
    def falseObject(self):
        return self._falseObject

    @property
    def objectClass(self):
        return self._objectClass

    @property
    def classClass(self):
        return self._classClass

    @property
    def nilClass(self):
        return self._nilClass

    @property
    def integerClass(self):
        return self._integerClass

    @property
    def bigintegerClass(self):
        return self._bigintegerClass

    @property
    def arrayClass(self):
        return self._arrayClass

    @property
    def methodClass(self):
        return self._methodClass

    @property
    def symbolClass(self):
        return self._symbolClass

    @property
    def frameClass(self):
        return self._frameClass

    @property
    def systemClass(self):
        return self._systemClass

    @property
    def blockClass(self):
        return self._blockClass

    @property
    def stringClass(self):
        return self._stringClass

    @property
    def doubleClass(self):
        return self._doubleClass

    @property
    def primitiveClass(self):
        return self._primitiveClass

    @property
    def metaclassClass(self):
        return self._metaclassClass

    def exit(self, error_code):
        if self._avoid_exit:
            self._last_exit_code = error_code
        else:
            sys.exit(error_code)

    def last_exit_code(self):
        return self._last_exit_code

    def get_interpreter(self):
        return self._interpreter

    def execute_method(self, class_name, selector):
        self._initialize_object_system()

        clazz = self.load_class(self.symbol_for(class_name))

        # Lookup the invokable on class
        invokable = clazz.get_class().lookup_invokable(
            self.symbol_for(selector))

        bootstrap_method = self._create_bootstrap_method()
        bootstrap_frame = self._create_bootstrap_frame(bootstrap_method, clazz)

        return self.start(bootstrap_frame, invokable)

    def _create_bootstrap_method(self):
        # Create a fake bootstrap method to simplify later frame traversal
        bootstrap_method = self.new_method(self.symbol_for("bootstrap"), 1, 0,
                                           self.new_integer(0),
                                           self.new_integer(2))
        bootstrap_method.set_bytecode(0, Bytecodes.halt)
        bootstrap_method.set_holder(self._systemClass)
        return bootstrap_method

    def _create_bootstrap_frame(self,
                                bootstrap_method,
                                receiver,
                                arguments=None):
        # Create a fake bootstrap frame with the system object on the stack
        bootstrap_frame = self._interpreter.push_new_frame(
            bootstrap_method, self._nilObject)
        bootstrap_frame.push(receiver)

        if arguments:
            bootstrap_frame.push(arguments)
        return bootstrap_frame

    def interpret(self, arguments):
        # Check for command line switches
        arguments = self.handle_arguments(arguments)

        # Initialize the known universe
        system_object = self._initialize_object_system()
        bootstrap_method = self._create_bootstrap_method()

        # Start the shell if no filename is given
        if len(arguments) == 0:
            shell = Shell(self, self._interpreter)
            shell.set_bootstrap_method(bootstrap_method)
            shell.start()
            return
        else:
            # Convert the arguments into an array
            arguments_array = self.new_array_with_strings(arguments)
            bootstrap_frame = self._create_bootstrap_frame(
                bootstrap_method, system_object, arguments_array)
            # Lookup the initialize invokable on the system class
            initialize = self._systemClass.lookup_invokable(
                self.symbol_for("initialize:"))

            self.start(bootstrap_frame, initialize)

    def start(self, bootstrap_frame, invokable):
        # Invoke the initialize invokable
        invokable.invoke(bootstrap_frame, self._interpreter)

        # Start the interpreter
        return self._interpreter.start()

    def handle_arguments(self, arguments):
        got_classpath = False
        remaining_args = []

        i = 0
        while i < len(arguments):
            if arguments[i] == "-cp":
                if i + 1 >= len(arguments):
                    self._print_usage_and_exit()
                self.setup_classpath(arguments[i + 1])
                i += 1  # skip class path
                got_classpath = True
            elif arguments[i] == "-d":
                self._dump_bytecodes = True
            elif arguments[i] in ["-h", "--help", "-?"]:
                self._print_usage_and_exit()
            else:
                remaining_args.append(arguments[i])
            i += 1

        if not got_classpath:
            # Get the default class path of the appropriate size
            self._classpath = self._setup_default_classpath()

        # check remaining args for class paths, and strip file extension
        i = 0
        while i < len(remaining_args):
            split = self._get_path_class_ext(remaining_args[i])

            if split[0] != "":  # there was a path
                self._classpath.insert(0, split[0])

            remaining_args[i] = split[1]
            i += 1

        return remaining_args

    def setup_classpath(self, cp):
        self._classpath = cp.split(os.pathsep)

    def _setup_default_classpath(self):
        return ['.']

    # take argument of the form "../foo/Test.som" and return
    # "../foo", "Test", "som"
    def _get_path_class_ext(self, path):
        (path, file_name) = os.path.split(path)
        (file_name, ext) = os.path.splitext(file_name)
        return (path, file_name, ext[1:])

    def _print_usage_and_exit(self):
        # Print the usage
        self.std_println(
            "Usage: som [-options] [args...]                          ")
        self.std_println(
            "                                                         ")
        self.std_println(
            "where options include:                                   ")
        self.std_println("    -cp <directories separated by " + os.pathsep +
                         ">")
        self.std_println(
            "                  set search path for application classes")
        self.std_println("    -d            enable disassembling")
        self.std_println("    -h  print this help")

        # Exit
        self.exit(0)

    def _initialize_object_system(self):
        # Allocate the nil object
        self._nilObject = Object(None)

        # Allocate the Metaclass classes
        self._metaclassClass = self.new_metaclass_class()

        # Allocate the rest of the system classes
        self._objectClass = self.new_system_class()
        self._nilClass = self.new_system_class()
        self._classClass = self.new_system_class()
        self._arrayClass = self.new_system_class()
        self._symbolClass = self.new_system_class()
        self._methodClass = self.new_system_class()
        self._integerClass = self.new_system_class()
        self._bigintegerClass = self.new_system_class()
        self._frameClass = self.new_system_class()
        self._primitiveClass = self.new_system_class()
        self._stringClass = self.new_system_class()
        self._doubleClass = self.new_system_class()

        # Setup the class reference for the nil object
        self._nilObject.set_class(self._nilClass)

        # Initialize the system classes
        self._initialize_system_class(self._objectClass, None, "Object")
        self._initialize_system_class(self._classClass, self._objectClass,
                                      "Class")
        self._initialize_system_class(self._metaclassClass, self._classClass,
                                      "Metaclass")
        self._initialize_system_class(self._nilClass, self._objectClass, "Nil")
        self._initialize_system_class(self._arrayClass, self._objectClass,
                                      "Array")
        self._initialize_system_class(self._methodClass, self._arrayClass,
                                      "Method")
        self._initialize_system_class(self._symbolClass, self._objectClass,
                                      "Symbol")
        self._initialize_system_class(self._integerClass, self._objectClass,
                                      "Integer")
        self._initialize_system_class(self._bigintegerClass, self._objectClass,
                                      "BigInteger")
        self._initialize_system_class(self._frameClass, self._arrayClass,
                                      "Frame")
        self._initialize_system_class(self._primitiveClass, self._objectClass,
                                      "Primitive")
        self._initialize_system_class(self._stringClass, self._objectClass,
                                      "String")
        self._initialize_system_class(self._doubleClass, self._objectClass,
                                      "Double")

        # Load methods and fields into the system classes
        self._load_system_class(self._objectClass)
        self._load_system_class(self._classClass)
        self._load_system_class(self._metaclassClass)
        self._load_system_class(self._nilClass)
        self._load_system_class(self._arrayClass)
        self._load_system_class(self._methodClass)
        self._load_system_class(self._symbolClass)
        self._load_system_class(self._integerClass)
        self._load_system_class(self._bigintegerClass)
        self._load_system_class(self._frameClass)
        self._load_system_class(self._primitiveClass)
        self._load_system_class(self._stringClass)
        self._load_system_class(self._doubleClass)

        # Load the generic block class
        self._blockClass = self.load_class(self.symbol_for("Block"))

        # Setup the true and false objects
        trueClassName = self.symbol_for("True")
        trueClass = self.load_class(trueClassName)
        self._trueObject = self.new_instance(trueClass)

        falseClassName = self.symbol_for("False")
        falseClass = self.load_class(falseClassName)
        self._falseObject = self.new_instance(falseClass)

        # Load the system class and create an instance of it
        self._systemClass = self.load_class(self.symbol_for("System"))
        system_object = self.new_instance(self._systemClass)

        # Put special objects and classes into the dictionary of globals
        self.set_global(self.symbol_for("nil"), self._nilObject)
        self.set_global(self.symbol_for("true"), self._trueObject)
        self.set_global(self.symbol_for("false"), self._falseObject)
        self.set_global(self.symbol_for("system"), system_object)
        self.set_global(self.symbol_for("System"), self._systemClass)
        self.set_global(self.symbol_for("Block"), self._blockClass)

        self.set_global(self.symbol_for("Nil"), self.nilClass)

        self.set_global(trueClassName, trueClass)
        self.set_global(falseClassName, falseClass)

        return system_object

    def symbol_for(self, string):
        # Lookup the symbol in the symbol table
        result = self._symbol_table.lookup(string)
        if result:
            return result

        # Create a new symbol and return it
        result = self.new_symbol(string)
        return result

    def new_array_with_length(self, length):
        # Allocate a new array and set its class to be the array class
        result = Array(self._nilObject, length)
        result.set_class(self._arrayClass)

        # Return the freshly allocated array
        return result

    def new_array_from_list(self, values):
        # Allocate a new array with the same length as the list
        result = self.new_array_with_length(len(values))

        # Copy all elements from the list into the array
        for i in range(len(values)):
            result.set_indexable_field(i, values[i])

        # Return the allocated and initialized array
        return result

    def new_array_with_strings(self, strings):
        # Allocate a new array with the same length as the string array
        result = self.new_array_with_length(len(strings))

        # Copy all elements from the string array into the array
        for i in range(len(strings)):
            result.set_indexable_field(i, self.new_string(strings[i]))

        # Return the allocated and initialized array
        return result

    def new_block(self, method, context_frame, arguments):
        # Allocate a new block and set its class to be the block class
        result = Block(self._nilObject, method, context_frame)
        result.set_class(self._get_block_class(arguments))

        # Return the freshly allocated block
        return result

    def new_class(self, class_class):
        # Allocate a new class and set its class to be the given class class
        result = Class(self, class_class.get_number_of_instance_fields())
        result.set_class(class_class)

        # Return the freshly allocated class
        return result

    def new_frame(self, previous_frame, method, context):
        # Compute the maximum number of stack locations (including arguments,
        # locals and extra buffer to support doesNotUnderstand) and set the
        # number of indexable fields accordingly
        length = (method.get_number_of_arguments() +
                  method.get_number_of_locals().get_embedded_integer() +
                  method.get_maximum_number_of_stack_elements(
                  ).get_embedded_integer() + 2)

        # Allocate a new frame and set its class to be the frame class
        result = Frame(self._nilObject, length, method, context,
                       previous_frame)
        result.set_class(self._frameClass)

        # Reset the stack pointer and the bytecode index
        result.reset_stack_pointer()
        result.set_bytecode_index(0)

        # Return the freshly allocated frame
        return result

    def new_method(self, signature, num_bytecodes, num_literals, num_locals,
                   maximum_number_of_stack_elements):
        # Allocate a new method and set its class to be the method class
        result = Method(self._nilObject, num_literals, num_locals,
                        maximum_number_of_stack_elements, num_bytecodes,
                        signature)
        result.set_class(self._methodClass)

        # Return the freshly allocated method
        return result

    def new_instance(self, instance_class):
        # Allocate a new instance and set its class to be the given class
        result = Object(self._nilObject,
                        instance_class.get_number_of_instance_fields())
        result.set_class(instance_class)

        # Return the freshly allocated instance
        return result

    def new_integer(self, value):
        # Allocate a new integer and set its class to be the integer class
        result = Integer(self._nilObject, value)
        result.set_class(self._integerClass)

        # Return the freshly allocated integer
        return result

    def new_biginteger(self, value):
        # Allocate a new integer and set its class to be the integer class
        result = BigInteger(self._nilObject, value)
        result.set_class(self._bigintegerClass)

        # Return the freshly allocated integer
        return result

    def new_double(self, value):
        # Allocate a new integer and set its class to be the double class
        result = Double(self._nilObject, value)
        result.set_class(self._doubleClass)

        # Return the freshly allocated double
        return result

    def new_metaclass_class(self):
        # Allocate the metaclass classes
        result = Class(self)
        result.set_class(Class(self))

        # Setup the metaclass hierarchy
        result.get_class().set_class(result)

        # Return the freshly allocated metaclass class
        return result

    def new_string(self, embedded_string):
        # Allocate a new string and set its class to be the string class
        result = String(self._nilObject, embedded_string)
        result.set_class(self._stringClass)

        # Return the freshly allocated string
        return result

    def new_symbol(self, string):
        # Allocate a new symbol and set its class to be the symbol class
        result = Symbol(self._nilObject, string)
        result.set_class(self._symbolClass)

        # Insert the new symbol into the symbol table
        self._symbol_table.insert(result)

        # Return the freshly allocated symbol
        return result

    def new_system_class(self):
        # Allocate the new system class
        system_class = Class(self)

        # Setup the metaclass hierarchy
        system_class.set_class(Class(self))
        system_class.get_class().set_class(self._metaclassClass)

        # Return the freshly allocated system class
        return system_class

    def _initialize_system_class(self, system_class, super_class, name):
        # Initialize the superclass hierarchy
        if super_class:
            system_class.set_super_class(super_class)
            system_class.get_class().set_super_class(super_class.get_class())
        else:
            system_class.get_class().set_super_class(self._classClass)

        # Initialize the array of instance fields
        system_class.set_instance_fields(self.new_array_with_length(0))
        system_class.get_class().set_instance_fields(
            self.new_array_with_length(0))

        # Initialize the array of instance invokables
        system_class.set_instance_invokables(self.new_array_with_length(0))
        system_class.get_class().set_instance_invokables(
            self.new_array_with_length(0))

        # Initialize the name of the system class
        system_class.set_name(self.symbol_for(name))
        system_class.get_class().set_name(self.symbol_for(name + " class"))

        # Insert the system class into the dictionary of globals
        self.set_global(system_class.get_name(), system_class)

    def get_global(self, name):
        # Return the global with the given name if it's in the dictionary of globals
        if self.has_global(name):
            return self._globals[name]

        # Global not found
        return None

    def set_global(self, name, value):
        # Insert the given value into the dictionary of globals
        self._globals[name] = value

    def has_global(self, name):
        # Returns if the universe has a value for the global of the given name
        return name in self._globals

    def _get_block_class(self, number_of_arguments=None):
        if not number_of_arguments:
            # Get the generic block class
            return self._blockClass

        # Compute the name of the block class with the given number of
        # arguments
        name = self.symbol_for("Block" + str(number_of_arguments))

        # Lookup the specific block class in the dictionary of globals and
        # return it
        if self.has_global(name):
            return self.get_global(name)

        # Get the block class for blocks with the given number of arguments
        result = self._load_class(name, None)

        # Add the appropriate value primitive to the block class
        result.add_instance_primitive(
            Block.get_evaluation_primitive(number_of_arguments, self))

        # Insert the block class into the dictionary of globals
        self.set_global(name, result)

        # Return the loaded block class
        return result

    def load_class(self, name):
        # Check if the requested class is already in the dictionary of globals
        if self.has_global(name):
            return self.get_global(name)

        # Load the class
        result = self._load_class(name, None)

        # Load primitives (if necessary) and return the resulting class
        if result and result.has_primitives():
            result.load_primitives()

        return result

    def _load_system_class(self, system_class):
        # Load the system class
        result = self._load_class(system_class.get_name(), system_class)

        if not result:
            error_println(
                system_class.get_name().get_string() +
                " class could not be loaded. It is likely that the " +
                " class path has not been initialized properly. " +
                "Please make sure that the '-cp' parameter is given on the command-line."
            )
            self.exit(200)

        # Load primitives if necessary
        if result.has_primitives():
            result.load_primitives()

    def _load_class(self, name, system_class):
        # Try loading the class from all different paths
        for cpEntry in self._classpath:
            try:
                # Load the class from a file and return the loaded class
                result = sourcecode_compiler.compile_class_from_file(
                    cpEntry, name.get_string(), system_class, self)
                if self._dump_bytecodes:
                    from som.compiler.disassembler import Disassembler
                    Disassembler.dump(result.get_class())
                    Disassembler.dump(result)

                return result
            except IOError:
                # Continue trying different paths
                pass

        # The class could not be found.
        return None

    def load_shell_class(self, stmt):
        # Load the class from a stream and return the loaded class
        result = sourcecode_compiler.compile_class_from_string(
            stmt, None, self)
        if self._dump_bytecodes:
            from som.compiler.disassembler import Disassembler
            Disassembler.dump(result)
        return result

    @classmethod
    def error_print(cls, msg):
        print(msg, file=sys.stderr, end="")

    @classmethod
    def error_println(cls, msg=""):
        print(msg, file=sys.stderr)

    @classmethod
    def std_print(cls, msg):
        print(msg, end="")

    @classmethod
    def std_println(cls, msg=""):
        print(msg)
Exemplo n.º 15
0
 def new_instance(self, instance_class):
     return Object(self.nilObject, instance_class.get_number_of_instance_fields(), instance_class)
Exemplo n.º 16
0
 def setUp(self):
     self.string = String(Object(None), "test")
Exemplo n.º 17
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._embedded_biginteger = value
Exemplo n.º 18
0
    def __init__(self, nilObject, number_of_indexable_fields):
        Object.__init__(self, nilObject)

        # Private array of indexable fields
        self._indexable_fields = [nilObject] * number_of_indexable_fields
Exemplo n.º 19
0
 def setUp(self):
     self.table = SymbolTable()
     self.symbol = Symbol(nilObject=Object(None), value="foo")
Exemplo n.º 20
0
 def setUp(self):
     self.big_integer = BigInteger(Object(None), 30000000000)
     self.integer = Integer(Object(None), 3)
Exemplo n.º 21
0
 def setUp(self):
     self.method = 0
     self.context = 0
     self.block = Block(Object(None), )
Exemplo n.º 22
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._string = value
     self._number_of_signature_arguments = self._determine_number_of_signature_arguments(
     )  # updated later
Exemplo n.º 23
0
 def setUp(self):
     self.universe = Universe
     self.object_integer = Object(None)
     self.integer_class = Class(self.universe)
     self.integer_class.set_name(Symbol(Object(None), "Integer"))
     self.object_integer._class = self.integer_class
Exemplo n.º 24
0
 def test_get_class(self):
     integer_class = Class(self.universe)
     integer_class.set_name(Symbol(Object(None), "Integer"))
     self.assertEqual(integer_class, self.object_integer.get_class())
Exemplo n.º 25
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._string = value
Exemplo n.º 26
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._string = value
Exemplo n.º 27
0
 def setUp(self):
     self.double = Double(Object(None), 5.5)
Exemplo n.º 28
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._embedded_double = value
Exemplo n.º 29
0
 def __init__(self, universe, number_of_fields = -1):
     Object.__init__(self, universe.nilObject, number_of_fields)
     self._invokables_table = {}
     self._universe = universe
Exemplo n.º 30
0
 def __init__(self, universe, number_of_fields=-1):
     Object.__init__(self, universe.nilObject, number_of_fields)
     self._invokables_table = {}
     self._universe = universe
Exemplo n.º 31
0
 def __init__(self, nilObject, number_of_indexable_fields):
     Object.__init__(self, nilObject)
     
     # Private array of indexable fields
     self._indexable_fields = [nilObject] * number_of_indexable_fields
Exemplo n.º 32
0
class Universe(object):
    
    def __init__(self, avoid_exit = False):
        self._interpreter    = Interpreter(self)
        self._symbol_table   = SymbolTable()
        
        self._globals        = {}
        
        self._nilObject      = None
        self._trueObject     = None
        self._falseObject    = None
        self._objectClass    = None
        self._classClass     = None
        self._metaclassClass = None
        
        self._nilClass       = None
        self._integerClass   = None
        self._bigintegerClass= None
        self._arrayClass     = None
        self._methodClass    = None
        self._symbolClass    = None
        self._frameClass     = None
        self._primitiveClass = None
        self._systemClass    = None
        self._blockClass     = None
        self._stringClass    = None
        self._doubleClass    = None
        
        self._last_exit_code = 0
        self._avoid_exit     = avoid_exit
        self._classpath      = None
        self._dump_bytecodes = False        
    
    @property
    def nilObject(self):
        return self._nilObject
    
    @property
    def trueObject(self):
        return self._trueObject
    
    @property
    def falseObject(self):
        return self._falseObject
    
    @property
    def objectClass(self):
        return self._objectClass
    
    @property
    def classClass(self):
        return self._classClass
    
    @property
    def nilClass(self):
        return self._nilClass
    
    @property
    def integerClass(self):
        return self._integerClass
    
    @property
    def bigintegerClass(self):
        return self._bigintegerClass

    @property
    def arrayClass(self):
        return self._arrayClass
    
    @property
    def methodClass(self):
        return self._methodClass
    
    @property
    def symbolClass(self):
        return self._symbolClass
    
    @property
    def frameClass(self):
        return self._frameClass
    
    @property
    def systemClass(self):
        return self._systemClass
    
    @property
    def blockClass(self):
        return self._blockClass
    
    @property
    def stringClass(self):
        return self._stringClass
    
    @property
    def doubleClass(self):
        return self._doubleClass
    
    @property
    def primitiveClass(self):
        return self._primitiveClass
    
    @property
    def metaclassClass(self):
        return self._metaclassClass
    
    def exit(self, error_code):
        if self._avoid_exit:
            self._last_exit_code = error_code
        else:
            sys.exit(error_code)
    
    def last_exit_code(self):
        return self._last_exit_code
    
    def get_interpreter(self):
        return self._interpreter
    
    def execute_method(self, class_name, selector):
        self._initialize_object_system()

        clazz = self.load_class(self.symbol_for(class_name))

        # Lookup the invokable on class
        invokable = clazz.get_class().lookup_invokable(self.symbol_for(selector))

        bootstrap_method = self._create_bootstrap_method()
        bootstrap_frame  = self._create_bootstrap_frame(bootstrap_method, clazz)
        
        return self.start(bootstrap_frame, invokable)
    
    def _create_bootstrap_method(self):
        # Create a fake bootstrap method to simplify later frame traversal
        bootstrap_method = self.new_method(self.symbol_for("bootstrap"), 1, 0,
                                           self.new_integer(0),
                                           self.new_integer(2))
        bootstrap_method.set_bytecode(0, Bytecodes.halt)
        bootstrap_method.set_holder(self._systemClass)
        return bootstrap_method
    
    def _create_bootstrap_frame(self, bootstrap_method, receiver, arguments = None):
        # Create a fake bootstrap frame with the system object on the stack
        bootstrap_frame = self._interpreter.push_new_frame(bootstrap_method, self._nilObject)
        bootstrap_frame.push(receiver)
        
        if arguments:
            bootstrap_frame.push(arguments)
        return bootstrap_frame
        
    
    def interpret(self, arguments):
        # Check for command line switches
        arguments = self.handle_arguments(arguments)

        # Initialize the known universe
        system_object = self._initialize_object_system()
        bootstrap_method = self._create_bootstrap_method()
        
        # Start the shell if no filename is given
        if len(arguments) == 0:
            shell = Shell(self, self._interpreter)
            shell.set_bootstrap_method(bootstrap_method)
            shell.start()
            return
        else:
            # Convert the arguments into an array
            arguments_array = self.new_array_with_strings(arguments)
            bootstrap_frame = self._create_bootstrap_frame(bootstrap_method, system_object, arguments_array)
            # Lookup the initialize invokable on the system class
            initialize = self._systemClass.lookup_invokable(self.symbol_for("initialize:"))

            self.start(bootstrap_frame, initialize)
    
    def start(self, bootstrap_frame, invokable):
        # Invoke the initialize invokable
        invokable.invoke(bootstrap_frame, self._interpreter)

        # Start the interpreter
        return self._interpreter.start()
    
    def handle_arguments(self, arguments):
        got_classpath  = False
        remaining_args = []

        i = 0
        while i < len(arguments):
            if arguments[i] == "-cp":
                if i + 1 >= len(arguments):
                    self._print_usage_and_exit()
                self.setup_classpath(arguments[i + 1])
                i += 1    # skip class path
                got_classpath = True
            elif arguments[i] == "-d":
                self._dump_bytecodes = True
            elif arguments[i] in ["-h", "--help", "-?"]:
                self._print_usage_and_exit()
            else:
                remaining_args.append(arguments[i])
            i += 1
    
        if not got_classpath:
            # Get the default class path of the appropriate size
            self._classpath = self._setup_default_classpath()

        # check remaining args for class paths, and strip file extension
        i = 0
        while i < len(remaining_args):
            split = self._get_path_class_ext(remaining_args[i])

            if split[0] != "":  # there was a path
                self._classpath.insert(0, split[0])
        
            remaining_args[i] = split[1]
            i += 1
        
        return remaining_args
    
    def setup_classpath(self, cp):
        self._classpath = cp.split(os.pathsep)
    
    def _setup_default_classpath(self):
        return ['.']
    
    # take argument of the form "../foo/Test.som" and return
    # "../foo", "Test", "som"
    def _get_path_class_ext(self, path):
        (path, file_name) = os.path.split(path)
        (file_name, ext)  = os.path.splitext(file_name)
        return (path, file_name, ext[1:])
    
    def _print_usage_and_exit(self):
        # Print the usage
        self.std_println("Usage: som [-options] [args...]                          ")
        self.std_println("                                                         ")
        self.std_println("where options include:                                   ")
        self.std_println("    -cp <directories separated by " + os.pathsep     + ">")
        self.std_println("                  set search path for application classes")
        self.std_println("    -d            enable disassembling")
        self.std_println("    -h  print this help")

        # Exit
        self.exit(0)

    def _initialize_object_system(self):
        # Allocate the nil object
        self._nilObject = Object(None)

        # Allocate the Metaclass classes
        self._metaclassClass = self.new_metaclass_class()

        # Allocate the rest of the system classes
        self._objectClass     = self.new_system_class()
        self._nilClass        = self.new_system_class()
        self._classClass      = self.new_system_class()
        self._arrayClass      = self.new_system_class()
        self._symbolClass     = self.new_system_class()
        self._methodClass     = self.new_system_class()
        self._integerClass    = self.new_system_class()
        self._bigintegerClass = self.new_system_class()
        self._frameClass      = self.new_system_class()
        self._primitiveClass  = self.new_system_class()
        self._stringClass     = self.new_system_class()
        self._doubleClass     = self.new_system_class()

        # Setup the class reference for the nil object
        self._nilObject.set_class(self._nilClass)

        # Initialize the system classes
        self._initialize_system_class(self._objectClass,                  None, "Object")
        self._initialize_system_class(self._classClass,      self._objectClass, "Class")
        self._initialize_system_class(self._metaclassClass,   self._classClass, "Metaclass")
        self._initialize_system_class(self._nilClass,        self._objectClass, "Nil")
        self._initialize_system_class(self._arrayClass,      self._objectClass, "Array")
        self._initialize_system_class(self._methodClass,      self._arrayClass, "Method")
        self._initialize_system_class(self._symbolClass,     self._objectClass, "Symbol")
        self._initialize_system_class(self._integerClass,    self._objectClass, "Integer")
        self._initialize_system_class(self._bigintegerClass, self._objectClass, "BigInteger")
        self._initialize_system_class(self._frameClass,       self._arrayClass, "Frame")
        self._initialize_system_class(self._primitiveClass,  self._objectClass, "Primitive")
        self._initialize_system_class(self._stringClass,     self._objectClass, "String")
        self._initialize_system_class(self._doubleClass,     self._objectClass, "Double")

        # Load methods and fields into the system classes
        self._load_system_class(self._objectClass)
        self._load_system_class(self._classClass)
        self._load_system_class(self._metaclassClass)
        self._load_system_class(self._nilClass)
        self._load_system_class(self._arrayClass)
        self._load_system_class(self._methodClass)
        self._load_system_class(self._symbolClass)
        self._load_system_class(self._integerClass)
        self._load_system_class(self._bigintegerClass)
        self._load_system_class(self._frameClass)
        self._load_system_class(self._primitiveClass)
        self._load_system_class(self._stringClass)
        self._load_system_class(self._doubleClass)

        # Load the generic block class
        self._blockClass = self.load_class(self.symbol_for("Block"))

        # Setup the true and false objects
        trueClassName    = self.symbol_for("True")
        trueClass        = self.load_class(trueClassName)
        self._trueObject = self.new_instance(trueClass)

        falseClassName    = self.symbol_for("False")
        falseClass        = self.load_class(falseClassName)
        self._falseObject = self.new_instance(falseClass)

        # Load the system class and create an instance of it
        self._systemClass = self.load_class(self.symbol_for("System"))
        system_object = self.new_instance(self._systemClass)

        # Put special objects and classes into the dictionary of globals
        self.set_global(self.symbol_for("nil"),    self._nilObject)
        self.set_global(self.symbol_for("true"),   self._trueObject)
        self.set_global(self.symbol_for("false"),  self._falseObject)
        self.set_global(self.symbol_for("system"), system_object)
        self.set_global(self.symbol_for("System"), self._systemClass)
        self.set_global(self.symbol_for("Block"),  self._blockClass)

        self.set_global(self.symbol_for("Nil"),    self.nilClass)
        
        self.set_global( trueClassName,  trueClass)
        self.set_global(falseClassName, falseClass)

        return system_object
    
    def symbol_for(self, string):
        # Lookup the symbol in the symbol table
        result = self._symbol_table.lookup(string)
        if result:
            return result
        
        # Create a new symbol and return it
        result = self.new_symbol(string)
        return result
    
    def new_array_with_length(self, length):
        # Allocate a new array and set its class to be the array class
        result = Array(self._nilObject, length)
        result.set_class(self._arrayClass)

        # Return the freshly allocated array
        return result
  
    def new_array_from_list(self, values):
        # Allocate a new array with the same length as the list
        result = self.new_array_with_length(len(values))

        # Copy all elements from the list into the array
        for i in range(len(values)):
            result.set_indexable_field(i, values[i])
    
        # Return the allocated and initialized array
        return result
  
    def new_array_with_strings(self, strings):
        # Allocate a new array with the same length as the string array
        result = self.new_array_with_length(len(strings))

        # Copy all elements from the string array into the array
        for i in range(len(strings)):
            result.set_indexable_field(i, self.new_string(strings[i]))
    
        # Return the allocated and initialized array
        return result
    
    def new_block(self, method, context_frame, arguments):
        # Allocate a new block and set its class to be the block class
        result = Block(self._nilObject, method, context_frame)
        result.set_class(self._get_block_class(arguments))

        # Return the freshly allocated block
        return result

    def new_class(self, class_class):
        # Allocate a new class and set its class to be the given class class
        result = Class(self, class_class.get_number_of_instance_fields())
        result.set_class(class_class)

        # Return the freshly allocated class
        return result

    def new_frame(self, previous_frame, method, context):
        # Compute the maximum number of stack locations (including arguments,
        # locals and extra buffer to support doesNotUnderstand) and set the
        # number of indexable fields accordingly
        length = (method.get_number_of_arguments() +
                  method.get_number_of_locals().get_embedded_integer() +
                  method.get_maximum_number_of_stack_elements().get_embedded_integer() + 2)

        # Allocate a new frame and set its class to be the frame class
        result = Frame(self._nilObject, length, method, context, previous_frame)
        result.set_class(self._frameClass)

        # Reset the stack pointer and the bytecode index
        result.reset_stack_pointer()
        result.set_bytecode_index(0)

        # Return the freshly allocated frame
        return result

    def new_method(self, signature, num_bytecodes, num_literals,
                   num_locals, maximum_number_of_stack_elements):
        # Allocate a new method and set its class to be the method class
        result = Method(self._nilObject,
                        num_literals,
                        num_locals,
                        maximum_number_of_stack_elements,
                        num_bytecodes,
                        signature)
        result.set_class(self._methodClass)

        # Return the freshly allocated method
        return result

    def new_instance(self, instance_class):
        # Allocate a new instance and set its class to be the given class
        result = Object(self._nilObject, instance_class.get_number_of_instance_fields())
        result.set_class(instance_class)
 
        # Return the freshly allocated instance
        return result

 
    def new_integer(self, value):
        # Allocate a new integer and set its class to be the integer class
        result = Integer(self._nilObject, value)
        result.set_class(self._integerClass)
     
        # Return the freshly allocated integer
        return result
 
    def new_biginteger(self, value):
        # Allocate a new integer and set its class to be the integer class
        result = BigInteger(self._nilObject, value)
        result.set_class(self._bigintegerClass)
 
        # Return the freshly allocated integer
        return result
 
 
    def new_double(self, value):
        # Allocate a new integer and set its class to be the double class
        result = Double(self._nilObject, value)
        result.set_class(self._doubleClass)
 
        # Return the freshly allocated double
        return result
    
    def new_metaclass_class(self):
        # Allocate the metaclass classes
        result = Class(self)
        result.set_class(Class(self))

        # Setup the metaclass hierarchy
        result.get_class().set_class(result)

        # Return the freshly allocated metaclass class
        return result

    def new_string(self, embedded_string):
        # Allocate a new string and set its class to be the string class
        result = String(self._nilObject, embedded_string)
        result.set_class(self._stringClass)

        # Return the freshly allocated string
        return result
    
    def new_symbol(self, string):
        # Allocate a new symbol and set its class to be the symbol class
        result = Symbol(self._nilObject, string)
        result.set_class(self._symbolClass)

        # Insert the new symbol into the symbol table
        self._symbol_table.insert(result)

        # Return the freshly allocated symbol
        return result
      
    def new_system_class(self):
        # Allocate the new system class
        system_class = Class(self)

        # Setup the metaclass hierarchy
        system_class.set_class(Class(self))
        system_class.get_class().set_class(self._metaclassClass)

        # Return the freshly allocated system class
        return system_class
    
    def _initialize_system_class(self, system_class, super_class, name):
        # Initialize the superclass hierarchy
        if super_class:
            system_class.set_super_class(super_class)
            system_class.get_class().set_super_class(super_class.get_class())
        else:
            system_class.get_class().set_super_class(self._classClass)
    

        # Initialize the array of instance fields
        system_class.set_instance_fields(self.new_array_with_length(0))
        system_class.get_class().set_instance_fields(self.new_array_with_length(0))

        # Initialize the array of instance invokables
        system_class.set_instance_invokables(self.new_array_with_length(0))
        system_class.get_class().set_instance_invokables(self.new_array_with_length(0))

        # Initialize the name of the system class
        system_class.set_name(self.symbol_for(name))
        system_class.get_class().set_name(self.symbol_for(name + " class"))

        # Insert the system class into the dictionary of globals
        self.set_global(system_class.get_name(), system_class)
    
    
    def get_global(self, name):
        # Return the global with the given name if it's in the dictionary of globals
        if self.has_global(name):
            return self._globals[name]

        # Global not found
        return None

    def set_global(self, name, value):
        # Insert the given value into the dictionary of globals
        self._globals[name] = value

    def has_global(self, name):
        # Returns if the universe has a value for the global of the given name
        return name in self._globals
    
    def _get_block_class(self, number_of_arguments = None):
        if not number_of_arguments:
            # Get the generic block class
            return self._blockClass
        
        # Compute the name of the block class with the given number of
        # arguments
        name = self.symbol_for("Block" + str(number_of_arguments))

        # Lookup the specific block class in the dictionary of globals and
        # return it
        if self.has_global(name):
            return self.get_global(name)

        # Get the block class for blocks with the given number of arguments
        result = self._load_class(name, None)

        # Add the appropriate value primitive to the block class
        result.add_instance_primitive(Block.get_evaluation_primitive(number_of_arguments, self))

        # Insert the block class into the dictionary of globals
        self.set_global(name, result)

        # Return the loaded block class
        return result

    def load_class(self, name):
        # Check if the requested class is already in the dictionary of globals
        if self.has_global(name):
            return self.get_global(name)

        # Load the class
        result = self._load_class(name, None)

        # Load primitives (if necessary) and return the resulting class
        if result and result.has_primitives():
            result.load_primitives()
    
        return result

    def _load_system_class(self, system_class):
        # Load the system class
        result = self._load_class(system_class.get_name(), system_class)

        if not result:
            error_println(system_class.get_name().get_string()
                   + " class could not be loaded. It is likely that the "
                   + " class path has not been initialized properly. "
                   + "Please make sure that the '-cp' parameter is given on the command-line.")
            self.exit(200)

        # Load primitives if necessary
        if result.has_primitives():
            result.load_primitives()

    def _load_class(self, name, system_class):
        # Try loading the class from all different paths
        for cpEntry in self._classpath:
            try:
                # Load the class from a file and return the loaded class
                result = sourcecode_compiler.compile_class_from_file(cpEntry, name.get_string(), system_class, self)
                if self._dump_bytecodes:
                    from som.compiler.disassembler import Disassembler
                    Disassembler.dump(result.get_class())
                    Disassembler.dump(result)

                return result
            except IOError:
                # Continue trying different paths
                pass

        # The class could not be found.
        return None
    
    def load_shell_class(self, stmt):
        # Load the class from a stream and return the loaded class
        result = sourcecode_compiler.compile_class_from_string(stmt, None, self)
        if self._dump_bytecodes:
            from som.compiler.disassembler import Disassembler
            Disassembler.dump(result)
        return result

    @classmethod
    def error_print(cls, msg):
        print(msg, file=sys.stderr, end="")

    @classmethod
    def error_println(cls, msg = ""):
        print(msg, file=sys.stderr)

    @classmethod
    def std_print(cls, msg):
        print(msg, end="")

    @classmethod
    def std_println(cls, msg=""):
        print(msg)
Exemplo n.º 33
0
 def __init__(self, nilObject, method, context):
     Object.__init__(self, nilObject)
     self._number_of_arguments = 0
     self._method = method
     self._context = context
Exemplo n.º 34
0
 def __init__(self, nilObject, method, context):
     Object.__init__(self, nilObject)
     self._number_of_arguments = 0
     self._method  = method
     self._context = context
Exemplo n.º 35
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._embedded_double = value
Exemplo n.º 36
0
    def _initialize_object_system(self):
        # Allocate the nil object
        self.nilObject = Object(None)

        # Allocate the Metaclass classes
        self.metaclassClass = self.new_metaclass_class()

        # Allocate the rest of the system classes
        self.objectClass     = self.new_system_class()
        self.nilClass        = self.new_system_class()
        self.classClass      = self.new_system_class()
        self.arrayClass      = self.new_system_class()
        self.symbolClass     = self.new_system_class()
        self.methodClass     = self.new_system_class()
        self.integerClass    = self.new_system_class()
        self.primitiveClass  = self.new_system_class()
        self.stringClass     = self.new_system_class()
        self.doubleClass     = self.new_system_class()

        # Setup the class reference for the nil object
        self.nilObject.set_class(self.nilClass)

        # Initialize the system classes
        self._initialize_system_class(self.objectClass,                 None, "Object")
        self._initialize_system_class(self.classClass,      self.objectClass, "Class")
        self._initialize_system_class(self.metaclassClass,   self.classClass, "Metaclass")
        self._initialize_system_class(self.nilClass,        self.objectClass, "Nil")
        self._initialize_system_class(self.arrayClass,      self.objectClass, "Array")
        self._initialize_system_class(self.methodClass,      self.arrayClass, "Method")
        self._initialize_system_class(self.symbolClass,     self.objectClass, "Symbol")
        self._initialize_system_class(self.integerClass,    self.objectClass, "Integer")
        self._initialize_system_class(self.primitiveClass,  self.objectClass, "Primitive")
        self._initialize_system_class(self.stringClass,     self.objectClass, "String")
        self._initialize_system_class(self.doubleClass,     self.objectClass, "Double")

        # Load methods and fields into the system classes
        self._load_system_class(self.objectClass)
        self._load_system_class(self.classClass)
        self._load_system_class(self.metaclassClass)
        self._load_system_class(self.nilClass)
        self._load_system_class(self.arrayClass)
        self._load_system_class(self.methodClass)
        self._load_system_class(self.symbolClass)
        self._load_system_class(self.integerClass)
        self._load_system_class(self.primitiveClass)
        self._load_system_class(self.stringClass)
        self._load_system_class(self.doubleClass)

        # Load the generic block class
        self.blockClass = self.load_class(self.symbol_for("Block"))

        # Setup the true and false objects
        trueClassName    = self.symbol_for("True")
        trueClass        = self.load_class(trueClassName)
        self.trueObject  = self.new_instance(trueClass)
        
        falseClassName   = self.symbol_for("False")
        falseClass       = self.load_class(falseClassName)
        self.falseObject = self.new_instance(falseClass)

        # Load the system class and create an instance of it
        self.systemClass = self.load_class(self.symbol_for("System"))
        system_object = self.new_instance(self.systemClass)

        # Put special objects and classes into the dictionary of globals
        self.set_global(self.symbol_for("nil"),    self.nilObject)
        self.set_global(self.symbol_for("true"),   self.trueObject)
        self.set_global(self.symbol_for("false"),  self.falseObject)
        self.set_global(self.symbol_for("system"), system_object)
        self.set_global(self.symbol_for("System"), self.systemClass)
        self.set_global(self.symbol_for("Block"),  self.blockClass)
        
        self.set_global(self.symbol_for("Nil"),    self.nilClass)
        
        self.set_global( trueClassName,  trueClass)
        self.set_global(falseClassName, falseClass)

        self.blockClasses = [self.blockClass] + \
                [self._make_block_class(i) for i in [1, 2, 3]]

        self._interpreter.initialize_known_quick_sends()

        return system_object
Exemplo n.º 37
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._embedded_integer = value
Exemplo n.º 38
0
class Universe(object):
    
    CURRENT = None
    
    _immutable_fields_ = [
            "nilObject",
            "trueObject",
            "falseObject",
            "objectClass",
            "classClass",
            "metaclassClass",
            "nilClass",
            "integerClass",
            "arrayClass",
            "methodClass",
            "symbolClass",
            "primitiveClass",
            "systemClass",
            "blockClass",
            "blockClasses[*]",
            "stringClass",
            "doubleClass",
            "_symbol_table",
            "_globals"]

    def __init__(self, avoid_exit = False):
        self._interpreter    = Interpreter(self)
        self._symbol_table   = {}
        self._globals        = {}

        self.nilObject      = None
        self.trueObject     = None
        self.falseObject    = None
        self.objectClass    = None
        self.classClass     = None
        self.metaclassClass = None
        
        self.nilClass       = None
        self.integerClass   = None
        self.arrayClass     = None
        self.methodClass    = None
        self.symbolClass    = None
        self.primitiveClass = None
        self.systemClass    = None
        self.blockClass     = None
        self.blockClasses   = None
        self.stringClass    = None
        self.doubleClass    = None

        self._last_exit_code = 0
        self._avoid_exit     = avoid_exit
        self._dump_bytecodes = False
        self.classpath       = None
        self.start_time      = time.time()  # a float of the time in seconds
        self.random          = Random(abs(int(time.clock() * time.time())))

        CURRENT = self

    def exit(self, error_code):
        if self._avoid_exit:
            self._last_exit_code = error_code
        else:
            raise Exit(error_code)
    
    def last_exit_code(self):
        return self._last_exit_code
    
    def get_interpreter(self):
        return self._interpreter
    
    def execute_method(self, class_name, selector):
        self._initialize_object_system()

        clazz = self.load_class(self.symbol_for(class_name))

        bootstrap_method = self._create_bootstrap_method()
        bootstrap_frame  = self._create_bootstrap_frame(bootstrap_method, clazz)
        
        # Lookup the invokable on class
        invokable = clazz.get_class(self).lookup_invokable(self.symbol_for(selector))
        
        invokable.invoke(bootstrap_frame, self._interpreter)
        return bootstrap_frame.pop()
    
    def _create_bootstrap_method(self):
        # Create a fake bootstrap method to simplify later frame traversal
        bootstrap_method = self.new_method(self.symbol_for("bootstrap"), 1, [],
                                           self.new_integer(0),
                                           self.new_integer(2))
        bootstrap_method.set_bytecode(0, Bytecodes.halt)
        bootstrap_method.set_holder(self.systemClass)
        return bootstrap_method
    
    def _create_bootstrap_frame(self, bootstrap_method, receiver, arguments = None):
        # Create a fake bootstrap frame with the system object on the stack
        bootstrap_frame = self._interpreter.new_frame(None, bootstrap_method, None)
        bootstrap_frame.push(receiver)
        
        if arguments:
            bootstrap_frame.push(arguments)
        return bootstrap_frame
        
    
    def interpret(self, arguments):
        # Check for command line switches
        arguments = self.handle_arguments(arguments)

        # Initialize the known universe
        system_object = self._initialize_object_system()
        bootstrap_method = self._create_bootstrap_method()
        
        # Start the shell if no filename is given
        if len(arguments) == 0:
            shell = Shell(self, self._interpreter)
            shell.set_bootstrap_method(bootstrap_method)
            shell.start()
            return
        else:
            # Convert the arguments into an array
            arguments_array = self.new_array_with_strings(arguments)
            bootstrap_frame = self._create_bootstrap_frame(bootstrap_method, system_object, arguments_array)
            # Lookup the initialize invokable on the system class
            initialize = self.systemClass.lookup_invokable(self.symbol_for("initialize:"))
            return initialize.invoke(bootstrap_frame, self._interpreter)
    
    def handle_arguments(self, arguments):
        got_classpath  = False
        remaining_args = []

        i = 0
        while i < len(arguments):
            if arguments[i] == "-cp":
                if i + 1 >= len(arguments):
                    self._print_usage_and_exit()
                self.setup_classpath(arguments[i + 1])
                i += 1    # skip class path
                got_classpath = True
            elif arguments[i] == "-d":
                self._dump_bytecodes = True
            elif arguments[i] in ["-h", "--help", "-?"]:
                self._print_usage_and_exit()
            else:
                remaining_args.append(arguments[i])
            i += 1
    
        if not got_classpath:
            # Get the default class path of the appropriate size
            self.classpath = self._default_classpath()

        # check remaining args for class paths, and strip file extension
        i = 0
        while i < len(remaining_args):
            split = self._get_path_class_ext(remaining_args[i])

            if split[0] != "":  # there was a path
                self.classpath.insert(0, split[0])
        
            remaining_args[i] = split[1]
            i += 1
        
        return remaining_args
    
    def setup_classpath(self, cp):
        self.classpath = cp.split(os.pathsep)

    @staticmethod
    def _default_classpath():
        return ['.']
    
    # take argument of the form "../foo/Test.som" and return
    # "../foo", "Test", "som"
    @staticmethod
    def _get_path_class_ext(path):
        return path_split(path)
    
    def _print_usage_and_exit(self):
        # Print the usage
        std_println("Usage: som [-options] [args...]                          ")
        std_println("                                                         ")
        std_println("where options include:                                   ")
        std_println("    -cp <directories separated by " + os.pathsep     + ">")
        std_println("        set search path for application classes")
        std_println("    -d  enable disassembling")
        std_println("    -h  print this help")

        # Exit
        self.exit(0)

    def _initialize_object_system(self):
        # Allocate the nil object
        self.nilObject = Object(None)

        # Allocate the Metaclass classes
        self.metaclassClass = self.new_metaclass_class()

        # Allocate the rest of the system classes
        self.objectClass     = self.new_system_class()
        self.nilClass        = self.new_system_class()
        self.classClass      = self.new_system_class()
        self.arrayClass      = self.new_system_class()
        self.symbolClass     = self.new_system_class()
        self.methodClass     = self.new_system_class()
        self.integerClass    = self.new_system_class()
        self.primitiveClass  = self.new_system_class()
        self.stringClass     = self.new_system_class()
        self.doubleClass     = self.new_system_class()

        # Setup the class reference for the nil object
        self.nilObject.set_class(self.nilClass)

        # Initialize the system classes
        self._initialize_system_class(self.objectClass,                 None, "Object")
        self._initialize_system_class(self.classClass,      self.objectClass, "Class")
        self._initialize_system_class(self.metaclassClass,   self.classClass, "Metaclass")
        self._initialize_system_class(self.nilClass,        self.objectClass, "Nil")
        self._initialize_system_class(self.arrayClass,      self.objectClass, "Array")
        self._initialize_system_class(self.methodClass,      self.arrayClass, "Method")
        self._initialize_system_class(self.symbolClass,     self.objectClass, "Symbol")
        self._initialize_system_class(self.integerClass,    self.objectClass, "Integer")
        self._initialize_system_class(self.primitiveClass,  self.objectClass, "Primitive")
        self._initialize_system_class(self.stringClass,     self.objectClass, "String")
        self._initialize_system_class(self.doubleClass,     self.objectClass, "Double")

        # Load methods and fields into the system classes
        self._load_system_class(self.objectClass)
        self._load_system_class(self.classClass)
        self._load_system_class(self.metaclassClass)
        self._load_system_class(self.nilClass)
        self._load_system_class(self.arrayClass)
        self._load_system_class(self.methodClass)
        self._load_system_class(self.symbolClass)
        self._load_system_class(self.integerClass)
        self._load_system_class(self.primitiveClass)
        self._load_system_class(self.stringClass)
        self._load_system_class(self.doubleClass)

        # Load the generic block class
        self.blockClass = self.load_class(self.symbol_for("Block"))

        # Setup the true and false objects
        trueClassName    = self.symbol_for("True")
        trueClass        = self.load_class(trueClassName)
        self.trueObject  = self.new_instance(trueClass)
        
        falseClassName   = self.symbol_for("False")
        falseClass       = self.load_class(falseClassName)
        self.falseObject = self.new_instance(falseClass)

        # Load the system class and create an instance of it
        self.systemClass = self.load_class(self.symbol_for("System"))
        system_object = self.new_instance(self.systemClass)

        # Put special objects and classes into the dictionary of globals
        self.set_global(self.symbol_for("nil"),    self.nilObject)
        self.set_global(self.symbol_for("true"),   self.trueObject)
        self.set_global(self.symbol_for("false"),  self.falseObject)
        self.set_global(self.symbol_for("system"), system_object)
        self.set_global(self.symbol_for("System"), self.systemClass)
        self.set_global(self.symbol_for("Block"),  self.blockClass)
        
        self.set_global(self.symbol_for("Nil"),    self.nilClass)
        
        self.set_global( trueClassName,  trueClass)
        self.set_global(falseClassName, falseClass)

        self.blockClasses = [self.blockClass] + \
                [self._make_block_class(i) for i in [1, 2, 3]]

        self._interpreter.initialize_known_quick_sends()

        return system_object

    @jit.elidable
    def symbol_for(self, string):
        # Lookup the symbol in the symbol table
        result = self._symbol_table.get(string, None)
        if result is not None:
            return result
        
        # Create a new symbol and return it
        result = self._new_symbol(string)
        return result
    
    def new_array_with_length(self, length):
        return Array(self.nilObject, length)
  
    def new_array_from_list(self, values):
        make_sure_not_resized(values)
        return Array(self.nilObject, 0, values)

    def new_array_with_strings(self, strings):
        # Allocate a new array with the same length as the string array
        result = self.new_array_with_length(len(strings))

        # Copy all elements from the string array into the array
        for i in range(len(strings)):
            result.set_indexable_field(i, self.new_string(strings[i]))
    
        return result

    @staticmethod
    def new_block(method, context_frame):
        return Block(method, context_frame)

    def new_class(self, class_class):
        # Allocate a new class and set its class to be the given class class
        result = Class(self, class_class.get_number_of_instance_fields())
        result.set_class(class_class)
        return result

    @staticmethod
    def new_frame(previous_frame, method, context):
        # Compute the maximum number of stack locations (including arguments,
        # locals and extra buffer to support doesNotUnderstand) and set the
        # number of indexable fields accordingly
        length = (method.get_number_of_arguments() +
                  method.get_number_of_locals().get_embedded_integer() +
                  method.get_maximum_number_of_stack_elements().get_embedded_integer() + 2)

        return Frame(length, method, context, previous_frame)

    @staticmethod
    def new_method(signature, num_bytecodes, literals,
                   num_locals, maximum_number_of_stack_elements):
        return Method(literals, num_locals, maximum_number_of_stack_elements,
                      num_bytecodes, signature)

    def new_instance(self, instance_class):
        return Object(self.nilObject, instance_class.get_number_of_instance_fields(), instance_class)

    @staticmethod
    def new_integer(value):
        assert isinstance(value, int)
        return Integer(value)

    @staticmethod
    def new_biginteger(value):
        assert isinstance(value, rbigint)
        return BigInteger(value)

    @staticmethod
    def new_double(value):
        return Double(value)
    
    def new_metaclass_class(self):
        # Allocate the metaclass classes
        result = Class(self)
        result.set_class(Class(self))

        # Setup the metaclass hierarchy
        result.get_class(self).set_class(result)

        # Return the freshly allocated metaclass class
        return result

    @staticmethod
    def new_string(embedded_string):
        return String(embedded_string)

    def _new_symbol(self, string):
        result = Symbol(string)

        # Insert the new symbol into the symbol table
        self._symbol_table[string] = result
        return result
      
    def new_system_class(self):
        # Allocate the new system class
        system_class = Class(self)

        # Setup the metaclass hierarchy
        system_class.set_class(Class(self))
        system_class.get_class(self).set_class(self.metaclassClass)

        # Return the freshly allocated system class
        return system_class
    
    def _initialize_system_class(self, system_class, super_class, name):
        # Initialize the superclass hierarchy
        if super_class:
            system_class.set_super_class(super_class)
            system_class.get_class(self).set_super_class(super_class.get_class(self))
        else:
            system_class.get_class(self).set_super_class(self.classClass)

        # Initialize the array of instance fields
        system_class.set_instance_fields(self.new_array_with_length(0))
        system_class.get_class(self).set_instance_fields(self.new_array_with_length(0))

        # Initialize the array of instance invokables
        system_class.set_instance_invokables(self.new_array_with_length(0))
        system_class.get_class(self).set_instance_invokables(self.new_array_with_length(0))

        # Initialize the name of the system class
        system_class.set_name(self.symbol_for(name))
        system_class.get_class(self).set_name(self.symbol_for(name + " class"))

        # Insert the system class into the dictionary of globals
        self.set_global(system_class.get_name(), system_class)
    
    def get_global(self, name):
        # Return the global with the given name if it's in the dictionary of globals
        # if not, return None
        jit.promote(self)
        assoc = self._get_global(name)
        if assoc:
            return assoc.get_value()
        else:
            return None

    @jit.elidable
    def _get_global(self, name):
        return self._globals.get(name, None)

    def set_global(self, name, value):
        self.get_globals_association(name).set_value(value)

    def has_global(self, name):
        return name in self._globals

    @jit.elidable_promote("all")
    def get_globals_association(self, name):
        assoc = self._globals.get(name, None)
        if assoc is None:
            assoc = Assoc(name, self.nilObject)
            self._globals[name] = assoc
        return assoc

    def _get_block_class(self, number_of_arguments):
        return self.blockClasses[number_of_arguments]

    def _make_block_class(self, number_of_arguments):
        # Compute the name of the block class with the given number of
        # arguments
        name = self.symbol_for("Block" + str(number_of_arguments))

        # Get the block class for blocks with the given number of arguments
        result = self._load_class(name, None)

        # Add the appropriate value primitive to the block class
        result.add_instance_primitive(block_evaluation_primitive(number_of_arguments, self))

        # Insert the block class into the dictionary of globals
        self.set_global(name, result)

        # Return the loaded block class
        return result

    def load_class(self, name):
        # Check if the requested class is already in the dictionary of globals
        result = self.get_global(name)
        if result is not None:
            return result

        # Load the class
        result = self._load_class(name, None)

        # Load primitives (if necessary) and return the resulting class
        if result and result.has_primitives():
            result.load_primitives()

        self.set_global(name, result)
        return result

    def _load_system_class(self, system_class):
        # Load the system class
        result = self._load_class(system_class.get_name(), system_class)

        if not result:
            error_println(system_class.get_name().get_string()
                   + " class could not be loaded. It is likely that the"
                   + " class path has not been initialized properly."
                   + " Please make sure that the '-cp' parameter is given on the command-line.")
            self.exit(200)

        # Load primitives if necessary
        if result.has_primitives():
            result.load_primitives()

    def _load_class(self, name, system_class):
        # Try loading the class from all different paths
        for cpEntry in self.classpath:
            try:
                # Load the class from a file and return the loaded class
                result = sourcecode_compiler.compile_class_from_file(cpEntry, name.get_string(), system_class, self)
                if self._dump_bytecodes:
                    from som.compiler.disassembler import dump
                    dump(result.get_class(self))
                    dump(result)

                return result
            except IOError:
                # Continue trying different paths
                pass

        # The class could not be found.
        return None
    
    def load_shell_class(self, stmt):
        # Load the class from a stream and return the loaded class
        result = sourcecode_compiler.compile_class_from_string(stmt, None, self)
        if self._dump_bytecodes:
            from som.compiler.disassembler import dump
            dump(result)
        return result
Exemplo n.º 39
0
 def __init__(self, nilObject, value):
     Object.__init__(self, nilObject)
     self._string = value
     self._number_of_signature_arguments = self._determine_number_of_signature_arguments() # updated later