Skip to content

Commit

Permalink
Merge branch 'tap_stream'
Browse files Browse the repository at this point in the history
  • Loading branch information
Whiteknight committed Sep 10, 2011
2 parents 8f265cc + fa265df commit d8dfe10
Show file tree
Hide file tree
Showing 18 changed files with 161 additions and 92 deletions.
1 change: 1 addition & 0 deletions setup.winxed
Expand Up @@ -206,6 +206,7 @@ function setup_stable_libraries(var rosella)
"filesystem/FileIterator",
"filesystem/FilePath",
"filesystem/FileSystem",
"filesystem/IterableHandle",
"filesystem/Visitor",
"filesystem/visitor/Delete",
"filesystem/visitor/Function",
Expand Down
5 changes: 2 additions & 3 deletions src/core/IO.winxed
Expand Up @@ -52,11 +52,10 @@ namespace Rosella
err_func(e);
}
swap_handles(save_handles);
string stdout_text = stdout.readall();
if (together)
return stdout_text;
return stdout;
else
return stdout_text, stderr.readall();
return stdout, stderr;
}

function execute_pipe(string cmd,
Expand Down
5 changes: 2 additions & 3 deletions src/filesystem/FileIterator.winxed
Expand Up @@ -21,7 +21,6 @@ namespace Rosella.FileSystem
{
if (self.handle != null && !self.handle.is_closed())
self.handle.close();
say("Closed");
}

function FileIterator(string filename)
Expand All @@ -45,7 +44,7 @@ namespace Rosella.FileSystem
{
if (self.handle == null)
self.handle = self.file.open_read();
string line = self.handle.readline_interactive();
string line = self.handle.readline();
if (line == null)
return "";
return line;
Expand All @@ -55,7 +54,7 @@ namespace Rosella.FileSystem
{
if (self.handle == null)
self.handle = self.file.open_read();
string line = self.handle.readline_interactive();
string line = self.handle.readline();
if (line == null)
return "";
return line;
Expand Down
7 changes: 7 additions & 0 deletions src/filesystem/FileSystem.winxed
Expand Up @@ -76,5 +76,12 @@ namespace Rosella
string path_sep = path_separator();
return join(path_sep, parts);
}

function iterable_handle(var handle)
{
if (handle instanceof "Handle")
return new Rosella.FileSystem.IterableHandle(handle);
Rosella.Error.invalid(__FUNCTION__, "handle_iterator expects a Handle object");
}
}
}
18 changes: 18 additions & 0 deletions src/filesystem/IterableHandle.winxed
@@ -0,0 +1,18 @@
namespace Rosella.FileSystem
{
class IterableHandle
{
var handle;
function IterableHandle(var handle)
{
self.handle = handle;
}

function handle() { return self.handle; }

function get_iter[vtable]()
{
return new Rosella.FileSystem.FileIterator(self.handle);
}
}
}
3 changes: 0 additions & 3 deletions src/harness/Harness.winxed
Expand Up @@ -70,13 +70,10 @@ namespace Rosella
function run(var test_runs [optional], int has_runs [opt_flag],
var view [optional], int has_view [opt_flag],
int run_inline [named,optional], int has_ri [opt_flag],
int line_length [named,optional], int has_ll [opt_flag],
int debug [named,optional], int has_dbg [opt_flag])
{
if (!has_ri)
run_inline = 0;
if (!has_ll)
line_length = 0;
if (!has_dbg)
debug = 0;
if (has_view == 0 || view == null)
Expand Down
72 changes: 31 additions & 41 deletions src/harness/TapParser.winxed
Expand Up @@ -14,35 +14,27 @@ namespace Rosella { namespace Harness
]);
}

