Properly handle compilation errors in Erlang compiler

Closes #2654.

This what the output before the change looked like:
```
src/cliproj_cli.erl:6: syntax error before: ':'
src/cliproj_cli.erl:2: function main/1 undefined
02:11:30.212 [error] Error in process <0.47.0> with exit value: {#{'__exception__'=>true,'__struct__'=>'Elixir.ArgumentError',message=><<188 bytes>>},[{'Elixir.Exception',message,1,[{file,"lib/exception.ex"},{line,48}]},{'Elixir.Exception',format_banner,3,[{file,"lib/exception.ex"},{line,106}]},{'Elixir.Exception'...


** (EXIT from #PID<0.47.0>) an exception was raised:
    ** (ArgumentError) Got FunctionClauseError with message "no function clause matching in IO.chardata_to_string/1" while retrieving message for %CompileError{description: "compile error", file: nil, line: nil}
        (elixir) lib/exception.ex:48: Exception.message/1
        (elixir) lib/exception.ex:106: Exception.format_banner/3
        (elixir) lib/exception.ex:141: Exception.format/3
        (elixir) lib/kernel/cli.ex:113: Kernel.CLI.print_error/3
        (elixir) lib/kernel/cli.ex:83: anonymous fn/3 in Kernel.CLI.exec_fun/2
```

I made a controversial change to the compiler.erlang task in this patch. Instead for raising a `CompilerError`, I'm raising `Mix.Error` to get a nice error message:

```
src/cliproj_cli.erl:6: syntax error before: ':'
src/cliproj_cli.erl:2: function main/1 undefined
** (Mix) Encountered some compilation errors.
```

However, there are now 10 tests breaking because all of them relied on `CompileError` being raised.

When there is a syntax error in Elixir source, the error message is rather short:

```
== Compilation error on file lib/compilerror.ex ==
** (SyntaxError) lib/compilerror.ex:4: unexpected token: end
    (elixir) lib/kernel/parallel_compiler.ex:93: anonymous fn/3 in Kernel.ParallelCompiler.spawn_compilers/8
```

I suppose it also emits a `CompileError` but it gets formatted before propagating to the top.

My question is this: should I keep the `CompileError` in `compile.erlang` and where should I catch it to format it more nicely?
So `compile` expects the result of each compilation task, like `compile.erlang`, to return `:ok` or `:noop`. So we need to ensure it is the case even after this change.