<commit_before>/*!

Dark-0.51 exact compression model

# Links

http://darchiver.narod.ru/
http://code.google.com/p/adark/

*/

use std::{cmp, io, vec};
use compress::entropy::ari;

/// Aggregate frequency model of two sources
pub struct Aggregate<'a,X,Y> {
	priv x: &'a X,
	priv y: &'a Y,
}

impl<'a, X: ari::Model, Y: ari::Model>
ari::Model for Aggregate<'a,X,Y> {
	fn get_range(&self, value: ari::Value) -> (ari::Border,ari::Border) {
		let (x1,x2) = self.x.get_range(value);
		let (y1,y2) = self.y.get_range(value);
		(x1+y1, x2+y2)
	}

	fn find_value(&self, _offset: ari::Border) -> (ari::Value,ari::Border,ari::Border) {
		(0,0,0)	//TODO
	}

	fn get_denominator(&self) -> ari::Border {
		self.x.get_denominator() + self.y.get_denominator()
	}
}

static MAX_LOG_CODE		: uint = 8;
static MAX_LOG_CONTEXT	: uint = 11;
static NUM_LAST_LOGS	: uint = 3;
static MAX_BIT_CONTEXT	: uint = 3;
static ADAPT_POWERS: [int, ..9] = [6,5,4,3,2,1,4,6,4];
static DIST_OFFSET: super::Distance = 1;

struct SymbolContext {
	avg_dist	: int,
	freq_log	: ari::FrequencyTable,
	freq_extra	: ari::BinaryModel,
}

impl SymbolContext {
	fn new(threshold: ari::Border) -> SymbolContext {
		SymbolContext{
			avg_dist	: 1000,
			freq_log	: ari::FrequencyTable::new_flat(MAX_LOG_CODE+1, threshold),
			freq_extra	: ari::BinaryModel::new_flat(threshold),
		}
	}

	fn reset(&mut self) {
		self.avg_dist = 1000;
		self.freq_log.reset_flat();
		self.freq_extra.reset_flat();
	}

	fn update(&mut self, dist: super::Distance, mut log_diff: int) {
		log_diff = cmp::max(-5, cmp::min(log_diff, 3));
		let adapt = ADAPT_POWERS[5 + log_diff];
		self.avg_dist += (adapt*((dist as int) - self.avg_dist)) >> 3;
	}
}

/// Coding model for BWT-DC output
pub struct Model {
	priv freq_log		: ~[~[ari::FrequencyTable]],	//[MAX_LOG_CONTEXT+1][NUM_LAST_LOGS]
	priv freq_log_bits	: [ari::BinaryModel, ..2],
	priv freq_mantissa	: [ari::BinaryModel, ..MAX_BIT_CONTEXT+1],
	/// specific context tracking
	priv contexts		: ~[SymbolContext],
	priv last_log_token	: uint,
	/// update parameters
	priv update_log_global		: uint,
	priv update_log_power		: uint,
	priv update_log_add			: ari::Border,
	priv update_bits_global		: uint,
	priv update_bits_sym		: uint,
	priv update_mantissa_global	: uint,
}

impl Model {
	/// Create a new Model instance
	pub fn new(threshold: ari::Border) -> Model {
		Model {
			freq_log		: vec::from_fn(MAX_LOG_CONTEXT+1, |_| {
				vec::from_fn(NUM_LAST_LOGS, |_|
					ari::FrequencyTable::new_flat(MAX_LOG_CODE+1, threshold))
			}),
			freq_log_bits	: [ari::BinaryModel::new_flat(threshold), ..2],
			freq_mantissa	: [ari::BinaryModel::new_flat(threshold), ..MAX_BIT_CONTEXT+1],
			contexts		: vec::from_fn(0x100, |_| SymbolContext::new(threshold)),
			last_log_token	: 0,
			update_log_global		: 12,
			update_log_power		: 5,
			update_log_add			: 5,
			update_bits_global		: 2,
			update_bits_sym			: 3,
			update_mantissa_global	: 8,
		}
	}

	fn int_log(d: super::Distance) -> uint {
		let mut log = 0;
		while d>>log !=0 {log += 1;}
		log
	}
}

impl super::DistanceModel for Model {
	fn new_default() -> Model {
		Model::new(ari::range_default_threshold >> 2)
	}

	fn reset(&mut self) {
		for array in self.freq_log.mut_iter() {
			for table in array.mut_iter() {
				table.reset_flat();
			}
		}
		for bm in self.freq_log_bits.mut_iter() {
			bm.reset_flat();
		}
		for bm in self.freq_mantissa.mut_iter() {
			bm.reset_flat();
		}
		for con in self.contexts.mut_iter() {
			con.reset();
		}
		self.last_log_token = 0;
	}

	fn encode<W: io::Writer>(&mut self, mut dist: super::Distance, sym: super::Symbol, eh: &mut ari::Encoder<W>) {
		dist = dist + DIST_OFFSET;
		let log = Model::int_log(dist);
		let context = &mut self.contexts[sym];
		let avg_log = Model::int_log(context.avg_dist as super::Distance);
		let avg_log_capped = cmp::min(MAX_LOG_CONTEXT, avg_log);
		let log_diff = (log as int) - (avg_log_capped as int);	//check avg_log
		// write exponent
		{	// base part
			let sym_freq = &mut context.freq_log;
			let log_capped = cmp::min(log, MAX_LOG_CODE);
			let global_freq = &mut self.freq_log[avg_log_capped][self.last_log_token];
			debug!("Dark encoding log {} with context[{}][{}] of sym {}",
				log_capped, avg_log_capped, self.last_log_token, sym);
			eh.encode(log_capped, &ari::TableSumProxy::new(sym_freq, global_freq)).unwrap();
			sym_freq.update(log_capped, self.update_log_power, self.update_log_add);
			global_freq.update(log_capped, self.update_log_global, self.update_log_add);
		}
		if log >= MAX_LOG_CODE {	// extension
			let freq_log_bits = &mut self.freq_log_bits[if avg_log_capped==MAX_LOG_CONTEXT {1} else {0}];
			for _ in range(MAX_LOG_CODE, log) {
				let bc = &mut context.freq_extra;
				eh.encode(0, &ari::BinarySumProxy::new(bc, freq_log_bits)).unwrap();
				bc.update(0, self.update_bits_sym);
				freq_log_bits.update(0, self.update_bits_global);
			}
			let bc = &mut context.freq_extra;
			eh.encode(1, &ari::BinarySumProxy::new(bc, freq_log_bits)).unwrap();
			bc.update(1, self.update_bits_sym);
			freq_log_bits.update(1, self.update_bits_global);
		}
		self.last_log_token = if log<2 {0} else if log<8 {1} else {2};
		// write mantissa
		for i in range(1,log) {
			let bit = (dist>>(log-i-1)) as uint & 1;
			if i > MAX_BIT_CONTEXT {
				// just send bits past the model, equally distributed
				eh.encode(bit, self.freq_mantissa.last().unwrap()).unwrap();
			}else {
				let bc = &mut self.freq_mantissa[i-1];
				eh.encode(bit, bc).unwrap();
				bc.update(bit, self.update_mantissa_global);
			};
		}
		// update the model
		context.update(dist, log_diff);
	}

	fn decode<R: io::Reader>(&mut self, sym: super::Symbol, dh: &mut ari::Decoder<R>) -> super::Distance {
		let context = &mut self.contexts[sym];
		let avg_log = Model::int_log(context.avg_dist as super::Distance);
		let avg_log_capped = cmp::min(MAX_LOG_CONTEXT, avg_log);
		// read exponent
		let log_pre = { // base part
			let sym_freq = &mut context.freq_log;
			let global_freq = &mut self.freq_log[avg_log_capped][self.last_log_token];
			let log = dh.decode(&ari::TableSumProxy::new(sym_freq, global_freq)).unwrap();
			debug!("Dark decoding log {} with context[{}][{}] of sym {}",
				log, avg_log_capped, self.last_log_token, sym);
			sym_freq.update(log, self.update_log_power, self.update_log_add);
			global_freq.update(log, self.update_log_global, self.update_log_add);
			log
		};
		let log = if log_pre >= MAX_LOG_CODE {	//extension
			let mut count = 0;
			let freq_log_bits = &mut self.freq_log_bits[if avg_log_capped==MAX_LOG_CONTEXT {1} else {0}];
			let bc = &mut context.freq_extra;
			while dh.decode(&ari::BinarySumProxy::new(bc, freq_log_bits)).unwrap() == 0 {
				count += 1;
				bc.update(0, self.update_bits_sym);
				freq_log_bits.update(0, self.update_bits_global);
			}
			bc.update(1, self.update_bits_sym);
			freq_log_bits.update(1, self.update_bits_global);
			log_pre + count
		}else {
			log_pre
		};
		self.last_log_token = if log<2 {0} else if log<8 {1} else {2};
		// read mantissa
		let mut dist = 1 as super::Distance;
		for i in range(1,log) {
			let bit = if i > MAX_BIT_CONTEXT {
				dh.decode( self.freq_mantissa.last().unwrap() ).unwrap()
			}else {
				let bc = &mut self.freq_mantissa[i-1];
				let bit = dh.decode(bc).unwrap();
				bc.update(bit, self.update_mantissa_global);
				bit
			};
			dist = (dist<<1) + (bit as super::Distance);
		}
		// update model
		let log_diff = (log as int) - (avg_log_capped as int);
		context.update(dist, log_diff);
		// return
		dist-DIST_OFFSET
	}
}
<commit_msg>Implemented multi-positioned binary contexts for Dark. The implementation seems complete now, but need some tuning to go from 217kb to 215kb on book1<commit_after>/*!

Dark-0.51 exact compression model

# Links

http://darchiver.narod.ru/
http://code.google.com/p/adark/

*/

