Skip to content

Commit 06c1ce1

Browse files
sbarzowskisparkprime
authored andcommitted
std.parseJson - a builtin for parsing json (google#553)
1 parent c869920 commit 06c1ce1

15 files changed

+19115
-72
lines changed

.travis.yml

+27-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,32 @@
1-
language: cpp
2-
compiler:
3-
- gcc
4-
- clang
1+
language: generic
2+
matrix:
3+
include:
4+
- os: linux
5+
env: COMPILER_NAME=gcc CXX=g++-4.9 CC=gcc-4.9
6+
addons:
7+
apt:
8+
packages:
9+
- g++-4.9
10+
sources: &sources
11+
- llvm-toolchain-precise-3.8
12+
- ubuntu-toolchain-r-test
13+
- os: linux
14+
env: COMPILER_NAME=clang CXX=clang++-3.8 CC=clang-3.8
15+
addons:
16+
apt:
17+
packages:
18+
- clang-3.8
19+
sources: *sources
20+
- os: osx
21+
osx_image: xcode8
22+
env: CC=gcc-4.9 && CXX=g++-4.9
23+
- os: osx
24+
osx_image: xcode8
25+
env: CC=clang && CXX=clang++
526
before_install:
627
- echo $LANG
728
- echo $LC_ALL
29+
- $CXX --version
830
before_script:
931
script:
1032
# - rvm get head # Workaround 'shell_session_update: command not found'
@@ -27,7 +49,4 @@ notifications:
2749
channels:
2850
- "chat.freenode.net#jsonnet"
2951
template:
30-
- "%{repository}/%{branch} (%{commit} - %{author}): %{message}"
31-
os:
32-
- linux
33-
- osx
52+
- "%{repository}/%{branch} (%{commit} - %{author}): %{message}"

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ link_directories(${GLOBAL_OUTPUT_PATH})
8787
include_directories(
8888
include
8989
third_party/md5
90+
third_party/json
9091
core)
9192

9293
install(DIRECTORY include DESTINATION include)

MANIFEST.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
include LICENSE include/*.h core/*.cpp core/*.h python/*.c third_party/md5/*.cpp third_party/md5/*.h stdlib/std.jsonnet Makefile
1+
include LICENSE include/*.h core/*.cpp core/*.h python/*.c third_party/json*.hpp third_party/md5/*.cpp third_party/md5/*.h stdlib/std.jsonnet Makefile
22
#recursive-include test_suite examples gc_stress benchmarks editors

Makefile

+4-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ OD ?= od
2929

3030
OPT ?= -O3
3131

32-
CXXFLAGS ?= -g $(OPT) -Wall -Wextra -Woverloaded-virtual -pedantic -std=c++0x -fPIC -Iinclude -Ithird_party/md5
32+
CXXFLAGS ?= -g $(OPT) -Wall -Wextra -Woverloaded-virtual -pedantic -std=c++0x -fPIC -Iinclude -Ithird_party/md5 -Ithird_party/json
3333
CFLAGS ?= -g $(OPT) -Wall -Wextra -pedantic -std=c99 -fPIC -Iinclude
34-
MAKEDEPENDFLAGS ?= -Iinclude -Ithird_party/md5
34+
MAKEDEPENDFLAGS ?= -Iinclude -Ithird_party/md5 -Ithird_party/json
3535
EMCXXFLAGS = $(CXXFLAGS) -g0 -Os --memory-init-file 0 -s DISABLE_EXCEPTION_CATCHING=0 -s OUTLINING_LIMIT=10000 -s RESERVED_FUNCTION_POINTERS=20
3636
EMCFLAGS = $(CFLAGS) --memory-init-file 0 -s DISABLE_EXCEPTION_CATCHING=0
3737
LDFLAGS ?=
@@ -86,7 +86,8 @@ ALL_HEADERS = \
8686
include/libjsonnet.h \
8787
include/libjsonnet_fmt.h \
8888
include/libjsonnet++.h \
89-
third_party/md5/md5.h
89+
third_party/md5/md5.h \
90+
third_party/json/json.hpp
9091

9192
default: jsonnet
9293

core/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ cc_library(
3232
"//include:libjsonnet",
3333
"//include:libjsonnet_fmt",
3434
"//stdlib:std",
35+
"//third_party/json:json",
3536
"//third_party/md5:libmd5",
3637
],
3738
linkopts = ["-lm"],

core/desugarer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ struct BuiltinDecl {
3434
std::vector<UString> params;
3535
};
3636

37-
static unsigned long max_builtin = 34;
37+
static unsigned long max_builtin = 35;
3838
BuiltinDecl jsonnet_builtin_decl(unsigned long builtin)
3939
{
4040
switch (builtin) {
@@ -73,6 +73,7 @@ BuiltinDecl jsonnet_builtin_decl(unsigned long builtin)
7373
case 32: return {U"asciiLower", {U"str"}};
7474
case 33: return {U"asciiUpper", {U"str"}};
7575
case 34: return {U"join", {U"sep", U"arr"}};
76+
case 35: return {U"parseJson", {U"str"}};
7677
default:
7778
std::cerr << "INTERNAL ERROR: Unrecognized builtin function: " << builtin << std::endl;
7879
std::abort();

core/vm.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,16 @@ limitations under the License.
2323

2424
#include "desugarer.h"
2525
#include "json.h"
26+
#include "json.hpp"
2627
#include "md5.h"
2728
#include "parser.h"
2829
#include "state.h"
2930
#include "static_analysis.h"
3031
#include "string_utils.h"
3132
#include "vm.h"
3233

34+
using json = nlohmann::json;
35+
3336
namespace {
3437

3538
/** Turn a path e.g. "/a/b/c" into a dir, e.g. "/a/b/". If there is no path returns "".
@@ -870,6 +873,7 @@ class Interpreter {
870873
builtins["asciiLower"] = &Interpreter::builtinAsciiLower;
871874
builtins["asciiUpper"] = &Interpreter::builtinAsciiUpper;
872875
builtins["join"] = &Interpreter::builtinJoin;
876+
builtins["parseJson"] = &Interpreter::builtinParseJson;
873877
}
874878

875879
/** Clean up the heap, stack, stash, and builtin function ASTs. */
@@ -1435,6 +1439,75 @@ class Interpreter {
14351439
return nullptr;
14361440
}
14371441

1442+
const AST *builtinParseJson(const LocationRange &loc, const std::vector<Value> &args)
1443+
{
1444+
validateBuiltinArgs(loc, "parseJson", args, {Value::STRING});
1445+
1446+
std::string value = encode_utf8(static_cast<HeapString *>(args[0].v.h)->value);
1447+
1448+
auto j = json::parse(value);
1449+
1450+
bool filled;
1451+
1452+
otherJsonToHeap(j, filled, scratch);
1453+
1454+
return nullptr;
1455+
}
1456+
1457+
void otherJsonToHeap(const json &v, bool &filled, Value &attach) {
1458+
// In order to not anger the garbage collector, assign to attach immediately after
1459+
// making the heap object.
1460+
switch (v.type()) {
1461+
case json::value_t::string:
1462+
attach = makeString(decode_utf8(v.get<std::string>()));
1463+
filled = true;
1464+
break;
1465+
1466+
case json::value_t::boolean:
1467+
attach = makeBoolean(v.get<bool>());
1468+
filled = true;
1469+
break;
1470+
1471+
case json::value_t::number_integer:
1472+
case json::value_t::number_unsigned:
1473+
case json::value_t::number_float:
1474+
attach = makeNumber(v.get<double>());
1475+
filled = true;
1476+
break;
1477+
1478+
case json::value_t::null:
1479+
attach = makeNull();
1480+
filled = true;
1481+
break;
1482+
1483+
case json::value_t::array:{
1484+
attach = makeArray(std::vector<HeapThunk *>(v.size()));
1485+
filled = true;
1486+
auto *arr = static_cast<HeapArray *>(attach.v.h);
1487+
for (size_t i = 0; i < v.size(); ++i) {
1488+
arr->elements[i] = makeHeap<HeapThunk>(idArrayElement, nullptr, 0, nullptr);
1489+
otherJsonToHeap(v[i], arr->elements[i]->filled, arr->elements[i]->content);
1490+
}
1491+
} break;
1492+
1493+
case json::value_t::object: {
1494+
attach = makeObject<HeapComprehensionObject>(
1495+
BindingFrame{}, jsonObjVar, idJsonObjVar, BindingFrame{});
1496+
filled = true;
1497+
auto *obj = static_cast<HeapComprehensionObject *>(attach.v.h);
1498+
for (auto it = v.begin(); it != v.end(); ++it) {
1499+
auto *thunk = makeHeap<HeapThunk>(idJsonObjVar, nullptr, 0, nullptr);
1500+
obj->compValues[alloc->makeIdentifier(decode_utf8(it.key()))] = thunk;
1501+
otherJsonToHeap(it.value(), thunk->filled, thunk->content);
1502+
}
1503+
} break;
1504+
1505+
case json::value_t::discarded: {
1506+
abort();
1507+
}
1508+
}
1509+
}
1510+
14381511
void joinString(UString &running, const Value &sep, unsigned idx, const Value &elt)
14391512
{
14401513
if (elt.t == Value::NULL_TYPE) {

0 commit comments

Comments
 (0)