Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epidemian
GitHub Repository: epidemian/gravity
Path: blob/master/src/cli/gravity.c
1214 views
1
//
2
// compiler_test.c
3
// gravity
4
//
5
// Created by Marco Bambini on 24/03/16.
6
// Copyright © 2016 CreoLabs. All rights reserved.
7
//
8
9
#include "gravity_compiler.h"
10
#include "gravity_core.h"
11
#include "gravity_vm.h"
12
13
#define DEFAULT_OUTPUT "gravity.json"
14
typedef enum {
15
OP_COMPILE, // just compile source code and exit
16
OP_RUN, // just run an already compiled file
17
OP_COMPILE_RUN, // compile source code and run it
18
OP_REPL // run a read eval print loop
19
} op_type;
20
21
static const char *input_file = NULL;
22
static const char *output_file = DEFAULT_OUTPUT;
23
24
static void report_error (error_type_t error_type, const char *message, error_desc_t error_desc, void *xdata) {
25
#pragma unused(xdata)
26
const char *type = "N/A";
27
switch (error_type) {
28
case GRAVITY_ERROR_NONE: type = "NONE"; break;
29
case GRAVITY_ERROR_SYNTAX: type = "SYNTAX"; break;
30
case GRAVITY_ERROR_SEMANTIC: type = "SEMANTIC"; break;
31
case GRAVITY_ERROR_RUNTIME: type = "RUNTIME"; break;
32
case GRAVITY_WARNING: type = "WARNING"; break;
33
case GRAVITY_ERROR_IO: type = "I/O"; break;
34
}
35
36
if (error_type == GRAVITY_ERROR_RUNTIME) printf("RUNTIME ERROR: ");
37
else printf("%s ERROR on %d (%d,%d): ", type, error_desc.fileid, error_desc.lineno, error_desc.colno);
38
printf("%s\n", message);
39
}
40
41
static void print_version (void) {
42
printf("Gravity version %s (%s)\n", GRAVITY_VERSION, GRAVITY_BUILD_DATE);
43
}
44
45
static void print_help (void) {
46
printf("usage: gravity [options]\n");
47
printf("no options means enter interactive mode (not yet supported)\n");
48
printf("Available options are:\n");
49
printf("--version show version information and exit\n");
50
printf("--help show command line usage and exit\n");
51
printf("-c input_file compile input_file (default to gravity.json)\n");
52
printf("-o output_file specify output file name\n");
53
printf("-x input_file execute input_file (JSON format expected)\n");
54
printf("file_name compile file_name and executes it\n");
55
}
56
57
static void gravity_repl (void) {
58
printf("REPL not yet implemented.\n");
59
}
60
61
static op_type parse_args (int argc, const char* argv[]) {
62
if (argc == 1) return OP_REPL;
63
64
if (argc == 2 && strcmp(argv[1], "--version") == 0) {
65
print_version();
66
exit(0);
67
}
68
69
if (argc == 2 && strcmp(argv[1], "--help") == 0) {
70
print_help();
71
exit(0);
72
}
73
74
op_type type = OP_RUN;
75
for (int i=1; i<argc; ++i) {
76
if ((strcmp(argv[i], "-c") == 0) && (i+1 < argc)) {
77
input_file = argv[++i];
78
type = OP_COMPILE;
79
}
80
else if ((strcmp(argv[i], "-o") == 0) && (i+1 < argc)) {
81
output_file = argv[++i];
82
}
83
else if ((strcmp(argv[i], "-x") == 0) && (i+1 < argc)) {
84
input_file = argv[++i];
85
type = OP_RUN;
86
}
87
}
88
89
if (input_file == NULL) {
90
input_file = argv[1];
91
return OP_COMPILE_RUN;
92
}
93
return type;
94
}
95
96
// MARK: -
97
98
int main (int argc, const char* argv[]) {
99
// parse arguments and return operation type
100
op_type type = parse_args(argc, argv);
101
102
// special repl case
103
if (type == OP_REPL) {
104
gravity_repl();
105
exit(0);
106
}
107
108
// initialize memory debugger (if activated)
109
mem_init();
110
111
// closure to execute/serialize
112
gravity_closure_t *closure = NULL;
113
114
// optional compiler
115
gravity_compiler_t *compiler = NULL;
116
117
// setup compiler/VM delegate
118
gravity_delegate_t delegate = {.error_callback = report_error};
119
120
// create VM
121
gravity_vm *vm = gravity_vm_new(&delegate);
122
123
// check if input file is source code that needs to be compiled
124
if ((type == OP_COMPILE) || (type == OP_COMPILE_RUN)) {
125
size_t size = 0;
126
127
// load source code
128
const char *source_code = file_read(input_file, &size);
129
if (!source_code) {
130
printf("Error loading file %s", input_file);
131
goto cleanup;
132
}
133
134
// create compiler
135
compiler = gravity_compiler_create(&delegate);
136
137
// compile source code into a closure
138
closure = gravity_compiler_run(compiler, source_code, size, 0, false);
139
140
// check if closure needs to be serialized
141
if (type == OP_COMPILE) {
142
bool result = gravity_compiler_serialize_infile(compiler, closure, output_file);
143
if (!result) printf("Error serializing file %s\n", output_file);
144
goto cleanup;
145
}
146
147
// op is OP_COMPILE_RUN so transfer memory from compiler to VM
148
gravity_compiler_transfer(compiler, vm);
149
150
} else if (type == OP_RUN) {
151
// unserialize file
152
closure = gravity_vm_loadfile(vm, input_file);
153
if (!closure) {
154
printf("Error while loading compile file %s\n", input_file);
155
goto cleanup;
156
}
157
}
158
159
// sanity check
160
assert(closure);
161
162
if (gravity_vm_run(vm, closure)) {
163
gravity_value_t result = gravity_vm_result(vm);
164
double t = gravity_vm_time(vm);
165
166
char buffer[512];
167
gravity_value_dump(result, buffer, sizeof(buffer));
168
printf("RESULT: %s (in %.4f ms)\n\n", buffer, t);
169
}
170
171
cleanup:
172
if (compiler) gravity_compiler_free(compiler);
173
if (vm) gravity_vm_free(vm);
174
gravity_core_free();
175
176
#if GRAVITY_MEMORY_DEBUG
177
size_t current_memory = mem_leaks();
178
if (current_memory != 0) {
179
printf("--> VM leaks: %zu bytes\n", current_memory);
180
mem_stat();
181
} else {
182
printf("\tNo VM leaks found!\n");
183
}
184
#endif
185
186
return 0;
187
}
188
189