<commit_before>///! Basic tests for instructions/constructions, missing in wabt tests

use std::sync::{Arc, Weak};
use builder::module;
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
	InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
use interpreter::Error;
use interpreter::env_native::{env_native_module, UserFunctions, UserFunctionExecutor, UserFunctionDescriptor};
use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams, ExportEntryType, FunctionSignature};
use interpreter::program::ProgramInstance;
use interpreter::validator::{FunctionValidationContext, Validator};
use interpreter::value::RuntimeValue;

#[test]
fn import_function() {
	let module1 = module()
		.with_export(ExportEntry::new("external_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module2 = module()
		.with_import(ImportEntry::new("external_module".into(), "external_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let external_module = program.add_module("external_module", module1, None).unwrap();
	let main_module = program.add_module("main", module2, None).unwrap();

	assert_eq!(external_module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(3));
	assert_eq!(main_module.execute_index(1, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(10));
}

#[test]
fn wrong_import() {
	let side_module = module()
		.with_export(ExportEntry::new("cool_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module = module()
		.with_import(ImportEntry::new("side_module".into(), "not_cool_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let _side_module_instance = program.add_module("side_module", side_module, None).unwrap();
	assert!(program.add_module("main", module, None).is_err());
}

#[test]
fn global_get_set() {
	let module = module()
		.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const(42)])))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::GetGlobal(0),
				Opcode::I32Const(8),
				Opcode::I32Add,
				Opcode::SetGlobal(0),
				Opcode::GetGlobal(0),
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let module = program.add_module("main", module, None).unwrap();
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(50));
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(58));
}

const SIGNATURE_I32_I32: &'static [ValueType] = &[ValueType::I32, ValueType::I32];

const SIGNATURES: &'static [UserFunctionDescriptor] = &[
	UserFunctionDescriptor::Static(
		"add",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
	UserFunctionDescriptor::Static(
		"sub",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
];

// user function executor
struct FunctionExecutor {
	pub memory: Arc<MemoryInstance>,
	pub values: Vec<i32>,
}

impl UserFunctionExecutor for FunctionExecutor {
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error> {
		match name {
			"add" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let sum = memory_value + fn_argument;
				self.memory.set(0, &vec![sum]).unwrap();
				self.values.push(sum as i32);
				Ok(Some(RuntimeValue::I32(sum as i32)))
			},
			"sub" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let diff = memory_value - fn_argument;
				self.memory.set(0, &vec![diff]).unwrap();
				self.values.push(diff as i32);
				Ok(Some(RuntimeValue::I32(diff as i32)))
			},
			_ => Err(Error::Trap("not implemented".into())),
		}
	}
}

#[test]
fn single_program_different_modules() {
	// create new program
	let program = ProgramInstance::new().unwrap();
	// => env module is created
	let env_instance = program.module("env").unwrap();
	// => linear memory is created
	let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

	// create native env module executor
	let mut executor = FunctionExecutor {
		memory: env_memory.clone(),
		values: Vec::new(),
	};
	{
		let functions: UserFunctions = UserFunctions {
			executor: &mut executor,
			functions: ::std::borrow::Cow::from(SIGNATURES),
		};
		let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
		let params = ExecutionParams::with_external("env".into(), native_env_instance);

		let module = module()
			.with_import(ImportEntry::new("env".into(), "add".into(), External::Function(0)))
			.with_import(ImportEntry::new("env".into(), "sub".into(), External::Function(0)))
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(0),
					Opcode::End,
				])).build()
				.build()
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(1),
					Opcode::End,
				])).build()
				.build()
			.build();

		// load module
		let module_instance = program.add_module("main", module, Some(&params.externals)).unwrap();

		{
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(7)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(7));
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(50)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(57));
			assert_eq!(module_instance.execute_index(3, params.clone().add_argument(RuntimeValue::I32(15)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(42));
		}
	}

	assert_eq!(executor.memory.get(0, 1).unwrap()[0], 42);
	assert_eq!(executor.values, vec![7, 57, 42]);
}

#[test]
fn env_native_export_entry_type_check() {
	let program = ProgramInstance::new().unwrap();
	let mut function_executor = FunctionExecutor {
		memory: program.module("env").unwrap().memory(ItemIndex::Internal(0)).unwrap(),
		values: Vec::new(),
	};
	let native_env_instance = Arc::new(env_native_module(program.module("env").unwrap(), UserFunctions {
		executor: &mut function_executor,
		functions: ::std::borrow::Cow::from(SIGNATURES),
	}).unwrap());

	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I32))))).is_ok());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![], Some(ValueType::I32))))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], None)))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I64))))).is_err());
}

#[test]
fn if_else_with_return_type_validation() {
	let module_instance = ModuleInstance::new(Weak::default(), "test".into(), module().build()).unwrap();
	let mut context = FunctionValidationContext::new(&module_instance, &[], 1024, 1024, FunctionSignature::Module(&FunctionType::default()));

	Validator::validate_function(&mut context, BlockType::NoResult, &[
		Opcode::I32Const(1),
		Opcode::If(BlockType::NoResult),
			Opcode::I32Const(1),
			Opcode::If(BlockType::Value(ValueType::I32)),
				Opcode::I32Const(1),
			Opcode::Else,
				Opcode::I32Const(2),
			Opcode::End,
		Opcode::Drop,
		Opcode::End,
		Opcode::End,
	]).unwrap();
}
<commit_msg>global import breaks with Function("missing exports with name STACKTOP")<commit_after>///! Basic tests for instructions/constructions, missing in wabt tests

use std::sync::{Arc, Weak};
use builder::module;
use elements::{ExportEntry, Internal, ImportEntry, External, GlobalEntry, GlobalType,
	InitExpr, ValueType, BlockType, Opcodes, Opcode, FunctionType};
use interpreter::Error;
use interpreter::env_native::{env_native_module, UserFunctions, UserFunctionExecutor, UserFunctionDescriptor};
use interpreter::memory::MemoryInstance;
use interpreter::module::{ModuleInstance, ModuleInstanceInterface, CallerContext, ItemIndex, ExecutionParams, ExportEntryType, FunctionSignature};
use interpreter::program::ProgramInstance;
use interpreter::validator::{FunctionValidationContext, Validator};
use interpreter::value::RuntimeValue;

#[test]
fn import_function() {
	let module1 = module()
		.with_export(ExportEntry::new("external_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module2 = module()
		.with_import(ImportEntry::new("external_module".into(), "external_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let external_module = program.add_module("external_module", module1, None).unwrap();
	let main_module = program.add_module("main", module2, None).unwrap();

	assert_eq!(external_module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(3));
	assert_eq!(main_module.execute_index(1, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(10));
}

#[test]
fn wrong_import() {
	let side_module = module()
		.with_export(ExportEntry::new("cool_func".into(), Internal::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::I32Const(3),
				Opcode::End,
			])).build()
			.build()
		.build();

	let module = module()
		.with_import(ImportEntry::new("side_module".into(), "not_cool_func".into(), External::Function(0)))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::Call(0),
				Opcode::I32Const(7),
				Opcode::I32Add,
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let _side_module_instance = program.add_module("side_module", side_module, None).unwrap();
	assert!(program.add_module("main", module, None).is_err());
}

#[test]
fn global_get_set() {
	let module = module()
		.with_global(GlobalEntry::new(GlobalType::new(ValueType::I32, true), InitExpr::new(vec![Opcode::I32Const(42)])))
		.function()
			.signature().return_type().i32().build()
			.body().with_opcodes(Opcodes::new(vec![
				Opcode::GetGlobal(0),
				Opcode::I32Const(8),
				Opcode::I32Add,
				Opcode::SetGlobal(0),
				Opcode::GetGlobal(0),
				Opcode::End,
			])).build()
			.build()
		.build();

	let program = ProgramInstance::new().unwrap();
	let module = program.add_module("main", module, None).unwrap();
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(50));
	assert_eq!(module.execute_index(0, vec![].into()).unwrap().unwrap(), RuntimeValue::I32(58));
}

const SIGNATURE_I32_I32: &'static [ValueType] = &[ValueType::I32, ValueType::I32];

const SIGNATURES: &'static [UserFunctionDescriptor] = &[
	UserFunctionDescriptor::Static(
		"add",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
	UserFunctionDescriptor::Static(
		"sub",
		SIGNATURE_I32_I32,
		Some(ValueType::I32),
	),
];

// user function executor
struct FunctionExecutor {
	pub memory: Arc<MemoryInstance>,
	pub values: Vec<i32>,
}

impl UserFunctionExecutor for FunctionExecutor {
	fn execute(&mut self, name: &str, context: CallerContext) -> Result<Option<RuntimeValue>, Error> {
		match name {
			"add" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let sum = memory_value + fn_argument;
				self.memory.set(0, &vec![sum]).unwrap();
				self.values.push(sum as i32);
				Ok(Some(RuntimeValue::I32(sum as i32)))
			},
			"sub" => {
				let memory_value = self.memory.get(0, 1).unwrap()[0];
				let fn_argument_unused = context.value_stack.pop_as::<u32>().unwrap() as u8;
				let fn_argument = context.value_stack.pop_as::<u32>().unwrap() as u8;
				assert_eq!(fn_argument_unused, 0);

				let diff = memory_value - fn_argument;
				self.memory.set(0, &vec![diff]).unwrap();
				self.values.push(diff as i32);
				Ok(Some(RuntimeValue::I32(diff as i32)))
			},
			_ => Err(Error::Trap("not implemented".into())),
		}
	}
}

#[test]
fn single_program_different_modules() {
	// create new program
	let program = ProgramInstance::new().unwrap();
	// => env module is created
	let env_instance = program.module("env").unwrap();
	// => linear memory is created
	let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

	// create native env module executor
	let mut executor = FunctionExecutor {
		memory: env_memory.clone(),
		values: Vec::new(),
	};
	{
		let functions: UserFunctions = UserFunctions {
			executor: &mut executor,
			functions: ::std::borrow::Cow::from(SIGNATURES),
		};
		let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
		let params = ExecutionParams::with_external("env".into(), native_env_instance);

		let module = module()
			.with_import(ImportEntry::new("env".into(), "add".into(), External::Function(0)))
			.with_import(ImportEntry::new("env".into(), "sub".into(), External::Function(0)))
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(0),
					Opcode::End,
				])).build()
				.build()
			.function()
				.signature().param().i32().param().i32().return_type().i32().build()
				.body().with_opcodes(Opcodes::new(vec![
					Opcode::GetLocal(0),
					Opcode::GetLocal(1),
					Opcode::Call(1),
					Opcode::End,
				])).build()
				.build()
			.build();

		// load module
		let module_instance = program.add_module("main", module, Some(&params.externals)).unwrap();

		{
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(7)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(7));
			assert_eq!(module_instance.execute_index(2, params.clone().add_argument(RuntimeValue::I32(50)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(57));
			assert_eq!(module_instance.execute_index(3, params.clone().add_argument(RuntimeValue::I32(15)).add_argument(RuntimeValue::I32(0))).unwrap().unwrap(), RuntimeValue::I32(42));
		}
	}

	assert_eq!(executor.memory.get(0, 1).unwrap()[0], 42);
	assert_eq!(executor.values, vec![7, 57, 42]);
}

#[test]
fn import_global() {
	// create new program
	let program = ProgramInstance::new().unwrap();
	// => env module is created
	let env_instance = program.module("env").unwrap();
	// => linear memory is created
	let env_memory = env_instance.memory(ItemIndex::Internal(0)).unwrap();

	// create native env module executor
	let mut executor = FunctionExecutor {
		memory: env_memory.clone(),
		values: Vec::new(),
	};
	{
		let functions: UserFunctions = UserFunctions {
			executor: &mut executor,
			functions: ::std::borrow::Cow::from(SIGNATURES),
		};
		let native_env_instance = Arc::new(env_native_module(env_instance, functions).unwrap());
		let params = ExecutionParams::with_external("env".into(), native_env_instance);

		let module = module()
			.with_import(ImportEntry::new("env".into(), "STACKTOP".into(), External::Global(GlobalType::new(ValueType::I32, false))))
			.build();

		// load module
		program.add_module("main", module, Some(&params.externals)).unwrap();
	}

}

#[test]
fn env_native_export_entry_type_check() {
	let program = ProgramInstance::new().unwrap();
	let mut function_executor = FunctionExecutor {
		memory: program.module("env").unwrap().memory(ItemIndex::Internal(0)).unwrap(),
		values: Vec::new(),
	};
	let native_env_instance = Arc::new(env_native_module(program.module("env").unwrap(), UserFunctions {
		executor: &mut function_executor,
		functions: ::std::borrow::Cow::from(SIGNATURES),
	}).unwrap());

	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I32))))).is_ok());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![], Some(ValueType::I32))))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], None)))).is_err());
	assert!(native_env_instance.export_entry("add", &ExportEntryType::Function(FunctionSignature::Module(&FunctionType::new(vec![ValueType::I32, ValueType::I32], Some(ValueType::I64))))).is_err());
}

#[test]
fn if_else_with_return_type_validation() {
	let module_instance = ModuleInstance::new(Weak::default(), "test".into(), module().build()).unwrap();
	let mut context = FunctionValidationContext::new(&module_instance, &[], 1024, 1024, FunctionSignature::Module(&FunctionType::default()));

	Validator::validate_function(&mut context, BlockType::NoResult, &[
		Opcode::I32Const(1),
		Opcode::If(BlockType::NoResult),
			Opcode::I32Const(1),
			Opcode::If(BlockType::Value(ValueType::I32)),
				Opcode::I32Const(1),
			Opcode::Else,
				Opcode::I32Const(2),
			Opcode::End,
		Opcode::Drop,
		Opcode::End,
		Opcode::End,
	]).unwrap();
}
<|endoftext|>


<commit_before>#![crate_name = "jit_macros"]
#![comment = "Macros for LibJIT Bindings"]
#![crate_type = "dylib"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types)]
#![deny(unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, unused_must_use)]
#![feature(globs, plugin_registrar, quote)]
#![experimental]
//! This crate provides some macros for better LibJIT interop
//! For example, here's a quick example of automatic struct compilation to a LibJIT value:
//!
//! ```rust
//! extern crate jit;
//! #[phase(syntax)]
//! extern crate jit_macros;
//! use jit::{C_DECL, Context, Function, Type, Types, get_type};
//!
//! #[jit_compile]
//! struct Pos {
//!     x: f64,
//!     y: f64,
//!     z: f64
//! }
//! fn main() {
//!     let cx = Context::new();
//!     cx.build(|| {
//!         // build the IR
//!         let sig = get_type(fn() -> Pos);
//!         let func = Function::new(cx, sig);
//!         let result = Pos {
//!             x: -10,
//!             y: 0,
//!             z: 10
//!         }.compile();
//!         func.insn_return(&result);
//!         /// run the IR
//!         func.compile();
//!         let rfunc:fn() -> Pos = func.closure0();
//!         assert_eq(rfunc().x, -10)
//!     });
//! }
//! ```
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use std::gc::GC;
use syntax::ast::*;
use syntax::ext::base::*;
use syntax::ext::build::*;
use syntax::ext::quote::rt::*;
use syntax::parse::token::*;
use syntax::owned_slice::OwnedSlice;
pub use context::MacroContext;
use gen_compile::gen_compile_meth;
use gen_type::gen_type_meth;
pub mod context;
pub mod gen_compile;
pub mod gen_type;
fn gen_compile(cx:&mut ExtCtxt, pos:Span, _:P<MetaItem>, item:P<Item>, cb:|P<Item>|) {
    let context = MacroContext::new(cx, pos, item);
    let ref cx = context.cx;
    let methods = vec!(
        box(GC) gen_type_meth(context),
        box(GC) gen_compile_meth(context)
    );
    let node = ItemImpl(
        Generics {
            lifetimes: vec!(),
            ty_params: OwnedSlice::empty()
        },
        Some(cx.trait_ref(cx.path_global(pos, vec!(cx.ident_of("jit"), cx.ident_of("Compile"))))),
        cx.ty_path(cx.path_ident(pos, item.ident), None),
        methods
    );
    cb(cx.item(pos, cx.ident_of("Compile"), vec!(), node));
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(intern("jit_compile"), ItemDecorator(gen_compile));
}<commit_msg>Organise imports in `jit_macros`<commit_after>#![crate_name = "jit_macros"]
#![comment = "Macros for LibJIT Bindings"]
#![crate_type = "dylib"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types)]
#![deny(unnecessary_parens, unrecognized_lint, unreachable_code, unnecessary_allocation, unnecessary_typecast, unnecessary_allocation, uppercase_variables, unused_must_use)]
#![feature(globs, plugin_registrar, quote)]
#![experimental]
//! This crate provides some macros for better LibJIT interop
//! For example, here's a quick example of automatic struct compilation to a LibJIT value:
//!
//! ```rust
//! extern crate jit;
//! #[phase(syntax)]
//! extern crate jit_macros;
//! use jit::{C_DECL, Context, Function, Type, Types, get_type};
//!
//! #[jit_compile]
//! struct Pos {
//!     x: f64,
//!     y: f64,
//!     z: f64
//! }
//! fn main() {
//!     let cx = Context::new();
//!     cx.build(|| {
//!         // build the IR
//!         let sig = get_type(fn() -> Pos);
//!         let func = Function::new(cx, sig);
//!         let result = Pos {
//!             x: -10,
//!             y: 0,
//!             z: 10
//!         }.compile();
//!         func.insn_return(&result);
//!         /// run the IR
//!         func.compile();
//!         let rfunc:fn() -> Pos = func.closure0();
//!         assert_eq(rfunc().x, -10)
//!     });
//! }
//! ```
extern crate rustc;
extern crate syntax;

use context::MacroContext;
use gen_compile::gen_compile_meth;
use gen_type::gen_type_meth;
use rustc::plugin::Registry;
use std::gc::GC;
use syntax::ast::{Generics, Item, ItemImpl, P, MetaItem};
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, ItemDecorator};
use syntax::ext::build::AstBuilder;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::token::intern;
pub mod context;
pub mod gen_compile;
pub mod gen_type;
fn gen_compile(cx:&mut ExtCtxt, pos:Span, _:P<MetaItem>, item:P<Item>, cb:|P<Item>|) {
    let context = MacroContext::new(cx, pos, item);
    let ref cx = context.cx;
    let methods = vec!(
        box(GC) gen_type_meth(context),
        box(GC) gen_compile_meth(context)
    );
    let node = ItemImpl(
        Generics {
            lifetimes: vec!(),
            ty_params: OwnedSlice::empty()
        },
        Some(cx.trait_ref(cx.path_global(pos, vec!(cx.ident_of("jit"), cx.ident_of("Compile"))))),
        cx.ty_path(cx.path_ident(pos, item.ident), None),
        methods
    );
    cb(cx.item(pos, cx.ident_of("Compile"), vec!(), node));
}

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(intern("jit_compile"), ItemDecorator(gen_compile));
}<|endoftext|>


<commit_before>use crate::dep_graph::SerializedDepNodeIndex;
use crate::dep_graph::{DepKind, DepNode};
use crate::hir::def_id::{CrateNum, DefId};
use crate::ty::TyCtxt;
use crate::ty::query::queries;
use crate::ty::query::{Query, QueryName};
use crate::ty::query::QueryCache;
use crate::ty::query::plumbing::CycleError;
use crate::util::profiling::ProfileCategory;

use std::borrow::Cow;
use std::hash::Hash;
use std::fmt::Debug;
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::fingerprint::Fingerprint;
use crate::ich::StableHashingContext;

// Query configuration and description traits.

// FIXME(eddyb) false positive, the lifetime parameter is used for `Key`/`Value`.
#[allow(unused_lifetimes)]
pub trait QueryConfig<'tcx> {
    const NAME: QueryName;
    const CATEGORY: ProfileCategory;

    type Key: Eq + Hash + Clone + Debug;
    type Value: Clone;
}

pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
    const ANON: bool;
    const EVAL_ALWAYS: bool;

    fn query(key: Self::Key) -> Query<'tcx>;

    // Don't use this method to access query results, instead use the methods on TyCtxt
    fn query_cache<'a>(tcx: TyCtxt<'tcx>) -> &'a Sharded<QueryCache<'tcx, Self>>;

    fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;

    fn dep_kind() -> DepKind;

    // Don't use this method to compute query results, instead use the methods on TyCtxt
    fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;

    fn hash_result(
        hcx: &mut StableHashingContext<'_>,
        result: &Self::Value
    ) -> Option<Fingerprint>;

    fn handle_cycle_error(tcx: TyCtxt<'tcx>, error: CycleError<'tcx>) -> Self::Value;
}

pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
    fn describe(tcx: TyCtxt<'_>, key: Self::Key) -> Cow<'static, str>;

    #[inline]
    fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
        false
    }

    fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option<Self::Value> {
        bug!("QueryDescription::load_from_disk() called for an unsupported query.")
    }
}

impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M {
    default fn describe(tcx: TyCtxt<'_>, def_id: DefId) -> Cow<'static, str> {
        if !tcx.sess.verbose() {
            format!("processing `{}`", tcx.def_path_str(def_id)).into()
        } else {
            let name = ::std::any::type_name::<M>();
            format!("processing {:?} with query `{}`", def_id, name).into()
        }
    }
}

impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
    fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> {
        "running analysis passes on this crate".into()
    }
}
<commit_msg>Fix the bootstrap<commit_after>use crate::dep_graph::SerializedDepNodeIndex;
use crate::dep_graph::{DepKind, DepNode};
use crate::hir::def_id::{CrateNum, DefId};
use crate::ty::TyCtxt;
use crate::ty::query::queries;
use crate::ty::query::{Query, QueryName};
use crate::ty::query::QueryCache;
use crate::ty::query::plumbing::CycleError;
use crate::util::profiling::ProfileCategory;

use std::borrow::Cow;
use std::hash::Hash;
use std::fmt::Debug;
use rustc_data_structures::sharded::Sharded;
use rustc_data_structures::fingerprint::Fingerprint;
use crate::ich::StableHashingContext;

// Query configuration and description traits.

// FIXME(eddyb) false positive, the lifetime parameter is used for `Key`/`Value`.
#[allow(unused_lifetimes)]
pub trait QueryConfig<'tcx> {
    const NAME: QueryName;
    const CATEGORY: ProfileCategory;

    type Key: Eq + Hash + Clone + Debug;
    type Value: Clone;
}

pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
    const ANON: bool;
    const EVAL_ALWAYS: bool;

    fn query(key: Self::Key) -> Query<'tcx>;

    // Don't use this method to access query results, instead use the methods on TyCtxt
    fn query_cache<'a>(tcx: TyCtxt<'tcx>) -> &'a Sharded<QueryCache<'tcx, Self>>;

    fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode;

    fn dep_kind() -> DepKind;

    // Don't use this method to compute query results, instead use the methods on TyCtxt
    fn compute(tcx: TyCtxt<'tcx>, key: Self::Key) -> Self::Value;

    fn hash_result(
        hcx: &mut StableHashingContext<'_>,
        result: &Self::Value
    ) -> Option<Fingerprint>;

    fn handle_cycle_error(tcx: TyCtxt<'tcx>, error: CycleError<'tcx>) -> Self::Value;
}

pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
    fn describe(tcx: TyCtxt<'_>, key: Self::Key) -> Cow<'static, str>;

    #[inline]
    fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
        false
    }

    fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option<Self::Value> {
        bug!("QueryDescription::load_from_disk() called for an unsupported query.")
    }
}

impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M {
    default fn describe(tcx: TyCtxt<'_>, def_id: DefId) -> Cow<'static, str> {
        if !tcx.sess.verbose() {
            format!("processing `{}`", tcx.def_path_str(def_id)).into()
        } else {
            let name = ::std::any::type_name::<M>();
            format!("processing {:?} with query `{}`", def_id, name).into()
        }
    }

    default fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool {
        false
    }

    default fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option<Self::Value> {
        bug!("QueryDescription::load_from_disk() called for an unsupported query.")
    }
}

impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> {
    fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> {
        "running analysis passes on this crate".into()
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

use std::rc::Rc;
use syntax::abi;
use syntax::ast::TokenTree;
use syntax::ast;
use syntax::ast_util::empty_generics;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};
use syntax::parse::token::InternedString;
use syntax::ptr::P;

use node;

mod mcu;
mod os;
pub mod meta_args;

pub struct Builder {
  main_stmts: Vec<P<ast::Stmt>>,
  type_items: Vec<P<ast::Item>>,
  pt: Rc<node::PlatformTree>,
}

impl Builder {
  pub fn build(cx: &mut ExtCtxt, pt: Rc<node::PlatformTree>) -> Option<Builder> {
    let mut builder = Builder::new(pt.clone());

    if !pt.expect_subnodes(cx, &["mcu", "os", "drivers"]) {
      return None;
    }

    match pt.get_by_path("mcu") {
      Some(node) => mcu::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): should it actaully fail?
    }

    match pt.get_by_path("os") {
      Some(node) => os::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): this should fail.
    }

    match pt.get_by_path("drivers") {
      Some(node) => ::drivers_pt::attach(&mut builder, cx, node),
      None => (),
    }

    for sub in pt.nodes().iter() {
      Builder::walk_mutate(&mut builder, cx, sub);
    }

    let base_node = pt.get_by_path("mcu").and_then(|mcu|{mcu.get_by_path("clock")});
    match base_node {
      Some(node) => Builder::walk_materialize(&mut builder, cx, node),
      None => {
        cx.parse_sess().span_diagnostic.span_err(DUMMY_SP,
            "root node `mcu::clock` must be present");
      }
    }

    Some(builder)
  }

  fn walk_mutate(builder: &mut Builder, cx: &mut ExtCtxt, node: &Rc<node::Node>) {
    let maybe_mut = node.mutator.get();
    if maybe_mut.is_some() {
      maybe_mut.unwrap()(builder, cx, node.clone());
    }
    for sub in node.subnodes().iter() {
      Builder::walk_mutate(builder, cx, sub);
    }
  }

  // FIXME(farcaller): verify that all nodes have been materialized
  fn walk_materialize(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
    let maybe_mat = node.materializer.get();
    if maybe_mat.is_some() {
      maybe_mat.unwrap()(builder, cx, node.clone());
    }
    let rev_depends = node.rev_depends_on.borrow();
    for weak_sub in rev_depends.iter() {
      let sub = weak_sub.upgrade().unwrap();
      let mut sub_deps = sub.depends_on.borrow_mut();
      let deps = sub_deps.deref_mut();
      let mut index = None;
      let mut i = 0u;
      // FIXME: iter().position()
      for dep in deps.iter() {
        let strong_dep = dep.upgrade().unwrap();
        if node == strong_dep {
          index = Some(i);
          break;
        }
        i = i + 1;
      }
      if index.is_none() {
        panic!("no index found");
      } else {
        deps.remove(index.unwrap());
        if deps.len() == 0 {
          Builder::walk_materialize(builder, cx, sub.clone());
        }
      }
    }
  }

  pub fn new(pt: Rc<node::PlatformTree>) -> Builder {
    Builder {
      main_stmts: Vec::new(),
      type_items: Vec::new(),
      pt: pt,
    }
  }

  pub fn main_stmts(&self) -> Vec<P<ast::Stmt>> {
    self.main_stmts.clone()
  }

  pub fn pt(&self) -> Rc<node::PlatformTree> {
    self.pt.clone()
  }

  pub fn add_main_statement(&mut self, stmt: P<ast::Stmt>) {
    self.main_stmts.push(stmt);
  }

  pub fn add_type_item(&mut self, item: P<ast::Item>) {
    self.type_items.push(item);
  }

  fn emit_main(&self, cx: &ExtCtxt) -> P<ast::Item> {
    // init stack
    let init_stack_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_stack();
    ));

    // init data
    let init_data_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_data();
    ));

    let mut stmts = vec!(init_stack_stmt, init_data_stmt);
    stmts.push_all(self.main_stmts.as_slice());

    let body = cx.block(DUMMY_SP, stmts, None);

    let unused_variables = cx.meta_word(DUMMY_SP,
        InternedString::new("unused_variables"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(unused_variables));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);

    self.item_fn(cx, DUMMY_SP, "main", &[allow_noncamel], body)
  }

  fn emit_morestack(&self, cx: &ExtCtxt) -> P<ast::Item> {
    let stmt = cx.stmt_expr(quote_expr!(&*cx,
        core::intrinsics::abort()
        // or
        // zinc::os::task::morestack();
    ));
    let empty_span = DUMMY_SP;
    let body = cx.block(empty_span, vec!(stmt), None);
    self.item_fn(cx, empty_span, "__morestack", &[], body)
  }

  pub fn emit_items(&self, cx: &ExtCtxt) -> Vec<P<ast::Item>> {
    let non_camel_case_types = cx.meta_word(DUMMY_SP,
        InternedString::new("non_camel_case_types"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(non_camel_case_types));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);
    let use_zinc = cx.view_use_simple(DUMMY_SP, ast::Inherited, cx.path_ident(
        DUMMY_SP, cx.ident_of("zinc")));
    let pt_mod_item = cx.item_mod(DUMMY_SP, DUMMY_SP, cx.ident_of("pt"),
        vec!(allow_noncamel), vec!(use_zinc), self.type_items.clone());

    if self.type_items.len() > 0 {
      vec!(pt_mod_item, self.emit_main(cx), self.emit_morestack(cx))
    } else {
      vec!(self.emit_main(cx), self.emit_morestack(cx))
    }
  }

  fn item_fn(&self, cx: &ExtCtxt, span: Span, name: &str,
      local_attrs: &[ast::Attribute], body: P<ast::Block>)
      -> P<ast::Item> {
    let attr_no_mangle = cx.attribute(span, cx.meta_word(
        span, InternedString::new("no_mangle")));
    let mut attrs = vec!(attr_no_mangle);
    attrs.push_all(local_attrs);

    P(ast::Item {
      ident: cx.ident_of(name),
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemFn(
          cx.fn_decl(Vec::new(), cx.ty(DUMMY_SP, ast::Ty_::TyTup(Vec::new()))),
          ast::UnsafeFn,
          abi::Rust, // TODO(farcaller): should this be abi::C?
          empty_generics(),
          body),
      vis: ast::Public,
      span: span,
    })
  }
}

pub struct TokenString(pub String);

impl ToTokens for TokenString {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    let &TokenString(ref s) = self;
    (cx as &ExtParseUtils).parse_tts(s.clone())
  }
}

pub fn add_node_dependency(node: &Rc<node::Node>, dep: &Rc<node::Node>) {
  let mut depends_on = node.depends_on.borrow_mut();
  depends_on.deref_mut().push(dep.downgrade());

  let mut rev_depends_on = dep.rev_depends_on.borrow_mut();
  rev_depends_on.push(node.downgrade());
}

#[cfg(test)]
mod test {
  use test_helpers::fails_to_build;

  #[test]
  fn fails_to_parse_pt_with_unknown_root_node() {
    fails_to_build("unknown@node {}");
  }

  #[test]
  fn fails_to_parse_pt_with_unknown_mcu() {
    fails_to_build("mcu@bad {}");
  }
}
<commit_msg>platformtree: FnStyle is now Unsafety<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// 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.

use std::rc::Rc;
use syntax::abi;
use syntax::ast::TokenTree;
use syntax::ast;
use syntax::ast_util::empty_generics;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};
use syntax::parse::token::InternedString;
use syntax::ptr::P;

use node;

mod mcu;
mod os;
pub mod meta_args;

pub struct Builder {
  main_stmts: Vec<P<ast::Stmt>>,
  type_items: Vec<P<ast::Item>>,
  pt: Rc<node::PlatformTree>,
}

impl Builder {
  pub fn build(cx: &mut ExtCtxt, pt: Rc<node::PlatformTree>) -> Option<Builder> {
    let mut builder = Builder::new(pt.clone());

    if !pt.expect_subnodes(cx, &["mcu", "os", "drivers"]) {
      return None;
    }

    match pt.get_by_path("mcu") {
      Some(node) => mcu::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): should it actaully fail?
    }

    match pt.get_by_path("os") {
      Some(node) => os::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): this should fail.
    }

    match pt.get_by_path("drivers") {
      Some(node) => ::drivers_pt::attach(&mut builder, cx, node),
      None => (),
    }

    for sub in pt.nodes().iter() {
      Builder::walk_mutate(&mut builder, cx, sub);
    }

    let base_node = pt.get_by_path("mcu").and_then(|mcu|{mcu.get_by_path("clock")});
    match base_node {
      Some(node) => Builder::walk_materialize(&mut builder, cx, node),
      None => {
        cx.parse_sess().span_diagnostic.span_err(DUMMY_SP,
            "root node `mcu::clock` must be present");
      }
    }

    Some(builder)
  }

  fn walk_mutate(builder: &mut Builder, cx: &mut ExtCtxt, node: &Rc<node::Node>) {
    let maybe_mut = node.mutator.get();
    if maybe_mut.is_some() {
      maybe_mut.unwrap()(builder, cx, node.clone());
    }
    for sub in node.subnodes().iter() {
      Builder::walk_mutate(builder, cx, sub);
    }
  }

  // FIXME(farcaller): verify that all nodes have been materialized
  fn walk_materialize(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
    let maybe_mat = node.materializer.get();
    if maybe_mat.is_some() {
      maybe_mat.unwrap()(builder, cx, node.clone());
    }
    let rev_depends = node.rev_depends_on.borrow();
    for weak_sub in rev_depends.iter() {
      let sub = weak_sub.upgrade().unwrap();
      let mut sub_deps = sub.depends_on.borrow_mut();
      let deps = sub_deps.deref_mut();
      let mut index = None;
      let mut i = 0u;
      // FIXME: iter().position()
      for dep in deps.iter() {
        let strong_dep = dep.upgrade().unwrap();
        if node == strong_dep {
          index = Some(i);
          break;
        }
        i = i + 1;
      }
      if index.is_none() {
        panic!("no index found");
      } else {
        deps.remove(index.unwrap());
        if deps.len() == 0 {
          Builder::walk_materialize(builder, cx, sub.clone());
        }
      }
    }
  }

  pub fn new(pt: Rc<node::PlatformTree>) -> Builder {
    Builder {
      main_stmts: Vec::new(),
      type_items: Vec::new(),
      pt: pt,
    }
  }

  pub fn main_stmts(&self) -> Vec<P<ast::Stmt>> {
    self.main_stmts.clone()
  }

  pub fn pt(&self) -> Rc<node::PlatformTree> {
    self.pt.clone()
  }

  pub fn add_main_statement(&mut self, stmt: P<ast::Stmt>) {
    self.main_stmts.push(stmt);
  }

  pub fn add_type_item(&mut self, item: P<ast::Item>) {
    self.type_items.push(item);
  }

  fn emit_main(&self, cx: &ExtCtxt) -> P<ast::Item> {
    // init stack
    let init_stack_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_stack();
    ));

    // init data
    let init_data_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_data();
    ));

    let mut stmts = vec!(init_stack_stmt, init_data_stmt);
    stmts.push_all(self.main_stmts.as_slice());

    let body = cx.block(DUMMY_SP, stmts, None);

    let unused_variables = cx.meta_word(DUMMY_SP,
        InternedString::new("unused_variables"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(unused_variables));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);

    self.item_fn(cx, DUMMY_SP, "main", &[allow_noncamel], body)
  }

  fn emit_morestack(&self, cx: &ExtCtxt) -> P<ast::Item> {
    let stmt = cx.stmt_expr(quote_expr!(&*cx,
        core::intrinsics::abort()
        // or
        // zinc::os::task::morestack();
    ));
    let empty_span = DUMMY_SP;
    let body = cx.block(empty_span, vec!(stmt), None);
    self.item_fn(cx, empty_span, "__morestack", &[], body)
  }

  pub fn emit_items(&self, cx: &ExtCtxt) -> Vec<P<ast::Item>> {
    let non_camel_case_types = cx.meta_word(DUMMY_SP,
        InternedString::new("non_camel_case_types"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(non_camel_case_types));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);
    let use_zinc = cx.view_use_simple(DUMMY_SP, ast::Inherited, cx.path_ident(
        DUMMY_SP, cx.ident_of("zinc")));
    let pt_mod_item = cx.item_mod(DUMMY_SP, DUMMY_SP, cx.ident_of("pt"),
        vec!(allow_noncamel), vec!(use_zinc), self.type_items.clone());

    if self.type_items.len() > 0 {
      vec!(pt_mod_item, self.emit_main(cx), self.emit_morestack(cx))
    } else {
      vec!(self.emit_main(cx), self.emit_morestack(cx))
    }
  }

  fn item_fn(&self, cx: &ExtCtxt, span: Span, name: &str,
      local_attrs: &[ast::Attribute], body: P<ast::Block>)
      -> P<ast::Item> {
    let attr_no_mangle = cx.attribute(span, cx.meta_word(
        span, InternedString::new("no_mangle")));
    let mut attrs = vec!(attr_no_mangle);
    attrs.push_all(local_attrs);

    P(ast::Item {
      ident: cx.ident_of(name),
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemFn(
          cx.fn_decl(Vec::new(), cx.ty(DUMMY_SP, ast::Ty_::TyTup(Vec::new()))),
          ast::Unsafety::Unsafe,
          abi::Rust, // TODO(farcaller): should this be abi::C?
          empty_generics(),
          body),
      vis: ast::Public,
      span: span,
    })
  }
}

pub struct TokenString(pub String);

impl ToTokens for TokenString {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    let &TokenString(ref s) = self;
    (cx as &ExtParseUtils).parse_tts(s.clone())
  }
}

pub fn add_node_dependency(node: &Rc<node::Node>, dep: &Rc<node::Node>) {
  let mut depends_on = node.depends_on.borrow_mut();
  depends_on.deref_mut().push(dep.downgrade());

  let mut rev_depends_on = dep.rev_depends_on.borrow_mut();
  rev_depends_on.push(node.downgrade());
}

#[cfg(test)]
mod test {
  use test_helpers::fails_to_build;

  #[test]
  fn fails_to_parse_pt_with_unknown_root_node() {
    fails_to_build("unknown@node {}");
  }

  #[test]
  fn fails_to_parse_pt_with_unknown_mcu() {
    fails_to_build("mcu@bad {}");
  }
}
<|endoftext|>


<commit_before>struct Selector<T> {
    elements: Vec<T>,
    current: usize
}

use std::ops::{Deref, DerefMut};

impl<T> Deref for Selector<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.elements[self.current]
    }
}

impl<T> DerefMut for Selector<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.elements[self.current]
    }
}

// A string literal is a &str, but the type that implements AsRef<Path> is str,
// without an &. And as we explained in “Deref and DerefMut” on page 289,
// Rust doesn’t try deref coercions to satisfy type variable bounds,
// so they won’t help here either.

// Fortunately, the standard library includes the blanket implementation:

// impl<'a, T, U> AsRef<U> for &'a T
//   where T: AsRef<U>, T: ?Sized, U: ?Sized
// {
//     fn as_ref(&self) -> &U {
//         (*self).as_ref()
//     }
// }

// In other words, for any types T and U, if T: AsRef<U>, then &T: AsRef<U> as well:
// simply follow the reference and proceed as before.
// In particular, since str: AsRef<Path>, then &str: AsRef<Path> as well.
// In a sense, this is a way to get a limited form of deref coercion
// in checking AsRef bounds on type variables.

fn main() {
    let mut s = Selector { elements: vec!['x', 'y', 'z'],
                           current: 2 };

    assert_eq!(*s, 'z');
}

<commit_msg>samll note about unit lamda shortcut<commit_after>struct Selector<T> {
    elements: Vec<T>,
    current: usize
}

use std::ops::{Deref, DerefMut};

impl<T> Deref for Selector<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.elements[self.current]
    }
}

impl<T> DerefMut for Selector<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.elements[self.current]
    }
}

// A string literal is a &str, but the type that implements AsRef<Path> is str,
// without an &. And as we explained in “Deref and DerefMut” on page 289,
// Rust doesn’t try deref coercions to satisfy type variable bounds,
// so they won’t help here either.

// Fortunately, the standard library includes the blanket implementation:

// impl<'a, T, U> AsRef<U> for &'a T
//   where T: AsRef<U>, T: ?Sized, U: ?Sized
// {
//     fn as_ref(&self) -> &U {
//         (*self).as_ref()
//     }
// }

// In other words, for any types T and U, if T: AsRef<U>, then &T: AsRef<U> as well:
// simply follow the reference and proceed as before.
// In particular, since str: AsRef<Path>, then &str: AsRef<Path> as well.
// In a sense, this is a way to get a limited form of deref coercion
// in checking AsRef bounds on type variables.

// Small note:
// Fn() is shorthand for Fn() -> ()

fn main() {
    let mut s = Selector { elements: vec!['x', 'y', 'z'],
                           current: 2 };

    assert_eq!(*s, 'z');
}

<|endoftext|>


<commit_before>use crate::{Browser, Error, ErrorKind, Result};
use jni::objects::JValue;
pub use std::os::unix::process::ExitStatusExt;
use std::process::{Command, ExitStatus};

/// Deal with opening of browsers on Android
#[inline]
pub fn open_browser_internal(_: Browser, url: &str) -> Result<ExitStatus> {
    // Create a VM for executing Java calls
    let native_activity = ndk_glue::native_activity();
    let vm_ptr = native_activity.vm();
    let vm = unsafe { jni::JavaVM::from_raw(vm_ptr) }.unwrap();
    let env = vm.attach_current_thread().map_err(|_| -> Error {
        Error::new(ErrorKind::Other, "Failed to attach current thread")
    })?;

    // Create ACTION_VIEW object
    let intent_class = env
        .find_class("android/content/Intent")
        .map_err(|_| -> Error { Error::new(ErrorKind::NotFound, "Failed to find Intent class") })?;
    let action_view = env
        .get_static_field(intent_class, "ACTION_VIEW", "Ljava/lang/String;")
        .map_err(|_| -> Error {
            Error::new(ErrorKind::NotFound, "Failed to get intent.ACTION_VIEW")
        })?;

    // Create Uri object
    let uri_class = env
        .find_class("android/net/Uri")
        .map_err(|_| -> Error { Error::new(ErrorKind::NotFound, "Failed to find Uri class") })?;
    let url = env
        .new_string(url)
        .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to create JNI string") })?;
    let uri = env
        .call_static_method(
            uri_class,
            "parse",
            "(Ljava/lang/String;)Landroid/net/Uri;",
            &[JValue::Object(*url)],
        )
        .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to parse JNI Uri") })?;

    // Create new ACTION_VIEW intent with the uri
    let intent = env
        .alloc_object(intent_class)
        .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to allocate intent") })?;
    env.call_method(
        intent,
        "<init>",
        "(Ljava/lang/String;Landroid/net/Uri;)V",
        &[action_view, uri],
    )
    .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to initialize intent") })?;

    // Start the intent activity.
    env.call_method(
        native_activity.activity(),
        "startActivity",
        "(Landroid/content/Intent;)V",
        &[JValue::Object(intent)],
    )
    .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to start activity") })?;

    Ok(ExitStatus::from_raw(0))
}
<commit_msg>remove unnecessary import<commit_after>use crate::{Browser, Error, ErrorKind, Result};
use jni::objects::JValue;
pub use std::os::unix::process::ExitStatusExt;
use std::process::ExitStatus;

/// Deal with opening of browsers on Android
#[inline]
pub fn open_browser_internal(_: Browser, url: &str) -> Result<ExitStatus> {
    // Create a VM for executing Java calls
    let native_activity = ndk_glue::native_activity();
    let vm_ptr = native_activity.vm();
    let vm = unsafe { jni::JavaVM::from_raw(vm_ptr) }.unwrap();
    let env = vm.attach_current_thread().map_err(|_| -> Error {
        Error::new(ErrorKind::Other, "Failed to attach current thread")
    })?;

    // Create ACTION_VIEW object
    let intent_class = env
        .find_class("android/content/Intent")
        .map_err(|_| -> Error { Error::new(ErrorKind::NotFound, "Failed to find Intent class") })?;
    let action_view = env
        .get_static_field(intent_class, "ACTION_VIEW", "Ljava/lang/String;")
        .map_err(|_| -> Error {
            Error::new(ErrorKind::NotFound, "Failed to get intent.ACTION_VIEW")
        })?;

    // Create Uri object
    let uri_class = env
        .find_class("android/net/Uri")
        .map_err(|_| -> Error { Error::new(ErrorKind::NotFound, "Failed to find Uri class") })?;
    let url = env
        .new_string(url)
        .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to create JNI string") })?;
    let uri = env
        .call_static_method(
            uri_class,
            "parse",
            "(Ljava/lang/String;)Landroid/net/Uri;",
            &[JValue::Object(*url)],
        )
        .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to parse JNI Uri") })?;

    // Create new ACTION_VIEW intent with the uri
    let intent = env
        .alloc_object(intent_class)
        .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to allocate intent") })?;
    env.call_method(
        intent,
        "<init>",
        "(Ljava/lang/String;Landroid/net/Uri;)V",
        &[action_view, uri],
    )
    .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to initialize intent") })?;

    // Start the intent activity.
    env.call_method(
        native_activity.activity(),
        "startActivity",
        "(Landroid/content/Intent;)V",
        &[JValue::Object(intent)],
    )
    .map_err(|_| -> Error { Error::new(ErrorKind::Other, "Failed to start activity") })?;

    Ok(ExitStatus::from_raw(0))
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use xshell::pushd;

use crate::{cmd, Metadata, Result};

const MSRV: &str = "1.50";

/// Task to run CI tests.
pub struct CiTask {
    /// Which version of Rust to test against.
    version: Option<String>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(version: Option<String>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { version, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.version.as_deref() {
            Some("msrv") => self.build_msrv()?,
            Some("stable") => self.build_stable()?,
            Some("nightly") => self.build_nightly()?,
            Some(_) => return Err("Wrong Rust version specified.".into()),
            None => {
                self.build_msrv().and(self.build_stable()).and(self.build_nightly())?;
            }
        }

        Ok(())
    }

    fn build_msrv(&self) -> xshell::Result<()> {
        // Check all crates with all features except
        // * ruma (would pull in ruma-signatures)
        // * ruma-client (tested with default features due to optional HTTP client deps)
        // * ruma-signatures (MSRV exception)
        // * xtask (no real reason to enforce an MSRV for it)
        cmd!(
            "rustup run {MSRV} cargo check --workspace --all-features
                --exclude ruma
                --exclude ruma-client
                --exclude ruma-signatures
                --exclude xtask"
        )
        .run()?;

        // Check ruma-client crate with default features
        cmd!("rustup run {MSRV} cargo check -p ruma-client").run()?;

        // Check ruma crate with default features
        cmd!("rustup run {MSRV} cargo check -p ruma").run()
    }

    fn build_stable(&self) -> xshell::Result<()> {
        // 1. Make sure everything compiles
        cmd!("rustup run stable cargo check --workspace --all-features").run()?;
        cmd!("rustup run stable cargo check -p ruma-client --no-default-features").run()?;
        cmd!("rustup run stable cargo check -p ruma-identifiers --no-default-features").run()?;

        // 2. Run tests
        cmd!("rustup run stable cargo test --workspace --features unstable-pre-spec").run()
    }

    fn build_nightly(&self) -> xshell::Result<()> {
        let fmt_res = cmd!("rustup run nightly cargo fmt -- --check").run();
        let clippy_res = cmd!("rustup run nightly cargo ruma-clippy -D warnings").run();
        let sort_res = cmd!(
            "
            rustup run nightly cargo sort
                --workspace --grouped --check
                --order package,lib,features,dependencies,dev-dependencies,build-dependencies
            "
        )
        .run();

        fmt_res.and(clippy_res).and(sort_res)
    }
}
<commit_msg>ci: Check ruma without unstable features<commit_after>use std::path::PathBuf;

use xshell::pushd;

use crate::{cmd, Metadata, Result};

const MSRV: &str = "1.50";

/// Task to run CI tests.
pub struct CiTask {
    /// Which version of Rust to test against.
    version: Option<String>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(version: Option<String>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { version, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.version.as_deref() {
            Some("msrv") => self.build_msrv()?,
            Some("stable") => self.build_stable()?,
            Some("nightly") => self.build_nightly()?,
            Some(_) => return Err("Wrong Rust version specified.".into()),
            None => {
                self.build_msrv().and(self.build_stable()).and(self.build_nightly())?;
            }
        }

        Ok(())
    }

    fn build_msrv(&self) -> xshell::Result<()> {
        // Check all crates with all features except
        // * ruma (would pull in ruma-signatures)
        // * ruma-client (tested with default features due to optional HTTP client deps)
        // * ruma-signatures (MSRV exception)
        // * xtask (no real reason to enforce an MSRV for it)
        cmd!(
            "rustup run {MSRV} cargo check --workspace --all-features
                --exclude ruma
                --exclude ruma-client
                --exclude ruma-signatures
                --exclude xtask"
        )
        .run()?;

        // Check ruma-client crate with default features
        cmd!("rustup run {MSRV} cargo check -p ruma-client").run()?;

        // Check ruma crate with default features
        cmd!("rustup run {MSRV} cargo check -p ruma").run()
    }

    fn build_stable(&self) -> xshell::Result<()> {
        // 1. Make sure everything compiles
        cmd!("rustup run stable cargo check --workspace --all-features").run()?;
        cmd!("rustup run stable cargo check -p ruma-client --no-default-features").run()?;
        cmd!("rustup run stable cargo check -p ruma-identifiers --no-default-features").run()?;

        // 2. Run tests
        cmd!("rustup run stable cargo test --workspace --features unstable-pre-spec").run()
    }

    fn build_nightly(&self) -> xshell::Result<()> {
        // Check formatting
        let fmt_res = cmd!("rustup run nightly cargo fmt -- --check").run();
        // Check `ruma` crate with `full` feature (sometimes things only compile with an unstable
        // flag)
        let check_full_res = cmd!("rustup run nightly cargo check -p ruma --features full").run();
        // Check everything with (almost) all features with clippy
        let clippy_res = cmd!("rustup run nightly cargo ruma-clippy -D warnings").run();
        // Check dependencies being sorted
        let sort_res = cmd!(
            "
            rustup run nightly cargo sort
                --workspace --grouped --check
                --order package,lib,features,dependencies,dev-dependencies,build-dependencies
            "
        )
        .run();

        fmt_res.and(check_full_res).and(clippy_res).and(sort_res)
    }
}
<|endoftext|>


<commit_before>use tensorflow_sys as ffi;

/// Test that the library is linked properly
#[test]
fn linkage() {
    unsafe {
        let buffer = ffi::TF_NewBuffer();
        assert!(!buffer.is_null());
        ffi::TF_DeleteBuffer(buffer);
    }
}

/// Test that the eager API works.
#[cfg(feature = "eager")]
#[test]
fn tfe_tensor_handle() {
    let data = vec![0.0f32; 100];
    let shape = [1, 10, 10];
    let num_elements = shape.iter().product::<i64>() as usize;

    unsafe {
        let tf_tensor = ffi::TF_AllocateTensor(
            ffi::TF_FLOAT,
            shape.as_ptr(),
            shape.len() as i32,
            num_elements * std::mem::size_of::<f32>(),
        );
        std::ptr::copy_nonoverlapping(
            data.as_ptr(),
            ffi::TF_TensorData(tf_tensor) as *mut f32,
            ffi::TF_TensorByteSize(tf_tensor) / std::mem::size_of::<f32>(),
        );
        let status = ffi::TF_NewStatus();
        let tfe_handle = ffi::TFE_NewTensorHandle(tf_tensor, status);

        ffi::TF_DeleteStatus(status);
        ffi::TFE_DeleteTensorHandle(tfe_handle);
        ffi::TF_DeleteTensor(tf_tensor);
    }
}
<commit_msg>[tensorflow-sys] add status check code.<commit_after>use tensorflow_sys as ffi;

/// Test that the library is linked properly
#[test]
fn linkage() {
    unsafe {
        let buffer = ffi::TF_NewBuffer();
        assert!(!buffer.is_null());
        ffi::TF_DeleteBuffer(buffer);
    }
}

/// Test that the eager API works.
#[cfg(feature = "eager")]
#[test]
fn tfe_tensor_handle() {
    let data = vec![0.0f32; 100];
    let shape = [1, 10, 10];
    let num_elements = shape.iter().product::<i64>() as usize;

    unsafe {
        let tf_tensor = ffi::TF_AllocateTensor(
            ffi::TF_FLOAT,
            shape.as_ptr(),
            shape.len() as i32,
            num_elements * std::mem::size_of::<f32>(),
        );
        std::ptr::copy_nonoverlapping(
            data.as_ptr(),
            ffi::TF_TensorData(tf_tensor) as *mut f32,
            ffi::TF_TensorByteSize(tf_tensor) / std::mem::size_of::<f32>(),
        );
        let status = ffi::TF_NewStatus();
        let tfe_handle = ffi::TFE_NewTensorHandle(tf_tensor, status);
        if ffi::TF_GetCode(status) != ffi::TF_OK {
            panic!(
                "{}",
                std::ffi::CStr::from_ptr(ffi::TF_Message(status))
                    .to_string_lossy()
                    .into_owned()
            );
        }

        ffi::TF_DeleteStatus(status);
        ffi::TFE_DeleteTensorHandle(tfe_handle);
        ffi::TF_DeleteTensor(tf_tensor);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::sync::atomic::{spin_loop_hint as cpu_relax};

use crate::Mutex;

/// A barrier enables multiple threads to synchronize the beginning
/// of some computation.
///
/// # Examples
///
/// ```
/// use spin;
/// use std::sync::Arc;
/// use std::thread;
///
/// let mut handles = Vec::with_capacity(10);
/// let barrier = Arc::new(spin::Barrier::new(10));
/// for _ in 0..10 {
///     let c = barrier.clone();
///     // The same messages will be printed together.
///     // You will NOT see any interleaving.
///     handles.push(thread::spawn(move|| {
///         println!("before wait");
///         c.wait();
///         println!("after wait");
///     }));
/// }
/// // Wait for other threads to finish.
/// for handle in handles {
///     handle.join().unwrap();
/// }
/// ```
pub struct Barrier {
    lock: Mutex<BarrierState>,
    num_threads: usize,
}

// The inner state of a double barrier
struct BarrierState {
    count: usize,
    generation_id: usize,
}

/// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`]
/// have rendezvoused.
///
/// [`wait`]: struct.Barrier.html#method.wait
/// [`Barrier`]: struct.Barrier.html
///
/// # Examples
///
/// ```
/// use spin;
///
/// let barrier = spin::Barrier::new(1);
/// let barrier_wait_result = barrier.wait();
/// ```
pub struct BarrierWaitResult(bool);

impl Barrier {
    /// Creates a new barrier that can block a given number of threads.
    ///
    /// A barrier will block `n`-1 threads which call [`wait`] and then wake up
    /// all threads at once when the `n`th thread calls [`wait`].
    ///
    /// [`wait`]: #method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use spin;
    ///
    /// let barrier = spin::Barrier::new(10);
    /// ```
    pub const fn new(n: usize) -> Barrier {
        Barrier {
            lock: Mutex::new(BarrierState {
                count: 0,
                generation_id: 0,
            }),
            num_threads: n,
        }
    }

    /// Blocks the current thread until all threads have rendezvoused here.
    ///
    /// Barriers are re-usable after all threads have rendezvoused once, and can
    /// be used continuously.
    ///
    /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that
    /// returns `true` from [`is_leader`] when returning from this function, and
    /// all other threads will receive a result that will return `false` from
    /// [`is_leader`].
    ///
    /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html
    /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader
    ///
    /// # Examples
    ///
    /// ```
    /// use spin;
    /// use std::sync::Arc;
    /// use std::thread;
    ///
    /// let mut handles = Vec::with_capacity(10);
    /// let barrier = Arc::new(spin::Barrier::new(10));
    /// for _ in 0..10 {
    ///     let c = barrier.clone();
    ///     // The same messages will be printed together.
    ///     // You will NOT see any interleaving.
    ///     handles.push(thread::spawn(move|| {
    ///         println!("before wait");
    ///         c.wait();
    ///         println!("after wait");
    ///     }));
    /// }
    /// // Wait for other threads to finish.
    /// for handle in handles {
    ///     handle.join().unwrap();
    /// }
    /// ```
    pub fn wait(&self) -> BarrierWaitResult {
        let mut lock = self.lock.lock();
        let local_gen = lock.generation_id;
        lock.count += 1;

        if lock.count < self.num_threads {
            // not the leader
            while local_gen == lock.generation_id &&
                lock.count < self.num_threads {
                drop(lock);
                cpu_relax();
                lock = self.lock.lock();
            }
            lock.count -= 1;
            return BarrierWaitResult(false);
        } else {
            // this thread is the leader,
            //   and is responsible for incrementing the generation
            lock.generation_id = local_gen + 1;
            lock.count -= 1;
            return BarrierWaitResult(true);
        }
    }
}

impl BarrierWaitResult {
    /// Returns whether this thread from [`wait`] is the "leader thread".
    ///
    /// Only one thread will have `true` returned from their result, all other
    /// threads will have `false` returned.
    ///
    /// [`wait`]: struct.Barrier.html#method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use spin;
    ///
    /// let barrier = spin::Barrier::new(1);
    /// let barrier_wait_result = barrier.wait();
    /// println!("{:?}", barrier_wait_result.is_leader());
    /// ```
    pub fn is_leader(&self) -> bool { self.0 }
}

#[cfg(test)]
mod tests {
    use std::prelude::v1::*;

    use std::sync::mpsc::{channel, TryRecvError};
    use std::sync::Arc;
    use std::thread;

    use super::Barrier;

    fn use_barrier(n: usize, barrier: Arc<Barrier>) {
        let (tx, rx) = channel();

        for _ in 0..n - 1 {
            let c = barrier.clone();
            let tx = tx.clone();
            thread::spawn(move|| {
                tx.send(c.wait().is_leader()).unwrap();
            });
        }

        // At this point, all spawned threads should be blocked,
        // so we shouldn't get anything from the port
        assert!(match rx.try_recv() {
            Err(TryRecvError::Empty) => true,
            _ => false,
        });

        let mut leader_found = barrier.wait().is_leader();

        // Now, the barrier is cleared and we should get data.
        for _ in 0..n - 1 {
            if rx.recv().unwrap() {
                assert!(!leader_found);
                leader_found = true;
            }
        }
        assert!(leader_found);
    }

    #[test]
    fn test_barrier() {
        const N: usize = 10;

        let barrier = Arc::new(Barrier::new(N));

        use_barrier(N, barrier.clone());

        // use barrier twice to ensure it is reusable
        use_barrier(N, barrier.clone());
    }
}
<commit_msg>ensure barrier behavior across generations matches std lib<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::sync::atomic::{spin_loop_hint as cpu_relax};

use crate::Mutex;

/// A barrier enables multiple threads to synchronize the beginning
/// of some computation.
///
/// # Examples
///
/// ```
/// use spin;
/// use std::sync::Arc;
/// use std::thread;
///
/// let mut handles = Vec::with_capacity(10);
/// let barrier = Arc::new(spin::Barrier::new(10));
/// for _ in 0..10 {
///     let c = barrier.clone();
///     // The same messages will be printed together.
///     // You will NOT see any interleaving.
///     handles.push(thread::spawn(move|| {
///         println!("before wait");
///         c.wait();
///         println!("after wait");
///     }));
/// }
/// // Wait for other threads to finish.
/// for handle in handles {
///     handle.join().unwrap();
/// }
/// ```
pub struct Barrier {
    lock: Mutex<BarrierState>,
    num_threads: usize,
}

// The inner state of a double barrier
struct BarrierState {
    count: usize,
    generation_id: usize,
}

/// A `BarrierWaitResult` is returned by [`wait`] when all threads in the [`Barrier`]
/// have rendezvoused.
///
/// [`wait`]: struct.Barrier.html#method.wait
/// [`Barrier`]: struct.Barrier.html
///
/// # Examples
///
/// ```
/// use spin;
///
/// let barrier = spin::Barrier::new(1);
/// let barrier_wait_result = barrier.wait();
/// ```
pub struct BarrierWaitResult(bool);

impl Barrier {
    /// Creates a new barrier that can block a given number of threads.
    ///
    /// A barrier will block `n`-1 threads which call [`wait`] and then wake up
    /// all threads at once when the `n`th thread calls [`wait`].
    ///
    /// [`wait`]: #method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use spin;
    ///
    /// let barrier = spin::Barrier::new(10);
    /// ```
    pub const fn new(n: usize) -> Barrier {
        Barrier {
            lock: Mutex::new(BarrierState {
                count: 0,
                generation_id: 0,
            }),
            num_threads: n,
        }
    }

    /// Blocks the current thread until all threads have rendezvoused here.
    ///
    /// Barriers are re-usable after all threads have rendezvoused once, and can
    /// be used continuously.
    ///
    /// A single (arbitrary) thread will receive a [`BarrierWaitResult`] that
    /// returns `true` from [`is_leader`] when returning from this function, and
    /// all other threads will receive a result that will return `false` from
    /// [`is_leader`].
    ///
    /// [`BarrierWaitResult`]: struct.BarrierWaitResult.html
    /// [`is_leader`]: struct.BarrierWaitResult.html#method.is_leader
    ///
    /// # Examples
    ///
    /// ```
    /// use spin;
    /// use std::sync::Arc;
    /// use std::thread;
    ///
    /// let mut handles = Vec::with_capacity(10);
    /// let barrier = Arc::new(spin::Barrier::new(10));
    /// for _ in 0..10 {
    ///     let c = barrier.clone();
    ///     // The same messages will be printed together.
    ///     // You will NOT see any interleaving.
    ///     handles.push(thread::spawn(move|| {
    ///         println!("before wait");
    ///         c.wait();
    ///         println!("after wait");
    ///     }));
    /// }
    /// // Wait for other threads to finish.
    /// for handle in handles {
    ///     handle.join().unwrap();
    /// }
    /// ```
    pub fn wait(&self) -> BarrierWaitResult {
        let mut lock = self.lock.lock();
        lock.count += 1;

        if lock.count < self.num_threads {
            // not the leader
            let local_gen = lock.generation_id;

            while local_gen == lock.generation_id &&
                lock.count < self.num_threads {
                drop(lock);
                cpu_relax();
                lock = self.lock.lock();
            }
            return BarrierWaitResult(false);
        } else {
            // this thread is the leader,
            //   and is responsible for incrementing the generation
            lock.count = 0;
            lock.generation_id = lock.generation_id.wrapping_add(1);
            return BarrierWaitResult(true);
        }
    }
}

impl BarrierWaitResult {
    /// Returns whether this thread from [`wait`] is the "leader thread".
    ///
    /// Only one thread will have `true` returned from their result, all other
    /// threads will have `false` returned.
    ///
    /// [`wait`]: struct.Barrier.html#method.wait
    ///
    /// # Examples
    ///
    /// ```
    /// use spin;
    ///
    /// let barrier = spin::Barrier::new(1);
    /// let barrier_wait_result = barrier.wait();
    /// println!("{:?}", barrier_wait_result.is_leader());
    /// ```
    pub fn is_leader(&self) -> bool { self.0 }
}

#[cfg(test)]
mod tests {
    use std::prelude::v1::*;

    use std::sync::mpsc::{channel, TryRecvError};
    use std::sync::Arc;
    use std::thread;

    use super::Barrier;

    fn use_barrier(n: usize, barrier: Arc<Barrier>) {
        let (tx, rx) = channel();

        for _ in 0..n - 1 {
            let c = barrier.clone();
            let tx = tx.clone();
            thread::spawn(move|| {
                tx.send(c.wait().is_leader()).unwrap();
            });
        }

        // At this point, all spawned threads should be blocked,
        // so we shouldn't get anything from the port
        assert!(match rx.try_recv() {
            Err(TryRecvError::Empty) => true,
            _ => false,
        });

        let mut leader_found = barrier.wait().is_leader();

        // Now, the barrier is cleared and we should get data.
        for _ in 0..n - 1 {
            if rx.recv().unwrap() {
                assert!(!leader_found);
                leader_found = true;
            }
        }
        assert!(leader_found);
    }

    #[test]
    fn test_barrier() {
        const N: usize = 10;

        let barrier = Arc::new(Barrier::new(N));

        use_barrier(N, barrier.clone());

        // use barrier twice to ensure it is reusable
        use_barrier(N, barrier.clone());
    }
}
<|endoftext|>


<commit_before>#![allow(unused_imports, unused_must_use, unused_variables, dead_code)]

extern crate combine;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::str;
use std::marker::PhantomData;
use combine::{spaces, parser, between, many, many1, digit, char, any, string, token, Parser, ParserExt, ParseError};
use combine::primitives::{State, Stream, ParseResult, Consumed};
use combine::combinator::{Between, Token, FnParser, satisfy};

//my own bencode stuff!
//
fn open_file <P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut fd = File::open(path).unwrap();
    let mut buffer:Vec<u8> = Vec::new();
    fd.read_to_end(&mut buffer);
    buffer
}

#[derive(Debug, Eq, PartialEq)]
enum Bencode {
    Int(i64),
    String(String)
}

//TODO: this does not handle negatives, yo
fn bencode_integer<I>(input: State<I>) -> ParseResult<Bencode, I> where I:Stream<Item=char> {
    let (open, close) = (char('i'), char('e'));
    let mut int = between(open, close, many1::<String, _>(digit())).map(|x| {
        Bencode::Int(x.parse::<i64>().unwrap())
    });
    int.parse_state(input)
}

fn bencode_string<I>(input: State<I>) -> ParseResult<Bencode, I> where I:Stream<Item=char> {
    let (len, input_) = try!(bencode_string_length_prefix(input));
    input_.combine(|input__| take(len).map(|x| Bencode::String(x)).parse_state(input__))
}

fn bencode_string_length_prefix<I>(input: State<I>) -> ParseResult<i32, I> where I:Stream<Item=char> {
    let many_digit = many1::<String, _>(digit());
    let mut get_len = (many_digit, char(':')).map(|(length, _)| length.parse::<i32>().unwrap());
    get_len.parse_state(input)
}

//for now only handle i64s
fn bencode_list<I>(input: State<I>) -> ParseResult<Vec<Bencode>, I> where I:Stream<Item=char> {
    let (open, close) = (char('l'), char('e'));
    let list_contents = many(parser(bencode_integer).or(parser(bencode_string)));
    let mut list = between(open, close, list_contents).map(|x| {
        x
    });
    list.parse_state(input)
}

fn take <I> (num: i32) -> SizedBuffer<I> where I: Stream<Item=char> {
    SizedBuffer(num, PhantomData)
}

#[derive(Clone)]
pub struct SizedBuffer <I>(i32, PhantomData<I>);
impl <I> Parser for SizedBuffer<I> where I: Stream<Item=char> {
    type Input = I;
    type Output = String;
    fn parse_lazy(&mut self, mut input: State<I>) -> ParseResult<String, I> {
        let start = input.position;
        let mut vec_buf:Vec<char> = Vec::new();
        for _ in 0..self.0 {
            match input.uncons() {
                Ok((other, rest)) => {
                    vec_buf.push(other);
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(Consumed::Consumed(error))
                    })
                }
            };
        }
        Ok((vec_buf.into_iter().collect(), Consumed::Consumed(input)))
    }
}

fn main () {
    let file_contents = open_file("t-test.torrent");

    match str::from_utf8(&file_contents) {
        Ok(v) => println!("file: {}", v),
        Err(e) => panic!("Not a UTF-8 String: {}", e)
    }
}

#[test]
fn test_integer() {
    let result = parser(bencode_integer).parse("i57e");
    assert_eq!(result, Ok((Bencode::Int(57),"")));
}

#[test]
fn test_string() {
    let result = parser(bencode_string).parse("5:abcde");
    assert_eq!(result, Ok((Bencode::String("abcde".to_string()), "")));;
}

#[test]
fn test_list() {
    let homogenous_int_list = parser(bencode_list).parse("li57ei32ee");
    assert_eq!(homogenous_int_list, Ok((vec![Bencode::Int(57), Bencode::Int(32)], "")));

    let homogenous_str_list = parser(bencode_list).parse("l3:abc5:defghe");
    assert_eq!(homogenous_str_list, Ok((vec![Bencode::String("abc".to_string()), Bencode::String("defgh".to_string())], "")));

    let hetero_list = parser(bencode_list).parse("li32e3:abce");
    assert_eq!(hetero_list, Ok((vec![Bencode::Int(32), Bencode::String("abc".to_string())], "")));
}

<commit_msg>remove unnecessary map<commit_after>#![allow(unused_imports, unused_must_use, unused_variables, dead_code)]

extern crate combine;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::str;
use std::marker::PhantomData;
use combine::{spaces, parser, between, many, many1, digit, char, any, string, token, Parser, ParserExt, ParseError};
use combine::primitives::{State, Stream, ParseResult, Consumed};
use combine::combinator::{Between, Token, FnParser, satisfy};

//my own bencode stuff!
//
fn open_file <P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut fd = File::open(path).unwrap();
    let mut buffer:Vec<u8> = Vec::new();
    fd.read_to_end(&mut buffer);
    buffer
}

#[derive(Debug, Eq, PartialEq)]
enum Bencode {
    Int(i64),
    String(String)
}

//TODO: this does not handle negatives, yo
fn bencode_integer<I>(input: State<I>) -> ParseResult<Bencode, I> where I:Stream<Item=char> {
    let (open, close) = (char('i'), char('e'));
    let mut int = between(open, close, many1::<String, _>(digit())).map(|x| {
        Bencode::Int(x.parse::<i64>().unwrap())
    });
    int.parse_state(input)
}

fn bencode_string<I>(input: State<I>) -> ParseResult<Bencode, I> where I:Stream<Item=char> {
    let (len, input_) = try!(bencode_string_length_prefix(input));
    input_.combine(|input__| take(len).map(|x| Bencode::String(x)).parse_state(input__))
}

fn bencode_string_length_prefix<I>(input: State<I>) -> ParseResult<i32, I> where I:Stream<Item=char> {
    let many_digit = many1::<String, _>(digit());
    let mut get_len = (many_digit, char(':')).map(|(length, _)| length.parse::<i32>().unwrap());
    get_len.parse_state(input)
}

//for now only handle i64s
fn bencode_list<I>(input: State<I>) -> ParseResult<Vec<Bencode>, I> where I:Stream<Item=char> {
    let (open, close) = (char('l'), char('e'));
    let list_contents = many(parser(bencode_integer).or(parser(bencode_string)));
    let mut list = between(open, close, list_contents);
    list.parse_state(input)
}

fn take <I> (num: i32) -> SizedBuffer<I> where I: Stream<Item=char> {
    SizedBuffer(num, PhantomData)
}

#[derive(Clone)]
pub struct SizedBuffer <I>(i32, PhantomData<I>);
impl <I> Parser for SizedBuffer<I> where I: Stream<Item=char> {
    type Input = I;
    type Output = String;
    fn parse_lazy(&mut self, mut input: State<I>) -> ParseResult<String, I> {
        let start = input.position;
        let mut vec_buf:Vec<char> = Vec::new();
        for _ in 0..self.0 {
            match input.uncons() {
                Ok((other, rest)) => {
                    vec_buf.push(other);
                    input = rest.into_inner();
                }
                Err(error) => {
                    return error.combine(|mut error| {
                        error.position = start;
                        Err(Consumed::Consumed(error))
                    })
                }
            };
        }
        Ok((vec_buf.into_iter().collect(), Consumed::Consumed(input)))
    }
}

fn main () {
    let file_contents = open_file("t-test.torrent");

    match str::from_utf8(&file_contents) {
        Ok(v) => println!("file: {}", v),
        Err(e) => panic!("Not a UTF-8 String: {}", e)
    }
}

#[test]
fn test_integer() {
    let result = parser(bencode_integer).parse("i57e");
    assert_eq!(result, Ok((Bencode::Int(57),"")));
}

#[test]
fn test_string() {
    let result = parser(bencode_string).parse("5:abcde");
    assert_eq!(result, Ok((Bencode::String("abcde".to_string()), "")));;
}

#[test]
fn test_list() {
    let homogenous_int_list = parser(bencode_list).parse("li57ei32ee");
    assert_eq!(homogenous_int_list, Ok((vec![Bencode::Int(57), Bencode::Int(32)], "")));

    let homogenous_str_list = parser(bencode_list).parse("l3:abc5:defghe");
    assert_eq!(homogenous_str_list, Ok((vec![Bencode::String("abc".to_string()), Bencode::String("defgh".to_string())], "")));

    let hetero_list = parser(bencode_list).parse("li32e3:abce");
    assert_eq!(hetero_list, Ok((vec![Bencode::Int(32), Bencode::String("abc".to_string())], "")));
}

<|endoftext|>


<commit_before>// Copyright 2015 Ilkka Rauta
//
// 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.

extern crate glfw;

extern crate htgl;

use glfw::Context;

use htgl::{VertexAttributeType,
    RenderOption,
    ShaderType,
    PrimitiveMode,
    SimpleUniformTypeFloat};

#[allow(dead_code)]
#[repr(packed)]
struct Vec3 {
    x: f32,
    y: f32,
    z: f32,
}

#[allow(dead_code)]
#[repr(packed)]
struct Rgba {
    r: u8,
    g: u8,
    b: u8,
    a: u8,
}

#[allow(dead_code)]
#[repr(packed)]
struct Vertex {
    position: Vec3,
    color: Rgba
}

impl Vertex {
    fn new(x: f32, y: f32, z: f32, r: u8, g: u8, b: u8, a: u8) -> Vertex {
        Vertex { position: Vec3 { x: x, y: y, z: z }, color: Rgba { r: r, g: g, b: b, a: a } }
    }
}

static VS_SOURCE: &'static str = "
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;

uniform float scale;

out vec4 v_color;

void main() {
    gl_Position.xyz = position * scale;
    gl_Position.w = 1.0;
    v_color = color;
}
";

static FS_SOURCE: &'static str = "
#version 330 core

in vec4 v_color;
out vec3 color;

void main() {
    color = v_color.rgb;
}
";

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenglProfile(glfw::OpenGlProfileHint::Core));
    glfw.window_hint(glfw::WindowHint::OpenglForwardCompat(true));

    // Create a windowed mode window and its OpenGL context
    let (mut window, events) = glfw.create_window(300, 300, "Hello this is window", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.set_key_polling(true);
    window.make_current();

    htgl::load_with(|s| window.get_proc_address(s));

    let mut ctx = htgl::Context::new();
    println!("{:?}", ctx.get_info());
    ctx.renderer().set_option(RenderOption::ClearColor(1f32, 1f32, 1f32, 1f32));
    ctx.renderer().set_option(RenderOption::DepthTest(false));
    ctx.renderer().set_option(RenderOption::CullingEnabled(true));
    let vbo = ctx.new_vertex_buffer();
    let vertices = [
        Vertex::new(-0.5f32, -0.5f32, 0f32, 255, 0, 0, 0),
        Vertex::new(0.5f32, -0.5f32, 0f32, 0, 255, 0, 0),
        Vertex::new(0f32, 0.5f32, 0f32, 0, 0, 255, 0),
        ];
    ctx.edit_vertex_buffer(&vbo).data(&vertices);
    let ibo = ctx.new_index_buffer();
    let vao = ctx.new_vertex_array_simple(&[(3, VertexAttributeType::Float, false), (4, VertexAttributeType::UnsignedByte, true)], vbo, Some(ibo));
    if let Some(mut editor) = ctx.edit_index_buffer(&vao) {
        let indices = [0, 1, 2];
        editor.data_u16(&indices);
    }
    let vs = ctx.new_shader(ShaderType::VertexShader, VS_SOURCE);
    if !ctx.shader_info(&vs).get_compile_status() {
        panic!(ctx.shader_info(&vs).get_info_log())
    }
    let fs = ctx.new_shader(ShaderType::FragmentShader, FS_SOURCE);
    if !ctx.shader_info(&fs).get_compile_status() {
        panic!(ctx.shader_info(&fs).get_info_log())
    }
    let program = ctx.new_program(&[vs, fs]);
    if !ctx.program_info(&program).get_link_status() {
        panic!(ctx.program_info(&program).get_info_log())
    }

    {
        let program_editor = ctx.edit_program(&program);
        let program_info = program_editor.program_info();
        let uniform_info = program_info.get_uniform_info();
        let scale_location = uniform_info.get_global_uniform("scale").map(|u| u.location).unwrap_or(-1);
        program_editor.uniform_f32(scale_location, 1, SimpleUniformTypeFloat::Uniform1f, &[1.5]);
        for uniform in uniform_info.globals.iter() {
            println!("{:?}", uniform);
        }
        for block in uniform_info.blocks.iter() {
            println!("InterfaceBlock {{ name: {}, index: {}, data_size: {} }}", block.name, block.index, block.data_size);
            for uniform in block.uniforms.iter() {
                println!("    {:?}", uniform);
            }
        }
        for attribute in program_info.get_attribute_info().attributes.iter() {
            println!("{:?}", attribute)
        }
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }

        let mut renderer = ctx.renderer();
        renderer.clear();
        renderer.use_vertex_array(&vao);
        renderer.use_program(&program);
        renderer.draw_elements_u16(PrimitiveMode::Triangles, 3, 0);

        window.swap_buffers();
        // break;
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    match event {
        glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _) => {
            window.set_should_close(true)
        }
        _ => {}
    }
}
<commit_msg>Fix the test app to work with the new buffer API.<commit_after>// Copyright 2015 Ilkka Rauta
//
// 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.

extern crate glfw;

extern crate htgl;

use glfw::Context;

use htgl::{VertexAttributeType,
    RenderOption,
    ShaderType,
    PrimitiveMode,
    SimpleUniformTypeFloat};

#[allow(dead_code)]
#[repr(packed)]
struct Vec3 {
    x: f32,
    y: f32,
    z: f32,
}

#[allow(dead_code)]
#[repr(packed)]
struct Rgba {
    r: u8,
    g: u8,
    b: u8,
    a: u8,
}

#[allow(dead_code)]
#[repr(packed)]
struct Vertex {
    position: Vec3,
    color: Rgba
}

impl Vertex {
    fn new(x: f32, y: f32, z: f32, r: u8, g: u8, b: u8, a: u8) -> Vertex {
        Vertex { position: Vec3 { x: x, y: y, z: z }, color: Rgba { r: r, g: g, b: b, a: a } }
    }
}

static VS_SOURCE: &'static str = "
#version 330 core

layout(location = 0) in vec3 position;
layout(location = 1) in vec4 color;

uniform float scale;

out vec4 v_color;

void main() {
    gl_Position.xyz = position * scale;
    gl_Position.w = 1.0;
    v_color = color;
}
";

static FS_SOURCE: &'static str = "
#version 330 core

in vec4 v_color;
out vec3 color;

void main() {
    color = v_color.rgb;
}
";

fn main() {
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();

    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenglProfile(glfw::OpenGlProfileHint::Core));
    glfw.window_hint(glfw::WindowHint::OpenglForwardCompat(true));

    // Create a windowed mode window and its OpenGL context
    let (mut window, events) = glfw.create_window(300, 300, "Hello this is window", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window.");

    window.set_key_polling(true);
    window.make_current();

    htgl::load_with(|s| window.get_proc_address(s));

    let mut ctx = htgl::Context::new();
    println!("{:?}", ctx.get_info());
    ctx.renderer().set_option(RenderOption::ClearColor(1f32, 1f32, 1f32, 1f32));
    ctx.renderer().set_option(RenderOption::DepthTest(false));
    ctx.renderer().set_option(RenderOption::CullingEnabled(true));
    let vbo = ctx.new_buffer();
    let vertices = [
        Vertex::new(-0.5f32, -0.5f32, 0f32, 255, 0, 0, 0),
        Vertex::new(0.5f32, -0.5f32, 0f32, 0, 255, 0, 0),
        Vertex::new(0f32, 0.5f32, 0f32, 0, 0, 255, 0),
        ];
    ctx.edit_vertex_buffer(&vbo).data(&vertices);
    let ibo = ctx.new_buffer();
    let vao = ctx.new_vertex_array_simple(&[(3, VertexAttributeType::Float, false), (4, VertexAttributeType::UnsignedByte, true)], vbo, Some(ibo));
    if let Some(mut editor) = ctx.edit_index_buffer(&vao) {
        let indices = [0u16, 1u16, 2u16];
        editor.data(&indices);
    }
    let vs = ctx.new_shader(ShaderType::VertexShader, VS_SOURCE);
    if !ctx.shader_info(&vs).get_compile_status() {
        panic!(ctx.shader_info(&vs).get_info_log())
    }
    let fs = ctx.new_shader(ShaderType::FragmentShader, FS_SOURCE);
    if !ctx.shader_info(&fs).get_compile_status() {
        panic!(ctx.shader_info(&fs).get_info_log())
    }
    let program = ctx.new_program(&[vs, fs]);
    if !ctx.program_info(&program).get_link_status() {
        panic!(ctx.program_info(&program).get_info_log())
    }

    {
        let program_editor = ctx.edit_program(&program);
        let program_info = program_editor.program_info();
        let uniform_info = program_info.get_uniform_info();
        let scale_location = uniform_info.get_global_uniform("scale").map(|u| u.location).unwrap_or(-1);
        program_editor.uniform_f32(scale_location, 1, SimpleUniformTypeFloat::Uniform1f, &[1.5]);
        for uniform in uniform_info.globals.iter() {
            println!("{:?}", uniform);
        }
        for block in uniform_info.blocks.iter() {
            println!("InterfaceBlock {{ name: {}, index: {}, data_size: {} }}", block.name, block.index, block.data_size);
            for uniform in block.uniforms.iter() {
                println!("    {:?}", uniform);
            }
        }
        for attribute in program_info.get_attribute_info().attributes.iter() {
            println!("{:?}", attribute)
        }
    }

    while !window.should_close() {
        glfw.poll_events();
        for (_, event) in glfw::flush_messages(&events) {
            handle_window_event(&mut window, event);
        }

        let mut renderer = ctx.renderer();
        renderer.clear();
        renderer.use_vertex_array(&vao);
        renderer.use_program(&program);
        renderer.draw_elements_u16(PrimitiveMode::Triangles, 3, 0);

        window.swap_buffers();
        // break;
    }
}

fn handle_window_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
    match event {
        glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _) => {
            window.set_should_close(true)
        }
        _ => {}
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate test;

use super::v2_serializer::varint_write;
use super::deserializer::varint_read;
use std::io::Cursor;
use self::rand::Rng;
use self::test::Bencher;

#[bench]
fn varint_write_rand_1_k(b: &mut Bencher) {
    do_varint_write_rand(b, 1000)
}

#[bench]
fn varint_write_rand_1_m(b: &mut Bencher) {
    do_varint_write_rand(b, 1000_000)
}

#[bench]
fn varint_read_rand_1_k(b: &mut Bencher) {
    do_varint_read_rand(b, 1000)
}

#[bench]
fn varint_read_rand_1_m(b: &mut Bencher) {
    do_varint_read_rand(b, 1000_000)
}

fn do_varint_write_rand(b: &mut Bencher, num: usize) {
    let mut rng = rand::weak_rng();

    let mut vec: Vec<u64> = Vec::new();

    for _ in 0..num {
        vec.push(rng.gen());
    }

    let mut buf = [0; 9];
    b.iter(|| {
        for i in vec.iter() {
            let _ = varint_write(*i, &mut buf);
        }
    });
}

fn do_varint_read_rand(b: &mut Bencher, num: usize) {
    let mut rng = rand::weak_rng();

    let mut vec = Vec::new();
    vec.resize(9 * num, 0);
    let mut bytes_written = 0;

    for _ in 0..num {
        bytes_written += varint_write(rng.gen(), &mut vec[bytes_written..]);
    }

    b.iter(|| {
        let mut cursor = Cursor::new(&vec);
        for _ in 0..num {
            let _ = varint_read(&mut cursor);
        }
    });
}
<commit_msg>Better varint benchmarks to explore difference across byte length range<commit_after>extern crate rand;
extern crate test;

use super::v2_serializer::varint_write;
use super::deserializer::varint_read;
use std::io::Cursor;
use self::rand::distributions::range::Range;
use self::rand::distributions::IndependentSample;
use self::test::Bencher;

#[bench]
fn varint_write_rand(b: &mut Bencher) {
    do_varint_write_rand(b, 1000_000, Range::new(0, u64::max_value()))
}

#[bench]
fn varint_write_rand_1_byte(b: &mut Bencher) {
    do_varint_write_rand(b, 1000_000, Range::new(0, 128))
}

#[bench]
fn varint_write_rand_9_bytes(b: &mut Bencher) {
    do_varint_write_rand(b, 1000_000, Range::new(1 << 56, u64::max_value()))
}

#[bench]
fn varint_read_rand(b: &mut Bencher) {
    do_varint_read_rand(b, 1000_000, Range::new(0, u64::max_value()))
}

#[bench]
fn varint_read_rand_1_byte(b: &mut Bencher) {
    do_varint_read_rand(b, 1000_000, Range::new(0, 128))
}

#[bench]
fn varint_read_rand_9_byte(b: &mut Bencher) {
    do_varint_read_rand(b, 1000_000, Range::new(1 << 56, u64::max_value()))
}

fn do_varint_write_rand(b: &mut Bencher, num: usize, range: Range<u64>) {
    let mut rng = rand::weak_rng();

    let mut vec: Vec<u64> = Vec::new();

    for _ in 0..num {
        vec.push(range.ind_sample(&mut rng));
    }

    let mut buf = [0; 9];
    b.iter(|| {
        for i in vec.iter() {
            let _ = varint_write(*i, &mut buf);
        }
    });
}

fn do_varint_read_rand(b: &mut Bencher, num: usize, range: Range<u64>) {
    let mut rng = rand::weak_rng();

    let mut vec = Vec::new();
    vec.resize(9 * num, 0);
    let mut bytes_written = 0;

    for _ in 0..num {
        bytes_written += varint_write(range.ind_sample(&mut rng), &mut vec[bytes_written..]);
    }

    b.iter(|| {
        let mut cursor = Cursor::new(&vec);
        for _ in 0..num {
            let _ = varint_read(&mut cursor);
        }
    });
}
<|endoftext|>