git.haldean.org ubik / e5d14f1
better error diagnostics when names are bound twice Haldean Brown 4 years ago
8 changed file(s) with 388 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 /*
1 * clash.h: make sure names don't clash
2 * Copyright (C) 2017, Haldean Brown
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "ubik/stream.h"
20 #include "ubik/ubik.h"
21
22 no_ignore ubik_error
23 ubik_clash_check(struct ubik_ast *ast, struct ubik_stream *feedback);
0 /*
1 * stringset.h: sets of strings, encoded as tries
2 * Copyright (C) 2017, Haldean Brown
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "ubik/vector.h"
20
21 struct ubik_stringset
22 {
23 struct ubik_vector children;
24 uint8_t byte;
25 };
26
27 no_ignore ubik_error
28 ubik_stringset_add(struct ubik_stringset *ss, char *str);
29
30 bool
31 ubik_stringset_present(struct ubik_stringset *ss, char *str);
32
33 void
34 ubik_stringset_free(struct ubik_stringset *ss);
33 c_sources = \
44 ./codegen/assign.c \
55 ./codegen/ast.c \
6 ./codegen/clash.c \
67 ./codegen/closure.c \
78 ./codegen/compile.c \
89 ./codegen/gen.c \
5051 ./shared/stream.c \
5152 ./shared/streamutil.c \
5253 ./shared/string.c \
54 ./shared/stringset.c \
5355 ./shared/typ.c \
5456 ./shared/uri.c \
5557 ./shared/util.c \
0 /*
1 * clash.c: make sure names don't clash
2 * Copyright (C) 2017, Haldean Brown
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "ubik/assert.h"
20 #include "ubik/feedback.h"
21 #include "ubik/stringset.h"
22 #include "ubik/ubik.h"
23 #include "ubik/walk.h"
24
25 #include <string.h>
26
27 static void
28 print_dupe(
29 struct ubik_stream *feedback,
30 struct ubik_ast *ast,
31 struct ubik_ast_binding *bind,
32 size_t i)
33 {
34 size_t j;
35 struct ubik_ast_binding *other;
36
37 other = NULL;
38 for (j = 0; j < i; j++)
39 {
40 other = ast->bindings.elems[j];
41 if (strcmp(other->name, bind->name) == 0)
42 break;
43 }
44 ubik_assert(other != NULL);
45
46 ubik_feedback_line(
47 feedback,
48 UBIK_FEEDBACK_ERR,
49 &other->loc,
50 "tried to assign to \x1b[32m%s\x1b[0m more than once",
51 bind->name);
52 ubik_feedback_line(
53 feedback,
54 UBIK_FEEDBACK_ERR,
55 &bind->loc,
56 "...previous definition was here");
57 }
58
59 struct clash_info
60 {
61 struct ubik_walk_info head;
62 struct ubik_stream *feedback;
63 };
64
65 no_ignore static ubik_error
66 visit_ast(struct ubik_walk_info *wi, struct ubik_ast *ast)
67 {
68 struct ubik_ast_binding *bind;
69 struct clash_info *ci;
70 local(stringset) struct ubik_stringset s = {0};
71 size_t i;
72 ubik_error err;
73
74 ci = (struct clash_info *) wi;
75
76 for (i = 0; i < ast->bindings.n; i++)
77 {
78 bind = ast->bindings.elems[i];
79 if (ubik_stringset_present(&s, bind->name))
80 {
81 print_dupe(ci->feedback, ast, bind, i);
82 return ubik_raise(
83 ERR_PRESENT, "name was bound twice");
84 }
85 err = ubik_stringset_add(&s, bind->name);
86 if (err != OK)
87 return err;
88 }
89 return OK;
90 }
91
92 no_ignore ubik_error
93 ubik_clash_check(struct ubik_ast *ast, struct ubik_stream *feedback)
94 {
95 struct clash_info ci = {
96 .head = {
97 .ast = visit_ast,
98 },
99 .feedback = feedback,
100 };
101 return ubik_walk_ast(ast, &ci.head);
102 }
2525 #include "ubik/adt.h"
2626 #include "ubik/assert.h"
2727 #include "ubik/assign.h"
28 #include "ubik/clash.h"
2829 #include "ubik/compile.h"
2930 #include "ubik/feedback.h"
3031 #include "ubik/gen.h"
312313 if (err != OK)
313314 return err;
314315 }
316
317 err = ubik_clash_check(job->ast, job->request->feedback);
318 if (err != OK)
319 return err;
315320
316321 err = ubik_typesystem_load(
317322 cenv->type_system, job->ast, job->request);
0 /*
1 * stringset.c: sets of strings, encoded as tries
2 * Copyright (C) 2017, Haldean Brown
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "ubik/stringset.h"
20
21 no_ignore ubik_error
22 ubik_stringset_add(struct ubik_stringset *ss, char *str)
23 {
24 struct ubik_stringset *cs;
25 size_t i;
26 char c;
27 bool found;
28 ubik_error err;
29
30 do
31 {
32 c = *str++;
33 found = false;
34 for (i = 0; i < ss->children.n; i++)
35 {
36 cs = ss->children.elems[i];
37 if (cs.byte == (uint8_t) c)
38 {
39 ss = cs;
40 found = true;
41 break;
42 }
43 }
44 if (found)
45 continue;
46 ubik_alloc1(&cs, struct ubik_stringset, NULL);
47 cs->byte = c;
48 err = ubik_vector_append(&ss->children, cs);
49 if (err != OK)
50 return err;
51 ss = cs;
52 }
53 while (c != '\0');
54 }
55
56 bool
57 ubik_stringset_present(struct ubik_stringset *ss, char *str)
58 {
59 struct ubik_stringset *cs;
60 size_t i;
61 char c;
62 bool found;
63 ubik_error err;
64
65 do
66 {
67 c = *str++;
68 found = false;
69 for (i = 0; i < ss->children.n; i++)
70 {
71 cs = ss->children.elems[i];
72 if (cs.byte == (uint8_t) c)
73 {
74 ss = cs;
75 found = true;
76 break;
77 }
78 }
79 if (found && c == '\0')
80 return true;
81 if (!found)
82 return false;
83 }
84 while (c != '\0');
85 }
86
87 void
88 ubik_stringset_free(struct ubik_stringset *ss)
89 {
90 size_t i;
91
92 for (i = 0; i < ss->children.n; i++)
93 {
94 ubik_stringset_free(ss->children.elems[i]);
95 }
96 ubik_vector_free(&ss->children);
97 }
98
0 /*
1 * stringset.c: sets of strings, encoded as tries
2 * Copyright (C) 2017, Haldean Brown
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include "ubik/stringset.h"
20
21 #include <stdlib.h>
22
23 no_ignore ubik_error
24 ubik_stringset_add(struct ubik_stringset *ss, char *str)
25 {
26 struct ubik_stringset *cs;
27 size_t i;
28 char c;
29 bool found;
30 ubik_error err;
31
32 do
33 {
34 c = *str++;
35 found = false;
36 for (i = 0; i < ss->children.n; i++)
37 {
38 cs = ss->children.elems[i];
39 if (cs->byte == (uint8_t) c)
40 {
41 ss = cs;
42 found = true;
43 break;
44 }
45 }
46 if (found)
47 continue;
48 ubik_alloc1(&cs, struct ubik_stringset, NULL);
49 cs->byte = c;
50 err = ubik_vector_append(&ss->children, cs);
51 if (err != OK)
52 return err;
53 ss = cs;
54 }
55 while (c != '\0');
56 return OK;
57 }
58
59 bool
60 ubik_stringset_present(struct ubik_stringset *ss, char *str)
61 {
62 struct ubik_stringset *cs;
63 size_t i;
64 char c;
65 bool found;
66
67 do
68 {
69 c = *str++;
70 found = false;
71 for (i = 0; i < ss->children.n; i++)
72 {
73 cs = ss->children.elems[i];
74 if (cs->byte == (uint8_t) c)
75 {
76 ss = cs;
77 found = true;
78 break;
79 }
80 }
81 if (found && c == '\0')
82 return true;
83 if (!found)
84 return false;
85 }
86 while (c != '\0');
87 return false;
88 }
89
90 void
91 ss_free(struct ubik_stringset *ss)
92 {
93 size_t i;
94
95 for (i = 0; i < ss->children.n; i++)
96 {
97 ss_free(ss->children.elems[i]);
98 }
99 ubik_vector_free(&ss->children);
100 free(ss);
101 }
102
103 void
104 ubik_stringset_free(struct ubik_stringset *ss)
105 {
106 size_t i;
107
108 for (i = 0; i < ss->children.n; i++)
109 {
110 ss_free(ss->children.elems[i]);
111 }
112 ubik_vector_free(&ss->children);
113 }
114
0 ~ ubik-tests/name-clash
1
2 ` *boolean
3
4 : true ^ Number = 10