import os

from rpython.rlib.streamio import open_file_as_stream

from StringIO import StringIO

from som.compiler.parser                   import Parser
from som.compiler.class_generation_context import ClassGenerationContext

def compile_class_from_file(path, filename, system_class, universe):
    return _SourcecodeCompiler().compile(path, filename, system_class, universe)

def compile_class_from_string(stmt, system_class, universe):
    return _SourcecodeCompiler().compile_class_string(stmt, system_class, universe)

class _SourcecodeCompiler(object):
    
    def __init__(self):
        self._parser = None
    
    def compile(self, path, filename, system_class, universe):
        fname = path + os.sep + filename + ".som"

        try:
            input_file = open_file_as_stream(fname, "r")
            try:
                self._parser = Parser(input_file, universe)
                result = self._compile(system_class, universe)
            finally:
                input_file.close()
        except OSError as e:
            raise IOError()

        cname = result.get_name()
        cnameC = cname.get_string()

        if filename != cnameC:
            raise ValueError("File name " + filename + " does not match class name " + cnameC)
    
        return result

    def compile_class_string(self, stream, system_class, universe):
        self._parser = Parser(StringIO(stream), universe)

        result = self._compile(system_class, universe)
        return result

    def _compile(self, system_class, universe):
        cgc = ClassGenerationContext(universe)

        result = system_class
        self._parser.classdef(cgc)

        if not system_class:
            result = cgc.assemble()
        else:
            cgc.assemble_system_class(result)

        return result

@@ -61,39 +61,29 @@
 ream
-%0A%0Afrom StringIO import StringIO
+, Stream, StreamError
 %0A%0Afr
@@ -211,16 +211,1027 @@
 ontext%0A%0A
+%0Aclass _StringStream(Stream):%0A    def __init__(self, string):%0A        self._string = string%0A        self.pos     = 0%0A        self.max     = len(string) - 1%0A%0A    def write(self, data):%0A        raise StreamError(%22StringStream is not writable%22)%0A    def truncate(self, size):%0A        raise StreamError(%22StringStream is immutable%22)%0A%0A    def peek(self):%0A        if self.pos %3C self.max:%0A            return self._string%5Bself.pos:%5D%0A        else:%0A            return ''%0A%0A    def tell(self):%0A        return self.pos%0A%0A    def seek(self, offset, whence):%0A        if whence == 0:%0A            self.pos = max(0, offset)%0A        elif whence == 1:%0A            self.pos = max(0, self.pos + offset)%0A        elif whence == 2:%0A            self.pos = max(0, self.max + offset)%0A        else:%0A            raise StreamError(%22seek(): whence must be 0, 1 or 2%22)%0A%0A    def read(self, n):%0A        assert isinstance(n, int)%0A        end = self.pos + n%0A        data = self._string%5Bself.pos:end%5D%0A        self.pos += len(data)%0A        return data%0A%0A
 def comp
@@ -2381,16 +2381,21 @@
 ser(
+_
 String
-IO
+Stream
 (str

make the file and string stream type-compatible