<commit_before>use std::fmt;
use std::fmt::Display;
use std::result::Result as StdResult;
use std::io;

pub type Result<T> = StdResult<T, PrefetchError>;

#[derive(Debug)]
pub enum ErrorKind {
    InvalidFileSignature,
    IoError,
}
/// USN Record Parsing Error
#[derive(Debug)]
pub struct PrefetchError {
    /// Formated error message
    pub message: String,
    /// The type of error
    pub kind: ErrorKind
}

impl PrefetchError{
    #[allow(dead_code)]
    pub fn invalid_file_signature(err: String)->Self{
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::InvalidFileSignature
        }
    }
    #[allow(dead_code)]
    pub fn io_error(err: String)->Self{
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::IoError
        }
    }
}

impl From<io::Error> for PrefetchError {
    fn from(err: io::Error) -> Self {
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::IoError
        }
    }
}

impl Display for PrefetchError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln!(f, "{:?}: {}",self.kind,self.message) }
}
<commit_msg>added additional errors<commit_after>use std::fmt;
use std::fmt::Display;
use std::result::Result as StdResult;
use std::io;
use std::string;

pub type Result<T> = StdResult<T, PrefetchError>;

#[derive(Debug)]
pub enum ErrorKind {
    InvalidFileSignature,
    IoError,
    Utf16Error,
    FromUtf16Error,
    DecompressionError
}
/// USN Record Parsing Error
#[derive(Debug)]
pub struct PrefetchError {
    /// Formated error message
    pub message: String,
    /// The type of error
    pub kind: ErrorKind
}

impl PrefetchError{
    #[allow(dead_code)]
    pub fn invalid_file_signature(err: String)->Self{
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::InvalidFileSignature
        }
    }
    #[allow(dead_code)]
    pub fn decompression_error(err: String)->Self{
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::DecompressionError
        }
    }
    #[allow(dead_code)]
    pub fn io_error(err: String)->Self{
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::IoError
        }
    }
    #[allow(dead_code)]
    pub fn decode_error(err: String)->Self{
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::Utf16Error
        }
    }
}

impl From<io::Error> for PrefetchError {
    fn from(err: io::Error) -> Self {
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::IoError
        }
    }
}

impl From<string::FromUtf16Error> for PrefetchError {
    fn from(err: string::FromUtf16Error) -> Self {
        PrefetchError {
            message: format!("{}",err),
            kind: ErrorKind::FromUtf16Error
        }
    }
}

impl Display for PrefetchError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { writeln!(f, "{:?}: {}",self.kind,self.message) }
}
<|endoftext|>


<commit_before>extern crate llvm_sys;

use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::str;
use self::llvm_sys::core::*;
use self::llvm_sys::analysis::*;
use self::llvm_sys::execution_engine::*;
use self::llvm_sys::prelude::*;
use self::llvm_sys::target::*;
//use self::llvm_sys::transforms::scalar::*;
use syntax::ast::op::*;
use syntax::ast::expr::*;
use syntax::ast::literals::*;

// Struct to keep track of data needed to build IR
pub struct Context {
    context: LLVMContextRef,
    module: LLVMModuleRef,
    builder: LLVMBuilderRef,
    execution_engine: LLVMExecutionEngineRef,
    fn_pass_manager: LLVMPassManagerRef,
    named_values: HashMap<String, LLVMValueRef>,
}

impl Context {
    pub unsafe fn new(module_name: &str) -> Context {
        LLVM_InitializeNativeTarget();
        LLVM_InitializeNativeAsmPrinter();
        LLVM_InitializeNativeAsmParser();
        LLVMLinkInInterpreter();

        let context = LLVMContextCreate();
        let module = LLVMModuleCreateWithNameInContext(c_str_ptr(module_name), context);
        let builder = LLVMCreateBuilderInContext(context);
        let named_values = HashMap::new();
        let mut execution_engine = 0 as LLVMExecutionEngineRef;
        let mut error_msg = 0 as *mut i8;

        if LLVMCreateExecutionEngineForModule(&mut execution_engine, module, &mut error_msg) == 1 {
            panic!("{}", str::from_utf8(CStr::from_ptr(error_msg).to_bytes()).unwrap())
        }

        let fn_pass_manager = LLVMCreateFunctionPassManagerForModule(module);
        let target_data = LLVMGetExecutionEngineTargetData(execution_engine);
        let data_layout = LLVMCopyStringRepOfTargetData(target_data);
        LLVMSetDataLayout(module, data_layout);
        LLVMAddTargetData(target_data, fn_pass_manager);
        LLVMDisposeMessage(data_layout);

        // Add desired passes to pass manager here
//        LLVMAddInstructionCombiningPass(fn_pass_manager);

        LLVMInitializeFunctionPassManager(fn_pass_manager);

        Context {
            context: context,
            module: module,
            builder: builder,
            execution_engine: execution_engine,
            fn_pass_manager: fn_pass_manager,
            named_values: named_values,
        }
    }

    // Dump the IR to stdout
    pub unsafe fn dump(&self) {
        LLVMDumpModule(self.module);
    }

    // Verifies that the llvm code is valid. Optionally prints
    // the error message, else abort.
    pub unsafe fn verify(&self) {
        let action = LLVMVerifierFailureAction::LLVMPrintMessageAction;
        let msg = vec![c_str_ptr("")];

        LLVMVerifyModule(self.module, action, msg.as_ptr() as *mut _);
        LLVMDisposeMessage(msg[0] as *mut _);
    }

    pub unsafe fn run(&self) -> u64 {
        let main = LLVMGetNamedFunction(self.module, c_str_ptr("main"));
        let result = LLVMRunFunction(self.execution_engine, main, 0, 0 as *mut LLVMGenericValueRef);

        LLVMGenericValueToInt(result, 1)
    }

    // Struct getters
    pub fn get_context(&self) -> LLVMContextRef {
        self.context
    }

    pub fn get_module(&self) -> LLVMModuleRef {
        self.module
    }

    pub fn get_builder(&self) -> LLVMBuilderRef {
        self.builder
    }

    pub fn clear_values(&mut self) {
        self.named_values.clear();
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposePassManager(self.fn_pass_manager);
//            LLVMDisposeExecutionEngine(self.execution_engine); // signal 4s for some reason
            LLVMDisposeBuilder(self.builder);
            LLVMDisposeModule(self.module);
            LLVMContextDispose(self.context);
        }
    }
}

pub trait CodeGen {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef>;
}

impl CodeGen for ExprWrapper {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        self.get_expr().gen_code(context)
    }
}

impl CodeGen for Expr {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        match *self {
            Expr::Block(ref vec) => {
                let mut gen = None;

                for expr in vec {
                    gen = expr.gen_code(context);
                }

                gen
            },
            Expr::Ident(ref name) => {
                match context.named_values.get(name) {
                    Some(val) => Some(*val),
                    None => {
                        println!("Error: Unknown variable named {}", name);

                        None
                    }
                }
            },
            Expr::Literal(ref literal_type) => {
                match literal_type {
                    &Literals::UTF8String(ref val) => {
                        // Types
                        let array_type1 = LLVMArrayType(LLVMInt8TypeInContext(context.get_context()), val.len() as u32);
                        // let string_struct_type = LLVMGetNamedGlobal(context.get_module(), c_str_ptr("struct.string"));
                        // if string_struct_type.is_null() {
                        //     println!("TMP Error: Cannot find builtin string type!");
                        // }
                        let i8_type = LLVMInt8TypeInContext(context.get_context());
                        let i8_ptr_type = LLVMPointerType(i8_type, 0);
                        let i32_type = LLVMInt32TypeInContext(context.get_context());
                        let i64_type = LLVMInt64TypeInContext(context.get_context());
                        // let string_type_fields = vec![LLVMInt32TypeInContext(context.get_context()),
                        //               LLVMPointerType(LLVMInt8TypeInContext(context.get_context()), 0)];

                        // Values
                        let len = LLVMConstInt(i64_type, val.len() as u64, 0);

                        // Make a global string constant and assign the value:
                        let const_str_var = LLVMAddGlobal(context.get_module(), array_type1, c_str_ptr("str"));
                        let mut chars = Vec::new();
                        for chr in val.bytes() {
                            chars.push(LLVMConstInt(i8_type, chr as u64, 0));
                        }

                        let const_str_array = LLVMConstArray(i8_type, chars.as_ptr() as *mut _, chars.len() as u32);
                        LLVMSetInitializer(const_str_var, const_str_array);
                        LLVMSetGlobalConstant(const_str_var, 1);

                        let args = vec![LLVMConstInt(i32_type, 0, 0), LLVMConstInt(i32_type, 0, 0)];
                        let allocated_str_ptr = LLVMBuildAlloca(context.get_builder(), i8_ptr_type, c_str_ptr("a"));
                        let mallocated_ptr = LLVMBuildMalloc(context.get_builder(), i8_type, c_str_ptr("m"));

                        LLVMSetTailCall(mallocated_ptr, 0);
                        LLVMBuildStore(context.get_builder(), mallocated_ptr, allocated_str_ptr);

                        let element_ptr = LLVMBuildGEP(context.get_builder(), const_str_var, args.as_ptr() as *mut _, 2, c_str_ptr(""));
                        LLVMBuildStore(context.get_builder(), element_ptr, allocated_str_ptr);

                        let loaded_ptr = LLVMBuildLoad(context.get_builder(), allocated_str_ptr, c_str_ptr("l"));
                        let struct_fields = vec![LLVMGetUndef(i8_ptr_type), len];
                        let const_struct = LLVMConstStructInContext(context.get_context(), struct_fields.as_ptr() as *mut _, 2, 0);

                        Some(LLVMBuildInsertValue(context.get_builder(), const_struct, loaded_ptr, 0, c_str_ptr("i")))
                    },
                    &Literals::I32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::I64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::U32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    &Literals::U64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val, 0))
                    },
                    &Literals::F32Num(ref val) => {
                        let ty = LLVMFloatTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val as f64))
                    },
                    &Literals::F64Num(ref val) => {
                        let ty = LLVMDoubleTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val))
                    },
                    &Literals::Bool(ref val) => {
                        let ty = LLVMInt1TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    _ => {
                        println!("Error: Codegen unimplemented for {:?}", literal_type);
                        None
                    }
                }
            },
            Expr::FnCall(ref name, ref args) => {
                let function = LLVMGetNamedFunction(context.module, c_str_ptr(name));

                if function.is_null() {
                    // TODO: Add standardized error message writing?
                    println!("Error: Function {} not found.", name);
                    return None;
                }

                let arg_count = LLVMCountParams(function) as usize;

                if arg_count != args.len() {
                    println!("Error: Function {} requires {} argument(s), {} given.", name, arg_count, args.len());
                    return None;
                }

                let mut arg_values = Vec::new();

                for arg in args {
                    match arg.gen_code(context) {
                        Some(value) => arg_values.push(value),
                        None => {
                            println!("Fatal Error: Argument {:?} codegen failed!", arg);
                            return None
                        }
                    }
                }

                // Void functions don't get saved return values
                let ret_var = if LLVMGetReturnType(LLVMGetElementType(LLVMTypeOf(function))) == LLVMVoidTypeInContext(context.context) {
                    c_str_ptr("")
                } else {
                    let mut tmp = name.to_string();
                    tmp.push_str("tmp");

                    c_str_ptr(&tmp)
                };

                Some(LLVMBuildCall(context.builder, function, arg_values.as_ptr() as *mut _, arg_values.len() as u32, ret_var))
            },
            Expr::UnaryOp(ref op, ref expr) => {
                match *op {
                    // I think Negate would be easier to handle by replacing it with multiply * -1 in the parser
                    UnaryOp::Negate => panic!("Codegen error: Negation not supported in codegen."),
                    UnaryOp::Not => match expr.gen_code(context) {
                        Some(val) => Some(LLVMBuildNot(context.get_builder(), val, c_str_ptr("nottmp"))),
                        None => None
                    }
                }
            },
            // Expr::VarDecl(ref const_bool, ref typ, ref name, ref expr) => {
            //     panic!("Codegen error: unimplemented variable declaration");
            // },
            Expr::NoOp => None,
            _ => None
        }
    }
}

