Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
c2d6dbf
begin working on checker api (see TM030)
awstlaur Dec 28, 2016
efd3350
set up reason/fancy-reason differentiator
awstlaur Dec 28, 2016
51be9a8
Merge branch 'horizon' into checker-api
awstlaur Dec 30, 2016
f05dd21
make --run work, modulu exit codes
awstlaur Dec 30, 2016
f305fc0
revert unnecessary diff
awstlaur Dec 30, 2016
3deb191
propogate exit code correctly
awstlaur Jan 3, 2017
4fbe82c
render error and exit correctly on runtime errors
awstlaur Jan 3, 2017
7ba2c4b
defer all work to results-report
awstlaur Jan 4, 2017
1f781f6
update broken load-lib test
awstlaur Jan 4, 2017
b9a6e04
add print to type-check main.arr
awstlaur Jan 4, 2017
12fda50
Revert "add print to type-check main.arr"
awstlaur Jan 4, 2017
5b020fa
investigate timeout on travis ci#fx-run
awstlaur Jan 4, 2017
e3f93d6
okay now that test works
awstlaur Jan 4, 2017
c4573ba
fix invalid option: s/compiled-dir/compiled-cache/
awstlaur Jan 5, 2017
d1fb5bc
Revert "investigate timeout on travis ci#fx-run"
awstlaur Jan 5, 2017
caa3f9d
clean up load-lib
awstlaur Jan 5, 2017
ac1f136
add phaseX scripts
awstlaur Jan 5, 2017
0445c70
re-add raise for compilation error
awstlaur Jan 6, 2017
45e1837
revert to raise semantics for compilation errors
awstlaur Jan 6, 2017
798965c
disallow run-phase to be run directly - must be run via a phaseX symlink
awstlaur Jan 6, 2017
9f84117
fix throwInternalError call
awstlaur Jan 11, 2017
29fdb98
switch to command-line interface
awstlaur Jan 11, 2017
9d22cb7
make ffi.toJSON behave more like json-struct's to-json
awstlaur Jan 11, 2017
52129d5
make message optional - use in results-summary
awstlaur Jan 11, 2017
debf728
Merge branch 'fix-run' into checker-api
awstlaur Jan 12, 2017
8b4f598
make resumeWith.message a js string
awstlaur Jan 12, 2017
2332319
Merge branch 'fix-run' into checker-api
awstlaur Jan 12, 2017
e66ccfb
make compile/run error report output json as well
awstlaur Jan 12, 2017
c1236f6
add maybe-surface-parse to capture parse errors in an Either
awstlaur Jan 13, 2017
e6e86b4
maybe-surface-parse: implementation and tests
awstlaur Jan 13, 2017
c1f09b7
Revert "add maybe-surface-parse to capture parse errors in an Either"
awstlaur Jan 14, 2017
30b7c0d
Merge branch 'horizon' into checker-api
awstlaur Jan 14, 2017
4310b1a
Merge branch 'maybe-surface-parse' into checker-api
awstlaur Jan 14, 2017
fc18dfa
leverage maybe-surface-parse
awstlaur Jan 14, 2017
4eee725
Merge branch 'horizon' into fix-run
awstlaur Jan 14, 2017
c5fc30e
fix get-stack for rendering check results
awstlaur Jan 14, 2017
d654aaa
Merge branch 'fix-run' into checker-api
awstlaur Jan 14, 2017
c57233c
fix get-stack for renderCheckReport
awstlaur Jan 14, 2017
cfc8b9d
Merge branch 'horizon' into checker-api
awstlaur Feb 1, 2017
d4ec4ea
Merge branch 'horizon' into fix-run
awstlaur Feb 1, 2017
75ed2c9
checkout horizon's pyret.arr and handalone.js
awstlaur Feb 7, 2017
0658df1
Merge branch 'horizon' into fix-run
awstlaur Feb 7, 2017
32a7d90
re-instate the propogation of information from CLI.run
awstlaur Feb 7, 2017
99aa480
propagate exit while using the --run flag
awstlaur Feb 16, 2017
30d8e0d
document run-phase scripts in README
awstlaur Feb 26, 2017
236b4a6
Merge branch 'fix-run' into checker-api
awstlaur Mar 9, 2017
b885758
re-add run-full-report flag
awstlaur Mar 21, 2017
b0828e3
add timestamp to checker api report
awstlaur Mar 27, 2017
117cccc
capture output to include in final report
awstlaur Mar 31, 2017
e08ecf6
add note about exit code (vis a vis error report)
awstlaur Mar 31, 2017
6c3ecaf
change captureOutput to be a separate argument
awstlaur Apr 1, 2017
83fa9a7
remove stray line
awstlaur Apr 1, 2017
e027035
Merge branch 'horizon' into checker-api
awstlaur Apr 1, 2017
f338f58
remove stray comments
awstlaur Apr 1, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions src/arr/compiler/cli-module-loader.arr
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import string-dict as SD
import render-error-display as RED
import file as F
import filelib as FS
import error as ERR
import system as SYS
import parse-pyret as PP
import file("js-ast.arr") as J
import file("concat-lists.arr") as C
import file("compile-lib.arr") as CL
Expand Down Expand Up @@ -334,7 +334,7 @@ fun run(path, options):
| left(problems) =>
handle-compilation-errors(problems, options)
| right(program) =>
result = L.run-program(R.make-runtime(), L.empty-realm(), program.js-ast.to-ugly-source(), options)
result = L.run-program(R.make-runtime(), L.empty-realm(), program.js-ast.to-ugly-source(), options, false)
if L.is-success-result(result):
L.render-check-results(result)
else:
Expand All @@ -344,6 +344,61 @@ fun run(path, options):
end
end

