Skip to content

Commit

Permalink
Merge pull request #457 from ArkScript-lang/error-messages
Browse files Browse the repository at this point in the history
Error messages
  • Loading branch information
SuperFola authored May 6, 2024
2 parents 6aa6d35 + 7d816f5 commit 21b465c
Show file tree
Hide file tree
Showing 71 changed files with 306 additions and 273 deletions.
2 changes: 1 addition & 1 deletion .github/launch-lizard.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

for file in lizard.analyze(files):
for func in file.function_list:
filename = func.filename.replace('\\', '/')
filename = func.filename.replace('\\', '/').lstrip('./')
param_count = len(func.parameters)

if func.cyclomatic_complexity >= MAX_CCN or func.nloc >= MAX_NLOC or param_count >= MAX_PARAM:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/setup-compilers/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ runs:
shell: bash
run: |
if [[ '${{ startsWith(inputs.os_name, 'macos') }}' == 'true' ]]; then
echo "cc=/usr/local/opt/llvm@${{ inputs.compiler_version }}/bin/${{ inputs.compiler }}" >> $GITHUB_OUTPUT
echo "cxx=/usr/local/opt/llvm@${{ inputs.compiler_version }}/bin/${{ inputs.compiler }}++" >> $GITHUB_OUTPUT
echo "cc=/opt/homebrew/opt/llvm@${{ inputs.compiler_version }}/bin/${{ inputs.compiler }}" >> $GITHUB_OUTPUT
echo "cxx=/opt/homebrew/opt/llvm@${{ inputs.compiler_version }}/bin/${{ inputs.compiler }}++" >> $GITHUB_OUTPUT
elif [[ '${{ inputs.compiler }}' == 'clang' ]]; then
echo "cc=clang-${{ inputs.compiler_version }}" >> $GITHUB_OUTPUT
echo "cxx=clang++-${{ inputs.compiler_version }}" >> $GITHUB_OUTPUT
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/static_analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2

- uses: actions/setup-python@v5
with:
Expand All @@ -21,7 +23,7 @@ jobs:
id: lizard
shell: bash
run: |
content=$(python .github/launch-lizard.py $(git diff HEAD..dev --name-only))
content=$(python .github/launch-lizard.py $(echo $(git diff --name-only -r HEAD^1 HEAD)))
echo "LIZARD_REPORT<<EOF" >> $GITHUB_ENV
echo "$content" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
Expand Down
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ repos:
rev: v3.2.0
hooks:
- id: trailing-whitespace
exclude: '\.expected^'
- id: end-of-file-fixer
exclude: '\.expected^'
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/pre-commit/mirrors-clang-format
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
- allow nodes to be empty when dumping the AST to JSON
- macros can be declared inside a begin block within a cond macro and used in the scope surrounding the cond macro
- `arkscript --version` and `arkscript --help` now output ArkScript version with the commit hash
- `void Value::toString(std::ostream&, VM&)` now becomes `std::string Value::toString(VM&)`
- removed `Node::operator<<` to replace it with `Node::debugPrint`

### Removed
- removed unused `NodeType::Closure`
Expand Down
10 changes: 7 additions & 3 deletions include/Ark/Compiler/AST/Node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,13 @@ namespace Ark::internal
*/
[[nodiscard]] std::string repr() const noexcept;

friend ARK_API std::ostream& operator<<(std::ostream& os, const Node& N) noexcept;
/**
* @brief Print a node to an output stream with added type annotations
* @param os
* @return
*/
[[nodiscard]] std::ostream& debugPrint(std::ostream& os) const noexcept;

friend bool operator==(const Node& A, const Node& B);
friend bool operator<(const Node& A, const Node& B);
friend bool operator!(const Node& A);
Expand All @@ -186,8 +192,6 @@ namespace Ark::internal
std::string m_after_comment; ///< Comment after node
};

ARK_API std::ostream& operator<<(std::ostream& os, const std::vector<Node>& node) noexcept;

const Node& getTrueNode();
const Node& getFalseNode();
const Node& getNilNode();
Expand Down
14 changes: 0 additions & 14 deletions include/Ark/Exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,6 @@ namespace Ark
{}
};

/**
* @brief A pow error triggered when we can't do a pow b
*
*/
class PowError : public Error
{
public:
PowError() :
Error(
"PowError: Can not pow the given number (a) to the given exponent (b) because "
"a^b, with b being a member of the rational numbers, isn't supported.")
{}
};

/**
* @brief An assertion error, only triggered from ArkScript code through (assert expr error-message)
*
Expand Down
6 changes: 4 additions & 2 deletions include/Ark/VM/ErrorKind.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ namespace Ark::internal
Type,
Index,
Arity,
DivisionByZero,
};

constexpr std::array<std::string_view, 7> errorKinds = {
constexpr std::array<std::string_view, 8> errorKinds = {
"VMError",
"ModuleError",
"MutabilityError",
"ScopeError",
"TypeError",
"IndexError",
"ArityError"
"ArityError",
"DivisionByZero"
};
}

Expand Down
1 change: 1 addition & 0 deletions include/Ark/VM/VM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <unordered_map>
#include <utility>
#include <mutex>
#include <fmt/core.h>

#include <Ark/VM/Value.hpp>
#include <Ark/VM/Scope.hpp>
Expand Down
5 changes: 2 additions & 3 deletions include/Ark/VM/Value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @file Value.hpp
* @author Default value type handled by the virtual machine
* @brief
* @version 1.0
* @version 1.1
* @date 2024-04-20
*
* @copyright Copyright (c) 2020-2024
Expand Down Expand Up @@ -66,7 +66,6 @@ namespace Ark
public:
using ProcType = Value (*)(std::vector<Value>&, VM*);
using Iterator = std::vector<Value>::iterator;
using ConstIterator = std::vector<Value>::const_iterator;

using Value_t = std::variant<
double, // 8 bytes
Expand Down Expand Up @@ -151,7 +150,7 @@ namespace Ark
*/
void push_back(Value&& value);

void toString(std::ostream& os, VM& vm) const noexcept;
std::string toString(VM& vm) const noexcept;

friend ARK_API_INLINE bool operator==(const Value& A, const Value& B) noexcept;
friend ARK_API_INLINE bool operator<(const Value& A, const Value& B) noexcept;
Expand Down
32 changes: 5 additions & 27 deletions include/Ark/VM/Value/Closure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
* @file Closure.hpp
* @author Alexandre Plateau ([email protected])
* @brief Subtype of the value type, handling closures
* @version 0.2
* @date 2020-10-27
* @version 1.0
* @date 2024-04-21
*
* @copyright Copyright (c) 2020-2021
* @copyright Copyright (c) 2020-2024
*
*/

Expand All @@ -15,6 +15,7 @@
#include <memory>
#include <vector>
#include <iostream>
#include <string>

#include <Ark/Platform.hpp>

Expand Down Expand Up @@ -65,33 +66,10 @@ namespace Ark::internal
*/
Closure(const std::shared_ptr<Scope>& scope_ptr, PageAddr_t pa) noexcept;

/**
* @brief Return the scope held by the object
*
* @return const Scope&
*/
[[nodiscard]] inline const Scope& scope() const noexcept { return *m_scope.get(); }

/**
* @brief Return a reference to the scope held by the object
*
* @return Scope&
*/
[[nodiscard]] inline Scope& refScope() noexcept { return *m_scope.get(); }

/**
* @brief Return a reference to the shared pointer representing the scope
* @details The scope has to be kept alive somewhere or all its variables will be destroyed.
*
* @return const std::shared_ptr<Scope>&
*/
[[nodiscard]] inline const std::shared_ptr<Scope>& scopePtr() const { return m_scope; }

/**
* @brief Return the page address of the object
*
* @return PageAddr_t
*/
[[nodiscard]] inline PageAddr_t pageAddr() const { return m_page_addr; }

/**
Expand All @@ -100,7 +78,7 @@ namespace Ark::internal
* @param os
* @param vm
*/
void toString(std::ostream& os, VM& vm) const noexcept;
std::string toString(VM& vm) const noexcept;

friend ARK_API bool operator==(const Closure& A, const Closure& B) noexcept;
friend ARK_API_INLINE bool operator<(const Closure& A, const Closure& B) noexcept;
Expand Down
17 changes: 13 additions & 4 deletions include/Ark/VM/inline/VM.inl
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,17 @@ inline void VM::call(internal::ExecutionContext& context, int16_t argc_)
default:
{
if (m_state.m_symbols.size() > 0)
throwVMError(ErrorKind::Type, "Can't call '" + m_state.m_symbols[context.last_symbol] + "': it isn't a Function but a " + types_to_str[static_cast<std::size_t>(function.valueType())]);
throwVMError(
ErrorKind::Type,
fmt::format(
"`{}' is not a Function but a {}",
m_state.m_symbols[context.last_symbol], types_to_str[static_cast<std::size_t>(function.valueType())]));
else
throwVMError(ErrorKind::Type, "A " + types_to_str[static_cast<std::size_t>(function.valueType())] + " isn't a callable");
throwVMError(
ErrorKind::Type,
fmt::format(
"{} is not a Function but a {}",
function.toString(*this), types_to_str[static_cast<std::size_t>(function.valueType())]));
}
}

