Browse Source

Added logging settings and command line options

It was getting a bit annoying to have to toggle on/off hard-coded
bools.
HotReloadingState
Macoy Madson 9 months ago
parent
commit
8cb0267d4d
10 changed files with 151 additions and 63 deletions
  1. +17
    -24
      src/Evaluator.cpp
  2. +2
    -1
      src/Jamfile
  3. +3
    -0
      src/Logging.cpp
  4. +14
    -0
      src/Logging.hpp
  5. +90
    -12
      src/Main.cpp
  6. +4
    -5
      src/ModuleManager.cpp
  7. +8
    -4
      src/RunProcess.cpp
  8. +2
    -2
      src/Tokenizer.cpp
  9. +2
    -3
      src/Utilities.cpp
  10. +9
    -12
      src/Writer.cpp

+ 17
- 24
src/Evaluator.cpp View File

@ -5,6 +5,7 @@
#include "FileUtilities.hpp"
#include "GeneratorHelpers.hpp"
#include "Generators.hpp"
#include "Logging.hpp"
#include "OutputPreambles.hpp"
#include "RunProcess.hpp"
#include "Tokenizer.hpp"
@ -67,8 +68,6 @@ const ObjectReferenceStatus* addObjectReference(EvaluatorEnvironment& environmen
const Token& referenceNameToken,
ObjectReference& reference)
{
bool verbose = false;
// Default to the module requiring the reference, for top-level references
std::string definitionName = globalDefinitionName;
if (!reference.context.definitionName && reference.context.scope != EvaluatorScope_Module)
@ -80,7 +79,7 @@ const ObjectReferenceStatus* addObjectReference(EvaluatorEnvironment& environmen
}
const char* defName = definitionName.c_str();
if (verbose)
if (log.references)
printf("Adding reference %s to %s\n", referenceNameToken.contents.c_str(), defName);
// Add the reference requirement to the definition it occurred in
@ -428,8 +427,6 @@ const char* objectTypeToString(ObjectType type);
// TODO This can be made faster. I did the most naive version first, for now
void PropagateRequiredToReferences(EvaluatorEnvironment& environment)
{
bool verbose = false;
// Figure out what is required
// This needs to loop so long as it doesn't recurse to references
int numRequiresStatusChanged = 0;
@ -441,14 +438,14 @@ void PropagateRequiredToReferences(EvaluatorEnvironment& environment)
ObjectDefinition& definition = definitionPair.second;
const char* status = definition.isRequired ? "(required)" : "(not required)";
if (verbose)
if (log.dependencyPropagation)
printf("Define %s %s\n", definition.name->contents.c_str(), status);
for (ObjectReferenceStatusPair& reference : definition.references)
{
ObjectReferenceStatus& referenceStatus = reference.second;
if (verbose)
if (log.dependencyPropagation)
printf("\tRefers to %s\n", referenceStatus.name->contents.c_str());
if (definition.isRequired)
@ -457,7 +454,7 @@ void PropagateRequiredToReferences(EvaluatorEnvironment& environment)
environment.definitions.find(referenceStatus.name->contents);
if (findIt != environment.definitions.end() && !findIt->second.isRequired)
{
if (verbose)
if (log.dependencyPropagation)
printf("\t Infecting %s with required due to %s\n",
referenceStatus.name->contents.c_str(),
definition.name->contents.c_str());
@ -478,9 +475,6 @@ void OnCompileProcessOutput(const char* output)
int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut)
{
bool verbose = true;
bool verboseBuildProcess = true;
int numReferencesResolved = 0;
enum BuildStage
@ -532,7 +526,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
ObjectDefinition& definition = *definitionPointer;
const char* defName = definition.name->contents.c_str();
if (verbose)
if (log.buildReasons)
printf("Checking to build %s\n", defName);
// Can it be built in the current environment?
@ -572,7 +566,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
// incorrectly that this was a C call
if (referenceStatus.guessState != GuessState_Resolved)
{
if (verbose)
if (log.buildReasons)
printf("\tRequired code has been loaded\n");
hasRelevantChangeOccurred = true;
@ -584,7 +578,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
{
// If we know we are missing a compile time function, we won't try to
// guess
if (verbose)
if (log.buildReasons)
printf("\tCannot build until %s is loaded\n",
referenceStatus.name->contents.c_str());
@ -617,7 +611,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
{
if (referenceStatus.guessState == GuessState_None)
{
if (verbose)
if (log.buildReasons)
printf("\tCannot build until %s is guessed. Guessing now\n",
referenceStatus.name->contents.c_str());
@ -676,7 +670,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
{
ObjectDefinition* definition = buildObject.definition;
if (verboseBuildProcess)
if (log.buildProcess)
printf("Build %s\n", definition->name->contents.c_str());
char convertedNameBuffer[MAX_NAME_LENGTH] = {0};
@ -740,7 +734,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
if (!fileIsMoreRecentlyModified(sourceOutputName, buildObject.dynamicLibraryPath.c_str()))
{
if (verboseBuildProcess)
if (log.buildProcess)
printf("Skipping compiling %s (using cached library)\n", sourceOutputName);
// Skip straight to linking, which immediately becomes loading
buildObject.stage = BuildStage_Linking;
@ -792,7 +786,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
buildObject.stage = BuildStage_Linking;
if (verboseBuildProcess)
if (log.buildProcess)
printf("Compiled %s successfully\n", buildObject.definition->name->contents.c_str());
char linkerExecutable[MAX_PATH_LENGTH] = {0};
@ -830,7 +824,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
buildObject.stage = BuildStage_Loading;
if (verboseBuildProcess)
if (log.buildProcess)
printf("Linked %s successfully\n", buildObject.definition->name->contents.c_str());
DynamicLibHandle builtLib = loadDynamicLibrary(buildObject.dynamicLibraryPath.c_str());
@ -889,7 +883,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
// function, clear that invocation output
resetGeneratorOutput(*reference.spliceOutput);
if (verbose)
if (log.buildProcess)
NoteAtToken((*reference.tokens)[reference.startIndex], "resolving reference");
// Evaluate from that reference
@ -906,7 +900,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
++numReferencesResolved;
}
if (verbose)
if (log.buildProcess)
printf("Resolved %d references\n", numReferencesResolved);
// Remove need to build
@ -914,7 +908,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
buildObject.stage = BuildStage_Finished;
if (verboseBuildProcess)
if (log.buildProcess)
printf("Successfully built, loaded, and executed %s\n",
buildObject.definition->name->contents.c_str());
}
@ -925,8 +919,7 @@ int BuildEvaluateReferences(EvaluatorEnvironment& environment, int& numErrorsOut
bool EvaluateResolveReferences(EvaluatorEnvironment& environment)
{
// Print state
bool verbose = false;
if (verbose)
if (log.references)
{
for (ObjectDefinitionPair& definitionPair : environment.definitions)
{


+ 2
- 1
src/Jamfile View File

@ -15,7 +15,8 @@ GeneratorHelpers.cpp
RunProcess.cpp
OutputPreambles.cpp
DynamicLoader.cpp
ModuleManager.cpp ;
ModuleManager.cpp
Logging.cpp ;
MakeLocate cakelisp$(SUFEXE) : bin ;
MakeLocate libCakelisp.a : lib ;


+ 3
- 0
src/Logging.cpp View File

@ -0,0 +1,3 @@
#include "Logging.hpp"
LoggingSettings log = {};

+ 14
- 0
src/Logging.hpp View File

@ -0,0 +1,14 @@
struct LoggingSettings
{
// verbosity
bool tokenization;
bool references;
bool dependencyPropagation;
bool buildReasons;
bool buildProcess;
bool fileSystem;
bool metadata;
bool processes;
};
extern LoggingSettings log;

+ 90
- 12
src/Main.cpp View File

@ -3,37 +3,113 @@
#include <vector>
#include "Logging.hpp"
#include "ModuleManager.hpp"
#include "Utilities.hpp"
int main(int argc, char* argv[])
struct CommandLineOption
{
const char* handle;
bool* toggleOnOut;
const char* help;
};
void printHelp(const CommandLineOption* options, int numOptions)
{
const char* helpString =
"OVERVIEW: Cakelisp transpiler\n"
"Cakelisp is a transpiler which generates C/C++ from a Lisp dialect.\n"
"Created by Macoy Madson <macoy@macoy.me>.\nhttps://macoy.me/code/macoy/cakelisp\n\n"
"USAGE: cakelisp <input .cake files>\n\n"
"USAGE: cakelisp [options] <input .cake files>\nAll options must precede .cake files.\n\n"
"OPTIONS:\n";
if (argc != 2)
printf("%s", helpString);
for (int optionIndex = 0; optionIndex < numOptions; ++optionIndex)
{
printf("Error: expected file to parse\n\n");
printf("%s", helpString);
return 1;
printf("%s\n\t%s\n", options[optionIndex].handle, options[optionIndex].help);
}
}
if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
int main(int numArguments, char* arguments[])
{
const CommandLineOption options[] = {
{"--verbose-tokenization", &log.tokenization,
"Output details about the conversion from file text to tokens"},
{"--verbose-references", &log.references,
"Output when references to function/macro/generator invocations are created"},
{"--verbose-dependency-propagation", &log.dependencyPropagation,
"Output why objects are being built (why they are required for building)"},
{"--verbose-build-reasons", &log.buildReasons,
"Output why objects are or are not being built in each compile-time build cycle"},
{"--verbose-build-process", &log.buildProcess,
"Output object statuses as they move through the compile-time pipeline"},
{"--verbose-processes", &log.processes,
"Output full command lines of all child processes created during the compile-time build "
"process"},
{"--verbose-file-system", &log.fileSystem,
"Output why files are being written, the status of comparing files, etc."},
{"--verbose-metadata", &log.metadata, "Output generated metadata"},
};
if (numArguments == 1)
{
printf("%s", helpString);
printf("Error: expected file(s) to evaluate\n\n");
printHelp(options, ArraySize(options));
return 1;
}
const char* filename = argv[1];
int startFiles = numArguments;
for (int i = 1; i < numArguments; ++i)
{
if (strcmp(arguments[i], "-h") == 0 || strcmp(arguments[i], "--help") == 0)
{
printHelp(options, ArraySize(options));
return 1;
}
else if (arguments[i][0] != '-')
{
startFiles = i;
}
else
{
if (startFiles < numArguments)
{
printf("Error: Options must precede files\n\n");
printHelp(options, ArraySize(options));
return 1;
}
for (int optionIndex = 0; (unsigned long)optionIndex < ArraySize(options);
++optionIndex)
{
if (strcmp(arguments[i], options[optionIndex].handle) == 0)
*options[optionIndex].toggleOnOut = true;
}
}
}
std::vector<const char*> filesToEvaluate;
for (int i = startFiles; i < numArguments; ++i)
filesToEvaluate.push_back(arguments[i]);
if (filesToEvaluate.empty())
{
printf("Error: expected file(s) to evaluate\n\n");
printHelp(options, ArraySize(options));
return 1;
}
ModuleManager moduleManager = {};
moduleManagerInitialize(moduleManager);
if (!moduleManagerAddEvaluateFile(moduleManager, filename))
for (const char* filename : filesToEvaluate)
{
moduleManagerDestroy(moduleManager);
return 1;
if (!moduleManagerAddEvaluateFile(moduleManager, filename))
{
moduleManagerDestroy(moduleManager);
return 1;
}
}
if (!moduleManagerEvaluateResolveReferences(moduleManager))
@ -48,6 +124,8 @@ int main(int argc, char* argv[])
return 1;
}
printf("Successfully generated files\n");
moduleManagerDestroy(moduleManager);
return 0;
}

+ 4
- 5
src/ModuleManager.cpp View File

@ -4,6 +4,7 @@
#include "Evaluator.hpp"
#include "FileUtilities.hpp"
#include "Generators.hpp"
#include "Logging.hpp"
#include "OutputPreambles.hpp"
#include "RunProcess.hpp"
#include "Tokenizer.hpp"
@ -50,8 +51,6 @@ void moduleManagerDestroy(ModuleManager& manager)
bool moduleLoadTokenizeValidate(const char* filename, const std::vector<Token>** tokensOut)
{
bool verbose = false;
*tokensOut = nullptr;
FILE* file = fileOpen(filename, "r");
@ -67,7 +66,7 @@ bool moduleLoadTokenizeValidate(const char* filename, const std::vector<Token>**
std::vector<Token>* tokens_CREATIONONLY = new std::vector<Token>;
while (fgets(lineBuffer, sizeof(lineBuffer), file))
{
if (verbose)
if (log.tokenization)
printf("%s", lineBuffer);
const char* error =
@ -87,7 +86,7 @@ bool moduleLoadTokenizeValidate(const char* filename, const std::vector<Token>**
tokens = tokens_CREATIONONLY;
}
if (verbose)
if (log.tokenization)
printf("Tokenized %d lines\n", lineNumber - 1);
if (!validateParentheses(*tokens))
@ -96,7 +95,7 @@ bool moduleLoadTokenizeValidate(const char* filename, const std::vector<Token>**
return false;
}
if (verbose)
if (log.tokenization)
{
printf("\nResult:\n");


+ 8
- 4
src/RunProcess.cpp View File

@ -12,6 +12,7 @@
#error Platform support is needed for running subprocesses
#endif
#include "Logging.hpp"
#include "Utilities.hpp"
#ifdef UNIX
@ -54,12 +55,15 @@ void subprocessReceiveStdOut(const char* processOutputBuffer)
int runProcess(const RunProcessArguments& arguments, int* statusOut)
{
#ifdef UNIX
printf("RunProcess command: ");
for (char** arg = arguments.arguments; *arg != nullptr; ++arg)
if (log.processes)
{
printf("%s ", *arg);
printf("RunProcess command: ");
for (char** arg = arguments.arguments; *arg != nullptr; ++arg)
{
printf("%s ", *arg);
}
printf("\n");
}
printf("\n");
int pipeFileDescriptors[2] = {0};
const int PipeRead = 0;


+ 2
- 2
src/Tokenizer.cpp View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include <cctype>
#include "Logging.hpp"
#include "Utilities.hpp"
static const char commentCharacter = ';';
@ -18,7 +19,6 @@ enum TokenizeState
const char* tokenizeLine(const char* inputLine, const char* source, unsigned int lineNumber,
std::vector<Token>& tokensOut)
{
bool verbose = false;
const char* A_OK = nullptr;
TokenizeState tokenizeState = TokenizeState_Normal;
@ -93,7 +93,7 @@ const char* tokenizeLine(const char* inputLine, const char* source, unsigned int
// Finished the symbol
if (std::isspace(*currentChar) || *currentChar == '\n' || isParenthesis)
{
if (verbose)
if (log.tokenization)
printf("%s\n", contentsBuffer);
Token symbol = {TokenType_Symbol, EmptyString, source,
lineNumber, columnStart, currentColumn};


+ 2
- 3
src/Utilities.cpp View File

@ -1,4 +1,5 @@
#include "Utilities.hpp"
#include "Logging.hpp"
#include <stdio.h>
@ -12,8 +13,6 @@ void printIndentToDepth(int depth)
FILE* fileOpen(const char* filename, const char* mode)
{
bool verbose = false;
FILE* file = nullptr;
file = fopen(filename, mode);
if (!file)
@ -23,7 +22,7 @@ FILE* fileOpen(const char* filename, const char* mode)
}
else
{
if (verbose)
if (log.fileSystem)
printf("Opened %s\n", filename);
}
return file;


+ 9
- 12
src/Writer.cpp View File

@ -2,6 +2,7 @@
#include "Converters.hpp"
#include "Evaluator.hpp"
#include "Logging.hpp"
#include "Tokenizer.hpp"
#include "Utilities.hpp"
@ -24,7 +25,8 @@ bool moveFile(const char* srcFilename, const char* destFilename)
fclose(srcFile);
fclose(destFile);
printf("Wrote %s\n", destFilename);
if (log.fileSystem)
printf("Wrote %s\n", destFilename);
if (remove(srcFilename) != 0)
{
@ -37,7 +39,6 @@ bool moveFile(const char* srcFilename, const char* destFilename)
bool writeIfContentsNewer(const char* tempFilename, const char* outputFilename)
{
bool verbose = false;
// Read temporary file and destination file and compare
FILE* newFile = fopen(tempFilename, "r");
if (!newFile)
@ -49,14 +50,14 @@ bool writeIfContentsNewer(const char* tempFilename, const char* outputFilename)
if (!oldFile)
{
// Write new and remove temp
if (verbose)
if (log.fileSystem)
printf("Destination file didn't exist. Writing\n");
return moveFile(tempFilename, outputFilename);
}
else
{
if (verbose)
if (log.fileSystem)
printf("Destination file exists. Comparing\n");
char newBuffer[1024] = {0};
@ -82,7 +83,7 @@ bool writeIfContentsNewer(const char* tempFilename, const char* outputFilename)
if (identical)
{
if (verbose)
if (log.fileSystem)
printf("Files are identical. Skipping\n");
fclose(newFile);
@ -95,7 +96,7 @@ bool writeIfContentsNewer(const char* tempFilename, const char* outputFilename)
return true;
}
if (verbose)
if (log.fileSystem)
printf("File changed. writing\n");
fclose(newFile);
@ -350,8 +351,6 @@ void writeOutputFollowSplices_Recursive(const NameStyleSettings& nameSettings,
bool writeOutputs(const NameStyleSettings& nameSettings, const WriterFormatSettings& formatSettings,
const WriterOutputSettings& outputSettings, const GeneratorOutput& outputToWrite)
{
bool verbose = false;
char sourceOutputName[MAX_PATH_LENGTH] = {0};
PrintfBuffer(sourceOutputName, "%s.cpp", outputSettings.sourceCakelispFilename);
char headerOutputName[MAX_PATH_LENGTH] = {0};
@ -421,7 +420,7 @@ bool writeOutputs(const NameStyleSettings& nameSettings, const WriterFormatSetti
if (outputs[i].outputState.numCharsOutput ==
outputs[i].stateBeforeOutputWrite.numCharsOutput)
{
if (verbose)
if (log.fileSystem)
printf("%s had no meaningful output\n", outputs[i].tempFilename);
fclose(outputs[i].outputState.fileOut);
@ -464,13 +463,11 @@ bool writeGeneratorOutput(const GeneratorOutput& generatedOutput,
const WriterFormatSettings& formatSettings,
const WriterOutputSettings& outputSettings)
{
bool verbose = false;
if (!writeOutputs(nameSettings, formatSettings, outputSettings, generatedOutput))
return false;
// TODO: Write mapping and metadata
if (verbose)
if (log.metadata)
{
// Metadata
printf("\n\tImports:\n");


Loading…
Cancel
Save