function parse(string text, var result)
function parse(var stream, var result)
{
self.tokenizer.add_data(text);
if (!self.tokenizer.has_tokens() || !self.get_plan(result)) {
var plan_stream = stream
.take(1)
.map(function(l) {
self.tokenizer.add_data(l);
return self.get_plan(self.tokenizer.all_tokens(), result);
});
if (plan_stream.has_more() == false || plan_stream.next() == false) {
result.mark_test_empty();
return;
}
self.parse_internal(result);
}

function get_plan(var result)
{
if (self.tokenizer.get_token().data() != "1" ||
self.tokenizer.get_token().data() != "..")
return false;

int num_cclass = Rosella.String.get_character_class("numeric");
var plan_t = self.tokenizer.get_token();
if (plan_t.metadata() != num_cclass || indexof("\n", self.tokenizer.get_token().data()) == -1)
return false;

string lim = plan_t.data();
result.set_plan(int(lim));
return true;
}

function parse_internal(var result)
{
Rosella.Query.as_queryable(self.get_lines())
stream
.clear_stages()
.map(function(l) {
self.tokenizer.add_data(l);
return Rosella.Query.as_stream(self.tokenizer)
.filter(function(t) { return int(t.metadata()) != 0; })
.map(function(t) { return t.data(); })
.data();
})
.filter(function(l) { return elements(l) >= 2 && substr(l[0], 0, 1) != "#"; })
.map(function(l) {
int i = 0;
Expand All @@ -68,25 +60,23 @@ namespace Rosella { namespace Harness
return [name, num, result, 1];
return [name, num, result, 0];
})
.foreach(function(r) { result.*(r[2] == 1 ? "add_pass" : "add_fail")(r[0], r[1], r[3]); });
.foreach(function(r) { result.*(r[2] == 1 ? "add_pass" : "add_fail")(r[0], r[1], r[3]); })
.execute();
}

function get_lines()
function get_plan(var tokens, var result)
{
var lines = [[]];
int i = 0;
while(self.tokenizer.has_tokens()) {
var t = self.tokenizer.get_token();
string d = t.data();
if (indexof("\n", d) != -1) {
i++;
lines[i] = [];
continue;
}
if (int(t.metadata()) != 0)
push(lines[i], d);
}
return lines;
if (tokens[0].data() != "1" || tokens[1].data() != "..")
return false;

var plan_t = tokens[2];
int num_cclass = Rosella.String.get_character_class("numeric");
if (plan_t.metadata() != num_cclass)
return false;

string lim = plan_t.data();
result.set_plan(int(lim));
return true;
}
}
}}
46 changes: 29 additions & 17 deletions src/harness/TestExecutor.winxed
Expand Up @@ -15,42 +15,54 @@ namespace Rosella { namespace Harness
function run(var view, var file, var parser, int debug)
{
var result = new Rosella.Harness.FileResult(file);
// TODO: Instead of a complete blob of text, return a queryable
// stream of input so we can get real-time test counts
var text;
var stream;
if (int(self.mode) == MODE_COMPILE_INLINE)
text = self.compile_and_execute(view, file, result, debug);
stream = self.compile_and_execute(file, debug);
else
text = self.spawn_and_execute(view, file, result, debug);

stream = self.open_pipe_stream(file);
if (result.status == null || result.status != "ABORTED")
parser.parse(text, result);
parser.parse(stream, result);
int exit_status = self.close_stream(file, stream);
if (exit_status != 0 || (result.status != null && result.status == "ABORTED"))
result.mark_test_abort("Test aborted with exit code " + string(exit_status));
return result;
}

function compile_and_execute(var view, var file, var result, int debug)
function compile_and_execute(var file, int debug)
{
var sub = file.compile_test();
string output = Rosella.IO.capture_output(1, sub,
var handle = Rosella.IO.capture_output(1, sub,
function(e) {
result.mark_test_abort(e);
view.debug(debug, e["message"]);
}
);
return output;
var ihandle = Rosella.FileSystem.iterable_handle(handle);
return Rosella.Query.as_stream(ihandle);
}

function close_stream(var file, var stream)
{
int exit_code = stream.on_data(function(ih) {
var handle = ih.handle();
handle.close();
int can_exit_status;
${ can can_exit_status, handle, "exit_status" };
return can_exit_status == 1 ? handle.exit_status() : 0;
});
file.cleanup_spawn();
return exit_code;
}

function spawn_and_execute(var view, var file, var result, int debug)
function open_pipe_stream(var file)
{
string filename = file.setup_spawn();
if (filename == null)
return "";
return null;
string cmd = file.get_spawn_command(filename);
string output = Rosella.IO.execute_pipe(cmd, function(ec) {
result.mark_test_abort("Test aborted with exit code " + string(ec));
});
file.cleanup_spawn(filename);
return output;
var pipe = Rosella.IO.open_pipe(cmd);
var ihandle = Rosella.FileSystem.iterable_handle(pipe);
return Rosella.Query.as_stream(ihandle);
}
}
}}
2 changes: 1 addition & 1 deletion src/harness/TestFile.winxed
Expand Up @@ -35,6 +35,6 @@ namespace Rosella { namespace Harness
Rosella.Error.must_subclass(__CLASS__);
}