use std::{cmp, io, vec};
use compress::entropy::ari;

/// Aggregate frequency model of two sources
pub struct Aggregate<'a,X,Y> {
	priv x: &'a X,
	priv y: &'a Y,
}

impl<'a, X: ari::Model, Y: ari::Model>
ari::Model for Aggregate<'a,X,Y> {
	fn get_range(&self, value: ari::Value) -> (ari::Border,ari::Border) {
		let (x1,x2) = self.x.get_range(value);
		let (y1,y2) = self.y.get_range(value);
		(x1+y1, x2+y2)
	}

	fn find_value(&self, _offset: ari::Border) -> (ari::Value,ari::Border,ari::Border) {
		(0,0,0)	//TODO
	}

	fn get_denominator(&self) -> ari::Border {
		self.x.get_denominator() + self.y.get_denominator()
	}
}

static MAX_LOG_CODE		: uint = 8;
static MAX_LOG_CONTEXT	: uint = 11;
static NUM_LAST_LOGS	: uint = 3;
static MAX_BIT_CONTEXT	: uint = 3;
static ADAPT_POWERS: [int, ..9] = [6,5,4,3,2,1,4,6,4];
static DIST_OFFSET: super::Distance = 1;

struct BinaryMultiplex {
	freqs: [ari::BinaryModel, ..32],
}

impl BinaryMultiplex {
	fn new(threshold: ari::Border) -> BinaryMultiplex {
		BinaryMultiplex {
			freqs: [ari::BinaryModel::new_flat(threshold), ..32],
		}
	}
	fn reset(&mut self) {
		for fr in self.freqs.mut_iter() {
			fr.reset_flat();
		}
	}
}

struct SymbolContext {
	avg_dist	: int,
	freq_log	: ari::FrequencyTable,
	freq_extra	: BinaryMultiplex,
}

impl SymbolContext {
	fn new(threshold: ari::Border) -> SymbolContext {
		SymbolContext{
			avg_dist	: 1000,
			freq_log	: ari::FrequencyTable::new_flat(MAX_LOG_CODE+1, threshold),
			freq_extra	: BinaryMultiplex::new(threshold),
		}
	}

	fn reset(&mut self) {
		self.avg_dist = 1000;
		self.freq_log.reset_flat();
		self.freq_extra.reset();
	}

	fn update(&mut self, dist: super::Distance, mut log_diff: int) {
		log_diff = cmp::max(-6, cmp::min(log_diff, 2));
		let adapt = ADAPT_POWERS[6 + log_diff];
		self.avg_dist += (adapt*((dist as int) - self.avg_dist)) >> 3;
	}
}

/// Coding model for BWT-DC output
pub struct Model {
	priv freq_log		: ~[~[ari::FrequencyTable]],	//[MAX_LOG_CONTEXT+1][NUM_LAST_LOGS]
	priv freq_log_bits	: [BinaryMultiplex, ..2],
	priv freq_mantissa	: [[ari::BinaryModel, ..MAX_BIT_CONTEXT+1], ..32],
	/// specific context tracking
	priv contexts		: ~[SymbolContext],
	priv last_log_token	: uint,
	/// update parameters
	priv update_log_global		: uint,
	priv update_log_power		: uint,
	priv update_log_add			: ari::Border,
	priv update_bits_global		: uint,
	priv update_bits_sym		: uint,
	priv update_mantissa_global	: uint,
}

impl Model {
	/// Create a new Model instance
	pub fn new(threshold: ari::Border) -> Model {
		Model {
			freq_log		: vec::from_fn(MAX_LOG_CONTEXT+1, |_| {
				vec::from_fn(NUM_LAST_LOGS, |_|
					ari::FrequencyTable::new_flat(MAX_LOG_CODE+1, threshold))
			}),
			freq_log_bits	: [BinaryMultiplex::new(threshold), ..2],
			freq_mantissa	: [[ari::BinaryModel::new_flat(threshold), ..MAX_BIT_CONTEXT+1], ..32],
			contexts		: vec::from_fn(0x100, |_| SymbolContext::new(threshold)),
			last_log_token	: 0,
			update_log_global		: 12,
			update_log_power		: 5,
			update_log_add			: 5,
			update_bits_global		: 2,
			update_bits_sym			: 3,
			update_mantissa_global	: 8,
		}
	}

	fn int_log(d: super::Distance) -> uint {
		let mut log = 0;
		while d>>log !=0 {log += 1;}
		log
	}
}

impl super::DistanceModel for Model {
	fn new_default() -> Model {
		Model::new(ari::range_default_threshold >> 2)
	}

	fn reset(&mut self) {
		for array in self.freq_log.mut_iter() {
			for table in array.mut_iter() {
				table.reset_flat();
			}
		}
		for bm in self.freq_log_bits.mut_iter() {
			bm.reset();
		}
		for array in self.freq_mantissa.mut_iter() {
			for bm in array.mut_iter() {
				bm.reset_flat();
			}
		}
		for con in self.contexts.mut_iter() {
			con.reset();
		}
		self.last_log_token = 0;
	}

	fn encode<W: io::Writer>(&mut self, mut dist: super::Distance, sym: super::Symbol, eh: &mut ari::Encoder<W>) {
		dist = dist + DIST_OFFSET;
		let log = Model::int_log(dist);
		let context = &mut self.contexts[sym];
		let avg_log = Model::int_log(context.avg_dist as super::Distance);
		let avg_log_capped = cmp::min(MAX_LOG_CONTEXT, avg_log);
		// write exponent
		{	// base part
			let sym_freq = &mut context.freq_log;
			let log_capped = cmp::min(log, MAX_LOG_CODE);
			let global_freq = &mut self.freq_log[avg_log_capped][self.last_log_token];
			debug!("Dark encoding log {} with context[{}][{}] of sym {}",
				log_capped, avg_log_capped, self.last_log_token, sym);
			eh.encode(log_capped, &ari::TableSumProxy::new(sym_freq, global_freq)).unwrap();
			sym_freq.update(log_capped, self.update_log_power, self.update_log_add);
			global_freq.update(log_capped, self.update_log_global, self.update_log_add);
		}
		if log >= MAX_LOG_CODE {	// extension
			let freq_log_bits = &mut self.freq_log_bits[if avg_log_capped==MAX_LOG_CONTEXT {1} else {0}];
			for i in range(MAX_LOG_CODE, log) {
				let bc = &mut context.freq_extra.freqs[i-MAX_LOG_CODE];
				let fc = &mut freq_log_bits.freqs[i-MAX_LOG_CODE];
				eh.encode(0, &ari::BinarySumProxy::new(bc, fc)).unwrap();
				bc.update(0, self.update_bits_sym);
				fc.update(0, self.update_bits_global);
			}
			let i = log-MAX_LOG_CODE;
			let bc = &mut context.freq_extra.freqs[i];
			let fc = &mut freq_log_bits.freqs[i];
			eh.encode(1, &ari::BinarySumProxy::new(bc, fc)).unwrap();
			bc.update(1, self.update_bits_sym);
			fc.update(1, self.update_bits_global);
		}
		self.last_log_token = if log<2 {0} else if log<8 {1} else {2};
		// write mantissa
		let mantissa_context = &mut self.freq_mantissa[log];
		for i in range(1,log) {
			let bit = (dist>>(log-i-1)) as uint & 1;
			if i > MAX_BIT_CONTEXT {
				// just send bits past the model, equally distributed
				eh.encode(bit, mantissa_context.last().unwrap()).unwrap();
			}else {
				let bc = &mut mantissa_context[i-1];
				eh.encode(bit, bc).unwrap();
				bc.update(bit, self.update_mantissa_global);
			};
		}
		// update the model
		let log_diff = (log as int) - (avg_log_capped as int);	//check avg_log
		context.update(dist, log_diff);
	}