// Helper function
pub fn c_str_ptr(rust_str: &str) -> *const i8 {
    match CString::new(rust_str.as_bytes()) {
        Ok(string) => string,
        Err(err) => panic!(err)
    }.as_ptr()
}
<commit_msg>Found where LLVM error occurs<commit_after>extern crate llvm_sys;

use std::collections::HashMap;
use std::ffi::{CStr, CString};
use std::str;
use self::llvm_sys::core::*;
use self::llvm_sys::analysis::*;
use self::llvm_sys::execution_engine::*;
use self::llvm_sys::prelude::*;
use self::llvm_sys::target::*;
//use self::llvm_sys::transforms::scalar::*;
use syntax::ast::op::*;
use syntax::ast::expr::*;
use syntax::ast::literals::*;

// Struct to keep track of data needed to build IR
pub struct Context {
    context: LLVMContextRef,
    module: LLVMModuleRef,
    builder: LLVMBuilderRef,
    execution_engine: LLVMExecutionEngineRef,
    fn_pass_manager: LLVMPassManagerRef,
    named_values: HashMap<String, LLVMValueRef>,
}

impl Context {
    pub unsafe fn new(module_name: &str) -> Context {
        LLVM_InitializeNativeTarget();
        LLVM_InitializeNativeAsmPrinter();
        LLVM_InitializeNativeAsmParser();
        LLVMLinkInInterpreter();

        let context = LLVMContextCreate();
        let module = LLVMModuleCreateWithNameInContext(c_str_ptr(module_name), context);
        let builder = LLVMCreateBuilderInContext(context);
        let named_values = HashMap::new();
        let mut execution_engine = 0 as LLVMExecutionEngineRef;
        let mut error_msg = 0 as *mut i8;

        if LLVMCreateExecutionEngineForModule(&mut execution_engine, module, &mut error_msg) == 1 {
            panic!("{}", str::from_utf8(CStr::from_ptr(error_msg).to_bytes()).unwrap())
        }

        let fn_pass_manager = LLVMCreateFunctionPassManagerForModule(module);
        let target_data = LLVMGetExecutionEngineTargetData(execution_engine);
        let data_layout = LLVMCopyStringRepOfTargetData(target_data);
        LLVMSetDataLayout(module, data_layout);
        LLVMAddTargetData(target_data, fn_pass_manager);
        LLVMDisposeMessage(data_layout);

        // Add desired passes to pass manager here
//        LLVMAddInstructionCombiningPass(fn_pass_manager);

        LLVMInitializeFunctionPassManager(fn_pass_manager);

        Context {
            context: context,
            module: module,
            builder: builder,
            execution_engine: execution_engine,
            fn_pass_manager: fn_pass_manager,
            named_values: named_values,
        }
    }

    // Dump the IR to stdout
    pub unsafe fn dump(&self) {
        LLVMDumpModule(self.module);
    }

    // Verifies that the llvm code is valid. Optionally prints
    // the error message, else abort.
    pub unsafe fn verify(&self) {
        let action = LLVMVerifierFailureAction::LLVMPrintMessageAction;
        let msg = vec![c_str_ptr("")];

        LLVMVerifyModule(self.module, action, msg.as_ptr() as *mut _);
        LLVMDisposeMessage(msg[0] as *mut _);
    }

    pub unsafe fn run(&self) -> u64 {
        let main = LLVMGetNamedFunction(self.module, c_str_ptr("main"));
        let result = LLVMRunFunction(self.execution_engine, main, 0, 0 as *mut LLVMGenericValueRef);

        LLVMGenericValueToInt(result, 1)
    }

    // Struct getters
    pub fn get_context(&self) -> LLVMContextRef {
        self.context
    }

    pub fn get_module(&self) -> LLVMModuleRef {
        self.module
    }

    pub fn get_builder(&self) -> LLVMBuilderRef {
        self.builder
    }

    pub fn clear_values(&mut self) {
        self.named_values.clear();
    }
}

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposePassManager(self.fn_pass_manager);
//            LLVMDisposeExecutionEngine(self.execution_engine); // signal 4s for some reason
            LLVMDisposeBuilder(self.builder);
            LLVMDisposeModule(self.module);
            LLVMContextDispose(self.context);
        }
    }
}

pub trait CodeGen {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef>;
}

impl CodeGen for ExprWrapper {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        self.get_expr().gen_code(context)
    }
}

impl CodeGen for Expr {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        match *self {
            Expr::Block(ref vec) => {
                let mut gen = None;

                for expr in vec {
                    gen = expr.gen_code(context);
                }

                gen
            },
            Expr::Ident(ref name) => {
                match context.named_values.get(name) {
                    Some(val) => Some(*val),
                    None => {
                        println!("Error: Unknown variable named {}", name);

                        None
                    }
                }
            },
            Expr::Literal(ref literal_type) => {
                match literal_type {
                    &Literals::UTF8String(ref val) => {
                        // Types
                        let array_type1 = LLVMArrayType(LLVMInt8TypeInContext(context.get_context()), val.len() as u32);
                        // let string_struct_type = LLVMGetNamedGlobal(context.get_module(), c_str_ptr("struct.string"));
                        // if string_struct_type.is_null() {
                        //     println!("TMP Error: Cannot find builtin string type!");
                        // }
                        let i8_type = LLVMInt8TypeInContext(context.get_context());
                        let i8_ptr_type = LLVMPointerType(i8_type, 0);
                        let i32_type = LLVMInt32TypeInContext(context.get_context());
                        let i64_type = LLVMInt64TypeInContext(context.get_context());
                        // let string_type_fields = vec![LLVMInt32TypeInContext(context.get_context()),
                        //               LLVMPointerType(LLVMInt8TypeInContext(context.get_context()), 0)];

                        // Values
                        let len = LLVMConstInt(i64_type, val.len() as u64, 0);

                        // Make a global string constant and assign the value:
                        let const_str_var = LLVMAddGlobal(context.get_module(), array_type1, c_str_ptr("str"));
                        let mut chars = Vec::new();
                        for chr in val.bytes() {
                            chars.push(LLVMConstInt(i8_type, chr as u64, 0));
                        }

                        let const_str_array = LLVMConstArray(i8_type, chars.as_ptr() as *mut _, chars.len() as u32);
                        LLVMSetInitializer(const_str_var, const_str_array);
                        LLVMSetGlobalConstant(const_str_var, 1);

                        let args = vec![LLVMConstInt(i32_type, 0, 0), LLVMConstInt(i32_type, 0, 0)];
                        let allocated_str_ptr = LLVMBuildAlloca(context.get_builder(), i8_ptr_type, c_str_ptr("a"));
                        let mallocated_ptr = LLVMBuildMalloc(context.get_builder(), i8_type, c_str_ptr("m"));

                        LLVMSetTailCall(mallocated_ptr, 0);
                        LLVMBuildStore(context.get_builder(), mallocated_ptr, allocated_str_ptr);

                        let element_ptr = LLVMBuildGEP(context.get_builder(), const_str_var, args.as_ptr() as *mut _, 2, c_str_ptr(""));
                        LLVMBuildStore(context.get_builder(), element_ptr, allocated_str_ptr);

                        let loaded_ptr = LLVMBuildLoad(context.get_builder(), allocated_str_ptr, c_str_ptr("l"));
                        let struct_fields = vec![LLVMGetUndef(i8_ptr_type), len];
                        let const_struct = LLVMConstStructInContext(context.get_context(), struct_fields.as_ptr() as *mut _, 2, 0);

                        Some(LLVMBuildInsertValue(context.get_builder(), const_struct, loaded_ptr, 0, c_str_ptr("i"))) // Problem
                    },
                    &Literals::I32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::I64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::U32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    &Literals::U64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val, 0))
                    },
                    &Literals::F32Num(ref val) => {
                        let ty = LLVMFloatTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val as f64))
                    },
                    &Literals::F64Num(ref val) => {
                        let ty = LLVMDoubleTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val))
                    },
                    &Literals::Bool(ref val) => {
                        let ty = LLVMInt1TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    _ => {
                        println!("Error: Codegen unimplemented for {:?}", literal_type);
                        None
                    }
                }
            },
            Expr::FnCall(ref name, ref args) => {
                let function = LLVMGetNamedFunction(context.module, c_str_ptr(name));

                if function.is_null() {
                    // TODO: Add standardized error message writing?
                    println!("Error: Function {} not found.", name);
                    return None;
                }

                let arg_count = LLVMCountParams(function) as usize;

                if arg_count != args.len() {
                    println!("Error: Function {} requires {} argument(s), {} given.", name, arg_count, args.len());
                    return None;
                }

                let mut arg_values = Vec::new();

                for arg in args {
                    match arg.gen_code(context) {
                        Some(value) => arg_values.push(value),
                        None => {
                            println!("Fatal Error: Argument {:?} codegen failed!", arg);
                            return None
                        }
                    }
                }

                // Void functions don't get saved return values
                let ret_var = if LLVMGetReturnType(LLVMGetElementType(LLVMTypeOf(function))) == LLVMVoidTypeInContext(context.context) {
                    c_str_ptr("")
                } else {
                    let mut tmp = name.to_string();
                    tmp.push_str("tmp");

                    c_str_ptr(&tmp)
                };

                Some(LLVMBuildCall(context.builder, function, arg_values.as_ptr() as *mut _, arg_values.len() as u32, ret_var))
            },
            Expr::UnaryOp(ref op, ref expr) => {
                match *op {
                    // I think Negate would be easier to handle by replacing it with multiply * -1 in the parser
                    UnaryOp::Negate => panic!("Codegen error: Negation not supported in codegen."),
                    UnaryOp::Not => match expr.gen_code(context) {
                        Some(val) => Some(LLVMBuildNot(context.get_builder(), val, c_str_ptr("nottmp"))),
                        None => None
                    }
                }
            },
            // Expr::VarDecl(ref const_bool, ref typ, ref name, ref expr) => {
            //     panic!("Codegen error: unimplemented variable declaration");
            // },
            Expr::NoOp => None,
            _ => None
        }
    }
}

