module test;
import std::io;
import libc;

faultdef NO_MORE_TOKENS;


// While we could have written this with libc
// the C way, let's showcase some features added to C3.
fn void main(String[] args)
{
	// Grab a string from stdin
	String s = io::readline(mem)!!;
	// Delete it at scope end [defer]
	defer free(s);

	// Copy the slice, which doesn't change the underlying data.
	String numbers = s;

	// Track our current value
	int val = 0;

	// Is the current state an add?
	bool add = true;

	while (try String token = read_next(&numbers))
	{
		// We're assuming well formed input here
		// so just use atoi.
		int i = libc::atoi(token.ptr);

		// This value is either added or subtracted from the sum.
		val = add ? val + i : val - i;

		// Read an optional token.
		String? op = read_next(&numbers);

		// If it's an error, then we're done.
		if (catch op) break;

		// Let's process the operator
		switch (op)
		{
			case "+":
				add = true;
			case "-":
				add = false;
			default:
				io::printn("Failed to parse expression.");
				return;
		}
	}
	io::printfn("%d", val);
}

fn String? read_next(String* remaining)
{
	while (remaining.len > 0 && (*remaining)[0] == ' ')
	{
		// Make the slice smaller
		*remaining = (*remaining)[1..];
	}

	// Store the beginning of the parse
	char* ptr_start = remaining.ptr;
	usz len = 0;
	while (remaining.len > 0 && (*remaining)[0] != ' ')
	{
		// Increase length
		len++;

		// And make the slice smaller
		*remaining = (*remaining)[1..];
	}

	// If it's a zero length token, return an optional result.
	if (!len) return NO_MORE_TOKENS~;

	// Otherwise create a slice from the pointer start and length.
	return (String)ptr_start[:len];
}
