<commit_before>use common::event::Event;
use common::get_slice::GetSlice;

use alloc::boxed::Box;

use collections::string::String;
use collections::vec::Vec;

use core::usize;

use scheduler::context::ContextMemory;
use common::debug;
use common::elf::Elf;
use common::memory;
use common::paging::Page;
use scheduler::{start_no_ints, end_no_ints};
use common::parse_path::parse_path;
use common::pwd;

use schemes::{KScheme, Resource, ResourceSeek, Url};

/// A scheme context
pub struct SchemeContext {
    /// Interrupted
    interrupts: bool,
    /// The old memory (before context switch)
    old_memory: Vec<ContextMemory>,
}

impl SchemeContext {
    /// Enter from a given context memory
    pub unsafe fn enter(memory: &ContextMemory) -> SchemeContext {
        let interrupts = start_no_ints();
        let mut old_memory: Vec<ContextMemory> = Vec::new();
        for i in 0..(memory.virtual_size + 4095) / 4096 {
            let mut page = Page::new(memory.virtual_address + i * 4096);
            //TODO: Use one contextmemory if possible
            old_memory.push(ContextMemory {
                physical_address: page.phys_addr(),
                virtual_address: page.virt_addr(),
                virtual_size: 4096,
            });
            page.map(memory.physical_address + i * 4096);
        }

        SchemeContext {
            interrupts: interrupts,
            old_memory: old_memory,
        }
    }

    pub fn translate<T>(&self, ptr: *const T) -> *const T {
        for memory in self.old_memory.iter() {
            if (ptr as usize) >= memory.virtual_address && (ptr as usize) < memory.virtual_address + memory.virtual_size {
                return ((ptr as usize) - memory.virtual_address + memory.physical_address) as *const T;
            }
        }

        ptr
    }

    pub fn translate_mut<T>(&self, ptr: *mut T) -> *mut T {
        for memory in self.old_memory.iter() {
            if (ptr as usize) >= memory.virtual_address && (ptr as usize) < memory.virtual_address + memory.virtual_size {
                return ((ptr as usize) - memory.virtual_address + memory.physical_address) as *mut T;
            }
        }

        ptr
    }

    /// Exit the context
    pub unsafe fn exit(self) {
        for memory in self.old_memory.iter() {
            for i in 0..(memory.virtual_size + 4095) / 4096 {
                let mut page = Page::new(memory.virtual_address + i * 4096);
                page.map(memory.physical_address + i * 4096);
            }
        }
        end_no_ints(self.interrupts);
    }
}

/// A scheme resource
pub struct SchemeResource {
    /// The handle
    handle: usize,
    /// The context memory
    memory: ContextMemory,
    /// Duplicate?
    _dup: usize,
    /// Internal fpath
    _fpath: usize,
    /// Internal read
    _read: usize,
    /// Internal write
    _write: usize,
    /// Internal lseek
    _lseek: usize,
    /// Internal fsync
    _fsync: usize,
    /// Internal ftruncate
    _ftruncate: usize,
    /// Internal close
    _close: usize,
}

impl SchemeResource {
    /// Check validity
    fn valid(&self, addr: usize) -> bool {
        addr >= self.memory.virtual_address && addr < self.memory.virtual_address + self.memory.virtual_size
    }
}

impl Resource for SchemeResource {
    // TODO: Clone instead?
    /// Duplicate the resource
    fn dup(&self) -> Option<Box<Resource>> {
        if self.valid(self._dup) {
            let fd;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._dup;
                fd = (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
            if fd != usize::MAX {
                //TODO: Count number of handles, don't allow drop until 0
                return Some(box SchemeResource {
                    handle: fd,
                    memory: ContextMemory {
                        physical_address: self.memory.physical_address,
                        virtual_address: self.memory.virtual_address,
                        virtual_size: self.memory.virtual_size,
                    },
                    _dup: self._dup,
                    _fpath: self._fpath,
                    _read: self._read,
                    _write: self._write,
                    _lseek: self._lseek,
                    _fsync: self._fsync,
                    _ftruncate: self._ftruncate,
                    _close: self._close,
                });
            }
        }

        None
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        if self.valid(self._fpath) {
            let mut buf: [u8; 4096] = [0; 4096];
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._fpath;
                result = (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(self.handle, context.translate_mut(buf.as_mut_ptr()), buf.len());
                context.exit();
            }
            if result != usize::MAX {
                return Url::from_string(unsafe { String::from_utf8_unchecked(Vec::from(buf.get_slice(None, Some(result)))) });
            }
        }
        Url::new()
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        if self.valid(self._read) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._read;
                result = (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(self.handle, context.translate_mut(buf.as_mut_ptr()), buf.len());
                context.exit();
            }
            if result != usize::MAX {
                return Some(result);
            }
        }
        None
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        if self.valid(self._write) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._write;
                result = (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(self.handle, context.translate(buf.as_ptr()), buf.len());
                context.exit();
            }
            if result != usize::MAX {
                return Some(result);
            }
        }
        None
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        if self.valid(self._lseek) {
            let offset;
            let whence;
            match pos {
                ResourceSeek::Start(off) => {
                    whence = 0;
                    offset = off as isize;
                },
                ResourceSeek::Current(off) => {
                    whence = 1;
                    offset = off;
                },
                ResourceSeek::End(off) => {
                    whence = 2;
                    offset = off;
                }
            }

            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._lseek;
                result = (*(fn_ptr as *const extern "C" fn(usize, isize, isize) -> usize))(self.handle, offset, whence);
                context.exit();
            }
            if result != usize::MAX {
                return Some(result);
            }
        }
        None
    }

    /// Sync the resource
    fn sync(&mut self) -> bool {
        if self.valid(self._fsync) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._fsync;
                result = (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
            return result == 0;
        }
        false
    }

    fn truncate(&mut self, len: usize) -> bool {
        if self.valid(self._ftruncate) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._ftruncate;
                result = (*(fn_ptr as *const extern "C" fn(usize, usize) -> usize))(self.handle, len);
                context.exit();
            }
            return result == 0;
        }
        false
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self){
        if self.valid(self._close) {
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._close;
                (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
        }
    }
}

/// A scheme item
pub struct SchemeItem {
    /// The URL
    url: Url,
    /// The scheme
    scheme: String,
    /// The binary for the scheme
    binary: Url,
    /// The handle
    handle: usize,
    /// The context memory
    memory: ContextMemory,
    _start: usize,
    _stop: usize,
    _open: usize,
    _dup: usize,
    _fpath: usize,
    _read: usize,
    _write: usize,
    _lseek: usize,
    _fsync: usize,
    _ftruncate: usize,
    _close: usize,
    _event: usize,
}

impl SchemeItem {
    /// Load scheme item from URL
    pub fn from_url(url: &Url) -> Box<SchemeItem> {
        debugln!("{}", url.to_string());

        let mut scheme_item = box SchemeItem {
            url: url.clone(),
            scheme: String::new(),
            binary: Url::new(),
            handle: 0,
            memory: ContextMemory {
                physical_address: 0,
                virtual_address: 0,
                virtual_size: 0,
            },
            _start: 0,
            _stop: 0,
            _open: 0,
            _dup: 0,
            _fpath: 0,
            _read: 0,
            _write: 0,
            _lseek: 0,
            _fsync: 0,
            _ftruncate: 0,
            _close: 0,
            _event: 0,
        };

        let path_parts = parse_path(url.reference(), pwd());
        if !path_parts.is_empty() {
            if let Some(part) = path_parts.get(path_parts.len() - 1) {
                scheme_item.scheme = part.clone();
                scheme_item.binary = Url::from_string(url.to_string() + part + ".bin");
            }
        }

        if let Some(mut resource) = scheme_item.binary.open() {
            let mut vec: Vec<u8> = Vec::new();
            resource.read_to_end(&mut vec);

            unsafe {
                let executable = Elf::from_data(vec.as_ptr() as usize);
                if let Some(segment) = executable.load_segment() {
                    scheme_item.memory.virtual_address = segment.vaddr as usize;
                    scheme_item.memory.virtual_size = segment.mem_len as usize;
                    scheme_item.memory.physical_address = memory::alloc(scheme_item.memory.virtual_size);

                    if scheme_item.memory.physical_address > 0 {
                        //Copy progbits
                        ::memcpy(scheme_item.memory.physical_address as *mut u8, (executable.data + segment.off as usize) as *const u8, segment.file_len as usize);
                        //Zero bss
                        ::memset((scheme_item.memory.physical_address + segment.file_len as usize) as *mut u8, 0, segment.mem_len as usize - segment.file_len as usize);
                    }

                    scheme_item._start = executable.symbol("_start");
                    scheme_item._stop = executable.symbol("_stop");
                    scheme_item._open = executable.symbol("_open");
                    scheme_item._dup = executable.symbol("_dup");
                    scheme_item._fpath = executable.symbol("_fpath");
                    scheme_item._read = executable.symbol("_read");
                    scheme_item._write = executable.symbol("_write");
                    scheme_item._lseek = executable.symbol("_lseek");
                    scheme_item._fsync = executable.symbol("_fsync");
                    scheme_item._ftruncate = executable.symbol("_ftruncate");
                    scheme_item._close = executable.symbol("_close");
                    scheme_item._event = executable.symbol("_event");
                } else {
                    debug::d("Invalid ELF\n");
                }
            }
        }

        if scheme_item.valid(scheme_item._start) {
            //TODO: Allow schemes to be called inside of other schemes
            unsafe {
                let context = SchemeContext::enter(&scheme_item.memory);
                let fn_ptr: *const usize = &scheme_item._start;
                scheme_item.handle = (*(fn_ptr as *const extern "C" fn() -> usize))();
                context.exit();
            }
        }

        scheme_item
    }

