Skip to content

Commit

Permalink
Use Cython.
Browse files Browse the repository at this point in the history
  • Loading branch information
progval committed Apr 30, 2012
1 parent 320c85b commit 8b042e2
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 2 deletions.
32 changes: 30 additions & 2 deletions lib/core.py
Expand Up @@ -28,11 +28,25 @@

import re

try:
from cython import locals as cfunc
from cython import declare as cvar
import cython
except ImportError:
def cfunc(**kwargs):
return lambda x:x
def cvar(**kwargs):
return lambda x:x
class cython:
def __getattr__(self, name):
return None

STRICT = True # Strict type and value checks. A bit time-consuming (~10%)

if 'xrange' not in globals(): # Python 3
xrange = range

@cfunc(operand=str)
def get_int(operand):
"""Shortcut for extracting the integer from an operand."""
if STRICT and len(operand) < 1:
Expand Down Expand Up @@ -77,6 +91,7 @@ class RedcodeSyntaxError(Exception):
pass

class Instruction(object):
_data = cvar(list)
def __init__(self, *data, **kwdata):
if data != () and kwdata != {}:
raise ValueError('You cannot give data both as non-keyword '
Expand Down Expand Up @@ -146,7 +161,7 @@ def _get_modifier(self):
return 'B'
def _set_modifier(self, value):
if STRICT and value not in SYNTAX.modifiers:
raise ValueError('%r is not a valid modifier' % r)
raise ValueError('%r is not a valid modifier' % value)
self._data[1] = value
modifier = property(_get_modifier, _set_modifier)
def _get_A(self):
Expand Down Expand Up @@ -207,12 +222,13 @@ def __str__(self):
@property
def as_tuple(self):
return tuple(self._data)

@property
def as_dict(self):
return dict(zip(SYNTAX.data_blocks, self._data))


@cfunc(memory=object, ptr=int)
def _read(self, memory, ptr):
"""Return input data of the instruction, based on modifiers.
Expand All @@ -236,6 +252,8 @@ def _read(self, memory, ptr):
return (A.as_tuple, B.as_tuple)
else:
assert False

@cfunc(memory=object, dest=int, inst=object)
def _write(self, memory, dest, inst):
"""Writes data to the memory"""
m = self.modifier
Expand Down Expand Up @@ -267,6 +285,7 @@ def _write(self, memory, dest, inst):
else:
assert False

@cfunc(A=tuple, B=tuple, function=object)
def _math(self, A, B, function):
"Shortcut for running math operations."
assert None not in (A[2], B[2])
Expand All @@ -276,13 +295,15 @@ def _math(self, A, B, function):
assert B[3] is not None
res2 = B[3][0]+str(function(get_int(A[3]), get_int(B[3])))
return (B[0], B[1], res1, res2)
@cfunc(memory=object, ptr=int, field=str)
def _increment(self, memory, ptr, field):
"Shortcut for incrementing fields."
inst = memory.read(ptr + get_int(field))
if field.startswith('}'):
inst.A = inst.A[0] + str(int(inst.A[1:])+1)
elif field.startswith('>'):
inst.B = inst.B[0] + str(int(inst.B[1:])+1)
@cfunc(memory=object, ptr=int)
def run(self, memory, ptr):
assert memory.read(ptr) == self

Expand Down Expand Up @@ -377,6 +398,9 @@ def run(self, memory, ptr):
return threads

class Memory(object):
_memory = cvar(list)
_size = cvar(int)
_loaded_warriors = cvar(dict)
def __init__(self, size):
if not isinstance(size, int):
raise ValueError('Memory size must be an integer, not %r' % size)
Expand All @@ -389,11 +413,13 @@ def __init__(self, size):
def size(self):
return self._size

@cfunc(ptr=int)
def read(self, ptr):
if STRICT and not isinstance(ptr, int):
raise ValueError('Pointer must be an integer, not %r' % ptr)
ptr %= self.size
return self._memory[ptr]
@cfunc(ptr=int)
def write(self, ptr, instruction=None, **kwargs):
if STRICT and not isinstance(ptr, int):
raise ValueError('Pointer must be an integer, not %r' % ptr)
Expand All @@ -414,6 +440,7 @@ def write(self, ptr, instruction=None, **kwargs):
data.update(kwargs)
self.write(ptr, Instruction(**data))

@cfunc(base_ptr=int, value=str)
def get_absolute_ptr(self, base_ptr, value):
if STRICT and len(value) < 2:
raise ValueError('The operand can be only A or B')
Expand All @@ -437,6 +464,7 @@ def get_absolute_ptr(self, base_ptr, value):
elif char in '<>':
return base_ptr + get_int(value2.B)

@cfunc(ptr=int, warrior=object)
def load(self, ptr, warrior):
if STRICT and not isinstance(warrior, Warrior):
raise ValueError('warrior must be an instance of Warrior, not %r.'%
Expand Down
10 changes: 10 additions & 0 deletions setup.py
@@ -1,8 +1,18 @@
from distutils.core import setup
from distutils.extension import Extension

try:
from Cython.Distutils import build_ext
cmdclass = {'build_ext': build_ext}
ext_modules = [Extension("vmars.core", ["lib/core.py"])]
except ImportError:
cmdclass = {}
ext_modules = []

setup(
name = 'vmars',
cmdclass = cmdclass,
ext_modules = ext_modules,
packages = ['vmars'],
package_dir = {'vmars': 'lib'},
)

0 comments on commit 8b042e2

Please sign in to comment.