@@ -372,7 +372,7 @@ namespace {
372
372
const Identifier *idArrayElement;
373
373
374
374
/* * Cache for imported Jsonnet files. */
375
- std::map<std::string, AST *> cachedImports;
375
+ std::map<std::string, const std::string *> cachedImports;
376
376
377
377
RuntimeError makeError (const LocationRange &loc, const std::string &msg)
378
378
{
@@ -581,22 +581,36 @@ namespace {
581
581
*/
582
582
AST *import (const LocationRange &loc, const std::string &file)
583
583
{
584
- auto *expr = cachedImports[file];
585
- if (expr != nullptr ) return expr;
584
+ const std::string *input = importString (loc, file);
585
+ auto *expr = jsonnet_parse (alloc, file, input->c_str ());
586
+ jsonnet_static_analysis (expr);
587
+ return expr;
588
+ }
586
589
587
- std::string input;
590
+ /* * Import a file as a string.
591
+ *
592
+ * If the file has already been imported, then use that version. This maintains
593
+ * referential transparency in the case of writes to disk during execution.
594
+ *
595
+ * \param loc Location of the import statement.
596
+ * \param file Path to the filename.
597
+ */
598
+ const std::string *importString (const LocationRange &loc, const std::string &file)
599
+ {
600
+ const std::string *str = cachedImports[file];
601
+ if (str != nullptr ) return str;
602
+
603
+ std::string *input = new std::string ();
588
604
std::ifstream f;
589
605
f.open (file.c_str ());
590
606
if (!f.good ()) {
591
607
std::string msg = " Couldn't open import \" " + file + " \" : " ;
592
608
msg += std::strerror (errno);
593
609
throw makeError (loc, msg);
594
610
}
595
- input.assign (std::istreambuf_iterator<char >(f), std::istreambuf_iterator<char >());
596
- expr = jsonnet_parse (alloc, file, input.c_str ());
597
- jsonnet_static_analysis (expr);
598
- cachedImports[file] = expr;
599
- return expr;
611
+ input->assign (std::istreambuf_iterator<char >(f), std::istreambuf_iterator<char >());
612
+ cachedImports[file] = input;
613
+ return input;
600
614
}
601
615
602
616
/* * Capture the required variables from the environment. */
@@ -645,6 +659,9 @@ namespace {
645
659
/* * Clean up the heap, stack, stash, and builtin function ASTs. */
646
660
~Interpreter ()
647
661
{
662
+ for (const auto &pair : cachedImports) {
663
+ delete pair.second ;
664
+ }
648
665
}
649
666
650
667
const Value &getScratchRegister (void )
@@ -913,6 +930,12 @@ namespace {
913
930
goto recurse;
914
931
} break ;
915
932
933
+ case AST_IMPORTSTR: {
934
+ const auto &ast = *static_cast <const Importstr*>(ast_);
935
+ const std::string *str = importString (ast.location , ast.file );
936
+ scratch = makeString (*str);
937
+ } break ;
938
+
916
939
case AST_INDEX: {
917
940
const auto &ast = *static_cast <const Index*>(ast_);
918
941
stack.newFrame (FRAME_INDEX_TARGET, ast_);
0 commit comments