• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ArkScript-lang / Ark / 12304789397

10 Dec 2024 10:04PM UTC coverage: 77.378% (-0.5%) from 77.864%
12304789397

push

github

SuperFola
fix(parser): fixing row/col computation while backtracking in the parser, leading to finally correct symbol underlined in errors

7 of 7 new or added lines in 2 files covered. (100.0%)

258 existing lines in 6 files now uncovered.

5490 of 7095 relevant lines covered (77.38%)

9291.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.82
/src/arkreactor/Builtins/String.cpp
1
#include <Ark/Builtins/Builtins.hpp>
2

3
#include <utility>
4
#include <utf8.hpp>
5
#include <fmt/args.h>
6
#include <fmt/core.h>
7
#include <fmt/format.h>
8

9
#include <Ark/TypeChecker.hpp>
10
#include <Ark/VM/VM.hpp>
11

12
namespace Ark::internal::Builtins::String
13
{
14
    /**
15
     * @name string:format
16
     * @brief Format a String given replacements
17
     * @details https://fmt.dev/latest/syntax.html
18
     * @param format the String to format
19
     * @param values as any argument as you need, of any valid ArkScript type
20
     * =begin
21
     * (string:format "Hello {}, my name is {}" "world" "ArkScript")
22
     * # Hello world, my name is ArkScript
23
     *
24
     * (string:format "Test {} with {{}}" "1")
25
     * # Test 1 with {}
26
     * =end
27
     * @author https://github.com/SuperFola
28
     */
29
    Value format(std::vector<Value>& n, VM* vm)
17✔
30
    {
17✔
31
        if (n.size() < 2 || n[0].valueType() != ValueType::String)
17✔
32
            types::generateError(
1✔
33
                "string:format",
×
34
                { { types::Contract { { types::Typedef("string", ValueType::String),
×
35
                                        types::Typedef("value", ValueType::Any, /* variadic */ true) } } } },
×
36
                n);
×
37

38
        fmt::dynamic_format_arg_store<fmt::format_context> store;
17✔
39

40
        for (auto it = n.begin() + 1, it_end = n.end(); it != it_end; ++it)
36✔
41
        {
42
            if (it->valueType() == ValueType::String)
19✔
43
                store.push_back(it->stringRef());
1✔
44
            else if (it->valueType() == ValueType::Number)
18✔
45
                store.push_back(it->number());
14✔
46
            else if (it->valueType() == ValueType::Nil)
4✔
47
                store.push_back("nil");
1✔
48
            else if (it->valueType() == ValueType::True)
3✔
49
                store.push_back("true");
1✔
50
            else if (it->valueType() == ValueType::False)
2✔
51
                store.push_back("false");
1✔
52
            else
53
                store.push_back(it->toString(*vm));
1✔
54
        }
19✔
55

56
        try
57
        {
58
            return Value(fmt::vformat(n[0].stringRef(), store));
17✔
59
        }
1✔
60
        catch (fmt::format_error& e)
61
        {
62
            throw std::runtime_error(
2✔
63
                fmt::format("string:format: can not format \"{}\" ({} argument{} provided) because of {}",
3✔
64
                            n[0].stringRef(),
1✔
65
                            n.size() - 1,
1✔
66
                            // if we have more than one argument (not counting the string to format), plural form
67
                            n.size() > 2 ? "s" : "",
1✔
68
                            e.what()));
1✔
69
        }
1✔
70
    }
19✔
71

72
    /**
73
     * @name string:find
74
     * @brief Search a substring in a given String
75
     * @details The original String is not modified. Return -1 when not found
76
     * @param string the String to search in
77
     * @param substr the substring to search for
78
     * @param (optional) startIndex index to start searching from
79
     * =begin
80
     * (string:find "hello world" "hello")  # 0
81
     * (string:find "hello world" "aworld")  # -1
82
     * =end
83
     * @author https://github.com/SuperFola
84
     */
85
    Value findSubStr(std::vector<Value>& n, VM* vm [[maybe_unused]])
10✔
86
    {
10✔
87
        if (!types::check(n, ValueType::String, ValueType::String) &&
10✔
88
            !types::check(n, ValueType::String, ValueType::String, ValueType::Number))
1✔
89
            types::generateError(
×
90
                "string:find",
×
UNCOV
91
                { { types::Contract {
×
UNCOV
92
                        { types::Typedef("string", ValueType::String),
×
UNCOV
93
                          types::Typedef("substr", ValueType::String) } },
×
UNCOV
94
                    types::Contract {
×
UNCOV
95
                        { types::Typedef("string", ValueType::String),
×
UNCOV
96
                          types::Typedef("substr", ValueType::String),
×
UNCOV
97
                          types::Typedef("startIndex", ValueType::Number) } } } },
×
UNCOV
98
                n);
×
99

100
        const std::size_t start = n.size() == 3 ? static_cast<std::size_t>(n[2].number()) : 0;
10✔
101
        const std::size_t index = n[0].stringRef().find(n[1].stringRef(), start);
10✔
102
        if (index != std::string::npos)
10✔
103
            return Value(static_cast<int>(index));
6✔
104
        return Value(-1);
4✔
105
    }
10✔
106

107
    /**
108
     * @name string:removeAt
109
     * @brief Remove a character from a String given an index
110
     * @details The original String is not modified
111
     * @param string the String to modify
112
     * @param index the index of the character to remove (can be negative to search from the end)
113
     * =begin
114
     * (string:removeAt "hello world" 0)  # "ello world"
115
     * (string:removeAt "hello world" -1)  # "hello worl"
116
     * =end
117
     * @author https://github.com/SuperFola
118
     */
119
    Value removeAtStr(std::vector<Value>& n, VM* vm [[maybe_unused]])
7✔
120
    {
7✔
121
        if (!types::check(n, ValueType::String, ValueType::Number))
7✔
122
            types::generateError(
1✔
UNCOV
123
                "string:removeAt",
×
UNCOV
124
                { { types::Contract { { types::Typedef("string", ValueType::String), types::Typedef("index", ValueType::Number) } } } },
×
UNCOV
125
                n);
×
126

127
        long id = static_cast<long>(n[1].number());
7✔
128
        if (id < 0 || std::cmp_greater_equal(id, n[0].stringRef().size()))
7✔
129
            throw std::runtime_error(fmt::format("string:removeAt: index {} out of range (length: {})", id, n[0].stringRef().size()));
1✔
130

131
        n[0].stringRef().erase(static_cast<std::size_t>(id), 1);
6✔
132
        return n[0];
6✔
133
    }
8✔
134

135
    /**
136
     * @name string:ord
137
     * @brief Get the ordinal of a given character
138
     * @param char a String with a single UTF8 character
139
     * =begin
140
     * (string:ord "h")  # 104
141
     * (string:ord "Ô")  # 212
142
     * =end
143
     * @author https://github.com/SuperFola
144
     */
145
    Value ord(std::vector<Value>& n, VM* vm [[maybe_unused]])
2✔
146
    {
2✔
147
        if (!types::check(n, ValueType::String))
2✔
UNCOV
148
            types::generateError(
×
UNCOV
149
                "string:ord",
×
UNCOV
150
                { { types::Contract { { types::Typedef("string", ValueType::String) } } } },
×
UNCOV
151
                n);
×
152

153
        return Value(utf8::codepoint(n[0].stringRef().c_str()));
2✔
UNCOV
154
    }
×
155

156
    /**
157
     * @name string:chr
158
     * @brief Create a character from an UTF8 codepoint
159
     * @param codepoint an UTF8 codepoint (Number)
160
     * =begin
161
     * (string:chr 104)  # "h"
162
     * (string:chr 212)  # "Ô"
163
     * =end
164
     * @author https://github.com/SuperFola
165
     */
166
    Value chr(std::vector<Value>& n, VM* vm [[maybe_unused]])
2✔
167
    {
2✔
168
        if (!types::check(n, ValueType::Number))
2✔
UNCOV
169
            types::generateError(
×
UNCOV
170
                "string:chr",
×
UNCOV
171
                { { types::Contract { { types::Typedef("codepoint", ValueType::Number) } } } },
×
UNCOV
172
                n);
×
173

174
        std::array<char, 5> utf8 {};
2✔
175
        utf8::codepointToUtf8(static_cast<int>(n[0].number()), utf8.data());
2✔
176
        return Value(std::string(utf8.data()));
2✔
177
    }
2✔
178

179
    /**
180
     * @name string:setAt
181
     * @brief Modify a given string and return a new one
182
     * @details The original string is not modified
183
     * @param string the string to modify
184
     * @param index the index of the element to modify
185
     * @param value the new character
186
     * =begin
187
     * (string:setAt "hello" 1 "a")  # "hallo"
188
     * =end
189
     * @author https://github.com/SuperFola
190
     */
UNCOV
191
    Value setStringAt(std::vector<Value>& n, VM* vm [[maybe_unused]])
×
UNCOV
192
    {
×
UNCOV
193
        if (!types::check(n, ValueType::String, ValueType::Number, ValueType::String))
×
UNCOV
194
            types::generateError(
×
UNCOV
195
                "string:setAt",
×
UNCOV
196
                { { types::Contract { { types::Typedef("string", ValueType::String),
×
UNCOV
197
                                        types::Typedef("index", ValueType::Number),
×
UNCOV
198
                                        types::Typedef("value", ValueType::String) } } } },
×
UNCOV
199
                n);
×
200

UNCOV
201
        n[0].stringRef()[static_cast<std::size_t>(n[1].number())] = n[2].string()[0];
×
UNCOV
202
        return n[0];
×
UNCOV
203
    }
×
204
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc