shithub: purgatorio

ref: a411870ee4640241e3c494367d922847da84f972
dir: purgatorio/appl/cmd/seq.b

View raw version
implement Seq;

include "sys.m";
	sys: Sys;

include "draw.m";

include "arg.m";

include "bufio.m";
	bio: Bufio;
	Iobuf: import bio;

Seq: module {
	init: fn(nil: ref Draw->Context, args: list of string);
};

out: ref Iobuf;

# Print a sequence of numbers in steps of a given increment
init(nil: ref Draw->Context, args: list of string) {
	sys = load Sys Sys->PATH;
	arg := load Arg Arg->PATH;
	if(arg == nil)
		raise "Arg is nil";
	bio = load Bufio Bufio->PATH;
	if(bio == nil)
		raise "Bio is nil";

	arg->init(args);
	out = bio->open("/fd/1", bio->OWRITE);

	# TODO: [-w] [-f format]
	# Note: Limbo doesn't seem to like non-constant format specifiers
	arg->setusage("seq [first [increment]] last");
	args = arg->argv();
	argc := len(args);

	step := 1.0;
	first := 1.0;
	last: real;
	printer: ref fn(i: real) = iprint;

	case argc {
	1 => 
		# Seq [1,last]
		last = real hd args;
	2 =>
		# Seq [first,last]
		first = real hd args;
		last = real hd tl args;
	3 =>
		# Seq [first,last] by step increment
		first = real hd args;
		step = real hd tl args;
		last = real hd tl tl args;
	* => arg->usage();
	}

	if(isfloat(first) || isfloat(step) || isfloat(last))
		printer = rprint;

	# Iterate
	for(i := first; i <= last; i += step)
		printer(i);

	out.flush();
	out.close();
	exit;
}

# Print int
iprint(i: real) {
	out.puts(sys->sprint("%d\n", int i));
}

# Print real
rprint(i: real) {
	out.puts(sys->sprint("%g\n", i));
}

# Determine if functionally float by truncating and comparing the difference
# 2.5 - 2.0 = 0.5 != 0.0 ;; 3.0 - 3.0 = 0.0 == 0.0
isfloat(r: real): int {
	i := int r;
	ir := real i;

	if(r - ir == 0.0)
		return 0;

	return 1;
}