	fn decode<R: io::Reader>(&mut self, sym: super::Symbol, dh: &mut ari::Decoder<R>) -> super::Distance {
		let context = &mut self.contexts[sym];
		let avg_log = Model::int_log(context.avg_dist as super::Distance);
		let avg_log_capped = cmp::min(MAX_LOG_CONTEXT, avg_log);
		// read exponent
		let log_pre = { // base part
			let sym_freq = &mut context.freq_log;
			let global_freq = &mut self.freq_log[avg_log_capped][self.last_log_token];
			let log = dh.decode(&ari::TableSumProxy::new(sym_freq, global_freq)).unwrap();
			debug!("Dark decoding log {} with context[{}][{}] of sym {}",
				log, avg_log_capped, self.last_log_token, sym);
			sym_freq.update(log, self.update_log_power, self.update_log_add);
			global_freq.update(log, self.update_log_global, self.update_log_add);
			log
		};
		let log = if log_pre >= MAX_LOG_CODE {	//extension
			let mut count = 0;
			let freq_log_bits = &mut self.freq_log_bits[if avg_log_capped==MAX_LOG_CONTEXT {1} else {0}];
			loop {
				let bc = &mut context.freq_extra.freqs[count];
				let fc = &mut freq_log_bits.freqs[count];
				let bit = dh.decode(&ari::BinarySumProxy::new(bc, fc)).unwrap();
				bc.update(bit, self.update_bits_sym);
				fc.update(bit, self.update_bits_global);
				if bit == 1 {break}
				count += 1;
			}
			log_pre + count
		}else {
			log_pre
		};
		self.last_log_token = if log<2 {0} else if log<8 {1} else {2};
		// read mantissa
		let mantissa_context = &mut self.freq_mantissa[log];
		let mut dist = 1 as super::Distance;
		for i in range(1,log) {
			let bit = if i > MAX_BIT_CONTEXT {
				dh.decode( mantissa_context.last().unwrap() ).unwrap()
			}else {
				let bc = &mut mantissa_context[i-1];
				let bit = dh.decode(bc).unwrap();
				bc.update(bit, self.update_mantissa_global);
				bit
			};
			dist = (dist<<1) + (bit as super::Distance);
		}
		// update model
		let log_diff = (log as int) - (avg_log_capped as int);
		context.update(dist, log_diff);
		// return
		dist-DIST_OFFSET
	}
}
<|endoftext|>


<commit_before>/// Enum describing positions in relation to a point
#[derive(Debug, PartialEq)]
pub enum Direction {
  East,
  Southeast,
  Southwest,
  West,
  Northwest,
  Northeast,
  Up,
  Down,
}

impl Direction {

  /// Get a vector of directions
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::{Direction};
  ///
  /// let vec: Vec<Direction> = Direction::to_vec();
  ///
  /// assert_eq!(Direction::East, vec[0]);
  /// ```
  pub fn to_vec() -> Vec<Direction> {
    vec![
      Direction::East,
      Direction::Southeast,
      Direction::Southwest,
      Direction::West,
      Direction::Northwest,
      Direction::Northeast,
      Direction::Up,
      Direction::Down,
    ]
  }

  /// Return the opposite direction
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::Direction;
  ///
  /// let east: Direction = Direction::East;
  ///
  /// assert_eq!(Direction::West, east.opposite());
  pub fn opposite(&self) -> Direction {

    match self {
      &Direction::East      => Direction::West,
      &Direction::Southeast => Direction::Northwest,
      &Direction::Southwest => Direction::Northeast,
      &Direction::West      => Direction::East,
      &Direction::Northwest => Direction::Southeast,
      &Direction::Northeast => Direction::Southwest,
      &Direction::Up        => Direction::Down,
      &Direction::Down      => Direction::Up,
    }

  }

}
<commit_msg>Issue #60: Added function for determining direction between two points<commit_after>use std::convert::From;

use structs::Point;
use traits::HasValues;

/// Enum describing positions in relation to a point
#[derive(Debug, PartialEq)]
pub enum Direction {
  East,
  Southeast,
  Southwest,
  West,
  Northwest,
  Northeast,
  Up,
  Down,
}

impl Direction {

  /// Get a vector of directions
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::{Direction};
  ///
  /// let vec: Vec<Direction> = Direction::to_vec();
  ///
  /// assert_eq!(Direction::East, vec[0]);
  /// ```
  pub fn to_vec() -> Vec<Direction> {
    vec![
      Direction::East,
      Direction::Southeast,
      Direction::Southwest,
      Direction::West,
      Direction::Northwest,
      Direction::Northeast,
      Direction::Up,
      Direction::Down,
    ]
  }

  /// Return the opposite direction
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::Direction;
  ///
  /// let east: Direction = Direction::East;
  ///
  /// assert_eq!(Direction::West, east.opposite());
  pub fn opposite(&self) -> Direction {

    match self {
      &Direction::East      => Direction::West,
      &Direction::Southeast => Direction::Northwest,
      &Direction::Southwest => Direction::Northeast,
      &Direction::West      => Direction::East,
      &Direction::Northwest => Direction::Southeast,
      &Direction::Northeast => Direction::Southwest,
      &Direction::Up        => Direction::Down,
      &Direction::Down      => Direction::Up,
    }

  }

}

impl <'a, 'b, T> From<(&'a T, &'b T)> for Direction where T: HasValues {

  /// Get the direction from one point to another
  ///
  /// # Example
  ///
  /// ```
  /// use hex_math::{Direction, Point};
  ///
  /// let point:     Point = Point::new(1, 2, 5);
  /// let east:      Point = Point::new(2, 2, 5);
  /// let southeast: Point = Point::new(1, 3, 5);
  /// let southwest: Point = Point::new(0, 3, 5);
  /// let west:      Point = Point::new(0, 2, 5);
  /// let northwest: Point = Point::new(1, 1, 5);
  /// let northeast: Point = Point::new(2, 1, 5);
  /// let up:        Point = Point::new(1, 2, 6);
  /// let down:      Point = Point::new(1, 2, 4);
  ///
  /// let from = Direction::from;
  ///
  /// assert_eq!(Direction::East,      from((&point, &east)));
  /// assert_eq!(Direction::Southeast, from((&point, &southeast)));
  /// assert_eq!(Direction::Southwest, from((&point, &southwest)));
  /// assert_eq!(Direction::West,      from((&point, &west)));
  /// assert_eq!(Direction::Northwest, from((&point, &northwest)));
  /// assert_eq!(Direction::Northeast, from((&point, &northeast)));
  /// assert_eq!(Direction::Up,        from((&point, &up)));
  /// assert_eq!(Direction::Down,      from((&point, &down)));
  /// ```
  fn from((p0, p1): (&'a T, &'b T)) -> Direction {

    let p0: Point = p0.values().into();
    let p1: Point = p1.values().into();
    let diff: Point = &p1 - &p0;

    let (dq, dr, dt) = diff.values();

    match dt.signum() {
       1 => return Direction::Up,
      -1 => return Direction::Down,
       _ => (),
    }

    return match (dq.signum(), dr.signum()) {
      ( 1,  0) => Direction::East,
      ( 0,  1) => Direction::Southeast,
      (-1,  1) => Direction::Southwest,
      (-1,  0) => Direction::West,
      ( 0, -1) => Direction::Northwest,
      ( 1, -1) => Direction::Northeast,
      _ => panic!(),
    }

  }

}
<|endoftext|>


<commit_before>use std::io;
use std::str::FromStr;
use std::collections::HashMap;

pub struct VM {
	op_stack: Vec<Operator>,
	data_stack: Vec<Operator>,
	words: HashMap<String, Vec<Operator>>,
}

