Apply a variety of rustfmt suggestions

This commit is contained in:
Tad Hardesty 2018-10-21 14:15:09 -07:00
parent e7ce6f6136
commit 63fa595bfc
47 changed files with 1175 additions and 526 deletions

View file

@ -1,9 +1,9 @@
extern crate chrono;
extern crate git2;
use std::io::Write;
use std::fs::File;
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {

View file

@ -12,10 +12,10 @@ extern crate serde_json;
extern crate dreammaker as dm;
extern crate dmm_tools;
use std::fmt;
use std::collections::HashMap;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::fmt;
use std::path::Path;
use std::sync::atomic::{AtomicIsize, Ordering};
use structopt::StructOpt;
@ -62,9 +62,12 @@ impl Context {
let environment: &std::path::Path = match opt.environment {
Some(ref env) => env.as_ref(),
None => match dm::detect_environment_default() {
Ok(Some(found)) => { pathbuf = found; &pathbuf },
Ok(Some(found)) => {
pathbuf = found;
&pathbuf
}
_ => dm::DEFAULT_ENV.as_ref(),
}
},
};
println!("parsing {}", environment.display());
@ -243,7 +246,12 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) {
context.dm_context.set_print_severity(Some(severity));
context.procs = procs;
context.objtree(opt);
*context.exit_status.get_mut() = context.dm_context.errors().iter().filter(|e| e.severity() <= severity).count() as isize;
*context.exit_status.get_mut() = context
.dm_context
.errors()
.iter()
.filter(|e| e.severity() <= severity)
.count() as isize;
},
// --------------------------------------------------------------------
Command::Minimap {
@ -251,10 +259,23 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) {
pngcrush, optipng,
} => {
context.objtree(opt);
if context.dm_context.errors().iter().filter(|e| e.severity() <= dm::Severity::Error).next().is_some() {
if context
.dm_context
.errors()
.iter()
.filter(|e| e.severity() <= dm::Severity::Error)
.next()
.is_some()
{
println!("there were some parsing errors; render may be inaccurate")
}
let Context { ref objtree, ref icon_cache, ref exit_status, parallel, .. } = *context;
let Context {
ref objtree,
ref icon_cache,
ref exit_status,
parallel,
..
} = *context;
let render_passes = &dmm_tools::render_passes::configure(enable, disable);
let paths: Vec<&Path> = files.iter().map(|p| p.as_ref()).collect();
@ -281,7 +302,11 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) {
let (dim_x, dim_y, dim_z) = map.dim_xyz();
let mut min = min.unwrap_or(CoordArg { x: 0, y: 0, z: 0 });
let mut max = max.unwrap_or(CoordArg { x: dim_x + 1, y: dim_y + 1, z: dim_z + 1 });
let mut max = max.unwrap_or(CoordArg {
x: dim_x + 1,
y: dim_y + 1,
z: dim_z + 1,
});
min.x = clamp(min.x, 1, dim_x);
min.y = clamp(min.y, 1, dim_y);
min.z = clamp(min.z, 1, dim_z);
@ -306,7 +331,12 @@ fn run(opt: &Opt, command: &Command, context: &mut Context) {
exit_status.fetch_add(1, Ordering::Relaxed);
return;
}
let outfile = format!("{}/{}-{}.png", output, path.file_stem().unwrap().to_string_lossy(), 1 + z);
let outfile = format!(
"{}/{}-{}.png",
output,
path.file_stem().unwrap().to_string_lossy(),
1 + z
);
println!("{}saving {}", prefix, outfile);
image.to_file(outfile.as_ref()).unwrap();
if pngcrush {
@ -449,13 +479,21 @@ impl std::str::FromStr for CoordArg {
type Err = String;
fn from_str(s: &str) -> Result<Self, String> {
match s.split(",").map(|x| x.parse()).collect::<Result<Vec<_>, std::num::ParseIntError>>() {
Ok(ref vec) if vec.len() == 2 => {
Ok(CoordArg { x: vec[0], y: vec[1], z: 0 })
}
Ok(ref vec) if vec.len() == 3 => {
Ok(CoordArg { x: vec[0], y: vec[1], z: vec[2] })
}
match s
.split(",")
.map(|x| x.parse())
.collect::<Result<Vec<_>, std::num::ParseIntError>>()
{
Ok(ref vec) if vec.len() == 2 => Ok(CoordArg {
x: vec[0],
y: vec[1],
z: 0,
}),
Ok(ref vec) if vec.len() == 3 => Ok(CoordArg {
x: vec[0],
y: vec[1],
z: vec[2],
}),
Ok(_) => Err("must specify 2 or 3 coordinates".into()),
Err(e) => Err(e.to_string()),
}

View file

@ -7,8 +7,8 @@ extern crate git2;
extern crate walkdir;
#[macro_use] extern crate serde_derive;
mod template;
mod markdown;
mod template;
use std::collections::{BTreeMap, BTreeSet};
use std::cell::RefCell;
@ -45,12 +45,16 @@ fn main() -> Result<(), Box<std::error::Error>> {
tera::Value::String(s) => Ok(s.len().into()),
tera::Value::Array(a) => Ok(a.len().into()),
tera::Value::Object(o) => Ok(o.len().into()),
_ => Ok(0 .into()),
_ => Ok(0.into()),
});
tera.register_filter("substring", |input, opts| match input {
tera::Value::String(s) => {
let start = opts.get("start").and_then(|v| v.as_u64()).unwrap_or(0) as usize;
let mut end = opts.get("end").and_then(|v| v.as_u64()).map(|s| s as usize).unwrap_or(s.len());
let mut end = opts
.get("end")
.and_then(|v| v.as_u64())
.map(|s| s as usize)
.unwrap_or(s.len());
if end > s.len() {
end = s.len();
}
@ -110,7 +114,12 @@ fn main() -> Result<(), Box<std::error::Error>> {
params = &[][..];
is_variadic = false;
}
dm::preprocessor::Define::Function { docs: dc, params: macro_params, variadic, .. } => {
dm::preprocessor::Define::Function {
docs: dc,
params: macro_params,
variadic,
..
} => {
docs = dc;
has_params = true;
params = macro_params;
@ -122,8 +131,23 @@ fn main() -> Result<(), Box<std::error::Error>> {
}
let docs = DocBlock::parse(&docs.text());
let module = module_entry(&mut modules, &context.file_path(range.start.file));
module.items_wip.push((range.start.line, ModuleItem::Define { name, teaser: docs.teaser().to_owned() }));
module.defines.insert(name, Define { docs, has_params, params, is_variadic, line: range.start.line });
module.items_wip.push((
range.start.line,
ModuleItem::Define {
name,
teaser: docs.teaser().to_owned(),
},
));
module.defines.insert(
name,
Define {
docs,
has_params,
params,
is_variadic,
line: range.start.line,
},
);
macro_count += 1;
}
@ -162,10 +186,14 @@ fn main() -> Result<(), Box<std::error::Error>> {
progress.update(&ty.path);
let mut parsed_type = ParsedType::default();
parsed_type.name = ty.get().vars.get("name")
parsed_type.name = ty
.get()
.vars
.get("name")
.and_then(|v| v.value.constant.as_ref())
.and_then(|c| c.as_str())
.unwrap_or("").into();
.unwrap_or("")
.into();
let mut anything = false;
let mut substance = false;
@ -234,11 +262,14 @@ fn main() -> Result<(), Box<std::error::Error>> {
// file the type under its module as well
if let Some(ref block) = parsed_type.docs {
if let Some(module) = modules.get_mut(&module_path(&context.file_path(ty.location.file))) {
module.items_wip.push((ty.location.line, ModuleItem::Type {
path: ty.get().pretty_path(),
teaser: block.teaser().to_owned(),
substance: substance,
}));
module.items_wip.push((
ty.location.line,
ModuleItem::Type {
path: ty.get().pretty_path(),
teaser: block.teaser().to_owned(),
substance: substance,
},
));
}
}
@ -305,7 +336,13 @@ fn main() -> Result<(), Box<std::error::Error>> {
if count == 0 {
println!("0 types");
} else {
println!("{}/{}/{} types ({}%)", substance_count, types_with_docs.len(), count, (types_with_docs.len() * 100 / count));
println!(
"{}/{}/{} types ({}%)",
substance_count,
types_with_docs.len(),
count,
(types_with_docs.len() * 100 / count)
);
}
ALL_TYPE_NAMES.with(|all| {
@ -320,12 +357,14 @@ fn main() -> Result<(), Box<std::error::Error>> {
template::save_resources(output_path)?;
let env_filename = environment.display().to_string();
let world_name = objtree.find("/world")
let world_name = objtree
.find("/world")
.and_then(|w| w.get().vars.get("name"))
.and_then(|v| v.value.constant.as_ref())
.and_then(|c| c.as_str())
.unwrap_or("");
let title = index_docs.as_ref()
let title = index_docs
.as_ref()
.and_then(|(title, _)| title.as_ref())
.map(|s| &s[..])
.unwrap_or(world_name);
@ -489,7 +528,12 @@ fn linkify_type<'a, I: Iterator<Item=&'a str>>(iter: I) -> String {
progress.push_str(bit);
if ALL_TYPE_NAMES.with(|t| t.borrow().contains(&all_progress)) {
use std::fmt::Write;
let _ = write!(output, r#"/<a href="{}.html">{}</a>"#, &all_progress[1..], &progress[1..]);
let _ = write!(
output,
r#"/<a href="{}.html">{}</a>"#,
&all_progress[1..],
&progress[1..]
);
progress.clear();
}
}
@ -526,10 +570,15 @@ fn create(path: &Path) -> io::Result<File> {
fn git_info(git: &mut Git) -> Result<(), git2::Error> {
macro_rules! req {
($e:expr) => { match $e { Some(x) => x, None => {
println!("incomplete git info: malformed or non-utf8 name");
return Ok(());
}}}
($e:expr) => {
match $e {
Some(x) => x,
None => {
println!("incomplete git info: malformed or non-utf8 name");
return Ok(());
}
}
};
}
// get the revision
@ -582,7 +631,7 @@ fn git_info(git: &mut Git) -> Result<(), git2::Error> {
let at = req!(url.find("@"));
let colon = req!(url.find(":"));
if colon >= at {
git.web_url = format!("https://{}/{}", &url[at+1..colon], &url[colon+1..]);
git.web_url = format!("https://{}/{}", &url[at + 1..colon], &url[colon + 1..]);
} else {
println!("incomplete git info: weird SSH path: {}", url);
}
@ -599,7 +648,7 @@ struct Progress {
impl Progress {
fn update(&mut self, msg: &str) {
print!("\r{}", msg);
for _ in msg.len() .. self.last_len {
for _ in msg.len()..self.last_len {
print!(" ");
}
self.last_len = msg.len();
@ -635,7 +684,8 @@ struct IndexTree<'a> {
}
fn build_index_tree<'a, I>(iter: I) -> Vec<IndexTree<'a>>
where I: IntoIterator<Item=IndexTree<'a>>
where
I: IntoIterator<Item=IndexTree<'a>>,
{
let mut stack = vec![IndexTree {
htmlname: "",

View file

@ -25,22 +25,25 @@ impl DocBlock {
pub fn parse_with_title(markdown: &str) -> (Option<String>, Self) {
let mut parser = parser(markdown).peekable();
(if let Some(&Event::Start(Tag::Header(1))) = parser.peek() {
parser.next();
let mut pieces = Vec::new();
loop {
match parser.next() {
None | Some(Event::End(Tag::Header(1))) => break,
Some(other) => pieces.push(other),
(
if let Some(&Event::Start(Tag::Header(1))) = parser.peek() {
parser.next();
let mut pieces = Vec::new();
loop {
match parser.next() {
None | Some(Event::End(Tag::Header(1))) => break,
Some(other) => pieces.push(other),
}
}
}
let mut title = String::new();
push_html(&mut title, pieces);
Some(title)
} else {
None
}, parse_main(parser))
let mut title = String::new();
push_html(&mut title, pieces);
Some(title)
} else {
None
},
parse_main(parser),
)
}
pub fn teaser(&self) -> &str {
@ -52,7 +55,7 @@ fn parser(markdown: &str) -> Parser {
Parser::new_with_broken_link_callback(
markdown,
pulldown_cmark::OPTION_ENABLE_TABLES,
Some(&::handle_crosslink)
Some(&::handle_crosslink),
)
}

View file

@ -216,7 +216,10 @@ pub struct Prefab<E=Expression> {
impl<E> From<TypePath> for Prefab<E> {
fn from(path: TypePath) -> Self {
Prefab { path, vars: Default::default() }
Prefab {
path,
vars: Default::default(),
}
}
}
@ -324,7 +327,7 @@ impl Expression {
None
}
},
_ => None
_ => None,
}
}
}
@ -337,7 +340,7 @@ impl From<Term> for Expression {
unary: vec![],
follow: vec![],
term,
}
},
}
}
}
@ -406,7 +409,7 @@ impl From<Expression> for Term {
} else {
Term::Expr(Box::new(Expression::Base { term, unary, follow }))
},
other => Term::Expr(Box::new(other))
other => Term::Expr(Box::new(other)),
}
}
}
@ -567,20 +570,28 @@ impl VarType {
impl FromIterator<String> for VarType {
fn from_iter<T: IntoIterator<Item=String>>(iter: T) -> Self {
let (mut is_static, mut is_const, mut is_tmp) = (false, false, false);
let type_path = iter.into_iter()
let type_path = iter
.into_iter()
.skip_while(|p| {
if p == "global" || p == "static" {
is_static = true; true
is_static = true;
true
} else if p == "const" {
is_const = true; true
is_const = true;
true
} else if p == "tmp" {
is_tmp = true; true
is_tmp = true;
true
} else {
false
}
})
.collect();
VarType { is_static, is_const, is_tmp, type_path }
}).collect();
VarType {
is_static,
is_const,
is_tmp,
type_path,
}
}
}

View file

@ -150,10 +150,14 @@ pub fn register_builtins(tree: &mut ObjectTree) -> Result<(), DMError> {
}
}
macro_rules! int {
($e:expr) => {Expression::from(Term::Int($e))}
($e:expr) => {
Expression::from(Term::Int($e))
};
}
macro_rules! string {
($e:expr) => {Expression::from(Term::String($e.into()))}
($e:expr) => {
Expression::from(Term::String($e.into()))
};
}
entries! {

View file

@ -71,7 +71,7 @@ impl Constant {
if key == k {
return true;
}
}
},
_ => {}
}
false
@ -84,7 +84,7 @@ impl Constant {
if key == k {
return v.as_ref();
}
}
},
_ => {}
}
None
@ -263,8 +263,16 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree, sloppy: boo
for ty in tree.graph.node_indices() {
let keys: Vec<String> = tree.graph.node_weight(ty).unwrap().vars.keys().cloned().collect();
for key in keys {
if !tree.graph.node_weight(ty).unwrap().get_declaration(&key, tree).map_or(true, |x| x.var_type.is_const_evaluable() && (x.var_type.is_const || ty != NodeIndex::new(0))) {
continue // skip non-constant-evaluable vars
if !tree
.graph
.node_weight(ty)
.unwrap()
.get_declaration(&key, tree)
.map_or(true, |x| {
x.var_type.is_const_evaluable() && (x.var_type.is_const || ty != NodeIndex::new(0))
})
{
continue; // skip non-constant-evaluable vars
}
match constant_ident_lookup(tree, ty, &key, false) {
Err(err) => context.register_error(err),
@ -280,8 +288,15 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree, sloppy: boo
""
};
context.register_error(DMError::new(tree.graph.node_weight(ty).unwrap().vars[&key].value.location,
format!("undefined var '{}' on type '{}'{}", key, tree.graph.node_weight(ty).unwrap().path, extra)));
context.register_error(DMError::new(
tree.graph.node_weight(ty).unwrap().vars[&key].value.location,
format!(
"undefined var '{}' on type '{}'{}",
key,
tree.graph.node_weight(ty).unwrap().path,
extra
),
));
}
}
}
@ -290,12 +305,22 @@ pub(crate) fn evaluate_all(context: &Context, tree: &mut ObjectTree, sloppy: boo
/// Evaluate an expression in the absence of any surrounding context.
pub fn simple_evaluate(location: Location, expr: Expression) -> Result<Constant, DMError> {
ConstantFolder { tree: None, location, ty: NodeIndex::new(0), defines: None }.expr(expr, None)
ConstantFolder {
tree: None,
location,
ty: NodeIndex::new(0),
defines: None,
}.expr(expr, None)
}
/// Evaluate an expression in the preprocessor, with `defined()` available.
pub fn preprocessor_evaluate(location: Location, expr: Expression, defines: &DefineMap) -> Result<Constant, DMError> {
ConstantFolder { tree: None, location, ty: NodeIndex::new(0), defines: Some(defines) }.expr(expr, None)
ConstantFolder {
tree: None,
location,
ty: NodeIndex::new(0),
defines: Some(defines),
}.expr(expr, None)
}
enum ConstLookup {
@ -303,29 +328,49 @@ enum ConstLookup {
Continue(Option<NodeIndex>),
}
fn constant_ident_lookup(tree: &mut ObjectTree, ty: NodeIndex, ident: &str, must_be_static: bool) -> Result<ConstLookup, DMError> {
fn constant_ident_lookup(
tree: &mut ObjectTree,
ty: NodeIndex,
ident: &str,
must_be_static: bool,
) -> Result<ConstLookup, DMError> {
// try to read the currently-set value if we can and
// substitute that in, otherwise try to evaluate it.
let (location, type_hint, expr) = {
let decl = match tree.graph.node_weight(ty).unwrap().get_declaration(ident, tree).cloned() {
let decl = match tree
.graph
.node_weight(ty)
.unwrap()
.get_declaration(ident, tree)
.cloned()
{
Some(decl) => decl,
None => return Ok(ConstLookup::Continue(None)) // definitely doesn't exist
None => return Ok(ConstLookup::Continue(None)), // definitely doesn't exist
};
let type_ = tree.graph.node_weight_mut(ty).unwrap();
let parent = type_.parent_type();
match type_.vars.get_mut(ident) {
None => { return Ok(ConstLookup::Continue(parent)); }
None => return Ok(ConstLookup::Continue(parent)),
Some(var) => match var.value.constant.clone() {
Some(constant) => { return Ok(ConstLookup::Found(decl.var_type.type_path.clone(), constant)); }
Some(constant) => return Ok(ConstLookup::Found(decl.var_type.type_path.clone(), constant)),
None => match var.value.expression.clone() {
Some(expr) => {
if var.value.being_evaluated {
return Err(DMError::new(var.value.location, format!("recursive constant reference: {}", ident)));
return Err(DMError::new(
var.value.location,
format!("recursive constant reference: {}", ident),
));
} else if !decl.var_type.is_const_evaluable() {
return Err(DMError::new(var.value.location, format!("non-const variable: {}", ident)));
return Err(DMError::new(
var.value.location,
format!("non-const variable: {}", ident),
));
} else if !decl.var_type.is_static && must_be_static {
return Err(DMError::new(var.value.location, format!("non-static variable: {}", ident)));
return Err(DMError::new(
var.value.location,
format!("non-static variable: {}", ident),
));
}
var.value.being_evaluated = true;
(var.value.location, decl.var_type.type_path, expr)
@ -335,13 +380,17 @@ fn constant_ident_lookup(tree: &mut ObjectTree, ty: NodeIndex, ident: &str, must
var.value.constant = Some(c.clone());
return Ok(ConstLookup::Found(decl.var_type.type_path, c));
}
}
}
},
},
}
};
// evaluate full_value
let value = ConstantFolder { tree: Some(tree), defines: None, location, ty }
.expr(expr, if type_hint.is_empty() { None } else { Some(&type_hint) })?;
let value = ConstantFolder {
tree: Some(tree),
defines: None,
location,
ty,
}.expr(expr, if type_hint.is_empty() { None } else { Some(&type_hint) })?;
// and store it into 'value', then return it
let var = tree.graph.node_weight_mut(ty).unwrap().vars.get_mut(ident).unwrap();
var.value.constant = Some(value.clone());
@ -366,7 +415,11 @@ impl<'a> ConstantFolder<'a> {
fn expr(&mut self, expression: Expression, type_hint: Option<&TreePath>) -> Result<Constant, DMError> {
Ok(match expression {
Expression::Base { unary, term, follow } => {
let base_type_hint = if follow.is_empty() && unary.is_empty() { type_hint } else { None };
let base_type_hint = if follow.is_empty() && unary.is_empty() {
type_hint
} else {
None
};
let mut term = self.term(term, base_type_hint)?;
for each in follow {
term = self.follow(term, each)?;
@ -407,7 +460,11 @@ impl<'a> ConstantFolder<'a> {
for each in v {
out.push(match each {
// handle associations
Expression::AssignOp { op: AssignOp::Assign, lhs, rhs } => {
Expression::AssignOp {
op: AssignOp::Assign,
lhs,
rhs,
} => {
let key = match Term::from(*lhs) {
Term::Ident(ident) => Constant::String(ident),
other => self.term(other, None)?,
@ -439,7 +496,7 @@ impl<'a> ConstantFolder<'a> {
None => Err(self.error(format!("unknown typepath {}", full_path))),
}
}
(term, follow) => Err(self.error(format!("non-constant expression follower: {} {:?}", term, follow)))
(term, follow) => Err(self.error(format!("non-constant expression follower: {} {:?}", term, follow))),
}
}
@ -487,12 +544,15 @@ impl<'a> ConstantFolder<'a> {
if rhs >= 2 && (i32::max_value() as f32).log(lhs as f32) < rhs as f32 {
return Err(self.error(format!("out-of-range {:?}: {} {} {}", op, lhs, op, rhs)));
}
return Ok(Constant::from(lhs.pow(rhs as u32)))
return Ok(Constant::from(lhs.pow(rhs as u32)));
}
(BinaryOp::Pow, Int(lhs), Float(rhs)) => return Ok(Constant::from((lhs as f32).powf(rhs.raw()))),
(BinaryOp::Pow, Float(lhs), Int(rhs)) => return Ok(Constant::from(lhs.powi(rhs))),
(BinaryOp::Pow, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs.powf(rhs))),
(_, lhs_, rhs_) => { lhs = lhs_; rhs = rhs_; }
(_, lhs_, rhs_) => {
lhs = lhs_;
rhs = rhs_;
}
}
macro_rules! integer {
@ -515,29 +575,25 @@ impl<'a> ConstantFolder<'a> {
(BinaryOp::NotEq, lhs, rhs) => Ok(Constant::from(lhs != rhs)),
(BinaryOp::And, lhs, rhs) => Ok(if lhs.to_bool() { rhs } else { lhs }),
(BinaryOp::Or, lhs, rhs) => Ok(if lhs.to_bool() { lhs } else { rhs }),
(op, lhs, rhs) => Err(self.error(format!("non-constant {:?}: {} {} {}", op, lhs, op, rhs)))
(op, lhs, rhs) => Err(self.error(format!("non-constant {:?}: {} {} {}", op, lhs, op, rhs))),
}
}
fn term(&mut self, term: Term, type_hint: Option<&TreePath>) -> Result<Constant, DMError> {
Ok(match term {
Term::Null => Constant::Null(type_hint.cloned()),
Term::New { type_, args } => {
Constant::New {
type_: match type_ {
NewType::Prefab(e) => NewType::Prefab(self.prefab(e)?),
NewType::Implicit => NewType::Implicit,
NewType::Ident(_) => return Err(self.error("non-constant new expression")),
},
args: match args {
Some(args) => Some(self.arguments(args)?),
None => None,
},
}
},
Term::List(vec) => {
Constant::List(self.arguments(vec)?)
Term::New { type_, args } => Constant::New {
type_: match type_ {
NewType::Prefab(e) => NewType::Prefab(self.prefab(e)?),
NewType::Implicit => NewType::Implicit,
NewType::Ident(_) => return Err(self.error("non-constant new expression")),
},
args: match args {
Some(args) => Some(self.arguments(args)?),
None => None,
},
},
Term::List(vec) => Constant::List(self.arguments(vec)?),
Term::Call(ident, args) => match &*ident {
// constructors which remain as they are
"matrix" => Constant::Call(ConstFn::Matrix, self.arguments(args)?),
@ -573,11 +629,11 @@ impl<'a> ConstantFolder<'a> {
=> {
Constant::Int(if defines.contains_key(ident) { 1 } else { 0 })
}
_ => return Err(self.error("malformed defined() call"))
_ => return Err(self.error("malformed defined() call")),
}
}
// other functions are no-goes
_ => return Err(self.error(format!("non-constant function call: {}", ident)))
_ => return Err(self.error(format!("non-constant function call: {}", ident))),
},
Term::Prefab(prefab) => Constant::Prefab(self.prefab(prefab)?),
Term::Ident(ident) => self.ident(ident, false)?,
@ -586,7 +642,7 @@ impl<'a> ConstantFolder<'a> {
Term::Int(v) => Constant::Int(v),
Term::Float(v) => Constant::from(v),
Term::Expr(expr) => self.expr(*expr, type_hint)?,
_ => return Err(self.error(format!("non-constant expression")))
_ => return Err(self.error(format!("non-constant expression"))),
})
}
@ -596,7 +652,10 @@ impl<'a> ConstantFolder<'a> {
// TODO: find a type annotation by looking up 'k' on the prefab's type
vars.insert(k, self.expr(v, None)?);
}
Ok(Prefab { path: prefab.path, vars })
Ok(Prefab {
path: prefab.path,
vars,
})
}
fn ident(&mut self, ident: String, must_be_static: bool) -> Result<Constant, DMError> {
@ -612,7 +671,9 @@ impl<'a> ConstantFolder<'a> {
return Err(self.error("cannot reference variables in this context"));
}
let tree = self.tree.as_mut().unwrap();
match constant_ident_lookup(tree, ty, &ident, must_be_static).map_err(|e| DMError::new(location, e.into_description()))? {
match constant_ident_lookup(tree, ty, &ident, must_be_static)
.map_err(|e| DMError::new(location, e.into_description()))?
{
ConstLookup::Found(_, v) => return Ok(v),
ConstLookup::Continue(i) => idx = i,
}

View file

@ -143,7 +143,7 @@ fn parse_metadata(data: &str) -> Metadata {
for line in lines {
if line.starts_with("# END DMI") {
break
break;
}
let mut split = line.trim().splitn(2, " = ");
let key = split.next().unwrap();
@ -201,7 +201,7 @@ fn parse_metadata(data: &str) -> Metadata {
vector.truncate(n);
state.frames = Frames::Delays(vector);
},
Frames::Delays(_) => panic!()
Frames::Delays(_) => panic!(),
}
}
"loop" => state.as_mut().unwrap().loop_ = value.parse().unwrap(),

View file

@ -69,7 +69,11 @@ pub struct DocComment {
impl DocComment {
/// Construct an empty DocComment with the given properties.
pub fn new(kind: CommentKind, target: DocTarget) -> DocComment {
DocComment { kind, target, text: String::new() }
DocComment {
kind,
target,
text: String::new(),
}
}
/// Check if this comment is entirely textless.
@ -121,7 +125,9 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool {
continue;
}
let this_prefix = &line[..line.len() - line.trim_left_matches(|c: char| c.is_whitespace() || c == ignore_char).len()];
let this_prefix = &line[..line.len() - line
.trim_left_matches(|c: char| c.is_whitespace() || c == ignore_char)
.len()];
match prefix {
None => prefix = Some(this_prefix),
Some(ref mut prefix) => {
@ -130,7 +136,9 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool {
loop {
no_match = chars.as_str();
match chars.next() {
Some(ch) => if Some(ch) != this_chars.next() { break },
Some(ch) => if Some(ch) != this_chars.next() {
break;
},
None => break,
}
}
@ -147,7 +155,9 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool {
loop {
no_match = chars.as_str();
match chars.next_back() {
Some(ch) => if Some(ch) != this_chars.next_back() { break },
Some(ch) => if Some(ch) != this_chars.next_back() {
break;
},
None => break,
}
}
@ -174,7 +184,7 @@ fn simplify(out: &mut String, text: &str, ignore_char: char) -> bool {
for _ in 0..newlines {
out.push_str("\n");
}
out.push_str(&line[prefix_len..line.len()-suffix_len]);
out.push_str(&line[prefix_len..line.len() - suffix_len]);
anything = true;
newlines = 1;
}

View file

@ -81,7 +81,8 @@ impl Context {
if let Some(severity) = self.print_severity {
if error.severity <= severity {
let stderr = io::stderr();
self.pretty_print_error(&mut stderr.lock(), &error).expect("error writing to stderr");
self.pretty_print_error(&mut stderr.lock(), &error)
.expect("error writing to stderr");
}
}
self.errors.borrow_mut().push(error);
@ -99,10 +100,13 @@ impl Context {
/// Pretty-print a `DMError` to the given output.
pub fn pretty_print_error<W: io::Write>(&self, w: &mut W, error: &DMError) -> io::Result<()> {
writeln!(w, "{}, line {}, column {}:",
writeln!(
w,
"{}, line {}, column {}:",
self.file_path(error.location.file).display(),
error.location.line,
error.location.column)?;
error.location.column,
)?;
writeln!(w, "{}: {}\n", error.severity, error.description)
}
@ -188,11 +192,15 @@ pub trait HasLocation {
}
impl<'a, T: HasLocation> HasLocation for &'a T {
fn location(&self) -> Location { (**self).location() }
fn location(&self) -> Location {
(**self).location()
}
}
impl<'a, T: HasLocation> HasLocation for &'a mut T {
fn location(&self) -> Location { (**self).location() }
fn location(&self) -> Location {
(**self).location()
}
}
// ----------------------------------------------------------------------------

View file

@ -14,8 +14,22 @@ fn main() {
println!("---- item_flags example ----");
objtree.find("/obj/item").expect("no root").recurse(&mut |ty| {
print!("{}: ", ty.path);
let mut flags_1 = ty.get_value("flags_1").expect("flags_1").constant.as_ref().expect("f1c").to_int().unwrap_or(0);
let mut item_flags = ty.get_value("item_flags").expect("item_flags").constant.as_ref().expect("ofc").to_int().unwrap_or(0);
let mut flags_1 = ty
.get_value("flags_1")
.expect("flags_1")
.constant
.as_ref()
.expect("f1c")
.to_int()
.unwrap_or(0);
let mut item_flags = ty
.get_value("item_flags")
.expect("item_flags")
.constant
.as_ref()
.expect("ofc")
.to_int()
.unwrap_or(0);
// Migrate old flags_1 values to their item_flags equivalents
let lhs =
@ -29,14 +43,20 @@ fn main() {
item_flags &= !rhs;
let crossover = if rhs != 0 && lhs != 0 {
panic!("flags_1={}, item_flags={}, lhs={}, rhs={}", flags_1, item_flags, lhs, rhs);
panic!(
"flags_1={}, item_flags={}, lhs={}, rhs={}",
flags_1, item_flags, lhs, rhs
);
} else if lhs != 0 {
lhs
} else {
rhs
};
println!("flags_1={}, item_flags={}, crossover={}", flags_1, item_flags, crossover);
println!(
"flags_1={}, item_flags={}, crossover={}",
flags_1, item_flags, crossover
);
});
println!("---- anchored example ----");
@ -50,7 +70,16 @@ fn main() {
println!("{} -> {}", ty.path, anch);
// print location info for any type with a redundant `anchored = TRUE`
if anch && ty.parent_type().unwrap().get_value("anchored").unwrap().constant.as_ref().unwrap().to_bool() {
if anch && ty
.parent_type()
.unwrap()
.get_value("anchored")
.unwrap()
.constant
.as_ref()
.unwrap()
.to_bool()
{
println!("{}:{}", ctx.file_path(var.location.file).display(), var.location.line);
}
});

View file

@ -123,7 +123,9 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where
// hope that truncating division will approximate
// a sane situation.
self.context.register_error(self.error(format!(
"inconsistent indentation: {} % {} != 0", spaces, spaces_per_indent)));
"inconsistent indentation: {} % {} != 0",
spaces, spaces_per_indent
)));
}
new_indents = spaces / spaces_per_indent;
self.current = Some((spaces_per_indent, new_indents));
@ -137,7 +139,9 @@ impl<'ctx, I> IndentProcessor<'ctx, I> where
} else if indents < new_indents {
// multiple indent is an error, register it but let it work
self.context.register_error(self.error(format!(
"inconsistent multiple indentation: {} > 1", new_indents - indents)));
"inconsistent multiple indentation: {} > 1",
new_indents - indents,
)));
for _ in indents..new_indents {
self.push_eol(Token::Punct(Punctuation::LBrace));
}

View file

@ -160,12 +160,17 @@ static SPEEDY_TABLE: [(usize, usize); 127] = [
#[test]
fn make_speedy_table() {
let everything: Vec<&str> = PUNCT_TABLE.iter()
let everything: Vec<&str> = PUNCT_TABLE
.iter()
.map(|p| p.0)
.filter(|s| !s.chars().any(|c| c.is_alphanumeric()))
.collect();
for each in everything.iter() {
assert!(each.len() == 1 || everything.contains(&&each[..each.len() - 1]), "no prefix: {}", each);
assert!(
each.len() == 1 || everything.contains(&&each[..each.len() - 1]),
"no prefix: {}",
each
);
}
let mut table = vec![];
@ -189,7 +194,11 @@ fn make_speedy_table() {
}
if &SPEEDY_TABLE[..] != &table[..] {
panic!("\n\nSpeedy table outdated, replace with:\n\nstatic SPEEDY_TABLE: [(usize, usize); {}] = {:?};\n\n", table.len(), table);
panic!(
"\n\nSpeedy table outdated, replace with:\n\nstatic SPEEDY_TABLE: [(usize, usize); {}] = {:?};\n\n",
table.len(),
table
);
}
}
@ -526,9 +535,7 @@ impl<I: Iterator<Item=io::Result<u8>>> Iterator for LocationTracker<I> {
}
Some(Ok(ch))
}
Some(Err(e)) => {
Some(Err(DMError::new(self.location, "i/o error").set_cause(e)))
}
Some(Err(e)) => Some(Err(DMError::new(self.location, "i/o error").set_cause(e))),
}
}
}
@ -673,7 +680,10 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Lexer<'ctx, I> {
match self.next() {
Some(b'/') => comment = Some(DocComment::new(CommentKind::Line, DocTarget::FollowingItem)),
Some(b'!') => comment = Some(DocComment::new(CommentKind::Line, DocTarget::EnclosingItem)),
Some(b'\n') => { self.put_back(Some(b'\n')); return None },
Some(b'\n') => {
self.put_back(Some(b'\n'));
return None;
}
Some(b'\\') => backslash = true,
_ => {}
}
@ -798,7 +808,10 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Lexer<'ctx, I> {
loop {
match self.next() {
Some(ch) if is_ident(ch) || is_digit(ch) => ident.push(ch),
ch => { self.put_back(ch); break }
ch => {
self.put_back(ch);
break;
}
}
}
from_latin1(ident)
@ -838,9 +851,9 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Lexer<'ctx, I> {
if ch == end[idx] && !backslash {
idx += 1;
if idx == end.len() {
break
break;
}
continue
continue;
} else if ch == end[0] && !backslash {
// TODO: this is a hack to fix the '""}' situation
buf.extend_from_slice(&end[..idx]);
@ -899,7 +912,7 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Lexer<'ctx, I> {
candidate = Some(items[0].1);
}
if items.len() == 1 {
return candidate
return candidate;
}
match self.next() {
@ -967,7 +980,7 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Iterator for Lexer<'ctx, I> {
return Some(LocatedToken {
location: location,
token: Token::Punct(Punctuation::Newline),
})
});
} else {
return None;
}
@ -1047,7 +1060,7 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Iterator for Lexer<'ctx, I> {
// check keywords
for &(name, value) in PUNCT_TABLE.iter() {
if name == ident {
return Some(locate(Punct(value)))
return Some(locate(Punct(value)));
}
}
self.close_allowed = true;
@ -1066,8 +1079,8 @@ impl<'ctx, I: Iterator<Item=io::Result<u8>>> Iterator for Lexer<'ctx, I> {
}
continue;
}
}
}
},
};
}
}
}

View file

@ -19,7 +19,7 @@ macro_rules! try_iter {
Ok(x) => x,
Err(e) => return Some(Err(From::from(e))),
}
}
};
}
mod error;
@ -72,17 +72,23 @@ pub fn pretty_print<W, I>(w: &mut W, input: I, show_ws: bool) -> io::Result<()>
lexer::Token::Punct(lexer::Punctuation::LBrace) => {
indents += 1;
needs_newline = true;
if show_ws { write!(w, "{{")?; }
if show_ws {
write!(w, "{{")?;
}
}
lexer::Token::Punct(lexer::Punctuation::RBrace) => {
indents -= 1;
needs_newline = true;
if show_ws { write!(w, "}}")?; }
if show_ws {
write!(w, "}}")?;
}
}
lexer::Token::Punct(lexer::Punctuation::Semicolon) |
lexer::Token::Punct(lexer::Punctuation::Newline) => {
needs_newline = true;
if show_ws { write!(w, ";")?; }
if show_ws {
write!(w, ";")?;
}
}
lexer::Token::DocComment(_) => {}
other => {

View file

@ -163,7 +163,11 @@ impl<'a> TypeRef<'a> {
/// Find the parent **path**, without taking `parent_type` into account.
pub fn parent_path(&self) -> Option<TypeRef<'a>> {
self.tree.graph.neighbors_directed(self.idx, Direction::Incoming).next().map(|i| TypeRef::new(self.tree, i))
self.tree
.graph
.neighbors_directed(self.idx, Direction::Incoming)
.next()
.map(|i| TypeRef::new(self.tree, i))
}
/// Find the parent **type** based on `parent_type` var, or parent path if unspecified.
@ -237,7 +241,9 @@ impl<'a> TypeRef<'a> {
pub fn is_subtype_of(self, parent: &Type) -> bool {
let mut current = Some(self);
while let Some(ty) = current.take() {
if ::std::ptr::eq(ty.get(), parent) { return true }
if ::std::ptr::eq(ty.get(), parent) {
return true;
}
current = ty.parent_type();
}
false
@ -336,7 +342,9 @@ impl ObjectTree {
}
pub fn type_by_path<I>(&self, path: I) -> Option<TypeRef>
where I: IntoIterator, I::Item: AsRef<str>
where
I: IntoIterator,
I::Item: AsRef<str>,
{
let (exact, ty) = self.type_by_path_approx(path);
if exact {
@ -347,7 +355,9 @@ impl ObjectTree {
}
pub fn type_by_path_approx<I>(&self, path: I) -> (bool, TypeRef)
where I: IntoIterator, I::Item: AsRef<str>
where
I: IntoIterator,
I::Item: AsRef<str>,
{
let mut current = NodeIndex::new(0);
let mut first = true;
@ -440,7 +450,10 @@ impl ObjectTree {
if let Some(&idx) = self.types.get(parent_type) {
idx
} else {
context.register_error(DMError::new(location, format!("bad parent type for {}: {}", path, parent_type)));
context.register_error(DMError::new(
location,
format!("bad parent type for {}: {}", path, parent_type),
));
NodeIndex::new(0) // on bad parent_type, fall back to the root
}
};
@ -484,7 +497,12 @@ impl ObjectTree {
node
}
fn get_from_path<'a, I: Iterator<Item=&'a str>>(&mut self, location: Location, mut path: I, len: usize) -> Result<(NodeIndex, &'a str), DMError> {
fn get_from_path<'a, I: Iterator<Item=&'a str>>(
&mut self,
location: Location,
mut path: I,
len: usize,
) -> Result<(NodeIndex, &'a str), DMError> {
let mut current = NodeIndex::new(0);
let mut last = match path.next() {
Some(name) => name,
@ -504,14 +522,16 @@ impl ObjectTree {
Ok((current, last))
}
fn register_var<'a, I>(&mut self,
fn register_var<'a, I>(
&mut self,
location: Location,
parent: NodeIndex,
mut prev: &'a str,
mut rest: I,
comment: DocCollection,
) -> Result<Option<&mut TypeVar>, DMError> where
I: Iterator<Item=&'a str>
) -> Result<Option<&mut TypeVar>, DMError>
where
I: Iterator<Item=&'a str>,
{
let (mut is_declaration, mut is_static, mut is_const, mut is_tmp) = (false, false, false, false);
@ -519,7 +539,7 @@ impl ObjectTree {
is_declaration = true;
prev = match rest.next() {
Some(name) => name,
None => return Ok(None) // var{} block, children will be real vars
None => return Ok(None), // var{} block, children will be real vars
};
while prev == "global" || prev == "static" || prev == "tmp" || prev == "const" {
if let Some(name) = rest.next() {
@ -528,11 +548,11 @@ impl ObjectTree {
is_tmp |= prev == "tmp";
prev = name;
} else {
return Ok(None) // var/const{} block, children will be real vars
return Ok(None); // var/const{} block, children will be real vars
}
}
} else if is_proc_decl(prev) {
return Err(DMError::new(location, "proc looks like a var"))
return Err(DMError::new(location, "proc looks like a var"));
}
let mut type_path = Vec::new();
@ -566,7 +586,8 @@ impl ObjectTree {
})))
}
fn register_proc(&mut self,
fn register_proc(
&mut self,
location: Location,
parent: NodeIndex,
name: &str,
@ -592,7 +613,8 @@ impl ObjectTree {
}
// an entry which may be anything depending on the path
pub fn add_entry<'a, I: Iterator<Item=&'a str>>(&mut self,
pub fn add_entry<'a, I: Iterator<Item = &'a str>>(
&mut self,
location: Location,
mut path: I,
len: usize,
@ -611,7 +633,8 @@ impl ObjectTree {
}
// an entry which is definitely a var because a value is specified
pub fn add_var<'a, I: Iterator<Item=&'a str>>(&mut self,
pub fn add_var<'a, I: Iterator<Item = &'a str>>(
&mut self,
location: Location,
mut path: I,
len: usize,
@ -629,7 +652,8 @@ impl ObjectTree {
}
// an entry which is definitely a proc because an argument list is specified
pub fn add_proc<'a, I: Iterator<Item=&'a str>>(&mut self,
pub fn add_proc<'a, I: Iterator<Item = &'a str>>(
&mut self,
location: Location,
mut path: I,
len: usize,
@ -641,13 +665,16 @@ impl ObjectTree {
is_verb = Some(proc_name == "verb");
proc_name = match path.next() {
Some(name) => name,
None => return Err(DMError::new(location, "proc must have a name"))
None => return Err(DMError::new(location, "proc must have a name")),
};
} else if is_var_decl(proc_name) {
return Err(DMError::new(location, "var looks like a proc"))
return Err(DMError::new(location, "var looks like a proc"));
}
if let Some(other) = path.next() {
return Err(DMError::new(location, format!("proc name must be a single identifier (spurious {:?})", other)))
return Err(DMError::new(
location,
format!("proc name must be a single identifier (spurious {:?})", other),
));
}
self.register_proc(location, parent, proc_name, is_verb, parameters)

View file

@ -19,8 +19,9 @@ use super::docs::*;
///
/// Compilation failures will return a best-effort parse, and diagnostics will
/// be registered with the provided `Context`.
pub fn parse<I>(context: &Context, iter: I) -> ObjectTree where
I: IntoIterator<Item=LocatedToken>
pub fn parse<I>(context: &Context, iter: I) -> ObjectTree
where
I: IntoIterator<Item=LocatedToken>,
{
Parser::new(context, iter.into_iter()).parse_object_tree()
}
@ -55,7 +56,7 @@ macro_rules! leading {
Some(x) => x,
None => return Ok(None),
}
}
};
}
// ----------------------------------------------------------------------------
@ -117,7 +118,7 @@ impl<'a> Iterator for PathStackIter<'a> {
fn next(&mut self) -> Option<&'a str> {
loop {
match {self.current}.split_first() {
match { self.current }.split_first() {
Some((first, rest)) => {
self.current = rest;
return Some(first);
@ -125,7 +126,7 @@ impl<'a> Iterator for PathStackIter<'a> {
None => match self.rest.pop() {
Some(c) => self.current = c,
None => return None,
}
},
}
}
}
@ -159,8 +160,8 @@ enum Op {
impl Op {
fn build(self, lhs: Box<Expression>, rhs: Box<Expression>) -> Expression {
match self {
Op::BinaryOp(op) => Expression::BinaryOp { op: op, lhs: lhs, rhs: rhs },
Op::AssignOp(op) => Expression::AssignOp { op: op, lhs: lhs, rhs: rhs },
Op::BinaryOp(op) => Expression::BinaryOp { op, lhs, rhs },
Op::AssignOp(op) => Expression::AssignOp { op, lhs, rhs },
}
}
}
@ -354,8 +355,9 @@ impl<'ctx, 'an, I> HasLocation for Parser<'ctx, 'an, I> {
}
}
impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
I: Iterator<Item=LocatedToken>
impl<'ctx, 'an, I> Parser<'ctx, 'an, I>
where
I: Iterator<Item=LocatedToken>,
{
/// Construct a new parser using the given input stream.
pub fn new(context: &'ctx Context, input: I) -> Parser<I> {
@ -415,7 +417,12 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
pub fn finalize_object_tree(mut self) -> ObjectTree {
let procs_total = self.procs_good + self.procs_bad;
if procs_total > 0 {
eprintln!("parsed {}/{} proc bodies ({}%)", self.procs_good, procs_total, (self.procs_good * 100 / procs_total));
eprintln!(
"parsed {}/{} proc bodies ({}%)",
self.procs_good,
procs_total,
(self.procs_good * 100 / procs_total)
);
}
let sloppy = self.context.errors().iter().any(|p| p.severity() == Severity::Error);
@ -437,10 +444,10 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
let message = format!("got '{}', expected one of: {}", got, expected);
self.put_back(got);
self.error(message)
},
Err(err) => {
self.error(format!("i/o error, expected one of: {}", expected)).set_cause(err)
}
Err(err) => self
.error(format!("i/o error, expected one of: {}", expected))
.set_cause(err),
}
}
@ -452,7 +459,7 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
match t {
Ok(Some(v)) => Ok(v),
Ok(None) => self.parse_error(),
Err(e) => Err(e)
Err(e) => Err(e),
}
}
@ -462,15 +469,19 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
break Ok(next);
}
match self.input.next() {
Some(LocatedToken { location, token: Token::DocComment(dc) }) => {
match dc.target {
DocTarget::EnclosingItem if self.in_docs == 0 => {
self.module_docs.entry(location.file).or_default().push((location.line, dc));
},
DocTarget::EnclosingItem => self.docs_enclosing.push(dc),
DocTarget::FollowingItem => self.docs_following.push(dc),
Some(LocatedToken {
location,
token: Token::DocComment(dc),
}) => match dc.target {
DocTarget::EnclosingItem if self.in_docs == 0 => {
self.module_docs
.entry(location.file)
.or_default()
.push((location.line, dc));
}
}
DocTarget::EnclosingItem => self.docs_enclosing.push(dc),
DocTarget::FollowingItem => self.docs_following.push(dc),
},
Some(token) => {
self.expected.clear();
self.location = token.location;
@ -613,7 +624,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
None if !(absolute || spurious_lead) => return Ok(None),
None => {
slash_loc.column += 1;
self.annotate_precise(slash_loc..slash_loc, || Annotation::IncompleteTreePath(absolute, parts.clone()));
self.annotate_precise(slash_loc..slash_loc, || {
Annotation::IncompleteTreePath(absolute, parts.clone())
});
self.context.register_error(self.error("path has no effect"));
return success((absolute, Vec::new()));
}
@ -635,7 +648,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
parts.push(i);
} else {
slash_loc.column += 1;
self.annotate_precise(slash_loc..slash_loc, || Annotation::IncompleteTreePath(absolute, parts.clone()));
self.annotate_precise(slash_loc..slash_loc, || {
Annotation::IncompleteTreePath(absolute, parts.clone())
});
}
}
@ -659,7 +674,7 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
let (absolute, path) = leading!(self.tree_path());
let new_stack = PathStack {
parent: if absolute { None } else { Some(&parent) },
parts: &path
parts: &path,
};
if absolute && parent.parent.is_some() {
self.context.register_error(self.error(format!("nested absolute path: {} inside {}", new_stack, parent))
@ -814,7 +829,12 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
};
let (input_type, in_list) = require!(self.input_specifier());
success(Parameter {
path, name, default, input_type, in_list, location
path,
name,
default,
input_type,
in_list,
location,
})
}
@ -826,9 +846,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
};
let next = self.next(message)?;
if next == terminator || next == Token::Eof {
break
break;
} else if next == Token::Punct(Punctuation::Semicolon) {
continue
continue;
}
self.put_back(next);
require!(self.tree_entry(parent));
@ -838,11 +858,16 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
fn tree_block(&mut self, parent: PathStack) -> Status<()> {
leading!(self.exact(Token::Punct(Punctuation::LBrace)));
Ok(Some(require!(self.tree_entries(parent, Token::Punct(Punctuation::RBrace)))))
Ok(Some(require!(
self.tree_entries(parent, Token::Punct(Punctuation::RBrace))
)))
}
fn root(&mut self) -> Status<()> {
let root = PathStack { parent: None, parts: &[] };
let root = PathStack {
parent: None,
parts: &[],
};
self.tree_entries(root, Token::Eof)
}
@ -950,7 +975,7 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
arms.push((expr, block));
} else {
else_arm = Some(require!(self.block(loop_ctx)));
break
break;
}
self.skip_phantom_semicolons()?;
}
@ -995,14 +1020,26 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
// in-list form ("for list")
let (var_type, name) = match init {
// this is a really terrible way to do this
Statement::Var(VarStatement { var_type, name, value: Some(value) }) => {
Statement::Var(VarStatement {
var_type,
name,
value: Some(value),
}) => {
// for(var/a = 1 to
require!(self.exact_ident("to"));
let rhs = require!(self.expression());
return success(require!(self.for_range(Some(var_type), name, value, rhs)));
},
Statement::Var(VarStatement { var_type, name, value: None }) => { (Some(var_type), name) },
Statement::Expr(Expression::BinaryOp { op: BinaryOp::In, lhs, rhs }) => {
}
Statement::Var(VarStatement {
var_type,
name,
value: None,
}) => (Some(var_type), name),
Statement::Expr(Expression::BinaryOp {
op: BinaryOp::In,
lhs,
rhs,
}) => {
let name = match lhs.into_term() {
Some(Term::Ident(name)) => name,
_ => return Err(self.error("for-list must start with variable")),
@ -1110,7 +1147,11 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
catch_params = Vec::new();
}
let catch_block = require!(self.block(loop_ctx));
success(Statement::TryCatch { try_block, catch_params, catch_block })
success(Statement::TryCatch {
try_block,
catch_params,
catch_block,
})
// SINGLE-LINE STATEMENTS
} else if let Some(()) = self.exact_ident("set")? {
let name = require!(self.ident());
@ -1190,7 +1231,7 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
let (_, mut tree_path) = require!(self.tree_path());
let name = match tree_path.pop() {
Some(name) => name,
None => return Err(self.error("'var' must be followed by a name"))
None => return Err(self.error("'var' must be followed by a name")),
};
require!(self.var_annotations());
@ -1222,7 +1263,7 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
var_stmts.push(VarStatement { var_type, name, value });
if in_for || self.exact(Token::Punct(Punctuation::Comma))?.is_none() {
break
break;
}
}
if var_stmts.len() == 1 {
@ -1248,7 +1289,13 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
// for(var/a = 1 to 20
// for(var/a in 1 to 20
fn for_range(&mut self, var_type: Option<VarType>, name: String, start: Expression, end: Expression) -> Status<Statement> {
fn for_range(
&mut self,
var_type: Option<VarType>,
name: String,
start: Expression,
end: Expression,
) -> Status<Statement> {
// step 2
let step = if let Some(()) = self.exact_ident("step")? {
Some(require!(self.expression()))
@ -1321,7 +1368,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
parts.push((sep, ident));
} else {
separator_loc.column += 1;
self.annotate_precise(separator_loc..separator_loc, || Annotation::IncompleteTypePath(parts.clone(), sep));
self.annotate_precise(separator_loc..separator_loc, || {
Annotation::IncompleteTypePath(parts.clone(), sep)
});
}
// followed by more path elements, empty ones ignored
@ -1331,7 +1380,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
parts.push((sep, ident));
} else {
separator_loc.column += 1;
self.annotate_precise(separator_loc..separator_loc, || Annotation::IncompleteTypePath(parts.clone(), sep));
self.annotate_precise(separator_loc..separator_loc, || {
Annotation::IncompleteTypePath(parts.clone(), sep)
});
}
}
@ -1479,7 +1530,10 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
Token::Punct(Punctuation::BitNot) => unary_ops.push(UnaryOp::BitNot),
Token::Punct(Punctuation::PlusPlus) => unary_ops.push(UnaryOp::PreIncr),
Token::Punct(Punctuation::MinusMinus) => unary_ops.push(UnaryOp::PreDecr),
other => { self.put_back(other); break }
other => {
self.put_back(other);
break;
}
}
}
@ -1557,17 +1611,22 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
},
// term :: 'call' arglist arglist
Token::Ident(ref i, _) if i == "call" => {
Term::DynamicCall(require!(self.arguments(&[], "call")), require!(self.arguments(&[], "call*")))
},
Token::Ident(ref i, _) if i == "call" => Term::DynamicCall(
require!(self.arguments(&[], "call")),
require!(self.arguments(&[], "call*")),
),
// term :: 'input' arglist input_specifier
Token::Ident(ref i, _) if i == "input" => match self.arguments(&[], "input")? {
Some(args) => {
let (input_type, in_list) = require!(self.input_specifier());
Term::Input { args, input_type, in_list: in_list.map(Box::new) }
Term::Input {
args,
input_type,
in_list: in_list.map(Box::new),
}
}
None => Term::Ident(i.to_owned())
None => Term::Ident(i.to_owned()),
},
// term :: 'locate' arglist ('in' expression)?
@ -1587,18 +1646,16 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
};
Term::Locate { args, in_list }
}
None => Term::Ident(i.to_owned())
None => Term::Ident(i.to_owned()),
},
// term :: 'pick' pick_arglist
Token::Ident(ref i, _) if i == "pick" => match self.pick_arguments()? {
Some(args) => Term::Pick(args),
None => Term::Ident(i.to_owned())
None => Term::Ident(i.to_owned()),
},
Token::Ident(ref i, _) if i == "null" => {
Term::Null
},
Token::Ident(ref i, _) if i == "null" => Term::Null,
// term :: ident arglist | ident
Token::Ident(i, _) => {
@ -1635,7 +1692,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
} else {
// bare dot
dot_loc.column += 1;
self.annotate_precise(dot_loc..dot_loc, || Annotation::IncompleteTypePath(Vec::new(), PathOp::Dot));
self.annotate_precise(dot_loc..dot_loc, || {
Annotation::IncompleteTypePath(Vec::new(), PathOp::Dot)
});
self.annotate(start, || Annotation::ReturnVal);
Term::Ident(".".to_owned())
}
@ -1690,14 +1749,14 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
let expr = require!(self.expression());
require!(self.exact(Token::Punct(Punctuation::RBracket)));
success(Follow::Index(Box::new(expr)))
},
}
// follow :: '.' ident arglist?
// TODO: only apply these rules if there is no whitespace around the punctuation
Token::Punct(Punctuation::Dot) => self.follow_index(IndexKind::Dot, belongs_to),
Token::Punct(Punctuation::CloseColon)
if !belongs_to.is_empty() || !in_ternary
=> self.follow_index(IndexKind::Colon, belongs_to),
Token::Punct(Punctuation::CloseColon) if !belongs_to.is_empty() || !in_ternary => {
self.follow_index(IndexKind::Colon, belongs_to)
},
Token::Punct(Punctuation::SafeDot) => self.follow_index(IndexKind::SafeDot, belongs_to),
Token::Punct(Punctuation::SafeColon) => self.follow_index(IndexKind::SafeColon, belongs_to),
@ -1712,7 +1771,9 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
Some(ident) => ident,
None => {
index_op_loc.column += kind.len() as u16;
self.annotate_precise(index_op_loc..index_op_loc, || Annotation::ScopedMissingIdent(belongs_to.clone()));
self.annotate_precise(index_op_loc..index_op_loc, || {
Annotation::ScopedMissingIdent(belongs_to.clone())
});
// register the parse error, but keep going
self.context.register_error(self.describe_parse_error());
String::new()
@ -1750,13 +1811,18 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
let result = this.expression();
this.annotate(arg_start, || Annotation::ProcArgument(arguments.len()));
match result {
Ok(Some(expr)) => { arguments.push(expr); SUCCESS },
Ok(Some(expr)) => {
arguments.push(expr);
SUCCESS
}
Ok(None) => Ok(None),
Err(e) => Err(e),
}
});
let end = self.location; // location of the closing parenthesis
self.annotate_precise(start..end, || Annotation::ProcArguments(parents.to_owned(), proc.to_owned(), arguments.len()));
self.annotate_precise(start..end, || {
Annotation::ProcArguments(parents.to_owned(), proc.to_owned(), arguments.len())
});
match result {
Ok(Some(_)) => success(arguments),
Ok(None) => Ok(None),
@ -1766,17 +1832,28 @@ impl<'ctx, 'an, I> Parser<'ctx, 'an, I> where
fn pick_arguments(&mut self) -> Status<Vec<(Option<Expression>, Expression)>> {
leading!(self.exact(Token::Punct(Punctuation::LParen)));
success(require!(self.separated(Punctuation::Comma, Punctuation::RParen, None, |this| {
let expr = leading!(this.expression());
if let Some(()) = this.exact(Token::Punct(Punctuation::Semicolon))? {
success((Some(expr), require!(this.expression())))
} else {
success((None, expr))
success(require!(self.separated(
Punctuation::Comma,
Punctuation::RParen,
None,
|this| {
let expr = leading!(this.expression());
if let Some(()) = this.exact(Token::Punct(Punctuation::Semicolon))? {
success((Some(expr), require!(this.expression())))
} else {
success((None, expr))
}
}
})))
)))
}
fn separated<R: Clone, F: FnMut(&mut Self) -> Status<R>>(&mut self, sep: Punctuation, terminator: Punctuation, allow_empty: Option<R>, mut f: F) -> Status<Vec<R>> {
fn separated<R: Clone, F: FnMut(&mut Self) -> Status<R>>(
&mut self,
sep: Punctuation,
terminator: Punctuation,
allow_empty: Option<R>,
mut f: F,
) -> Status<Vec<R>> {
let mut comma_legal = false;
let mut elems = Vec::new();
loop {

View file

@ -115,12 +115,14 @@ impl DefineMap {
return false;
}
self.inner.iter().all(|(key, value)| rhs.inner.get(key).map_or(false, |v| {
if value.len() != v.len() {
return false;
}
value.iter().zip(v.iter()).all(|(lhs, rhs)| lhs.1 == rhs.1)
}))
self.inner.iter().all(|(key, value)| {
rhs.inner.get(key).map_or(false, |v| {
if value.len() != v.len() {
return false;
}
value.iter().zip(v.iter()).all(|(lhs, rhs)| lhs.1 == rhs.1)
})
})
}
}
@ -138,7 +140,7 @@ enum Include<'ctx> {
name: String,
location: Location,
tokens: VecDeque<Token>,
}
},
}
impl<'ctx> Include<'ctx> {
@ -210,11 +212,15 @@ impl<'ctx> Iterator for IncludeStack<'ctx> {
//Some(Err(e)) => return Some(Err(e)),
Some(t) => return Some(t),
None => {} // fall through
}
Some(&mut Include::Expansion { ref mut tokens, location, .. }) => match tokens.pop_front() {
},
Some(&mut Include::Expansion {
ref mut tokens,
location,
..
}) => match tokens.pop_front() {
Some(token) => return Some(LocatedToken { location, token }),
None => {} // fall through
}
},
None => return None,
}
self.stack.pop();
@ -234,13 +240,25 @@ struct Ifdef {
impl Ifdef {
fn new(location: Location, active: bool) -> Ifdef {
Ifdef { location, active, chain_active: active }
Ifdef {
location,
active,
chain_active: active,
}
}
fn else_(self, location: Location) -> Ifdef {
Ifdef { location, active: !self.chain_active, chain_active: true }
Ifdef {
location,
active: !self.chain_active,
chain_active: true,
}
}
fn else_if(self, location: Location, active: bool) -> Ifdef {
Ifdef { location, active: !self.chain_active && active, chain_active: self.chain_active || active }
Ifdef {
location,
active: !self.chain_active && active,
chain_active: self.chain_active || active,
}
}
}
@ -296,9 +314,7 @@ impl<'ctx> Preprocessor<'ctx> {
Ok(Preprocessor {
context,
env_file,
include_stack: IncludeStack {
stack: vec![include],
},
include_stack: IncludeStack { stack: vec![include] },
history: Default::default(),
defines,
maps: Default::default(),
@ -462,7 +478,7 @@ impl<'ctx> Preprocessor<'ctx> {
self.last_input_loc = tok.location;
if let Token::Punct(Punctuation::Newline) = tok.token {
break
break;
}
if let Err(e) = self.real_next(tok.token, true) {
@ -470,8 +486,10 @@ impl<'ctx> Preprocessor<'ctx> {
}
}
let mut parser = ::parser::Parser::new(self.context,
self.output.drain(..).map(|token| LocatedToken::new(start, token)));
let mut parser = ::parser::Parser::new(
self.context,
self.output.drain(..).map(|token| LocatedToken::new(start, token)),
);
parser.set_fallback_location(start);
let expr = parser.expression();
let expr = parser.require(expr)?;
@ -519,10 +537,13 @@ impl<'ctx> Preprocessor<'ctx> {
macro_rules! next {
() => {
match self.inner_next() {
Some(x) => { _last_expected_loc = x.location; x.token },
None => return Err(self.error("unexpected EOF"))
Some(x) => {
_last_expected_loc = x.location;
x.token
}
None => return Err(self.error("unexpected EOF")),
}
}
};
}
macro_rules! expect_token {
(($($i:ident),*) = $p:pat) => {
@ -590,17 +611,27 @@ impl<'ctx> Preprocessor<'ctx> {
self.include_stack.top_file_path().parent().unwrap().join(&path),
path,
].into_iter().rev() {
if !candidate.exists() { continue }
if !candidate.exists() {
continue;
}
// Double-match is used to let go of the borrow of
// `candidate` so it can be used in the second half.
enum FileType { DMM, DMF, DMS, DM }
enum FileType {
DMM,
DMF,
DMS,
DM,
}
match match candidate.extension().and_then(|s| s.to_str()) {
Some("dmm") => FileType::DMM,
Some("dmf") => FileType::DMF,
Some("dms") => FileType::DMS,
Some("dm") => FileType::DM,
Some(ext) => {
self.context.register_error(DMError::new(self.last_input_loc, format!("unknown extension {:?}", ext)));
self.context.register_error(DMError::new(
self.last_input_loc,
format!("unknown extension {:?}", ext),
));
return Ok(());
}
None => {
@ -669,7 +700,7 @@ impl<'ctx> Preprocessor<'ctx> {
params.push("__VA_ARGS__".to_owned()); // default
variadic = true;
}
_ => return Err(self.error("malformed macro parameters, expected name"))
_ => return Err(self.error("malformed macro parameters, expected name")),
}
match next!() {
Token::Punct(Punctuation::Comma) => {}
@ -681,7 +712,7 @@ impl<'ctx> Preprocessor<'ctx> {
_ => return Err(self.error("only the last parameter of a macro may be variadic"))
}
}
_ => return Err(self.error("malformed macro parameters, expected comma"))
_ => return Err(self.error("malformed macro parameters, expected comma")),
}
}
}
@ -849,7 +880,7 @@ impl<'ctx> Preprocessor<'ctx> {
}
}
if args.len() != params.len() {
return Err(self.error("wrong number of arguments to macro call"))
return Err(self.error("wrong number of arguments to macro call"));
}
// paste them into the expansion
@ -871,7 +902,10 @@ impl<'ctx> Preprocessor<'ctx> {
let mut arg = args[i].iter().cloned();
match arg.next() {
Some(Token::Ident(second, ws)) => {
expansion.push_back(Token::Ident(format!("{}{}", first, second), ws));
expansion.push_back(Token::Ident(
format!("{}{}", first, second),
ws,
));
}
Some(other) => {
expansion.push_back(Token::Ident(first, ws1));

View file

@ -20,12 +20,15 @@ fn floats() {
#[test]
fn nested_interpolation() {
assert_eq!(lex(r#""A[B"C"D]E""#), vec![
InterpStringBegin("A".into()),
Ident("B".into(), false),
String("C".into()),
Ident("D".into(), false),
InterpStringEnd("E".into()),
Punct(Newline),
]);
assert_eq!(
lex(r#""A[B"C"D]E""#),
vec![
InterpStringBegin("A".into()),
Ident("B".into(), false),
String("C".into()),
Ident("D".into(), false),
InterpStringEnd("E".into()),
Punct(Newline),
]
);
}

View file

@ -62,7 +62,11 @@ fn reconstruct(tokens: &[LocatedToken], iffy: bool) -> String {
let this_line = &mut reconstructed[line];
if this_line.len() > column && !iffy {
panic!("column numbers went backwards: line {}, so far {:?}", line + 1, this_line);
panic!(
"column numbers went backwards: line {}, so far {:?}",
line + 1,
this_line
);
}
while this_line.len() < column {
this_line.push(' ');

View file

@ -31,7 +31,11 @@ fn check_indentor() {
let context = Context::default();
with_test_dme(&context, |mut preprocessor| {
let mut string = Vec::new();
pretty_print(&mut string, indents::IndentProcessor::new(&context, &mut preprocessor).map(|t| t.token), true).unwrap();
pretty_print(
&mut string,
indents::IndentProcessor::new(&context, &mut preprocessor).map(|t| t.token),
true,
).unwrap();
context.assert_success();
});
}

View file

@ -7,7 +7,8 @@ fn main() {
let out_dir = env::var("OUT_DIR").ok().expect("can't find out_dir");
if cfg!(target_env="msvc") {
if let Err(e) = Command::new("windres").args(&["res/editor.rc", "-o"])
if let Err(e) = Command::new("windres")
.args(&["res/editor.rc", "-o"])
.arg(&format!("{}/editor_rc.lib", out_dir))
.status()
{
@ -15,16 +16,19 @@ fn main() {
return;
}
} else {
if let Err(e) = Command::new("windres").args(&["res/editor.rc", "-o"])
if let Err(e) = Command::new("windres")
.args(&["res/editor.rc", "-o"])
.arg(&format!("{}/editor.rc.o", out_dir))
.status()
{
println!("cargo:warning=`windres` unavailable: {}", e);
return;
}
Command::new("ar").args(&["crus", "libeditor_rc.a", "editor.rc.o"])
Command::new("ar")
.args(&["crus", "libeditor_rc.a", "editor.rc.o"])
.current_dir(Path::new(&out_dir))
.status().unwrap();
.status()
.unwrap();
}
println!("cargo:rerun-if-changed=editor.rc");

View file

@ -20,7 +20,7 @@ impl Config {
pub fn make_recent(&mut self, recent: &Path) {
if let Some(first) = self.recent.first() {
if first == recent {
return // no work to do
return; // no work to do
}
}
@ -63,10 +63,12 @@ fn save(cfg: &Config, path: &Path) -> io::Result<()> {
use serde::Serialize;
let mut buffer = String::new();
cfg.serialize(::toml::ser::Serializer::new(&mut buffer)
.pretty_string(true)
.pretty_string_literal(false)
.pretty_array(true)).unwrap();
cfg.serialize(
::toml::ser::Serializer::new(&mut buffer)
.pretty_string(true)
.pretty_string_literal(false)
.pretty_array(true),
).unwrap();
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;

View file

@ -53,7 +53,13 @@ impl IconCache {
}
pub fn get_index(&self, relative_file_path: &Path) -> Option<usize> {
let existing = self.lock.read().expect("IconCache poisoned").paths.get(relative_file_path).cloned();
let existing = self
.lock
.read()
.expect("IconCache poisoned")
.paths
.get(relative_file_path)
.cloned();
// shouldn't be inlined or the lifetime of the lock will be extended
match existing {
// inner None = failure to load, don't keep trying every time
@ -72,7 +78,7 @@ impl IconCache {
lock.paths.insert(relative_file_path.to_owned(), None);
None
}
}
},
}
}
@ -174,7 +180,7 @@ impl IconFile {
}
let state_index = match self.metadata.state_names.get(icon_state) {
Some(&i) => i,
None => return None
None => return None,
};
let state = &self.metadata.states[state_index];
@ -193,8 +199,12 @@ impl IconFile {
let icon_index = state.offset as u32 + dir_idx;
let icon_count = self.width / self.metadata.width;
let (icon_x, icon_y) = (icon_index % icon_count, icon_index / icon_count);
Some((icon_x * self.metadata.width, icon_y * self.metadata.height,
self.metadata.width, self.metadata.height))
Some((
icon_x * self.metadata.width,
icon_y * self.metadata.height,
self.metadata.width,
self.metadata.height,
))
}
}

View file

@ -25,9 +25,7 @@ struct Edit<T, E> {
impl<T, E> History<T, E> {
pub fn new(desc: String, current: T) -> Self {
let mut graph = Graph::default();
let idx = graph.add_node(Entry {
desc,
});
let idx = graph.add_node(Entry { desc });
History {
current,
idx,
@ -85,7 +83,10 @@ impl<T, E> History<T, E> {
}
pub fn can_redo(&self) -> bool {
self.graph.neighbors_directed(self.idx, Direction::Outgoing).next().is_some()
self.graph
.neighbors_directed(self.idx, Direction::Outgoing)
.next()
.is_some()
}
pub fn redo(&mut self, env: &E) {

View file

@ -137,7 +137,7 @@ enum MapState {
Active {
merge_base: Arc<Map>,
hist: History,
}
},
}
struct NewMap {
@ -325,11 +325,18 @@ impl EditorScene {
for _ in 0..z {
map.rendered.push(None);
}
MapState::Active { merge_base, hist: History::new("Loaded".to_owned(), val) }
MapState::Active {
merge_base,
hist: History::new("Loaded".to_owned(), val),
}
} else {
MapState::Preparing(merge_base, rx)
},
MapState::Refreshing { merge_base, mut hist, rx } => if let Ok(val) = rx.try_recv() {
MapState::Refreshing {
merge_base,
mut hist,
rx,
} => if let Ok(val) = rx.try_recv() {
hist.replace_current(val);
MapState::Active { merge_base, hist }
} else {
@ -376,16 +383,23 @@ impl EditorScene {
fn run_ui(&mut self, ui: &Ui, renderer: &mut ImRenderer) -> bool {
for tool in self.tools.iter_mut() {
tool.icon.prepare(self.environment.as_ref(), &mut tools::IconCtx::new(renderer, &mut self.map_renderer));
tool.icon.prepare(
self.environment.as_ref(),
&mut tools::IconCtx::new(renderer, &mut self.map_renderer),
);
}
#[cfg(not(target_os = "macos"))]
macro_rules! ctrl_shortcut {
($rest:expr) => (im_str!("Ctrl+{}", $rest))
($rest:expr) => {
im_str!("Ctrl+{}", $rest)
};
}
#[cfg(target_os = "macos")]
macro_rules! ctrl_shortcut {
($rest:expr) => (im_str!("Cmd+{}", $rest))
($rest:expr) => {
im_str!("Cmd+{}", $rest)
};
}
let mut continue_running = true;
@ -580,7 +594,12 @@ impl EditorScene {
self.counter = self.counter.wrapping_add(1);
let mut i = 0;
macro_rules! spinner {
() => (SPINNER[(self.counter / 10 + { i += 1; i }) % SPINNER.len()])
() => {
SPINNER[(self.counter / 10 + {
i += 1;
i
}) % SPINNER.len()]
};
}
if let Some(loading) = self.loading_env.as_ref() {
@ -675,17 +694,24 @@ impl EditorScene {
for (map_idx, map) in self.maps.iter_mut().enumerate() {
let dirty = map.state.hist().map_or(false, |h| h.is_dirty());
let title = match map.path {
Some(ref path) => format!("{}{}##map_{}", file_name(path), if dirty { " *" } else { "" }, path.display()),
Some(ref path) => format!(
"{}{}##map_{}",
file_name(path),
if dirty { " *" } else { "" },
path.display()
),
None => format!("Untitled##{}", map_idx),
};
if ui.collapsing_header(&ImString::from(title)).default_open(true).build() {
if let Some(hist) = map.state.hist() {
let world = hist.current();
if let Some(dmm) = map.state.base_dmm() {
ui.text(im_str!("{:?}; {}-keys: {}",
ui.text(im_str!(
"{:?}; {}-keys: {}",
world.dim_xyz(),
dmm.key_length,
dmm.dictionary.len()));
dmm.dictionary.len()
));
} else {
ui.text(im_str!("{:?}", world.dim_xyz()));
}
@ -696,10 +722,12 @@ impl EditorScene {
}
}
} else if let Some(dmm) = map.state.base_dmm() {
ui.text(im_str!("{:?}; {}-keys: {}",
ui.text(im_str!(
"{:?}; {}-keys: {}",
dmm.dim_xyz(),
dmm.key_length,
dmm.dictionary.len()));
dmm.dictionary.len()
));
}
}
}
@ -797,13 +825,21 @@ impl EditorScene {
for _ in 0..new_map.z {
rendered.push(None);
}
let dmm = Map::new(new_map.x as usize, new_map.y as usize, new_map.z as usize,
env.turf.clone(), env.area.clone());
let dmm = Map::new(
new_map.x as usize,
new_map.y as usize,
new_map.z as usize,
env.turf.clone(),
env.area.clone(),
);
let atom_map = map_repr::AtomMap::new(&dmm, &env.icons, &env.objtree);
let desc = format!("New {}x{}x{} map", new_map.x, new_map.y, new_map.z);
self.maps.push(EditorMap {
path: None,
state: MapState::Active { merge_base: Arc::new(dmm), hist: History::new(desc, atom_map) },
state: MapState::Active {
merge_base: Arc::new(dmm),
hist: History::new(desc, atom_map),
},
z_current: 0,
center: [new_map.x as f32 * 16.0, new_map.y as f32 * 16.0],
rendered,
@ -814,7 +850,11 @@ impl EditorScene {
opened = false;
}
}
if opened && !closed { Some(new_map) } else { None }
if opened && !closed {
Some(new_map)
} else {
None
}
});
if let Some(map) = self.maps.get_mut(self.map_current) {
@ -828,7 +868,10 @@ impl EditorScene {
let mut keep = true;
let mut keep2 = true;
let EditInstance { ref mut inst, ref mut base } = edit;
let EditInstance {
ref mut inst,
ref mut base,
} = edit;
ui.window(im_str!("{}##{}/{:?}", base.fab.path, uid, inst))
.opened(&mut keep)
.position(ui.imgui().mouse_pos(), ImGuiCond::Appearing)
@ -883,11 +926,18 @@ impl EditorScene {
.always_auto_resize(true)
.opened(&mut opened)
.build(|| {
ui.text(im_str!("maps[{}], map = {}, zoom = {}",
ui.text(im_str!(
"maps[{}], map = {}, zoom = {}",
self.maps.len(),
self.map_current, self.map_renderer.zoom));
self.map_current,
self.map_renderer.zoom
));
if let Some(env) = self.environment.as_ref() {
ui.text(im_str!("types[{}], icons[{}]", env.objtree.graph.node_count(), env.icons.len()));
ui.text(im_str!(
"types[{}], icons[{}]",
env.objtree.graph.node_count(),
env.icons.len()
));
ui.text(im_str!("turf = {}", env.turf));
ui.text(im_str!("area = {}", env.area));
}
@ -896,7 +946,12 @@ impl EditorScene {
if let Some(hist) = map.state.hist() {
let current = hist.current();
if let Some(level) = current.levels.get(map.z_current) {
ui.text(im_str!("draw_calls[{}], pops[{}], atoms[{}]", level.draw_calls.len(), current.pops.len(), level.instances.len()));
ui.text(im_str!(
"draw_calls[{}], pops[{}], atoms[{}]",
level.draw_calls.len(),
current.pops.len(),
level.instances.len()
));
}
}
if let Some(rendered) = map.rendered.get(map.z_current).and_then(|x| x.as_ref()) {
@ -950,7 +1005,7 @@ impl EditorScene {
let ty = ((map.center[1].round() + (cy as f32 - y as f32) / self.map_renderer.zoom) / 32.0).floor() as i32;
let (dim_x, dim_y, _) = hist.current().dim_xyz();
if tx >= 0 && ty >= 0 && tx < dim_x as i32 && ty < dim_y as i32 {
return Some((tx as u32, ty as u32))
return Some((tx as u32, ty as u32));
}
}
}
@ -1078,21 +1133,22 @@ impl EditorScene {
Ok(Environment {
objtree: Arc::new(objtree),
icons: Arc::new(IconCache::new(
path.parent().expect("invalid environment file path"))),
icons: Arc::new(IconCache::new(path.parent().expect("invalid environment file path"))),
turf,
area,
path,
})
});
self.loading_env = Some(LoadingEnvironment {
path: path2,
rx,
});
self.loading_env = Some(LoadingEnvironment { path: path2, rx });
}
fn new_map(&mut self) {
self.new_map = Some(NewMap { x: 32, y: 32, z: 1, created: false });
self.new_map = Some(NewMap {
x: 32,
y: 32,
z: 1,
created: false,
});
}
fn open_map(&mut self) {
@ -1297,7 +1353,10 @@ impl EditPrefab {
}
fn show(&mut self, ui: &Ui, env: Option<&Environment>, extra_vars: bool) {
let EditPrefab { ref mut filter, ref mut fab } = self;
let EditPrefab {
ref mut filter,
ref mut fab,
} = self;
// find the "best" type by chopping the path if needed
let (red_paths, ty) = if let Some(env) = env.as_ref() {
@ -1401,7 +1460,7 @@ fn root_node(ui: &Ui, ty: TypeRef, name: &str) {
fn tree_node(ui: &Ui, ty: TypeRef) {
let mut children = ty.children();
if children.is_empty() {
ui.tree_node(im_str!("{}", ty.name)).leaf(true).build(||{});
ui.tree_node(im_str!("{}", ty.name)).leaf(true).build(|| {});
} else {
children.sort_by_key(|t| &t.get().name);
ui.tree_node(im_str!("{}", ty.name)).build(|| {
@ -1446,15 +1505,19 @@ fn prepare_tool_icon(
) -> tools::ToolIcon {
use tools::ToolIcon;
match icon {
ToolIcon::Dmi { icon, icon_state, tint, dir } => if let Some(env) = environment {
ToolIcon::Dmi {
icon,
icon_state,
tint,
dir,
} => if let Some(env) = environment {
if let Some(id) = env.icons.get_index(icon.as_ref()) {
let icon = env.icons.get_icon(id);
if let Some([u1, v1, u2, v2]) = icon.uv_of(&icon_state, dir) {
let tex = map_renderer.icon_textures.retrieve(
&mut map_renderer.factory,
&env.icons,
id,
).clone();
let tex = map_renderer
.icon_textures
.retrieve(&mut map_renderer.factory, &env.icons, id)
.clone();
let samp = map_renderer.sampler.clone();
ToolIcon::Loaded {
tex: renderer.textures().insert((tex, samp)),
@ -1469,7 +1532,12 @@ fn prepare_tool_icon(
ToolIcon::None
}
} else {
ToolIcon::Dmi { icon, icon_state, tint, dir }
ToolIcon::Dmi {
icon,
icon_state,
tint,
dir,
}
},
ToolIcon::EmbeddedPng { data } => if let Ok(tex) = dmi::texture_from_bytes(&mut map_renderer.factory, data) {
let samp = map_renderer.sampler.clone();

View file

@ -92,7 +92,8 @@ impl MapRenderer {
let sampler = factory.create_sampler(gfx::texture::SamplerInfo::new(
gfx::texture::FilterMethod::Scale,
gfx::texture::WrapMode::Clamp));
gfx::texture::WrapMode::Clamp,
));
MapRenderer {
icons: Arc::new(IconCache::new(".".as_ref())),
@ -164,7 +165,16 @@ impl RenderedMap {
encoder.update_buffer(&self.ibuf, ibuf_data, 0).expect("update ibuf");
}
pub fn paint(&mut self, parent: &mut MapRenderer, map: &AtomMap, z: u32, center: [f32; 2], factory: &mut Factory, encoder: &mut Encoder, view: &RenderTargetView) {
pub fn paint(
&mut self,
parent: &mut MapRenderer,
map: &AtomMap,
z: u32,
center: [f32; 2],
factory: &mut Factory,
encoder: &mut Encoder,
view: &RenderTargetView,
) {
// update vertex and index buffers from the map
if map.levels[z as usize].buffers_dirty.replace(false) {
self.update_buffers(map, z, factory, encoder);
@ -178,9 +188,11 @@ impl RenderedMap {
[0.0, 2.0 / y as f32, 0.0, -2.0 * center[1].round() / y as f32],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0 / parent.zoom],
]
],
};
encoder.update_buffer(&parent.transform_buffer, &[transform], 0).expect("update_buffer failed");
encoder
.update_buffer(&parent.transform_buffer, &[transform], 0)
.expect("update_buffer failed");
let mut start = 0;
for call in map.levels[z as usize].draw_calls.iter() {
@ -188,7 +200,9 @@ impl RenderedMap {
start += call.len;
continue;
}
let texture = parent.icon_textures.retrieve(factory, &parent.icons, call.texture as usize);
let texture = parent
.icon_textures
.retrieve(factory, &parent.icons, call.texture as usize);
let slice = gfx::Slice {
start: start,
end: start + call.len,
@ -267,8 +281,11 @@ impl RenderPop {
let color = minimap::color_of(objtree, fab);
let color = [
color[0] as f32 / 255.0, color[1] as f32 / 255.0,
color[2] as f32 / 255.0, color[3] as f32 / 255.0];
color[0] as f32 / 255.0,
color[1] as f32 / 255.0,
color[2] as f32 / 255.0,
color[3] as f32 / 255.0,
];
let pixel_x = fab.get_var("pixel_x", objtree).to_int().unwrap_or(0);
let pixel_y = fab.get_var("pixel_y", objtree).to_int().unwrap_or(0);

View file

@ -103,7 +103,8 @@ impl AtomMap {
let mut coords = HashMap::<(usize, usize, usize), Vec<&Prefab>>::new();
for (z, level) in self.levels.iter().enumerate() {
for (_, inst) in level.instances.keys_iter() {
coords.entry((inst.x as usize, (self.size.1 - 1 - inst.y) as usize, z as usize))
coords
.entry((inst.x as usize, (self.size.1 - 1 - inst.y) as usize, z as usize))
.or_default()
.push(&inst.pop);
}
@ -181,7 +182,10 @@ impl AtomMap {
key
} else {
let rc = Arc::new(prefab.to_owned());
self.pops.insert(rc.clone(), RenderPop::from_prefab(icons, objtree, &prefab).unwrap_or_default());
self.pops.insert(
rc.clone(),
RenderPop::from_prefab(icons, objtree, &prefab).unwrap_or_default(),
);
rc
}
}
@ -245,7 +249,9 @@ impl AtomMap {
let (draw_call, start) = find_draw_call(draw_calls, pos);
// extend the draw call or insert a new one
let rpop = pops.get(&instances.get_key(new_instance).pop).expect("instance with missing pop");
let rpop = pops
.get(&instances.get_key(new_instance).pop)
.expect("instance with missing pop");
if pos == start {
// in between two calls
if draw_call > 0 && draw_calls[draw_call - 1].can_contain(rpop) {
@ -315,7 +321,10 @@ impl AtomMap {
self.add_instance((removed.old.x, removed.old.y, removed.z), pop);
}
pub fn iter_instances<'a>(&'a self, (x, y, z): (u32, u32, u32)) -> impl Iterator<Item=(InstanceId, &'a Prefab)> + 'a {
pub fn iter_instances<'a>(
&'a self,
(x, y, z): (u32, u32, u32),
) -> impl Iterator<Item = (InstanceId, &'a Prefab)> + 'a {
let level = &self.levels[z as usize];
level.sorted_order.iter().rev().filter_map(move |&idx| {
let inst = &level.instances.get_key(idx);
@ -382,8 +391,14 @@ impl AtomMap {
}
impl AtomZ {
fn prep_instance(&mut self, pops: &mut WeakKeyHashMap<Weak<Prefab>, RenderPop>, (x, y): (u32, u32), prefab: Arc<Prefab>) -> usize {
let vertices = pops.get(&prefab)
fn prep_instance(
&mut self,
pops: &mut WeakKeyHashMap<Weak<Prefab>, RenderPop>,
(x, y): (u32, u32),
prefab: Arc<Prefab>,
) -> usize {
let vertices = pops
.get(&prefab)
.map_or_else(|| [Vertex::default(); 4], |rpop| rpop.instance((x, y)));
self.instances.push(Instance { x, y, pop: prefab }, vertices)
}
@ -479,8 +494,10 @@ impl<K, V> DualPool<K, V> {
self.keys.len() - self.freelist.len()
}
pub fn keys_iter<'a>(&'a self) -> impl Iterator<Item=(usize, &'a K)> + 'a {
self.keys.iter().enumerate()
pub fn keys_iter<'a>(&'a self) -> impl Iterator<Item = (usize, &'a K)> + 'a {
self.keys
.iter()
.enumerate()
.filter(move |(i, _)| !self.freelist.contains(i))
}
}

View file

@ -123,7 +123,8 @@ pub fn run(title: String, clear_color: [f32; 4]) -> ::EditorScene {
window_hidpi_factor = new_factor;
hidpi_factor = window_hidpi_factor.round();
frame_size.hidpi_factor = hidpi_factor;
frame_size.logical_size = window.get_inner_size()
frame_size.logical_size = window
.get_inner_size()
.unwrap()
.to_physical(window_hidpi_factor)
.to_logical(hidpi_factor)
@ -162,9 +163,7 @@ pub fn run(title: String, clear_color: [f32; 4]) -> ::EditorScene {
Some(Key::X) => imgui.set_key(16, pressed),
Some(Key::Y) => imgui.set_key(17, pressed),
Some(Key::Z) => imgui.set_key(18, pressed),
Some(Key::LControl) | Some(Key::RControl) => {
imgui.set_key_ctrl(pressed)
}
Some(Key::LControl) | Some(Key::RControl) => imgui.set_key_ctrl(pressed),
Some(Key::LShift) | Some(Key::RShift) => imgui.set_key_shift(pressed),
Some(Key::LAlt) | Some(Key::RAlt) => imgui.set_key_alt(pressed),
Some(Key::LWin) | Some(Key::RWin) => imgui.set_key_super(pressed),
@ -217,7 +216,13 @@ pub fn run(title: String, clear_color: [f32; 4]) -> ::EditorScene {
.to_logical(hidpi_factor);
mouse_state.wheel = diff.y as f32;
if !mouse_captured {
scene.mouse_wheel(ctrl(&imgui), imgui.key_shift(), imgui.key_alt(), diff.x as f32, diff.y as f32);
scene.mouse_wheel(
ctrl(&imgui),
imgui.key_shift(),
imgui.key_alt(),
diff.x as f32,
diff.y as f32,
);
}
},
ReceivedCharacter(c) => imgui.add_input_character(c),

View file

@ -24,7 +24,10 @@ impl<R: Send + 'static> Task<R> {
pub fn poll<F: FnMut(Result<R, Err>)>(&self, mut f: F) -> bool {
match self.rx.try_recv() {
Ok(v) => { f(v); true },
Ok(v) => {
f(v);
true
}
Err(TryRecvError::Empty) => true,
Err(TryRecvError::Disconnected) => false,
}

View file

@ -43,14 +43,11 @@ pub enum ToolIcon {
#[allow(unused_variables)]
pub trait ToolBehavior {
fn settings(&mut self, ui: &Ui, env: &Environment, ctx: &mut IconCtx) {
}
fn settings(&mut self, ui: &Ui, env: &Environment, ctx: &mut IconCtx) {}
fn click(&mut self, hist: &mut History, env: &Environment, loc: (u32, u32, u32)) {
}
fn click(&mut self, hist: &mut History, env: &Environment, loc: (u32, u32, u32)) {}
fn pick(&mut self, env: &Environment, prefab: &Prefab) {
}
fn pick(&mut self, env: &Environment, prefab: &Prefab) {}
}
impl Tool {
@ -73,11 +70,22 @@ impl Tool {
}
fn dmi(self, icon: PathBuf, icon_state: String) -> Self {
Tool { icon: ToolIcon::Dmi { icon, icon_state, tint: NO_TINT, dir: dmi::SOUTH }, ..self }
Tool {
icon: ToolIcon::Dmi {
icon,
icon_state,
tint: NO_TINT,
dir: dmi::SOUTH,
},
..self
}
}
fn png(self, data: &'static [u8]) -> Self {
Tool { icon: ToolIcon::EmbeddedPng { data }, ..self }
Tool {
icon: ToolIcon::EmbeddedPng { data },
..self
}
}
fn build(self, tools: &mut Vec<Tool>) {

View file

@ -15,7 +15,7 @@ enum Visiting {
pub struct RangePairIter<'a, K: 'a, V: 'a> {
start: Bound<K>,
end: Bound<K>,
stack: Vec<(&'a Node<K, V>, Visiting)>
stack: Vec<(&'a Node<K, V>, Visiting)>,
}
impl<'a, K: Ord, V> RangePairIter<'a, K, V> {
@ -73,7 +73,7 @@ impl<'a, K: Ord, V> RangePairIter<'a, K, V> {
self.stack.push((node, Visiting::Right));
} else {
self.stack.push((node, Visiting::Middle(i + 1)));
return Some((node, i))
return Some((node, i));
}
}
}

View file

@ -8,12 +8,19 @@ pub struct Node<K, V> {
height: u32,
pub max: K,
pub left: Option<Box<Node<K, V>>>,
pub right:Option<Box<Node<K, V>>>,
pub right: Option<Box<Node<K, V>>>,
}
impl<K: Ord + Clone, V> Node<K, V> {
pub fn new(key: RangeInclusive<K>, data: V) -> Self {
Node { max: key.end.clone(), key: key, data: vec![data], height: 1, left: None, right: None }
Node {
max: key.end.clone(),
key: key,
data: vec![data],
height: 1,
left: None,
right: None,
}
}
fn diff_of_successors_height(&self) -> i32 {
@ -40,13 +47,13 @@ impl<K: Ord + Clone, V> Node<K, V> {
}
///returns the minimal key,value pair within this tree
pub fn min_pair(&self) -> (&RangeInclusive<K>,&[V]) {
self.left.as_ref().map_or((&self.key,&self.data), |n| n.min_pair())
pub fn min_pair(&self) -> (&RangeInclusive<K>, &[V]) {
self.left.as_ref().map_or((&self.key, &self.data), |n| n.min_pair())
}
///returns the maximal key,value pair within this tree
pub fn max_pair(&self) -> (&RangeInclusive<K>,&[V]) {
self.right.as_ref().map_or((&self.key,&self.data), |n| n.max_pair())
pub fn max_pair(&self) -> (&RangeInclusive<K>, &[V]) {
self.right.as_ref().map_or((&self.key, &self.data), |n| n.max_pair())
}
/// Perform a single right rotation on this (sub) tree
@ -101,7 +108,7 @@ impl<K: Ord + Clone, V> Node<K, V> {
2 => self.rotate_left_successor(),
1 | 0 | -1 => self,
-2 => self.rotate_right_successor(),
_ => unreachable!()
_ => unreachable!(),
}
}
@ -133,7 +140,7 @@ impl<K: Ord + Clone, V> Node<K, V> {
fn drop_min(mut self: Box<Self>) -> (Option<Box<Self>>, Box<Self>) {
match self.left.take() {
Some(left) => Node::drop_min_from_left(self, left),
None => (self.right.take(), self)
None => (self.right.take(), self),
}
}
@ -150,19 +157,19 @@ impl<K: Ord + Clone, V> Node<K, V> {
// empty: None.
//
//
pub fn delete(mut self: Box<Self>, key: RangeInclusive<K>) -> Option<Box<Self>>{
pub fn delete(mut self: Box<Self>, key: RangeInclusive<K>) -> Option<Box<Self>> {
match self.key.cmp(&key) {
Ordering::Equal => return self.delete_root(),
Ordering::Less => {
if let Some(succ) = self.right.take() {
self.right = succ.delete(key);
return Some(self.updated_node())
return Some(self.updated_node());
}
},
Ordering::Greater => {
if let Some(succ) = self.left.take() {
self.left = succ.delete(key);
return Some(self.updated_node())
return Some(self.updated_node());
}
}
}
@ -175,11 +182,11 @@ impl<K: Ord + Clone, V> Node<K, V> {
}
/// returns a read only reference paie to the data stored under key in the tree given by root
pub fn search_pair(&self, key: &RangeInclusive<K>) -> Option<(&RangeInclusive<K>, &[V])>{
pub fn search_pair(&self, key: &RangeInclusive<K>) -> Option<(&RangeInclusive<K>, &[V])> {
match self.key.cmp(key) {
Ordering::Equal => Some((&self.key, &self.data)),
Ordering::Less => self.right.as_ref().map_or(None, |succ| succ.search_pair(key)),
Ordering::Greater => self.left.as_ref().map_or(None, |succ| succ.search_pair(key))
Ordering::Greater => self.left.as_ref().map_or(None, |succ| succ.search_pair(key)),
}
}
@ -201,7 +208,7 @@ impl<K: Ord + Clone, V> Node<K, V> {
fn insert_in_successor(succ: Option<Box<Self>>, key: RangeInclusive<K>, data: V) -> Option<Box<Self>> {
Some(match succ {
Some(succ) => succ.insert(key, data),
None => Box::new(Node::new(key, data))
None => Box::new(Node::new(key, data)),
})
}
}

View file

@ -6,7 +6,7 @@ use iterators::RangePairIter;
/// An interval tree.
#[derive(Debug, Clone)]
pub struct IntervalTree<K, V> {
pub(crate) root: Option<Box<Node<K, V>>>
pub(crate) root: Option<Box<Node<K, V>>>,
}
impl<K, V> Default for IntervalTree<K, V> {

View file

@ -44,11 +44,16 @@ pub fn item_proc(ty: TypeRef, name: &str, _proc: &TypeProc) -> CompletionItem {
CompletionItemKind::Method
}),
detail: Some(ty.pretty_path().to_owned()),
.. Default::default()
..Default::default()
}
}
pub fn items_ty<'a>(results: &mut Vec<CompletionItem>, skip: &mut HashSet<(&str, &'a String)>, ty: TypeRef<'a>, query: &str) {
pub fn items_ty<'a>(
results: &mut Vec<CompletionItem>,
skip: &mut HashSet<(&str, &'a String)>,
ty: TypeRef<'a>,
query: &str,
) {
// type variables
for (name, var) in ty.get().vars.iter() {
if !skip.insert(("var", name)) {
@ -82,7 +87,7 @@ pub fn combine_tree_path<'a, I>(iter: &I, mut absolute: bool, mut parts: &'a [St
}}
// if we're on the right side of a 'var/', start the lookup there
if let Some(i) = parts.iter().position(|x| x == "var") {
parts = &parts[i+1..];
parts = &parts[i + 1..];
absolute = true;
}
// if we're on the right side of a 'list/', start the lookup there
@ -107,7 +112,8 @@ pub fn combine_tree_path<'a, I>(iter: &I, mut absolute: bool, mut parts: &'a [St
impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
pub fn follow_type_path<'b, I>(&'b self, iter: &I, mut parts: &'b [(PathOp, String)]) -> Option<TypePathResult<'b>>
where I: Iterator<Item=(Span, &'a Annotation)> + Clone
where
I: Iterator<Item = (Span, &'a Annotation)> + Clone,
{
// cut off the part of the path we haven't selected
if_annotation! { Annotation::InSequence(idx) in iter; {
@ -121,17 +127,19 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
// use the first path op to select the starting type of the lookup
if parts.is_empty() {
return Some(TypePathResult { ty: self.objtree.root(), decl: None, proc: None });
return Some(TypePathResult {
ty: self.objtree.root(),
decl: None,
proc: None,
});
}
let mut ty = match parts[0].0 {
PathOp::Colon => return None, // never finds anything, apparently?
PathOp::Slash => self.objtree.root(),
PathOp::Dot => {
match self.find_type_context(iter) {
(Some(base), _) => base,
(None, _) => self.objtree.root(),
}
}
PathOp::Dot => match self.find_type_context(iter) {
(Some(base), _) => base,
(None, _) => self.objtree.root(),
},
};
// follow the path ops until we hit 'proc' or 'verb'
@ -236,13 +244,24 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
}
}
pub fn path_completions<'b, I>(&'b self, results: &mut Vec<CompletionItem>, iter: &I, parts: &'b [(PathOp, String)], _last_op: PathOp, query: &str)
where I: Iterator<Item=(Span, &'b Annotation)> + Clone
pub fn path_completions<'b, I>(
&'b self,
results: &mut Vec<CompletionItem>,
iter: &I,
parts: &'b [(PathOp, String)],
_last_op: PathOp,
query: &str,
) where
I: Iterator<Item = (Span, &'b Annotation)> + Clone,
{
// TODO: take last_op into account
match self.follow_type_path(iter, parts) {
// '/datum/<complete types>'
Some(TypePathResult { ty, decl: None, proc: None }) => {
Some(TypePathResult {
ty,
decl: None,
proc: None,
}) => {
// path keywords
for &name in ["proc", "verb"].iter() {
if contains(name, query) {
@ -267,7 +286,11 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
},
// '/datum/proc/<complete procs>'
// TODO: take the path op into acocunt (`/proc` vs `.proc`)
Some(TypePathResult { ty, decl: Some(decl), proc: None }) => {
Some(TypePathResult {
ty,
decl: Some(decl),
proc: None,
}) => {
let mut next = Some(ty);
let mut skip = HashSet::new();
while let Some(ty) = next {
@ -279,10 +302,10 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
// declarations only
let mut proc_decl = match proc.declaration.as_ref() {
Some(decl) => decl,
None => continue
None => continue,
};
if proc_decl.is_verb != (decl == "verb") {
continue
continue;
}
if contains(name, query) {
results.push(item_proc(ty, name, proc));
@ -296,7 +319,8 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
}
pub fn unscoped_completions<'b, I>(&'b self, results: &mut Vec<CompletionItem>, iter: &I, query: &str)
where I: Iterator<Item=(Span, &'b Annotation)> + Clone
where
I: Iterator<Item = (Span, &'b Annotation)> + Clone,
{
let (ty, proc_name) = self.find_type_context(iter);
@ -368,8 +392,14 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
}
}
pub fn scoped_completions<'b, I>(&'b self, results: &mut Vec<CompletionItem>, iter: &I, priors: &[String], query: &str)
where I: Iterator<Item=(Span, &'b Annotation)> + Clone
pub fn scoped_completions<'b, I>(
&'b self,
results: &mut Vec<CompletionItem>,
iter: &I,
priors: &[String],
query: &str,
) where
I: Iterator<Item = (Span, &'b Annotation)> + Clone,
{
let mut next = self.find_scoped_type(iter, priors);
let mut skip = HashSet::new();

View file

@ -38,7 +38,8 @@ impl DocumentStore {
}
}
pub fn change(&mut self,
pub fn change(
&mut self,
doc_id: VersionedTextDocumentIdentifier,
changes: Vec<TextDocumentContentChangeEvent>,
) -> Result<PathBuf, jsonrpc::Error> {
@ -48,7 +49,7 @@ impl DocumentStore {
// the client and the file is not open in the editor (the server has
// not received an open notification before) the server can send `null`
// to indicate that the version is known and the content on disk is the
// truth (as speced with document content ownership)."
// truth (as speced with document content ownership)."
let new_version = match doc_id.version {
Some(version) => version,
None => return Err(invalid_request("don't know how to deal with this")),
@ -103,7 +104,10 @@ struct Document {
impl Document {
fn new(version: u64, text: String) -> Document {
Document { version, text: Rc::new(text) }
Document {
version,
text: Rc::new(text),
}
}
fn change(&mut self, change: TextDocumentContentChangeEvent) -> Result<(), jsonrpc::Error> {
@ -118,7 +122,7 @@ impl Document {
};
let start_pos = total_offset(&self.text, range.start.line, range.start.character)?;
Rc::make_mut(&mut self.text).replace_range(start_pos .. start_pos + range_length as usize, &change.text);
Rc::make_mut(&mut self.text).replace_range(start_pos..start_pos + range_length as usize, &change.text);
Ok(())
}
}
@ -150,7 +154,7 @@ pub fn find_word(text: &str, offset: usize) -> &str {
start_next -= 1;
}
if !text[start_next..start].chars().next().map_or(false, is_ident) {
break
break;
}
start = start_next;
}
@ -163,7 +167,7 @@ pub fn find_word(text: &str, offset: usize) -> &str {
end_next += 1;
}
if !text[end..end_next].chars().next().map_or(false, is_ident) {
break
break;
}
end = end_next;
}
@ -212,5 +216,7 @@ impl BufRead for Cursor {
let amt = ::std::cmp::min(self.pos, self.inner.as_ref().len() as u64);
Ok(&self.inner.as_bytes()[(amt as usize)..])
}
fn consume(&mut self, amt: usize) { self.pos += amt as u64; }
fn consume(&mut self, amt: usize) {
self.pos += amt as u64;
}
}

View file

@ -20,25 +20,25 @@ impl RequestRead for StdIo {
Ok(x) => x,
Err(e) => {
eprintln!("{:?}", e);
return None
return None;
}
}
}
};
}
// read the content-length
let mut buffer = String::new();
check!(io::stdin().read_line(&mut buffer));
if buffer.is_empty() {
return None
return None;
}
let size = {
let parts: Vec<&str> = buffer.split(' ').collect();
if parts.len() != 2 {
return None
return None;
}
if !parts[0].eq_ignore_ascii_case("content-length:") {
return None
return None;
}
check!(usize::from_str_radix(parts[1].trim(), 10))
};

View file

@ -41,7 +41,10 @@ use dm::objtree::TypeRef;
fn main() {
std::env::set_var("RUST_BACKTRACE", "1");
eprintln!("dm-langserver {} Copyright (C) 2017-2018 Tad Hardesty", env!("CARGO_PKG_VERSION"));
eprintln!(
"dm-langserver {} Copyright (C) 2017-2018 Tad Hardesty",
env!("CARGO_PKG_VERSION")
);
eprintln!("This program comes with ABSOLUTELY NO WARRANTY. This is free software,");
eprintln!("and you are welcome to redistribute it under the conditions of the GNU");
eprintln!("General Public License version 3.");
@ -110,7 +113,8 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
// ------------------------------------------------------------------------
// General input and output utilities
fn issue_notification<T>(&mut self, params: T::Params) where
fn issue_notification<T>(&mut self, params: T::Params)
where
T: langserver::notification::Notification,
T::Params: serde::Serialize,
{
@ -198,7 +202,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
message: err.description().to_owned(),
.. Default::default()
}],
}
},
);
eprintln!("{:?}", err);
return Ok(());
@ -210,7 +214,11 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
self.preprocessor = Some(pp);
self.issue_notification::<extras::WindowStatus>(Default::default());
let elapsed = start.elapsed();
eprintln!("parsed in {}.{:03}s", elapsed.as_secs(), elapsed.subsec_nanos() / 1_000_000);
eprintln!(
"parsed in {}.{:03}s",
elapsed.as_secs(),
elapsed.subsec_nanos() / 1_000_000
);
// initial diagnostics pump
let mut map: HashMap<_, Vec<_>> = HashMap::new();
@ -240,7 +248,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
langserver::PublishDiagnosticsParams {
uri: path_to_url(joined_path)?,
diagnostics,
}
},
);
}
@ -279,7 +287,8 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
}
fn find_type_context<'b, I, Ign>(&self, iter: &I) -> (Option<TypeRef>, Option<(&'b str, usize)>)
where I: Iterator<Item=(Ign, &'b Annotation)> + Clone
where
I: Iterator<Item = (Ign, &'b Annotation)> + Clone,
{
let mut found = None;
let mut proc_name = None;
@ -314,14 +323,24 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
(found, proc_name)
}
fn find_unscoped_var<'b, I>(&'b self, iter: &I, ty: Option<TypeRef<'b>>, proc_name: Option<(&'b str, usize)>, var_name: &str) -> UnscopedVar<'b>
where I: Iterator<Item=(Span, &'b Annotation)> + Clone
fn find_unscoped_var<'b, I>(
&'b self,
iter: &I,
ty: Option<TypeRef<'b>>,
proc_name: Option<(&'b str, usize)>,
var_name: &str,
) -> UnscopedVar<'b>
where
I: Iterator<Item = (Span, &'b Annotation)> + Clone,
{
// local variables
for (span, annotation) in iter.clone() {
if let Annotation::LocalVarScope(var_type, name) = annotation {
if name == var_name {
return UnscopedVar::Local { loc: span.start, var_type }
return UnscopedVar::Local {
loc: span.start,
var_type,
};
}
}
}
@ -386,7 +405,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
next = self.objtree.type_by_path(&decl.var_type.type_path);
}
} else {
break
break;
}
}
next
@ -402,17 +421,15 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
let mut outputs: Vec<Output> = match serde_json::from_str(&message) {
Ok(Request::Single(call)) => self.handle_call(call).into_iter().collect(),
Ok(Request::Batch(calls)) => calls.into_iter().flat_map(|call| self.handle_call(call)).collect(),
Err(decode_error) => {
vec![Output::Failure(jsonrpc::Failure {
jsonrpc: VERSION,
error: jsonrpc::Error {
code: jsonrpc::ErrorCode::ParseError,
message: decode_error.to_string(),
data: None,
},
id: jsonrpc::Id::Null,
})]
}
Err(decode_error) => vec![Output::Failure(jsonrpc::Failure {
jsonrpc: VERSION,
error: jsonrpc::Error {
code: jsonrpc::ErrorCode::ParseError,
message: decode_error.to_string(),
data: None,
},
id: jsonrpc::Id::Null,
})],
};
let response = match outputs.len() {
@ -427,9 +444,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
fn handle_call(&mut self, call: Call) -> Option<Output> {
match call {
Call::Invalid(id) => {
Some(Output::invalid_request(id, VERSION))
},
Call::Invalid(id) => Some(Output::invalid_request(id, VERSION)),
Call::MethodCall(method_call) => {
let id = method_call.id.clone();
Some(Output::from(self.handle_method_call(method_call), id, VERSION))
@ -1003,7 +1018,7 @@ fn value_to_params(value: serde_json::Value) -> jsonrpc::Params {
serde_json::Value::Null => jsonrpc::Params::None,
serde_json::Value::Array(x) => jsonrpc::Params::Array(x),
serde_json::Value::Object(x) => jsonrpc::Params::Map(x),
_ => panic!("bad value to params conversion")
_ => panic!("bad value to params conversion"),
}
}

View file

@ -14,20 +14,20 @@ impl Query {
/// Parse a symbol query.
pub fn parse(query: &str) -> Option<Query> {
if !any_alphanumeric(query) {
return None
return None;
}
Some(if query.starts_with("#") {
Query::Define(query[1..].to_lowercase())
} else if query.starts_with("var/") {
let query = &query["var/".len()..];
if !any_alphanumeric(query) {
return None
return None;
}
Query::Var(query.to_lowercase())
} else if query.starts_with("proc/") {
let query = &query["proc/".len()..];
if !any_alphanumeric(query) {
return None
return None;
}
Query::Proc(query.to_lowercase())
} else if query.contains("/") {

View file

@ -64,7 +64,7 @@ impl IconFile {
pub fn rect_of(&self, icon_state: &str, dir: i32) -> Option<Rect> {
let state_index = match self.metadata.state_names.get(icon_state) {
Some(&i) => i,
None => return None
None => return None,
};
let state = &self.metadata.states[state_index];
@ -83,12 +83,15 @@ impl IconFile {
let icon_index = state.offset as u32 + dir_idx;
let icon_count = self.image.width / self.metadata.width;
let (icon_x, icon_y) = (icon_index % icon_count, icon_index / icon_count);
Some((icon_x * self.metadata.width, icon_y * self.metadata.height,
self.metadata.width, self.metadata.height))
Some((
icon_x * self.metadata.width,
icon_y * self.metadata.height,
self.metadata.width,
self.metadata.height,
))
}
}
// ----------------------------------------------------------------------------
// Image manipulation
@ -163,19 +166,26 @@ impl Image {
use ndarray::Axis;
let mut destination = self.data.slice_mut(s![
pos.1 as isize .. (pos.1 + crop.3) as isize,
pos.0 as isize .. (pos.0 + crop.2) as isize,
..]);
pos.1 as isize..(pos.1 + crop.3) as isize,
pos.0 as isize..(pos.0 + crop.2) as isize,
..
]);
let source = other.data.slice(s![
crop.1 as isize .. (crop.1 + crop.3) as isize,
crop.0 as isize .. (crop.0 + crop.2) as isize,
..]);
crop.1 as isize..(crop.1 + crop.3) as isize,
crop.0 as isize..(crop.0 + crop.2) as isize,
..
]);
// loop over each [r, g, b, a] available in the relevant area
for (mut dest, orig_src) in destination.lanes_mut(Axis(2)).into_iter().zip(source.lanes(Axis(2))) {
macro_rules! tint { ($i:expr) => {
mul255(*orig_src.get($i).unwrap_or(&255), *color.get($i).unwrap_or(&255))
}}
macro_rules! tint {
($i:expr) => {
mul255(
*orig_src.get($i).unwrap_or(&255),
*color.get($i).unwrap_or(&255),
)
};
}
let src = [tint!(0), tint!(1), tint!(2), tint!(3)];
// out_A = src_A + dst_A (1 - src_A)
@ -183,7 +193,9 @@ impl Image {
let out_a = src[3] + mul255(dest[3], 255 - src[3]);
if out_a != 0 {
for i in 0..3 {
dest[i] = ((src[i] as u32 * src[3] as u32 + dest[i] as u32 * dest[3] as u32 * (255 - src[3] as u32) / 255) / out_a as u32) as u8;
dest[i] = ((src[i] as u32 * src[3] as u32
+ dest[i] as u32 * dest[3] as u32 * (255 - src[3] as u32) / 255)
/ out_a as u32) as u8;
}
} else {
for i in 0..3 {

View file

@ -117,7 +117,10 @@ impl Map {
impl Prefab {
pub fn from_path<S: Into<String>>(path: S) -> Prefab {
Prefab { path: path.into(), vars: Default::default() }
Prefab {
path: path.into(),
vars: Default::default(),
}
}
}
@ -273,11 +276,11 @@ fn parse_map(map: &mut Map, f: File) -> Result<(), DMError> {
if ch == b'\n' || ch == b'\r' {
in_comment_line = false;
comment_trigger = false;
continue
continue;
} else if in_comment_line {
continue
continue;
} else if ch == b'\t' {
continue
continue;
}
if ch == b'/' && !in_quote_block {
@ -319,19 +322,23 @@ fn parse_map(map: &mut Map, f: File) -> Result<(), DMError> {
} else if ch == b'=' && curr_var.is_empty() {
curr_var = take(&mut curr_datum);
let mut length = curr_var.len();
while length > 0 && (curr_var[length-1] as char).is_whitespace() {
while length > 0 && (curr_var[length - 1] as char).is_whitespace() {
length -= 1;
}
curr_var.truncate(length);
skip_whitespace = true;
} else if ch == b';' {
curr_prefab.vars.insert(from_latin1(take(&mut curr_var)),
parse_constant(chars.location(), take(&mut curr_datum))?);
curr_prefab.vars.insert(
from_latin1(take(&mut curr_var)),
parse_constant(chars.location(), take(&mut curr_datum))?,
);
skip_whitespace = true;
} else if ch == b'}' {
if !curr_var.is_empty() {
curr_prefab.vars.insert(from_latin1(take(&mut curr_var)),
parse_constant(chars.location(), take(&mut curr_datum))?);
curr_prefab.vars.insert(
from_latin1(take(&mut curr_var)),
parse_constant(chars.location(), take(&mut curr_datum))?,
);
}
in_varedit_block = false;
} else {
@ -387,7 +394,9 @@ fn parse_map(map: &mut Map, f: File) -> Result<(), DMError> {
// grid
#[derive(PartialEq, Debug)]
enum Coord {
X, Y, Z
X,
Y,
Z,
}
let mut grid = BTreeMap::new();
@ -426,7 +435,7 @@ fn parse_map(map: &mut Map, f: File) -> Result<(), DMError> {
} else {
match (ch as char).to_digit(10) {
Some(x) => curr_num = 10 * curr_num + x as usize,
None => return Err(DMError::new(Location::default(), "bad digit in map coordinate"))
None => return Err(DMError::new(Location::default(), "bad digit in map coordinate")),
}
}
} else if in_map_string {

View file

@ -100,7 +100,8 @@ pub fn check(
}
pub fn retain_mut<T, F>(v: &mut Vec<T>, mut f: F)
where F: FnMut(&mut T) -> bool
where
F: FnMut(&mut T) -> bool,
{
let len = v.len();
let mut del = 0;

View file

@ -25,11 +25,14 @@ pub struct Context<'a> {
pub render_passes: &'a [Box<RenderPass>],
}
pub fn generate(
ctx: Context,
icon_cache: &IconCache,
) -> Result<Image, ()> {
let Context { objtree, map, grid, render_passes, .. } = ctx;
pub fn generate(ctx: Context, icon_cache: &IconCache) -> Result<Image, ()> {
let Context {
objtree,
map,
grid,
render_passes,
..
} = ctx;
// transform min/max from bottom-left-based to top-left-based
// probably doesn't belong here
@ -42,16 +45,26 @@ pub fn generate(
let mut overlays = Vec::new();
for (y, row) in grid.axis_iter(Axis(0)).enumerate() {
if y < min_y || y > max_y { continue }
if y < min_y || y > max_y {
continue;
}
for (x, e) in row.iter().enumerate() {
if x < ctx.min.0 || x > ctx.max.0 { continue }
if x < ctx.min.0 || x > ctx.max.0 {
continue;
}
for mut atom in get_atom_list(objtree, &map.dictionary[e], (x as u32, y as u32), render_passes) {
// icons which differ from their map states
let p = &atom.type_.path;
if p == "/obj/structure/table/wood/fancy/black" {
atom.set_var("icon", Constant::Resource("icons/obj/smooth_structures/fancy_table_black.dmi".into()));
atom.set_var(
"icon",
Constant::Resource("icons/obj/smooth_structures/fancy_table_black.dmi".into()),
);
} else if p == "/obj/structure/table/wood/fancy" {
atom.set_var("icon", Constant::Resource("icons/obj/smooth_structures/fancy_table.dmi".into()));
atom.set_var(
"icon",
Constant::Resource("icons/obj/smooth_structures/fancy_table.dmi".into()),
);
} else if subtype(p, "/turf/closed/mineral/") {
atom.set_var("pixel_x", Constant::Int(-4));
atom.set_var("pixel_y", Constant::Int(-4));
@ -67,18 +80,24 @@ pub fn generate(
let mut copy = atom.clone();
copy.set_var("icon_state", Constant::string($icon));
overlays.push(copy);
}}
}};
}
if subtype(p, "/obj/structure/closet/") {
// closet doors
if atom.get_var("opened", objtree).to_bool() {
let var = if atom.get_var("icon_door_override", objtree).to_bool() { "icon_door" } else { "icon_state" };
let var = if atom.get_var("icon_door_override", objtree).to_bool() {
"icon_door"
} else {
"icon_state"
};
if let &Constant::String(ref door) = atom.get_var(var, objtree) {
add_overlay!(format!("{}_open", door));
}
} else {
if let &Constant::String(ref door) = atom.get_var_notnull("icon_door", objtree)
.unwrap_or_else(|| atom.get_var("icon_state", objtree)) {
if let &Constant::String(ref door) = atom
.get_var_notnull("icon_door", objtree)
.unwrap_or_else(|| atom.get_var("icon_state", objtree))
{
add_overlay!(format!("{}_door", door));
}
if atom.get_var("welded", objtree).to_bool() {
@ -122,7 +141,7 @@ pub fn generate(
"scrub_map" => "scrub_off",
"scrub_map_on" => "scrub_on",
_ => "",
}
},
_ => "",
};
if !aboveground.is_empty() {
@ -175,7 +194,7 @@ pub fn generate(
&Constant::Resource(ref path) | &Constant::String(ref path) => path,
_ => {
println!("no icon: {}", atom.type_.path);
continue
continue;
}
};
let icon_state = match atom.get_var("icon_state", objtree) {
@ -196,7 +215,7 @@ pub fn generate(
icon_file.metadata.height as i32;
let mut loc = (
((atom.loc.0 - ctx.min.0 as u32) * TILE_SIZE) as i32 + pixel_x,
((atom.loc.1 + 1 - min_y as u32) * TILE_SIZE) as i32 - pixel_y
((atom.loc.1 + 1 - min_y as u32) * TILE_SIZE) as i32 - pixel_y,
);
// OOB handling
@ -204,25 +223,29 @@ pub fn generate(
rect.0 += (-loc.0) as u32;
match rect.2.checked_sub((-loc.0) as u32) {
Some(s) => rect.2 = s,
None => continue 'atom // out of the viewport
None => continue 'atom, // out of the viewport
}
loc.0 = 0;
}
while loc.0 + rect.2 as i32 > map_image.width as i32 {
rect.2 -= 1;
if rect.2 == 0 { continue 'atom }
if rect.2 == 0 {
continue 'atom;
}
}
if loc.1 < 0 {
rect.1 += (-loc.1) as u32;
match rect.3.checked_sub((-loc.1) as u32) {
Some(s) => rect.3 = s,
None => continue 'atom // out of the viewport
None => continue 'atom, // out of the viewport
}
loc.1 = 0;
}
while loc.1 + rect.3 as i32 > map_image.height as i32 {
rect.3 -= 1;
if rect.3 == 0 { continue 'atom }
if rect.3 == 0 {
continue 'atom;
}
}
let loc = (loc.0 as u32, loc.1 as u32);
@ -259,7 +282,7 @@ pub fn get_atom_list<'a>(
Some(x) => x,
None => {
println!("Warning: missing {:?}", fab.path);
continue
continue;
}
};
@ -316,7 +339,7 @@ impl<'a> Atom<'a> {
type_: type_,
prefab: None,
vars: Default::default(),
loc
loc,
}
}
@ -349,7 +372,7 @@ pub trait GetVar {
fn get_var_notnull<'a>(&'a self, key: &str, objtree: &'a ObjectTree) -> Option<&'a Constant> {
match self.get_var_inner(key, objtree) {
None | Some(&Constant::Null(_)) => None,
Some(other) => Some(other)
Some(other) => Some(other),
}
}
@ -466,7 +489,12 @@ pub fn color_of<T: GetVar + ?Sized>(objtree: &ObjectTree, atom: &T) -> [u8; 4] {
if color.len() == 7 { // #rrggbb
[(sum >> 16) as u8, (sum >> 8) as u8, sum as u8, alpha]
} else if color.len() == 4 { // #rgb
[(0x11 * ((sum >> 8) & 0xf)) as u8, (0x11 * ((sum >> 4) & 0xf)) as u8, (0x11 * (sum & 0xf)) as u8, alpha]
[
(0x11 * ((sum >> 8) & 0xf)) as u8,
(0x11 * ((sum >> 4) & 0xf)) as u8,
(0x11 * (sum & 0xf)) as u8,
alpha,
]
} else {
[255, 255, 255, alpha] // invalid
}
@ -515,7 +543,9 @@ fn calculate_adjacencies(ctx: Context, atom: &Atom, flags: i32) -> i32 {
let check_one = |direction, flag| {
if find_type_in_direction(ctx, atom, direction, flags) {
flag
} else { 0 }
} else {
0
}
};
for &dir in &[SOUTH, NORTH, EAST, WEST] {
@ -554,9 +584,12 @@ fn find_type_in_direction<'a>(ctx: Context, source: &Atom, direction: i32, flags
let new_loc = (new_loc.0 as u32, new_loc.1 as u32);
// TODO: make this not call get_atom_list way too many times
let atom_list = get_atom_list(ctx.objtree,
let atom_list = get_atom_list(
ctx.objtree,
&ctx.map.dictionary[&ctx.grid[ndarray::Dim([new_loc.1 as usize, new_loc.0 as usize])]],
new_loc, ctx.render_passes);
new_loc,
ctx.render_passes,
);
match source.get_var("canSmoothWith", ctx.objtree) {
&Constant::List(ref elements) => if flags & SMOOTH_MORE != 0 {
// smooth with canSmoothWith + subtypes
@ -630,21 +663,21 @@ fn cardinal_smooth<'a>(output: &mut Vec<Atom<'a>>, ctx: Context<'a>, source: &At
}
fn diagonal_smooth<'a>(output: &mut Vec<Atom<'a>>, ctx: Context<'a>, source: &Atom<'a>, adjacencies: i32) {
let presets = if adjacencies == N_NORTH|N_WEST {
let presets = if adjacencies == N_NORTH | N_WEST {
["d-se", "d-se-0"]
} else if adjacencies == N_NORTH|N_EAST {
} else if adjacencies == N_NORTH | N_EAST {
["d-sw", "d-sw-0"]
} else if adjacencies == N_SOUTH|N_WEST {
} else if adjacencies == N_SOUTH | N_WEST {
["d-ne", "d-ne-0"]
} else if adjacencies == N_SOUTH|N_EAST {
} else if adjacencies == N_SOUTH | N_EAST {
["d-nw", "d-nw-0"]
} else if adjacencies == N_NORTH|N_WEST|N_NORTHWEST {
} else if adjacencies == N_NORTH | N_WEST | N_NORTHWEST {
["d-se", "d-se-1"]
} else if adjacencies == N_NORTH|N_EAST|N_NORTHEAST {
} else if adjacencies == N_NORTH | N_EAST | N_NORTHEAST {
["d-sw", "d-sw-1"]
} else if adjacencies == N_SOUTH|N_WEST|N_SOUTHWEST {
} else if adjacencies == N_SOUTH | N_WEST | N_SOUTHWEST {
["d-ne", "d-ne-1"]
} else if adjacencies == N_SOUTH|N_EAST|N_SOUTHEAST {
} else if adjacencies == N_SOUTH | N_EAST | N_SOUTHEAST {
["d-nw", "d-nw-1"]
} else {
return cardinal_smooth(output, ctx, source, adjacencies);
@ -653,7 +686,11 @@ fn diagonal_smooth<'a>(output: &mut Vec<Atom<'a>>, ctx: Context<'a>, source: &At
// turf underneath
if subtype(&source.type_.path, "/turf/closed/wall/") {
// BYOND memes
if source.get_var("fixed_underlay", ctx.objtree).index(&Constant::string("space")).is_some() {
if source
.get_var("fixed_underlay", ctx.objtree)
.index(&Constant::string("space"))
.is_some()
{
output.push(Atom::from_type(ctx.objtree, "/turf/open/space/basic", source.loc).unwrap());
} else {
let dir = flip(reverse_ndir(adjacencies));
@ -666,9 +703,12 @@ fn diagonal_smooth<'a>(output: &mut Vec<Atom<'a>>, ctx: Context<'a>, source: &At
if !(new_loc.0 < 0 || new_loc.1 < 0 || new_loc.0 >= dim_x as i32 || new_loc.1 >= dim_y as i32) {
let new_loc = (new_loc.0 as u32, new_loc.1 as u32);
// TODO: make this not call get_atom_list way too many times
let atom_list = get_atom_list(ctx.objtree,
let atom_list = get_atom_list(
ctx.objtree,
&ctx.map.dictionary[&ctx.grid[ndarray::Dim([new_loc.1 as usize, new_loc.0 as usize])]],
new_loc, ctx.render_passes);
new_loc,
ctx.render_passes,
);
for mut atom in atom_list {
if subtype(&atom.type_.path, "/turf/open/") {
atom.loc = source.loc;
@ -730,14 +770,14 @@ fn flip(direction: i32) -> i32 {
fn reverse_ndir(ndir: i32) -> i32 {
use dmi::*;
const NW1: i32 = N_NORTH|N_WEST;
const NW2: i32 = NW1|N_NORTHWEST;
const NE1: i32 = N_NORTH|N_EAST;
const NE2: i32 = NE1|N_NORTHEAST;
const SW1: i32 = N_SOUTH|N_WEST;
const SW2: i32 = SW1|N_SOUTHWEST;
const SE1: i32 = N_SOUTH|N_EAST;
const SE2: i32 = SE1|N_SOUTHEAST;
const NW1: i32 = N_NORTH | N_WEST;
const NW2: i32 = NW1 | N_NORTHWEST;
const NE1: i32 = N_NORTH | N_EAST;
const NE2: i32 = NE1 | N_NORTHEAST;
const SW1: i32 = N_SOUTH | N_WEST;
const SW2: i32 = SW1 | N_SOUTHWEST;
const SE1: i32 = N_SOUTH | N_EAST;
const SE2: i32 = SE1 | N_SOUTHEAST;
match ndir {
N_NORTH => NORTH,
@ -781,4 +821,3 @@ fn right_45(dir: i32) -> i32 {
e => e,
}
}

View file

@ -172,7 +172,8 @@ impl RenderPass for HideInvisible {
#[derive(Default)]
pub struct FakeGlass;
impl RenderPass for FakeGlass {
fn overlays<'a>(&self,
fn overlays<'a>(
&self,
atom: &mut Atom<'a>,
_objtree: &'a ObjectTree,
underlays: &mut Vec<Atom<'a>>,

View file

@ -89,7 +89,7 @@ impl RenderPass for Random {
for child in root.children() {
if let Some(v) = child.vars.get("hidden") {
if !v.value.constant.as_ref().map_or(false, |c| c.to_bool()) {
continue
continue;
}
}
if let Some(icon) = child.vars.get("icon") {

View file

@ -12,7 +12,7 @@ impl RenderPass for TransitTube {
use dmi::*;
if !atom.istype("/obj/structure/transit_tube/") {
return
return;
}
let dir = atom.get_var("dir", objtree).to_int().unwrap_or(::dmi::SOUTH);
@ -95,7 +95,13 @@ impl RenderPass for TransitTube {
}
}
fn create_tube_overlay<'a>(output: &mut Vec<Atom<'a>>, objtree: &'a ObjectTree, source: &Atom<'a>, dir: i32, shift: i32) {
fn create_tube_overlay<'a>(
output: &mut Vec<Atom<'a>>,
objtree: &'a ObjectTree,
source: &Atom<'a>,
dir: i32,
shift: i32,
) {
use dmi::*;
let mut copy = Atom::from_type(objtree, "/atom", source.loc).unwrap();

View file

@ -6,7 +6,8 @@ use walkdir::{DirEntry, WalkDir};
use dmm_tools::*;
fn is_visible(entry: &DirEntry) -> bool {
entry.path()
entry
.path()
.file_name()
.unwrap_or("".as_ref())
.to_str()
@ -22,10 +23,7 @@ fn files_with_extension<F: FnMut(&Path)>(ext: &str, mut f: F) {
return;
}
};
for entry in WalkDir::new(dir)
.into_iter()
.filter_entry(is_visible)
{
for entry in WalkDir::new(dir).into_iter().filter_entry(is_visible) {
let entry = entry.unwrap();
if entry.file_type().is_file() && entry.path().extension() == Some(ext.as_ref()) {
let path = entry.path();

View file

@ -24,8 +24,12 @@ impl<R: Read> Iterator for Chars<R> {
Some(Err(e)) => return Some(Err(e)),
};
let width = utf8_char_width(first_byte);
if width == 1 { return Some(Ok(first_byte as char)) }
if width == 0 { return Some(Err(ErrorKind::InvalidData.into())) }
if width == 1 {
return Some(Ok(first_byte as char));
}
if width == 0 {
return Some(Err(ErrorKind::InvalidData.into()));
}
let mut buf = [first_byte, 0, 0, 0];
{
let mut start = 1;