// Helper function
pub fn c_str_ptr(rust_str: &str) -> *const i8 {
    match CString::new(rust_str.as_bytes()) {
        Ok(string) => string,
        Err(err) => panic!(err)
    }.as_ptr()
}
<|endoftext|>


<commit_before>use types::base::{GraphQLType, Arguments, TypeKind};
use executor::{Executor, Registry, ExecutionResult};

use schema::meta::{MetaType, ObjectMeta, EnumMeta, InputObjectMeta, UnionMeta, InterfaceMeta,
                   Field, Argument, EnumValue};
use schema::model::{RootNode, SchemaType, TypeType, DirectiveType, DirectiveLocation};

impl<'a, CtxT, QueryT, MutationT> GraphQLType for RootNode<'a, QueryT, MutationT>
    where QueryT: GraphQLType<Context=CtxT>,
          MutationT: GraphQLType<Context=CtxT>
{
    type Context = CtxT;

    fn name() -> Option<&'static str> {
        QueryT::name()
    }

    fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> {
        QueryT::meta(registry)
    }

    fn resolve_field(&self, field: &str, args: &Arguments, executor: &Executor<CtxT>) -> ExecutionResult {
        match field {
            "__schema" => executor.replaced_context(&self.schema).resolve(&self.schema),
            "__type" => {
                let type_name: String = args.get("name").unwrap();
                executor.replaced_context(&self.schema).resolve(&self.schema.type_by_name(&type_name))
            },
            _=> self.query_type.resolve_field(field, args, executor),
        }
    }
}

graphql_object!(<'a> SchemaType<'a>: SchemaType<'a> as "__Schema" |&self| {
    field types() -> Vec<TypeType> {
        self.type_list()
    }

    field query_type() -> TypeType {
        self.query_type()
    }

    field mutation_type() -> Option<TypeType> {
        self.mutation_type()
    }

    field directives() -> Vec<&DirectiveType> {
        self.directive_list()
    }
});

graphql_object!(<'a> TypeType<'a>: SchemaType<'a> as "__Type" |&self| {
    field name() -> Option<&str> {
        match *self {
            TypeType::Concrete(t) => t.name(),
            _ => None,
        }
    }

    field description() -> Option<&String> {
        match *self {
            TypeType::Concrete(t) => t.description(),
            _ => None,
        }
    }

    field kind() -> TypeKind {
        match *self {
            TypeType::Concrete(t) => t.type_kind(),
            TypeType::List(_) => TypeKind::List,
            TypeType::NonNull(_) => TypeKind::NonNull,
        }
    }

    field fields(include_deprecated = false: bool) -> Option<Vec<&Field>> {
        match *self {
            TypeType::Concrete(&MetaType::Interface(InterfaceMeta { ref fields, .. })) |
            TypeType::Concrete(&MetaType::Object(ObjectMeta { ref fields, .. })) =>
                Some(fields
                    .iter()
                    .filter(|f| include_deprecated || f.deprecation_reason.is_none())
                    .collect()),
            _ => None,
        }
    }

    field of_type() -> Option<&Box<TypeType>> {
        match *self {
            TypeType::Concrete(_) => None,
            TypeType::List(ref l) | TypeType::NonNull(ref l) => Some(l),
        }
    }

    field input_fields() -> Option<&Vec<Argument>> {
        match *self {
            TypeType::Concrete(&MetaType::InputObject(InputObjectMeta { ref input_fields, .. })) =>
                Some(input_fields),
            _ => None,
        }
    }

    field interfaces(&executor) -> Option<Vec<TypeType>> {
        match *self {
            TypeType::Concrete(&MetaType::Object(ObjectMeta { ref interface_names, .. })) => {
                let schema = executor.context();
                Some(interface_names
                    .iter()
                    .filter_map(|n| schema.type_by_name(n))
                    .collect())
            }
            _ => None,
        }
    }

    field possible_types(&executor) -> Option<Vec<TypeType>> {
        let schema = executor.context();
        match *self {
            TypeType::Concrete(&MetaType::Union(UnionMeta { ref of_type_names, .. })) => {
                Some(of_type_names
                    .iter()
                    .filter_map(|tn| schema.type_by_name(tn))
                    .collect())
            }
            TypeType::Concrete(&MetaType::Interface(InterfaceMeta { name: iface_name, .. })) => {
                Some(schema.concrete_type_list()
                    .iter()
                    .filter_map(|&ct|
                        if let MetaType::Object(ObjectMeta { ref name, ref interface_names, .. }) = *ct {
                            if interface_names.contains(&iface_name.to_owned()) {
                                schema.type_by_name(name)
                            } else { None }
                        } else { None }
                    )
                    .collect())
            }
            _ => None,
        }
    }

    field enum_values(include_deprecated = false: bool) -> Option<Vec<&EnumValue>> {
        match *self {
            TypeType::Concrete(&MetaType::Enum(EnumMeta { ref values, .. })) =>
                Some(values
                    .iter()
                    .filter(|f| include_deprecated || f.deprecation_reason.is_none())
                    .collect()),
            _ => None,
        }
    }
});

graphql_object!(<'a> Field<'a>: SchemaType<'a> as "__Field" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field args() -> Vec<&Argument> {
        self.arguments.as_ref().map_or_else(Vec::new, |v| v.iter().collect())
    }

    field type(&executor) -> TypeType {
        executor.context().make_type(&self.field_type)
    }

    field is_deprecated() -> bool {
        self.deprecation_reason.is_some()
    }

    field deprecation_reason() -> &Option<String> {
        &self.deprecation_reason
    }
});

graphql_object!(<'a> Argument<'a>: SchemaType<'a> as "__InputValue" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field type(&executor) -> TypeType {
        executor.context().make_type(&self.arg_type)
    }

    field default_value() -> Option<String> {
        self.default_value.as_ref().map(|v| format!("{}", v))
    }
});

graphql_object!(EnumValue: () as "__EnumValue" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field is_deprecated() -> bool {
        self.deprecation_reason.is_some()
    }

    field deprecation_reason() -> &Option<String> {
        &self.deprecation_reason
    }
});

graphql_enum!(TypeKind as "__TypeKind" {
    TypeKind::Scalar => "SCALAR",
    TypeKind::Object => "OBJECT",
    TypeKind::Interface => "INTERFACE",
    TypeKind::Union => "UNION",
    TypeKind::Enum => "ENUM",
    TypeKind::InputObject => "INPUT_OBJECT",
    TypeKind::List => "LIST",
    TypeKind::NonNull => "NON_NULL",
});

graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field locations() -> &Vec<DirectiveLocation> {
        &self.locations
    }

    field args() -> &Vec<Argument> {
        &self.arguments
    }
});

graphql_enum!(DirectiveLocation as "__DirectiveLocation" {
    DirectiveLocation::Query => "QUERY",
    DirectiveLocation::Mutation => "MUTATION",
    DirectiveLocation::Field => "FIELD",
    DirectiveLocation::FragmentDefinition => "FRAGMENT_DEFINITION",
    DirectiveLocation::FragmentSpread => "FRAGMENT_SPREAD",
    DirectiveLocation::InlineFragment => "INLINE_FRAGMENT",
});
<commit_msg>Add fields to improve tooling compatibility<commit_after>use types::base::{GraphQLType, Arguments, TypeKind};
use executor::{Executor, Registry, ExecutionResult};

use schema::meta::{MetaType, ObjectMeta, EnumMeta, InputObjectMeta, UnionMeta, InterfaceMeta,
                   Field, Argument, EnumValue};
use schema::model::{RootNode, SchemaType, TypeType, DirectiveType, DirectiveLocation};

impl<'a, CtxT, QueryT, MutationT> GraphQLType for RootNode<'a, QueryT, MutationT>
    where QueryT: GraphQLType<Context=CtxT>,
          MutationT: GraphQLType<Context=CtxT>
{
    type Context = CtxT;

    fn name() -> Option<&'static str> {
        QueryT::name()
    }

    fn meta<'r>(registry: &mut Registry<'r>) -> MetaType<'r> {
        QueryT::meta(registry)
    }

    fn resolve_field(&self, field: &str, args: &Arguments, executor: &Executor<CtxT>) -> ExecutionResult {
        match field {
            "__schema" => executor.replaced_context(&self.schema).resolve(&self.schema),
            "__type" => {
                let type_name: String = args.get("name").unwrap();
                executor.replaced_context(&self.schema).resolve(&self.schema.type_by_name(&type_name))
            },
            _=> self.query_type.resolve_field(field, args, executor),
        }
    }
}

graphql_object!(<'a> SchemaType<'a>: SchemaType<'a> as "__Schema" |&self| {
    field types() -> Vec<TypeType> {
        self.type_list()
    }

    field query_type() -> TypeType {
        self.query_type()
    }

    field mutation_type() -> Option<TypeType> {
        self.mutation_type()
    }

    // Included for compatibility with the introspection query in GraphQL.js
    field subscription_type() -> Option<TypeType> {
        None
    }

    field directives() -> Vec<&DirectiveType> {
        self.directive_list()
    }
});

graphql_object!(<'a> TypeType<'a>: SchemaType<'a> as "__Type" |&self| {
    field name() -> Option<&str> {
        match *self {
            TypeType::Concrete(t) => t.name(),
            _ => None,
        }
    }

    field description() -> Option<&String> {
        match *self {
            TypeType::Concrete(t) => t.description(),
            _ => None,
        }
    }

    field kind() -> TypeKind {
        match *self {
            TypeType::Concrete(t) => t.type_kind(),
            TypeType::List(_) => TypeKind::List,
            TypeType::NonNull(_) => TypeKind::NonNull,
        }
    }

    field fields(include_deprecated = false: bool) -> Option<Vec<&Field>> {
        match *self {
            TypeType::Concrete(&MetaType::Interface(InterfaceMeta { ref fields, .. })) |
            TypeType::Concrete(&MetaType::Object(ObjectMeta { ref fields, .. })) =>
                Some(fields
                    .iter()
                    .filter(|f| include_deprecated || f.deprecation_reason.is_none())
                    .collect()),
            _ => None,
        }
    }

    field of_type() -> Option<&Box<TypeType>> {
        match *self {
            TypeType::Concrete(_) => None,
            TypeType::List(ref l) | TypeType::NonNull(ref l) => Some(l),
        }
    }

    field input_fields() -> Option<&Vec<Argument>> {
        match *self {
            TypeType::Concrete(&MetaType::InputObject(InputObjectMeta { ref input_fields, .. })) =>
                Some(input_fields),
            _ => None,
        }
    }

    field interfaces(&executor) -> Option<Vec<TypeType>> {
        match *self {
            TypeType::Concrete(&MetaType::Object(ObjectMeta { ref interface_names, .. })) => {
                let schema = executor.context();
                Some(interface_names
                    .iter()
                    .filter_map(|n| schema.type_by_name(n))
                    .collect())
            }
            _ => None,
        }
    }

    field possible_types(&executor) -> Option<Vec<TypeType>> {
        let schema = executor.context();
        match *self {
            TypeType::Concrete(&MetaType::Union(UnionMeta { ref of_type_names, .. })) => {
                Some(of_type_names
                    .iter()
                    .filter_map(|tn| schema.type_by_name(tn))
                    .collect())
            }
            TypeType::Concrete(&MetaType::Interface(InterfaceMeta { name: iface_name, .. })) => {
                Some(schema.concrete_type_list()
                    .iter()
                    .filter_map(|&ct|
                        if let MetaType::Object(ObjectMeta { ref name, ref interface_names, .. }) = *ct {
                            if interface_names.contains(&iface_name.to_owned()) {
                                schema.type_by_name(name)
                            } else { None }
                        } else { None }
                    )
                    .collect())
            }
            _ => None,
        }
    }

    field enum_values(include_deprecated = false: bool) -> Option<Vec<&EnumValue>> {
        match *self {
            TypeType::Concrete(&MetaType::Enum(EnumMeta { ref values, .. })) =>
                Some(values
                    .iter()
                    .filter(|f| include_deprecated || f.deprecation_reason.is_none())
                    .collect()),
            _ => None,
        }
    }
});

graphql_object!(<'a> Field<'a>: SchemaType<'a> as "__Field" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field args() -> Vec<&Argument> {
        self.arguments.as_ref().map_or_else(Vec::new, |v| v.iter().collect())
    }

    field type(&executor) -> TypeType {
        executor.context().make_type(&self.field_type)
    }

    field is_deprecated() -> bool {
        self.deprecation_reason.is_some()
    }

    field deprecation_reason() -> &Option<String> {
        &self.deprecation_reason
    }
});

graphql_object!(<'a> Argument<'a>: SchemaType<'a> as "__InputValue" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field type(&executor) -> TypeType {
        executor.context().make_type(&self.arg_type)
    }

    field default_value() -> Option<String> {
        self.default_value.as_ref().map(|v| format!("{}", v))
    }
});

graphql_object!(EnumValue: () as "__EnumValue" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field is_deprecated() -> bool {
        self.deprecation_reason.is_some()
    }

    field deprecation_reason() -> &Option<String> {
        &self.deprecation_reason
    }
});

graphql_enum!(TypeKind as "__TypeKind" {
    TypeKind::Scalar => "SCALAR",
    TypeKind::Object => "OBJECT",
    TypeKind::Interface => "INTERFACE",
    TypeKind::Union => "UNION",
    TypeKind::Enum => "ENUM",
    TypeKind::InputObject => "INPUT_OBJECT",
    TypeKind::List => "LIST",
    TypeKind::NonNull => "NON_NULL",
});

graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self| {
    field name() -> &String {
        &self.name
    }

    field description() -> &Option<String> {
        &self.description
    }

    field locations() -> &Vec<DirectiveLocation> {
        &self.locations
    }

    field args() -> &Vec<Argument> {
        &self.arguments
    }

    // Included for compatibility with the introspection query in GraphQL.js
    field deprecated "Use the locations array instead"
    on_operation() -> bool {
        self.locations.contains(&DirectiveLocation::Query)
    }

    // Included for compatibility with the introspection query in GraphQL.js
    field deprecated "Use the locations array instead"
    on_fragment() -> bool {
        self.locations.contains(&DirectiveLocation::FragmentDefinition) ||
            self.locations.contains(&DirectiveLocation::InlineFragment) ||
            self.locations.contains(&DirectiveLocation::FragmentSpread)
    }

    // Included for compatibility with the introspection query in GraphQL.js
    field deprecated "Use the locations array instead"
    on_field() -> bool {
        self.locations.contains(&DirectiveLocation::Field)
    }
});

graphql_enum!(DirectiveLocation as "__DirectiveLocation" {
    DirectiveLocation::Query => "QUERY",
    DirectiveLocation::Mutation => "MUTATION",
    DirectiveLocation::Field => "FIELD",
    DirectiveLocation::FragmentDefinition => "FRAGMENT_DEFINITION",
    DirectiveLocation::FragmentSpread => "FRAGMENT_SPREAD",
    DirectiveLocation::InlineFragment => "INLINE_FRAGMENT",
});
<|endoftext|>


<commit_before>//! Define semi-implicit schemes

use ndarray::*;
use ndarray_linalg::*;

use super::traits::*;

/// Linear ODE with diagonalized matrix (exactly solvable)
#[derive(Debug, Clone)]
pub struct Diagonal<A, D>
where
    A: Scalar,
    D: Dimension,
{
    exp_diag: Array<A, D>,
    diag: Array<A, D>,
    dt: A::Real,
}

impl<A, D> TimeStep for Diagonal<A, D>
where
    A: Scalar,
    D: Dimension,
{
    type Time = A::Real;

    fn get_dt(&self) -> Self::Time {
        self.dt
    }
    fn set_dt(&mut self, dt: Self::Time) {
        Zip::from(&mut self.exp_diag)
            .and(&self.diag)
            .apply(|a, &b| {
                *a = b.mul_real(dt).exp();
            });
    }
}

impl<A, D> ModelSpec for Diagonal<A, D>
where
    A: Scalar,
    D: Dimension,
{
    type Scalar = A;
    type Dim = D;

    fn model_size(&self) -> D::Pattern {
        self.exp_diag.dim()
    }
}

impl<A, D> TimeEvolution for Diagonal<A, D>
where
    A: Scalar,
    D: Dimension,
{
    fn iterate<'a, S>(&mut self, x: &'a mut ArrayBase<S, D>) -> &'a mut ArrayBase<S, D>
    where
        S: DataMut<Elem = A>,
    {
        for (val, d) in x.iter_mut().zip(self.exp_diag.iter()) {
            *val = *val * *d;
        }
        x
    }
}

impl<F: SemiImplicit> Scheme<F> for Diagonal<F::Scalar, F::Dim> {
    fn new(f: F, dt: Self::Time) -> Self {
        let diag = f.diag();
        let mut exp_diag = diag.to_owned();
        for v in exp_diag.iter_mut() {
            *v = v.mul_real(dt).exp();
        }
        Diagonal {
            exp_diag: exp_diag,
            diag: diag,
            dt: dt,
        }
    }
}

#[derive(Debug, Clone)]
pub struct DiagRK4<A, D, NLin, Lin>
where
    A: Scalar,
    D: Dimension,
    NLin: ModelSpec<Scalar = A, Dim = D>,
    Lin: ModelSpec<Scalar = A, Dim = D> + TimeStep<Time = A::Real>,
{
    nlin: NLin,
    lin: Lin,
    dt: Lin::Time,
    x: Array<A, D>,
    lx: Array<A, D>,
    k1: Array<A, D>,
    k2: Array<A, D>,
    k3: Array<A, D>,
}

pub fn diag_rk4<A, D, NLin>(nlin: NLin, dt: A::Real) -> DiagRK4<A, D, NLin, Diagonal<A, D>>
where
    A: Scalar,
    D: Dimension,
    NLin: SemiImplicit<Scalar = A, Dim = D>,
{
    let lin = Diagonal::new(nlin.clone(), dt / into_scalar(2.0));
    let x = Array::zeros(lin.model_size());
    let lx = Array::zeros(lin.model_size());
    let k1 = Array::zeros(lin.model_size());
    let k2 = Array::zeros(lin.model_size());
    let k3 = Array::zeros(lin.model_size());
    DiagRK4 {
        nlin,
        lin,
        dt,
        x,
        lx,
        k1,
        k2,
        k3,
    }
}

impl<A, D, NLin, Lin> TimeStep for DiagRK4<A, D, NLin, Lin>
where
    A: Scalar,
    D: Dimension,
    NLin: ModelSpec<Scalar = A, Dim = D>,
    Lin: ModelSpec<Scalar = A, Dim = D> + TimeStep<Time = A::Real>,
{
    type Time = Lin::Time;

    fn get_dt(&self) -> Self::Time {
        self.dt
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.lin.set_dt(dt / into_scalar(2.0));
    }
}

impl<A, D, NLin, Lin> ModelSpec for DiagRK4<A, D, NLin, Lin>
where
    A: Scalar,
    D: Dimension,
    NLin: ModelSpec<Scalar = A, Dim = D>,
    Lin: ModelSpec<Scalar = A, Dim = D> + TimeStep<Time = A::Real>,
{
    type Scalar = A;
    type Dim = D;

    fn model_size(&self) -> <Self::Dim as Dimension>::Pattern {
        self.nlin.model_size() // TODO check
    }
}

impl<A, D, NLin, Lin> TimeEvolution for DiagRK4<A, D, NLin, Lin>
where
    A: Scalar,
    D: Dimension,
    NLin: SemiImplicit<Scalar = A, Dim = D>,
    Lin: TimeEvolution<Scalar = A, Dim = D> + TimeStep<Time = A::Real>,
{
    fn iterate<'a, S>(
        &mut self,
        x: &'a mut ArrayBase<S, Self::Dim>,
    ) -> &'a mut ArrayBase<S, Self::Dim>
    where
        S: DataMut<Elem = A>,
    {
        // constants
        let dt = self.dt;
        let dt_2 = self.dt / into_scalar(2.0);
        let dt_3 = self.dt / into_scalar(3.0);
        let dt_6 = self.dt / into_scalar(6.0);
        // operators
        let l = &mut self.lin;
        let f = &mut self.nlin;
        // calc
        self.x.zip_mut_with(x, |buf, x| *buf = *x);
        self.lx.zip_mut_with(x, |buf, lx| *buf = *lx);
        l.iterate(&mut self.lx);
        let k1 = f.nlin(x);
        self.k1.zip_mut_with(k1, |buf, k1| *buf = *k1);
        Zip::from(&mut *k1).and(&self.x).apply(|k1, &x_| {
            *k1 = x_ + k1.mul_real(dt_2);
        });
        let k2 = f.nlin(l.iterate(k1));
        self.k2.zip_mut_with(k2, |buf, k| *buf = *k);
        Zip::from(&mut *k2).and(&self.lx).apply(|k2, &lx| {
            *k2 = lx + k2.mul_real(dt_2);
        });
        let k3 = f.nlin(k2);
        self.k3.zip_mut_with(k3, |buf, k| *buf = *k);
        Zip::from(&mut *k3).and(&self.lx).apply(|k3, &lx| {
            *k3 = lx + k3.mul_real(dt);
        });
        let k4 = f.nlin(l.iterate(k3));
        Zip::from(&mut self.x)
            .and(&self.k1)
            .apply(|x_, k1_| *x_ = *x_ + k1_.mul_real(dt_6));
        l.iterate(&mut self.x);
        Zip::from(&mut self.x)
            .and(&self.k2)
            .and(&self.k3)
            .apply(|x_, &k2_, &k3_| *x_ = *x_ + (k2_ + k3_).mul_real(dt_3));
        l.iterate(&mut self.x);
        Zip::from(&mut *k4).and(&self.x).apply(|k4, &x_| {
            *k4 = x_ + k4.mul_real(dt_6);
        });
        k4
    }
}
<commit_msg>Simplify type restrictions<commit_after>//! Define semi-implicit schemes

use ndarray::*;
use ndarray_linalg::*;

use super::traits::*;

/// Linear ODE with diagonalized matrix (exactly solvable)
#[derive(Debug, Clone)]
pub struct Diagonal<F: SemiImplicit> {
    exp_diag: Array<F::Scalar, F::Dim>,
    diag: Array<F::Scalar, F::Dim>,
    dt: <F::Scalar as AssociatedReal>::Real,
}

impl<F: SemiImplicit> TimeStep for Diagonal<F> {
    type Time = <F::Scalar as AssociatedReal>::Real;

    fn get_dt(&self) -> Self::Time {
        self.dt
    }
    fn set_dt(&mut self, dt: Self::Time) {
        Zip::from(&mut self.exp_diag)
            .and(&self.diag)
            .apply(|a, &b| {
                *a = b.mul_real(dt).exp();
            });
    }
}

impl<F: SemiImplicit> ModelSpec for Diagonal<F> {
    type Scalar = F::Scalar;
    type Dim = F::Dim;

    fn model_size(&self) -> <Self::Dim as Dimension>::Pattern {
        self.exp_diag.dim()
    }
}

impl<F: SemiImplicit> TimeEvolution for Diagonal<F> {
    fn iterate<'a, S>(
        &mut self,
        x: &'a mut ArrayBase<S, Self::Dim>,
    ) -> &'a mut ArrayBase<S, Self::Dim>
    where
        S: DataMut<Elem = Self::Scalar>,
    {
        for (val, d) in x.iter_mut().zip(self.exp_diag.iter()) {
            *val = *val * *d;
        }
        x
    }
}

impl<F: SemiImplicit> Scheme<F> for Diagonal<F> {
    fn new(f: F, dt: Self::Time) -> Self {
        let diag = f.diag();
        let mut exp_diag = diag.to_owned();
        for v in exp_diag.iter_mut() {
            *v = v.mul_real(dt).exp();
        }
        Diagonal {
            exp_diag: exp_diag,
            diag: diag,
            dt: dt,
        }
    }
}

#[derive(Debug, Clone)]
pub struct DiagRK4<F: SemiImplicit> {
    nlin: F,
    lin: Diagonal<F>,
    dt: <Diagonal<F> as TimeStep>::Time,
    x: Array<F::Scalar, F::Dim>,
    lx: Array<F::Scalar, F::Dim>,
    k1: Array<F::Scalar, F::Dim>,
    k2: Array<F::Scalar, F::Dim>,
    k3: Array<F::Scalar, F::Dim>,
}

impl<F: SemiImplicit> Scheme<F> for DiagRK4<F> {
    fn new(nlin: F, dt: Self::Time) -> Self {
        let lin = Diagonal::new(nlin.clone(), dt / into_scalar(2.0));
        let x = Array::zeros(lin.model_size());
        let lx = Array::zeros(lin.model_size());
        let k1 = Array::zeros(lin.model_size());
        let k2 = Array::zeros(lin.model_size());
        let k3 = Array::zeros(lin.model_size());
        DiagRK4 {
            nlin,
            lin,
            dt,
            x,
            lx,
            k1,
            k2,
            k3,
        }
    }
}

impl<F: SemiImplicit> TimeStep for DiagRK4<F> {
    type Time = <Diagonal<F> as TimeStep>::Time;

    fn get_dt(&self) -> Self::Time {
        self.dt
    }

    fn set_dt(&mut self, dt: Self::Time) {
        self.lin.set_dt(dt / into_scalar(2.0));
    }
}

impl<F: SemiImplicit> ModelSpec for DiagRK4<F> {
    type Scalar = F::Scalar;
    type Dim = F::Dim;

    fn model_size(&self) -> <Self::Dim as Dimension>::Pattern {
        self.nlin.model_size() // TODO check
    }
}

impl<F: SemiImplicit> TimeEvolution for DiagRK4<F> {
    fn iterate<'a, S>(
        &mut self,
        x: &'a mut ArrayBase<S, Self::Dim>,
    ) -> &'a mut ArrayBase<S, Self::Dim>
    where
        S: DataMut<Elem = Self::Scalar>,
    {
        // constants
        let dt = self.dt;
        let dt_2 = self.dt / into_scalar(2.0);
        let dt_3 = self.dt / into_scalar(3.0);
        let dt_6 = self.dt / into_scalar(6.0);
        // operators
        let l = &mut self.lin;
        let f = &mut self.nlin;
        // calc
        self.x.zip_mut_with(x, |buf, x| *buf = *x);
        self.lx.zip_mut_with(x, |buf, lx| *buf = *lx);
        l.iterate(&mut self.lx);
        let k1 = f.nlin(x);
        self.k1.zip_mut_with(k1, |buf, k1| *buf = *k1);
        Zip::from(&mut *k1).and(&self.x).apply(|k1, &x_| {
            *k1 = x_ + k1.mul_real(dt_2);
        });
        let k2 = f.nlin(l.iterate(k1));
        self.k2.zip_mut_with(k2, |buf, k| *buf = *k);
        Zip::from(&mut *k2).and(&self.lx).apply(|k2, &lx| {
            *k2 = lx + k2.mul_real(dt_2);
        });
        let k3 = f.nlin(k2);
        self.k3.zip_mut_with(k3, |buf, k| *buf = *k);
        Zip::from(&mut *k3).and(&self.lx).apply(|k3, &lx| {
            *k3 = lx + k3.mul_real(dt);
        });
        let k4 = f.nlin(l.iterate(k3));
        Zip::from(&mut self.x)
            .and(&self.k1)
            .apply(|x_, k1_| *x_ = *x_ + k1_.mul_real(dt_6));
        l.iterate(&mut self.x);
        Zip::from(&mut self.x)
            .and(&self.k2)
            .and(&self.k3)
            .apply(|x_, &k2_, &k3_| *x_ = *x_ + (k2_ + k3_).mul_real(dt_3));
        l.iterate(&mut self.x);
        Zip::from(&mut *k4).and(&self.x).apply(|k4, &x_| {
            *k4 = x_ + k4.mul_real(dt_6);
        });
        k4
    }
}
<|endoftext|>


<commit_before>
mod types;
mod input;
mod output;
pub use self::output::Output;
pub use self::input::InputParameter;
use {ffi, DataSource, Return, Result, Raii, Handle, Connected};
use ffi::SQLRETURN::*;
use std::marker::PhantomData;

/// `Statement` state used to represent a freshly allocated connection
pub enum Allocated {}
/// `Statement` state used to represent a statement with a result set cursor
///
/// A statement is most likely to enter this state after a `SELECT` query.
pub enum HasResult {}
/// `Statement` state used to represent a statement with no result set
///
/// A statement is likely to enter this state after executing e.g. a `CREATE TABLE` statement
type NoResult = Allocated; // pub enum NoResult {}

/// Holds a `Statement` after execution of a query.Allocated
///
/// A executed statement may be in one of two states. Either the statement has yielded a result set
/// or not. Keep in mind that some ODBC drivers just yield empty result sets on e.g. `INSERT`
/// Statements
pub enum Executed<'a, 'b> {
    Data(Statement<'a, 'b, HasResult>),
    NoData(Statement<'a, 'b, NoResult>),
}
pub use Executed::*;

/// RAII wrapper around ODBC statement
pub struct Statement<'a, 'b, S> {
    raii: Raii<ffi::Stmt>,
    // we use phantom data to tell the borrow checker that we need to keep the data source alive
    // for the lifetime of the statement
    parent: PhantomData<&'a DataSource<'a, Connected>>,
    state: PhantomData<S>,
    parameters: PhantomData<&'b [u8]>,
}

/// Used to retrieve data from the fields of a query resul
pub struct Cursor<'a, 'b: 'a, 'c : 'a> {
    stmt: &'a mut Statement<'b, 'c, HasResult>,
    buffer: [u8; 512],
}

impl<'a, 'b, S> Handle for Statement<'a, 'b, S> {
    type To = ffi::Stmt;
    unsafe fn handle(&self) -> ffi::SQLHSTMT {
        self.raii.handle()
    }
}

impl<'a, 'b, S> Statement<'a, 'b, S> {
    fn with_raii(raii: Raii<ffi::Stmt>) -> Self {
        Statement {
            raii: raii,
            parent: PhantomData,
            state: PhantomData,
            parameters: PhantomData,
        }
    }
}

impl<'a, 'b> Statement<'a, 'b, Allocated> {
    pub fn with_parent(ds: &'a DataSource<Connected>) -> Result<Self> {
        let raii = Raii::with_parent(ds).into_result(ds)?;
        Ok(Self::with_raii(raii))
    }

    pub fn tables(mut self) -> Result<Statement<'a, 'b, HasResult>> {
        self.raii.tables().into_result(&self)?;
        Ok(Statement::with_raii(self.raii))
    }

    /// Executes a preparable statement, using the current values of the parameter marker variables
    /// if any parameters exist in the statement.
    ///
    /// `SQLExecDirect` is the fastest way to submit an SQL statement for one-time execution.
    pub fn exec_direct(mut self, statement_text: &str) -> Result<Executed<'a, 'b>> {
        if self.raii.exec_direct(statement_text).into_result(&self)? {
            Ok(Executed::Data(Statement::with_raii(self.raii)))
        } else {
            Ok(Executed::NoData(Statement::with_raii(self.raii)))
        }
    }
}

impl<'a, 'b> Statement<'a, 'b, HasResult> {
    /// The number of columns in a result set
    ///
    /// Can be called successfully only when the statement is in the prepared, executed, or
    /// positioned state. If the statement does not return columns the result will be 0.
    pub fn num_result_cols(&self) -> Result<i16> {
        self.raii.num_result_cols().into_result(self)
    }

    /// Fetches the next rowset of data from the result set and returns data for all bound columns.
    ///
    /// # Return
    /// Returns false on the last row
    pub fn fetch<'c>(&'c mut self) -> Result<Option<Cursor<'c, 'a, 'b>>> {
        if self.raii.fetch().into_result(self)? {
            Ok(Some(Cursor {
                stmt: self,
                buffer: [0u8; 512],
            }))
        } else {
            Ok(None)
        }
    }

    /// Call this method to reuse the statement to execute another query.
    ///
    /// For many drivers allocating new statemens is expensive. So reusing a `Statement` is usually
    /// more efficient than freeing an existing and alloctaing a new one. However to reuse a
    /// statement any open result sets must be closed.
    /// Only call this method if you have already read the result set returned by the previous
    /// query, or if you do no not intend to read it.
    ///
    /// # Example
    ///
    /// ```
    /// # use odbc::*;
    /// # fn reuse () -> Result<()> {
    /// let env = Environment::new().unwrap().set_odbc_version_3()?;
    /// let conn = DataSource::with_parent(&env)?.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// let stmt = match stmt.exec_direct("CREATE TABLE STAGE (A TEXT, B TEXT);")?{
    ///     // Some drivers will return an empty result set. We need to close it before we can use
    ///     // statement again.
    ///     Data(stmt) => stmt.close_cursor()?,
    ///     NoData(stmt) => stmt,
    /// };
    /// let stmt = stmt.exec_direct("INSERT INTO STAGE (A, B) VALUES ('Hello', 'World');")?;
    /// //...
    /// # Ok(())
    /// # };
    /// ```
    pub fn close_cursor(mut self) -> Result<Statement<'a, 'b, NoResult>> {
        self.raii.close_cursor().into_result(&self)?;
        Ok(Statement::with_raii(self.raii))
    }
}

impl<'a, 'b, 'c> Cursor<'a, 'b, 'c> {
    /// Retrieves data for a single column in the result set
    pub fn get_data<'d, T>(&'d mut self, col_or_param_num: u16) -> Result<Option<T>>
        where T: Output<'d>
    {
        T::get_data(&mut self.stmt.raii, col_or_param_num, &mut self.buffer).into_result(self.stmt)
    }
}

impl Raii<ffi::Stmt> {
    fn num_result_cols(&self) -> Return<i16> {
        let mut num_cols: ffi::SQLSMALLINT = 0;
        unsafe {
            match ffi::SQLNumResultCols(self.handle(), &mut num_cols as *mut ffi::SQLSMALLINT) {
                SQL_SUCCESS => Return::Success(num_cols),
                SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(num_cols),
                SQL_ERROR => Return::Error,
                r => panic!("SQLNumResultCols returned unexpected result: {:?}", r),
            }
        }
    }

    fn exec_direct(&mut self, statement_text: &str) -> Return<bool> {
        let length = statement_text.len();
        if length > ffi::SQLINTEGER::max_value() as usize {
            panic!("Statement text too long");
        }
        match unsafe {
            ffi::SQLExecDirect(self.handle(),
                               statement_text.as_ptr(),
                               length as ffi::SQLINTEGER)
        } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NEED_DATA => panic!("SQLExecDirec returned SQL_NEED_DATA"),
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLExecDirect returned unexpected result: {:?}", r),
        }
    }

    /// Fetches the next rowset of data from the result set and returns data for all bound columns.
    fn fetch(&mut self) -> Return<bool> {
        match unsafe { ffi::SQLFetch(self.handle()) } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLFetch returned unexpected result: {:?}", r),
        }
    }

    fn tables(&mut self) -> Return<()> {
        let catalog_name = "";
        let schema_name = "";
        let table_name = "";
        let table_type = "TABLE";
        unsafe {
            match ffi::SQLTables(self.handle(),
                                 catalog_name.as_ptr(),
                                 catalog_name.as_bytes().len() as ffi::SQLSMALLINT,
                                 schema_name.as_ptr(),
                                 schema_name.as_bytes().len() as ffi::SQLSMALLINT,
                                 table_name.as_ptr(),
                                 table_name.as_bytes().len() as ffi::SQLSMALLINT,
                                 table_type.as_ptr(),
                                 table_type.as_bytes().len() as ffi::SQLSMALLINT) {
                SQL_SUCCESS => Return::Success(()),
                SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
                SQL_ERROR => Return::Error,
                r => panic!("SQLTables returned: {:?}", r),
            }
        }
    }

    fn close_cursor(&mut self) -> Return<()> {
        unsafe {
            match ffi::SQLCloseCursor(self.handle()) {
                ffi::SQL_SUCCESS => Return::Success(()),
                ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
                ffi::SQL_ERROR => Return::Error,
                r => panic!("unexpected return value from SQLCloseCursor: {:?}", r),
            }
        }
    }
}
<commit_msg>fix typo<commit_after>
mod types;
mod input;
mod output;
pub use self::output::Output;
pub use self::input::InputParameter;
use {ffi, DataSource, Return, Result, Raii, Handle, Connected};
use ffi::SQLRETURN::*;
use std::marker::PhantomData;

/// `Statement` state used to represent a freshly allocated connection
pub enum Allocated {}
/// `Statement` state used to represent a statement with a result set cursor
///
/// A statement is most likely to enter this state after a `SELECT` query.
pub enum HasResult {}
/// `Statement` state used to represent a statement with no result set
///
/// A statement is likely to enter this state after executing e.g. a `CREATE TABLE` statement
type NoResult = Allocated; // pub enum NoResult {}

/// Holds a `Statement` after execution of a query.Allocated
///
/// A executed statement may be in one of two states. Either the statement has yielded a result set
/// or not. Keep in mind that some ODBC drivers just yield empty result sets on e.g. `INSERT`
/// Statements
pub enum Executed<'a, 'b> {
    Data(Statement<'a, 'b, HasResult>),
    NoData(Statement<'a, 'b, NoResult>),
}
pub use Executed::*;

/// RAII wrapper around ODBC statement
pub struct Statement<'a, 'b, S> {
    raii: Raii<ffi::Stmt>,
    // we use phantom data to tell the borrow checker that we need to keep the data source alive
    // for the lifetime of the statement
    parent: PhantomData<&'a DataSource<'a, Connected>>,
    state: PhantomData<S>,
    parameters: PhantomData<&'b [u8]>,
}

/// Used to retrieve data from the fields of a query result
pub struct Cursor<'a, 'b: 'a, 'c : 'a> {
    stmt: &'a mut Statement<'b, 'c, HasResult>,
    buffer: [u8; 512],
}

impl<'a, 'b, S> Handle for Statement<'a, 'b, S> {
    type To = ffi::Stmt;
    unsafe fn handle(&self) -> ffi::SQLHSTMT {
        self.raii.handle()
    }
}

impl<'a, 'b, S> Statement<'a, 'b, S> {
    fn with_raii(raii: Raii<ffi::Stmt>) -> Self {
        Statement {
            raii: raii,
            parent: PhantomData,
            state: PhantomData,
            parameters: PhantomData,
        }
    }
}

impl<'a, 'b> Statement<'a, 'b, Allocated> {
    pub fn with_parent(ds: &'a DataSource<Connected>) -> Result<Self> {
        let raii = Raii::with_parent(ds).into_result(ds)?;
        Ok(Self::with_raii(raii))
    }

    pub fn tables(mut self) -> Result<Statement<'a, 'b, HasResult>> {
        self.raii.tables().into_result(&self)?;
        Ok(Statement::with_raii(self.raii))
    }

    /// Executes a preparable statement, using the current values of the parameter marker variables
    /// if any parameters exist in the statement.
    ///
    /// `SQLExecDirect` is the fastest way to submit an SQL statement for one-time execution.
    pub fn exec_direct(mut self, statement_text: &str) -> Result<Executed<'a, 'b>> {
        if self.raii.exec_direct(statement_text).into_result(&self)? {
            Ok(Executed::Data(Statement::with_raii(self.raii)))
        } else {
            Ok(Executed::NoData(Statement::with_raii(self.raii)))
        }
    }
}

impl<'a, 'b> Statement<'a, 'b, HasResult> {
    /// The number of columns in a result set
    ///
    /// Can be called successfully only when the statement is in the prepared, executed, or
    /// positioned state. If the statement does not return columns the result will be 0.
    pub fn num_result_cols(&self) -> Result<i16> {
        self.raii.num_result_cols().into_result(self)
    }

    /// Fetches the next rowset of data from the result set and returns data for all bound columns.
    ///
    /// # Return
    /// Returns false on the last row
    pub fn fetch<'c>(&'c mut self) -> Result<Option<Cursor<'c, 'a, 'b>>> {
        if self.raii.fetch().into_result(self)? {
            Ok(Some(Cursor {
                stmt: self,
                buffer: [0u8; 512],
            }))
        } else {
            Ok(None)
        }
    }

    /// Call this method to reuse the statement to execute another query.
    ///
    /// For many drivers allocating new statemens is expensive. So reusing a `Statement` is usually
    /// more efficient than freeing an existing and alloctaing a new one. However to reuse a
    /// statement any open result sets must be closed.
    /// Only call this method if you have already read the result set returned by the previous
    /// query, or if you do no not intend to read it.
    ///
    /// # Example
    ///
    /// ```
    /// # use odbc::*;
    /// # fn reuse () -> Result<()> {
    /// let env = Environment::new().unwrap().set_odbc_version_3()?;
    /// let conn = DataSource::with_parent(&env)?.connect("TestDataSource", "", "")?;
    /// let stmt = Statement::with_parent(&conn)?;
    /// let stmt = match stmt.exec_direct("CREATE TABLE STAGE (A TEXT, B TEXT);")?{
    ///     // Some drivers will return an empty result set. We need to close it before we can use
    ///     // statement again.
    ///     Data(stmt) => stmt.close_cursor()?,
    ///     NoData(stmt) => stmt,
    /// };
    /// let stmt = stmt.exec_direct("INSERT INTO STAGE (A, B) VALUES ('Hello', 'World');")?;
    /// //...
    /// # Ok(())
    /// # };
    /// ```
    pub fn close_cursor(mut self) -> Result<Statement<'a, 'b, NoResult>> {
        self.raii.close_cursor().into_result(&self)?;
        Ok(Statement::with_raii(self.raii))
    }
}

impl<'a, 'b, 'c> Cursor<'a, 'b, 'c> {
    /// Retrieves data for a single column in the result set
    pub fn get_data<'d, T>(&'d mut self, col_or_param_num: u16) -> Result<Option<T>>
        where T: Output<'d>
    {
        T::get_data(&mut self.stmt.raii, col_or_param_num, &mut self.buffer).into_result(self.stmt)
    }
}

impl Raii<ffi::Stmt> {
    fn num_result_cols(&self) -> Return<i16> {
        let mut num_cols: ffi::SQLSMALLINT = 0;
        unsafe {
            match ffi::SQLNumResultCols(self.handle(), &mut num_cols as *mut ffi::SQLSMALLINT) {
                SQL_SUCCESS => Return::Success(num_cols),
                SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(num_cols),
                SQL_ERROR => Return::Error,
                r => panic!("SQLNumResultCols returned unexpected result: {:?}", r),
            }
        }
    }

    fn exec_direct(&mut self, statement_text: &str) -> Return<bool> {
        let length = statement_text.len();
        if length > ffi::SQLINTEGER::max_value() as usize {
            panic!("Statement text too long");
        }
        match unsafe {
            ffi::SQLExecDirect(self.handle(),
                               statement_text.as_ptr(),
                               length as ffi::SQLINTEGER)
        } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NEED_DATA => panic!("SQLExecDirec returned SQL_NEED_DATA"),
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLExecDirect returned unexpected result: {:?}", r),
        }
    }

    /// Fetches the next rowset of data from the result set and returns data for all bound columns.
    fn fetch(&mut self) -> Return<bool> {
        match unsafe { ffi::SQLFetch(self.handle()) } {
            ffi::SQL_SUCCESS => Return::Success(true),
            ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(true),
            ffi::SQL_ERROR => Return::Error,
            ffi::SQL_NO_DATA => Return::Success(false),
            r => panic!("SQLFetch returned unexpected result: {:?}", r),
        }
    }

    fn tables(&mut self) -> Return<()> {
        let catalog_name = "";
        let schema_name = "";
        let table_name = "";
        let table_type = "TABLE";
        unsafe {
            match ffi::SQLTables(self.handle(),
                                 catalog_name.as_ptr(),
                                 catalog_name.as_bytes().len() as ffi::SQLSMALLINT,
                                 schema_name.as_ptr(),
                                 schema_name.as_bytes().len() as ffi::SQLSMALLINT,
                                 table_name.as_ptr(),
                                 table_name.as_bytes().len() as ffi::SQLSMALLINT,
                                 table_type.as_ptr(),
                                 table_type.as_bytes().len() as ffi::SQLSMALLINT) {
                SQL_SUCCESS => Return::Success(()),
                SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
                SQL_ERROR => Return::Error,
                r => panic!("SQLTables returned: {:?}", r),
            }
        }
    }

    fn close_cursor(&mut self) -> Return<()> {
        unsafe {
            match ffi::SQLCloseCursor(self.handle()) {
                ffi::SQL_SUCCESS => Return::Success(()),
                ffi::SQL_SUCCESS_WITH_INFO => Return::SuccessWithInfo(()),
                ffi::SQL_ERROR => Return::Error,
                r => panic!("unexpected return value from SQLCloseCursor: {:?}", r),
            }
        }
    }
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Tagged stream
//!
//! A tagged stream recursively applies tags to regions of an input stream. A stream consisting of a single tag forms a tree,
//! so this stream type is useful for representing the parsed represention of an input.
//!
//! The simplest form of tagged stream is one that's just a set of untagged symbols. This can be created using the `TaggedStream::from_reader`
//! method.
//!
//! ```
//! # use concordance::*;
//! #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
//! enum SomeTag {
//!     Identifier
//! };
//!
//! let simple_tagged = TaggedStream::from_reader(&mut "Hello, world".read_symbols());
//! let with_tag      = simple_tagged.with_tags(vec![(0..5, SomeTag::Identifier)].iter().cloned());
//! ```
//!

// TODO: a possibly better way to design this would be to make it so that there's an underlying stream we read from when generating tag
// symbols so that we don't need to store the contents of the stream in memory

use std::slice::Iter;
use std::ops::Index;
use std::ops::Range;

use super::symbol_reader::*;
use super::tokenizer::*;
use super::symbol_range_dfa::*;

///
/// Represents a symbol in a tagged stream.
///
/// A symbol can either be a sequence of untagged base symbols, or it can be a tag (which itself can contain any number of tagged symbol)
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TagSymbol<Base: Clone+Ord, Tag: Clone+Ord> {
    /// An untagged element in this stream
    Untagged(Base),

    /// A tagged region of the stream
    Tagged(Tag, TaggedStream<Base, Tag>)
}

///
/// Represents a stream of tagged symbols
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TaggedStream<Base: Clone+Ord, Tag: Clone+Ord> {
    /// The data in this stream
    data: Vec<TagSymbol<Base, Tag>>
}

impl<Base: Ord+Clone, Tag: Ord+Clone> TaggedStream<Base, Tag> {
    ///
    /// Creates a basic tagged stream from a source of the base symbol
    ///
    pub fn from_reader(reader: &mut SymbolReader<Base>) -> TaggedStream<Base, Tag> {
        // Read from the reader into an array
        let mut symbols = vec![];

        while let Some(next_symbol) = reader.next_symbol() {
            symbols.push(TagSymbol::Untagged(next_symbol));
        }

        // Generate a simple tagged stream from the result
        TaggedStream { data: symbols }
    }

    ///
    /// The number of symbols in this stream
    ///
    pub fn len(&self) -> usize {
        self.data.len()
    }

    ///
    /// Replaces a range in this stream with a tag
    ///
    pub fn tag(&mut self, tag: Tag, range: Range<usize>) {
        // Create a tag to replace the range
        let replaced_symbols    = self.data[range.clone()].to_vec();
        let tag_symbol          = TagSymbol::Tagged(tag, TaggedStream { data: replaced_symbols });

        // Draining seems to be for reading a range but does double duty for deleting a range?
        // I don't think rust has a way to replace a range in a vector, or at least not one that's easy to find in the docs.
        self.data.drain(range.clone());

        // Draining then inserting is inefficient compared to flat out replacing items :-/ This may be possible but the vec docs aren't very easy to read
        self.data.insert(range.start, tag_symbol);
    }

    ///
    /// Creates a tag symbol by tagging a particular range within this stream
    ///
    pub fn tag_range(&self, range: Range<usize>, tag: Tag) -> TagSymbol<Base, Tag> {
        let tag_data = self.data[range].to_vec();

        TagSymbol::Tagged(tag, TaggedStream { data: tag_data })
    }

    ///
    /// Applies tags to the specified ranges in this stream
    ///
    /// The tag ranges must be in ascending order and must not overlap
    ///
    pub fn with_tags<I>(&self, tags: I) -> TaggedStream<Base, Tag>
        where I : Iterator<Item=(Range<usize>, Tag)> {
        // The data that will make up the new stream
        let mut new_stream = vec![];

        // The last processed range (we haven't processed any range yet, so this starts at 0..0)
        let mut last_range = 0..0;

        // Build up the result from the tag list and the last range
        for tag in tags {
            // Fetch the information for this tag and check ordering
            let (next_range, next_tag)  = tag;
            let end                     = last_range.end;

            if end > next_range.start {
                panic!("Tags for with_tags must be sorted in order");
            }

            // Sometimes need to leave some data from this stream untagged
            if end < next_range.start {
                new_stream.extend(self.data[end..next_range.start].iter().cloned());
            }

            // Push the tag
            new_stream.push(self.tag_range(next_range.clone(), next_tag));

            // Update state
            last_range = next_range;
        }

        // Append anything left in the stream
        if last_range.end < self.data.len() {
            new_stream.extend(self.data[last_range.end..self.data.len()].iter().cloned());
        }

        // Final result
        TaggedStream { data: new_stream }
    }

    ///
    /// Runs the current values of this tagged stream through a tokenizer and tags anything it matches
    ///
    /// This takes a mapping function: the idea is that
    ///
    pub fn tokenize<DfaSymbol: Ord>(&self, dfa: &SymbolRangeDfa<DfaSymbol, Tag>, map_symbol: Fn(TagSymbol<Base, Tag>) -> Option<DfaSymbol>) -> TaggedStream<Base, Tag> {
        unimplemented!();
    }
}

impl<Base: Clone+Ord, Tag: Clone+Ord> Index<usize> for TaggedStream<Base, Tag> {
    type Output = TagSymbol<Base, Tag>;

    fn index(&self, index: usize) -> &TagSymbol<Base, Tag> {
        &self.data[index]
    }
}

impl<'a, Base: Clone+Ord, Tag: Clone+Ord> SymbolSource<'a, TagSymbol<Base, Tag>> for &'a TaggedStream<Base, Tag> {
    type SymbolReader = Iter<'a, TagSymbol<Base, Tag>>;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader {
        self.data.read_symbols()
    }
}

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

    #[test]
    fn can_tag_range() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let mut tagged: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());

        tagged.tag(Tags::Hello, 0..5);
        tagged.tag(Tags::World, 1..6);

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn can_tag_everything_with_tags() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello), (5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_middle() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..4, Tags::Hello), (6..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 4);
        assert!(tagged[1] == TagSymbol::Untagged('o'));
        assert!(tagged[2] == TagSymbol::Untagged('W'));

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[3] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('o'));
            assert!(stream[1] == TagSymbol::Untagged('r'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_end() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        assert!(tagged[1] == TagSymbol::Untagged('W'));
        assert!(tagged[2] == TagSymbol::Untagged('o'));
        assert!(tagged[3] == TagSymbol::Untagged('r'));
        assert!(tagged[4] == TagSymbol::Untagged('l'));
        assert!(tagged[5] == TagSymbol::Untagged('d'));
    }

    #[test]
    fn with_tags_preserves_start() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[5] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }

        assert!(tagged[0] == TagSymbol::Untagged('H'));
        assert!(tagged[1] == TagSymbol::Untagged('e'));
        assert!(tagged[2] == TagSymbol::Untagged('l'));
        assert!(tagged[3] == TagSymbol::Untagged('l'));
        assert!(tagged[4] == TagSymbol::Untagged('o'));
    }
}
<commit_msg>Make this part of the type declaration<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! # Tagged stream
//!
//! A tagged stream recursively applies tags to regions of an input stream. A stream consisting of a single tag forms a tree,
//! so this stream type is useful for representing the parsed represention of an input.
//!
//! The simplest form of tagged stream is one that's just a set of untagged symbols. This can be created using the `TaggedStream::from_reader`
//! method.
//!
//! ```
//! # use concordance::*;
//! #[derive(Ord, PartialOrd, Eq, PartialEq, Clone)]
//! enum SomeTag {
//!     Identifier
//! };
//!
//! let simple_tagged = TaggedStream::from_reader(&mut "Hello, world".read_symbols());
//! let with_tag      = simple_tagged.with_tags(vec![(0..5, SomeTag::Identifier)].iter().cloned());
//! ```
//!

// TODO: a possibly better way to design this would be to make it so that there's an underlying stream we read from when generating tag
// symbols so that we don't need to store the contents of the stream in memory

use std::slice::Iter;
use std::ops::Index;
use std::ops::Range;

use super::symbol_reader::*;
use super::tokenizer::*;
use super::symbol_range_dfa::*;

///
/// Represents a symbol in a tagged stream.
///
/// A symbol can either be a sequence of untagged base symbols, or it can be a tag (which itself can contain any number of tagged symbol)
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum TagSymbol<Base: Clone+Ord, Tag: Clone+Ord> {
    /// An untagged element in this stream
    Untagged(Base),

    /// A tagged region of the stream
    Tagged(Tag, TaggedStream<Base, Tag>)
}

///
/// Represents a stream of tagged symbols
///
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TaggedStream<Base: Clone+Ord, Tag: Clone+Ord> {
    /// The data in this stream
    data: Vec<TagSymbol<Base, Tag>>
}

impl<Base: Ord+Clone, Tag: Ord+Clone> TaggedStream<Base, Tag> {
    ///
    /// Creates a basic tagged stream from a source of the base symbol
    ///
    pub fn from_reader(reader: &mut SymbolReader<Base>) -> TaggedStream<Base, Tag> {
        // Read from the reader into an array
        let mut symbols = vec![];

        while let Some(next_symbol) = reader.next_symbol() {
            symbols.push(TagSymbol::Untagged(next_symbol));
        }

        // Generate a simple tagged stream from the result
        TaggedStream { data: symbols }
    }

    ///
    /// The number of symbols in this stream
    ///
    pub fn len(&self) -> usize {
        self.data.len()
    }

    ///
    /// Replaces a range in this stream with a tag
    ///
    pub fn tag(&mut self, tag: Tag, range: Range<usize>) {
        // Create a tag to replace the range
        let replaced_symbols    = self.data[range.clone()].to_vec();
        let tag_symbol          = TagSymbol::Tagged(tag, TaggedStream { data: replaced_symbols });

        // Draining seems to be for reading a range but does double duty for deleting a range?
        // I don't think rust has a way to replace a range in a vector, or at least not one that's easy to find in the docs.
        self.data.drain(range.clone());

        // Draining then inserting is inefficient compared to flat out replacing items :-/ This may be possible but the vec docs aren't very easy to read
        self.data.insert(range.start, tag_symbol);
    }

    ///
    /// Creates a tag symbol by tagging a particular range within this stream
    ///
    pub fn tag_range(&self, range: Range<usize>, tag: Tag) -> TagSymbol<Base, Tag> {
        let tag_data = self.data[range].to_vec();

        TagSymbol::Tagged(tag, TaggedStream { data: tag_data })
    }

    ///
    /// Applies tags to the specified ranges in this stream
    ///
    /// The tag ranges must be in ascending order and must not overlap
    ///
    pub fn with_tags<I>(&self, tags: I) -> TaggedStream<Base, Tag>
        where I : Iterator<Item=(Range<usize>, Tag)> {
        // The data that will make up the new stream
        let mut new_stream = vec![];

        // The last processed range (we haven't processed any range yet, so this starts at 0..0)
        let mut last_range = 0..0;

        // Build up the result from the tag list and the last range
        for tag in tags {
            // Fetch the information for this tag and check ordering
            let (next_range, next_tag)  = tag;
            let end                     = last_range.end;

            if end > next_range.start {
                panic!("Tags for with_tags must be sorted in order");
            }

            // Sometimes need to leave some data from this stream untagged
            if end < next_range.start {
                new_stream.extend(self.data[end..next_range.start].iter().cloned());
            }

            // Push the tag
            new_stream.push(self.tag_range(next_range.clone(), next_tag));

            // Update state
            last_range = next_range;
        }

        // Append anything left in the stream
        if last_range.end < self.data.len() {
            new_stream.extend(self.data[last_range.end..self.data.len()].iter().cloned());
        }

        // Final result
        TaggedStream { data: new_stream }
    }

    ///
    /// Runs the current values of this tagged stream through a tokenizer and tags anything it matches
    ///
    /// This takes a mapping function: the idea is that
    ///
    pub fn tokenize<DfaSymbol: Ord, MapFn>(&self, dfa: &SymbolRangeDfa<DfaSymbol, Tag>, map_symbol: MapFn) -> TaggedStream<Base, Tag>
        where MapFn: Fn(TagSymbol<Base, Tag>) -> Option<DfaSymbol> {
        unimplemented!();
    }
}

impl<Base: Clone+Ord, Tag: Clone+Ord> Index<usize> for TaggedStream<Base, Tag> {
    type Output = TagSymbol<Base, Tag>;

    fn index(&self, index: usize) -> &TagSymbol<Base, Tag> {
        &self.data[index]
    }
}

impl<'a, Base: Clone+Ord, Tag: Clone+Ord> SymbolSource<'a, TagSymbol<Base, Tag>> for &'a TaggedStream<Base, Tag> {
    type SymbolReader = Iter<'a, TagSymbol<Base, Tag>>;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader {
        self.data.read_symbols()
    }
}

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

    #[test]
    fn can_tag_range() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let mut tagged: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());

        tagged.tag(Tags::Hello, 0..5);
        tagged.tag(Tags::World, 1..6);

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn can_tag_everything_with_tags() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello), (5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 2);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[1] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_middle() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello,
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..4, Tags::Hello), (6..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 4);
        assert!(tagged[1] == TagSymbol::Untagged('o'));
        assert!(tagged[2] == TagSymbol::Untagged('W'));

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
        } else {
            assert!(false);
        }

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[3] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 4);
            assert!(stream[0] == TagSymbol::Untagged('o'));
            assert!(stream[1] == TagSymbol::Untagged('r'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }
    }

    #[test]
    fn with_tags_preserves_end() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            Hello
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(0..5, Tags::Hello)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[0] {
            assert!(*tag == Tags::Hello);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('H'));
            assert!(stream[1] == TagSymbol::Untagged('e'));
            assert!(stream[2] == TagSymbol::Untagged('l'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('o'));
        } else {
            assert!(false);
        }

        assert!(tagged[1] == TagSymbol::Untagged('W'));
        assert!(tagged[2] == TagSymbol::Untagged('o'));
        assert!(tagged[3] == TagSymbol::Untagged('r'));
        assert!(tagged[4] == TagSymbol::Untagged('l'));
        assert!(tagged[5] == TagSymbol::Untagged('d'));
    }

    #[test]
    fn with_tags_preserves_start() {
        #[derive(Clone, PartialEq, Eq, Copy, PartialOrd, Ord)]
        enum Tags {
            World
        }

        let original: TaggedStream<char, Tags> = TaggedStream::from_reader(&mut "HelloWorld".read_symbols());
        let tagged = original.with_tags(vec![(5..10, Tags::World)].iter().cloned());

        assert!(tagged.len() == 6);

        if let TagSymbol::Tagged(ref tag, ref stream) = tagged[5] {
            assert!(*tag == Tags::World);
            assert!(stream.len() == 5);
            assert!(stream[0] == TagSymbol::Untagged('W'));
            assert!(stream[1] == TagSymbol::Untagged('o'));
            assert!(stream[2] == TagSymbol::Untagged('r'));
            assert!(stream[3] == TagSymbol::Untagged('l'));
            assert!(stream[4] == TagSymbol::Untagged('d'));
        } else {
            assert!(false);
        }

        assert!(tagged[0] == TagSymbol::Untagged('H'));
        assert!(tagged[1] == TagSymbol::Untagged('e'));
        assert!(tagged[2] == TagSymbol::Untagged('l'));
        assert!(tagged[3] == TagSymbol::Untagged('l'));
        assert!(tagged[4] == TagSymbol::Untagged('o'));
    }
}
<|endoftext|>