    /// Check validity
    fn valid(&self, addr: usize) -> bool {
        addr >= self.memory.virtual_address && addr < self.memory.virtual_address + self.memory.virtual_size
    }
}

impl KScheme for SchemeItem {
    fn scheme(&self) -> &str {
        return &self.scheme;
    }

    //TODO: Hack for orbital
    fn event(&mut self, event: &Event){
        if self.valid(self._event) {
            unsafe {
                let event_ptr: *const Event = event;

                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._event;
                (*(fn_ptr as *const extern "C" fn(usize, usize)))(self.handle, event_ptr as usize);
                context.exit();
            }
        }
    }

    fn open(&mut self, url: &Url, flags: usize) -> Option<Box<Resource>> {
        if self.valid(self._open) {
            let fd;
            unsafe {
                let c_str = url.to_string() + "\0";

                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._open;
                fd = (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(self.handle, context.translate(c_str.as_ptr()), flags);
                context.exit();
            }
            if fd != usize::MAX {
                //TODO: Count number of handles, don't allow drop until 0
                return Some(box SchemeResource {
                    handle: fd,
                    memory: ContextMemory {
                        physical_address: self.memory.physical_address,
                        virtual_address: self.memory.virtual_address,
                        virtual_size: self.memory.virtual_size,
                    },
                    _dup: self._dup,
                    _fpath: self._fpath,
                    _read: self._read,
                    _write: self._write,
                    _lseek: self._lseek,
                    _fsync: self._fsync,
                    _ftruncate: self._ftruncate,
                    _close: self._close,
                });
            }
        }

        None
    }
}

impl Drop for SchemeItem {
    fn drop(&mut self) {
        if self.valid(self._stop) {
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._stop;
                (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
        }
    }
}
<commit_msg>Fix double free<commit_after>use common::event::Event;
use common::get_slice::GetSlice;

use alloc::boxed::Box;

use collections::string::String;
use collections::vec::Vec;

use core::usize;

use common::debug;
use common::elf::Elf;
use common::memory;
use common::paging::Page;
use scheduler::{start_no_ints, end_no_ints};
use common::parse_path::parse_path;
use common::pwd;

use schemes::{KScheme, Resource, ResourceSeek, Url};

pub struct SchemeMemory {
    pub physical_address: usize,
    pub virtual_address: usize,
    pub virtual_size: usize,
}

impl SchemeMemory {
    pub unsafe fn map(&mut self) {
        for i in 0..(self.virtual_size + 4095) / 4096 {
            Page::new(self.virtual_address + i * 4096).map(self.physical_address + i * 4096);
        }
    }
    pub unsafe fn unmap(&mut self) {
        for i in 0..(self.virtual_size + 4095) / 4096 {
            Page::new(self.virtual_address + i * 4096).map_identity();
        }
    }
}

/// A scheme context
pub struct SchemeContext {
    /// Interrupted
    interrupts: bool,
    /// The old memory (before context switch)
    old_memory: Vec<SchemeMemory>,
}

impl SchemeContext {
    /// Enter from a given context memory
    pub unsafe fn enter(memory: &SchemeMemory) -> SchemeContext {
        let interrupts = start_no_ints();
        let mut old_memory: Vec<SchemeMemory> = Vec::new();
        for i in 0..(memory.virtual_size + 4095) / 4096 {
            let mut page = Page::new(memory.virtual_address + i * 4096);
            //TODO: Use one SchemeMemory if possible
            old_memory.push(SchemeMemory {
                physical_address: page.phys_addr(),
                virtual_address: page.virt_addr(),
                virtual_size: 4096,
            });
            page.map(memory.physical_address + i * 4096);
        }

        SchemeContext {
            interrupts: interrupts,
            old_memory: old_memory,
        }
    }

    pub fn translate<T>(&self, ptr: *const T) -> *const T {
        for memory in self.old_memory.iter() {
            if (ptr as usize) >= memory.virtual_address && (ptr as usize) < memory.virtual_address + memory.virtual_size {
                return ((ptr as usize) - memory.virtual_address + memory.physical_address) as *const T;
            }
        }

        ptr
    }

    pub fn translate_mut<T>(&self, ptr: *mut T) -> *mut T {
        for memory in self.old_memory.iter() {
            if (ptr as usize) >= memory.virtual_address && (ptr as usize) < memory.virtual_address + memory.virtual_size {
                return ((ptr as usize) - memory.virtual_address + memory.physical_address) as *mut T;
            }
        }

        ptr
    }

    /// Exit the context
    pub unsafe fn exit(self) {
        for memory in self.old_memory.iter() {
            for i in 0..(memory.virtual_size + 4095) / 4096 {
                let mut page = Page::new(memory.virtual_address + i * 4096);
                page.map(memory.physical_address + i * 4096);
            }
        }
        end_no_ints(self.interrupts);
    }
}

/// A scheme resource
pub struct SchemeResource {
    /// The handle
    handle: usize,
    /// The scheme memory
    memory: SchemeMemory,
    /// Duplicate?
    _dup: usize,
    /// Internal fpath
    _fpath: usize,
    /// Internal read
    _read: usize,
    /// Internal write
    _write: usize,
    /// Internal lseek
    _lseek: usize,
    /// Internal fsync
    _fsync: usize,
    /// Internal ftruncate
    _ftruncate: usize,
    /// Internal close
    _close: usize,
}

impl SchemeResource {
    /// Check validity
    fn valid(&self, addr: usize) -> bool {
        addr >= self.memory.virtual_address && addr < self.memory.virtual_address + self.memory.virtual_size
    }
}

impl Resource for SchemeResource {
    // TODO: Clone instead?
    /// Duplicate the resource
    fn dup(&self) -> Option<Box<Resource>> {
        if self.valid(self._dup) {
            let fd;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._dup;
                fd = (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
            if fd != usize::MAX {
                //TODO: Count number of handles, don't allow drop until 0
                return Some(box SchemeResource {
                    handle: fd,
                    memory: SchemeMemory {
                        physical_address: self.memory.physical_address,
                        virtual_address: self.memory.virtual_address,
                        virtual_size: self.memory.virtual_size,
                    },
                    _dup: self._dup,
                    _fpath: self._fpath,
                    _read: self._read,
                    _write: self._write,
                    _lseek: self._lseek,
                    _fsync: self._fsync,
                    _ftruncate: self._ftruncate,
                    _close: self._close,
                });
            }
        }

        None
    }

    /// Return the url of this resource
    fn url(&self) -> Url {
        if self.valid(self._fpath) {
            let mut buf: [u8; 4096] = [0; 4096];
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._fpath;
                result = (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(self.handle, context.translate_mut(buf.as_mut_ptr()), buf.len());
                context.exit();
            }
            if result != usize::MAX {
                return Url::from_string(unsafe { String::from_utf8_unchecked(Vec::from(buf.get_slice(None, Some(result)))) });
            }
        }
        Url::new()
    }

    /// Read data to buffer
    fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
        if self.valid(self._read) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._read;
                result = (*(fn_ptr as *const extern "C" fn(usize, *mut u8, usize) -> usize))(self.handle, context.translate_mut(buf.as_mut_ptr()), buf.len());
                context.exit();
            }
            if result != usize::MAX {
                return Some(result);
            }
        }
        None
    }

    /// Write to resource
    fn write(&mut self, buf: &[u8]) -> Option<usize> {
        if self.valid(self._write) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._write;
                result = (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(self.handle, context.translate(buf.as_ptr()), buf.len());
                context.exit();
            }
            if result != usize::MAX {
                return Some(result);
            }
        }
        None
    }

    /// Seek
    fn seek(&mut self, pos: ResourceSeek) -> Option<usize> {
        if self.valid(self._lseek) {
            let offset;
            let whence;
            match pos {
                ResourceSeek::Start(off) => {
                    whence = 0;
                    offset = off as isize;
                },
                ResourceSeek::Current(off) => {
                    whence = 1;
                    offset = off;
                },
                ResourceSeek::End(off) => {
                    whence = 2;
                    offset = off;
                }
            }

            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._lseek;
                result = (*(fn_ptr as *const extern "C" fn(usize, isize, isize) -> usize))(self.handle, offset, whence);
                context.exit();
            }
            if result != usize::MAX {
                return Some(result);
            }
        }
        None
    }

    /// Sync the resource
    fn sync(&mut self) -> bool {
        if self.valid(self._fsync) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._fsync;
                result = (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
            return result == 0;
        }
        false
    }

    fn truncate(&mut self, len: usize) -> bool {
        if self.valid(self._ftruncate) {
            let result;
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._ftruncate;
                result = (*(fn_ptr as *const extern "C" fn(usize, usize) -> usize))(self.handle, len);
                context.exit();
            }
            return result == 0;
        }
        false
    }
}

