~torresjrjr/dc

9af0cd2a34a261e50b40439abed2d6abefe8f726 — Byron Torres 6 months ago ae7c431
handle files
1 files changed, 41 insertions(+), 20 deletions(-)

M dc.ha
M dc.ha => dc.ha +41 -20
@@ 2,6 2,7 @@ use ascii;
use bufio;
use encoding::utf8;
use fmt;
use fs;
use getopt;
use io;
use math;


@@ 14,29 15,41 @@ let S: []f64 = [];
export fn main() void = {
	const help: [_]getopt::help = [
		"desk calculator",
		"[file]",
		"[file ...]",
	];
	const cmd = getopt::parse(os::args, help...);
	defer getopt::finish(&cmd);

	if (len(cmd.args) > 1) {
		usage_exit(help);
	};
	static const buf: [1]u8 = [0...];

	let filename: (str | void) = if (len(cmd.args) == 1)
		switch (cmd.args[0]) {
	for (let i = 0z; i < len(cmd.args); i += 1) {
		const filename = switch (cmd.args[i]) {
		case "-" =>
			fmt::fatal("dc: invalid filename '-'");
		case "" =>
			fmt::fatal("dc: invalid filename ''");
		case =>
			yield cmd.args[0];
		}
	else
		void;
			yield cmd.args[i];
		};

		const file = match (os::open(filename)) {
		case f: io::file =>
			yield f;
		case err: fs::error =>
			fmt::fatal("dc: {} '{}'", fs::strerror(err), filename);
		};
		defer io::close(file);

		const in = bufio::buffered(file, buf, []);
		dc(in);
	};

	dc(os::stdin);
};

fn dc(in: io::handle) void = {
	for (true) {
		const r = match (bufio::scanrune(os::stdin)) {
		const r = match (bufio::scanrune(in)) {
		case utf8::invalid =>
			fmt::fatal("dc: invalid utf8 input");
		case io::error =>


@@ 52,13 65,13 @@ export fn main() void = {
		};

		if (ascii::isdigit(r)) {
			bufio::unreadrune(os::stdin, r);
			push(scan_number());
			bufio::unreadrune(in, r);
			push(scan_number(in));
			continue;
		};

		if (r == '_') {
			push(-scan_number());
			push(-scan_number(in));
			continue;
		};



@@ 69,13 82,13 @@ export fn main() void = {
		// printing
		case 'p' =>
			if (len(S) == 0) {
				fmt::errorln("dc: stack has no elements")?;
				fmt::errorln("dc: stack empty")?;
				continue;
			};
			fmt::println(peek())?;
		case 'n' =>
			if (len(S) == 0) {
				fmt::errorln("dc: stack has no elements")?;
				fmt::errorln("dc: stack empty")?;
				continue;
			};
			fmt::println(pop())?;


@@ 87,8 100,16 @@ export fn main() void = {
		case 'c' =>
			clear();
		case 'd' =>
			if (len(S) == 0) {
				fmt::errorln("dc: stack empty")?;
				continue;
			};
			push(peek());
		case 'r' =>
			if (len(S) < 2) {
				fmt::errorln("dc: stack has too few elements")?;
				continue;
			};
			const b = pop();
			const a = pop();
			push(b);


@@ 102,7 123,7 @@ export fn main() void = {
				const a = S[i];
				delete(S[i]);
				append(S, a);
			} else if (n < 1) {
			} else if (n < -1) {
				const l = len(S): int;
				const n = if (-n < l) -n else l;
				const i = l - n;


@@ 169,12 190,12 @@ export fn main() void = {
	os::exit(1);
};

fn scan_number() f64 = {
fn scan_number(in: io::handle) f64 = {
	let num: []u8 = [];
	defer free(num);
	let seen_decimal = false;
	for (true) {
		const r = match (bufio::scanrune(os::stdin)) {
		const r = match (bufio::scanrune(in)) {
		case utf8::invalid =>
			fmt::fatal("dc: invalid utf8 input");
		case io::error =>


@@ 191,7 212,7 @@ fn scan_number() f64 = {
				seen_decimal = true;
			};
		} else {
			bufio::unreadrune(os::stdin, r);
			bufio::unreadrune(in, r);
			match (strconv::stof64(strings::fromutf8(num))) {
			case (strconv::invalid | strconv::overflow) =>
				abort("dc: invalid numerical input");