impl VM {
	pub fn pop_data <'a> (&'a mut self) -> Operator {
		return self.data_stack.pop().expect("data stack is empty!");
	}

	pub fn push_data <'a> (&'a mut self, op: Operator) {
		self.data_stack.push(op);
	}

	pub fn pop_op <'a> (&'a mut self) -> Operator {
		return self.op_stack.pop().expect("operand stack is empty!");
	}

	pub fn push_op <'a> (&'a mut self, op: Operator) {
		self.op_stack.push(op);
	}

	pub fn eval <'a> (&'a mut self) {
		let op = self.pop_op();
		match op {
			Operator::Add => self.add(),
			Operator::Subtract => self.subtract(),
			Operator::Multiply => self.multiply(),
			Operator::Divide => self.divide(),
			Operator::Modulus => self.modulus(),
			Operator::And => self.and(),
			Operator::Or => self.or(),
			Operator::Xor => self.xor(),
			Operator::Lshift => self.lshift(),
			Operator::Rshift => self.rshift(),
			Operator::Abs => self.abs(),
			Operator::Max => self.max(),
			Operator::Min => self.min(),
			Operator::Invert => self.invert(),
			Operator::Negate => self.negate(),
			Operator::Dup => self.dup(),
			Operator::Drop => self.drop(),
			Operator::Swap => self.swap(),
			Operator::Over => self.over(),
			Operator::Rot => self.rot(),
			Operator::Value(i) => self.push_data(Operator::Value(i)),
			Operator::Print => self.print(),
			x => panic!("soon {}", x.stringify())
		}
	}

	fn pop_two_ints <'a> (&'a mut self) -> (i32, i32){
		let a = self.pop_one_int();
		let b = self.pop_one_int();
		(a, b)
	}

	fn pop_one_int <'a> (&'a mut self) -> i32 {
		let a = self.pop_data();
		match a {
			Operator::Value(j) => j,
			_ => panic!("can only add ints"),
		}
	}

	// Math Functions
	pub fn add <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x + y));
	}

	pub fn subtract <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x - y));
	}

	pub fn multiply <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x * y));
	}

	pub fn divide <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(y / x));
	}

	pub fn modulus <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x % y));
	}

	pub fn and <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x & y));
	}

	pub fn or <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x | y));
	}

	pub fn xor <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x ^ y));
	}

	pub fn lshift <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x << y));
	}

	pub fn rshift <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x >> y));
	}

	pub fn abs <'a> (&'a mut self) {
		let x = self.pop_one_int();
		self.push_data(Operator::Value(if x < 0 {-x} else {x}));
	}

	pub fn max <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(if y > x {y} else {x}));
	}

	pub fn min <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(if y < x {y} else {x}));
	}

	pub fn invert <'a> (&'a mut self) {
		let x = self.pop_one_int();
		self.push_data(Operator::Value(!x));
	}

	pub fn negate <'a> (&'a mut self) {
		let x = self.pop_one_int();
		self.push_data(Operator::Value(-x));
	}

	//Stack Functions
	pub fn dup <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = x.clone();
		self.push_data(x);
		self.push_data(y);
	}

	pub fn drop <'a> (&'a mut self) {
		self.pop_data();
	}

	pub fn swap <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = self.pop_data();
		self.push_data(x);
		self.push_data(y);
	}

	pub fn over <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = self.pop_data();
		let z = x.clone();
		self.push_data(x);
		self.push_data(y);
		self.push_data(z);
	}

	pub fn rot <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = self.pop_data();
		let z = self.pop_data();
		self.push_data(x);
		self.push_data(z);
		self.push_data(y);
	}

	//Debug Functions
	pub fn print <'a> (&'a mut self) {
		let x = self.pop_data();
		println!("{}",match x{
			Operator::Value(i) => i,
			_ => panic!("tried to print something other than a value"),
		});
	}
}

#[derive(Clone)]
pub enum Operator {
	//stack
	Dup,
	Drop,
	Swap,
	Over,
	Rot,

	//debug
	Print,

	//math
	Add,
	Subtract,
	Multiply,
	Divide,
	Modulus,
	And,
	Or,
	Xor,
	Lshift,
	Rshift,
	Abs,
	Max,
	Min,
	Invert,
	Negate,

	//custom
	Define,

	//values and custom calls
	Value(i32),
	Other,
}

impl Operator {
	fn stringify(&self) -> String {
		match *self{
			Operator::Add => format!("+"),
			Operator::Subtract => format!("-"),
			Operator::Multiply => format!("*"),
			Operator::Divide => format!("/"),
			Operator::Modulus => format!("mod"),
			Operator::And => format!("and"),
			Operator::Or => format!("or"),
			Operator::Xor => format!("xor"),
			Operator::Lshift => format!("<<"),
			Operator::Rshift => format!(">>"),
			Operator::Abs => format!("abs"),
			Operator::Max => format!("max"),
			Operator::Min => format!("min"),
			Operator::Invert => format!("invert"),
			Operator::Negate => format!("negate"),
			Operator::Dup => format!("dup"),
			Operator::Drop => format!("drop"),
			Operator::Swap => format!("swap"),
			Operator::Over => format!("over"),
			Operator::Rot => format!("rot"),
			Operator::Value(i) => format!("{}", i),
			Operator::Print => format!("."),
			Operator::Define => format!(":"),
			Operator::Other => format!("other"),
		}
	}
}

fn parse(s: &str) -> Operator {
	match s {
		//stack operations:
		"dup" => Operator::Dup,
		"drop" => Operator::Drop,
		"swap" => Operator::Swap,
		"over" => Operator::Over,
		"rot" => Operator::Rot,

		//debug operations:
		"." => Operator::Print,

		//math operations:
		"+" => Operator::Add,
		"-" => Operator::Subtract,
		"*" => Operator::Multiply,
		"/" => Operator::Divide,
		"mod" => Operator::Modulus,
		"and" => Operator::And,
		"or" => Operator::Or,
		"xor" => Operator::Xor,
		"lshift" => Operator::Lshift,
		"<<" => Operator::Lshift,
		"rshift" => Operator::Rshift,
		">>" => Operator::Rshift,
		"abs" => Operator::Abs,
		"max" => Operator::Max,
		"min" => Operator::Min,
		"invert" => Operator::Invert,
		"negate" => Operator::Negate,

		//custom definitions
		":" => Operator::Define,

		//value or custom operator
		x => {
			let y: Option<i32> = FromStr::from_str(x).ok();
			match y{
				Some(i) => Operator::Value(i),
				None => Operator::Other,
			}
		},
	}
}

fn main() {
	let x = io::stdin();
	let mut vm = VM {op_stack: vec![],
					 data_stack: vec![],
					 words: HashMap::new()};

	loop{
		let mut line: String = "".to_string();
		let _ = x.read_line(&mut line);

		if line.trim() == "" {break;}

		for o in line.rsplit(" "){
			let b = parse(o.trim());
			vm.push_op(b);
		}

		while vm.op_stack.len() > 0 {
			vm.eval();
		}
	}
}
<commit_msg>starting to get custom word definitions working WIP<commit_after>use std::io;
use std::str::FromStr;
use std::collections::HashMap;

enum VMState {
	Definition,
	Execution
}

pub struct VM {
	state: VMState,
	op_stack: Vec<Operator>,
	data_stack: Vec<Operator>,
	words: HashMap<String, Vec<Operator>>,
	current_def_word: Option<String>,
}

