Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
- compile time argument count check for `and` and `or`
- basic dead code elimination in the AST optimizer
- new operator `@@` to get elements in list of lists / list of strings
- new builtin `random`, returning a random number between INT_MIN and INT_MAX, or in a custom range

### Changed
- instructions are on 4 bytes: 1 byte for the instruction, 1 byte of padding, 2 bytes for an immediate argument
Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,7 @@ Also, it has:
## More or less game

```clojure
(import std.random)
(import std.Math)

(let number (mod (math:abs (random)) 10000))
(let number (random 0 10000))

(let game (fun () {
(let impl (fun (tries) {
Expand Down
5 changes: 1 addition & 4 deletions examples/games/more-or-less.ark
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
(import random)
(import std.Math)

(let number (mod (math:abs (random)) 10000))
(let number (random 0 10000))

(let game (fun () {
(let impl (fun (tries) {
Expand Down
2 changes: 2 additions & 0 deletions include/Ark/Builtins/Builtins.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ namespace Ark::internal::Builtins
Value acosh_(std::vector<Value>& n, VM* vm); // math:acosh, 1 argument
Value asinh_(std::vector<Value>& n, VM* vm); // math:asinh, 1 argument
Value atanh_(std::vector<Value>& n, VM* vm); // math:atanh, 1 argument

Value random(std::vector<Value>& n, VM* vm); // random, 0-2 args
}

namespace Async
Expand Down
1 change: 1 addition & 0 deletions src/arkreactor/Builtins/Builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ namespace Ark::internal::Builtins
{ "math:acosh", Value(Mathematics::acosh_) },
{ "math:asinh", Value(Mathematics::asinh_) },
{ "math:atanh", Value(Mathematics::atanh_) },
{ "random", Value(Mathematics::random) },

// Async
{ "async", Value(Async::async) },
Expand Down
36 changes: 36 additions & 0 deletions src/arkreactor/Builtins/Mathematics.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#define _USE_MATH_DEFINES
#include <cmath>
#include <fmt/core.h>
#include <random>

#include <Ark/Builtins/Builtins.hpp>

Expand Down Expand Up @@ -385,4 +386,39 @@ namespace Ark::internal::Builtins::Mathematics

return Value(std::atanh(n[0].number()));
}

/**
* @name random
* @brief Compute a random number in [-2147483648, 2147483647] or in a custom range passed to the function
* @param min optional inclusive lower bound
* @param max optional inclusive upper bound. Must be present if `min` is passed
* =begin
* (print (random)) # a number in [-2147483648, 2147483647]
* (print (random 0 10)) # a number between 0 and 10
* =end
* @author https://github.com/SuperFola
*/
Value random(std::vector<Value>& n, VM* vm [[maybe_unused]])
{
static std::mt19937 gen { std::random_device()() };

if (n.size() == 2 && !types::check(n, ValueType::Number, ValueType::Number))
types::generateError(
"random",
{ { types::Contract {
{ types::Typedef("min", ValueType::Number), types::Typedef("max", ValueType::Number) } } } },
n);

if (n.size() == 2)
{
const auto inclusive_min = static_cast<int>(n[0].number()),
inclusive_max = static_cast<int>(n[1].number());

std::uniform_int_distribution<> distrib(inclusive_min, inclusive_max);
return Value(distrib(gen));
}

const auto x = static_cast<int>(gen());
return Value(x);
}
}
1 change: 1 addition & 0 deletions tests/fuzzing/arkscript.dict
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,4 @@
"math:arccos"
"math:arcsin"
"math:arctan"
"random"
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
(import random)
(import std.Math)

(let number (mod (math:abs (random)) 10000))
(let number (random 0 10000))

(let game (fun () {
(let impl (fun (tries) {
Expand Down
5 changes: 1 addition & 4 deletions tests/fuzzing/corpus-cmin/examples_games_more-or-less.ark
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
(import random)
(import std.Math)

(let number (mod (math:abs (random)) 10000))
(let number (random 0 10000))

(let game (fun () {
(let impl (fun (tries) {
Expand Down
5 changes: 1 addition & 4 deletions tests/fuzzing/corpus/examples_games_more-or-less.ark
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
(import random)
(import std.Math)

(let number (mod (math:abs (random)) 10000))
(let number (random 0 10000))

(let game (fun () {
(let impl (fun (tries) {
Expand Down
10 changes: 10 additions & 0 deletions tests/unittests/resources/LangSuite/builtins-tests.ark
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
(import std.Testing)
(import std.List)

(let foo (fun () ()))
(let closure (fun (&foo) ()))
Expand Down Expand Up @@ -30,6 +31,15 @@
(sys:sleep 1)
(test:expect (< old (time)))

(mut rands [])
(mut i 0)
(while (< i 100) {
(append! rands (random 0 10))
(set i (+ 1 i)) })
(test:expect
(not (list:any rands (fun (e) (or (< e 0) (> e 10)))))
"should not find any number outside the given range")

# no need to test the math functions since they're 1:1 binding of C++ functions and were carefully checked
# before writing this comment, to ensure we aren't binding math:sin to the C++ tan function

Expand Down
Loading