Adding all tracks, I guess
This commit is contained in:
51
sml/hello-world/README.md
Normal file
51
sml/hello-world/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Hello World
|
||||
|
||||
The classical introductory exercise. Just say "Hello, World!".
|
||||
|
||||
["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is
|
||||
the traditional first program for beginning programming in a new language
|
||||
or environment.
|
||||
|
||||
The objectives are simple:
|
||||
|
||||
- Write a function that returns the string "Hello, World!".
|
||||
- Run the test suite and make sure that it succeeds.
|
||||
- Submit your solution and check it at the website.
|
||||
|
||||
If everything goes well, you will be ready to fetch your first real exercise.
|
||||
|
||||
## Loading your exercise implementation in PolyML
|
||||
|
||||
```
|
||||
$ poly --use {exercise}.sml
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```
|
||||
$ poly
|
||||
> use "{exercise}.sml";
|
||||
```
|
||||
|
||||
**Note:** You have to replace {exercise}.
|
||||
|
||||
## Running the tests
|
||||
|
||||
```
|
||||
$ poly -q --use test.sml
|
||||
```
|
||||
|
||||
## Feedback, Issues, Pull Requests
|
||||
|
||||
The [exercism/sml](https://github.com/exercism/sml) repository on
|
||||
GitHub is the home for all of the Standard ML exercises.
|
||||
|
||||
If you have feedback about an exercise, or want to help implementing a new
|
||||
one, head over there and create an issue. We'll do our best to help you!
|
||||
|
||||
## Source
|
||||
|
||||
This is an exercise to introduce users to using Exercism [http://en.wikipedia.org/wiki/%22Hello,_world!%22_program](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program)
|
||||
|
||||
## Submitting Incomplete Solutions
|
||||
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
2
sml/hello-world/hello-world.sml
Normal file
2
sml/hello-world/hello-world.sml
Normal file
@@ -0,0 +1,2 @@
|
||||
fun hello (): string =
|
||||
raise Fail "'hello' is not implemented"
|
15
sml/hello-world/test.sml
Normal file
15
sml/hello-world/test.sml
Normal file
@@ -0,0 +1,15 @@
|
||||
(* version 1.0.0 *)
|
||||
|
||||
use "hello-world.sml";
|
||||
use "testlib.sml";
|
||||
|
||||
infixr |>
|
||||
fun x |> f = f x
|
||||
|
||||
val testsuite =
|
||||
describe "hello-world" [
|
||||
test "Say Hi!"
|
||||
(fn _ => hello () |> Expect.equalTo "Hello, World!")
|
||||
]
|
||||
|
||||
val _ = Test.run testsuite
|
159
sml/hello-world/testlib.sml
Normal file
159
sml/hello-world/testlib.sml
Normal file
@@ -0,0 +1,159 @@
|
||||
structure Expect =
|
||||
struct
|
||||
datatype expectation = Pass | Fail of string * string
|
||||
|
||||
local
|
||||
fun failEq b a =
|
||||
Fail ("Expected: " ^ b, "Got: " ^ a)
|
||||
|
||||
fun failExn b a =
|
||||
Fail ("Expected: " ^ b, "Raised: " ^ a)
|
||||
|
||||
fun exnName (e: exn): string = General.exnName e
|
||||
in
|
||||
fun truthy a =
|
||||
if a
|
||||
then Pass
|
||||
else failEq "true" "false"
|
||||
|
||||
fun falsy a =
|
||||
if a
|
||||
then failEq "false" "true"
|
||||
else Pass
|
||||
|
||||
fun equalTo b a =
|
||||
if a = b
|
||||
then Pass
|
||||
else failEq (PolyML.makestring b) (PolyML.makestring a)
|
||||
|
||||
fun nearTo b a =
|
||||
if Real.== (a, b)
|
||||
then Pass
|
||||
else failEq (Real.toString b) (Real.toString a)
|
||||
|
||||
fun anyError f =
|
||||
(
|
||||
f ();
|
||||
failExn "an exception" "Nothing"
|
||||
) handle _ => Pass
|
||||
|
||||
fun error e f =
|
||||
(
|
||||
f ();
|
||||
failExn (exnName e) "Nothing"
|
||||
) handle e' => if exnMessage e' = exnMessage e
|
||||
then Pass
|
||||
else failExn (exnMessage e) (exnMessage e')
|
||||
end
|
||||
end
|
||||
|
||||
structure TermColor =
|
||||
struct
|
||||
datatype color = Red | Green | Yellow | Normal
|
||||
|
||||
fun f Red = "\027[31m"
|
||||
| f Green = "\027[32m"
|
||||
| f Yellow = "\027[33m"
|
||||
| f Normal = "\027[0m"
|
||||
|
||||
fun colorize color s = (f color) ^ s ^ (f Normal)
|
||||
|
||||
val redit = colorize Red
|
||||
|
||||
val greenit = colorize Green
|
||||
|
||||
val yellowit = colorize Yellow
|
||||
end
|
||||
|
||||
structure Test =
|
||||
struct
|
||||
datatype testnode = TestGroup of string * testnode list
|
||||
| Test of string * (unit -> Expect.expectation)
|
||||
|
||||
local
|
||||
datatype evaluation = Success of string
|
||||
| Failure of string * string * string
|
||||
| Error of string * string
|
||||
|
||||
fun indent n s = (implode (List.tabulate (n, fn _ => #" "))) ^ s
|
||||
|
||||
fun fmt indentlvl ev =
|
||||
let
|
||||
val check = TermColor.greenit "\226\156\148 " (* ✔ *)
|
||||
val cross = TermColor.redit "\226\156\150 " (* ✖ *)
|
||||
val indentlvl = indentlvl * 2
|
||||
in
|
||||
case ev of
|
||||
Success descr => indent indentlvl (check ^ descr)
|
||||
| Failure (descr, exp, got) =>
|
||||
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
||||
indent (indentlvl + 2) exp,
|
||||
indent (indentlvl + 2) got]
|
||||
| Error (descr, reason) =>
|
||||
String.concatWith "\n" [indent indentlvl (cross ^ descr),
|
||||
indent (indentlvl + 2) (TermColor.redit reason)]
|
||||
end
|
||||
|
||||
fun eval (TestGroup _) = raise Fail "Only a 'Test' can be evaluated"
|
||||
| eval (Test (descr, thunk)) =
|
||||
(
|
||||
case thunk () of
|
||||
Expect.Pass => ((1, 0, 0), Success descr)
|
||||
| Expect.Fail (s, s') => ((0, 1, 0), Failure (descr, s, s'))
|
||||
)
|
||||
handle e => ((0, 0, 1), Error (descr, "Unexpected error: " ^ exnMessage e))
|
||||
|
||||
fun flatten depth testnode =
|
||||
let
|
||||
fun sum (x, y, z) (a, b, c) = (x + a, y + b, z + c)
|
||||
|
||||
fun aux (t, (counter, acc)) =
|
||||
let
|
||||
val (counter', texts) = flatten (depth + 1) t
|
||||
in
|
||||
(sum counter' counter, texts :: acc)
|
||||
end
|
||||
in
|
||||
case testnode of
|
||||
TestGroup (descr, ts) =>
|
||||
let
|
||||
val (counter, texts) = foldr aux ((0, 0, 0), []) ts
|
||||
in
|
||||
(counter, (indent (depth * 2) descr) :: List.concat texts)
|
||||
end
|
||||
| Test _ =>
|
||||
let
|
||||
val (counter, evaluation) = eval testnode
|
||||
in
|
||||
(counter, [fmt depth evaluation])
|
||||
end
|
||||
end
|
||||
|
||||
fun println s = print (s ^ "\n")
|
||||
in
|
||||
fun run suite =
|
||||
let
|
||||
val ((succeeded, failed, errored), texts) = flatten 0 suite
|
||||
|
||||
val summary = String.concatWith ", " [
|
||||
TermColor.greenit ((Int.toString succeeded) ^ " passed"),
|
||||
TermColor.redit ((Int.toString failed) ^ " failed"),
|
||||
TermColor.redit ((Int.toString errored) ^ " errored"),
|
||||
(Int.toString (succeeded + failed + errored)) ^ " total"
|
||||
]
|
||||
|
||||
val status = if failed = 0 andalso errored = 0
|
||||
then OS.Process.success
|
||||
else OS.Process.failure
|
||||
|
||||
in
|
||||
List.app println texts;
|
||||
println "";
|
||||
println ("Tests: " ^ summary);
|
||||
OS.Process.exit status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fun describe description tests = Test.TestGroup (description, tests)
|
||||
fun test description thunk = Test.Test (description, thunk)
|
Reference in New Issue
Block a user