impl VM{
	pub fn pop_data <'a> (&'a mut self) -> Operator {
		return self.data_stack.pop().expect("data stack is empty!");
	}

	pub fn push_data <'a> (&'a mut self, op: Operator) {
		self.data_stack.push(op);
	}

	pub fn pop_op <'a> (&'a mut self) -> Operator {
		return self.op_stack.pop().expect("operand stack is empty!");
	}

	pub fn push_op <'a> (&'a mut self, op: Operator) {
		match op {
			Operator::Define => {
				self.state = VMState::Definition;
				return;
			},
			Operator::EndDefine => {
				self.state = VMState::Execution;
				self.current_def_word = None;
				return;
			},
			_ => {}
		};
		let should_def = match self.state {
			VMState::Definition => true,
			VMState::Execution => false
		};
		if should_def {
			let current_def_word = self.push_def_word(op);
			self.current_def_word = Some(current_def_word);
		} else {
			self.op_stack.push(op);
		}
	}

	fn push_def_word <'a> (&'a mut self, op: Operator) -> String{
		let wrapped = self.current_def_word.as_ref();
		let new_key = match wrapped {
			Some(w) => {
				self.words.get_mut(w).expect("error").push(op);
				w.clone()
			},
			None => {
				let key = match op {
					Operator::Other(key) => key,
					_ => panic!("key is broken")
				};
				self.words.insert(key.clone(), Vec::new());
				key
			}
		};

		return new_key;
	}

	pub fn eval <'a> (&'a mut self) {
		let op = self.pop_op();
		match op {
			Operator::Add => self.add(),
			Operator::Subtract => self.subtract(),
			Operator::Multiply => self.multiply(),
			Operator::Divide => self.divide(),
			Operator::Modulus => self.modulus(),
			Operator::And => self.and(),
			Operator::Or => self.or(),
			Operator::Xor => self.xor(),
			Operator::Lshift => self.lshift(),
			Operator::Rshift => self.rshift(),
			Operator::Abs => self.abs(),
			Operator::Max => self.max(),
			Operator::Min => self.min(),
			Operator::Invert => self.invert(),
			Operator::Negate => self.negate(),
			Operator::Dup => self.dup(),
			Operator::Drop => self.drop(),
			Operator::Swap => self.swap(),
			Operator::Over => self.over(),
			Operator::Rot => self.rot(),
			Operator::Value(i) => self.push_data(Operator::Value(i)),
			Operator::Print => self.print(),
			Operator::Other(s) => self.custom(s),
			x => panic!("cannot eval: {}", x.stringify())
		}
	}

	fn custom <'a> (&'a mut self, word: String) {

	}

	fn pop_two_ints <'a> (&'a mut self) -> (i32, i32){
		let a = self.pop_one_int();
		let b = self.pop_one_int();
		(a, b)
	}

	fn pop_one_int <'a> (&'a mut self) -> i32 {
		let a = self.pop_data();
		match a {
			Operator::Value(j) => j,
			_ => panic!("can only add ints"),
		}
	}

	// Math Functions
	pub fn add <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x + y));
	}

	pub fn subtract <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x - y));
	}

	pub fn multiply <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x * y));
	}

	pub fn divide <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(y / x));
	}

	pub fn modulus <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x % y));
	}

	pub fn and <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x & y));
	}

	pub fn or <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x | y));
	}

	pub fn xor <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x ^ y));
	}

	pub fn lshift <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x << y));
	}

	pub fn rshift <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(x >> y));
	}

	pub fn abs <'a> (&'a mut self) {
		let x = self.pop_one_int();
		self.push_data(Operator::Value(if x < 0 {-x} else {x}));
	}

	pub fn max <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(if y > x {y} else {x}));
	}

	pub fn min <'a> (&'a mut self) {
		let (x, y) = self.pop_two_ints();
		self.push_data(Operator::Value(if y < x {y} else {x}));
	}

	pub fn invert <'a> (&'a mut self) {
		let x = self.pop_one_int();
		self.push_data(Operator::Value(!x));
	}

	pub fn negate <'a> (&'a mut self) {
		let x = self.pop_one_int();
		self.push_data(Operator::Value(-x));
	}

	//Stack Functions
	pub fn dup <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = x.clone();
		self.push_data(x);
		self.push_data(y);
	}

	pub fn drop <'a> (&'a mut self) {
		self.pop_data();
	}

	pub fn swap <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = self.pop_data();
		self.push_data(x);
		self.push_data(y);
	}

	pub fn over <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = self.pop_data();
		let z = x.clone();
		self.push_data(x);
		self.push_data(y);
		self.push_data(z);
	}

	pub fn rot <'a> (&'a mut self) {
		let x = self.pop_data();
		let y = self.pop_data();
		let z = self.pop_data();
		self.push_data(x);
		self.push_data(z);
		self.push_data(y);
	}

	//Debug Functions
	pub fn print <'a> (&'a mut self) {
		let x = self.pop_data();
		println!("{}",match x{
			Operator::Value(i) => i,
			_ => panic!("tried to print something other than a value"),
		});
	}
}

#[derive(Clone)]
pub enum Operator {
	//stack
	Dup,
	Drop,
	Swap,
	Over,
	Rot,

	//debug
	Print,

	//math
	Add,
	Subtract,
	Multiply,
	Divide,
	Modulus,
	And,
	Or,
	Xor,
	Lshift,
	Rshift,
	Abs,
	Max,
	Min,
	Invert,
	Negate,

	//custom
	Define,
	EndDefine,

	//values and custom calls
	Value(i32),
	Other(String),
}

impl Operator {
	fn stringify(self) -> String {
		match self{
			Operator::Add => format!("+"),
			Operator::Subtract => format!("-"),
			Operator::Multiply => format!("*"),
			Operator::Divide => format!("/"),
			Operator::Modulus => format!("mod"),
			Operator::And => format!("and"),
			Operator::Or => format!("or"),
			Operator::Xor => format!("xor"),
			Operator::Lshift => format!("<<"),
			Operator::Rshift => format!(">>"),
			Operator::Abs => format!("abs"),
			Operator::Max => format!("max"),
			Operator::Min => format!("min"),
			Operator::Invert => format!("invert"),
			Operator::Negate => format!("negate"),
			Operator::Dup => format!("dup"),
			Operator::Drop => format!("drop"),
			Operator::Swap => format!("swap"),
			Operator::Over => format!("over"),
			Operator::Rot => format!("rot"),
			Operator::Value(i) => format!("{}", i),
			Operator::Print => format!("."),
			Operator::Define => format!(":"),
			Operator::EndDefine => format!(";"),
			Operator::Other(_) => format!("other"),
		}
	}
}

fn parse(s: &str) -> Operator {
	match s {
		//stack operations:
		"dup" => Operator::Dup,
		"drop" => Operator::Drop,
		"swap" => Operator::Swap,
		"over" => Operator::Over,
		"rot" => Operator::Rot,

		//debug operations:
		"." => Operator::Print,

		//math operations:
		"+" => Operator::Add,
		"-" => Operator::Subtract,
		"*" => Operator::Multiply,
		"/" => Operator::Divide,
		"mod" => Operator::Modulus,
		"and" => Operator::And,
		"or" => Operator::Or,
		"xor" => Operator::Xor,
		"lshift" => Operator::Lshift,
		"<<" => Operator::Lshift,
		"rshift" => Operator::Rshift,
		">>" => Operator::Rshift,
		"abs" => Operator::Abs,
		"max" => Operator::Max,
		"min" => Operator::Min,
		"invert" => Operator::Invert,
		"negate" => Operator::Negate,

		//custom definitions
		":" => Operator::Define,
		";" => Operator::EndDefine,

		//value or custom operator
		x => {
			let y: Option<i32> = FromStr::from_str(x).ok();
			match y{
				Some(i) => Operator::Value(i),
				None => Operator::Other(format!("other")),
			}
		},
	}
}

