#!/bin/env rdmd import std.stdio; import std.process; import std.concurrency; import std.conv; import std.string, std.format; import std.algorithm, std.range; int failures; int main(){ "./test/func.lox".match("-1\n6\n1\n"); "./test/bigsum.lox".match("125250\n"); "./test/biglocals.lox".match("125250\n"); "./test/simplescope.lox".match("abc\nabd\n"); "./test/for.lox".match("1 2 1 2 3 ".replace(' ', '\n')); "./test/ifelse.lox".match("a1 b2 c3 ".replace(' ', '\n')); "./test/while.lox".match("1 2 3 2 1 0 1 1 2 3 2 1 0 1 ".replace(' ', '\n')); "./test/fields.lox".match("0 10 ".replace(' ', '\n')); "./test/ops.lox".match("1\n2\n3\n4\n5\n6\n7\ntrue\nfalse\ntrue\ntrue\nhello, world\n"); "./test/shortcircuit.lox".match("true\nAAAA!\nAAAA!\nAAAA?\n"); "./test/closure.lox".match("1\n2\n"); "./test/scope.lox".match("global first first second first ".replace(' ', '\n')); "./test/fib_for.lox".match(fib(6765)); "./test/fib_recursive.lox".match(fib(34)); "./test/fib_closure.lox".match(fib(34)); "./test/perverseclosure.lox".match("return from outer create inner closure value ".replace(" ", "\n")); "./test/class.lox".match("The German chocolate cake is delicious!\n"); "./test/methods.lox".match("Enjoy your cup of coffee and chicory\nnot a method\n"); "./test/super.lox".match("Fry until golden brown.\nPipe full of custard and coat with chocolate.\nA method\n"); "./test/err/invalid_syntax.lox".shouldFail(RetVal.other); "./test/err/already_defined.lox".shouldFail(RetVal.other, "Already a variable with this name"); "./test/err/undefined_var.lox".shouldFail(RetVal.runtime, "Undefined variable"); "./test/err/self_ref_vardecl.lox".shouldFail(RetVal.runtime, "Undefined variable"); "./test/err/global_scope_return.lox".shouldFail(RetVal.other, "Can't return from top-level code"); "./test/err/super_outside_class.lox".shouldFail(RetVal.other, "Can't use 'super' outside of a class"); "./test/err/super_without_superclass.lox".shouldFail(RetVal.other, "Can't use 'super' in a class with no superclass"); return failures; } enum RetVal{ success = 0, other = 65, runtime = 70 } string fib(uint n){ string r = ""; double a = 0; double temp; for(double b = 1; a <= n; b = temp + b){ r ~= a.to!string ~ "\n"; temp = a; a = b; } return r; } auto run(string file, Config.Flags f = Config.Flags.stderrPassThrough) => [ "./lox", file ].execute(null, Config(f)); void match(string file, string correct){ auto res = file.run.output; if(res != correct){ stderr.writeln("Match %s failed\n-- Got --\n%s\n-- Expected --\n%s".format(file, res, correct)); failures++; } } void shouldFail(string file, int code = 1, string msg = null){ auto c = file.run(Config.Flags.none); if(!(c.status == code)){ stderr.writeln("Expected %s to fail with code %d but got %d".format(file, code, c.status)); failures++; return; } if(!(!msg || c.output.toLower.indexOf(msg.toLower) >= 0)){ stderr.writeln("ShouldFail %s failed\n-- Got --\n%s\n-- Expected --\n%s".format(file, c.output, msg)); failures++; return; } if(!(c.output.indexOf("_Dmain") == -1)){ stderr.writeln("ShouldFail %s got D exception\n%s".format(file, c.output)); failures++; return; } }