mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Added header-only parsing to the repl, read more
Also: * Ensured TOY_VERSION_BUILD is consistent throughout the whole build * Updated README.md
This commit is contained in:
@@ -4,9 +4,11 @@
|
||||
|
||||
# Toy
|
||||
|
||||
This is the Toy programming language interpreter, written in C.
|
||||
The Toy programming language is an imperative bytecode-intermediate embedded scripting language. It isn't intended to operate on its own, but rather as part of another program, the "host". This process is intended to allow a decent amount of easy customisation by the host's end user, by exposing logic in script files. Alternatively, binary files in a custom format can be used as well.
|
||||
|
||||
Special thanks to http://craftinginterpreters.com/ for their fantastic book that set me on this path.
|
||||
The host will provide all of the extensions needed on a case-by-case basis. Script files have the `.toy` file extension, while binary files have the `.tb` file extension.
|
||||
|
||||
This is the Toy programming language interpreter, written in C.
|
||||
|
||||
# Nifty Features
|
||||
|
||||
@@ -14,7 +16,7 @@ Special thanks to http://craftinginterpreters.com/ for their fantastic book that
|
||||
* Bytecode intermediate compilation
|
||||
* Optional, but robust type system (including `opaque` for arbitrary data)
|
||||
* Functions and types are first-class citizens
|
||||
* Import external libraries
|
||||
* Import native libraries from the host
|
||||
* Fancy slice notation for strings, arrays and dictionaries
|
||||
* Can re-direct output, error and assertion failure messages
|
||||
* Open source under the zlib license
|
||||
@@ -71,3 +73,4 @@ This source code is covered by the zlib license (see [LICENSE.md](LICENSE.md)).
|
||||
|
||||
* Seth A. Robinson
|
||||
|
||||
Special thanks to http://craftinginterpreters.com/ for their fantastic book that set me on this path.
|
||||
@@ -193,8 +193,14 @@ int main(int argc, const char* argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (Toy_commandLine.parseBytecodeHeader) {
|
||||
//only parse the bytecode header
|
||||
Toy_parseBinaryFileHeader(Toy_commandLine.binaryfile);
|
||||
}
|
||||
else {
|
||||
//run the binary file
|
||||
Toy_runBinaryFile(Toy_commandLine.binaryfile);
|
||||
}
|
||||
|
||||
//lib cleanup
|
||||
Toy_freeDriveSystem();
|
||||
|
||||
@@ -149,3 +149,59 @@ void Toy_runSourceFile(const char* fname) {
|
||||
Toy_runSource(source);
|
||||
free((void*)source);
|
||||
}
|
||||
|
||||
//utils for debugging the header
|
||||
static unsigned char readByte(const unsigned char* tb, int* count) {
|
||||
unsigned char ret = *(unsigned char*)(tb + *count);
|
||||
*count += 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char* readString(const unsigned char* tb, int* count) {
|
||||
const unsigned char* ret = tb + *count;
|
||||
*count += strlen((char*)ret) + 1; //+1 for null character
|
||||
return (const char*)ret;
|
||||
}
|
||||
|
||||
void Toy_parseBinaryFileHeader(const char* fname) {
|
||||
size_t size = 0; //not used
|
||||
const unsigned char* tb = Toy_readFile(fname, &size);
|
||||
if (!tb || size < 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
//header section
|
||||
const unsigned char major = readByte(tb, &count);
|
||||
const unsigned char minor = readByte(tb, &count);
|
||||
const unsigned char patch = readByte(tb, &count);
|
||||
|
||||
const char* build = readString(tb, &count);
|
||||
|
||||
printf("Toy Programming Language Interpreter Version %d.%d.%d (interpreter built on %s)\n\n", TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD);
|
||||
|
||||
printf("Toy Programming Language Bytecode Version ");
|
||||
|
||||
//print the output
|
||||
if (major == TOY_VERSION_MAJOR && minor == TOY_VERSION_MINOR && patch == TOY_VERSION_PATCH) {
|
||||
printf("%d.%d.%d", major, minor, patch);
|
||||
}
|
||||
else {
|
||||
printf(TOY_CC_FONT_YELLOW TOY_CC_BACK_BLACK "%d.%d.%d" TOY_CC_RESET, major, minor, patch);
|
||||
}
|
||||
|
||||
printf(" (interpreter built on ");
|
||||
|
||||
if (strncmp(build, TOY_VERSION_BUILD, strlen(TOY_VERSION_BUILD)) == 0) {
|
||||
printf("%s", build);
|
||||
}
|
||||
else {
|
||||
printf(TOY_CC_FONT_YELLOW TOY_CC_BACK_BLACK "%s" TOY_CC_RESET, build);
|
||||
}
|
||||
|
||||
printf(")\n");
|
||||
|
||||
//cleanup
|
||||
free((void*)tb);
|
||||
}
|
||||
@@ -12,3 +12,4 @@ void Toy_runBinaryFile(const char* fname);
|
||||
void Toy_runSource(const char* source);
|
||||
void Toy_runSourceFile(const char* fname);
|
||||
|
||||
void Toy_parseBinaryFileHeader(const char* fname);
|
||||
@@ -15,6 +15,12 @@ STATIC_ASSERT(sizeof(unsigned char) == 1);
|
||||
STATIC_ASSERT(sizeof(unsigned short) == 2);
|
||||
STATIC_ASSERT(sizeof(unsigned int) == 4);
|
||||
|
||||
static const char* build = __DATE__ " " __TIME__;
|
||||
|
||||
const char* Toy_private_version_build() {
|
||||
return build;
|
||||
}
|
||||
|
||||
#ifndef TOY_DISABLE_REPL
|
||||
|
||||
//declare the singleton with default values
|
||||
@@ -29,6 +35,7 @@ Toy_CommandLine Toy_commandLine = {
|
||||
.source = NULL,
|
||||
.initialfile = NULL,
|
||||
.enablePrintNewline = true,
|
||||
.parseBytecodeHeader = false,
|
||||
.verbose = false
|
||||
};
|
||||
|
||||
@@ -89,6 +96,16 @@ void Toy_initCommandLine(int argc, const char* argv[]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "-p")) {
|
||||
Toy_commandLine.parseBytecodeHeader = true;
|
||||
|
||||
if (Toy_commandLine.binaryfile) {
|
||||
Toy_commandLine.error = false;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "-n")) {
|
||||
Toy_commandLine.enablePrintNewline = false;
|
||||
Toy_commandLine.error = false;
|
||||
@@ -124,6 +141,7 @@ void Toy_helpCommandLine(int argc, const char* argv[]) {
|
||||
printf(" -c, --compile filename\tParse and compile the specified source file into an output file.\n");
|
||||
printf(" -o, --output outfile\t\tName of the output file built with --compile (default: out.tb).\n");
|
||||
printf(" -t, --initial filename\tStart the repl as normal, after first running the given file.\n");
|
||||
printf(" -p\t\t\t\tParse the given bytecode's header, then exit (requires file.tb).\n");
|
||||
printf(" -n\t\t\t\tDisable the newline character at the end of the print statement.\n");
|
||||
}
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
|
||||
#define TOY_VERSION_MAJOR 1
|
||||
#define TOY_VERSION_MINOR 1
|
||||
#define TOY_VERSION_PATCH 4
|
||||
#define TOY_VERSION_BUILD __DATE__ " " __TIME__
|
||||
#define TOY_VERSION_PATCH 5
|
||||
#define TOY_VERSION_BUILD Toy_private_version_build()
|
||||
|
||||
const char* Toy_private_version_build();
|
||||
|
||||
//platform/compiler-specific instructions
|
||||
#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__)
|
||||
@@ -42,6 +44,7 @@ typedef struct {
|
||||
char* source;
|
||||
char* initialfile;
|
||||
bool enablePrintNewline;
|
||||
bool parseBytecodeHeader;
|
||||
bool verbose;
|
||||
} Toy_CommandLine;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user