fn main() {
	let x = io::stdin();
	let mut vm = VM {state: VMState::Execution,
					 op_stack: vec![],
					 data_stack: vec![],
					 words: HashMap::new(),
				     current_def_word: None};

	loop{
		let mut line: String = "".to_string();
		let _ = x.read_line(&mut line);

		if line.trim() == "" {break;}

		for o in line.rsplit(" "){
			let b = parse(o.trim());
			vm.push_op(b)
		}

		while vm.op_stack.len() > 0 {
			vm.eval();
		}
	}
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::collections::HashMap;
use std::string::String;

pub struct Schema {
    pub id: u32,
    pub name: String,
    pub key_field: u16,
    pub fields: Vec<Field>
}

pub struct Field {
    pub type_id: u32,
    pub name: String,
    pub sub: Option<Vec<Field>>
}

pub fn to_json (schema: Schema) -> String {

}<commit_msg>testing ci<commit_after>use std::any::Any;
use std::collections::HashMap;
use std::string::String;

pub struct Schema {
    pub id: u32,
    pub name: String,
    pub key_field: u16,
    pub fields: Vec<Field>
}

pub struct Field {
    pub type_id: u32,
    pub name: String,
    pub sub: Option<Vec<Field>>
}<|endoftext|>


<commit_before>#[cfg(all(feature = "unstable", test))]
mod benches {
    extern crate test;

    use self::test::Bencher;

    use base::{TreeRepr, TreeBase, TeardownTreeRefill};
    use applied::plain_tree::PlainDeleteInternal;

    type Tree = TreeRepr<usize>;

    #[bench]
    fn bench_delete_range_00100(bencher: &mut Bencher) {
        bench_delete_range_n(100, bencher);
    }

    #[bench]
    fn bench_delete_range_01022(bencher: &mut Bencher) {
        bench_delete_range_n(1022, bencher);
    }

    #[bench]
    fn bench_delete_range_01023(bencher: &mut Bencher) {
        bench_delete_range_n(1023, bencher);
    }

    #[bench]
    fn bench_delete_range_02046(bencher: &mut Bencher) {
        bench_delete_range_n(2046, bencher);
    }

    #[bench]
    fn bench_delete_range_02047(bencher: &mut Bencher) {
        bench_delete_range_n(2047, bencher);
    }

    #[bench]
    fn bench_delete_range_04094(bencher: &mut Bencher) {
        bench_delete_range_n(4094, bencher);
    }

    #[bench]
    fn bench_delete_range_04095(bencher: &mut Bencher) {
        bench_delete_range_n(4095, bencher);
    }

    #[bench]
    fn bench_delete_range_05000(bencher: &mut Bencher) {
        bench_delete_range_n(5000, bencher);
    }

    #[bench]
    fn bench_delete_range_08190(bencher: &mut Bencher) {
        bench_delete_range_n(8190, bencher);
    }

    #[bench]
    fn bench_delete_range_08191(bencher: &mut Bencher) {
        bench_delete_range_n(8191, bencher);
    }

    #[bench]
    fn bench_delete_range_10000(bencher: &mut Bencher) {
        bench_delete_range_n(10000, bencher);
    }

    #[bench]
    fn bench_delete_range_16000(bencher: &mut Bencher) {
        bench_delete_range_n(16000, bencher);
    }

    #[bench]
    fn bench_delete_range_16381(bencher: &mut Bencher) {
        bench_delete_range_n(16381, bencher);
    }

    #[bench]
    fn bench_delete_range_16382(bencher: &mut Bencher) {
        bench_delete_range_n(test::black_box(16382), bencher);
    }

    #[bench]
    fn bench_delete_range_16383(bencher: &mut Bencher) {
        bench_delete_range_n(test::black_box(16383), bencher);
    }

    #[bench]
    fn bench_delete_range_25000(bencher: &mut Bencher) {
        bench_delete_range_n(25000, bencher);
    }

    #[bench]
    fn bench_delete_range_50000(bencher: &mut Bencher) {
        bench_delete_range_n(50000, bencher);
    }

    //    #[bench]
    //    fn bench_delete_range_100000(bencher: &mut Bencher) {
    //        bench_delete_range_n(100000, bencher);
    //    }
    //
    //    #[bench]
    //    fn bench_delete_range_10000000(bencher: &mut Bencher) {
    //        bench_delete_range_n(10000000, bencher);
    //    }

    #[inline(never)]
    fn bench_delete_range_n(n: usize, bencher: &mut Bencher) {
        let elems: Vec<_> = (1..n + 1).collect();

        let perm = {
            // generate a random permutation
            let mut pool: Vec<_> = (1..101).collect();
            let mut perm = vec![];

            use rand::{XorShiftRng, SeedableRng, Rng};

            let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]);

            for i in 0..100 {
                let n: u32 = rng.gen_range(0, 100 - i);
                let next = pool.swap_remove(n as usize);
                perm.push(next);
            }

            perm
        };

        let tree = Tree::new(elems);
        let mut copy = tree.clone();
        let mut output = Vec::with_capacity(tree.size());

        bencher.iter(|| {
            copy.refill(&tree);
            for i in 0..100 {
                output.truncate(0);
                let x = perm[i];
                copy.delete_range((x - 1) * n / 100, x * n / 100, &mut output);
                test::black_box(output.len());
            }
        });
    }
}
<commit_msg>comment out rust_bench, as it's not up to date<commit_after>//#[cfg(all(feature = "unstable", test))]
//mod benches {
//    extern crate test;
//
//    use self::test::Bencher;
//
//    use base::{TreeRepr, TreeBase, TeardownTreeRefill};
//    use applied::plain_tree::PlainDeleteInternal;
//
//    type Tree = TreeRepr<usize>;
//
//    #[bench]
//    fn bench_delete_range_00100(bencher: &mut Bencher) {
//        bench_delete_range_n(100, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_01022(bencher: &mut Bencher) {
//        bench_delete_range_n(1022, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_01023(bencher: &mut Bencher) {
//        bench_delete_range_n(1023, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_02046(bencher: &mut Bencher) {
//        bench_delete_range_n(2046, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_02047(bencher: &mut Bencher) {
//        bench_delete_range_n(2047, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_04094(bencher: &mut Bencher) {
//        bench_delete_range_n(4094, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_04095(bencher: &mut Bencher) {
//        bench_delete_range_n(4095, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_05000(bencher: &mut Bencher) {
//        bench_delete_range_n(5000, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_08190(bencher: &mut Bencher) {
//        bench_delete_range_n(8190, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_08191(bencher: &mut Bencher) {
//        bench_delete_range_n(8191, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_10000(bencher: &mut Bencher) {
//        bench_delete_range_n(10000, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_16000(bencher: &mut Bencher) {
//        bench_delete_range_n(16000, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_16381(bencher: &mut Bencher) {
//        bench_delete_range_n(16381, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_16382(bencher: &mut Bencher) {
//        bench_delete_range_n(test::black_box(16382), bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_16383(bencher: &mut Bencher) {
//        bench_delete_range_n(test::black_box(16383), bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_25000(bencher: &mut Bencher) {
//        bench_delete_range_n(25000, bencher);
//    }
//
//    #[bench]
//    fn bench_delete_range_50000(bencher: &mut Bencher) {
//        bench_delete_range_n(50000, bencher);
//    }
//
//    //    #[bench]
//    //    fn bench_delete_range_100000(bencher: &mut Bencher) {
//    //        bench_delete_range_n(100000, bencher);
//    //    }
//    //
//    //    #[bench]
//    //    fn bench_delete_range_10000000(bencher: &mut Bencher) {
//    //        bench_delete_range_n(10000000, bencher);
//    //    }
//
//    #[inline(never)]
//    fn bench_delete_range_n(n: usize, bencher: &mut Bencher) {
//        let elems: Vec<_> = (1..n + 1).collect();
//
//        let perm = {
//            // generate a random permutation
//            let mut pool: Vec<_> = (1..101).collect();
//            let mut perm = vec![];
//
//            use rand::{XorShiftRng, SeedableRng, Rng};
//
//            let mut rng = XorShiftRng::from_seed([1, 2, 3, 4]);
//
//            for i in 0..100 {
//                let n: u32 = rng.gen_range(0, 100 - i);
//                let next = pool.swap_remove(n as usize);
//                perm.push(next);
//            }
//
//            perm
//        };
//
//
//        let tree = Tree::new(elems);
//        let mut copy = tree.clone();
//        let mut output = Vec::with_capacity(tree.size());
//
//        bencher.iter(|| {
//            copy.refill(&tree);
//            for i in 0..100 {
//                output.truncate(0);
//                let x = perm[i];
//                copy.delete_range((x - 1) * n / 100, x * n / 100, &mut output);
//                test::black_box(output.len());
//            }
//        });
//    }
//}
<|endoftext|>


<commit_before>mod env;

use std::fmt;
use ast::{Expr, Operator, Stmt};
use self::env::Env;

#[derive(Debug, PartialEq, Clone)]
pub enum Value {
    Nil,
    Boolean(bool),
    Number(f64),
    // TODO: Don't copy strings, intern them
    String(String),
}

impl Value {
    pub fn is_truthy(&self) -> bool {
        match *self {
            Value::Nil | Value::Boolean(false) => false,
            _ => true,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Number(val) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "{}", val),
        }
    }
}

pub struct Context {
    current_env: Env,
}

impl Context {
    pub fn new() -> Context {
        Context {
            current_env: Env::root(),
        }
    }
}

pub trait Evaluate {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String>;
}

impl Evaluate for Vec<Stmt> {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String> {
        let mut ret = Value::Nil;
        for stmt in self {
            ret = stmt.eval(ctx)?;
        }
        Ok(ret)
    }
}

impl Evaluate for Stmt {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String> {
        match *self {
            Stmt::ExprStmt(ref expr) => expr.eval(ctx),

            Stmt::Declaration(ref name, ref expr) => {
                let value = expr.eval(ctx)?;
                ctx.current_env.declare(name.clone(), value);
                Ok(Value::Nil)
            }

            Stmt::If(ref condition, ref when_true, ref when_false) => {
                let cond_val = condition.eval(ctx)?;

                if cond_val.is_truthy() {
                    when_true.eval(ctx)?;
                } else {
                    when_false.eval(ctx)?;
                }

                Ok(Value::Nil)
            }

            Stmt::Print(ref expr) => {
                let value = expr.eval(ctx)?;
                println!("{}", value);
                Ok(Value::Nil)
            }
        }
    }
}

impl Evaluate for Expr {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String> {
        match *self {
            Expr::Nil => Ok(Value::Nil),
            Expr::BooleanLiteral(val) => Ok(Value::Boolean(val)),
            Expr::NumberLiteral(val) => Ok(Value::Number(val)),
            Expr::StringLiteral(ref val) => Ok(Value::String(val.clone())),

            Expr::Identifier(ref name) => match ctx.current_env.get(name) {
                Some(value) => Ok(value),
                None => Ok(Value::Nil),
            },

            Expr::Assign(ref name, ref expr) => {
                let expr_val = expr.eval(ctx)?;
                ctx.current_env.assign(name.clone(), expr_val.clone())?;
                Ok(expr_val)
            }

            Expr::UnaryOp(ref op, ref expr) => {
                let expr_val = expr.eval(ctx)?;

                match *op {
                    Operator::Not => Ok(Value::Boolean(!expr_val.is_truthy())),

                    Operator::UnaryMinus => match expr_val {
                        Value::Number(val) => Ok(Value::Number(-val)),
                        other => Err(format!("{} cannot be negated", other)),
                    },

                    ref other => Err(format!("{:?} is not a valid unary operator", other)),
                }
            }

            Expr::BinaryOp(ref op, ref left, ref right) => {
                let left_val = left.eval(ctx)?;
                let right_val = right.eval(ctx)?;

                match *op {
                    // Arithmatic
                    Operator::Add => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l + r)),
                        (Value::String(l), Value::String(r)) => Ok(Value::String(l + &r)),
                        (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                    },

                    Operator::Subtract => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l - r)),
                        (l, r) => Err(format!("{} and {} cannot be subtracted", l, r)),
                    },

                    Operator::Multiply => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l * r)),
                        (l, r) => Err(format!("{} and {} cannot be multiplied", l, r)),
                    },

                    Operator::Divide => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l / r)),
                        (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                    },

                    // Comparison
                    Operator::Equals => Ok(Value::Boolean(left_val == right_val)),
                    Operator::NotEquals => Ok(Value::Boolean(left_val != right_val)),

                    Operator::GreaterThan => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l > r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::GreaterEquals => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l >= r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::LessThan => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l < r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    Operator::LessEquals => match (left_val, right_val) {
                        (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l <= r)),
                        (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                    },

                    ref other => Err(format!("{:?} is not a valid binary operator", other)),
                }
            }
        }
    }
}
<commit_msg>Interpret logical operators<commit_after>mod env;

use std::fmt;
use ast::{Expr, Operator, Stmt};
use self::env::Env;

#[derive(Debug, PartialEq, Clone)]
pub enum Value {
    Nil,
    Boolean(bool),
    Number(f64),
    // TODO: Don't copy strings, intern them
    String(String),
}

impl Value {
    pub fn is_truthy(&self) -> bool {
        match *self {
            Value::Nil | Value::Boolean(false) => false,
            _ => true,
        }
    }

    pub fn is_falsey(&self) -> bool {
        !self.is_truthy()
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Number(val) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "{}", val),
        }
    }
}

pub struct Context {
    current_env: Env,
}

impl Context {
    pub fn new() -> Context {
        Context {
            current_env: Env::root(),
        }
    }
}

pub trait Evaluate {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String>;
}

impl Evaluate for Vec<Stmt> {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String> {
        let mut ret = Value::Nil;
        for stmt in self {
            ret = stmt.eval(ctx)?;
        }
        Ok(ret)
    }
}

impl Evaluate for Stmt {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String> {
        match *self {
            Stmt::ExprStmt(ref expr) => expr.eval(ctx),

            Stmt::Declaration(ref name, ref expr) => {
                let value = expr.eval(ctx)?;
                ctx.current_env.declare(name.clone(), value);
                Ok(Value::Nil)
            }

            Stmt::If(ref condition, ref when_true, ref when_false) => {
                let cond_val = condition.eval(ctx)?;

                if cond_val.is_truthy() {
                    when_true.eval(ctx)?;
                } else {
                    when_false.eval(ctx)?;
                }

                Ok(Value::Nil)
            }

            Stmt::Print(ref expr) => {
                let value = expr.eval(ctx)?;
                println!("{}", value);
                Ok(Value::Nil)
            }
        }
    }
}

impl Evaluate for Expr {
    fn eval(&self, ctx: &mut Context) -> Result<Value, String> {
        match *self {
            Expr::Nil => Ok(Value::Nil),
            Expr::BooleanLiteral(val) => Ok(Value::Boolean(val)),
            Expr::NumberLiteral(val) => Ok(Value::Number(val)),
            Expr::StringLiteral(ref val) => Ok(Value::String(val.clone())),

            Expr::Identifier(ref name) => match ctx.current_env.get(name) {
                Some(value) => Ok(value),
                None => Ok(Value::Nil),
            },

            Expr::Assign(ref name, ref expr) => {
                let expr_val = expr.eval(ctx)?;
                ctx.current_env.assign(name.clone(), expr_val.clone())?;
                Ok(expr_val)
            }

            Expr::UnaryOp(ref op, ref expr) => {
                let expr_val = expr.eval(ctx)?;

                match *op {
                    Operator::Not => Ok(Value::Boolean(!expr_val.is_truthy())),

                    Operator::UnaryMinus => match expr_val {
                        Value::Number(val) => Ok(Value::Number(-val)),
                        other => Err(format!("{} cannot be negated", other)),
                    },

                    ref other => Err(format!("{:?} is not a valid unary operator", other)),
                }
            }

            Expr::BinaryOp(ref op, ref left, ref right) => {
                match *op {
                    // Arithmatic
                    Operator::Add => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l + r)),
                            (Value::String(l), Value::String(r)) => Ok(Value::String(l + &r)),
                            (l, r) => Err(format!("{} and {} cannot be added", l, r)),
                        }
                    }

                    Operator::Subtract => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l - r)),
                            (l, r) => Err(format!("{} and {} cannot be subtracted", l, r)),
                        }
                    }

                    Operator::Multiply => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l * r)),
                            (l, r) => Err(format!("{} and {} cannot be multiplied", l, r)),
                        }
                    }

                    Operator::Divide => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Number(l / r)),
                            (l, r) => Err(format!("{} and {} cannot be divided", l, r)),
                        }
                    }

                    // Comparison
                    Operator::Equals => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        Ok(Value::Boolean(left_val == right_val))
                    }

                    Operator::NotEquals => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        Ok(Value::Boolean(left_val != right_val))
                    }

                    Operator::GreaterThan => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l > r)),
                            (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                        }
                    }

                    Operator::GreaterEquals => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l >= r)),
                            (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                        }
                    }

                    Operator::LessThan => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l < r)),
                            (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                        }
                    }

                    Operator::LessEquals => {
                        let left_val = left.eval(ctx)?;
                        let right_val = right.eval(ctx)?;

                        match (left_val, right_val) {
                            (Value::Number(l), Value::Number(r)) => Ok(Value::Boolean(l <= r)),
                            (l, r) => Err(format!("{} and {} cannot be compared", l, r)),
                        }
                    }

                    // Logic
                    Operator::And => {
                        let left_val = left.eval(ctx)?;

                        if left_val.is_falsey() {
                            Ok(left_val)
                        } else {
                            right.eval(ctx)
                        }
                    }

                    Operator::Or => {
                        let left_val = left.eval(ctx)?;

                        if left_val.is_truthy() {
                            Ok(left_val)
                        } else {
                            right.eval(ctx)
                        }
                    }

                    ref other => Err(format!("{:?} is not a valid binary operator", other)),
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use super::error::CompilerError;
use crate::{builtin_functions::BuiltinFunction, hir, input::Input};
use itertools::Itertools;
use std::fmt::Display;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Lir {
    pub instructions: Vec<Instruction>,
}

pub type StackOffset = usize; // 0 is the last item, 1 the one before that, etc.

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Instruction {
    /// Pushes an int.
    CreateInt(u64),

    /// Pushes a text.
    CreateText(String),

    /// Pushes a symbol.
    CreateSymbol(String),

    /// Pops 2 * num_entries items, pushes a struct.
    ///
    /// a, key, value, key, value, ..., key, value -> a, pointer to struct
    CreateStruct {
        num_entries: usize,
    },

    /// Pushes a closure.
    ///
    /// a -> a, pointer to closure
    CreateClosure {
        captured: Vec<StackOffset>,
        num_args: usize,
        body: Vec<Instruction>,
    },

    /// Pushes a builtin function.
    ///
    /// a -> a, builtin
    CreateBuiltin(BuiltinFunction),

    /// Leaves the top stack item untouched, but removes n below.
    PopMultipleBelowTop(usize),

    /// Pushes an item from back in the stack on the stack again.
    PushFromStack(StackOffset),

    /// Pops a closure and num_args arguments, pushes the current instruction
    /// pointer, all captured variables, and arguments, and then changes the
    /// instruction pointer to the first instruction of the closure.
    ///
    /// a, arg1, arg2, ..., argN, closure -> a, caller, captured vars, arg1, arg2, ..., argN
    ///
    /// Later, when the closure returns (perhaps many instructions after this
    /// one), the stack will contain the result:
    ///
    /// a, arg1, arg2, ..., argN, closure -> a, return value from closure
    Call {
        num_args: usize,
    },

    /// Pops a boolean condition and a reason. If the condition is true, it
    /// just pushes Nothing. If the condition is false, it panic with the
    /// reason.
    ///
    /// a, condition, reason -> a, Nothing
    Needs,

    /// Returns from the current closure to the original caller.
    ///
    /// a, caller, return value -> a, return value
    Return,

    /// Indicates that a fuzzable closure sits at the top of the stack.
    RegisterFuzzableClosure(hir::Id),

    TraceValueEvaluated(hir::Id),
    TraceCallStarts {
        id: hir::Id,
        num_args: usize,
    },
    TraceCallEnds,
    TraceNeedsStarts {
        id: hir::Id,
    },
    TraceNeedsEnds,
    TraceModuleStarts {
        input: Input,
    },
    TraceModuleEnds,

    Error {
        id: hir::Id,
        error: CompilerError,
    },
}

impl Display for Instruction {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Instruction::CreateInt(int) => write!(f, "createInt {int}"),
            Instruction::CreateText(text) => write!(f, "createText {text:?}"),
            Instruction::CreateSymbol(symbol) => write!(f, "createSymbol {symbol}"),
            Instruction::CreateStruct { num_entries } => {
                write!(f, "createStruct {num_entries}")
            }
            Instruction::CreateClosure {
                captured,
                num_args,
                body: instructions,
            } => {
                write!(
                    f,
                    "createClosure with {num_args} {} capturing {}",
                    if *num_args == 1 {
                        "argument"
                    } else {
                        "arguments"
                    },
                    if captured.is_empty() {
                        "nothing".to_string()
                    } else {
                        captured.iter().join(", ")
                    }
                )?;
                for instruction in instructions {
                    let indented = format!("{instruction}")
                        .lines()
                        .map(|line| format!("  {line}"))
                        .join("\n");
                    write!(f, "\n{indented}")?;
                }
                Ok(())
            }
            Instruction::CreateBuiltin(builtin_function) => {
                write!(f, "createBuiltin {builtin_function:?}")
            }
            Instruction::PopMultipleBelowTop(count) => {
                write!(f, "popMultipleBelowTop {count}")
            }
            Instruction::PushFromStack(offset) => write!(f, "pushFromStack {offset}"),
            Instruction::Call { num_args } => {
                write!(f, "call with {num_args} arguments")
            }
            Instruction::Needs => write!(f, "needs"),
            Instruction::Return => write!(f, "return"),
            Instruction::RegisterFuzzableClosure(hir_id) => {
                write!(f, "registerFuzzableClosure {hir_id}")
            }
            Instruction::TraceValueEvaluated(hir_id) => {
                write!(f, "traceValueEvaluated {hir_id}")
            }
            Instruction::TraceCallStarts { id, num_args } => {
                write!(f, "traceCallStarts {id} ({num_args} args)")
            }
            Instruction::TraceCallEnds => write!(f, "traceCallEnds"),
            Instruction::TraceNeedsStarts { id } => {
                write!(f, "traceNeedsStarts {id}")
            }
            Instruction::TraceNeedsEnds => write!(f, "traceNeedsEnds"),
            Instruction::TraceModuleStarts { input } => write!(f, "traceModuleStarts {input}"),
            Instruction::TraceModuleEnds => write!(f, "traceModuleEnds"),
            Instruction::Error { id, error } => write!(f, "error at {id}: {error:?}"),
        }
    }
}
impl Display for Lir {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        for instruction in &self.instructions {
            writeln!(f, "{instruction}")?;
        }
        Ok(())
    }
}
<commit_msg>Update compiler/src/compiler/lir.rs<commit_after>use super::error::CompilerError;
use crate::{builtin_functions::BuiltinFunction, hir, input::Input};
use itertools::Itertools;
use std::fmt::Display;

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Lir {
    pub instructions: Vec<Instruction>,
}

pub type StackOffset = usize; // 0 is the last item, 1 the one before that, etc.

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Instruction {
    /// Pushes an int.
    CreateInt(u64),

    /// Pushes a text.
    CreateText(String),

    /// Pushes a symbol.
    CreateSymbol(String),

    /// Pops 2 * num_entries items, pushes a struct.
    ///
    /// a, key, value, key, value, ..., key, value -> a, pointer to struct
    CreateStruct {
        num_entries: usize,
    },

    /// Pushes a closure.
    ///
    /// a -> a, pointer to closure
    CreateClosure {
        captured: Vec<StackOffset>,
        num_args: usize,
        body: Vec<Instruction>,
    },

    /// Pushes a builtin function.
    ///
    /// a -> a, builtin
    CreateBuiltin(BuiltinFunction),

    /// Leaves the top stack item untouched, but removes n below.
    PopMultipleBelowTop(usize),

    /// Pushes an item from back in the stack on the stack again.
    PushFromStack(StackOffset),

    /// Pops a closure and num_args arguments, pushes the current instruction
    /// pointer, all captured variables, and arguments, and then changes the
    /// instruction pointer to the first instruction of the closure.
    ///
    /// a, arg1, arg2, ..., argN, closure -> a, caller, captured vars, arg1, arg2, ..., argN
    ///
    /// Later, when the closure returns (perhaps many instructions after this
    /// one), the stack will contain the result:
    ///
    /// a, arg1, arg2, ..., argN, closure -> a, return value from closure
    Call {
        num_args: usize,
    },

    /// Pops a boolean condition and a reason. If the condition is true, it
    /// just pushes Nothing. If the condition is false, it panics with the
    /// reason.
    ///
    /// a, condition, reason -> a, Nothing
    Needs,

    /// Returns from the current closure to the original caller.
    ///
    /// a, caller, return value -> a, return value
    Return,

    /// Indicates that a fuzzable closure sits at the top of the stack.
    RegisterFuzzableClosure(hir::Id),

    TraceValueEvaluated(hir::Id),
    TraceCallStarts {
        id: hir::Id,
        num_args: usize,
    },
    TraceCallEnds,
    TraceNeedsStarts {
        id: hir::Id,
    },
    TraceNeedsEnds,
    TraceModuleStarts {
        input: Input,
    },
    TraceModuleEnds,

    Error {
        id: hir::Id,
        error: CompilerError,
    },
}

impl Display for Instruction {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Instruction::CreateInt(int) => write!(f, "createInt {int}"),
            Instruction::CreateText(text) => write!(f, "createText {text:?}"),
            Instruction::CreateSymbol(symbol) => write!(f, "createSymbol {symbol}"),
            Instruction::CreateStruct { num_entries } => {
                write!(f, "createStruct {num_entries}")
            }
            Instruction::CreateClosure {
                captured,
                num_args,
                body: instructions,
            } => {
                write!(
                    f,
                    "createClosure with {num_args} {} capturing {}",
                    if *num_args == 1 {
                        "argument"
                    } else {
                        "arguments"
                    },
                    if captured.is_empty() {
                        "nothing".to_string()
                    } else {
                        captured.iter().join(", ")
                    }
                )?;
                for instruction in instructions {
                    let indented = format!("{instruction}")
                        .lines()
                        .map(|line| format!("  {line}"))
                        .join("\n");
                    write!(f, "\n{indented}")?;
                }
                Ok(())
            }
            Instruction::CreateBuiltin(builtin_function) => {
                write!(f, "createBuiltin {builtin_function:?}")
            }
            Instruction::PopMultipleBelowTop(count) => {
                write!(f, "popMultipleBelowTop {count}")
            }
            Instruction::PushFromStack(offset) => write!(f, "pushFromStack {offset}"),
            Instruction::Call { num_args } => {
                write!(f, "call with {num_args} arguments")
            }
            Instruction::Needs => write!(f, "needs"),
            Instruction::Return => write!(f, "return"),
            Instruction::RegisterFuzzableClosure(hir_id) => {
                write!(f, "registerFuzzableClosure {hir_id}")
            }
            Instruction::TraceValueEvaluated(hir_id) => {
                write!(f, "traceValueEvaluated {hir_id}")
            }
            Instruction::TraceCallStarts { id, num_args } => {
                write!(f, "traceCallStarts {id} ({num_args} args)")
            }
            Instruction::TraceCallEnds => write!(f, "traceCallEnds"),
            Instruction::TraceNeedsStarts { id } => {
                write!(f, "traceNeedsStarts {id}")
            }
            Instruction::TraceNeedsEnds => write!(f, "traceNeedsEnds"),
            Instruction::TraceModuleStarts { input } => write!(f, "traceModuleStarts {input}"),
            Instruction::TraceModuleEnds => write!(f, "traceModuleEnds"),
            Instruction::Error { id, error } => write!(f, "error at {id}: {error:?}"),
        }
    }
}
impl Display for Lir {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        for instruction in &self.instructions {
            writeln!(f, "{instruction}")?;
        }
        Ok(())
    }
}
<|endoftext|>