feat: faster parser (#3)

* fix(load): support nested objects

* feat: initial golang parser

Moves most of load.libsonnet to a Golang app for hopefully much faster
parsing (fingers crossed)

* feat(fast): nested objects, subpackages

* feat: incorporate fast mode into main binary

Moves the work done in the fast directory into the main executable,
removing the Jsonnet based parser in favor of the much faster Golang one.
This commit is contained in:
sh0rez 2020-05-10 23:09:12 +02:00 committed by GitHub
parent 75f8e7373c
commit 4e4d4a7170
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 442 additions and 57 deletions

View file

@ -1,59 +1,24 @@
local lib = {
// reshape converts the Jsonnet structure to the one used by docsonnet:
// - put fields into an `api` key
// - put subpackages into `sub` key
reshape(pkg)::
local aux(old, key) =
if key == '#' then
old
else if std.objectHas(pkg[key], '#') then
old { sub+: { [key]: $.package(pkg[key]) } }
else
old { api+: { [key]: pkg[key] } };
std.foldl(aux, std.objectFields(pkg), {})
+ pkg['#'],
// fillObjects creates docsonnet objects from Jsonnet ones,
// also filling those that have been specified explicitely
fillObjects(api)::
scan(obj)::
local aux(old, key) =
if std.startsWith(key, '#') then
old { [key]: api[key] }
else if std.isObject(api[key]) && std.length(std.objectFields(api[key])) > 0 then
old { ['#' + key]+: { object+: {
fields: api[key],
} } }
true
else if std.isObject(obj[key]) then
old || $.scan(obj[key])
else old;
std.foldl(aux, std.objectFieldsAll(obj), false),
load(pkg)::
local aux(old, key) =
if !std.isObject(pkg[key]) then
old
else if std.startsWith(key, '#') then
old { [key]: pkg[key] }
else if self.scan(pkg[key]) then
old { [key]: $.load(pkg[key]) }
else old;
std.foldl(aux, std.objectFields(api), {}),
// clean removes all hashes from field names
clean(api):: {
[std.lstripChars(key, '#')]:
if std.isObject(api[key]) then $.clean(api[key])
else api[key]
for key in std.objectFields(api)
},
cleanNonObj(api):: {
[key]:
if std.startsWith(key, "#") then api[key]
else if std.isObject(api[key]) then $.cleanNonObj(api[key])
else api[key]
for key in std.objectFieldsAll(api)
if std.isObject(api[key])
},
// package loads docsonnet from a Jsonnet package
package(pkg)::
local cleaned = self.cleanNonObj(pkg);
local reshaped = self.reshape(cleaned);
local filled =
if std.objectHas(reshaped, 'api')
then reshaped { api: $.fillObjects(reshaped.api) }
else reshaped;
self.clean(filled),
std.foldl(aux, std.objectFieldsAll(pkg), {}),
};
lib.package(std.extVar("main"))
lib.load(std.extVar('main'))