fun run-full-report(path, options):
maybe-ast = PP.maybe-surface-parse(F.file-to-string(path), path)
cases(Either) maybe-ast:
| left(e) =>
rendered-problems = [list: e.message, RED.display-to-string(e.exn.render-reason(), torepr, empty)]
obj = JSON.to-json([SD.string-dict:
"timestamp", time-now(),
"is-error", true,
"message", "There were parse errors",
"error", rendered-problems,
"report", [SD.string-dict:
"result", nothing,
"stats", nothing
]
])
{
message: obj.serialize(),
exit-code: 0
}
| right(_) =>
maybe-program = build-program(path, options)
cases(Either) maybe-program block:
| left(problems) =>
rendered-problems =
for map(e from problems):
RED.display-to-string(e.render-reason(), torepr, empty)
end
obj = JSON.to-json([SD.string-dict:
"timestamp", time-now(),
"is-error", true,
"message", "There were compilation errors",
"error", rendered-problems,
"report", [SD.string-dict:
"result", nothing,
"stats", nothing
]
])
{
message: obj.serialize(),
exit-code: 0
}
| right(program) =>
result = L.run-program(R.make-runtime(), L.empty-realm(), program.js-ast.to-ugly-source(), options, true)
if L.is-success-result(result):
L.render-check-report(result)
else:
# NOTE(awstlaur): Any exit code, even 0, results in checks being
# skipped. Thus, it's okay to render "Exited with code 0" as an
# error in this context.
L.render-error-report(result)
end
end
end
end

fun build-program(path, options) block:
doc: ```Returns the program as a JavaScript AST of module list and dependency map,
and its native dependencies as a list of strings```
Expand Down
11 changes: 11 additions & 0 deletions src/arr/compiler/pyret.arr
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ fun main(args :: List<String>) -> Number:
C.next-val(C.String, C.once, "Pyret (.arr) file to build"),
"run",
C.next-val(C.String, C.once, "Pyret (.arr) file to compile and run"),
"run-full-report",
C.next-val(C.String, C.once, "Pyret (.arr) file to compile and run"),
"standalone-file",
C.next-val-default(C.String, "src/js/base/handalone.js", none, C.once, "Path to override standalone JavaScript file for main"),
"builtin-js-dir",
Expand Down Expand Up @@ -174,6 +176,15 @@ fun main(args :: List<String>) -> Number:
})
_ = print(result.message + "\n")
result.exit-code
else if r.has-key("run-full-report"):
result = CLI.run-full-report(r.get-value("run-full-report"), CS.default-compile-options.{
standalone-file: standalone-file,
compile-module: true,
display-progress: false,
check-all: check-all
})
_ = print(result.message + "\n")
result.exit-code
else:
_ = print(C.usage-info(options).join-str("\n"))
_ = print("Unknown command line options\n")
Expand Down
207 changes: 155 additions & 52 deletions src/arr/trove/checker.arr
Original file line number Diff line number Diff line change
Expand Up @@ -691,73 +691,166 @@ fun make-check-context(main-module-name :: String, check-all :: Boolean):
}
end

fun make-test-reporter(maybe-stack-loc, src-available, maybe-ast) -> (TestResult -> {}):
lam(test-result):
loc-formatted = test-result.loc.format(false)
cases(TestResult) test-result:
| success(loc) =>
{
passed: true,
reason: "",
fancy-reason: "",
loc: loc-formatted
}
| else =>
reason = test-result.render-reason()
fancy-reason = test-result.render-fancy-reason(maybe-stack-loc, src-available, maybe-ast)
{
passed: false,
reason: RED.display-to-string(reason, torepr, empty),
fancy-reason: RED.display-to-string(fancy-reason, torepr, empty),
loc: loc-formatted
}
end
end
end

# NOTE(joe): get-stack lets us hide the stack from Pyret's semantics, and
# require that magical callers provide a get-stack function that produces
# the list of locations to render
fun results-summary(block-results :: List<CheckBlockResult>, get-stack):
init = {
message: "",
errored: 0,
fun results-report(block-results :: List<CheckBlockResult>, include-messages, get-stack, maybe-stack-loc, src-available, maybe-ast):
get-message =
if (include-messages):
lam(obj):
obj.message
end
else:
lam(obj):
""
end
end
with-message =
if (include-messages):
lam(obj, message):
obj.{message: message}
end
else:
lam(obj, message):
obj
end
end

initBlock = with-message({
passed: 0,
failed: 0,
total: 0
}, "")
initComplete = initBlock.{
errored: 0,
blocks: empty
}
complete-summary = for fold(summary from init, br from block-results.reverse()):
block-summary = for fold(s from init, tr from br.test-results.reverse()):
cases(TestResult) tr:
| success(loc) => s.{
message: s.message + "\n " + loc.format(false) + ": ok",
passed: s.passed + 1,
total: s.total + 1
}
| else =>
m = s.message + "\n " + tr.loc.format(false) + ": failed because: \n "
+ RED.display-to-string(tr.render-reason(), torepr, empty)
s.{
message: m,
failed: s.failed + 1,
total: s.total + 1
}
end
end
ended-in-error = cases(Option) br.maybe-err:
| none => ""

test-reporter = make-test-reporter(maybe-stack-loc, src-available, maybe-ast)
complete-summary = for fold(summary from initComplete, br from block-results.reverse()):
test-reports = br.test-results.reverse().map(test-reporter)
error-reason = cases(Option) br.maybe-err:
| none =>
{
is-error: false,
reason: ""
}
| some(err) =>
stack = get-stack(err)
"\n Block ended in the following error (all tests may not have ran): \n\n "
+ RED.display-to-string(exn-unwrap(err).render-reason(), torepr, stack)
+ RED.display-to-string(ED.v-sequence(lists.map(ED.loc, stack)), torepr, empty)
+ "\n\n"
{
is-error: true,
reason: "\n Block ended in the following error (all tests may not have ran): \n\n "
+ RED.display-to-string(exn-unwrap(err).render-reason(), torepr, stack)
+ RED.display-to-string(ED.v-sequence(lists.map(ED.loc, stack)), torepr, empty)
+ "\n\n"
}
end
message = summary.message + "\n\n" + br.loc.format(true) + ": " + br.name + " (" + tostring(block-summary.passed) + "/" + tostring(block-summary.total) + ") \n"
with-error-notification = message + ended-in-error
rest-of-message =
if block-summary.failed == 0: ""
else: block-summary.message
block-summary = for fold(s from initBlock, tr from test-reports):
if (tr.passed):
with-message(s.{
passed: s.passed + 1,
total: s.total + 1
}, get-message(s) + "\n " + tr.loc + ": ok")
else:
with-message(s.{
failed: s.failed + 1,
total: s.total + 1
}, get-message(s) + "\n " + tr.loc + ": failed because: \n " + tr.reason)
end
{
message: with-error-notification + rest-of-message,
errored: summary.errored + if is-some(br.maybe-err): 1 else: 0 end,
passed: summary.passed + block-summary.passed,
failed: summary.failed + block-summary.failed,
total: summary.total + block-summary.total
end.{
is-error: error-reason.is-error,
reason: error-reason.reason,
tests: test-reports
}
end
if (complete-summary.total == 0) and (complete-summary.errored == 0):
complete-summary.{message: "The program didn't define any tests."}
else if (complete-summary.failed == 0) and (complete-summary.errored == 0):
happy-msg = if complete-summary.passed == 1:
"Looks shipshape, your test passed, mate!"

ended-in-error = block-summary.reason

message =
if (include-messages):
prefix = summary.message + "\n\n" + br.loc.format(true) + ": " + br.name + " (" + tostring(block-summary.passed) + "/" + tostring(block-summary.total) + ") \n"
with-error-notification = prefix + ended-in-error
rest-of-message =
if block-summary.failed == 0: ""
else: block-summary.message
end
with-error-notification + rest-of-message
else:
"Looks shipshape, all " + tostring(complete-summary.passed) + " tests passed, mate!"
""
end
complete-summary.{message: happy-msg}
else:
c = complete-summary
c.{
message: c.message + "\n\nPassed: " + tostring(c.passed) + "; Failed: " + tostring(c.failed) + "; Ended in Error: " + tostring(c.errored) + "; Total: " + tostring(c.total) + "\n"
}

with-message({
errored: summary.errored + if block-summary.is-error: 1 else: 0 end,
passed: summary.passed + block-summary.passed,
failed: summary.failed + block-summary.failed,
total: summary.total + block-summary.total,
blocks: link(block-summary, summary.blocks)
}, message)
end

complete-summary-with-happy-msg =
if (complete-summary.total == 0) and (complete-summary.errored == 0):
complete-summary.{message: "The program didn't define any tests."}
else if (complete-summary.failed == 0) and (complete-summary.errored == 0):
happy-msg = if complete-summary.passed == 1:
"Looks shipshape, your test passed, mate!"
else:
"Looks shipshape, all " + tostring(complete-summary.passed) + " tests passed, mate!"
end
complete-summary.{message: happy-msg}
else:
c = complete-summary
prefix =
if (include-messages):
c.message + "\n\n"
else:
""
end
c.{
message: prefix + "Passed: " + tostring(c.passed) + "; Failed: " + tostring(c.failed) + "; Ended in Error: " + tostring(c.errored) + "; Total: " + tostring(c.total) + "\n"
}
end

complete-summary-with-happy-msg.{
blocks: complete-summary.blocks.reverse()
}
end

fun results-summary(block-results :: List<CheckBlockResult>, get-stack):
maybe-stack-loc = lam(x,y): none end
maybe-ast = lam(x): none end
test-report = results-report(block-results, true, get-stack, maybe-stack-loc, SL.is-srcloc, maybe-ast)

{
message: test-report.message,
errored: test-report.errored,
passed: test-report.passed,
failed: test-report.failed,
total: test-report.total
}
end

fun render-check-results(block-results):
Expand All @@ -767,3 +860,13 @@ end
fun render-check-results-stack(block-results :: List<CheckBlockResult>, get-stack):
results-summary(block-results, get-stack)
end

fun render-check-report(block-results):
render-check-report-stack(block-results, lam(err): empty end)
end

fun render-check-report-stack(block-results :: List<CheckBlockResult>, get-stack):
maybe-stack-loc = lam(x,y): none end
maybe-ast = lam(x): none end
results-report(block-results, false, get-stack, maybe-stack-loc, SL.is-srcloc, maybe-ast)
end
3 changes: 3 additions & 0 deletions src/js/base/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -5565,6 +5565,9 @@ function (Namespace, jsnums, codePoint, seedrandom, util) {
'setStdout': function(newStdout) {
theOutsideWorld.stdout = newStdout;
},
'setStderr': function(newStderr) {
theOutsideWorld.stderr = newStderr;
},
'getParam' : getParam,
'getParamOrSetDefault' : getParamOrSetDefault,
'setParam' : setParam,
Expand Down
Loading