Expand All @@ -337,6 +345,7 @@ inline void VM::call(internal::ExecutionContext& context, int16_t argc_)
if (needed_argc != argc) [[unlikely]]
throwVMError(
ErrorKind::Arity,
"Function '" + m_state.m_symbols[context.last_symbol] + "' needs " + std::to_string(needed_argc) +
" arguments, but it received " + std::to_string(argc));
fmt::format(
"Function `{}' needs {} arguments, but it received {}",
m_state.m_symbols[context.last_symbol], needed_argc, argc));
}
6 changes: 3 additions & 3 deletions src/arkreactor/Builtins/Async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace Ark::internal::Builtins::Async
*/
Value async(std::vector<Value>& n, VM* vm)
{
if (n.size() == 0)
if (n.empty())
types::generateError(
"async", { { types::Contract { { types::Typedef("function", ValueType::PageAddr) } }, types::Contract { { types::Typedef("function", ValueType::CProc) } }, types::Contract { { types::Typedef("function", ValueType::Closure) } } } }, n);

Expand All @@ -35,7 +35,7 @@ namespace Ark::internal::Builtins::Async
* @name await
* @brief Blocks until the result becomes available
* @details
* @param future the future to wait for its result to be avaible
* @param future the future to wait for its result to be available
* =begin
* (let foo (fun (a b) (+ a b)))
* (let async-foo (async foo 1 2))
Expand All @@ -48,7 +48,7 @@ namespace Ark::internal::Builtins::Async
if (!types::check(n, ValueType::User) || !n[0].usertypeRef().is<Future>())
types::generateError("await", { { types::Contract { { types::Typedef("future", ValueType::User) } } } }, n);

Future& f = n[0].usertypeRef().as<Future>();
auto& f = n[0].usertypeRef().as<Future>();
Value res = f.resolve();
vm->deleteFuture(&f);

Expand Down
32 changes: 16 additions & 16 deletions src/arkreactor/Builtins/IO.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
#include <Ark/Builtins/Builtins.hpp>

#include <cstdio>
#include <iostream>
#include <filesystem>
#include <fmt/core.h>

#include <Ark/Files.hpp>
#include <Ark/VM/VM.hpp>
#include <Ark/Exceptions.hpp>
#include <Ark/TypeChecker.hpp>
#include <fmt/format.h>

namespace Ark::internal::Builtins::IO
{
Expand All @@ -24,8 +23,8 @@ namespace Ark::internal::Builtins::IO
*/
Value print(std::vector<Value>& n, VM* vm)
{
for (Value::Iterator it = n.begin(), it_end = n.end(); it != it_end; ++it)
it->toString(std::cout, *vm);
for (auto& value : n)
std::cout << value.toString(*vm);
std::cout << '\n';

return nil;
Expand All @@ -43,8 +42,8 @@ namespace Ark::internal::Builtins::IO
*/
Value puts_(std::vector<Value>& n, VM* vm)
{
for (Value::Iterator it = n.begin(), it_end = n.end(); it != it_end; ++it)
it->toString(std::cout, *vm);
for (auto& value : n)
std::cout << value.toString(*vm);

return nil;
}
Expand All @@ -63,10 +62,10 @@ namespace Ark::internal::Builtins::IO
{
if (types::check(n, ValueType::String))
fmt::print("{}", n[0].string());
else if (n.size() != 0)
else if (!n.empty())
types::generateError("input", { { types::Contract {}, types::Contract { { types::Typedef("prompt", ValueType::String) } } } }, n);

std::string line = "";
std::string line;
std::getline(std::cin, line);

return Value(line);
Expand All @@ -91,17 +90,17 @@ namespace Ark::internal::Builtins::IO
std::ofstream f(n[0].string());
if (f.is_open())
{
n[1].toString(f, *vm);
f << n[1].toString(*vm);
f.close();
}
else
throw std::runtime_error("Couldn't write to file \"" + n[0].stringRef() + "\"");
throw std::runtime_error(fmt::format("io:writeFile: couldn't write to file \"{}\"", n[0].stringRef()));
}
else if (types::check(n, ValueType::String, ValueType::String, ValueType::Any))
{
auto mode = n[1].string();
if (mode != "w" && mode != "a")
throw std::runtime_error("io:writeFile: mode must be equal to \"a\" or \"w\"");
throw std::runtime_error(fmt::format("io:writeFile: mode must be equal to \"a\" or \"w\", not \"{}\"", mode));

auto ios_mode = std::ios::out | std::ios::trunc;
if (mode == "a")
Expand All @@ -110,11 +109,11 @@ namespace Ark::internal::Builtins::IO
std::ofstream f(n[0].string(), ios_mode);
if (f.is_open())
{
n[2].toString(f, *vm);
f << n[2].toString(*vm);
f.close();
}
else
throw std::runtime_error("Couldn't write to file \"" + n[0].stringRef() + "\"");
throw std::runtime_error(fmt::format("io:writeFile: couldn't write to file \"{}\"", n[0].stringRef()));
}
else
types::generateError(
Expand Down Expand Up @@ -145,7 +144,8 @@ namespace Ark::internal::Builtins::IO

std::string filename = n[0].string();
if (!Utils::fileExists(filename))
throw std::runtime_error("Couldn't read file \"" + std::string(filename) + "\": it doesn't exist");
throw std::runtime_error(
fmt::format("io:readFile: couldn't read file \"{}\" because it doesn't exist", filename));

return Value(Utils::readFile(filename));
}
Expand Down Expand Up @@ -247,13 +247,13 @@ namespace Ark::internal::Builtins::IO
*/
Value removeFiles(std::vector<Value>& n, VM* vm [[maybe_unused]])
{
if (n.size() < 1 || n[0].valueType() != ValueType::String)
if (n.empty() || n[0].valueType() != ValueType::String)
types::generateError(
"io:removeFiles",
{ { types::Contract { { types::Typedef("filename", ValueType::String), types::Typedef("filenames", ValueType::String, /* variadic */ true) } } } },
n);

for (Value::Iterator it = n.begin(), it_end = n.end(); it != it_end; ++it)
for (auto it = n.begin(), it_end = n.end(); it != it_end; ++it)
{
if (it->valueType() != ValueType::String)
types::generateError(
Expand Down
Loading

0 comments on commit 21b465c

Please sign in to comment.