function cleanup_spawn(string filename) { }
function cleanup_spawn() { }
}
}}
4 changes: 2 additions & 2 deletions src/harness/testfile/NQP.winxed
Expand Up @@ -7,9 +7,9 @@ namespace Rosella { namespace Harness { namespace TestFile
{
function NQP(var p [slurpy]) { self.TestFile(p:[flat]); }

function compile_test(string filename)
function compile_test()
{
var file = new Rosella.FileSystem.File(filename);
var file = new Rosella.FileSystem.File(string(self));
string code = file.read_all_text();
var compiler = compreg('NQP-rx');
var result = compiler.compile(code);
Expand Down
4 changes: 2 additions & 2 deletions src/harness/testfile/PIR.winxed
Expand Up @@ -9,10 +9,10 @@ namespace Rosella { namespace Harness { namespace TestFile
{
function PIR(var p [slurpy]) { self.TestFile(p:[flat]); }

function compile_test(string filename)
function compile_test()
{
var compiler = compreg("PIR");
var packfile = compiler.compile_file(filename);
var packfile = compiler.compile_file(string(self));
return packfile.main_sub();
}

Expand Down
4 changes: 2 additions & 2 deletions src/harness/testfile/Winxed.winxed
Expand Up @@ -7,10 +7,10 @@ namespace Rosella { namespace Harness { namespace TestFile
{
function Winxed(var p [slurpy]) { self.TestFile(p:[flat]); }

function compile_test(string filename)
function compile_test()
{
var winxed = compreg("winxed");
return winxed.compile_file(filename);
return winxed.compile_file(string(self));
}

function get_spawn_command(string filename)
Expand Down
1 change: 1 addition & 0 deletions src/include/FileSystem.winxed
Expand Up @@ -7,6 +7,7 @@ namespace Rosella {
extern function is_directory;
extern function path_separator;
extern function join_path_parts;
extern function iterable_handle;

// src/filesystem/Directory.winxed
class Directory;
Expand Down
1 change: 1 addition & 0 deletions src/include/Query.winxed
Expand Up @@ -3,6 +3,7 @@ namespace Rosella {
class Provider;
class Queryable;
extern function as_queryable;
extern function as_stream;
extern function is_array;
extern function is_hash;
extern function array_or_hash;
Expand Down
5 changes: 5 additions & 0 deletions src/query/Query.winxed
Expand Up @@ -22,6 +22,11 @@ namespace Rosella
return new Rosella.Query.Queryable(data);
}

function as_stream(var data)
{
return new Rosella.Query.Queryable.Stream(data);
}

// Helper function. Determine if the aggregate is an array
function is_array(var data)
{
Expand Down
29 changes: 28 additions & 1 deletion src/query/Stage.winxed
Expand Up @@ -63,7 +63,8 @@ namespace Rosella.Query
:(var is_valid, var value) = self.previous.next();
if (!is_valid)
return false, null;
var(self.func)(value);
var f = self.func;
f(value);
return true, value;
}
}
Expand Down Expand Up @@ -231,5 +232,31 @@ namespace Rosella.Query
return false, null;
}
}

class Project : Rosella.Query.Stage
{
var cache;
function Project(var p, var f)
{
self.Stage(p, f);
self.cache = [];
}

function next()
{
if (elements(self.cache) > 0)
return true, self.cache.shift();
:(int is_valid, var value) = self.previous.next();
if (!is_valid)
return false, null;
var f = self.func;
var results = f(value);
for (var r in results)
push(self.cache, r);
if (elements(self.cache) > 0)
return true, self.cache.shift();
return false, null;
}
}
}
}

0 comments on commit d8dfe10

Please sign in to comment.