impl Drop for SchemeResource {
    fn drop(&mut self){
        if self.valid(self._close) {
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._close;
                (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
        }
    }
}

/// A scheme item
pub struct SchemeItem {
    /// The URL
    url: Url,
    /// The scheme
    scheme: String,
    /// The binary for the scheme
    binary: Url,
    /// The handle
    handle: usize,
    /// The scheme memory
    memory: SchemeMemory,
    _start: usize,
    _stop: usize,
    _open: usize,
    _dup: usize,
    _fpath: usize,
    _read: usize,
    _write: usize,
    _lseek: usize,
    _fsync: usize,
    _ftruncate: usize,
    _close: usize,
    _event: usize,
}

impl SchemeItem {
    /// Load scheme item from URL
    pub fn from_url(url: &Url) -> Box<SchemeItem> {
        debugln!("{}", url.to_string());

        let mut scheme_item = box SchemeItem {
            url: url.clone(),
            scheme: String::new(),
            binary: Url::new(),
            handle: 0,
            memory: SchemeMemory {
                physical_address: 0,
                virtual_address: 0,
                virtual_size: 0,
            },
            _start: 0,
            _stop: 0,
            _open: 0,
            _dup: 0,
            _fpath: 0,
            _read: 0,
            _write: 0,
            _lseek: 0,
            _fsync: 0,
            _ftruncate: 0,
            _close: 0,
            _event: 0,
        };

        let path_parts = parse_path(url.reference(), pwd());
        if !path_parts.is_empty() {
            if let Some(part) = path_parts.get(path_parts.len() - 1) {
                scheme_item.scheme = part.clone();
                scheme_item.binary = Url::from_string(url.to_string() + part + ".bin");
            }
        }

        if let Some(mut resource) = scheme_item.binary.open() {
            let mut vec: Vec<u8> = Vec::new();
            resource.read_to_end(&mut vec);

            unsafe {
                let executable = Elf::from_data(vec.as_ptr() as usize);
                if let Some(segment) = executable.load_segment() {
                    scheme_item.memory.virtual_address = segment.vaddr as usize;
                    scheme_item.memory.virtual_size = segment.mem_len as usize;
                    scheme_item.memory.physical_address = memory::alloc(scheme_item.memory.virtual_size);

                    if scheme_item.memory.physical_address > 0 {
                        //Copy progbits
                        ::memcpy(scheme_item.memory.physical_address as *mut u8, (executable.data + segment.off as usize) as *const u8, segment.file_len as usize);
                        //Zero bss
                        ::memset((scheme_item.memory.physical_address + segment.file_len as usize) as *mut u8, 0, segment.mem_len as usize - segment.file_len as usize);
                    }

                    scheme_item._start = executable.symbol("_start");
                    scheme_item._stop = executable.symbol("_stop");
                    scheme_item._open = executable.symbol("_open");
                    scheme_item._dup = executable.symbol("_dup");
                    scheme_item._fpath = executable.symbol("_fpath");
                    scheme_item._read = executable.symbol("_read");
                    scheme_item._write = executable.symbol("_write");
                    scheme_item._lseek = executable.symbol("_lseek");
                    scheme_item._fsync = executable.symbol("_fsync");
                    scheme_item._ftruncate = executable.symbol("_ftruncate");
                    scheme_item._close = executable.symbol("_close");
                    scheme_item._event = executable.symbol("_event");
                } else {
                    debug::d("Invalid ELF\n");
                }
            }
        }

        if scheme_item.valid(scheme_item._start) {
            //TODO: Allow schemes to be called inside of other schemes
            unsafe {
                let context = SchemeContext::enter(&scheme_item.memory);
                let fn_ptr: *const usize = &scheme_item._start;
                scheme_item.handle = (*(fn_ptr as *const extern "C" fn() -> usize))();
                context.exit();
            }
        }

        scheme_item
    }

    /// Check validity
    fn valid(&self, addr: usize) -> bool {
        addr >= self.memory.virtual_address && addr < self.memory.virtual_address + self.memory.virtual_size
    }
}

impl KScheme for SchemeItem {
    fn scheme(&self) -> &str {
        return &self.scheme;
    }

    //TODO: Hack for orbital
    fn event(&mut self, event: &Event){
        if self.valid(self._event) {
            unsafe {
                let event_ptr: *const Event = event;

                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._event;
                (*(fn_ptr as *const extern "C" fn(usize, usize)))(self.handle, event_ptr as usize);
                context.exit();
            }
        }
    }

    fn open(&mut self, url: &Url, flags: usize) -> Option<Box<Resource>> {
        if self.valid(self._open) {
            let fd;
            unsafe {
                let c_str = url.to_string() + "\0";

                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._open;
                fd = (*(fn_ptr as *const extern "C" fn(usize, *const u8, usize) -> usize))(self.handle, context.translate(c_str.as_ptr()), flags);
                context.exit();
            }
            if fd != usize::MAX {
                //TODO: Count number of handles, don't allow drop until 0
                return Some(box SchemeResource {
                    handle: fd,
                    memory: SchemeMemory {
                        physical_address: self.memory.physical_address,
                        virtual_address: self.memory.virtual_address,
                        virtual_size: self.memory.virtual_size,
                    },
                    _dup: self._dup,
                    _fpath: self._fpath,
                    _read: self._read,
                    _write: self._write,
                    _lseek: self._lseek,
                    _fsync: self._fsync,
                    _ftruncate: self._ftruncate,
                    _close: self._close,
                });
            }
        }

        None
    }
}

impl Drop for SchemeItem {
    fn drop(&mut self) {
        if self.valid(self._stop) {
            unsafe {
                let context = SchemeContext::enter(&self.memory);
                let fn_ptr: *const usize = &self._stop;
                (*(fn_ptr as *const extern "C" fn(usize) -> usize))(self.handle);
                context.exit();
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

use self::serde::ser::Serialize;
use self::serde_json::Value;
use model::game::Id;
use model::comp::Actor;
use std::fmt::Debug;

#[derive(Debug, Clone, Serialize)]
pub enum OpCode {
    Greeting,
    Connect,
    Disconnect,
    WorldUpdate,
}

#[derive(Debug, Clone, Serialize)]
pub struct Message<T>
where
    T: Serialize + Debug,
{
    pub opcode: OpCode,
    pub payload: T,
}
impl Message<Vec<Value>> {
    pub fn new_greeting(own_id: &Id, actors: &Vec<&Actor>) -> Self {
        Message {
            opcode: OpCode::Greeting,
            payload: vec![json!(own_id), json!(actors)]
        }
    }
}
impl Message<Value> {
    pub fn new_connection(new_actor: &Actor) -> Self {
        Message {
            opcode: OpCode::Connect,
            payload: json!(new_actor)
        }
    }
    pub fn new_disconnect(id: &Id) -> Self {
        Message {
            opcode: OpCode::Disconnect,
            payload: json!(id)
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
pub enum Key {
    ArrowUp,
    ArrowDown,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct KeyState {
    pub id: i32,
    pub key: Key,
    pub pressed: bool,
}
<commit_msg>Core: Run rustfmt<commit_after>extern crate serde;
extern crate serde_json;

use self::serde::ser::Serialize;
use self::serde_json::Value;
use model::game::Id;
use model::comp::Actor;
use std::fmt::Debug;

#[derive(Debug, Clone, Serialize)]
pub enum OpCode {
    Greeting,
    Connect,
    Disconnect,
    WorldUpdate,
}

#[derive(Debug, Clone, Serialize)]
pub struct Message<T>
where
    T: Serialize + Debug,
{
    pub opcode: OpCode,
    pub payload: T,
}
impl Message<Vec<Value>> {
    pub fn new_greeting(own_id: &Id, actors: &Vec<&Actor>) -> Self {
        Message {
            opcode: OpCode::Greeting,
            payload: vec![json!(own_id), json!(actors)],
        }
    }
}
impl Message<Value> {
    pub fn new_connection(new_actor: &Actor) -> Self {
        Message {
            opcode: OpCode::Connect,
            payload: json!(new_actor),
        }
    }
    pub fn new_disconnect(id: &Id) -> Self {
        Message {
            opcode: OpCode::Disconnect,
            payload: json!(id),
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)]
pub enum Key {
    ArrowUp,
    ArrowDown,
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct KeyState {
    pub id: i32,
    pub key: Key,
    pub pressed: bool,
}
<|endoftext|>


<commit_before>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//

use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;
use std::{ fmt
         , iter
         };
use std::fmt::Write;
use std::rc::Rc;

use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        , ScopedState
                        , Scoped
                        };
use super::types;
use super::SymbolTable;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated<'a
               , Form<'a, S>
               , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a
                   , Binding<'a, S>
                   , S>>;

macro_rules! concat_exprs {
    ($it:expr, $level:expr) => {
        $it.iter()
           .fold(String::new(), |mut s, expr| {
                 write!(s, " {} ", expr.to_sexpr($level))
                     .expect("Could not write to string!");
                 s
            })
        }
}

/// Trait for a node in the abstract syntax tree.
///
/// This provides a visitor method for semantic analysis (which may be split
/// into multiple transforms later), and a method for formatting the AST node
/// as an S-expression.
pub trait Node {

   /// Pretty-print the AST node as an S-expression at the desired
   /// indentation level.]
   ///
   /// Note that this prints the desugared form and may not be a perfect
   /// match for the original source code.
   fn to_sexpr(&self, level: usize) -> String;

}

impl fmt::Display for Node + Sized {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_sexpr(0))
    }
}

pub trait AnnotateTypes<'a>: Sized {

   #[allow(unused_variables)]
   fn annotate_types(self, scope: SymbolTable) -> Scoped<'a, Self> {
       unimplemented!() //TODO: implement
   }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Module<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub exporting: Vec<Ident>
  , pub body: Body<'a, S>
}

impl<'a, S> Module<'a, S> where S: ScopednessTypestate {

    /// Returns true if the namespace is exporting any nages
    #[inline] pub fn is_lib (&self) -> bool { !self.exporting.is_empty() }

}

impl<'a> Scoped<'a, Module<'a, ScopedState>>{

    pub fn contains_name<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>
        , String: PartialEq<Q>
        , Q: Hash + Eq
    {
        self.is_defined_here(name) &&
        self.node.exporting
            .iter()
            .find(|ref i| &i.value == name)
            .is_some()
    }

}

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    // TODO: maybe definitions aren't expressions?
    // (they don't return a value...)
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
  , Logical(Logical<'a, S>)
  , Lit(Literal)
  , NameRef(NameRef)
}

#[derive(PartialEq, Clone, Debug)]
pub enum NameRef { Owned(Ident)
                 , Borrowed(Ident)
                 , Deref(Ident)
                 , Unique(Ident)
                 }

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: types::Type
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Class<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub ty_param: Ident
  , pub defs: Vec<Prototype<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Instance<'a, S: ScopednessTypestate> {
    pub class: Ident
  , pub ty: types::Type
  , pub functions: Vec<Function<'a, S>>
}

/// Logical `and` and `or` expressions
///
/// The general expectation is that these will generally be parsed as infix.
#[derive(PartialEq, Clone, Debug)]
pub enum Logical<'a, S: ScopednessTypestate> {
    And { a: Rc<Expr<'a, S>>
        , b: Rc<Expr<'a, S>>
        }
  , Or { a: Rc<Expr<'a, S>>
       , b: Rc<Expr<'a, S>>
       }
}

#[derive(PartialEq, Clone, Debug)]
pub enum Literal { IntConst(i64)
                 , UintConst(u64)
                 }

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Literal::IntConst(ref n)    => write!(f, "{}", n)
                    , Literal::UintConst(ref n)   => write!(f, "{}", n)
                    }
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: types::Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub sig: types::Signature
  , pub equations: Vec<Equation<'a, S>>
}

/// A pattern is a vector of pattern elements.
///
/// When entering a function scope that binds using patterns, we should
/// check that the pattern's length matches the arity of the function,
/// until autocurrying is implemented (after the Glorious Revolution).
pub type Pattern = Vec<PatElement>;

impl Node for Pattern {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       format!( "({})", concat_exprs!(self, level) )
   }

}

/// An element in a pattern-matching expression.
///
/// A pattern element can be a name binding, a typed name binding,
/// a literal, or the magic underscore (anything). Destructuring bind
/// will come later, as will equality.
#[derive(PartialEq, Clone, Debug)]
pub enum PatElement { // eventually this could just be implemented using an Expr,
                      // but it's currently this way because the types of patterns
                      // that you can write are currently quite limited
                      Name(Ident)
                    , Typed { name: Ident, ty: types::Type }
                    , Lit(Literal)
                      // TODO: write literal types for other things (i.e. lists)
                    , Anything
                    }

impl Node for PatElement {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           PatElement::Name(ref n) => n.to_sexpr(level)
         , PatElement::Typed { ref name, ref ty } =>
            format!( "{}: {}"
                   , name.to_sexpr(level)
                   , ty )
        , PatElement::Lit(ref c) => format!("{}", c)
        , PatElement::Anything => String::from("_")
       }
   }

}

/// A function equation definition
#[derive(PartialEq, Clone, Debug)]
pub struct Equation<'a, S: ScopednessTypestate> {
    pub pattern: Pattern
 ,  pub body: Body<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Prototype<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
}

pub type Variant<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a, Formal, S>>;

#[derive(PartialEq, Clone, Debug)]
pub struct Data<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub variants: HashMap<Ident, Variant<'a, S>>
}

// #[derive(PartialEq, Clone, Debug)]
// pub enum Data<'a, S: ScopednessTypestate> {
//     Sum { name: Ident
//         , variants: Vec<Type> }
//   , Product { name: Ident
//             , fields: Vec<Binding<'a, S>> }
// }

impl<'a, S> Data<'a, S>
where S: ScopednessTypestate {

    /// Returns true if this ADT is a sum type
    pub fn is_sum_type(&self) -> bool {
        self.variants.len() > 1
    }

    /// Returns true if this ADT is a product type
    #[inline] pub fn is_product_type(&self) -> bool {
        !self.is_sum_type()
    }

    /// Returns the fields of a product type.
    ///
    /// # Returns
    ///  + A `Some<Vec<Annotated<'a, Formal, S>>>` representing
    ///    this type's fields, if this is the definition of a
    ///    product type.
    ///  + Otherwise, `None`
    pub fn get_product_fields(&self) -> Option<&Variant<'a, S>> {
        self.variants.get(&self.name)
    }
}

impl<'a, S> Node for Form<'a, S>
where S: ScopednessTypestate {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           Form::Define(ref form)  => form.to_sexpr(level)
         , Form::Let(ref form)     => form.to_sexpr(level)
         , Form::If { .. }         => unimplemented!()
         , Form::Call { ref fun, ref body } =>
               format!( "({}{})"
                      , fun.to_sexpr(level)
                      , concat_exprs!(body, level) )
         , Form::Lambda(ref fun)   => fun.to_sexpr(level)
         , Form::Logical(ref form) => form.to_sexpr(level)
         , Form::Lit(ref c)   => format!("{}", c)
         , Form::NameRef(ref n)    => n.to_sexpr(level)
       }
   }

}

impl<'a, S> Node for DefForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            DefForm::TopLevel { ref name, ref annot, ref value } =>
                format!("{}(define {} {} {})"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , annot
                  , value.to_sexpr(level + 1)
                  )
          , DefForm::Function { ref name, ref fun } =>
                format!("{}(define {} {}\n)"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , fun.to_sexpr(level)
                  )
        }
    }

}

impl<'a, S> Node for LetForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            LetForm::Let { ref bindings, ref body } =>
                format!("{}(let [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                                 })
                    , concat_exprs!(body, level + 1)
                    )
          , LetForm::LetRec { ref bindings, ref body } =>
                format!("{}(letrec [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                               })
                    , concat_exprs!(body, level + 1)
                    )
          , LetForm::LetSplat { ref bindings, ref body } =>
                format!("{}(let* [{}]\n{})"
                    , indent!(level)
                    , bindings.iter()
                              .fold(String::new(), |mut s, binding| {
                                    write!(s, "{}\n", binding.to_sexpr(level))
                                        .expect("Could not write to string!");
                                    s
                               })
                    , concat_exprs!(body, level + 1)
                    )
          , _ => unimplemented!()
        }
    }

}

impl<'a, S> Node for Logical<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            Logical::And { ref a, ref b } =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
         ,  Logical::Or { ref a, ref b }  =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
        }
    }
}

impl<'a, S> Node for Function<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl<'a, S> Node for Binding<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl Node for Formal {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        format!("{}: {}", *(self.name), *(self.annot))
    }

}

impl Node for NameRef {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self  { NameRef::Owned(ref name)      => format!("{}", **name)
                     , NameRef::Borrowed(ref name)   => format!("&{}", **name)
                     , NameRef::Deref(ref name)      => format!("*{}", **name)
                     , NameRef::Unique(ref name)     => format!("@{}", **name)
                     }

    }
}

impl Node for Ident {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String { self.value.clone() }

}
<commit_msg>concat_exprs!() actually works now<commit_after>//
// Mnemosyne: a functional systems programming language.
// (c) 2015 Hawk Weisman
//
// Mnemosyne is released under the MIT License. Please refer to
// the LICENSE file at the top-level directory of this distribution
// or at https://github.com/hawkw/mnemosyne/.
//

use std::borrow::Borrow;
use std::collections::HashMap;
use std::hash::Hash;
use std::{ fmt
         , iter
         };
use std::fmt::Write;
use std::rc::Rc;

use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        , ScopedState
                        , Scoped
                        };
use super::types;
use super::SymbolTable;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated<'a
               , Form<'a, S>
               , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a
                   , Binding<'a, S>
                   , S>>;

macro_rules! concat_exprs {
    ($it:expr, $level:expr) => {
        $it.iter()
           .map(|expr| expr.to_sexpr($level) )
           .collect::<Vec<String>>() // todo: remove temp. vector
           .join(" ")
        };
    ($it:expr, $level:expr, $sep:expr) => {
        $it.iter()
           .map(|expr| expr.to_sexpr($level) )
           .collect::<Vec<String>>() // todo: remove temp. vector
           .join($sep)
        }
}

/// Trait for a node in the abstract syntax tree.
///
/// This provides a visitor method for semantic analysis (which may be split
/// into multiple transforms later), and a method for formatting the AST node
/// as an S-expression.
pub trait Node {

   /// Pretty-print the AST node as an S-expression at the desired
   /// indentation level.]
   ///
   /// Note that this prints the desugared form and may not be a perfect
   /// match for the original source code.
   fn to_sexpr(&self, level: usize) -> String;

}

impl fmt::Display for Node + Sized {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.to_sexpr(0))
    }
}

