Commit 25bd9a52 authored by Stefan Marr's avatar Stefan Marr

Started with Primitive support

- also more complete implementation of Class
Signed-off-by: default avatarStefan Marr <git@stefan-marr.de>
parent 8006d14f
from som.primitives.primitives import Primitives
from som.vmobjects.primitive import Primitive
from som.vmobjects.array import Array
class ObjectPrimitives(Primitives):
def install_primitives(self):
def _equals(self, frame, interpreter):
op1 = frame.pop()
op2 = frame.pop()
if op1 is op2:
frame.push(self._universe.trueObject)
else:
frame.push(self._universe.falseObject)
self._install_instance_primitive(Primitive("==", self._universe, _equals))
def _hashcode(self, frame, interpreter):
rcvr = frame.pop()
frame.push(self._universe.new_integer(hash(rcvr)))
self._install_instance_primitive(Primitive("hashcode", self._universe, _hashcode))
def _objectSize(self, frame, interpreter):
rcvr = frame.pop()
size = rcvr.get_number_of_fields()
if isinstance(rcvr, Array):
size += rcvr.get_number_of_indexable_fields()
frame.push(self._universe.new_integer(size))
self._install_instance_primitive(Primitive("objectSize", self._universe, _objectSize))
def _perform(self, frame, interpreter):
selector = frame.pop()
rcvr = frame.get_stack_element(0)
invokable = rcvr.get_class().lookup_invokable(selector)
invokable.invoke(frame, interpreter)
self._install_instance_primitive(Primitive("perform:", self._universe, _perform))
def _performInSuperclass(self, frame, interpreter):
clazz = frame.pop()
selector = frame.pop()
rcvr = frame.get_stack_element(0)
invokable = clazz.lookup_invokable(selector)
invokable.invoke(frame, interpreter)
self._install_instance_primitive(Primitive("perform:inSuperclass:", self._universe, _performInSuperclass))
def _performWithArguments(self, frame, interpreter):
args = frame.pop()
selector = frame.pop()
rcvr = frame.get_stack_element(0)
for i in range(0, args.get_number_of_indexable_fields()):
frame.push(args.get_indexable_field(i))
invokable = rcvr.get_class().lookup_invokable(selector)
invokable.invoke(frame, interpreter)
self._install_instance_primitive(Primitive("perform:withArguments:", self._universe, _performWithArguments))
def _instVarAt(self, frame, interpreter):
idx = frame.pop()
rcvr = frame.pop()
frame.push(rcvr.get_field(idx.get_embedded_integer() - 1))
self._install_instance_primitive(Primitive("instVarAt:", self._universe, _instVarAt))
def _instVarAtPut(self, frame, interpreter):
val = frame.pop()
idx = frame.pop()
rcvr = frame.get_stack_element(0)
rcvr.set_field(idx.get_embedded_integer() - 1, val)
self._install_instance_primitive(Primitive("instVarAt:put:", self._universe, _instVarAtPut))
class Primitives(object):
def __init__(self, universe):
self._universe = universe
self._holder = None
def install_primitives_in(self, value):
# Save a reference to the holder class
self._holder = value
# Install the primitives from this primitives class
self.install_primitives()
def install_primitives(self):
raise NotImplementedError()
def _install_instance_primitive(self, primitive):
# Install the given primitive as an instance primitive in the holder class
self._holder.add_instance_primitive(primitive)
def _install_class_primitive(self, primitive):
# Install the given primitive as an instance primitive in the class of
# the holder class
self._holder.get_class().add_instance_primitive(primitive)
from __future__ import print_function
from som.interpreter.interpreter import Interpreter
from som.interpreter.bytecodes import Bytecodes
from som.vm.symbol_table import SymbolTable
from som.vmobjects.object import Object
from som.vmobjects.clazz import Class
from som.vmobjects.array import Array
from som.vmobjects.symbol import Symbol
from som.vmobjects.method import Method
from som.vmobjects.integer import Integer
from som.vmobjects.integer import Integer
from som.vmobjects.string import String
import som.compiler.sourcecode_compiler as sourcecode_compiler
......@@ -48,6 +50,10 @@ class Universe(object):
@property
def nilObject(self):
return self._nilObject
@property
def primitiveClass(self):
return self._primitiveClass
def _create_bootstrap_method(self):
......
from som.vmobjects.object import Object
from som.vmobjects.object import Object
from som.primitives.primitives import Primitives
from importlib import import_module
import inspect
class Class(Object):
......@@ -112,6 +116,40 @@ class Class(Object):
# Field not found
return -1
def add_instance_invokable(self, value):
# Add the given invokable to the array of instance invokables
for i in range(0, self.get_number_of_instance_invokables()):
# Get the next invokable in the instance invokable array
invokable = self.get_instance_invokable(i)
# Replace the invokable with the given one if the signature matches
if invokable.get_signature() == value.get_signature():
self.set_instance_invokable(i, value)
return False
# Append the given method to the array of instance methods
self.set_instance_invokables(self.get_instance_invokables().copy_and_extend_with(value, self._universe))
return True
def add_instance_primitive(self, value):
if self.add_instance_invokable(value):
self._universe.std_print("Warning: Primitive " + value.get_signature().get_string())
self._universe.std_println(" is not in class definition for class " + self.get_name().get_string())
def get_instance_field_name(self, index):
# Get the name of the instance field with the given index
if index >= self._get_number_of_super_instance_fields():
# Adjust the index to account for fields defined in the super class
index -= self._get_number_of_super_instance_fields()
# Return the symbol representing the instance fields name
return self.get_instance_fields().get_indexable_field(index)
else:
# Ask the super class to return the name of the instance field
return self.get_super_class().get_instance_field_name(index)
def get_number_of_instance_fields(self):
# Get the total number of instance fields in this class
return (self.get_instance_fields().get_number_of_indexable_fields() +
......@@ -126,11 +164,31 @@ class Class(Object):
def has_primitives(self):
# Lookup invokable with given signature in array of instance invokables
for invokable in self.get_instance_invokables():
if invokable.is_primitive():
for i in range(0, self.get_number_of_instance_invokables()):
# Get the next invokable in the instance invokable array
if self.get_instance_invokable(i).is_primitive():
return True
return False
def load_primitives(self):
# determine module name for the primitives of the class
module_name = "som.primitives." + self.get_name().get_string().lower() + "_primitives"
# Try loading the primitives
module = import_module(module_name)
for name, element in inspect.getmembers(module):
if (inspect.isclass(element) and
issubclass(element, Primitives) and
element is not Primitives):
element(self._universe).install_primitives_in(self)
def replace_bytecodes(self):
cnt = self.get_number_of_instance_invokables()
for i in range(0, cnt):
inv = self.get_instance_invokable(i)
if not inv.is_primitive():
inv.replace_bytecodes()
def __str__(self):
return "Class(" + self.get_name().get_string() + ")"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment