From 6deccd5529243b04641805d65893a01523b6035c Mon Sep 17 00:00:00 2001 From: Adam Wick Date: Wed, 19 Jun 2024 09:47:37 -0700 Subject: [PATCH] Get some indenting right. --- src/syntax/arbitrary.rs | 125 +++++++++++++++++++++++++++++++--------- src/syntax/pretty.rs | 105 +++++++++++++++++++++------------ 2 files changed, 165 insertions(+), 65 deletions(-) diff --git a/src/syntax/arbitrary.rs b/src/syntax/arbitrary.rs index 6c42c30..5edc698 100644 --- a/src/syntax/arbitrary.rs +++ b/src/syntax/arbitrary.rs @@ -13,6 +13,7 @@ use std::str::FromStr; use std::sync::atomic::AtomicU64; pub const VALID_VARIABLE_NAMES: &str = r"[a-z][a-zA-Z0-9_]*"; +const MAX_COMPLEX_DEPTH: usize = 4; lazy_static::lazy_static! { static ref BASE_PROGRAM_LENGTH: WeightedIndex = WeightedIndex::new([ @@ -50,6 +51,11 @@ lazy_static::lazy_static! { (1, ExpressionType::Binding), ]); + static ref SIMPLIFIED_EXPRESSION_TYPES: WeightedMap = WeightedMap::new(&[ + (1, ExpressionType::Reference), + (1, ExpressionType::Value), + ]); + static ref TYPE_FREQUENCIES: WeightedMap<&'static str> = WeightedMap::new(&[ (1, "void"), (5, "i8"), @@ -166,13 +172,14 @@ impl ProgramTree { while current.len() < base_program_length { let (expression, mut requirements) = - generate_expr(&mut rng, &mut established_structs, &mut env, None); + generate_expr(0, &mut rng, &mut established_structs, &mut env, None); current.push_front(TopLevel::Expression(expression)); while let Some(requirement) = requirements.pop() { match requirement { Requirement::Function(name, args, result) => { let (expression, newreqs) = generate_function( + 1, &mut rng, &mut established_structs, &mut env, @@ -203,8 +210,13 @@ impl ProgramTree { } Requirement::Variable(name, ty) => { - let (newexpr, newreqs) = - generate_expr(&mut rng, &mut established_structs, &mut env, Some(ty)); + let (newexpr, newreqs) = generate_expr( + 1, + &mut rng, + &mut established_structs, + &mut env, + Some(ty), + ); let binding = Expression::Binding(Location::manufactured(), name, Box::new(newexpr)); current.push_front(TopLevel::Expression(binding)); @@ -222,6 +234,7 @@ impl ProgramTree { } fn generate_expr( + depth: usize, rng: &mut TestRng, established_struct_types: &mut EstablishedStructMap, env: &mut ScopedMap, @@ -229,22 +242,26 @@ fn generate_expr( ) -> (Expression, Vec) { let target_type = optional_target_type.unwrap_or_else(|| generate_type(rng, established_struct_types)); - let expression_type = EXPRESSION_TYPE_FREQUENCIES.sample(rng); + let expression_type = if depth > MAX_COMPLEX_DEPTH { + SIMPLIFIED_EXPRESSION_TYPES.sample(rng) + } else { + EXPRESSION_TYPE_FREQUENCIES.sample(rng) + }; match expression_type { ExpressionType::Value => match target_type { Type::Named(ref x) => match ConstantType::from_str(x.current_name()) { Ok(ct) => (generate_constant(rng, ct), vec![]), - _ => generate_constructor(rng, established_struct_types, env, target_type), + _ => generate_constructor(depth, rng, established_struct_types, env, target_type), }, Type::Struct(_) => { - generate_constructor(rng, established_struct_types, env, target_type) + generate_constructor(depth, rng, established_struct_types, env, target_type) } }, ExpressionType::Constructor => { - generate_constructor(rng, established_struct_types, env, target_type) + generate_constructor(depth, rng, established_struct_types, env, target_type) } ExpressionType::Reference => { @@ -292,8 +309,13 @@ fn generate_expr( .get(new_target_type_idx) .expect("generated reasonable index") .clone(); - let (subexp, newreqs) = - generate_expr(rng, established_struct_types, env, Some(new_target_type)); + let (subexp, newreqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(new_target_type), + ); requirements.extend(newreqs); ( @@ -309,8 +331,13 @@ fn generate_expr( let idx = rng.gen_range(0..new_targets.len()); let new_constant_type = new_targets.get(idx).expect("generates in bounds"); let new_type = Type::Named(Name::manufactured(new_constant_type.name())); - let (subexpr, reqs) = - generate_expr(rng, established_struct_types, env, Some(new_type)); + let (subexpr, reqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(new_type), + ); ( Expression::Cast(Location::manufactured(), ct.name(), Box::new(subexpr)), reqs, @@ -319,6 +346,7 @@ fn generate_expr( Err(_) => { let (subexpr, reqs) = generate_expr( + depth + 1, rng, established_struct_types, env, @@ -349,6 +377,7 @@ fn generate_expr( established_struct_types.insert(name.clone(), new_fields.clone()); let (subexpr, mut reqs) = generate_expr( + depth + 1, rng, established_struct_types, env, @@ -365,6 +394,7 @@ fn generate_expr( Some((name, _)) => { let (subexpr, reqs) = generate_expr( + depth + 1, rng, established_struct_types, env, @@ -382,9 +412,13 @@ fn generate_expr( ExpressionType::Call => match target_type { Type::Named(ref x) => match ConstantType::from_str(x.current_name()) { - Err(_) => { - genererate_call_to_function(rng, established_struct_types, env, target_type) - } + Err(_) => genererate_call_to_function( + depth, + rng, + established_struct_types, + env, + target_type, + ), Ok(prim) if CALL_SHOULD_BE_PRIMITIVE.sample(rng) => { let options = prim.primitives_for(); let idx = rng.gen_range(0..options.len()); @@ -398,6 +432,7 @@ fn generate_expr( for possible_type in argtypes.iter() { let (expr, new_prereqs) = generate_expr( + depth + 1, rng, established_struct_types, env, @@ -412,13 +447,17 @@ fn generate_expr( (retval, prereqs) } - Ok(_) => { - genererate_call_to_function(rng, established_struct_types, env, target_type) - } + Ok(_) => genererate_call_to_function( + depth, + rng, + established_struct_types, + env, + target_type, + ), }, Type::Struct(_) => { - genererate_call_to_function(rng, established_struct_types, env, target_type) + genererate_call_to_function(depth, rng, established_struct_types, env, target_type) } }, @@ -434,15 +473,20 @@ fn generate_expr( Some(generate_type(rng, established_struct_types)) }; let (expr, new_prereqs) = - generate_expr(rng, established_struct_types, env, inner_type); + generate_expr(depth + 1, rng, established_struct_types, env, inner_type); block.push_back(expr); let mut new_work_queue: VecDeque = new_prereqs.into_iter().collect(); while let Some(next) = new_work_queue.pop_front() { if let Requirement::Variable(name, varty) = next { - let (value, even_newer_reqs) = - generate_expr(rng, established_struct_types, env, Some(varty)); + let (value, even_newer_reqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(varty), + ); block.push_front(Expression::Binding( Location::manufactured(), @@ -465,6 +509,7 @@ fn generate_expr( ExpressionType::Binding => { let name = generate_name(rng); let (expr, prereqs) = generate_expr( + depth + 1, rng, established_struct_types, env, @@ -497,6 +542,7 @@ fn generate_constant(rng: &mut TestRng, ct: ConstantType) -> Expression { } fn generate_constructor( + depth: usize, rng: &mut TestRng, established_struct_types: &mut EstablishedStructMap, env: &mut ScopedMap, @@ -520,8 +566,13 @@ fn generate_constructor( }; for (field_name, field_type) in fields.into_iter() { - let (subexpr, reqs) = - generate_expr(rng, established_struct_types, env, Some(field_type)); + let (subexpr, reqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(field_type), + ); requirements.extend(reqs.into_iter()); field_assignments.push((field_name, subexpr)); } @@ -560,8 +611,13 @@ fn generate_constructor( let mut field_assignments = vec![]; for (field_name, field_type) in fields.into_iter() { - let (subexpr, reqs) = - generate_expr(rng, established_struct_types, env, Some(field_type)); + let (subexpr, reqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(field_type), + ); requirements.extend(reqs.into_iter()); field_assignments.push((field_name, subexpr)); } @@ -573,6 +629,7 @@ fn generate_constructor( } fn generate_function( + depth: usize, rng: &mut TestRng, established_struct_types: &mut EstablishedStructMap, env: &mut ScopedMap, @@ -588,7 +645,13 @@ fn generate_function( args.push((arg_name.clone(), Some(arg_type.clone()))); env.insert(arg_name, arg_type); } - let (body, prereqs) = generate_expr(rng, established_struct_types, env, Some(ret.clone())); + let (body, prereqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(ret.clone()), + ); env.release_scope(); let function = Expression::Function( @@ -715,6 +778,7 @@ fn find_variables_with_type(env: &ScopedMap, target_type: &Type) -> } fn genererate_call_to_function( + depth: usize, rng: &mut TestRng, established_struct_types: &mut EstablishedStructMap, env: &mut ScopedMap, @@ -728,8 +792,13 @@ fn genererate_call_to_function( for _ in 0..arg_count { let arg_type = generate_type(rng, established_struct_types); - let (arg_expr, new_reqs) = - generate_expr(rng, established_struct_types, env, Some(arg_type.clone())); + let (arg_expr, new_reqs) = generate_expr( + depth + 1, + rng, + established_struct_types, + env, + Some(arg_type.clone()), + ); arg_types.push(arg_type); arg_exprs.push(arg_expr); prereqs.extend(new_reqs.into_iter()); diff --git a/src/syntax/pretty.rs b/src/syntax/pretty.rs index 36deeab..1d92c8a 100644 --- a/src/syntax/pretty.rs +++ b/src/syntax/pretty.rs @@ -7,35 +7,37 @@ impl Program { let mut result = allocator.nil(); for definition in self.structures.values() { - result = result - .append(allocator.text("struct")) + let mut interior = allocator.nil(); + + for (name, ty) in definition.fields.iter() { + let mut type_bit = allocator.nil(); + + if let Some(ty) = ty { + type_bit = allocator + .text(":") + .append(allocator.space()) + .append(ty.pretty(allocator)); + } + + interior = interior + .append(name.original_name().to_string()) + .append(type_bit) + .append(allocator.text(";")) + .append(allocator.hardline()); + } + + interior = interior.indent(9); + + let start = allocator.text("struct") .append(allocator.space()) .append(allocator.text(definition.name.original_name().to_string())) .append(allocator.space()) - .append(allocator.text("{")) - .append(allocator.hardline()) - .append( - allocator - .concat(definition.fields.iter().map(|(name, ty)| { - let mut type_bit = allocator.nil(); + .append(allocator.text("{")); - if let Some(ty) = ty { - type_bit = allocator - .text(":") - .append(allocator.space()) - .append(ty.pretty(allocator)); - } - - allocator - .text(name.original_name().to_string()) - .append(type_bit) - .append(allocator.text(";")) - .append(allocator.hardline()) - })) - .nest(2), - ) - .append(allocator.text("}")) + let conclusion = allocator.text("}") .append(allocator.hardline()); + + result = result.append(start.append(interior).append(conclusion)); } for definition in self.functions.values() { @@ -111,8 +113,7 @@ impl TopLevel { .append(type_bit) .append(allocator.text(";")) .append(allocator.hardline()) - })) - .nest(2), + })).indent(2) ) .append(allocator.text("}")) .append(allocator.hardline()), @@ -127,6 +128,8 @@ impl Expression { Expression::Constructor(_, name, fields) => allocator .text(name.to_string()) .append(allocator.space()) + .append(allocator.text("{")) + .append(allocator.hardline()) .append( allocator .concat(fields.iter().map(|(n, e)| { @@ -138,9 +141,9 @@ impl Expression { .append(allocator.text(";")) .append(allocator.hardline()) })) - .nest(2) - .braces(), - ), + .indent(2) + ) + .append(allocator.text("}")), Expression::Reference(var) => allocator.text(var.to_string()), Expression::FieldRef(_, val, field) => val .pretty(allocator) @@ -152,27 +155,55 @@ impl Expression { .append(e.pretty(allocator)), Expression::Primitive(_, op) => allocator.text(op.original_name().to_string()), Expression::Call(_, fun, args) => { - let args = args.iter().map(|x| x.pretty(allocator)); - let comma_sepped_args = allocator.intersperse(args, allocator.text(",")); - fun.pretty(allocator).append(comma_sepped_args.parens()) + let mut args = args.iter().map(|x| x.pretty(allocator)).collect::>(); + + match fun.as_ref() { + Expression::Primitive(_, name) if ["/", "*", "+", "-"].contains(&name.current_name()) && args.len() == 2 => { + let second = args.pop().unwrap(); + args.pop() + .unwrap() + .append(allocator.space()) + .append(allocator.text(name.current_name().to_string())) + .append(allocator.space()) + .append(second) + .parens() + } + + Expression::Primitive(_, name) if ["negate"].contains(&name.current_name()) && args.len() == 1 => + allocator.text("-").append(args.pop().unwrap()), + + Expression::Primitive(_, name) if ["print"].contains(&&name.current_name()) && args.len() == 1 => + allocator.text("print") + .append(allocator.space()) + .append(args.pop().unwrap()), + + _ => { + let comma_sepped_args = allocator.intersperse(args, allocator.text(",")); + fun.pretty(allocator).append(comma_sepped_args.parens()) + } + } } Expression::Block(_, stmts) => match stmts.split_last() { None => allocator.text("()"), Some((last, &[])) => last.pretty(allocator), Some((last, start)) => { - let mut result = allocator.text("{").append(allocator.hardline()); + let beginning = allocator.text("{").append(allocator.hardline()); + let mut inner = allocator.nil(); for stmt in start.iter() { - result = result + inner = inner .append(stmt.pretty(allocator)) .append(allocator.text(";")) .append(allocator.hardline()); } - result + inner = inner .append(last.pretty(allocator)) - .append(allocator.hardline()) - .append(allocator.text("}")) + .append(allocator.hardline()); + + inner = inner.indent(2); + + beginning.append(inner).append(allocator.text("}")) } }, Expression::Binding(_, var, expr) => allocator