Files
fz-lang/src/vm/main.c
T

146 lines
3.1 KiB
C

#include <common/fzl_colors.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vm/fzl_vm.h>
typedef struct
{
char *filepath;
bool help;
bool debug;
bool allow_infinite;
uint64_t max_iter;
} run_args_t;
void print_hint()
{
printf("Usage: fz [flags] <file path>\n");
printf("Flags:\n");
printf("\t-h\t--help\t\t\tprint usage information\n");
printf("\t-d\t--debug\t\t\tdisplay program opcodes\n");
printf("\t\t--allow-infinite\tallow infinite loops\n");
printf("\t\t--max-iter N\t\trestrict loops to maximum N iterations\n");
}
// Parse passed arguments and build args setup structure
run_args_t *parse_args(int argc, char **argv)
{
if (argc < 2)
{
print_hint();
return NULL;
}
run_args_t *args = malloc(sizeof(run_args_t));
args->filepath = NULL;
args->help = false;
args->debug = false;
args->allow_infinite = false;
args->max_iter = 100000;
for (int i = 0; i < argc; i++)
{
if (argv[i][0] != '-')
continue;
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
{
args->help = true;
return args;
}
else if (strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--debug") == 0)
args->debug = true;
else if (strcmp(argv[i], "--allow-infinite") == 0)
args->allow_infinite = true;
else if (strcmp(argv[i], "--max-iter") == 0)
{
char *n = argv[++i];
if (!n || argc <= i || !(n[0] >= '0' && n[0] <= '9'))
{
printf("%sError%s: --max-iter options requires number after it\n",
FZL_CERROR, FZL_CRST);
free(args);
return NULL;
}
uint64_t iters = strtol(n, NULL, 10);
if (iters < 1)
{
printf("%sError%s: '--max-iter 0' is not allowed\n", FZL_CERROR,
FZL_CRST);
free(args);
return NULL;
}
args->max_iter = iters;
}
else
{
printf("%sError%s: unknown flag '%s'.\n", FZL_CERROR, FZL_CRST, argv[i]);
printf("Use 'fz --help' to read the usage\n");
free(args);
return NULL;
}
}
if (argv[argc - 1][0] == '-')
{
printf("%sError%s: last argument MUST be a file path\n", FZL_CERROR,
FZL_CRST);
printf("Use 'fz --help' for help\n");
free(args);
return NULL;
}
args->filepath = argv[argc - 1];
return args;
}
int main(int argc, char **argv)
{
run_args_t *args = parse_args(argc, argv);
if (!args)
return -1;
else if (args->help)
{
print_hint();
free(args);
return 0;
}
fzl_vm_t *vm = fzl_mkvm(args->filepath);
if (!vm)
{
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, fzl_vm_geterror());
free(args);
return -1;
}
if (args->debug)
fzl_vm_print_ops(vm);
else
{
int result = fzl_vm_run(vm, args->allow_infinite, args->max_iter);
if (result != 0)
{
char *err = fzl_vm_geterror();
if (err && err[0])
printf("%sError%s: %s\n", FZL_CERROR, FZL_CRST, err);
free(args);
fzl_freevm(vm);
return -1;
}
}
free(args);
fzl_freevm(vm);
return 0;
}