Skip to content

Commit

Permalink
Implement native extensions.
Browse files Browse the repository at this point in the history
  • Loading branch information
sparkprime committed May 27, 2016
1 parent c292727 commit 1c3cf2a
Show file tree
Hide file tree
Showing 10 changed files with 684 additions and 409 deletions.
6 changes: 3 additions & 3 deletions core/ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,11 @@ struct Binary : public AST {
* interpreter.
*/
struct BuiltinFunction : public AST {
unsigned long id;
std::string name;
Identifiers params;
BuiltinFunction(const LocationRange &lr, unsigned long id,
BuiltinFunction(const LocationRange &lr, const std::string &name,
const Identifiers &params)
: AST(lr, AST_BUILTIN_FUNCTION, Fodder{}), id(id), params(params)
: AST(lr, AST_BUILTIN_FUNCTION, Fodder{}), name(name), params(params)
{ }
};

Expand Down
7 changes: 6 additions & 1 deletion core/desugarer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ static const Fodder EF; // Empty fodder.

static const LocationRange E; // Empty.

struct BuiltinDecl {
String name;
std::vector<String> params;
};

static unsigned long max_builtin = 24;
BuiltinDecl jsonnet_builtin_decl(unsigned long builtin)
{
Expand Down Expand Up @@ -761,7 +766,7 @@ class Desugarer {
fields.emplace_back(
ObjectField::HIDDEN,
str(decl.name),
make<BuiltinFunction>(E, c, params));
make<BuiltinFunction>(E, encode_utf8(decl.name), params));
}
fields.emplace_back(
ObjectField::HIDDEN,
Expand Down
6 changes: 2 additions & 4 deletions core/formatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ class Unparser {
unparse(ast->right, true);

} else if (auto *ast = dynamic_cast<const BuiltinFunction*>(ast_)) {
o << "/* builtin " << ast->id << " */ null";
o << "/* builtin " << ast->name << " */ null";

} else if (auto *ast = dynamic_cast<const Conditional*>(ast_)) {
o << "if";
Expand Down Expand Up @@ -1724,10 +1724,8 @@ class FixIndentation {
expr(ast->right, new_indent, true);

} else if (auto *ast = dynamic_cast<BuiltinFunction*>(ast_)) {
std::stringstream ss;
ss << ast->id;
column += 11; // "/* builtin "
column += ss.str().length();
column += ast->name.length();
column += 8; // " */ null"

} else if (auto *ast = dynamic_cast<Conditional*>(ast_)) {
Expand Down
32 changes: 32 additions & 0 deletions core/json.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright 2015 Google Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef JSONNET_JSON_H
#define JSONNET_JSON_H

#include <string>

#include <libjsonnet.h>

struct JsonnetJsonValue {
enum Kind {
STRING
};
Kind kind;
std::string string;
};

#endif
40 changes: 35 additions & 5 deletions core/libjsonnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ extern "C" {

#include "desugarer.h"
#include "formatter.h"
#include "json.h"
#include "parser.h"
#include "static_analysis.h"
#include "vm.h"
Expand All @@ -50,6 +51,23 @@ static char *from_string(JsonnetVm* vm, const std::string &v)
static char *default_import_callback(void *ctx, const char *dir, const char *file,
char **found_here_cptr, int *success);

const char *jsonnet_json_extract_string(struct JsonnetJsonValue *v)
{
if (v->kind != JsonnetJsonValue::STRING)
return nullptr;
return v->string.c_str();
}

/** Convert the given UTF8 string to a JsonnetJsonValue.
*/
JsonnetJsonValue *jsonnet_json_make_string(const char *v)
{
JsonnetJsonValue *r = new JsonnetJsonValue();
r->kind = JsonnetJsonValue::STRING;
r->string = v;
return r;
}

struct JsonnetVm {
double gcGrowthTrigger;
unsigned maxStack;
Expand All @@ -58,6 +76,7 @@ struct JsonnetVm {
std::map<std::string, VmExt> ext;
std::map<std::string, VmExt> tla;
JsonnetImportCallback *importCallback;
VmNativeCallbackMap nativeCallbacks;
void *importCallbackContext;
bool stringOutput;
std::vector<std::string> jpaths;
Expand Down Expand Up @@ -212,6 +231,16 @@ void jsonnet_import_callback(struct JsonnetVm *vm, JsonnetImportCallback *cb, vo
vm->importCallbackContext = ctx;
}

void jsonnet_native_callback(struct JsonnetVm *vm, const char *name, JsonnetNativeCallback *cb,
void *ctx, const char * const *params)
{
std::vector<std::string> params2;
for (; params != nullptr; params++)
params2.push_back(*params);
vm->nativeCallbacks[name] = VmNativeCallback {cb, ctx, params2};
}


void jsonnet_ext_var(JsonnetVm *vm, const char *key, const char *val)
{
vm->ext[key] = VmExt(val, false);
Expand Down Expand Up @@ -373,8 +402,8 @@ static char *jsonnet_evaluate_snippet_aux(JsonnetVm *vm, const char *filename,
case REGULAR: {
std::string json_str = jsonnet_vm_execute(
&alloc, expr, vm->ext, vm->maxStack, vm->gcMinObjects,
vm->gcGrowthTrigger, vm->importCallback, vm->importCallbackContext,
vm->stringOutput);
vm->gcGrowthTrigger, vm->nativeCallbacks, vm->importCallback,
vm->importCallbackContext, vm->stringOutput);
json_str += "\n";
*error = false;
return from_string(vm, json_str);
Expand All @@ -384,8 +413,8 @@ static char *jsonnet_evaluate_snippet_aux(JsonnetVm *vm, const char *filename,
case MULTI: {
std::map<std::string, std::string> files = jsonnet_vm_execute_multi(
&alloc, expr, vm->ext, vm->maxStack, vm->gcMinObjects,
vm->gcGrowthTrigger, vm->importCallback, vm->importCallbackContext,
vm->stringOutput);
vm->gcGrowthTrigger, vm->nativeCallbacks, vm->importCallback,
vm->importCallbackContext, vm->stringOutput);
size_t sz = 1; // final sentinel
for (const auto &pair : files) {
sz += pair.first.length() + 1; // include sentinel
Expand Down Expand Up @@ -413,7 +442,8 @@ static char *jsonnet_evaluate_snippet_aux(JsonnetVm *vm, const char *filename,
case STREAM: {
std::vector<std::string> documents = jsonnet_vm_execute_stream(
&alloc, expr, vm->ext, vm->maxStack, vm->gcMinObjects,
vm->gcGrowthTrigger, vm->importCallback, vm->importCallbackContext);
vm->gcGrowthTrigger, vm->nativeCallbacks, vm->importCallback,
vm->importCallbackContext);
size_t sz = 1; // final sentinel
for (const auto &doc : documents) {
sz += doc.length() + 2; // Add a '\n' as well as sentinel
Expand Down
8 changes: 0 additions & 8 deletions core/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,6 @@ AST *jsonnet_parse(Allocator *alloc, Tokens &tokens);
*/
std::string jsonnet_unparse_number(double v);

struct BuiltinDecl {
String name;
std::vector<String> params;
};

/** Returns the signature of each built-in function. */
BuiltinDecl jsonnet_builtin_decl(unsigned long builtin);

/** The inverse of jsonnet_parse.
*/
std::string jsonnet_unparse_jsonnet(const AST *ast, const Fodder &final_fodder, unsigned indent,
Expand Down
8 changes: 4 additions & 4 deletions core/state.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ struct HeapComprehensionObject : public HeapLeafObject {

/** Stores the function itself and also the captured environment.
*
* Either body is non-null and builtin is 0, or body is null and builtin refers to a built-in
* Either body is non-null and builtinName is "", or body is null and builtin refers to a built-in
* function. In the former case, the closure represents a user function, otherwise calling it
* will trigger the builtin function to execute. Params is empty when the function is a
* builtin.
Expand All @@ -243,14 +243,14 @@ struct HeapClosure : public HeapEntity {
typedef std::vector<Param> Params;
const Params params;
const AST *body;
const unsigned long builtin;
std::string builtinName;
HeapClosure(const BindingFrame &up_values,
HeapObject *self,
unsigned offset,
const Params &params,
const AST *body, unsigned long builtin)
const AST *body, const std::string &builtin_name)
: upValues(up_values), self(self), offset(offset),
params(params), body(body), builtin(builtin)
params(params), body(body), builtinName(builtin_name)
{ }
};

Expand Down
Loading

0 comments on commit 1c3cf2a

Please sign in to comment.