Skip to content

Commit c5bd75a

Browse files
dmuir-gsparkprime
authored andcommitted
Migrate several methods from std.jsonnet to native implementations.
Updated test golden files since std.jsonnet line numbers changed.
1 parent 1ced750 commit c5bd75a

12 files changed

+157
-113
lines changed

core/desugarer.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct BuiltinDecl {
3232
std::vector<UString> params;
3333
};
3434

35-
static unsigned long max_builtin = 27;
35+
static unsigned long max_builtin = 33;
3636
BuiltinDecl jsonnet_builtin_decl(unsigned long builtin)
3737
{
3838
switch (builtin) {
@@ -64,6 +64,12 @@ BuiltinDecl jsonnet_builtin_decl(unsigned long builtin)
6464
case 25: return {U"native", {U"name"}};
6565
case 26: return {U"md5", {U"str"}};
6666
case 27: return {U"trace", {U"str", U"rest"}};
67+
case 28: return {U"splitLimit", {U"str", U"c", U"maxsplits"}};
68+
case 29: return {U"substr", {U"str", U"from", U"len"}};
69+
case 30: return {U"range", {U"from", U"to"}};
70+
case 31: return {U"strReplace", {U"str", U"from", U"to"}};
71+
case 32: return {U"asciiLower", {U"str"}};
72+
case 33: return {U"asciiUpper", {U"str"}};
6773
default:
6874
std::cerr << "INTERNAL ERROR: Unrecognized builtin function: " << builtin << std::endl;
6975
std::abort();

core/vm.cpp

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,12 @@ class Interpreter {
858858
builtins["native"] = &Interpreter::builtinNative;
859859
builtins["md5"] = &Interpreter::builtinMd5;
860860
builtins["trace"] = &Interpreter::builtinTrace;
861+
builtins["splitLimit"] = &Interpreter::builtinSplitLimit;
862+
builtins["substr"] = &Interpreter::builtinSubstr;
863+
builtins["range"] = &Interpreter::builtinRange;
864+
builtins["strReplace"] = &Interpreter::builtinStrReplace;
865+
builtins["asciiLower"] = &Interpreter::builtinAsciiLower;
866+
builtins["asciiUpper"] = &Interpreter::builtinAsciiUpper;
861867
}
862868

863869
/** Clean up the heap, stack, stash, and builtin function ASTs. */
@@ -1308,6 +1314,121 @@ class Interpreter {
13081314
return nullptr;
13091315
}
13101316

1317+
const AST *builtinSplitLimit(const LocationRange &loc, const std::vector<Value> &args)
1318+
{
1319+
validateBuiltinArgs(loc, "splitLimit", args, {Value::STRING, Value::STRING, Value::NUMBER});
1320+
const auto *str = static_cast<const HeapString *>(args[0].v.h);
1321+
const auto *c = static_cast<const HeapString *>(args[1].v.h);
1322+
long maxsplits = long(args[2].v.d);
1323+
int start = 0;
1324+
int test = 0;
1325+
scratch = makeArray({});
1326+
auto &elements = static_cast<HeapArray *>(scratch.v.h)->elements;
1327+
while (test < str->value.size() && (maxsplits == -1 ||
1328+
maxsplits > elements.size())) {
1329+
if (c->value[0] == str->value[test]) {
1330+
auto *th = makeHeap<HeapThunk>(idArrayElement, nullptr, 0, nullptr);
1331+
elements.push_back(th);
1332+
th->fill(makeString(str->value.substr(start, test - start)));
1333+
start = test + 1;
1334+
test = start;
1335+
} else {
1336+
++test;
1337+
}
1338+
}
1339+
auto *th = makeHeap<HeapThunk>(idArrayElement, nullptr, 0, nullptr);
1340+
elements.push_back(th);
1341+
th->fill(makeString(str->value.substr(start)));
1342+
1343+
return nullptr;
1344+
}
1345+
1346+
const AST *builtinSubstr(const LocationRange &loc, const std::vector<Value> &args)
1347+
{
1348+
validateBuiltinArgs(loc, "substr", args, {Value::STRING, Value::NUMBER, Value::NUMBER});
1349+
const auto *str = static_cast<const HeapString *>(args[0].v.h);
1350+
long from = long(args[1].v.d);
1351+
long len = long(args[2].v.d);
1352+
if (len + from > str->value.size()) {
1353+
len = str->value.size() - from;
1354+
}
1355+
if (len <= 0) {
1356+
scratch = makeString(U"");
1357+
} else {
1358+
scratch = makeString(str->value.substr(from, len));
1359+
}
1360+
return nullptr;
1361+
}
1362+
1363+
const AST *builtinRange(const LocationRange &loc, const std::vector<Value> &args)
1364+
{
1365+
validateBuiltinArgs(loc, "range", args, {Value::NUMBER, Value::NUMBER});
1366+
long from = long(args[0].v.d);
1367+
long to = long(args[1].v.d);
1368+
long len = to - from + 1;
1369+
scratch = makeArray({});
1370+
if (len > 0) {
1371+
auto &elements = static_cast<HeapArray *>(scratch.v.h)->elements;
1372+
for (int i = 0; i < len; ++i) {
1373+
auto *th = makeHeap<HeapThunk>(idArrayElement, nullptr, 0, nullptr);
1374+
elements.push_back(th);
1375+
th->fill(makeNumber(from + i));
1376+
}
1377+
}
1378+
return nullptr;
1379+
}
1380+
1381+
const AST *builtinStrReplace(const LocationRange &loc, const std::vector<Value> &args)
1382+
{
1383+
validateBuiltinArgs(loc, "strReplace", args, {Value::STRING, Value::STRING, Value::STRING});
1384+
const auto *str = static_cast<const HeapString *>(args[0].v.h);
1385+
const auto *from = static_cast<const HeapString *>(args[1].v.h);
1386+
const auto *to = static_cast<const HeapString *>(args[2].v.h);
1387+
if (from->value.empty()) {
1388+
throw makeError(loc, "'from' string must not be zero length.");
1389+
}
1390+
UString new_str(str->value);
1391+
UString::size_type pos = 0;
1392+
while (pos < new_str.size()) {
1393+
auto index = new_str.find(from->value, pos);
1394+
if (index == new_str.npos) {
1395+
break;
1396+
}
1397+
new_str.replace(index, from->value.size(), to->value);
1398+
pos = index + to->value.size();
1399+
}
1400+
scratch = makeString(new_str);
1401+
return nullptr;
1402+
}
1403+
1404+
const AST *builtinAsciiLower(const LocationRange &loc, const std::vector<Value> &args)
1405+
{
1406+
validateBuiltinArgs(loc, "asciiLower", args, {Value::STRING});
1407+
const auto *str = static_cast<const HeapString *>(args[0].v.h);
1408+
UString new_str(str->value);
1409+
for (int i = 0; i < new_str.size(); ++i) {
1410+
if (new_str[i] > 64 && new_str[i] < 91) {
1411+
new_str[i] = new_str[i] + 32;
1412+
}
1413+
}
1414+
scratch = makeString(new_str);
1415+
return nullptr;
1416+
}
1417+
1418+
const AST *builtinAsciiUpper(const LocationRange &loc, const std::vector<Value> &args)
1419+
{
1420+
validateBuiltinArgs(loc, "asciiUpper", args, {Value::STRING});
1421+
const auto *str = static_cast<const HeapString *>(args[0].v.h);
1422+
UString new_str(str->value);
1423+
for (int i = 0; i < new_str.size(); ++i) {
1424+
if (new_str[i] > 96 && new_str[i] < 123) {
1425+
new_str[i] = new_str[i] - 32;
1426+
}
1427+
}
1428+
scratch = makeString(new_str);
1429+
return nullptr;
1430+
}
1431+
13111432
void jsonToHeap(const std::unique_ptr<JsonnetJsonValue> &v, bool &filled, Value &attach)
13121433
{
13131434
// In order to not anger the garbage collector, assign to attach immediately after

stdlib/std.jsonnet

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -35,18 +35,6 @@ limitations under the License.
3535
toString(a)::
3636
if std.type(a) == 'string' then a else '' + a,
3737

38-
substr(str, from, len)::
39-
if std.type(str) != 'string' then
40-
error 'substr first parameter should be a string, got ' + std.type(str)
41-
else if std.type(from) != 'number' then
42-
error 'substr second parameter should be a number, got ' + std.type(from)
43-
else if std.type(len) != 'number' then
44-
error 'substr third parameter should be a number, got ' + std.type(len)
45-
else if len < 0 then
46-
error 'substr third parameter should be greater than zero, got ' + len
47-
else
48-
std.join('', std.makeArray(len, function(i) str[i + from])),
49-
5038
startsWith(a, b)::
5139
if std.length(a) < std.length(b) then
5240
false
@@ -108,77 +96,6 @@ limitations under the License.
10896
else
10997
std.splitLimit(str, c, -1),
11098

111-
splitLimit(str, c, maxsplits)::
112-
if std.type(str) != 'string' then
113-
error 'std.splitLimit first parameter should be a string, got ' + std.type(str)
114-
else if std.type(c) != 'string' then
115-
error 'std.splitLimit second parameter should be a string, got ' + std.type(c)
116-
else if std.length(c) != 1 then
117-
error 'std.splitLimit second parameter should have length 1, got ' + std.length(c)
118-
else if std.type(maxsplits) != 'number' then
119-
error 'std.splitLimit third parameter should be a number, got ' + std.type(maxsplits)
120-
else
121-
local aux(str, delim, i, arr, v) =
122-
local c = str[i];
123-
local i2 = i + 1;
124-
if i >= std.length(str) then
125-
arr + [v]
126-
else if c == delim && (maxsplits == -1 || std.length(arr) < maxsplits) then
127-
aux(str, delim, i2, arr + [v], '') tailstrict
128-
else
129-
aux(str, delim, i2, arr, v + c) tailstrict;
130-
aux(str, c, 0, [], ''),
131-
132-
strReplace(str, from, to)::
133-
assert std.type(str) == 'string';
134-
assert std.type(from) == 'string';
135-
assert std.type(to) == 'string';
136-
assert from != '' : "'from' string must not be zero length.";
137-
138-
// Cache for performance.
139-
local str_len = std.length(str);
140-
local from_len = std.length(from);
141-
142-
// True if from is at str[i].
143-
local found_at(i) = str[i:i + from_len] == from;
144-
145-
// Return the remainder of 'str' starting with 'start_index' where
146-
// all occurrences of 'from' after 'curr_index' are replaced with 'to'.
147-
local replace_after(start_index, curr_index, acc) =
148-
if curr_index > str_len then
149-
acc + str[start_index:curr_index]
150-
else if found_at(curr_index) then
151-
local new_index = curr_index + std.length(from);
152-
replace_after(new_index, new_index, acc + str[start_index:curr_index] + to) tailstrict
153-
else
154-
replace_after(start_index, curr_index + 1, acc) tailstrict;
155-
156-
// if from_len==1, then we replace by splitting and rejoining the
157-
// string which is much faster than recursing on replace_after
158-
if from_len == 1 then
159-
std.join(to, std.split(str, from))
160-
else
161-
replace_after(0, 0, ''),
162-
163-
asciiUpper(x)::
164-
local cp = std.codepoint;
165-
local up_letter(c) = if cp(c) >= 97 && cp(c) < 123 then
166-
std.char(cp(c) - 32)
167-
else
168-
c;
169-
std.join('', std.map(up_letter, std.stringChars(x))),
170-
171-
asciiLower(x)::
172-
local cp = std.codepoint;
173-
local down_letter(c) = if cp(c) >= 65 && cp(c) < 91 then
174-
std.char(cp(c) + 32)
175-
else
176-
c;
177-
std.join('', std.map(down_letter, std.stringChars(x))),
178-
179-
180-
range(from, to)::
181-
std.makeArray(to - from + 1, function(i) i + from),
18299

183100
slice(indexable, index, end, step)::
184101
local invar =
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
RUNTIME ERROR: cannot test equality of functions
2-
std.jsonnet:1223:9-34 function <anonymous>
2+
std.jsonnet:1140:9-34 function <anonymous>
33
error.equality_function.jsonnet:17:1-33
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
RUNTIME ERROR: foobar
22
error.inside_equals_array.jsonnet:18:18-32 thunk <array_element>
3-
std.jsonnet:1203:29-33 thunk <b>
4-
std.jsonnet:1203:21-33 function <anonymous>
5-
std.jsonnet:1203:21-33 function <aux>
6-
std.jsonnet:1206:15-31 function <anonymous>
7-
std.jsonnet:1207:11-23
3+
std.jsonnet:1120:29-33 thunk <b>
4+
std.jsonnet:1120:21-33 function <anonymous>
5+
std.jsonnet:1120:21-33 function <aux>
6+
std.jsonnet:1123:15-31 function <anonymous>
7+
std.jsonnet:1124:11-23
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
RUNTIME ERROR: foobar
22
error.inside_equals_object.jsonnet:18:22-36 object <b>
3-
std.jsonnet:1217:50-54 thunk <b>
4-
std.jsonnet:1217:42-54 function <anonymous>
5-
std.jsonnet:1217:42-54 function <aux>
6-
std.jsonnet:1220:15-31 function <anonymous>
7-
std.jsonnet:1221:11-23
3+
std.jsonnet:1134:50-54 thunk <b>
4+
std.jsonnet:1134:42-54 function <anonymous>
5+
std.jsonnet:1134:42-54 function <aux>
6+
std.jsonnet:1137:15-31 function <anonymous>
7+
std.jsonnet:1138:11-23
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
RUNTIME ERROR: Object assertion failed.
22
error.invariant.equality.jsonnet:17:10-15 thunk <object_assert>
3-
std.jsonnet:1217:42-46 thunk <a>
4-
std.jsonnet:1217:42-54 function <anonymous>
5-
std.jsonnet:1217:42-54 function <anonymous>
6-
std.jsonnet:1221:11-23
3+
std.jsonnet:1134:42-46 thunk <a>
4+
std.jsonnet:1134:42-54 function <anonymous>
5+
std.jsonnet:1134:42-54 function <anonymous>
6+
std.jsonnet:1138:11-23
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
RUNTIME ERROR: Object assertion failed.
22
error.obj_assert.fail1.jsonnet:20:23-29 thunk <object_assert>
3-
std.jsonnet:1217:42-46 thunk <a>
4-
std.jsonnet:1217:42-54 function <anonymous>
5-
std.jsonnet:1217:42-54 function <anonymous>
6-
std.jsonnet:1221:11-23
3+
std.jsonnet:1134:42-46 thunk <a>
4+
std.jsonnet:1134:42-54 function <anonymous>
5+
std.jsonnet:1134:42-54 function <anonymous>
6+
std.jsonnet:1138:11-23
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
RUNTIME ERROR: foo was not equal to bar
22
error.obj_assert.fail2.jsonnet:20:32-65 thunk <object_assert>
3-
std.jsonnet:1217:42-46 thunk <a>
4-
std.jsonnet:1217:42-54 function <anonymous>
5-
std.jsonnet:1217:42-54 function <anonymous>
6-
std.jsonnet:1221:11-23
3+
std.jsonnet:1134:42-46 thunk <a>
4+
std.jsonnet:1134:42-54 function <anonymous>
5+
std.jsonnet:1134:42-54 function <anonymous>
6+
std.jsonnet:1138:11-23
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
RUNTIME ERROR: Assertion failed. 1 != 2
2-
std.jsonnet:782:7-50 function <anonymous>
2+
std.jsonnet:699:7-50 function <anonymous>
33
error.sanity.jsonnet:17:1-22

0 commit comments

Comments
 (0)