pub trait AnnotateTypes<'a>: Sized {

   #[allow(unused_variables)]
   fn annotate_types(self, scope: SymbolTable) -> Scoped<'a, Self> {
       unimplemented!() //TODO: implement
   }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Module<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub exporting: Vec<Ident>
  , pub body: Body<'a, S>
}

impl<'a, S> Module<'a, S> where S: ScopednessTypestate {

    /// Returns true if the namespace is exporting any nages
    #[inline] pub fn is_lib (&self) -> bool { !self.exporting.is_empty() }

}

impl<'a> Scoped<'a, Module<'a, ScopedState>>{

    pub fn contains_name<Q: ?Sized>(&self, name: &Q) -> bool
    where String: Borrow<Q>
        , String: PartialEq<Q>
        , Q: Hash + Eq
    {
        self.is_defined_here(name) &&
        self.node.exporting
            .iter()
            .find(|ref i| &i.value == name)
            .is_some()
    }

}

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    // TODO: maybe definitions aren't expressions?
    // (they don't return a value...)
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
  , Logical(Logical<'a, S>)
  , Lit(Literal)
  , NameRef(NameRef)
}

#[derive(PartialEq, Clone, Debug)]
pub enum NameRef { Owned(Ident)
                 , Borrowed(Ident)
                 , Deref(Ident)
                 , Unique(Ident)
                 }

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: types::Type
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Class<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub ty_param: Ident
  , pub defs: Vec<Prototype<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Instance<'a, S: ScopednessTypestate> {
    pub class: Ident
  , pub ty: types::Type
  , pub functions: Vec<Function<'a, S>>
}

/// Logical `and` and `or` expressions
///
/// The general expectation is that these will generally be parsed as infix.
#[derive(PartialEq, Clone, Debug)]
pub enum Logical<'a, S: ScopednessTypestate> {
    And { a: Rc<Expr<'a, S>>
        , b: Rc<Expr<'a, S>>
        }
  , Or { a: Rc<Expr<'a, S>>
       , b: Rc<Expr<'a, S>>
       }
}

#[derive(PartialEq, Clone, Debug)]
pub enum Literal { IntConst(i64)
                 , UintConst(u64)
                 }

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self { Literal::IntConst(ref n)    => write!(f, "{}", n)
                    , Literal::UintConst(ref n)   => write!(f, "{}", n)
                    }
    }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: types::Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub sig: types::Signature
  , pub equations: Vec<Equation<'a, S>>
}

/// A pattern is a vector of pattern elements.
///
/// When entering a function scope that binds using patterns, we should
/// check that the pattern's length matches the arity of the function,
/// until autocurrying is implemented (after the Glorious Revolution).
pub type Pattern = Vec<PatElement>;

impl Node for Pattern {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       format!( "({})", concat_exprs!(self, level) )
   }

}

/// An element in a pattern-matching expression.
///
/// A pattern element can be a name binding, a typed name binding,
/// a literal, or the magic underscore (anything). Destructuring bind
/// will come later, as will equality.
#[derive(PartialEq, Clone, Debug)]
pub enum PatElement { // eventually this could just be implemented using an Expr,
                      // but it's currently this way because the types of patterns
                      // that you can write are currently quite limited
                      Name(Ident)
                    , Typed { name: Ident, ty: types::Type }
                    , Lit(Literal)
                      // TODO: write literal types for other things (i.e. lists)
                    , Anything
                    }

impl Node for PatElement {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           PatElement::Name(ref n) => n.to_sexpr(level)
         , PatElement::Typed { ref name, ref ty } =>
            format!( "{}: {}"
                   , name.to_sexpr(level)
                   , ty )
        , PatElement::Lit(ref c) => format!("{}", c)
        , PatElement::Anything => String::from("_")
       }
   }

}

/// A function equation definition
#[derive(PartialEq, Clone, Debug)]
pub struct Equation<'a, S: ScopednessTypestate> {
    pub pattern: Pattern
 ,  pub body: Body<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Prototype<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
}

pub type Variant<'a, S: ScopednessTypestate>
    = Vec<Annotated<'a, Formal, S>>;

#[derive(PartialEq, Clone, Debug)]
pub struct Data<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub variants: HashMap<Ident, Variant<'a, S>>
}

// #[derive(PartialEq, Clone, Debug)]
// pub enum Data<'a, S: ScopednessTypestate> {
//     Sum { name: Ident
//         , variants: Vec<Type> }
//   , Product { name: Ident
//             , fields: Vec<Binding<'a, S>> }
// }

impl<'a, S> Data<'a, S>
where S: ScopednessTypestate {

    /// Returns true if this ADT is a sum type
    pub fn is_sum_type(&self) -> bool {
        self.variants.len() > 1
    }

    /// Returns true if this ADT is a product type
    #[inline] pub fn is_product_type(&self) -> bool {
        !self.is_sum_type()
    }

    /// Returns the fields of a product type.
    ///
    /// # Returns
    ///  + A `Some<Vec<Annotated<'a, Formal, S>>>` representing
    ///    this type's fields, if this is the definition of a
    ///    product type.
    ///  + Otherwise, `None`
    pub fn get_product_fields(&self) -> Option<&Variant<'a, S>> {
        self.variants.get(&self.name)
    }
}

impl<'a, S> Node for Form<'a, S>
where S: ScopednessTypestate {
   #[allow(unused_variables)]
   fn to_sexpr(&self, level: usize) -> String {
       match *self {
           Form::Define(ref form)  => form.to_sexpr(level)
         , Form::Let(ref form)     => form.to_sexpr(level)
         , Form::If { .. }         => unimplemented!()
         , Form::Call { ref fun, ref body } =>
               format!( "({} {})"
                      , fun.to_sexpr(level)
                      , concat_exprs!(body, level) )
         , Form::Lambda(ref fun)   => fun.to_sexpr(level)
         , Form::Logical(ref form) => form.to_sexpr(level)
         , Form::Lit(ref c)   => format!("{}", c)
         , Form::NameRef(ref n)    => n.to_sexpr(level)
       }
   }

}

impl<'a, S> Node for DefForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            DefForm::TopLevel { ref name, ref annot, ref value } =>
                format!("{}(define {} {} {})"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , annot
                  , value.to_sexpr(level + 1)
                  )
          , DefForm::Function { ref name, ref fun } =>
                format!("{}(define {} {}\n)"
                  , indent!(level)
                  , name.to_sexpr(level)
                  , fun.to_sexpr(level)
                  )
        }
    }

}

impl<'a, S> Node for LetForm<'a, S>
where S: ScopednessTypestate {

    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            LetForm::Let { ref bindings, ref body } =>
                format!("{}(let [{}]\n{})"
                    , indent!(level)
                    , concat_exprs!(bindings, level, "\n")
                    , concat_exprs!(body, level + 1)
                    )
          , LetForm::LetRec { ref bindings, ref body } =>
                format!("{}(letrec [{}]\n{})"
                    , indent!(level)
                    , concat_exprs!(bindings, level, "\n")
                    , concat_exprs!(body, level + 1)
                    )
          , LetForm::LetSplat { ref bindings, ref body } =>
                format!("{}(let* [{}]\n{})"
                    , indent!(level)
                    , concat_exprs!(bindings, level, "\n")
                    , concat_exprs!(body, level + 1)
                    )
          , _ => unimplemented!()
        }
    }

}

impl<'a, S> Node for Logical<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self {
            Logical::And { ref a, ref b } =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
         ,  Logical::Or { ref a, ref b }  =>
                format!( "(and {} {})"
                       , a.to_sexpr(level)
                       , b.to_sexpr(level)
                       )
        }
    }
}

impl<'a, S> Node for Function<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl<'a, S> Node for Binding<'a, S>
where S: ScopednessTypestate
{
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        unimplemented!()
    }
}

impl Node for Formal {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        format!("{}: {}", *(self.name), *(self.annot))
    }

}

impl Node for NameRef {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String {
        match *self  { NameRef::Owned(ref name)      => format!("{}", **name)
                     , NameRef::Borrowed(ref name)   => format!("&{}", **name)
                     , NameRef::Deref(ref name)      => format!("*{}", **name)
                     , NameRef::Unique(ref name)     => format!("@{}", **name)
                     }

    }
}

impl Node for Ident {
    #[allow(unused_variables)]
    fn to_sexpr(&self, level: usize) -> String { self.value.clone() }

}
<|endoftext|>


<commit_before>// This lexer is based on the grammar I found here: https://github.com/antlr/grammars-v4/blob/master/asm6502/asm6502.g4
// It looks like it matches the various 6502 assembly examples I have seen online.

use std;
use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::str;

use assembler::token::{ImmediateBase, Token};
use ::opcodes::OpCode;

#[derive(Debug, PartialEq)]
pub struct LexerError {
    pub message: String,
}

impl LexerError {
    fn unexpected_ident<A, B>(expected: A, found: B) -> LexerError
        where A: std::fmt::Display,
              B: std::fmt::Display
    {
        LexerError {
            message: format!("ERR: Unexpected identifier. Found '{}', expected '{}'",
                             found,
                             expected),
        }
    }
}

impl From<std::io::Error> for LexerError {
    fn from(error: std::io::Error) -> LexerError {
        LexerError { message: error.description().into() }
    }
}

impl From<String> for LexerError {
    fn from(error: String) -> LexerError {
        LexerError { message: error }
    }
}

impl<'a> From<&'a str> for LexerError {
    fn from(error: &str) -> LexerError {
        LexerError { message: error.into() }
    }
}

/// Lexer accepts the program code as a string
/// and converts it to a list of Tokens
pub struct Lexer;

impl Lexer {
    /// Returns a vector of Tokens given an input of
    /// 6502 assembly code
    pub fn lex_string<S>(input: S) -> Result<Vec<Vec<Token>>, LexerError>
        where S: Into<String>
    {
        Ok(Self::lex(input.into())?)
    }

    /// Returns a vector of Tokens given a file
    /// to load 6502 assembly code from
    pub fn lex_file<P>(path: P) -> Result<Vec<Vec<Token>>, LexerError>
        where P: AsRef<std::path::Path>
    {
        let mut file = File::open(&path)?;
        let mut contents = String::new();

        file.read_to_string(&mut contents)?;

        Ok(Self::lex(contents)?)
    }

    /// Performs the bulk of the lexing logic
    fn lex(source: String) -> Result<Vec<Vec<Token>>, LexerError> {

        let mut result = Vec::new();

        for line in source.lines() {
            if line.trim().len() == 0 {
                continue;
            }
            let mut tokens = Vec::new();
            let mut idx = 0;
            let line = &line[..].as_bytes();
            while idx < line.len() {
                let c = line[idx] as char;
                if c.is_alphanumeric() {
                    let token = Self::consume_alphanumeric(&mut idx, line)?;
                    tokens.push(token);
                } else if c == '#' {
                    let token = Self::consume_immediate(&mut idx, line)?;
                    tokens.push(token);
                } else if c == '.' {
                    idx += 1;
                    let token = Self::consume_alphanumeric(&mut idx, line)?;
                    if let Token::Label(label) = token {
                        tokens.push(Token::Directive(label));
                    }
                } else {
                    idx += 1;
                }
            }

            result.push(tokens);
        }

        Ok(result)
    }

    fn consume_alphanumeric(idx: &mut usize, line: &[u8]) -> Result<Token, LexerError> {
        let mut tok = String::new();

        while *idx < line.len() {
            let c = line[*idx] as char;
            if c.is_whitespace() || c == ';' || c == ':' || c == '\n' {
                return Ok(Self::classify(&tok));
            } else {
                tok.push(c);
            }

            *idx += 1;
        }

        Err("ERR: An error occurred while consuming an alphanumeric identifier".into())
    }

    fn consume_immediate(idx: &mut usize, line: &[u8]) -> Result<Token, LexerError> {
        let mut tok = String::new();
        // Very next character should be a dollar sign
        let c = line[*idx + 0x01] as char;
        let mut base = ImmediateBase::Base16;
        if c != '$' {
            let mut c = line[*idx + 0x02] as char;
            if c.is_digit(10) {
                *idx += 0x02;
                base = ImmediateBase::Base10;
                // Consume every number
                while !c.is_digit(10) {
                    c = line[*idx] as char;
                    tok.push(c);
                }

                return Ok(Token::Immediate(tok.clone(), base));
            } else {
                return Err(LexerError::unexpected_ident("{digit}", line[*idx + 0x01] as char));
            }
        }

        let c = line[*idx + 0x02] as char;
        if c.is_digit(16) {
            tok.push(c as char);
        } else {
            return Err(LexerError::unexpected_ident("{hex_digit}", c));
        }

        let c = line[*idx + 0x03] as char;
        if c.is_digit(16) {
            let val = &line[*idx + 0x02..*idx + 0x04];
            *idx += 0x04;
            return Ok(Token::Immediate(str::from_utf8(val).unwrap().into(), base));
        } else {
            return Err(LexerError::unexpected_ident("{hex_digit}", c));
        }

        Err("An error occurred while consuming an immediate identifier".into())
    }

