Commit 0d775009 authored by Stefan Marr's avatar Stefan Marr

Added Array, Symbol, and SymbolTable

Signed-off-by: default avatarStefan Marr <>
parent 4b64e0b7
class SymbolTable(object):
\ No newline at end of file
def __init__(self):
self._map = {}
def lookup(self, string):
# Lookup the given string in the hash map
return self._map.get(string, None)
def insert(self, symbol):
# Insert the given symbol into the hash map by associating the
# symbol associated string to the symbol itself
self._map[symbol.get_string()] = symbol
from som.interpreter.interpreter import Interpreter
from som.vm.symbol_table import SymbolTable
from som.vmobjects.object import Object
from som.vmobjects.clazz import Class
from som.vmobjects.clazz import Class
from som.vmobjects.array import Array
from som.vmobjects.symbol import Symbol
import os
......@@ -169,14 +171,23 @@ class Universe(object):
system_object = self._new_instance(self._systemClass)
# Put special objects and classes into the dictionary of globals
self.setGlobal(self.symbol_for("nil"), self._nilObject)
self.setGlobal(self.symbol_for("true"), self._trueObject)
self.setGlobal(self.symbol_for("false"), self._falseObject)
self.setGlobal(self.symbol_for("system"), self._systemObject)
self.setGlobal(self.symbol_for("System"), self._systemClass)
self.setGlobal(self.symbol_for("Block"), self._blockClass)
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"), self._systemObject)
self.set_global(self.symbol_for("System"), self._systemClass)
self.set_global(self.symbol_for("Block"), self._blockClass)
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
......@@ -222,6 +233,20 @@ class Universe(object):
# Return the freshly allocated metaclass class
return result
def new_symbol(self, string):
# Allocate a new symbol and set its class to be the symbol class
result = Symbol(self._nilObject)
# Put the string into the symbol
# Insert the new symbol into the symbol table
# Return the freshly allocated symbol
return result
def new_system_class(self):
# Allocate the new system class
system_class = Class(self)
......@@ -236,7 +261,7 @@ class Universe(object):
def _initialize_system_class(self, system_class, super_class, name):
# Initialize the superclass hierarchy
if super_class:
......@@ -252,7 +277,7 @@ class Universe(object):
# Initialize the name of the system class
system_class.get_class().setName(self.symbol_for(name + " class"));
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)
......@@ -274,3 +299,69 @@ class Universe(object):
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._loadClass(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():
return result
def _load_system_class(self, system_class):
# Load the system class
result = self._load_class(system_class.get_name(), system_class)
# Load primitives if necessary
if result.has_primitives():
def _load_class(self, name, system_class):
# Try loading the class from all different paths
for cpEntry in self._classpath:
# Load the class from a file and return the loaded class
result = SourcecodeCompiler.compile_class(cpEntry, name.getString(), system_class, self)
if self._dump_bytecodes:
return result
except IOError:
# Continue trying different paths
# The class could not be found.
return None
from som.vmobjects.object import Object
class Array(Object):
def __init__(self, nilObject):
super(Array, self).__init__(nilObject)
# Private array of indexable fields
self._indexable_fields = None
def get_indexable_field(self, index):
# Get the indexable field with the given index
return self._indexable_fields[index]
def set_indexable_field(self, index, value):
# Set the indexable field with the given index to the given value
self._indexable_fields[index] = value
def get_number_of_indexable_fields(self):
# Get the number of indexable fields in this array
return len(self._indexable_fields)
def set_number_of_indexable_fields_and_clear(self, value, nilObject):
# Allocate a new array of indexable fields, initialized with nil
self._indexable_fields = [nilObject] * value
def copy_and_extend_with(self, value, universe):
# Allocate a new array which has one indexable field more than this
# array
result = universe.new_array_with_length(
self.get_number_of_indexable_fields() + 1)
# Copy the indexable fields from this array to the new array
# Insert the given object as the last indexable field in the new array
result.set_indexable_field(self.get_number_of_indexable_fields(), value)
# Return the new array
return result
def _copy_indexable_fields_to(self, destination):
# Copy all indexable fields from this array to the destination array
for i in range(self.get_number_of_indexable_fields()):
destination.set_indexable_field(i, self.get_indexable_field(i))
from som.vmobjects.object import Object
class Symbol(Object):
def __init__(self, nilObject):
super(Symbol, self).__init__(nilObject)
self._string = None
self._number_of_signature_arguments = None
def get_string(self):
# Get the string associated to this symbol
return self._string
def set_string(self, value):
# Set the string associated to this symbol
self._string = value
def _determine_number_of_signature_arguments(self):
# Check for binary signature
if self.is_binary_signature():
self._number_of_signature_arguments = 2
# Count the colons in the signature string
number_of_colons = 0
# Iterate through every character in the signature string
for c in self._string:
if c == ':':
number_of_colons += 1
# The number of arguments is equal to the number of colons plus one
self._number_of_signature_arguments = number_of_colons + 1
def get_number_of_signature_arguments(self):
return self._number_of_signature_arguments
def is_binary_signature(self):
# Check the individual characters of the string
for c in self._string:
if (c != '~' and c != '&' and c != '|' and c != '*' and c != '/' and
c != '@' and c != '+' and c != '-' and c != '=' and c != '>' and
c != '<' and c != ',' and c != '%' and c != '\\'):
return False
return True
def __str__(self):
return "#" + self._string
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment