<commit_before>

extern crate cratesfyi;
extern crate clap;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::process;
use std::path::PathBuf;

use clap::{Arg, App, SubCommand};
use cratesfyi::{DocBuilder, DocBuilderOptions, db};
use cratesfyi::utils::build_doc;

pub fn main() {
    let _ = env_logger::init();

    let matches = App::new("cratesfyi")
                      .version(cratesfyi::BUILD_VERSION)
                      .about(env!("CARGO_PKG_DESCRIPTION"))
                      .subcommand(SubCommand::with_name("doc")
                                      .about("Builds documentation of a crate")
                                      .arg(Arg::with_name("CRATE_NAME")
                                               .index(1)
                                               .required(true)
                                               .help("Crate name"))
                                      .arg(Arg::with_name("CRATE_VERSION")
                                               .index(2)
                                               .required(false)
                                               .help("Crate version")))
                      .subcommand(SubCommand::with_name("build")
                                      .about("Builds documentation in a chroot environment")
                                      .arg(Arg::with_name("PREFIX")
                                               .short("P")
                                               .long("prefix")
                                               .takes_value(true))
                                      .arg(Arg::with_name("DESTINATION")
                                               .short("d")
                                               .long("destination")
                                               .help("Sets destination path")
                                               .takes_value(true))
                                      .arg(Arg::with_name("CHROOT_PATH")
                                               .short("c")
                                               .long("chroot")
                                               .help("Sets chroot path")
                                               .takes_value(true))
                                      .arg(Arg::with_name("CHROOT_USER")
                                               .short("u")
                                               .long("chroot-user")
                                               .help("Sets chroot user name")
                                               .takes_value(true))
                                      .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
                                               .long("crates-io-index-path")
                                               .help("Sets crates.io-index path")
                                               .takes_value(true))
                                      .arg(Arg::with_name("SKIP_IF_EXISTS")
                                               .short("s")
                                               .long("skip")
                                               .help("Skips building documentation if \
                                                      documentation exists"))
                                      .arg(Arg::with_name("SKIP_IF_LOG_EXISTS")
                                               .long("skip-if-log-exists")
                                               .help("Skips building documentation if build \
                                                      log exists"))
                                      .arg(Arg::with_name("KEEP_BUILD_DIRECTORY")
                                               .short("-k")
                                               .long("keep-build-directory")
                                               .help("Keeps build directory after build."))
                                      .subcommand(SubCommand::with_name("world")
                                                      .about("Builds documentation of every \
                                                              crate"))
                                      .subcommand(SubCommand::with_name("crate")
                                                      .about("Builds documentation for a crate")
                                                      .arg(Arg::with_name("CRATE_NAME")
                                                               .index(1)
                                                               .required(true)
                                                               .help("Crate name"))
                                                      .arg(Arg::with_name("CRATE_VERSION")
                                                               .index(2)
                                                               .required(true)
                                                               .help("Version of crate"))))
                      .subcommand(SubCommand::with_name("database")
                                      .about("Database operations")
                                      .subcommand(SubCommand::with_name("init")
                                                      .about("Initialize database. Currently \
                                                             only creates tables in database."))
                                      .subcommand(SubCommand::with_name("update-github-fields")
                                                      .about("Updates github stats for crates.")))
                      .get_matches();

    // doc subcommand
    if let Some(matches) = matches.subcommand_matches("doc") {
        let name = matches.value_of("CRATE_NAME").unwrap();
        let version = matches.value_of("CRATE_VERSION");
        if let Err(e) = build_doc(name, version) {
            panic!("{:#?}", e);
        }
    } else if let Some(matches) = matches.subcommand_matches("build") {
        let docbuilder_opts = {
            let mut docbuilder_opts = if let Some(prefix) = matches.value_of("PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else if let Ok(prefix) = env::var("CRATESFYI_PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else {
                DocBuilderOptions::default()
            };

            // set options
            if let Some(destination) = matches.value_of("DESTINATION") {
                docbuilder_opts.destination = PathBuf::from(destination);
            }

            if let Some(chroot_path) = matches.value_of("CHROOT_PATH") {
                docbuilder_opts.chroot_path = PathBuf::from(chroot_path);
            }

            if let Some(chroot_user) = matches.value_of("CHROOT_USER") {
                docbuilder_opts.chroot_user = chroot_user.to_string();
            }

            if let Some(crates_io_index_path) = matches.value_of("CRATES_IO_INDEX_PATH") {
                docbuilder_opts.crates_io_index_path = PathBuf::from(crates_io_index_path);
            }

            docbuilder_opts.skip_if_exists = matches.is_present("SKIP_IF_EXISTS");
            docbuilder_opts.skip_if_log_exists = matches.is_present("SKIP_IF_LOG_EXISTS");
            docbuilder_opts.keep_build_directory = matches.is_present("KEEP_BUILD_DIRECTORY");

            docbuilder_opts.check_paths().unwrap();

            docbuilder_opts
        };

        let mut docbuilder = DocBuilder::new(docbuilder_opts);

        docbuilder.load_cache().expect("Failed to load cache");

        if let Some(_) = matches.subcommand_matches("world") {
            docbuilder.build_world().expect("Failed to build world");
        } else if let Some(matches) = matches.subcommand_matches("crate") {
            docbuilder.build_package(matches.value_of("CRATE_NAME").unwrap(),
                                     matches.value_of("CRATE_VERSION").unwrap())
                      .expect("Building documentation failed");
        }

        docbuilder.save_cache().expect("Failed to save cache");
    } else if let Some(matches) = matches.subcommand_matches("database") {
        if let Some(_) = matches.subcommand_matches("init") {
            use std::io::Write;
            use std::io;
            let conn = db::connect_db().unwrap();
            if let Err(err) = db::create_tables(&conn) {
                writeln!(&mut io::stderr(), "Failed to initialize database: {}", err).unwrap();
                process::exit(1);
            }
        } else if let Some(_) = matches.subcommand_matches("update-github-fields") {
            cratesfyi::utils::github_updater().expect("Failed to update github fields");
        }
    } else {
        println!("{}", matches.usage());
    }
}
<commit_msg>Add add-directory subcommand to database<commit_after>

extern crate cratesfyi;
extern crate clap;
#[macro_use]
extern crate log;
extern crate env_logger;

use std::env;
use std::process;
use std::path::PathBuf;

use clap::{Arg, App, SubCommand};
use cratesfyi::{DocBuilder, DocBuilderOptions, db};
use cratesfyi::utils::build_doc;
use cratesfyi::db::add_path_into_database;

pub fn main() {
    let _ = env_logger::init();

    let matches = App::new("cratesfyi")
                      .version(cratesfyi::BUILD_VERSION)
                      .about(env!("CARGO_PKG_DESCRIPTION"))
                      .subcommand(SubCommand::with_name("doc")
                                      .about("Builds documentation of a crate")
                                      .arg(Arg::with_name("CRATE_NAME")
                                               .index(1)
                                               .required(true)
                                               .help("Crate name"))
                                      .arg(Arg::with_name("CRATE_VERSION")
                                               .index(2)
                                               .required(false)
                                               .help("Crate version")))
                      .subcommand(SubCommand::with_name("build")
                                      .about("Builds documentation in a chroot environment")
                                      .arg(Arg::with_name("PREFIX")
                                               .short("P")
                                               .long("prefix")
                                               .takes_value(true))
                                      .arg(Arg::with_name("DESTINATION")
                                               .short("d")
                                               .long("destination")
                                               .help("Sets destination path")
                                               .takes_value(true))
                                      .arg(Arg::with_name("CHROOT_PATH")
                                               .short("c")
                                               .long("chroot")
                                               .help("Sets chroot path")
                                               .takes_value(true))
                                      .arg(Arg::with_name("CHROOT_USER")
                                               .short("u")
                                               .long("chroot-user")
                                               .help("Sets chroot user name")
                                               .takes_value(true))
                                      .arg(Arg::with_name("CRATES_IO_INDEX_PATH")
                                               .long("crates-io-index-path")
                                               .help("Sets crates.io-index path")
                                               .takes_value(true))
                                      .arg(Arg::with_name("SKIP_IF_EXISTS")
                                               .short("s")
                                               .long("skip")
                                               .help("Skips building documentation if \
                                                      documentation exists"))
                                      .arg(Arg::with_name("SKIP_IF_LOG_EXISTS")
                                               .long("skip-if-log-exists")
                                               .help("Skips building documentation if build \
                                                      log exists"))
                                      .arg(Arg::with_name("KEEP_BUILD_DIRECTORY")
                                               .short("-k")
                                               .long("keep-build-directory")
                                               .help("Keeps build directory after build."))
                                      .subcommand(SubCommand::with_name("world")
                                                      .about("Builds documentation of every \
                                                              crate"))
                                      .subcommand(SubCommand::with_name("crate")
                                                      .about("Builds documentation for a crate")
                                                      .arg(Arg::with_name("CRATE_NAME")
                                                               .index(1)
                                                               .required(true)
                                                               .help("Crate name"))
                                                      .arg(Arg::with_name("CRATE_VERSION")
                                                               .index(2)
                                                               .required(true)
                                                               .help("Version of crate"))))
                      .subcommand(SubCommand::with_name("database")
                                      .about("Database operations")
                                      .subcommand(SubCommand::with_name("init")
                                                      .about("Initialize database. Currently \
                                                              only creates tables in database."))
                                      .subcommand(SubCommand::with_name("update-github-fields")
                                                      .about("Updates github stats for crates."))
                                      .subcommand(SubCommand::with_name("add-directory")
                                                      .about("Adds a directory into database")
                                                      .arg(Arg::with_name("DIRECTORY")
                                                               .index(1)
                                                               .required(true)
                                                               .help("Path of file or \
                                                                      directory"))
                                                      .arg(Arg::with_name("PREFIX")
                                                               .index(2)
                                                               .help("Prefix of files in \
                                                                      database"))))
                      .get_matches();

    // doc subcommand
    if let Some(matches) = matches.subcommand_matches("doc") {
        let name = matches.value_of("CRATE_NAME").unwrap();
        let version = matches.value_of("CRATE_VERSION");
        if let Err(e) = build_doc(name, version) {
            panic!("{:#?}", e);
        }
    } else if let Some(matches) = matches.subcommand_matches("build") {
        let docbuilder_opts = {
            let mut docbuilder_opts = if let Some(prefix) = matches.value_of("PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else if let Ok(prefix) = env::var("CRATESFYI_PREFIX") {
                DocBuilderOptions::from_prefix(PathBuf::from(prefix))
            } else {
                DocBuilderOptions::default()
            };

            // set options
            if let Some(destination) = matches.value_of("DESTINATION") {
                docbuilder_opts.destination = PathBuf::from(destination);
            }

            if let Some(chroot_path) = matches.value_of("CHROOT_PATH") {
                docbuilder_opts.chroot_path = PathBuf::from(chroot_path);
            }

            if let Some(chroot_user) = matches.value_of("CHROOT_USER") {
                docbuilder_opts.chroot_user = chroot_user.to_string();
            }

            if let Some(crates_io_index_path) = matches.value_of("CRATES_IO_INDEX_PATH") {
                docbuilder_opts.crates_io_index_path = PathBuf::from(crates_io_index_path);
            }

            docbuilder_opts.skip_if_exists = matches.is_present("SKIP_IF_EXISTS");
            docbuilder_opts.skip_if_log_exists = matches.is_present("SKIP_IF_LOG_EXISTS");
            docbuilder_opts.keep_build_directory = matches.is_present("KEEP_BUILD_DIRECTORY");

            docbuilder_opts.check_paths().unwrap();

            docbuilder_opts
        };

        let mut docbuilder = DocBuilder::new(docbuilder_opts);

        docbuilder.load_cache().expect("Failed to load cache");

        if let Some(_) = matches.subcommand_matches("world") {
            docbuilder.build_world().expect("Failed to build world");
        } else if let Some(matches) = matches.subcommand_matches("crate") {
            docbuilder.build_package(matches.value_of("CRATE_NAME").unwrap(),
                                     matches.value_of("CRATE_VERSION").unwrap())
                      .expect("Building documentation failed");
        }

        docbuilder.save_cache().expect("Failed to save cache");
    } else if let Some(matches) = matches.subcommand_matches("database") {
        if let Some(_) = matches.subcommand_matches("init") {
            use std::io::Write;
            use std::io;
            let conn = db::connect_db().unwrap();
            if let Err(err) = db::create_tables(&conn) {
                writeln!(&mut io::stderr(), "Failed to initialize database: {}", err).unwrap();
                process::exit(1);
            }
        } else if let Some(_) = matches.subcommand_matches("update-github-fields") {
            cratesfyi::utils::github_updater().expect("Failed to update github fields");
        } else if let Some(matches) = matches.subcommand_matches("add-directory") {
            add_path_into_database(&db::connect_db().unwrap(),
                                   matches.value_of("PREFIX").unwrap_or(""),
                                   matches.value_of("DIRECTORY").unwrap())
                .unwrap();
        }
    } else {
        println!("{}", matches.usage());
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate octobuild;

use octobuild::common::BuildTask;
use octobuild::cache::Cache;
use octobuild::wincmd;
use octobuild::xg;
use octobuild::graph::{Graph, NodeIndex, Node, EdgeIndex, Edge};
use octobuild::vs::compiler::VsCompiler;
use octobuild::compiler::Compiler;

use std::os;

use std::io::{Command, File, BufferedReader, IoError, TempDir};
use std::io::process::{ProcessExit, ProcessOutput};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::Thread;

#[derive(Show)]
struct TaskMessage {
index: NodeIndex,
task: BuildTask
}

#[derive(Show)]
struct ResultMessage {
index: NodeIndex,
result: Result<BuildResult, String>
}

#[derive(Show)]
struct BuildResult {
exit_code: ProcessExit,
}

fn main() {
	let temp_dir = match TempDir::new("octobuild") {
		Ok(result) => result,
		Err(e) => {panic!(e);}
	};

	println!("XGConsole:");
	for arg in os::args().iter() {
		println!("  {}", arg);
	}

	let (tx_result, rx_result): (Sender<ResultMessage>, Receiver<ResultMessage>) = channel();
	let (tx_task, rx_task): (Sender<TaskMessage>, Receiver<TaskMessage>) = channel();
	let cache = Cache::new();

	let mutex_rx_task = create_threads(rx_task, tx_result, std::os::num_cpus(), |worker_id:usize| {
		let temp_path = temp_dir.path().clone();
		let temp_cache = cache.clone();
		move |task:TaskMessage| -> ResultMessage {
			println!("{}: {:?}", worker_id, task.task.title);
			execute_task(&temp_cache, &temp_path, task)
		}
	});

	let args = os::args();
	let mut path;
	if args.len() <= 1 {
		path = Path::new(&args[0]).dir_path();
		path.push("../tests/graph-parser.xml");
	} else {
		path = Path::new(&args[1]);
	}
	println!("Example path: {}", path.display());
	match File::open(&path) {
			Ok(file) => {
			match xg::parser::parse(BufferedReader::new(file)) {
					Ok(graph) => {
					match validate_graph(graph) {
							Ok(graph) => {
								execute_graph(&graph, tx_task, mutex_rx_task, rx_result);
						}
							Err(msg) =>{panic! (msg);}
						}
				}
					Err(msg) =>{panic! (msg);}
				}
		}
			Err(msg) =>{panic! (msg);}
		}

	println!("done");
}

fn create_threads<R: Send, T: Send, Worker:Fn(T) -> R + Send, Factory:Fn(usize) -> Worker>(rx_task: Receiver<T>, tx_result: Sender<R>, num_cpus: usize, factory: Factory) ->  Arc<Mutex<Receiver<T>>> {
	let mutex_rx_task = Arc::new(Mutex::new(rx_task));
	for cpu_id in range(0, num_cpus) {
	 		let local_rx_task = mutex_rx_task.clone();
			let local_tx_result = tx_result.clone();
		let worker = factory(cpu_id);
		Thread::spawn(move || {
			loop {
				let task: T;
				match local_rx_task.lock().unwrap().recv() {
					Ok(v) => {task = v;}
					Err(_) => {break;}
				}
				match local_tx_result.send(worker(task)) {
					Ok(_) => {}
					Err(_) => {break;}
				}
			}
		});
	}
	mutex_rx_task
}

fn validate_graph(graph: Graph<BuildTask, ()>) -> Result<Graph<BuildTask, ()>, String> {
	let mut completed:Vec<bool> = Vec::new();
	let mut queue:Vec<NodeIndex> = Vec::new();
		graph. each_node(|index: NodeIndex, _:&Node<BuildTask>|->bool {
			completed.push(false);
			queue.push(index);
			true
	});
	let mut count:usize = 0;
	let mut i:usize = 0;
	while i < queue.len() {
		let index = queue[i];
		if (!completed[index.node_id()]) && (is_ready(&graph, &completed, &index)) {
			completed[index.node_id()] = true;
				graph.each_incoming_edge(index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					queue.push(edge.source());
					true
			});
			count += 1;
			if count ==completed.len() {
				return Ok(graph);
			}
		}
		i = i + 1;
	}
	return Err("Found cycles in build dependencies.".to_string());
}

fn execute_task(cache: &Cache, temp_dir: &Path, message: TaskMessage) -> ResultMessage {
	println!("{}", message.task.title);

	let args = wincmd::expand_args(&message.task.args, &|name:&str|->Option<String>{os::getenv(name)});
	match execute_compiler(cache, temp_dir, message.task.exec.as_slice(), &Path::new(&message.task.working_dir), args.as_slice()) {
		Ok(output) => {
			println!("stdout: {}", String::from_utf8_lossy(output.output.as_slice()));
			println!("stderr: {}", String::from_utf8_lossy(output.error.as_slice()));
			ResultMessage {
				index: message.index,
				result: Ok(BuildResult {
				exit_code: output.status
			})
		}}
		Err(e) => {
			ResultMessage {
				index: message.index,
				result: Err(format!("Failed to start process: {}", e))
			}
		}
	}
}

fn execute_compiler(cache: &Cache, temp_dir: &Path, program: &str, cwd: &Path, args: &[String]) -> Result<ProcessOutput, IoError> {
	let mut command = Command::new(program);
	command.cwd(cwd);
	if Path::new(program).ends_with_path(&Path::new("cl.exe")) {
		let compiler = VsCompiler::new(cache, temp_dir);
		compiler.compile(&command, args)
	} else {
		command
			.args(args.as_slice())
			.output()
	}
}

fn execute_graph(graph: &Graph<BuildTask, ()>, tx_task: Sender<TaskMessage>, rx_task: Arc<Mutex<Receiver<TaskMessage>>>, rx_result: Receiver<ResultMessage>) {
	let mut completed:Vec<bool> = Vec::new();
		graph. each_node(|index: NodeIndex, node:&Node<BuildTask>|->bool {
		let mut has_edges = false;
			graph.each_outgoing_edge(index, |_:EdgeIndex, _:&Edge<()>| -> bool {
			has_edges = true;
			false
		});
		if !has_edges {
				tx_task.send(TaskMessage{
			index: index,
			task: node.data.clone(),
			})  ;
		}
			completed.push(false);
		true
	});
	let mut count:usize = 0;
	for message in rx_result.iter() {
		assert!(!completed[message.index.node_id()]);
		count += 1;
		println!("R {}/{}: {:?}", count, completed.len(), message);
		match message.result {
				Ok (result) => {
				if !result.exit_code.success() {
					break;
				}
				completed[message.index.node_id()] = true;
					graph.each_incoming_edge(message.index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					let source = edge.source();
					if !completed[source.node_id()] {
						if is_ready(graph, &completed, &source) {
								tx_task.send(TaskMessage{
							index: source,
							task: graph.node(source).data.clone(),
							})  ;
						}
					}
					true
				});
			}
				Err (e) => {
				println!("{}", e);
				break;
			}
			}
		if count == completed.len() {
			break;
		}
	}
	// No more tasks.
	free(tx_task);
	// Cleanup task list.
	match rx_task.lock() {
			queue => {
			for _ in queue.iter() {
			}
		}
		}
	// Wait for in progress task completion.
	for _ in rx_result.iter() {
	}
}

fn free<T>(_:T) {
}

fn is_ready(graph: &Graph<BuildTask, ()>, completed: &Vec<bool>, source: &NodeIndex) -> bool {
	let mut ready = true;
		graph.each_outgoing_edge(*source, |_:EdgeIndex, deps:&Edge<()>| -> bool {
		if !completed[deps.target().node_id()]{
			ready = false;
			false
		} else {
			true
		}
	});
	ready
}
<commit_msg>More clear output.<commit_after>#![allow(unstable)]
extern crate octobuild;

use octobuild::common::BuildTask;
use octobuild::cache::Cache;
use octobuild::wincmd;
use octobuild::xg;
use octobuild::graph::{Graph, NodeIndex, Node, EdgeIndex, Edge};
use octobuild::vs::compiler::VsCompiler;
use octobuild::compiler::Compiler;

use std::os;

use std::io::{stdout, stderr, Command, File, BufferedReader, IoError, TempDir};
use std::io::process::{ProcessExit, ProcessOutput};
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::Thread;

#[derive(Show)]
struct TaskMessage {
index: NodeIndex,
task: BuildTask
}

#[derive(Show)]
struct ResultMessage {
	index: NodeIndex,
	task: BuildTask,
	worker: usize,
	result: Result<BuildResult, String>
}

#[derive(Show)]
struct BuildResult {
	exit_code: ProcessExit,
	stdout: Vec<u8>,
	stderr: Vec<u8>,
}

fn main() {
	let temp_dir = match TempDir::new("octobuild") {
		Ok(result) => result,
		Err(e) => {panic!(e);}
	};

	println!("XGConsole:");
	for arg in os::args().iter() {
		println!("  {}", arg);
	}

	let (tx_result, rx_result): (Sender<ResultMessage>, Receiver<ResultMessage>) = channel();
	let (tx_task, rx_task): (Sender<TaskMessage>, Receiver<TaskMessage>) = channel();
	let cache = Cache::new();

	let mutex_rx_task = create_threads(rx_task, tx_result, std::os::num_cpus(), |worker_id:usize| {
		let temp_path = temp_dir.path().clone();
		let temp_cache = cache.clone();
		move |task:TaskMessage| -> ResultMessage {
			execute_task(&temp_cache, &temp_path, worker_id, task)
		}
	});

	let args = os::args();
	if args.len() <= 1 {
		panic! ("Task file is not defined");
	}
	let path = Path::new(&args[1]);
	match File::open(&path) {
		Ok(file) => {
			match xg::parser::parse(BufferedReader::new(file)) {
				Ok(graph) => {
					match validate_graph(graph) {
						Ok(graph) => {
							execute_graph(&graph, tx_task, mutex_rx_task, rx_result);
						}
						Err(msg) =>{panic! (msg);}
					}
				}
				Err(msg) =>{panic! (msg);}
			}
		}
		Err(msg) =>{panic! (msg);}
	}
}

fn create_threads<R: Send, T: Send, Worker:Fn(T) -> R + Send, Factory:Fn(usize) -> Worker>(rx_task: Receiver<T>, tx_result: Sender<R>, num_cpus: usize, factory: Factory) ->  Arc<Mutex<Receiver<T>>> {
	let mutex_rx_task = Arc::new(Mutex::new(rx_task));
	for cpu_id in range(0, num_cpus) {
	 		let local_rx_task = mutex_rx_task.clone();
			let local_tx_result = tx_result.clone();
		let worker = factory(cpu_id);
		Thread::spawn(move || {
			loop {
				let task: T;
				match local_rx_task.lock().unwrap().recv() {
					Ok(v) => {task = v;}
					Err(_) => {break;}
				}
				match local_tx_result.send(worker(task)) {
					Ok(_) => {}
					Err(_) => {break;}
				}
			}
		});
	}
	mutex_rx_task
}

fn validate_graph(graph: Graph<BuildTask, ()>) -> Result<Graph<BuildTask, ()>, String> {
	let mut completed:Vec<bool> = Vec::new();
	let mut queue:Vec<NodeIndex> = Vec::new();
		graph. each_node(|index: NodeIndex, _:&Node<BuildTask>|->bool {
			completed.push(false);
			queue.push(index);
			true
	});
	let mut count:usize = 0;
	let mut i:usize = 0;
	while i < queue.len() {
		let index = queue[i];
		if (!completed[index.node_id()]) && (is_ready(&graph, &completed, &index)) {
			completed[index.node_id()] = true;
				graph.each_incoming_edge(index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					queue.push(edge.source());
					true
			});
			count += 1;
			if count ==completed.len() {
				return Ok(graph);
			}
		}
		i = i + 1;
	}
	return Err("Found cycles in build dependencies.".to_string());
}

fn execute_task(cache: &Cache, temp_dir: &Path, worker: usize, message: TaskMessage) -> ResultMessage {
	let args = wincmd::expand_args(&message.task.args, &|name:&str|->Option<String>{os::getenv(name)});
	match execute_compiler(cache, temp_dir, message.task.exec.as_slice(), &Path::new(&message.task.working_dir), args.as_slice()) {
		Ok(output) => {
			ResultMessage {
				index: message.index,
				task: message.task,
				worker: worker,
				result: Ok(BuildResult {
					exit_code: output.status,
					stdout: output.output,
					stderr: output.error
				})
			}
		}
		Err(e) => {
			ResultMessage {
				index: message.index,
				task: message.task,
				worker: worker,
				result: Err(format!("Failed to start process: {}", e))
			}
		}
	}
}

fn execute_compiler(cache: &Cache, temp_dir: &Path, program: &str, cwd: &Path, args: &[String]) -> Result<ProcessOutput, IoError> {
	let mut command = Command::new(program);
	command.cwd(cwd);
	if Path::new(program).ends_with_path(&Path::new("cl.exe")) {
		let compiler = VsCompiler::new(cache, temp_dir);
		compiler.compile(&command, args)
	} else {
		command
			.args(args.as_slice())
			.output()
	}
}

fn execute_graph(graph: &Graph<BuildTask, ()>, tx_task: Sender<TaskMessage>, rx_task: Arc<Mutex<Receiver<TaskMessage>>>, rx_result: Receiver<ResultMessage>) {
	let mut completed:Vec<bool> = Vec::new();
		graph. each_node(|index: NodeIndex, node:&Node<BuildTask>|->bool {
		let mut has_edges = false;
			graph.each_outgoing_edge(index, |_:EdgeIndex, _:&Edge<()>| -> bool {
			has_edges = true;
			false
		});
		if !has_edges {
				tx_task.send(TaskMessage{
			index: index,
			task: node.data.clone(),
			})  ;
		}
			completed.push(false);
		true
	});
	let mut count:usize = 0;
	for message in rx_result.iter() {
		assert!(!completed[message.index.node_id()]);
		count += 1;
		println!("#{} {}/{}: {}", message.worker, count, completed.len(), message.task.title);
		match message.result {
			Ok (result) => {
				stdout().write(result.stdout.as_slice());
				stderr().write(result.stderr.as_slice());
				if !result.exit_code.success() {
					break;
				}
				completed[message.index.node_id()] = true;
					graph.each_incoming_edge(message.index, |_:EdgeIndex, edge:&Edge<()>| -> bool {
					let source = edge.source();
					if !completed[source.node_id()] {
						if is_ready(graph, &completed, &source) {
								tx_task.send(TaskMessage{
							index: source,
							task: graph.node(source).data.clone(),
							})  ;
						}
					}
					true
				});
			}
			Err (e) => {
				println!("{}", e);
				break;
			}
			}
		if count == completed.len() {
			break;
		}
	}
	// No more tasks.
	free(tx_task);
	// Cleanup task list.
	match rx_task.lock() {
			queue => {
			for _ in queue.iter() {
			}
		}
		}
	// Wait for in progress task completion.
	for _ in rx_result.iter() {
	}
}

fn free<T>(_:T) {
}

fn is_ready(graph: &Graph<BuildTask, ()>, completed: &Vec<bool>, source: &NodeIndex) -> bool {
	let mut ready = true;
		graph.each_outgoing_edge(*source, |_:EdgeIndex, deps:&Edge<()>| -> bool {
		if !completed[deps.target().node_id()]{
			ready = false;
			false
		} else {
			true
		}
	});
	ready
}
<|endoftext|>


<commit_before>//! Conversion methods for JSON values.

use rustwlc::{Geometry, Point, Size};
use std::collections::BTreeMap;

use rlua;
use rustc_serialize::json::{Json, ToJson};

/// Converts a Json map into a Lua value
pub fn json_to_lua<'lua>(lua: &'lua rlua::Lua, json: Json)
                         -> Result<rlua::Value<'lua>, rlua::Error> {
    use rlua::Value;
    match json {
        Json::String(val)  => Ok(Value::String(lua.create_string(&val))),
        Json::Boolean(val) => Ok(Value::Boolean(val)),
        Json::F64(val)     => Ok(Value::Number(val)),
        Json::I64(val)     => Ok(Value::Number((val as i32) as f64)),
        Json::U64(val)     => Ok(Value::Number((val as u32) as f64)),
        Json::Null         => Ok(Value::Nil),
        Json::Array(vals)  => {
            let mut new_vals = Vec::with_capacity(vals.len());
            for (idx, val) in vals.into_iter().enumerate() {
                new_vals.push((idx, json_to_lua(lua, val)?));
            }
            lua.create_table_from(new_vals)
                .map(|table| Value::Table(table))
        },
        Json::Object(vals) => {
            let mut new_vals = BTreeMap::new();
            for (k, v) in vals {
                new_vals.insert(k, json_to_lua(lua, v)?);
            }
            lua.create_table_from(new_vals)
                .map(|table| Value::Table(table))
        }
    }
}

/// Converts an `rlua::Value` to a `Json`.
pub fn lua_to_json<'lua>(lua_value: rlua::Value<'lua>)
                         -> Result<Json, rlua::Value<'lua>> {
    use rlua::Value::*;
    match lua_value {
        Nil => Ok(Json::Null),
        String(val) => Ok(Json::String(val.to_str().unwrap().into())),
        Number(val) => Ok(Json::F64(val)),
        Integer(val) => Ok(Json::I64(val as _)),
        Boolean(val) => Ok(Json::Boolean(val)),
        Table(arr) => lua_table_to_json(arr),
        _ => Err(lua_value)
    }
}

/// Convert an AnyLuaValue to a Json array using numerical indicies.
///
/// # Result
/// This function returns an Err if the Lua object has a non-String key.
pub fn lua_table_to_json<'lua>(table: rlua::Table<'lua>)
                               -> Result<Json, rlua::Value<'lua>> {
    use rlua::Value;
    use rlua::Error;
    // Check if every key is a number
    let mut counter = 0.0; // Account for first index?

    for entry in table.clone().pairs::<Value, Value>() {
        let (key, _ )= entry.unwrap();
        match key {
            Value::Number(num) => {
                counter += num;
            }
            Value::String(_) => {
                break;
            }
            // Non-string keys are not allowed
            _ => {
                return Err(Value::Error(Error::FromLuaConversionError {
                    from: "Lua table",
                    to: "JSON object",
                    message: Some(format!("Could not convert {:#?}", table))
                }))
            }
        }
    }

    // Gauss' trick
    let len = table.len().unwrap();
    let desired_sum = (len * (len + 1)) / 2;
    if counter != desired_sum as f64 {
        return lua_object_to_json(table)
    }

    let mut json_arr: Vec<Json> = Vec::with_capacity(len as _);

    for entry in table.pairs::<Value, Value>() {
        let (_, val) = entry.unwrap();
        let lua_val = lua_to_json(val)?;
        json_arr.push(lua_val);
    }
    Ok(Json::Array(json_arr))
}

/// Converts an AnyLuaValue object to a Json object.
///
/// Will return an Err if the Lua object uses non-String keys.
pub fn lua_object_to_json<'lua>(table: rlua::Table<'lua>)
                          -> Result<Json, rlua::Value<'lua>> {
    use rlua::Value;
    let mut json_obj: BTreeMap<String, Json> = BTreeMap::new();

    for entry in table.clone().pairs::<Value, Value>() {
        let (key, val) = entry.unwrap();
        match key {
            Value::String(text) => {
                let text = text.to_str().unwrap().into();
                json_obj.insert(text, lua_to_json(val.clone())?);
            },
            Value::Number(ix) => {
                json_obj.insert(ix.to_string(), lua_to_json(val.clone())?);
            }
            _ => {
                return Err(Value::Table(table))
            }
        }
    }
    Ok(Json::Object(json_obj))
}

pub fn size_to_json(size: Size) -> Json {
    let mut map = BTreeMap::new();
    map.insert("w".into(), size.w.to_json());
    map.insert("h".into(), size.h.to_json());
    map.to_json()
}

pub fn point_to_json(point: Point) -> Json {
    let mut map = BTreeMap::new();
    map.insert("x".into(), point.x.to_json());
    map.insert("y".into(), point.y.to_json());
    map.to_json()
}

pub fn geometry_to_json(geometry: Geometry) -> Json {
    let mut map = BTreeMap::new();
    let origin = point_to_json(geometry.origin);
    let size = size_to_json(geometry.size);
    map.insert("origin".into(), origin);
    map.insert("size".into(), size);
    map.to_json()
}
<commit_msg>Fixed convert erorr returns, and pub<commit_after>//! Conversion methods for JSON values.

use rustwlc::{Geometry, Point, Size};
use std::collections::BTreeMap;

use rlua;
use rustc_serialize::json::{Json, ToJson};

/// Converts a Json map into a Lua value
pub fn json_to_lua<'lua>(lua: &'lua rlua::Lua, json: Json)
                         -> Result<rlua::Value<'lua>, rlua::Error> {
    use rlua::Value;
    match json {
        Json::String(val)  => Ok(Value::String(lua.create_string(&val))),
        Json::Boolean(val) => Ok(Value::Boolean(val)),
        Json::F64(val)     => Ok(Value::Number(val)),
        Json::I64(val)     => Ok(Value::Number((val as i32) as f64)),
        Json::U64(val)     => Ok(Value::Number((val as u32) as f64)),
        Json::Null         => Ok(Value::Nil),
        Json::Array(vals)  => {
            let mut new_vals = Vec::with_capacity(vals.len());
            for (idx, val) in vals.into_iter().enumerate() {
                new_vals.push((idx, json_to_lua(lua, val)?));
            }
            lua.create_table_from(new_vals)
                .map(|table| Value::Table(table))
        },
        Json::Object(vals) => {
            let mut new_vals = BTreeMap::new();
            for (k, v) in vals {
                new_vals.insert(k, json_to_lua(lua, v)?);
            }
            lua.create_table_from(new_vals)
                .map(|table| Value::Table(table))
        }
    }
}

/// Converts an `rlua::Value` to a `Json`.
pub fn lua_to_json<'lua>(lua_value: rlua::Value<'lua>)
                         -> Result<Json, rlua::Error> {
    use rlua::Value::*;
    use rlua::Error;
    match lua_value {
        Nil => Ok(Json::Null),
        String(val) => Ok(Json::String(val.to_str().unwrap().into())),
        Number(val) => Ok(Json::F64(val)),
        Integer(val) => Ok(Json::I64(val as _)),
        Boolean(val) => Ok(Json::Boolean(val)),
        Table(arr) => lua_table_to_json(arr),
        _ => Err(Error::RuntimeError(
            format!("Did not expect {:#?}", lua_value)))
    }
}

/// Convert an AnyLuaValue to a Json array using numerical indicies.
///
/// # Result
/// This function returns an Err if the Lua object has a non-String key.
fn lua_table_to_json<'lua>(table: rlua::Table<'lua>)
                               -> Result<Json, rlua::Error> {
    use rlua::Value;
    use rlua::Error;
    // Check if every key is a number
    let mut counter = 0.0; // Account for first index?

    for entry in table.clone().pairs::<Value, Value>() {
        let (key, _ )= entry?;
        match key {
            Value::Number(num) => {
                counter += num;
            }
            Value::String(_) => {
                break;
            }
            // Non-string keys are not allowed
            _ => return Err(Error::FromLuaConversionError {
                from: "Lua table",
                to: "JSON object",
                message: Some(format!("Could not convert {:#?}", table))
            })
        }
    }

    // Gauss' trick
    let len = table.len().unwrap();
    let desired_sum = (len * (len + 1)) / 2;
    if counter != desired_sum as f64 {
        return lua_object_to_json(table)
    }

    let mut json_arr: Vec<Json> = Vec::with_capacity(len as _);

    for entry in table.pairs::<Value, Value>() {
        let (_, val) = entry.unwrap();
        let lua_val = lua_to_json(val)?;
        json_arr.push(lua_val);
    }
    Ok(Json::Array(json_arr))
}

/// Converts an AnyLuaValue object to a Json object.
///
/// Will return an Err if the Lua object uses non-String keys.
fn lua_object_to_json<'lua>(table: rlua::Table<'lua>)
                          -> Result<Json, rlua::Error> {
    use rlua::{Value, Error};
    let mut json_obj: BTreeMap<String, Json> = BTreeMap::new();

    for entry in table.clone().pairs::<Value, Value>() {
        let (key, val) = entry.unwrap();
        match key {
            Value::String(text) => {
                let text = text.to_str().unwrap().into();
                json_obj.insert(text, lua_to_json(val.clone())?);
            },
            Value::Number(ix) => {
                json_obj.insert(ix.to_string(), lua_to_json(val.clone())?);
            }
            _ => {
                return Err(Error::RuntimeError(
                    format!("Did not expect {:#?}", table)))
            }
        }
    }
    Ok(Json::Object(json_obj))
}

pub fn size_to_json(size: Size) -> Json {
    let mut map = BTreeMap::new();
    map.insert("w".into(), size.w.to_json());
    map.insert("h".into(), size.h.to_json());
    map.to_json()
}

pub fn point_to_json(point: Point) -> Json {
    let mut map = BTreeMap::new();
    map.insert("x".into(), point.x.to_json());
    map.insert("y".into(), point.y.to_json());
    map.to_json()
}

pub fn geometry_to_json(geometry: Geometry) -> Json {
    let mut map = BTreeMap::new();
    let origin = point_to_json(geometry.origin);
    let size = size_to_json(geometry.size);
    map.insert("origin".into(), origin);
    map.insert("size".into(), size);
    map.to_json()
}
<|endoftext|>


<commit_before>use analysis;
use analysis::type_kind::{TypeKind, ToTypeKind};
use library;

pub trait TranslateFromGlib {
    fn translate_from_glib_as_function(&self,
        library: &library::Library, func: &analysis::functions::Info) -> (String, String);
}

impl TranslateFromGlib for library::Parameter {
    fn translate_from_glib_as_function(&self,
        library: &library::Library, func: &analysis::functions::Info) -> (String, String) {
        let kind = library.type_(self.typ).to_type_kind(library);
        if func.kind == library::FunctionKind::Constructor {
            match kind {
                TypeKind::Widget => ("Widget::from_glib_none(".into(),
                    ").downcast_unchecked()".into()),
                _ => ("TODO:constructors_body ".into(), String::new())
            }
        } else {
            match kind {
                TypeKind::Converted => ("from_glib(".into(), ")".into()),
                TypeKind::Direct |
                    TypeKind::Enumeration => (String::new(), String::new()),
                TypeKind::Object |
                    TypeKind::Widget => from_glib_xxx(self.transfer),
                _ => ("TODO:".into(), String::new()),
            }
        }
    }
}

impl TranslateFromGlib for Option<library::Parameter> {
    fn translate_from_glib_as_function(&self,
        library: &library::Library, func: &analysis::functions::Info) -> (String, String) {
        match self {
            &Some(ref par) => par.translate_from_glib_as_function(library, func),
            &None => (String::new(), ";".into())
        }
    }
}

fn from_glib_xxx(transfer: library::Transfer) -> (String, String) {
    use library::Transfer::*;
    match transfer {
        None => ("from_glib_none(".into(), ")".into()),
        Full => ("from_glib_full(".into(), ")".into()),
        Container => ("TODO:".into(), String::new()),
    }
}
<commit_msg>Constructor generation don't use TypeKind::Widget<commit_after>use analysis;
use analysis::rust_type::{AsStr, rust_type};
use analysis::type_kind::{TypeKind, ToTypeKind};
use library;

pub trait TranslateFromGlib {
    fn translate_from_glib_as_function(&self,
        library: &library::Library, func: &analysis::functions::Info) -> (String, String);
}

impl TranslateFromGlib for library::Parameter {
    fn translate_from_glib_as_function(&self,
        library: &library::Library, func: &analysis::functions::Info) -> (String, String) {
        let kind = library.type_(self.typ).to_type_kind(library);
        if func.kind == library::FunctionKind::Constructor {
            let rust_type = rust_type(library, self.typ);
            if rust_type.as_str() != func.class_name.as_str() {
                let from_glib_xxx = from_glib_xxx(self.transfer);
                (
                    format!("{}::{}", rust_type.as_str(), from_glib_xxx.0),
                    format!("{}.downcast_unchecked()",from_glib_xxx.1)
                )
            } else {
                ("TODO:constructors_body ".into(), String::new())
            }
        } else {
            match kind {
                TypeKind::Converted => ("from_glib(".into(), ")".into()),
                TypeKind::Direct |
                    TypeKind::Enumeration => (String::new(), String::new()),
                TypeKind::Object |
                    TypeKind::Widget => from_glib_xxx(self.transfer),
                _ => ("TODO:".into(), String::new()),
            }
        }
    }
}

impl TranslateFromGlib for Option<library::Parameter> {
    fn translate_from_glib_as_function(&self,
        library: &library::Library, func: &analysis::functions::Info) -> (String, String) {
        match self {
            &Some(ref par) => par.translate_from_glib_as_function(library, func),
            &None => (String::new(), ";".into())
        }
    }
}

fn from_glib_xxx(transfer: library::Transfer) -> (String, String) {
    use library::Transfer::*;
    match transfer {
        None => ("from_glib_none(".into(), ")".into()),
        Full => ("from_glib_full(".into(), ")".into()),
        Container => ("TODO:".into(), String::new()),
    }
}
<|endoftext|>


<commit_before>//! The root scope of all timely dataflow computations.

use std::rc::Rc;
use std::cell::RefCell;

use progress::timestamp::RootTimestamp;
use progress::{Timestamp, Operate, Subgraph};
use timely_communication::{Allocate, Data};
use {Push, Pull};

use super::{ScopeParent, Child};

/// A `Root` is the entry point to a timely dataflow computation. It wraps a `Allocate`,
/// and has a list of child `Operate`s.
pub struct Root<A: Allocate> {
    allocator: Rc<RefCell<A>>,
    identifiers: Rc<RefCell<usize>>,
    dataflows: Rc<RefCell<Vec<Wrapper>>>,
    dataflow_counter: Rc<RefCell<usize>>,
}

impl<A: Allocate> Root<A> {
    /// Allocates a new `Root` bound to a channel allocator.
    pub fn new(c: A) -> Root<A> {
        let mut result = Root {
            allocator: Rc::new(RefCell::new(c)),
            identifiers: Rc::new(RefCell::new(0)),
            dataflows: Rc::new(RefCell::new(Vec::new())),
            dataflow_counter: Rc::new(RefCell::new(0)),
        };

        // LOGGING
        if cfg!(feature = "logging") {
            ::logging::initialize(&mut result);
        }

        result
    }

    /// Performs one step of the computation.
    ///
    /// A step gives each dataflow operator a chance to run, and is the
    /// main way to ensure that a computation procedes.
    pub fn step(&mut self) -> bool {

        if cfg!(feature = "logging") {
            ::logging::flush_logs();
        }

        let mut active = false;
        for dataflow in self.dataflows.borrow_mut().iter_mut() {
            let sub_active = dataflow.step();
            active = active || sub_active;
        }

        // discard completed dataflows.
        self.dataflows.borrow_mut().retain(|dataflow| dataflow.active());

        active
    }
    /// Calls `self.step()` as long as `func` evaluates to true.
    pub fn step_while<F: FnMut()->bool>(&mut self, mut func: F) {
        while func() { self.step(); }
    }

    /// The index of the worker out of its peers.
    pub fn index(&self) -> usize { self.allocator.borrow().index() }
    /// The total number of peer workers.
    pub fn peers(&self) -> usize { self.allocator.borrow().peers() }

    /// Introduces a new dataflow constructed in the supplied closure.
    ///
    /// NOTE: This is the same code as in the `scoped` method for scopes, but it has been extracted
    /// so that the `Root` type does not need to implement `Scope`.
    pub fn dataflow<T: Timestamp, R, F:FnOnce(&mut Child<Self, T>)->R>(&mut self, func: F) -> R {

        let addr = vec![self.allocator.borrow().index()];
        let dataflow_index = self.allocate_dataflow_index();
        let subscope = Subgraph::new_from(&mut (*self.allocator.borrow_mut()), dataflow_index, addr);
        let subscope = RefCell::new(subscope);

        let result = {
            let mut builder = Child {
                subgraph: &subscope,
                parent: self.clone(),
            };
            func(&mut builder)
        };

        let mut operator = subscope.into_inner();

        operator.get_internal_summary();
        operator.set_external_summary(Vec::new(), &mut []);

        let wrapper = Wrapper {
            index: dataflow_index,
            operate: Some(Box::new(operator)),
            resources: None,
        };
        self.dataflows.borrow_mut().push(wrapper);

        result
    }

    /// Manually construct a dataflow.
    pub fn construct_dataflow<O: Operate<RootTimestamp>+'static, F: FnOnce(usize)->O>(&mut self, func: F) {
        let index = self.allocate_dataflow_index();
        let mut operator = func(index);

        // prepare progress tracking for operator.
        operator.get_internal_summary();
        operator.set_external_summary(Vec::new(), &mut []);

        let wrapper = Wrapper {
            index: index,
            operate: Some(Box::new(operator)),
            resources: None,
        };
        self.dataflows.borrow_mut().push(wrapper);
    }

    // sane way to get new dataflow identifiers; used to be self.dataflows.len(). =/
    fn allocate_dataflow_index(&mut self) -> usize {
        *self.dataflow_counter.borrow_mut() += 1;
        *self.dataflow_counter.borrow() - 1
    }
}

impl<A: Allocate> ScopeParent for Root<A> {
    type Timestamp = RootTimestamp;

    fn new_identifier(&mut self) -> usize {
        *self.identifiers.borrow_mut() += 1;
        *self.identifiers.borrow() - 1
    }
}

impl<A: Allocate> Allocate for Root<A> {
    fn index(&self) -> usize { self.allocator.borrow().index() }
    fn peers(&self) -> usize { self.allocator.borrow().peers() }
    fn allocate<D: Data>(&mut self) -> (Vec<Box<Push<D>>>, Box<Pull<D>>) {
        self.allocator.borrow_mut().allocate()
    }
}

impl<A: Allocate> Clone for Root<A> {
    fn clone(&self) -> Self {
        Root {
            allocator: self.allocator.clone(),
            identifiers: self.identifiers.clone(),
            dataflows: self.dataflows.clone(),
            dataflow_counter: self.dataflow_counter.clone(),
        }
    }
}

struct Wrapper {
    index: usize,
    operate: Option<Box<Operate<RootTimestamp>>>,
    resources: Option<Box<Drop>>,
}

impl Wrapper {
    fn step(&mut self) -> bool {
        self.operate.as_mut().map(|op| op.pull_internal_progress(&mut [], &mut [], &mut [])).unwrap_or(false)
    }
    fn active(&self) -> bool { self.operate.is_some() }
}

impl Drop for Wrapper {
    fn drop(&mut self) {
        // println!("dropping dataflow {:?}", self.index);
        // ensure drop order
        self.operate = None;
        self.resources = None;
    }
}
<commit_msg>added dataflow_using for shared library needs<commit_after>//! The root scope of all timely dataflow computations.

use std::rc::Rc;
use std::cell::RefCell;
use std::any::Any;

use progress::timestamp::RootTimestamp;
use progress::{Timestamp, Operate, Subgraph};
use timely_communication::{Allocate, Data};
use {Push, Pull};

use super::{ScopeParent, Child};

/// A `Root` is the entry point to a timely dataflow computation. It wraps a `Allocate`,
/// and has a list of child `Operate`s.
pub struct Root<A: Allocate> {
    allocator: Rc<RefCell<A>>,
    identifiers: Rc<RefCell<usize>>,
    dataflows: Rc<RefCell<Vec<Wrapper>>>,
    dataflow_counter: Rc<RefCell<usize>>,
}

impl<A: Allocate> Root<A> {
    /// Allocates a new `Root` bound to a channel allocator.
    pub fn new(c: A) -> Root<A> {
        let mut result = Root {
            allocator: Rc::new(RefCell::new(c)),
            identifiers: Rc::new(RefCell::new(0)),
            dataflows: Rc::new(RefCell::new(Vec::new())),
            dataflow_counter: Rc::new(RefCell::new(0)),
        };

        // LOGGING
        if cfg!(feature = "logging") {
            ::logging::initialize(&mut result);
        }

        result
    }

    /// Performs one step of the computation.
    ///
    /// A step gives each dataflow operator a chance to run, and is the
    /// main way to ensure that a computation procedes.
    pub fn step(&mut self) -> bool {

        if cfg!(feature = "logging") {
            ::logging::flush_logs();
        }

        let mut active = false;
        for dataflow in self.dataflows.borrow_mut().iter_mut() {
            let sub_active = dataflow.step();
            active = active || sub_active;
        }

        // discard completed dataflows.
        self.dataflows.borrow_mut().retain(|dataflow| dataflow.active());

        active
    }
    /// Calls `self.step()` as long as `func` evaluates to true.
    pub fn step_while<F: FnMut()->bool>(&mut self, mut func: F) {
        while func() { self.step(); }
    }

    /// The index of the worker out of its peers.
    pub fn index(&self) -> usize { self.allocator.borrow().index() }
    /// The total number of peer workers.
    pub fn peers(&self) -> usize { self.allocator.borrow().peers() }

    /// Construct a new dataflow.
    pub fn dataflow<T: Timestamp, R, F:FnOnce(&mut Child<Self, T>)->R>(&mut self, func: F) -> R {
        self.dataflow_using(Box::new(()), |_, child| func(child))
    }

    /// Construct a new dataflow binding resources that are released only after the dataflow is dropped.
    ///
    /// This method is designed to allow the dataflow builder to use certain resources that are then stashed
    /// with the dataflow until it has completed running. Once complete, the resources are dropped. The most
    /// common use of this method at present is with loading shared libraries, where the library is important
    /// for building the dataflow, and must be kept around until after the dataflow has completed operation.
    pub fn dataflow_using<T: Timestamp, R, F:FnOnce(&mut V, &mut Child<Self, T>)->R, V: Any+'static>(&mut self, mut resources: V, func: F) -> R {

        let addr = vec![self.allocator.borrow().index()];
        let dataflow_index = self.allocate_dataflow_index();
        let subscope = Subgraph::new_from(&mut (*self.allocator.borrow_mut()), dataflow_index, addr);
        let subscope = RefCell::new(subscope);

        let result = {
            let mut builder = Child {
                subgraph: &subscope,
                parent: self.clone(),
            };
            func(&mut resources, &mut builder)
        };

        let mut operator = subscope.into_inner();

        operator.get_internal_summary();
        operator.set_external_summary(Vec::new(), &mut []);

        let wrapper = Wrapper {
            index: dataflow_index,
            operate: Some(Box::new(operator)),
            resources: Some(Box::new(resources)),
        };
        self.dataflows.borrow_mut().push(wrapper);

        result

    }

    // sane way to get new dataflow identifiers; used to be self.dataflows.len(). =/
    fn allocate_dataflow_index(&mut self) -> usize {
        *self.dataflow_counter.borrow_mut() += 1;
        *self.dataflow_counter.borrow() - 1
    }
}

impl<A: Allocate> ScopeParent for Root<A> {
    type Timestamp = RootTimestamp;

    fn new_identifier(&mut self) -> usize {
        *self.identifiers.borrow_mut() += 1;
        *self.identifiers.borrow() - 1
    }
}

impl<A: Allocate> Allocate for Root<A> {
    fn index(&self) -> usize { self.allocator.borrow().index() }
    fn peers(&self) -> usize { self.allocator.borrow().peers() }
    fn allocate<D: Data>(&mut self) -> (Vec<Box<Push<D>>>, Box<Pull<D>>) {
        self.allocator.borrow_mut().allocate()
    }
}

impl<A: Allocate> Clone for Root<A> {
    fn clone(&self) -> Self {
        Root {
            allocator: self.allocator.clone(),
            identifiers: self.identifiers.clone(),
            dataflows: self.dataflows.clone(),
            dataflow_counter: self.dataflow_counter.clone(),
        }
    }
}

struct Wrapper {
    index: usize,
    operate: Option<Box<Operate<RootTimestamp>>>,
    resources: Option<Box<Any>>,
}

impl Wrapper {
    fn step(&mut self) -> bool {
        self.operate.as_mut().map(|op| op.pull_internal_progress(&mut [], &mut [], &mut [])).unwrap_or(false)
    }
    fn active(&self) -> bool { self.operate.is_some() }
}

impl Drop for Wrapper {
    fn drop(&mut self) {
        // println!("dropping dataflow {:?}", self.index);
        // ensure drop order
        self.operate = None;
        self.resources = None;
    }
}
<|endoftext|>


<commit_before>use ll::stylesheet::css_fixed;
use core::libc::c_void;

pub fn css_fixed_to_float(f: css_fixed) -> float {
    const before: i32 = 10;
    f as float * 1.0f / ((1i32 << before) as float)
}

// FIXME: These methods should be unsafe
pub trait VoidPtrLike {
    static fn from_void_ptr(*c_void) -> self;
    fn to_void_ptr(&self) -> *c_void;
}<commit_msg>Absorb some string conversions from rust-css<commit_after>use ll::stylesheet::css_fixed;
use types::CssQName;
use core::libc::c_void;
use lwcstr_from_rust_str = wapcaplet::from_rust_string;

pub fn css_fixed_to_float(f: css_fixed) -> float {
    const before: i32 = 10;
    f as float * 1.0f / ((1i32 << before) as float)
}

pub fn rust_str_to_net_qname(s: &str) -> CssQName {
    CssQName {
        ns: None,
        name: lwcstr_from_rust_str(s)
    }
}

pub fn net_qname_to_rust_str(qname: &CssQName) -> ~str {
    qname.name.to_str()
}

// FIXME: These methods should be unsafe
pub trait VoidPtrLike {
    static fn from_void_ptr(*c_void) -> self;
    fn to_void_ptr(&self) -> *c_void;
}<|endoftext|>


<commit_before>/// Benchmarks game nbody code
/// Taken from the `packed_simd` crate
/// Run this benchmark with `cargo test --example nbody`
use core_simd::*;

use std::f64::consts::PI;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const DAYS_PER_YEAR: f64 = 365.24;

#[derive(Debug, Clone, Copy)]
pub struct Body {
    pub x: f64x4,
    pub v: f64x4,
    pub mass: f64,
}

const N_BODIES: usize = 5;
const BODIES: [Body; N_BODIES] = [
    // sun:
    Body {
        x: f64x4::from_array([0., 0., 0., 0.]),
        v: f64x4::from_array([0., 0., 0., 0.]),
        mass: SOLAR_MASS,
    },
    // jupiter:
    Body {
        x: f64x4::from_array([
            4.84143144246472090e+00,
            -1.16032004402742839e+00,
            -1.03622044471123109e-01,
            0.,
        ]),
        v: f64x4::from_array([
            1.66007664274403694e-03 * DAYS_PER_YEAR,
            7.69901118419740425e-03 * DAYS_PER_YEAR,
            -6.90460016972063023e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // saturn:
    Body {
        x: f64x4::from_array([
            8.34336671824457987e+00,
            4.12479856412430479e+00,
            -4.03523417114321381e-01,
            0.,
        ]),
        v: f64x4::from_array([
            -2.76742510726862411e-03 * DAYS_PER_YEAR,
            4.99852801234917238e-03 * DAYS_PER_YEAR,
            2.30417297573763929e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // uranus:
    Body {
        x: f64x4::from_array([
            1.28943695621391310e+01,
            -1.51111514016986312e+01,
            -2.23307578892655734e-01,
            0.,
        ]),
        v: f64x4::from_array([
            2.96460137564761618e-03 * DAYS_PER_YEAR,
            2.37847173959480950e-03 * DAYS_PER_YEAR,
            -2.96589568540237556e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // neptune:
    Body {
        x: f64x4::from_array([
            1.53796971148509165e+01,
            -2.59193146099879641e+01,
            1.79258772950371181e-01,
            0.,
        ]),
        v: f64x4::from_array([
            2.68067772490389322e-03 * DAYS_PER_YEAR,
            1.62824170038242295e-03 * DAYS_PER_YEAR,
            -9.51592254519715870e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

pub fn offset_momentum(bodies: &mut [Body; N_BODIES]) {
    let (sun, rest) = bodies.split_at_mut(1);
    let sun = &mut sun[0];
    for body in rest {
        let m_ratio = body.mass / SOLAR_MASS;
        sun.v -= body.v * m_ratio;
    }
}

pub fn energy(bodies: &[Body; N_BODIES]) -> f64 {
    let mut e = 0.;
    for i in 0..N_BODIES {
        let bi = &bodies[i];
        e += bi.mass * (bi.v * bi.v).horizontal_sum() * 0.5;
        for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
            let dx = bi.x - bj.x;
            e -= bi.mass * bj.mass / (dx * dx).horizontal_sum().sqrt()
        }
    }
    e
}

pub fn advance(bodies: &mut [Body; N_BODIES], dt: f64) {
    const N: usize = N_BODIES * (N_BODIES - 1) / 2;

    // compute distance between bodies:
    let mut r = [f64x4::splat(0.); N];
    {
        let mut i = 0;
        for j in 0..N_BODIES {
            for k in j + 1..N_BODIES {
                r[i] = bodies[j].x - bodies[k].x;
                i += 1;
            }
        }
    }

    let mut mag = [0.0; N];
    let mut i = 0;
    while i < N {
        let d2s = f64x2::from_array([
            (r[i] * r[i]).horizontal_sum(),
            (r[i + 1] * r[i + 1]).horizontal_sum(),
        ]);
        let dmags = f64x2::splat(dt) / (d2s * d2s.sqrt());
        mag[i] = dmags[0];
        mag[i + 1] = dmags[1];
        i += 2;
    }

    i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            let f = r[i] * mag[i];
            bodies[j].v -= f * bodies[k].mass;
            bodies[k].v += f * bodies[j].mass;
            i += 1
        }
    }
    for body in bodies {
        body.x += dt * body.v
    }
}

pub fn run(n: usize) -> (f64, f64) {
    let mut bodies = BODIES;
    offset_momentum(&mut bodies);
    let energy_before = energy(&bodies);
    for _ in 0..n {
        advance(&mut bodies, 0.01);
    }
    let energy_after = energy(&bodies);

    (energy_before, energy_after)
}

// Good enough for demonstration purposes, not going for strictness here.
fn approx_eq_f64(a: f64, b: f64) -> bool {
    (a - b).abs() < 0.00001
}

#[cfg(test)]
mod tests {
    #[test]
    fn test() {
        use super::*;
        const OUTPUT: [f64; 2] = [-0.169075164, -0.169087605];
        let (energy_before, energy_after) = super::run(1000);
        assert!(approx_eq_f64(energy_before, OUTPUT[0]));
        assert!(approx_eq_f64(energy_after, OUTPUT[1]));
    }
}

fn main () {
    // empty main to pass CI
}
<commit_msg>clean code vis. Jubilee's comments<commit_after>/// Benchmarks game nbody code
/// Taken from the `packed_simd` crate
/// Run this benchmark with `cargo test --example nbody`
use core_simd::*;

use std::f64::consts::PI;
const SOLAR_MASS: f64 = 4.0 * PI * PI;
const DAYS_PER_YEAR: f64 = 365.24;

#[derive(Debug, Clone, Copy)]
pub struct Body {
    pub x: f64x4,
    pub v: f64x4,
    pub mass: f64,
}

const N_BODIES: usize = 5;
const BODIES: [Body; N_BODIES] = [
    // sun:
    Body {
        x: f64x4::from_array([0., 0., 0., 0.]),
        v: f64x4::from_array([0., 0., 0., 0.]),
        mass: SOLAR_MASS,
    },
    // jupiter:
    Body {
        x: f64x4::from_array([
            4.84143144246472090e+00,
            -1.16032004402742839e+00,
            -1.03622044471123109e-01,
            0.,
        ]),
        v: f64x4::from_array([
            1.66007664274403694e-03 * DAYS_PER_YEAR,
            7.69901118419740425e-03 * DAYS_PER_YEAR,
            -6.90460016972063023e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 9.54791938424326609e-04 * SOLAR_MASS,
    },
    // saturn:
    Body {
        x: f64x4::from_array([
            8.34336671824457987e+00,
            4.12479856412430479e+00,
            -4.03523417114321381e-01,
            0.,
        ]),
        v: f64x4::from_array([
            -2.76742510726862411e-03 * DAYS_PER_YEAR,
            4.99852801234917238e-03 * DAYS_PER_YEAR,
            2.30417297573763929e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 2.85885980666130812e-04 * SOLAR_MASS,
    },
    // uranus:
    Body {
        x: f64x4::from_array([
            1.28943695621391310e+01,
            -1.51111514016986312e+01,
            -2.23307578892655734e-01,
            0.,
        ]),
        v: f64x4::from_array([
            2.96460137564761618e-03 * DAYS_PER_YEAR,
            2.37847173959480950e-03 * DAYS_PER_YEAR,
            -2.96589568540237556e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 4.36624404335156298e-05 * SOLAR_MASS,
    },
    // neptune:
    Body {
        x: f64x4::from_array([
            1.53796971148509165e+01,
            -2.59193146099879641e+01,
            1.79258772950371181e-01,
            0.,
        ]),
        v: f64x4::from_array([
            2.68067772490389322e-03 * DAYS_PER_YEAR,
            1.62824170038242295e-03 * DAYS_PER_YEAR,
            -9.51592254519715870e-05 * DAYS_PER_YEAR,
            0.,
        ]),
        mass: 5.15138902046611451e-05 * SOLAR_MASS,
    },
];

pub fn offset_momentum(bodies: &mut [Body; N_BODIES]) {
    let (sun, rest) = bodies.split_at_mut(1);
    let sun = &mut sun[0];
    for body in rest {
        let m_ratio = body.mass / SOLAR_MASS;
        sun.v -= body.v * m_ratio;
    }
}

pub fn energy(bodies: &[Body; N_BODIES]) -> f64 {
    let mut e = 0.;
    for i in 0..N_BODIES {
        let bi = &bodies[i];
        e += bi.mass * (bi.v * bi.v).horizontal_sum() * 0.5;
        for bj in bodies.iter().take(N_BODIES).skip(i + 1) {
            let dx = bi.x - bj.x;
            e -= bi.mass * bj.mass / (dx * dx).horizontal_sum().sqrt()
        }
    }
    e
}

pub fn advance(bodies: &mut [Body; N_BODIES], dt: f64) {
    const N: usize = N_BODIES * (N_BODIES - 1) / 2;

    // compute distance between bodies:
    let mut r = [f64x4::splat(0.); N];
    {
        let mut i = 0;
        for j in 0..N_BODIES {
            for k in j + 1..N_BODIES {
                r[i] = bodies[j].x - bodies[k].x;
                i += 1;
            }
        }
    }

    let mut mag = [0.0; N];
    for i in (0..N).step_by(2) {
        let d2s = f64x2::from_array([
            (r[i] * r[i]).horizontal_sum(),
            (r[i + 1] * r[i + 1]).horizontal_sum(),
        ]);
        let dmags = f64x2::splat(dt) / (d2s * d2s.sqrt());
        mag[i] = dmags[0];
        mag[i + 1] = dmags[1];
    }

    let mut i = 0;
    for j in 0..N_BODIES {
        for k in j + 1..N_BODIES {
            let f = r[i] * mag[i];
            bodies[j].v -= f * bodies[k].mass;
            bodies[k].v += f * bodies[j].mass;
            i += 1
        }
    }
    for body in bodies {
        body.x += dt * body.v
    }
}

pub fn run(n: usize) -> (f64, f64) {
    let mut bodies = BODIES;
    offset_momentum(&mut bodies);
    let energy_before = energy(&bodies);
    for _ in 0..n {
        advance(&mut bodies, 0.01);
    }
    let energy_after = energy(&bodies);

    (energy_before, energy_after)
}

#[cfg(test)]
mod tests {
    // Good enough for demonstration purposes, not going for strictness here.
    fn approx_eq_f64(a: f64, b: f64) -> bool {
        (a - b).abs() < 0.00001
    }
    #[test]
    fn test() {
        const OUTPUT: [f64; 2] = [-0.169075164, -0.169087605];
        let (energy_before, energy_after) = super::run(1000);
        assert!(approx_eq_f64(energy_before, OUTPUT[0]));
        assert!(approx_eq_f64(energy_after, OUTPUT[1]));
    }
}

fn main() {
    // empty main to pass CI
}
<|endoftext|>


<commit_before>/// Lookup hir elements using positions in the source code. This is a lossy
/// transformation: in general, a single source might correspond to several
/// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on
/// modules.
///
/// So, this modules should not be used during hir construction, it exists
/// purely for "IDE needs".
use std::sync::Arc;

use ra_db::{FileId, FilePosition};
use ra_syntax::{
    SyntaxNode, AstPtr, TextUnit,
    ast::{self, AstNode, NameOwner},
    algo::find_node_at_offset,
};

use crate::{
    HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody,
    AsName, Module, HirFileId, Crate, Trait, Resolver,
    ids::LocationCtx,
    expr, AstId
};

/// Locates the module by `FileId`. Picks topmost module in the file.
pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> {
    module_from_source(db, file_id.into(), None)
}

/// Locates the child module by `mod child;` declaration.
pub fn module_from_declaration(
    db: &impl HirDatabase,
    file_id: FileId,
    decl: &ast::Module,
) -> Option<Module> {
    let parent_module = module_from_file_id(db, file_id);
    let child_name = decl.name();
    match (parent_module, child_name) {
        (Some(parent_module), Some(child_name)) => parent_module.child(db, &child_name.as_name()),
        _ => None,
    }
}

/// Locates the module by position in the source code.
pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> {
    let file = db.parse(position.file_id);
    match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
        Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m),
        _ => module_from_file_id(db, position.file_id.into()),
    }
}

fn module_from_inline(
    db: &impl HirDatabase,
    file_id: FileId,
    module: &ast::Module,
) -> Option<Module> {
    assert!(!module.has_semi());
    let file_id = file_id.into();
    let ast_id_map = db.ast_id_map(file_id);
    let item_id = ast_id_map.ast_id(module).with_file_id(file_id);
    module_from_source(db, file_id, Some(item_id))
}

/// Locates the module by child syntax element within the module
pub fn module_from_child_node(
    db: &impl HirDatabase,
    file_id: FileId,
    child: &SyntaxNode,
) -> Option<Module> {
    if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
        module_from_inline(db, file_id.into(), m)
    } else {
        module_from_file_id(db, file_id.into())
    }
}

fn module_from_source(
    db: &impl HirDatabase,
    file_id: HirFileId,
    decl_id: Option<AstId<ast::Module>>,
) -> Option<Module> {
    let source_root_id = db.file_source_root(file_id.as_original_file());
    db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
        |krate| {
            let def_map = db.crate_def_map(krate);
            let module_id = def_map.find_module_by_source(file_id, decl_id)?;
            Some(Module { krate, module_id })
        },
    )
}

pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
    let file = db.parse(position.file_id);
    let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
    function_from_source(db, position.file_id, fn_def)
}

pub fn function_from_source(
    db: &impl HirDatabase,
    file_id: FileId,
    fn_def: &ast::FnDef,
) -> Option<Function> {
    let module = module_from_child_node(db, file_id, fn_def.syntax())?;
    let res = function_from_module(db, module, fn_def);
    Some(res)
}

pub fn function_from_module(
    db: &impl HirDatabase,
    module: Module,
    fn_def: &ast::FnDef,
) -> Function {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Function { id: ctx.to_def(fn_def) }
}

pub fn function_from_child_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
) -> Option<Function> {
    let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
    function_from_source(db, file_id, fn_def)
}

pub fn struct_from_module(
    db: &impl HirDatabase,
    module: Module,
    struct_def: &ast::StructDef,
) -> Struct {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Struct { id: ctx.to_def(struct_def) }
}

pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Enum { id: ctx.to_def(enum_def) }
}

pub fn trait_from_module(
    db: &impl HirDatabase,
    module: Module,
    trait_def: &ast::TraitDef,
) -> Trait {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Trait { id: ctx.to_def(trait_def) }
}

fn resolver_for_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
    offset: Option<TextUnit>,
) -> Resolver {
    node.ancestors()
        .find_map(|node| {
            if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
                if let Some(func) = function_from_child_node(db, file_id, node) {
                    let scopes = func.scopes(db);
                    let scope = match offset {
                        None => scopes.scope_for(&node),
                        Some(offset) => scopes.scope_for_offset(offset),
                    };
                    Some(expr::resolver_for_scope(func.body(db), db, scope))
                } else {
                    // FIXME const/static/array length
                    None
                }
            } else {
                try_get_resolver_for_node(db, file_id, node)
            }
        })
        .unwrap_or_default()
}

fn try_get_resolver_for_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
) -> Option<Resolver> {
    if let Some(module) = ast::Module::cast(node) {
        Some(module_from_declaration(db, file_id, module)?.resolver(db))
    } else if let Some(_) = ast::SourceFile::cast(node) {
        Some(module_from_source(db, file_id.into(), None)?.resolver(db))
    } else if let Some(s) = ast::StructDef::cast(node) {
        let module = module_from_child_node(db, file_id, s.syntax())?;
        Some(struct_from_module(db, module, s).resolver(db))
    } else if let Some(e) = ast::EnumDef::cast(node) {
        let module = module_from_child_node(db, file_id, e.syntax())?;
        Some(enum_from_module(db, module, e).resolver(db))
    } else if let Some(f) = ast::FnDef::cast(node) {
        function_from_source(db, file_id, f).map(|f| f.resolver(db))
    } else {
        // FIXME add missing cases
        None
    }
}

pub fn def_with_body_from_child_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
) -> Option<DefWithBody> {
    let module = module_from_child_node(db, file_id, node)?;
    let ctx = LocationCtx::new(db, module, file_id.into());
    node.ancestors().find_map(|node| {
        if let Some(def) = ast::FnDef::cast(node) {
            return Some(Function { id: ctx.to_def(def) }.into());
        }
        if let Some(def) = ast::ConstDef::cast(node) {
            return Some(Const { id: ctx.to_def(def) }.into());
        }
        if let Some(def) = ast::StaticDef::cast(node) {
            return Some(Static { id: ctx.to_def(def) }.into());
        }
        None
    })
}

/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
/// original source files. It should not be used inside the HIR itself.
#[derive(Debug)]
pub struct SourceAnalyzer {
    resolver: Resolver,
    body_source_map: Option<Arc<crate::expr::BodySourceMap>>,
    infer: Option<Arc<crate::ty::InferenceResult>>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathResolution {
    /// An item
    Def(crate::ModuleDef),
    /// A local binding (only value namespace)
    LocalBinding(Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>),
    /// A generic parameter
    GenericParam(u32),
    SelfType(crate::ImplBlock),
    AssocItem(crate::ImplItem),
}

impl SourceAnalyzer {
    pub fn new(
        db: &impl HirDatabase,
        file_id: FileId,
        node: &SyntaxNode,
        offset: Option<TextUnit>,
    ) -> SourceAnalyzer {
        let def_with_body = def_with_body_from_child_node(db, file_id, node);
        SourceAnalyzer {
            resolver: resolver_for_node(db, file_id, node, offset),
            body_source_map: def_with_body.map(|it| it.body_source_map(db)),
            infer: def_with_body.map(|it| it.infer(db)),
        }
    }

    pub fn resolver(&self) -> &Resolver {
        &self.resolver
    }

    pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> {
        let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?;
        Some(self.infer.as_ref()?[expr_id].clone())
    }

    pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> {
        let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?;
        Some(self.infer.as_ref()?[pat_id].clone())
    }

    pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
        let expr_id = self.body_source_map.as_ref()?.node_expr(call.into())?;
        self.infer.as_ref()?.method_resolution(expr_id)
    }

    pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
        let expr_id = self.body_source_map.as_ref()?.node_expr(field.into())?;
        self.infer.as_ref()?.field_resolution(expr_id)
    }

    pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
        if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
            let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?;
            if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
                return Some(PathResolution::AssocItem(assoc));
            }
        }
        if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
            let pat_id = self.body_source_map.as_ref()?.node_pat(path_pat.into())?;
            if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
                return Some(PathResolution::AssocItem(assoc));
            }
        }
        let hir_path = crate::Path::from_ast(path)?;
        let res = self.resolver.resolve_path(db, &hir_path);
        let res = res.clone().take_types().or_else(|| res.take_values())?;
        let res = match res {
            crate::Resolution::Def(it) => PathResolution::Def(it),
            crate::Resolution::LocalBinding(it) => {
                PathResolution::LocalBinding(self.body_source_map.as_ref()?.pat_syntax(it)?)
            }
            crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),
            crate::Resolution::SelfType(it) => PathResolution::SelfType(it),
        };
        Some(res)
    }

    #[cfg(test)]
    pub(crate) fn body_source_map(&self) -> Arc<crate::expr::BodySourceMap> {
        self.body_source_map.clone().unwrap()
    }

    #[cfg(test)]
    pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
        self.infer.clone().unwrap()
    }
}
<commit_msg>make stuff private<commit_after>/// Lookup hir elements using positions in the source code. This is a lossy
/// transformation: in general, a single source might correspond to several
/// modules, functions, etc, due to macros, cfgs and `#[path=]` attributes on
/// modules.
///
/// So, this modules should not be used during hir construction, it exists
/// purely for "IDE needs".
use std::sync::Arc;

use ra_db::{FileId, FilePosition};
use ra_syntax::{
    SyntaxNode, AstPtr, TextUnit,
    ast::{self, AstNode, NameOwner},
    algo::find_node_at_offset,
};

use crate::{
    HirDatabase, Function, Struct, Enum, Const, Static, Either, DefWithBody,
    AsName, Module, HirFileId, Crate, Trait, Resolver,
    ids::LocationCtx,
    expr, AstId
};

/// Locates the module by `FileId`. Picks topmost module in the file.
pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> {
    module_from_source(db, file_id.into(), None)
}

/// Locates the child module by `mod child;` declaration.
pub fn module_from_declaration(
    db: &impl HirDatabase,
    file_id: FileId,
    decl: &ast::Module,
) -> Option<Module> {
    let parent_module = module_from_file_id(db, file_id);
    let child_name = decl.name();
    match (parent_module, child_name) {
        (Some(parent_module), Some(child_name)) => parent_module.child(db, &child_name.as_name()),
        _ => None,
    }
}

/// Locates the module by position in the source code.
pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> {
    let file = db.parse(position.file_id);
    match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
        Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m),
        _ => module_from_file_id(db, position.file_id.into()),
    }
}

fn module_from_inline(
    db: &impl HirDatabase,
    file_id: FileId,
    module: &ast::Module,
) -> Option<Module> {
    assert!(!module.has_semi());
    let file_id = file_id.into();
    let ast_id_map = db.ast_id_map(file_id);
    let item_id = ast_id_map.ast_id(module).with_file_id(file_id);
    module_from_source(db, file_id, Some(item_id))
}

/// Locates the module by child syntax element within the module
pub fn module_from_child_node(
    db: &impl HirDatabase,
    file_id: FileId,
    child: &SyntaxNode,
) -> Option<Module> {
    if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
        module_from_inline(db, file_id.into(), m)
    } else {
        module_from_file_id(db, file_id.into())
    }
}

fn module_from_source(
    db: &impl HirDatabase,
    file_id: HirFileId,
    decl_id: Option<AstId<ast::Module>>,
) -> Option<Module> {
    let source_root_id = db.file_source_root(file_id.as_original_file());
    db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
        |krate| {
            let def_map = db.crate_def_map(krate);
            let module_id = def_map.find_module_by_source(file_id, decl_id)?;
            Some(Module { krate, module_id })
        },
    )
}

pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> {
    let file = db.parse(position.file_id);
    let fn_def = find_node_at_offset::<ast::FnDef>(file.syntax(), position.offset)?;
    function_from_source(db, position.file_id, fn_def)
}

fn function_from_source(
    db: &impl HirDatabase,
    file_id: FileId,
    fn_def: &ast::FnDef,
) -> Option<Function> {
    let module = module_from_child_node(db, file_id, fn_def.syntax())?;
    let res = function_from_module(db, module, fn_def);
    Some(res)
}

fn function_from_module(db: &impl HirDatabase, module: Module, fn_def: &ast::FnDef) -> Function {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Function { id: ctx.to_def(fn_def) }
}

pub fn function_from_child_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
) -> Option<Function> {
    let fn_def = node.ancestors().find_map(ast::FnDef::cast)?;
    function_from_source(db, file_id, fn_def)
}

pub fn struct_from_module(
    db: &impl HirDatabase,
    module: Module,
    struct_def: &ast::StructDef,
) -> Struct {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Struct { id: ctx.to_def(struct_def) }
}

pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Enum { id: ctx.to_def(enum_def) }
}

pub fn trait_from_module(
    db: &impl HirDatabase,
    module: Module,
    trait_def: &ast::TraitDef,
) -> Trait {
    let (file_id, _) = module.definition_source(db);
    let file_id = file_id.into();
    let ctx = LocationCtx::new(db, module, file_id);
    Trait { id: ctx.to_def(trait_def) }
}

fn resolver_for_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
    offset: Option<TextUnit>,
) -> Resolver {
    node.ancestors()
        .find_map(|node| {
            if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() {
                if let Some(func) = function_from_child_node(db, file_id, node) {
                    let scopes = func.scopes(db);
                    let scope = match offset {
                        None => scopes.scope_for(&node),
                        Some(offset) => scopes.scope_for_offset(offset),
                    };
                    Some(expr::resolver_for_scope(func.body(db), db, scope))
                } else {
                    // FIXME const/static/array length
                    None
                }
            } else {
                try_get_resolver_for_node(db, file_id, node)
            }
        })
        .unwrap_or_default()
}

fn try_get_resolver_for_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
) -> Option<Resolver> {
    if let Some(module) = ast::Module::cast(node) {
        Some(module_from_declaration(db, file_id, module)?.resolver(db))
    } else if let Some(_) = ast::SourceFile::cast(node) {
        Some(module_from_source(db, file_id.into(), None)?.resolver(db))
    } else if let Some(s) = ast::StructDef::cast(node) {
        let module = module_from_child_node(db, file_id, s.syntax())?;
        Some(struct_from_module(db, module, s).resolver(db))
    } else if let Some(e) = ast::EnumDef::cast(node) {
        let module = module_from_child_node(db, file_id, e.syntax())?;
        Some(enum_from_module(db, module, e).resolver(db))
    } else if let Some(f) = ast::FnDef::cast(node) {
        function_from_source(db, file_id, f).map(|f| f.resolver(db))
    } else {
        // FIXME add missing cases
        None
    }
}

pub fn def_with_body_from_child_node(
    db: &impl HirDatabase,
    file_id: FileId,
    node: &SyntaxNode,
) -> Option<DefWithBody> {
    let module = module_from_child_node(db, file_id, node)?;
    let ctx = LocationCtx::new(db, module, file_id.into());
    node.ancestors().find_map(|node| {
        if let Some(def) = ast::FnDef::cast(node) {
            return Some(Function { id: ctx.to_def(def) }.into());
        }
        if let Some(def) = ast::ConstDef::cast(node) {
            return Some(Const { id: ctx.to_def(def) }.into());
        }
        if let Some(def) = ast::StaticDef::cast(node) {
            return Some(Static { id: ctx.to_def(def) }.into());
        }
        None
    })
}

/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
/// original source files. It should not be used inside the HIR itself.
#[derive(Debug)]
pub struct SourceAnalyzer {
    resolver: Resolver,
    body_source_map: Option<Arc<crate::expr::BodySourceMap>>,
    infer: Option<Arc<crate::ty::InferenceResult>>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PathResolution {
    /// An item
    Def(crate::ModuleDef),
    /// A local binding (only value namespace)
    LocalBinding(Either<AstPtr<ast::Pat>, AstPtr<ast::SelfParam>>),
    /// A generic parameter
    GenericParam(u32),
    SelfType(crate::ImplBlock),
    AssocItem(crate::ImplItem),
}

impl SourceAnalyzer {
    pub fn new(
        db: &impl HirDatabase,
        file_id: FileId,
        node: &SyntaxNode,
        offset: Option<TextUnit>,
    ) -> SourceAnalyzer {
        let def_with_body = def_with_body_from_child_node(db, file_id, node);
        SourceAnalyzer {
            resolver: resolver_for_node(db, file_id, node, offset),
            body_source_map: def_with_body.map(|it| it.body_source_map(db)),
            infer: def_with_body.map(|it| it.infer(db)),
        }
    }

    pub fn resolver(&self) -> &Resolver {
        &self.resolver
    }

    pub fn type_of(&self, _db: &impl HirDatabase, expr: &ast::Expr) -> Option<crate::Ty> {
        let expr_id = self.body_source_map.as_ref()?.node_expr(expr)?;
        Some(self.infer.as_ref()?[expr_id].clone())
    }

    pub fn type_of_pat(&self, _db: &impl HirDatabase, pat: &ast::Pat) -> Option<crate::Ty> {
        let pat_id = self.body_source_map.as_ref()?.node_pat(pat)?;
        Some(self.infer.as_ref()?[pat_id].clone())
    }

    pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
        let expr_id = self.body_source_map.as_ref()?.node_expr(call.into())?;
        self.infer.as_ref()?.method_resolution(expr_id)
    }

    pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<crate::StructField> {
        let expr_id = self.body_source_map.as_ref()?.node_expr(field.into())?;
        self.infer.as_ref()?.field_resolution(expr_id)
    }

    pub fn resolve_path(&self, db: &impl HirDatabase, path: &ast::Path) -> Option<PathResolution> {
        if let Some(path_expr) = path.syntax().parent().and_then(ast::PathExpr::cast) {
            let expr_id = self.body_source_map.as_ref()?.node_expr(path_expr.into())?;
            if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_expr(expr_id) {
                return Some(PathResolution::AssocItem(assoc));
            }
        }
        if let Some(path_pat) = path.syntax().parent().and_then(ast::PathPat::cast) {
            let pat_id = self.body_source_map.as_ref()?.node_pat(path_pat.into())?;
            if let Some(assoc) = self.infer.as_ref()?.assoc_resolutions_for_pat(pat_id) {
                return Some(PathResolution::AssocItem(assoc));
            }
        }
        let hir_path = crate::Path::from_ast(path)?;
        let res = self.resolver.resolve_path(db, &hir_path);
        let res = res.clone().take_types().or_else(|| res.take_values())?;
        let res = match res {
            crate::Resolution::Def(it) => PathResolution::Def(it),
            crate::Resolution::LocalBinding(it) => {
                PathResolution::LocalBinding(self.body_source_map.as_ref()?.pat_syntax(it)?)
            }
            crate::Resolution::GenericParam(it) => PathResolution::GenericParam(it),
            crate::Resolution::SelfType(it) => PathResolution::SelfType(it),
        };
        Some(res)
    }

    #[cfg(test)]
    pub(crate) fn body_source_map(&self) -> Arc<crate::expr::BodySourceMap> {
        self.body_source_map.clone().unwrap()
    }

    #[cfg(test)]
    pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
        self.infer.clone().unwrap()
    }
}
<|endoftext|>


<commit_before>use crate::prelude::*;

static RANGE_MIN: f64 = 0.0;
static RANGE_MAX: f64 = 1.0;

#[derive(Default, AsAny)]
struct BarState {}

impl State for BarState {
    fn init(&mut self, _: &mut Registry, ctx: &mut Context) {
        ctx.child_from_index(0)
            .get_mut::<Constraint>("constraint")
            .set_width(0.1);
    }

    fn update(&mut self, _: &mut Registry, ctx: &mut Context<'_>) {
        let val = ctx.widget().clone_or_default::<f64>("val");
        let new_width: f64;

        if val == RANGE_MIN {
            new_width = 0.1;
        } else {
            let max_width = ctx.widget().get::<Rectangle>("bounds").width();
            if val == RANGE_MAX {
                new_width = max_width * 0.99;
            } else if val > RANGE_MIN && val < RANGE_MAX {
                new_width = max_width * val;
            } else {
                new_width = max_width * 0.99;
            }
        }
        ctx.child_from_index(0)
            .get_mut::<Constraint>("constraint")
            .set_width(new_width);
    }
}

widget!(
    /// The `ProgressBar` widget is used to indicating a finite progress
    /// (e.g. copying a file, downloading a video from the internet).
    /// A progress is visually represented as a horizontal bar which grows when the progress advances.
    /// The ProgressBar expects values between 0.0 and 1.0, whereas 0.0 means 0%, and 1.0 means 100%.
    /// Any value outside of this range cosidered as 100%.
    ///
    /// This example creates a ProgressBar with default values:
    /// ```rust
    /// ProgressBar::create().build(ctx)
    /// ```
    ///
    /// The next example creates a ProgressBar initialized with 25% progress:
    /// ```rust
    /// ProgressBar::create().val(0.25).build(ctx)
    /// ```
    ///
    /// The progress can be controlled by changing the value of the `val` property.
    /// (this code asssumes that you have a children with id "pgbar")
    /// ```rust
    /// ctx.child("pgbar").set::<f64>("val", amount);
    /// ```
    ProgressBar<BarState> {
        background: Brush,
        border_brush: Brush,
        border_radius: f64,
        border_width: Thickness,
        padding: Thickness,
        val: f64
    }
);

impl Template for ProgressBar {
    fn template(self, _: Entity, build_context: &mut BuildContext) -> Self {
        self.name("ProgressBar")
            .background("#000000")
            .border_brush("#BABABA")
            .border_radius(4.0)
            .border_width(1.0)
            .element("progress_bar")
            .height(34.0)
            .padding((2.0, 4.0, 2.0, 4.0))
            .child(
                Container::create()
                    .background("#EFD035")
                    .height(24.0)
                    .border_radius(1.0)
                    .width(0.0)
                    .build(build_context),
            )
            .val(0.0)
    }

    fn render_object(&self) -> Box<dyn RenderObject> {
        Box::new(RectangleRenderObject)
    }

    fn layout(&self) -> Box<dyn Layout> {
        Box::new(PaddingLayout::new())
    }
}
<commit_msg>Added comments to properties, logic moved to separate fn, added unit test<commit_after>use crate::prelude::*;

static RANGE_MIN: f64 = 0.0;
static RANGE_MAX: f64 = 1.0;
static ID_INDICATOR: &'static str = "PGBAR_INDICATOR";

#[derive(Default, AsAny)]
struct BarState {
    indicator: Entity
}

impl State for BarState {
    fn init(&mut self, _: &mut Registry, ctx: &mut Context) {
        self.indicator = ctx.entity_of_child(ID_INDICATOR).expect("BarState.init(): Child could not be found!");

        ctx.get_widget(self.indicator)
            .get_mut::<Constraint>("constraint")
            .set_width(0.1);
    }

    fn update(&mut self, _: &mut Registry, ctx: &mut Context<'_>) {
        let val = ctx.widget().clone_or_default::<f64>("val");
        let max_width = ctx.widget().get::<Rectangle>("bounds").width();
        let new_width = calculate_width(val, max_width);

        ctx.get_widget(self.indicator)
            .get_mut::<Constraint>("constraint")
            .set_width(new_width);
    }
}

fn calculate_width(curren_progress: f64, max_width: f64) -> f64 {
    if curren_progress == RANGE_MIN {
        return 0.01;
    } else {
        if curren_progress == RANGE_MAX {
            return max_width * 0.99;
        } else if curren_progress > RANGE_MIN && curren_progress < RANGE_MAX {
            return max_width * curren_progress;
        } else {
            return max_width * 0.99;
        }
    }
}

widget!(
    /// The `ProgressBar` widget is used to indicating a finite progress
    /// (e.g. copying a file, downloading a video from the internet).
    /// A progress is visually represented as a horizontal bar which grows when the progress advances.
    /// The ProgressBar expects values between 0.0 and 1.0, whereas 0.0 means 0%, and 1.0 means 100%.
    /// Any value outside of this range cosidered as 100%.
    ///
    /// This example creates a ProgressBar with default values:
    /// ```rust
    /// ProgressBar::create().build(ctx)
    /// ```
    ///
    /// The next example creates a ProgressBar initialized with 25% progress:
    /// ```rust
    /// ProgressBar::create().val(0.25).build(ctx)
    /// ```
    ///
    /// The progress can be controlled by changing the value of the `val` property.
    /// (this code assumes that you have a children with id "pgbar")
    /// ```rust
    /// ctx.child("pgbar").set::<f64>("val", amount);
    /// ```
    ProgressBar<BarState> {
        /// Sets or shares the background color property
        background: Brush,
        /// Sets or shares the border color property
        border_brush: Brush,
        /// Sets or shares the border radius property
        border_radius: f64,
        /// Sets or shares the border width property
        border_width: Thickness,
        /// Sets or shares the padding property
        padding: Thickness,
        /// Sets or shares the current progress property
        val: f64
    }
);

impl Template for ProgressBar {
    fn template(self, _: Entity, build_context: &mut BuildContext) -> Self {
        self.name("ProgressBar")
            .background("#000000")
            .border_brush("#BABABA")
            .border_radius(4.0)
            .border_width(1.0)
            .element("progress_bar")
            .height(34.0)
            .padding((2.0, 4.0, 2.0, 4.0))
            .child(
                Container::create()
                    .id(ID_INDICATOR)
                    .element("progress_bar_indicator")
                    .background("#EFD035")
                    .height(24.0)
                    .border_radius(1.0)
                    .width(0.0)
                    .build(build_context),
            )
            .val(0.0)
    }

    fn render_object(&self) -> Box<dyn RenderObject> {
        Box::new(RectangleRenderObject)
    }

    fn layout(&self) -> Box<dyn Layout> {
        Box::new(PaddingLayout::new())
    }
}

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

    #[test]
    fn test_calculate_width() {
        assert_eq!(0.01, calculate_width(0.0, 100.0));
        assert_eq!(50.0, calculate_width(0.5, 100.0));
        assert_eq!(99.0, calculate_width(1.0, 100.0));
        assert_eq!(99.0, calculate_width(1.23, 100.0));
        assert_eq!(99.0, calculate_width(-1.23, 100.0));
    }
}<|endoftext|>