Files
Toy/repl/main.c
Kayne Ruse 72cad02501 Squashed: Set up a pipeline for repl script testing
It's not ready yet, but considering how much crap this took to get
working... I'm done for the night.

commit 0f3ee91a0628654a61d47a0c41cd3e39c801b8f9
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 20:27:44 2024 +1000

    I have a titanic patience... but even the titanic sank

commit d606e0948b78bc0614c81bbea48abf5ffd9f2194
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 20:03:57 2024 +1000

    Terminated

commit 7b3b59321d349a8e361857ee3dbe955ec27cb38c
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 20:00:11 2024 +1000

    What the hell?

commit 36104b7b5a5d5487c84ab98fec1ae69487fd1a90
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 19:55:28 2024 +1000

    PLEASE

commit 0de373d10ad56cba228e9473509a527bf7a3208d
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 19:31:28 2024 +1000

    Remember to commit the file!

commit 1cb5780e2dc281ecc723b4042cd9ee1f9a3115ab
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 19:24:32 2024 +1000

    Please be correct

commit 2235d716c1d872db3744905fbd2305e65f96361a
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:58:00 2024 +1000

    Nearly there

commit eabe49130cfdbe93cc3a2056819e267f97304cf1
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:51:04 2024 +1000

    Oh green world, don't desert me now

commit f0127e2d4947ce47284f2ec72f41a5b6a62121b8
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:42:50 2024 +1000

    I'm on a highway to hell...

commit f96c0f51a48b080d11d15947940d678ae4f88024
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:41:01 2024 +1000

    OK, so there's a lot of security there.

commit af3645893a744b7cfa2638bf607373565b8e6ef9
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:33:51 2024 +1000

    I'm going to steal the declaration of independence

commit e71e1c1b4243e89a580d8b04b4d236ea66ded78c
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:27:11 2024 +1000

    Show me the money!

commit f29ba6eb96c31e9bbcf23b6ece137381f5be4050
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:12:23 2024 +1000

    Say hello to my little friend!

commit 3a5ee93884b1169abae48923161d7b47b8a45cdd
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:06:59 2024 +1000

    You had me at hello

commit 2901d92f24082173e7119a37baa12a6e968796c8
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 18:02:49 2024 +1000

    You and your little dog too!

commit 967194e0593233e17ea7737647dc8042ee3bf0aa
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:52:13 2024 +1000

    I'll get you my pretty!

commit ad48a7aec8ba7ab9e11d23104cd171169cc5ff45
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:50:14 2024 +1000

    Do you feel lucky, punk?

commit 13fa5c1e96fc7c64f71009f705b8bd69b8dfabf2
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:48:04 2024 +1000

    Frankly my dear, I don't give a damn

commit 2f15a5a7a71c22bd3f34f619887137c7cd09001b
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:20:06 2024 +1000

    One of us, one of us, one of us!

commit e696d15ea62cb5d965638e04e6f0458b19cf9e28
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:16:04 2024 +1000

    Why did it have to be snakes?

commit 90631eda6263c30b0643007fc2c7a84e5e08826d
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:07:11 2024 +1000

    No, I am your father!

commit 22e1d61caac3d37ce7fe9fc41bc3b60949fe5a81
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 17:00:18 2024 +1000

    I'm sorry Dave, I can't let you do that

commit 9aa17b8b04eb65c6c9bf8b015458f749db97494d
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:57:24 2024 +1000

    LIVE, DARN YOU, LIVE!

commit 1b7f0704d9a2744f10377384ff5f36ea7f61c2da
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:52:58 2024 +1000

    That's a whole lotta nothing

commit fd4001a9eb557afb3d6cbe409c72f7416b08db60
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:44:34 2024 +1000

    Here goes nothing

commit 7ba09ef0acda2fede952a912a8a1849e9b6c59b7
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:40:28 2024 +1000

    Oh, this is gonna be fun, trying to build on a machine I don't even have

commit 1155054552ef46ceb4c21117e35f8e5e46b26dbe
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:34:06 2024 +1000

    There is no repl-gdb in Ba Sing Se

commit 5361a31da1d9278972dcbe3c8a0ad59ea6e2ab41
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:31:05 2024 +1000

    Changed -R to -rpath

commit de982ce2846dd6ffe316648e32a8a04b9d7f242d
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:27:14 2024 +1000

    Fixed printf() string literal

commit 5ddec42af5b46a0c25f64b088a4992433e5a4116
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:24:05 2024 +1000

    Workflow experiment

commit 28570940b8758fc7f05c957055580e4286a887af
Author: Kayne Ruse <kayneruse@gmail.com>
Date:   Sat Sep 28 16:10:19 2024 +1000

    Fixed workflow for macos
2024-09-28 20:38:44 +10:00

260 lines
6.3 KiB
C

#include "toy.h"
#include <stdio.h>
#include <string.h>
//utilities
unsigned char* readFile(char* path, int* size) {
//open the file
FILE* file = fopen(path, "rb");
if (file == NULL) {
*size = -1; //missing file error
return NULL;
}
//determine the file's length
fseek(file, 0L, SEEK_END);
*size = ftell(file);
rewind(file);
//make some space
unsigned char* buffer = TOY_ALLOCATE(unsigned char, *size + 1);
if (buffer == NULL) {
fclose(file);
return NULL;
}
//
if (fread(buffer, sizeof(unsigned char), *size, file) < *size) {
fclose(file);
*size = -2; //singal a read error
return NULL;
}
fclose(file);
buffer[(*size)++] = '\0';
return buffer;
}
int dir(char* dest, const char* src) {
//extract the directory from src, and store it in dest
#if defined(_WIN32) || defined(_WIN64)
char* p = strrchr(src, '\\');
#else
char* p = strrchr(src, '/');
#endif
int len = p != NULL ? p - src + 1 : 0;
strncpy(dest, src, len);
dest[len] = '\0';
return len;
}
#define APPEND(dest, src) \
memcpy((dest) + (strlen(dest)), (src), strlen((src)));
#if defined(_WIN32) || defined(_WIN64)
#define FLIPSLASH(str) for (int i = 0; str[i]; i++) str[i] = str[i] == '/' ? '\\' : str[i];
#else
#define FLIPSLASH(str) for (int i = 0; str[i]; i++) str[i] = str[i] == '\\' ? '/' : str[i];
#endif
//handle command line arguments
typedef struct CmdLine {
bool error;
bool help;
bool version;
char* infile;
int infileLength;
} CmdLine;
void usageCmdLine(int argc, const char* argv[]) {
printf("Usage: %s [ -h | -v | -f source.toy ]\n\n", argv[0]);
}
void helpCmdLine(int argc, const char* argv[]) {
usageCmdLine(argc, argv);
printf(" -h, --help\t\t\tShow this help then exit.\n");
printf(" -v, --version\t\t\tShow version and copyright information then exit.\n");
printf(" -f, --file infile\t\tParse, compile and execute the source file then exit.\n");
}
void versionCmdLine(int argc, const char* argv[]) {
printf("The Toy Programming Language, Version %d.%d.%d %s\n\n", TOY_VERSION_MAJOR, TOY_VERSION_MINOR, TOY_VERSION_PATCH, TOY_VERSION_BUILD);
//copy/pasted from the license file - there's a way to include it directly, but it's too finnicky to bother
const char* license = "\
Copyright (c) 2020-2024 Kayne Ruse, KR Game Studios\n\
\n\
This software is provided 'as-is', without any express or implied\n\
warranty. In no event will the authors be held liable for any damages\n\
arising from the use of this software.\n\
\n\
Permission is granted to anyone to use this software for any purpose,\n\
including commercial applications, and to alter it and redistribute it\n\
freely, subject to the following restrictions:\n\
\n\
1. The origin of this software must not be misrepresented; you must not\n\
claim that you wrote the original software. If you use this software\n\
in a product, an acknowledgment in the product documentation would be\n\
appreciated but is not required.\n\
2. Altered source versions must be plainly marked as such, and must not be\n\
misrepresented as being the original software.\n\
3. This notice may not be removed or altered from any source distribution.\n\n";
printf("%s",license);
}
CmdLine parseCmdLine(int argc, const char* argv[]) {
CmdLine cmd = { .error = false, .help = false, .version = false, .infile = NULL, .infileLength = 0 };
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
cmd.help = true;
}
else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
cmd.version = true;
}
else if (!strcmp(argv[i], "-f") || !strcmp(argv[i], "--file")) {
if (argc < i + 1) {
cmd.error = true;
}
else {
if (cmd.infile != NULL) { //don't leak
TOY_FREE_ARRAY(char, cmd.infile, strlen(cmd.infile));
}
i++;
//total space to reserve - it's actually longer than needed, due to the exe name being removed
cmd.infileLength = strlen(argv[0]) + strlen(argv[i]);
cmd.infile = TOY_ALLOCATE(char, cmd.infileLength);
dir(cmd.infile, argv[0]);
APPEND(cmd.infile, argv[i]);
FLIPSLASH(cmd.infile);
}
}
else {
cmd.error = true;
}
}
return cmd;
}
//main file
int main(int argc, const char* argv[]) {
CmdLine cmd = parseCmdLine(argc, argv);
if (cmd.error) {
usageCmdLine(argc, argv);
}
else if (cmd.help) {
helpCmdLine(argc, argv);
}
else if (cmd.version) {
versionCmdLine(argc, argv);
}
else if (cmd.infile != NULL) {
//run the given file
int size;
unsigned char* source = readFile(cmd.infile, &size);
TOY_FREE_ARRAY(char, cmd.infile, cmd.infileLength); //clean this up, since it's no longer needed
cmd.infile = NULL;
cmd.infileLength = 0;
//check the file
if (source == NULL) {
if (size == 0) {
fprintf(stderr, TOY_CC_ERROR "ERROR: Could not parse an empty file, exiting\n" TOY_CC_RESET);
return -1;
}
else if (size == -1) {
fprintf(stderr, TOY_CC_ERROR "ERROR: File not found, exiting\n" TOY_CC_RESET);
return -1;
}
else {
fprintf(stderr, TOY_CC_ERROR "ERROR: Unknown error while reading file, exiting\n" TOY_CC_RESET);
return -1;
}
}
Toy_Lexer lexer;
Toy_bindLexer(&lexer, (char*)source);
Toy_Parser parser;
Toy_bindParser(&parser, &lexer);
Toy_Bucket* bucket = NULL;
TOY_BUCKET_INIT(Toy_Ast, bucket, 32);
Toy_Ast* ast = Toy_scanParser(&bucket, &parser);
Toy_Bytecode bc = Toy_compileBytecode(ast);
//run the setup
Toy_VM vm;
Toy_initVM(&vm);
Toy_bindVM(&vm, bc.ptr, bc.capacity);
//run
Toy_runVM(&vm);
//debugging result
printf("printing the stack result\n\ntype\tvalue\n");
for (int i = 0; i < vm.stack.count; i++) {
Toy_Value v = vm.stack.ptr[i];
printf(" %d\t ", v.type);
switch(v.type) {
case TOY_VALUE_NULL:
printf("null");
break;
case TOY_VALUE_BOOLEAN:
printf("%s", TOY_VALUE_AS_BOOLEAN(v) ? "true" : "false");
break;
case TOY_VALUE_INTEGER:
printf("%d", TOY_VALUE_AS_INTEGER(v));
break;
case TOY_VALUE_FLOAT:
printf("%f", TOY_VALUE_AS_FLOAT(v));
break;
case TOY_VALUE_STRING:
case TOY_VALUE_ARRAY:
case TOY_VALUE_DICTIONARY:
case TOY_VALUE_FUNCTION:
case TOY_VALUE_OPAQUE:
printf("???");
break;
}
printf("\n");
}
//cleanup
Toy_freeVM(&vm);
TOY_BUCKET_FREE(bucket);
TOY_FREE_ARRAY(unsigned char, source, size);
}
else {
usageCmdLine(argc, argv);
}
return 0;
}
//TODO: simple and consistent way to print an AST and Toy_Value