    fn classify(input: &str) -> Token {
        let mut tok = String::from(input);
        if let Some(opcode) = OpCode::from_mnemonic(tok.clone()) {
            Token::OpCode(tok.clone())
        } else {
            Token::Label(input.into())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ::assembler::token::{ImmediateBase, Token};

    #[test]
    fn can_classify_simple_labels_and_opcodes() {
        let tokens = Lexer::lex_string("
            LDA #$20
        ")
            .unwrap();

        assert_eq!(&[Token::OpCode("LDA".into()),
                     Token::Immediate("20".into(), ImmediateBase::Base16)],
                   &tokens[0][..]);
    }

    #[test]
    fn does_not_classify_unknown_labels_and_opcodes() {
        let tokens = Lexer::lex_string("
            .LOL LDA #$20
        ")
            .unwrap();

        assert_eq!(&[Token::Directive("LOL".into()),
                     Token::OpCode("LDA".into()),
                     Token::Immediate("20".into(), ImmediateBase::Base16)],
                   &tokens[0][..]);
    }

    #[test]
    fn can_classify_labels() {
        let tokens = Lexer::lex_string("MAIN: LDA #$20").unwrap();

        assert_eq!(&[Token::Label("MAIN".into()),
                     Token::OpCode("LDA".into()),
                     Token::Immediate("20".into(), ImmediateBase::Base16)],
                   &tokens[0][..]);
    }

    #[test]
    fn immediate_values_throw_errors_when_invalid() {
        assert_eq!(Lexer::lex_string("
            LDA #$INVALID20
        "),
                   Err(LexerError::unexpected_ident("{hex_digit}", "I")));
    }

    #[test]
    fn immediate_values_throw_errors_when_invalid_hex_code() {
        assert_eq!(Lexer::lex_string("
            LDA #$2Z
        "),
                   Err(LexerError::unexpected_ident("{hex_digit}", "Z")));
    }

    #[test]
    fn immediate_values_throw_errors_when_not_even_a_hex_code() {
        assert_eq!(Lexer::lex_string("
            LDA #@hotmail.com
        "),
                   Err(LexerError::unexpected_ident("{digit}", "@")));
    }
}
<commit_msg>Add tests for base 10 immediate values<commit_after>// This lexer is based on the grammar I found here: https://github.com/antlr/grammars-v4/blob/master/asm6502/asm6502.g4
// It looks like it matches the various 6502 assembly examples I have seen online.

use std;
use std::error::Error;
use std::fs::File;
use std::io::{self, Read};
use std::str;

use assembler::token::{ImmediateBase, Token};
use ::opcodes::OpCode;

#[derive(Debug, PartialEq)]
pub struct LexerError {
    pub message: String,
}

impl LexerError {
    fn unexpected_ident<A, B>(expected: A, found: B) -> LexerError
        where A: std::fmt::Display,
              B: std::fmt::Display
    {
        LexerError {
            message: format!("ERR: Unexpected identifier. Found '{}', expected '{}'",
                             found,
                             expected),
        }
    }
}

impl From<std::io::Error> for LexerError {
    fn from(error: std::io::Error) -> LexerError {
        LexerError { message: error.description().into() }
    }
}

impl From<String> for LexerError {
    fn from(error: String) -> LexerError {
        LexerError { message: error }
    }
}

impl<'a> From<&'a str> for LexerError {
    fn from(error: &str) -> LexerError {
        LexerError { message: error.into() }
    }
}

/// Lexer accepts the program code as a string
/// and converts it to a list of Tokens
pub struct Lexer;

impl Lexer {
    /// Returns a vector of Tokens given an input of
    /// 6502 assembly code
    pub fn lex_string<S>(input: S) -> Result<Vec<Vec<Token>>, LexerError>
        where S: Into<String>
    {
        Ok(Self::lex(input.into())?)
    }

    /// Returns a vector of Tokens given a file
    /// to load 6502 assembly code from
    pub fn lex_file<P>(path: P) -> Result<Vec<Vec<Token>>, LexerError>
        where P: AsRef<std::path::Path>
    {
        let mut file = File::open(&path)?;
        let mut contents = String::new();

        file.read_to_string(&mut contents)?;

        Ok(Self::lex(contents)?)
    }

    /// Performs the bulk of the lexing logic
    fn lex(source: String) -> Result<Vec<Vec<Token>>, LexerError> {

        let mut result = Vec::new();

        for line in source.lines() {
            if line.trim().len() == 0 {
                continue;
            }
            let mut tokens = Vec::new();
            let mut idx = 0;
            let line = &line[..].as_bytes();
            while idx < line.len() {
                let c = line[idx] as char;
                if c.is_alphanumeric() {
                    let token = Self::consume_alphanumeric(&mut idx, line)?;
                    tokens.push(token);
                } else if c == '#' {
                    let token = Self::consume_immediate(&mut idx, line)?;
                    tokens.push(token);
                } else if c == '.' {
                    idx += 1;
                    let token = Self::consume_alphanumeric(&mut idx, line)?;
                    if let Token::Label(label) = token {
                        tokens.push(Token::Directive(label));
                    }
                } else {
                    idx += 1;
                }
            }

            result.push(tokens);
        }

        Ok(result)
    }

    fn consume_alphanumeric(idx: &mut usize, line: &[u8]) -> Result<Token, LexerError> {
        let mut tok = String::new();

        while *idx < line.len() {
            let c = line[*idx] as char;
            if c.is_whitespace() || c == ';' || c == ':' || c == '\n' {
                return Ok(Self::classify(&tok));
            } else {
                tok.push(c);
            }

            *idx += 1;
        }

        Err("ERR: An error occurred while consuming an alphanumeric identifier".into())
    }

    fn consume_immediate(idx: &mut usize, line: &[u8]) -> Result<Token, LexerError> {
        let mut tok = String::new();
        *idx += 1;
        let mut c = line[*idx] as char;
        let mut base = ImmediateBase::Base16;

        // Very next character should be a dollar sign
        if c != '$' {
            if c.is_digit(10) {
                base = ImmediateBase::Base10;
                // Consume every number
                loop {
                    if c.is_digit(10) {
                        tok.push(c);
                        *idx += 1;
                        if *idx < line.len() {
                            c = line[*idx] as char;
                        } else {
                            break;
                        }
                    } else {
                        return Err(LexerError::unexpected_ident("{digit}", c));
                    }
                }

                return Ok(Token::Immediate(tok.clone(), base));
            } else {
                return Err(LexerError::unexpected_ident("{digit}", c));
            }
        }

        *idx += 1;
        let c = line[*idx] as char;
        if c.is_digit(16) {
            tok.push(c as char);
        } else {
            return Err(LexerError::unexpected_ident("{hex_digit}", c));
        }

        *idx += 1;
        let c = line[*idx] as char;
        if c.is_digit(16) {
            tok.push(c);
            *idx += 0x02;
            return Ok(Token::Immediate(str::from_utf8(&tok[..].as_bytes()).unwrap().into(), base));
        } else {
            return Err(LexerError::unexpected_ident("{hex_digit}", c));
        }

        Err("An error occurred while consuming an immediate identifier".into())
    }

    fn classify(input: &str) -> Token {
        let mut tok = String::from(input);
        if let Some(opcode) = OpCode::from_mnemonic(tok.clone()) {
            Token::OpCode(tok.clone())
        } else {
            Token::Label(input.into())
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ::assembler::token::{ImmediateBase, Token};

    #[test]
    fn can_classify_simple_labels_and_opcodes() {
        let tokens = Lexer::lex_string("
            LDA #$20
        ")
            .unwrap();

        assert_eq!(&[Token::OpCode("LDA".into()),
                     Token::Immediate("20".into(), ImmediateBase::Base16)],
                   &tokens[0][..]);
    }

    #[test]
    fn does_not_classify_unknown_labels_and_opcodes() {
        let tokens = Lexer::lex_string("
            .LOL LDA #$20
        ")
            .unwrap();

        assert_eq!(&[Token::Directive("LOL".into()),
                     Token::OpCode("LDA".into()),
                     Token::Immediate("20".into(), ImmediateBase::Base16)],
                   &tokens[0][..]);
    }

    #[test]
    fn can_classify_labels() {
        let tokens = Lexer::lex_string("MAIN: LDA #$20").unwrap();

        assert_eq!(&[Token::Label("MAIN".into()),
                     Token::OpCode("LDA".into()),
                     Token::Immediate("20".into(), ImmediateBase::Base16)],
                   &tokens[0][..]);
    }

    #[test]
    fn immediate_values_throw_errors_when_invalid() {
        assert_eq!(Lexer::lex_string("
            LDA #$INVALID20
        "),
                   Err(LexerError::unexpected_ident("{hex_digit}", "I")));
    }

    #[test]
    fn immediate_values_throw_errors_when_invalid_hex_code() {
        assert_eq!(Lexer::lex_string("
            LDA #$2Z
        "),
                   Err(LexerError::unexpected_ident("{hex_digit}", "Z")));
    }

    #[test]
    fn immediate_values_throw_errors_when_not_even_a_hex_code() {
        assert_eq!(Lexer::lex_string("
            LDA #@hotmail.com
        "),
                   Err(LexerError::unexpected_ident("{digit}", "@")));
    }

    #[test]
    fn immediate_values_accept_base_ten() {
        let tokens = Lexer::lex_string("LDA #10").unwrap();
        assert_eq!(&[Token::OpCode("LDA".into()),
                     Token::Immediate("10".into(), ImmediateBase::Base10)],
                   &tokens[0][..]);
    }

    #[test]
    fn immediate_values_base_ten_does_not_accept_hex() {
        assert_eq!(Lexer::lex_string("LDA #1A"),
                   Err(LexerError::unexpected_ident("{digit}", "A")));
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate evo;
extern crate petgraph;
extern crate graph_annealing;
extern crate clap;
extern crate crossbeam;
extern crate simple_parallel;
extern crate num_cpus;
extern crate pcg;
extern crate graph_sgf;
extern crate triadic_census;
extern crate time;
extern crate serde_json;
extern crate sexp;

use sexp::{Atom, Sexp, atom_i, atom_f, atom_s, list};

use std::f32;
use std::fmt::Debug;
use std::str::FromStr;
use clap::{App, Arg};
use rand::{Rng, SeedableRng};
use rand::distributions::{IndependentSample, Range};
use rand::os::OsRng;
use pcg::PcgRng;

use evo::Probability;
use evo::nsga2::{self, FitnessEval, MultiObjective3};
use graph_annealing::repr::edge_ops_genome::{EdgeOpsGenome, parse_weighted_op_list, random_genome,
                                             to_weighted_vec};
use graph_annealing::helper::draw_graph;
use graph_annealing::goal::Goal;
use graph_annealing::owned_weighted_choice::OwnedWeightedChoice;
use simple_parallel::Pool;

use petgraph::{Directed, Graph};
use graph_sgf::{PetgraphReader, Unweighted};
use triadic_census::OptDenseDigraph;

use std::io::{Write, BufReader};
use std::fs::File;
use std::string::ToString;

use serde_json::ser::to_string;

#[allow(non_snake_case)]
fn main() {
    let matches = App::new("edgeop_init")
                      .arg(Arg::with_name("OPS")
                               .long("ops")
                               .help("Edge operation and weight specification, e.g. \
                                      Dup:1,Split:3,Parent:2")
                               .takes_value(true)
                               .required(true))
                      .arg(Arg::with_name("MU")
                               .long("mu")
                               .help("Population size to create")
                               .takes_value(true)
                               .required(true))
                      .arg(Arg::with_name("SEED")
                               .long("seed")
                               .help("Seed value for Rng")
                               .takes_value(true))
                      .arg(Arg::with_name("ILEN")
                               .long("ilen")
                               .help("Initial genome length (random range)")
                               .takes_value(true)
                               .required(true))
                      .arg(Arg::with_name("OUT")
                               .long("out")
                               .help("Write population to file")
                               .takes_value(true)
                               .required(false))
                      .get_matches();

    let mut wr: Box<Write> =
    match matches.value_of("OUT") {
        Some(out) => {
            Box::new(File::create(out).unwrap())
        }
        None => {
            Box::new(std::io::stdout())
        }
    };

    writeln!(&mut wr, "(");

    // size of population
    let MU: usize = FromStr::from_str(matches.value_of("MU").unwrap()).unwrap();
    writeln!(&mut wr, "(MU {})", MU);

    let seed: Vec<u64>;
    if let Some(seed_str) = matches.value_of("SEED") {
        seed = seed_str.split(",").map(|s| FromStr::from_str(s).unwrap()).collect();
    } else {
        writeln!(&mut std::io::stderr(), "Use OsRng to generate seed..");
        let mut rng = OsRng::new().unwrap();
        seed = (0..2).map(|_| rng.next_u64()).collect();
    }
    writeln!(&mut wr, "(SEED {})",
             Sexp::List(seed.iter().map(|&s| atom_i(s as i64)).collect()));

    let ilen_str = matches.value_of("ILEN").unwrap();
    let ilen: Vec<usize> = ilen_str.split(",").map(|s| FromStr::from_str(s).unwrap()).collect();
    assert!(ilen.len() == 1 || ilen.len() == 2);

    let ilen_from = ilen[0];
    let ilen_to = if ilen.len() == 1 {
        ilen[0]
    } else {
        ilen[1]
    };
    assert!(ilen_from <= ilen_to);
    writeln!(&mut wr, "(ILEN {})",
             list(&[atom_i(ilen_from as i64), atom_i(ilen_to as i64)]));

    // Parse weighted operation choice from command line
    let ops = parse_weighted_op_list(matches.value_of("OPS").unwrap()).unwrap();
    let v = Sexp::List(ops.iter().map(|&(ref op, f)| {
        list(&[atom_s(&ToString::to_string(op)), atom_f(f as f64)])
    }).collect());
    writeln!(&mut wr, "(OPS {})", v);

    let w_ops = to_weighted_vec(&ops);
    assert!(w_ops.len() > 0);

    let owned_w_ops = OwnedWeightedChoice::new(w_ops);

    assert!(seed.len() == 2);
    let mut rng: PcgRng = SeedableRng::from_seed([seed[0], seed[1]]);

    // we use the toolbox only for creating a new genome.
    // let mut toolbox = Toolbox::new(w_ops, vec![], vec![], Probability::new(0.0));

    // create initial random population
    let initial_population: Vec<EdgeOpsGenome> = (0..MU)
                                                     .map(|_| {
                                                         let len = if ilen_from == ilen_to {
                                                             ilen_from
                                                         } else {
                                                             Range::new(ilen_from, ilen_to)
                                                                 .ind_sample(&mut rng)
                                                         };
                                                         random_genome(&mut rng, len, &owned_w_ops)
                                                     })
                                                     .collect();

    // output initial population to stdout.
    let sexp_pop = Sexp::List(vec![atom_s("POP"),
        Sexp::List(initial_population.iter().map(|ind| ind.to_sexp()).collect()),
    ]);
    writeln!(&mut wr, "{}", sexp_pop);

    // evaluate fitness
    // let fitness: Vec<_> = evaluator.fitness(&initial_population[..]);
    // assert!(fitness.len() == initial_population.len());

    writeln!(&mut wr, ")");
}
<commit_msg>Refactor. Use different sexp layout<commit_after>extern crate rand;
extern crate graph_annealing;
extern crate clap;
extern crate pcg;
extern crate sexp;

use sexp::{Sexp, atom_f, atom_i, atom_s, list};
use std::str::FromStr;
use clap::{App, Arg};
use rand::{Rng, SeedableRng};
use rand::distributions::{IndependentSample, Range};
use rand::os::OsRng;
use pcg::PcgRng;
use graph_annealing::repr::edge_ops_genome::{EdgeOpsGenome, parse_weighted_op_list, random_genome,
                                             to_weighted_vec};
use graph_annealing::owned_weighted_choice::OwnedWeightedChoice;
use std::io::Write;
use std::fs::File;
use std::string::ToString;

#[allow(non_snake_case)]
#[allow(unused_must_use)]
fn main() {
    let matches = App::new("edgeop_init")
                      .arg(Arg::with_name("OPS")
                               .long("ops")
                               .help("Edge operation and weight specification, e.g. \
                                      Dup:1,Split:3,Parent:2")
                               .takes_value(true)
                               .required(true))
                      .arg(Arg::with_name("MU")
                               .long("mu")
                               .help("Population size to create")
                               .takes_value(true)
                               .required(true))
                      .arg(Arg::with_name("SEED")
                               .long("seed")
                               .help("Seed value for Rng")
                               .takes_value(true))
                      .arg(Arg::with_name("ILEN")
                               .long("ilen")
                               .help("Initial genome length (random range)")
                               .takes_value(true)
                               .required(true))
                      .arg(Arg::with_name("OUT")
                               .long("out")
                               .help("Write population to file")
                               .takes_value(true)
                               .required(false))
                      .get_matches();

    let mut wr: Box<Write> = match matches.value_of("OUT") {
        Some(out) => {
            Box::new(File::create(out).unwrap())
        }
        None => {
            Box::new(std::io::stdout())
        }
    };

    writeln!(&mut wr, "(POPULATION");
    writeln!(&mut wr, "  (PARAMS");

    // size of population
    let MU: usize = FromStr::from_str(matches.value_of("MU").unwrap()).unwrap();
    writeln!(&mut wr, "    (MU {})", MU);

    let seed: Vec<u64>;
    if let Some(seed_str) = matches.value_of("SEED") {
        seed = seed_str.split(",").map(|s| FromStr::from_str(s).unwrap()).collect();
    } else {
        writeln!(&mut std::io::stderr(), "Use OsRng to generate seed..");
        let mut rng = OsRng::new().unwrap();
        seed = (0..2).map(|_| rng.next_u64()).collect();
    }
    writeln!(&mut wr,
             "    (SEED {})",
             Sexp::List(seed.iter().map(|&s| atom_i(s as i64)).collect()));

    let ilen_str = matches.value_of("ILEN").unwrap();
    let ilen: Vec<usize> = ilen_str.split(",").map(|s| FromStr::from_str(s).unwrap()).collect();
    assert!(ilen.len() == 1 || ilen.len() == 2);

    let ilen_from = ilen[0];
    let ilen_to = if ilen.len() == 1 {
        ilen[0]
    } else {
        ilen[1]
    };
    assert!(ilen_from <= ilen_to);
    writeln!(&mut wr,
             "    (ILEN {})",
             list(&[atom_i(ilen_from as i64), atom_i(ilen_to as i64)]));

    // Parse weighted operation choice from command line
    let ops = parse_weighted_op_list(matches.value_of("OPS").unwrap()).unwrap();
    let v = Sexp::List(ops.iter()
                          .map(|&(ref op, f)| {
                              list(&[atom_s(&ToString::to_string(op)), atom_f(f as f64)])
                          })
                          .collect());
    writeln!(&mut wr, "    (OPS {})", v);

    let w_ops = to_weighted_vec(&ops);
    assert!(w_ops.len() > 0);

    let owned_w_ops = OwnedWeightedChoice::new(w_ops);

    assert!(seed.len() == 2);
    let mut rng: PcgRng = SeedableRng::from_seed([seed[0], seed[1]]);

    writeln!(&mut wr, "  )");

    // we use the toolbox only for creating a new genome.
    // let mut toolbox = Toolbox::new(w_ops, vec![], vec![], Probability::new(0.0));

    // create initial random population
    let initial_population: Vec<EdgeOpsGenome> = (0..MU)
                                                     .map(|_| {
                                                         let len = if ilen_from == ilen_to {
                                                             ilen_from
                                                         } else {
                                                             Range::new(ilen_from, ilen_to)
                                                                 .ind_sample(&mut rng)
                                                         };
                                                         random_genome(&mut rng, len, &owned_w_ops)
                                                     })
                                                     .collect();

    // output initial population
    writeln!(&mut wr, "  (GENOMES");
    for ind in initial_population.iter() {
        writeln!(&mut wr, "    {}", ind.to_sexp());
    }
    writeln!(&mut wr, "  )");

    // evaluate fitness
    // let fitness: Vec<_> = evaluator.fitness(&initial_population[..]);
    // assert!(fitness.len() == initial_population.len());

    writeln!(&mut wr, ")");
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use syn;

use bindgen::ir::Type;
use bindgen::utilities::IterHelpers;

pub type Path = String;

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GenericPath {
    pub name: String,
    pub generics: Vec<Type>,
}

impl GenericPath {
    pub fn new(name: String, generics: Vec<Type>) -> GenericPath {
        GenericPath {
            name: name,
            generics: generics,
        }
    }

    pub fn load(path: &syn::Path) -> Result<GenericPath, String> {
        if path.segments.len() != 1 {
            return Err(format!("path contains more than one segment"));
        }

        let name = path.segments[0].ident.to_string();

        if name == "PhantomData" {
            return Ok(GenericPath::new(name, Vec::new()));
        }

        let generics = match &path.segments[0].parameters {
            &syn::PathParameters::AngleBracketed(ref d) => {
                d.types.iter()
                       .try_skip_map(|x| Type::load(x))?
            }
            &syn::PathParameters::Parenthesized(_) => {
                return Err(format!("path contains parentheses"));
            }
        };

        Ok(GenericPath::new(name, generics))
    }
}
<commit_msg>Allow paths with multiple segments, but only pay attention to the last segment<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use syn;

use bindgen::ir::Type;
use bindgen::utilities::IterHelpers;

pub type Path = String;

#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct GenericPath {
    pub name: String,
    pub generics: Vec<Type>,
}

impl GenericPath {
    pub fn new(name: String, generics: Vec<Type>) -> GenericPath {
        GenericPath {
            name: name,
            generics: generics,
        }
    }

    pub fn load(path: &syn::Path) -> Result<GenericPath, String> {
        assert!(path.segments.len() > 0);
        let last_segment = path.segments.last().unwrap();

        let name = last_segment.ident.to_string();

        if name == "PhantomData" {
            return Ok(GenericPath::new(name, Vec::new()));
        }

        let generics = match &last_segment.parameters {
            &syn::PathParameters::AngleBracketed(ref d) => {
                d.types.iter()
                       .try_skip_map(|x| Type::load(x))?
            }
            &syn::PathParameters::Parenthesized(_) => {
                return Err(format!("path contains parentheses"));
            }
        };

        Ok(GenericPath::new(name, generics))
    }
}
<|endoftext|>


<commit_before>#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Position {
    pub line:   usize,
    pub offset: usize,
}
<commit_msg>Implement PartialOrd trait for position type.<commit_after>use std::cmp::{PartialOrd, Ordering};

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Position {
    pub line:   usize,
    pub offset: usize,
}

impl PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
        Some(
            if self.line < other.line {
                Ordering::Less
            } else if self.line > other.line {
                Ordering::Greater
            } else {
                if self.offset < other.offset {
                    Ordering::Less
                } else if self.offset > other.offset {
                    Ordering::Greater
                } else {
                    Ordering::Equal
                }
            }
        )
    }
}

#[cfg(test)]
mod tests {
    use super::Position;

    #[test]
    fn compare_works_when_lines_differ() {
        // Important to make the earlier position have a greater
        // offset, since that's an easy mistake to make.
        let earlier_position = Position{ line: 2, offset: 20 };
        let later_position = Position{ line: 3, offset: 10};

        assert!(earlier_position < later_position);
    }

    #[test]
    fn compare_works_when_lines_are_equal() {
        let earlier_position = Position{ line: 3, offset: 10 };
        let later_position = Position{ line: 3, offset: 20};

        assert!(earlier_position < later_position);
    }

    #[test]
    fn compare_works_when_lines_and_offsets_are_equal() {
        let earlier_position = Position{ line: 3, offset: 10 };
        let later_position = Position{ line: 3, offset: 10};

        assert!(earlier_position <= later_position);
        assert!(earlier_position >= later_position);

        // This is technically not necessary since we
        // derive the PartialEq trait, which provides
        // the implementation for this.
        assert!(earlier_position == later_position);
    }
}
<|endoftext|>