Skip to content

Commit 0248c5e

Browse files
committed
Implement string indexing, closes #12
1 parent 291c3e6 commit 0248c5e

File tree

2 files changed

+58
-4
lines changed

2 files changed

+58
-4
lines changed

test_suite/arith_string.jsonnet

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright 2014 Google Inc. All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
std.assertEqual("foo", "foo") &&
18+
std.assertEqual("foo" + "bar", "foobar") &&
19+
20+
std.assertEqual("foo" + true, "footrue") &&
21+
std.assertEqual("foo" + false, "foofalse") &&
22+
std.assertEqual("foo" + 0, "foo0") &&
23+
std.assertEqual("foo" + null, "foonull") &&
24+
25+
std.assertEqual(true + "foo", "truefoo") &&
26+
std.assertEqual(false + "foo", "falsefoo") &&
27+
std.assertEqual(0 + "foo", "0foo") &&
28+
std.assertEqual(null + "foo", "nullfoo") &&
29+
30+
std.assertEqual("alphabet"[7], "t") &&
31+
std.assertEqual("alphabet"[0], "a") &&
32+
33+
true

vm.cpp

+25-4
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ namespace {
16171617
if (i < 0 || i >= sz) {
16181618
std::stringstream ss;
16191619
ss << "Array bounds error: " << i
1620-
<< " not within [0, " << sz << "]";
1620+
<< " not within [0, " << sz << ")";
16211621
throw makeError(ast.location, ss.str());
16221622
}
16231623
auto *thunk = array->elements[i];
@@ -1644,18 +1644,39 @@ namespace {
16441644
stack.pop();
16451645
ast_ = objectIndex(ast.location, obj, fid);
16461646
goto recurse;
1647+
} else if (target.t == Value::STRING) {
1648+
auto *obj = static_cast<HeapString*>(target.v.h);
1649+
assert(obj != nullptr);
1650+
if (scratch.t != Value::DOUBLE) {
1651+
throw makeError(ast.location,
1652+
"String index must be a number, got "
1653+
+ type_str(scratch) + ".");
1654+
}
1655+
// TODO(dcunnin): UTF-8 support goes here.
1656+
long sz = obj->value.length();
1657+
long i = (long)scratch.v.d;
1658+
if (i < 0 || i >= sz) {
1659+
std::stringstream ss;
1660+
ss << "String bounds error: " << i
1661+
<< " not within [0, " << sz << ")";
1662+
throw makeError(ast.location, ss.str());
1663+
}
1664+
char ch[] = {obj->value[i], '\0'};
1665+
scratch = makeString(ch);
16471666
} else {
1648-
std::cerr << "INTERNAL ERROR: Neither an object nor an array."
1667+
std::cerr << "INTERNAL ERROR: Not object / array / string."
16491668
<< std::endl;
16501669
abort();
16511670
}
16521671
} break;
16531672

16541673
case FRAME_INDEX_TARGET: {
16551674
const auto &ast = *static_cast<const Index*>(f.ast);
1656-
if (scratch.t != Value::ARRAY && scratch.t != Value::OBJECT) {
1675+
if (scratch.t != Value::ARRAY
1676+
&& scratch.t != Value::OBJECT
1677+
&& scratch.t != Value::STRING) {
16571678
throw makeError(ast.location,
1658-
"Can only index objects and arrays, got "
1679+
"Can only index objects, strings, and arrays, got "
16591680
+ type_str(scratch) + ".");
16601681
}
16611682
ast_ = ast.index;

0 commit comments

Comments
 (0)