Gwion coverage report


Directory: src/
File: src/compile.c
Date: 2023-01-30 18:32:28
Exec Total Coverage
Lines: 94 120 78.3%
Functions: 14 18 77.8%
Branches: 52 68 76.5%

Line Branch Exec Source
1 #include "gwion_util.h"
2 #include "gwion_ast.h"
3 #include "gwion_env.h"
4 #include "vm.h"
5 #include "instr.h"
6 #include "emit.h"
7 #include "compile.h"
8 #include "gwion.h"
9 #include "pass.h"
10 #include "shreduler_private.h"
11
12 enum compile_type { COMPILE_NAME, COMPILE_MSTR, COMPILE_FILE };
13
14 struct Compiler {
15 const m_str base;
16 m_str name;
17 union {
18 m_str data;
19 FILE * file;
20 };
21 Ast ast;
22 struct Vector_ args;
23 VM_Shred shred;
24 MP_Vector *values;
25 enum compile_type type;
26 };
27
28 1348 ANN static void compiler_name(struct Compiler *c) {
29 1348 m_str d = strdup(c->base);
30 1348 c->name = strsep(&d, ":");
31
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1346 times.
1348 if (d) vector_init(&c->args);
32
2/2
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1348 times.
1350 while (d) vector_add(&c->args, (vtype)strdup(strsep(&d, ":")));
33 1348 xfree(d);
34 1348 }
35
36 668 ANN static inline void compiler_error(struct Compiler *const c) {
37
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 666 times.
668 if (c->args.ptr) {
38 2 const Vector v = &c->args;
39
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 for (m_uint i = 0; i < vector_size(v); ++i) {
40 2 const m_str str = (m_str)vector_at(v, i);
41
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (str) xfree((m_str)vector_at(v, i));
42 }
43 2 vector_release(v);
44 }
45 668 }
46
47 1348 ANN static void compiler_clean(const struct Compiler *c) {
48
2/2
✓ Branch 0 taken 680 times.
✓ Branch 1 taken 668 times.
1348 if (c->name) xfree(c->name);
49 /* test c->type because COMPILE_FILE does not own file */
50
4/4
✓ Branch 0 taken 1347 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 679 times.
✓ Branch 3 taken 668 times.
1348 if (c->type != COMPILE_FILE && c->file) fclose(c->file);
51 1348 }
52
53 1348 ANN static m_bool _compiler_open(struct Compiler *c) {
54
2/2
✓ Branch 0 taken 1346 times.
✓ Branch 1 taken 2 times.
1348 if (c->type == COMPILE_NAME) {
55 1346 m_str name = c->name;
56 1346 c->name = realpath(name, NULL);
57 1346 xfree(name);
58
2/2
✓ Branch 0 taken 678 times.
✓ Branch 1 taken 668 times.
1346 return c->name ? !!(c->file = fopen(c->name, "r")) : GW_ERROR;
59
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 } else if (c->type == COMPILE_MSTR) {
60
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 c->file = c->data ? fmemopen(c->data, strlen(c->data), "r") : NULL;
61
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 return c->file ? GW_OK : GW_ERROR;
62 }
63 1 return GW_OK;
64 }
65
66 #ifndef BUILD_ON_WINDOWS
67 #include <sys/stat.h>
68 1347 ANN static int is_reg(const m_str path) {
69 1347 struct stat s = {};
70 1347 stat(path, &s);
71
4/6
✓ Branch 0 taken 1347 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 668 times.
✓ Branch 3 taken 679 times.
✓ Branch 4 taken 668 times.
✗ Branch 5 not taken.
1347 return !S_ISDIR(s.st_mode) && (S_ISREG(s.st_mode) || !S_ISFIFO(s.st_mode));
72 }
73
74 #else
75 ANN static m_bool is_reg(const m_str path) {
76 const DWORD dw = GetFileAttributes(path);
77 return !(dw == INVALID_FILE_ATTRIBUTES || dw & FILE_ATTRIBUTE_DIRECTORY);
78 }
79 #endif
80
81 1348 ANN static inline m_bool compiler_open(struct Compiler *c) {
82 1348 char name[strlen(c->name) + 1];
83 1348 strcpy(name, c->name);
84 #ifndef __FUZZING__
85
5/6
✓ Branch 0 taken 1347 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1346 times.
✓ Branch 3 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1347 times.
1348 if ((c->type == COMPILE_FILE || c->type == COMPILE_NAME) && !is_reg(name)) {
86 gw_err(_("'%s': is a not a regular file\n"), name);
87 return GW_ERROR;
88 }
89 #endif
90
2/2
✓ Branch 1 taken 668 times.
✓ Branch 2 taken 680 times.
1348 if (_compiler_open(c) < 0) {
91 668 compiler_error(c);
92 668 gw_err(_("can't open '%s'\n"), name);
93 668 return GW_ERROR;
94 }
95 680 return GW_OK;
96 }
97
98 641 ANN static inline m_bool _passes(struct Gwion_ *gwion, struct Compiler *c) {
99
2/2
✓ Branch 1 taken 991 times.
✓ Branch 2 taken 345 times.
1336 for (m_uint i = 0; i < vector_size(&gwion->data->passes->vec); ++i) {
100 991 const compilation_pass pass =
101 991 (compilation_pass)vector_at(&gwion->data->passes->vec, i);
102
2/2
✓ Branch 1 taken 296 times.
✓ Branch 2 taken 695 times.
991 CHECK_BB(pass(gwion->env, &c->ast));
103 }
104 345 return GW_OK;
105 }
106
107 641 ANN static inline m_bool passes(struct Gwion_ *gwion, struct Compiler *c) {
108 641 const Env env = gwion->env;
109 641 const Context ctx = new_context(env->gwion->mp, c->ast, env->name);
110 641 env_reset(env);
111 641 load_context(ctx, env);
112
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 641 times.
641 for(uint32_t i = 0; i < mp_vector_len(c->values); i++) {
113 const Value v = *mp_vector_at(c->values, Value, i);
114 set_vflag(v, vflag_builtin);
115 if(isa(v->type, gwion->type[et_class]) > 0) {
116 const Type t = (Type)v->d.ptr;
117 type_addref(t);
118 mk_class(gwion->env, t, (loc_t) {});
119 nspc_add_type(gwion->env->curr, insert_symbol(gwion->st, v->name), t);
120 } else
121 valid_value(gwion->env, insert_symbol(gwion->st, v->name), v);
122 }
123 641 const m_bool ret = _passes(gwion, c);
124 641 ctx->tree = c->ast;
125
2/2
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 296 times.
641 if (ret > 0) //{
126 345 nspc_commit(env->curr);
127
4/4
✓ Branch 0 taken 296 times.
✓ Branch 1 taken 345 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 291 times.
641 if (ret > 0 || env->context->global)
128 350 vector_add(&env->scope->known_ctx, (vtype)ctx);
129 else { // nspc_rollback(env->global_nspc);
130 291 context_remref(ctx, env->gwion);
131 }
132 641 unload_context(ctx, env);
133 641 return ret;
134 }
135
136 static pos_t pos = { 1 , 1 };
137 void gwion_set_default_pos(const pos_t _pos) {
138 pos = _pos;
139 }
140 680 ANN static inline m_bool _check(struct Gwion_ *gwion, struct Compiler *c) {
141 680 struct AstGetter_ arg = {c->name, c->file, gwion->st, .ppa = gwion->ppa};
142
2/2
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 641 times.
680 CHECK_OB((c->ast = parse_pos(&arg, pos)));
143 641 gwion->env->name = c->name;
144 641 const m_bool ret = passes(gwion, c);
145 641 return ret;
146 }
147
148 1348 ANN static m_uint _compile(struct Gwion_ *gwion, struct Compiler *c) {
149
2/2
✓ Branch 1 taken 668 times.
✓ Branch 2 taken 680 times.
1348 if (compiler_open(c) < 0) return 0;
150
2/2
✓ Branch 1 taken 335 times.
✓ Branch 2 taken 345 times.
680 if (_check(gwion, c) < 0) return 0;
151
1/2
✓ Branch 0 taken 345 times.
✗ Branch 1 not taken.
345 if (gwion->emit->info->code) {
152 345 c->shred = new_vm_shred(gwion->mp, gwion->emit->info->code);
153 345 c->shred->info->args.ptr = c->args.ptr;
154 345 vm_add_shred(gwion->vm, c->shred);
155 345 gwion->emit->info->code = NULL;
156 345 return c->shred->tick->xid;
157 }
158 return GW_OK;
159 }
160
161 1348 ANN static m_uint compile(struct Gwion_ *gwion, struct Compiler *c) {
162 1348 compiler_name(c);
163 1348 MUTEX_LOCK(gwion->data->mutex);
164 1348 const m_uint ret = _compile(gwion, c);
165 1348 MUTEX_UNLOCK(gwion->data->mutex);
166 1348 compiler_clean(c);
167 1348 return ret;
168 }
169
170 1346 ANN m_uint compile_filename_values(struct Gwion_ *gwion, const m_str filename, MP_Vector *values) {
171 1346 struct Compiler c = {.base = filename, .type = COMPILE_NAME, .values=values};
172 1346 return compile(gwion, &c);
173 }
174
175 1 ANN m_uint compile_string_values(struct Gwion_ *gwion, const m_str filename,
176 const m_str data, MP_Vector *values) {
177 1 struct Compiler c = {.base = filename, .type = COMPILE_MSTR, .data = data, .values=values};
178 1 return compile(gwion, &c);
179 }
180
181 1 ANN m_uint compile_file_values(struct Gwion_ *gwion, const m_str filename,
182 FILE *file, MP_Vector *values) {
183 1 struct Compiler c = {.base = filename, .type = COMPILE_FILE, .file = file, .values=values};
184 1 return compile(gwion, &c);
185 }
186
187 ANN m_uint compile_filename_xid_values(struct Gwion_ *gwion, const m_str filename,
188 const m_uint xid, MP_Vector *values) {
189 struct Compiler c = {.base = filename, .type = COMPILE_NAME, .values=values};
190 if (!compile(gwion, &c)) return 0;
191 assert(c.shred);
192 return c.shred->tick->xid = xid;
193 }
194
195 ANN m_uint compile_string_xid_values(struct Gwion_ *gwion, const m_str filename,
196 const m_str data, const m_uint xid, MP_Vector *values) {
197 struct Compiler c = {.base = filename, .type = COMPILE_MSTR, .data = data, .values=values};
198 if (!compile(gwion, &c)) return 0;
199 assert(c.shred);
200 gwion->vm->shreduler->shred_ids--;
201 return c.shred->tick->xid = xid;
202 }
203
204 ANN m_uint compile_file_xid_values(struct Gwion_ *gwion, const m_str filename,
205 FILE *file, const m_uint xid, MP_Vector *values) {
206 struct Compiler c = {.base = filename, .type = COMPILE_FILE, .file = file, .values=values};
207 if (!compile(gwion, &c)) return 0;
208 assert(c.shred);
209 return c.shred->tick->xid = xid;
210 }
211