Skip to content

Commit 3c6cbac

Browse files
committed
optionals using '?' and optional coelescing like '?.', '?[...]', etc
1 parent 7e2910f commit 3c6cbac

File tree

11 files changed

+199
-19
lines changed

11 files changed

+199
-19
lines changed

lib/string.qk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ struct str {
77
usize len(self) {
88
return self.slice.size;
99
}
10+
11+
char* data(self) {
12+
return self.slice.data;
13+
}
1014
}
1115

1216
struct String {

src/compiler/left.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ void comp_Identifier(Identifier* self, str* line, Compiler* compiler) {
6565
if(self->declaration && self->declaration->generics.base.size
6666
&& self->declaration->generics.stack.size
6767
&& !(self->flags & fExternal)) {
68-
append_generics_identifier(line, last(self->declaration->generics.stack));
68+
append_generics_identifier(line, last(self->declaration->generics.stack),
69+
StringifyAlphaNum);
6970
}
7071
}
7172

@@ -93,6 +94,8 @@ void comp_Scope(Scope* self, str* line, Compiler* compiler) {
9394
str bracket = new_line(compiler);
9495
push(&compiler->sections.data[compiler->open_section].lines, strf(&bracket, "}"));
9596
}
97+
98+
if(self->value) self->value->compiler(self->value, line, compiler);
9699
}
97100

98101
void comp_Missing(Missing* self, str* line, Compiler* compiler) {

src/compiler/right.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ void comp_FunctionType(FunctionType* self, str* line, Compiler* compiler) {
144144

145145
strf(line, "__Function%zd", self->typedef_id);
146146
if(self->declaration->generics.stack.size) {
147-
append_generics_identifier(line, last(self->declaration->generics.stack));
147+
append_generics_identifier(line, last(self->declaration->generics.stack),
148+
StringifyAlphaNum);
148149
}
149150
}
150151

src/parser/generics.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,25 @@ void apply_generics(Declaration* declaration, GenericsCollection collection) {
144144
init_scope(&declaration->generics.unique_map);
145145
}
146146

147-
void append_generics_identifier(str* string, TypeList generics) {
147+
void append_generics_identifier(str* string, TypeList generics, unsigned flags) {
148148
if(!generics.size) return;
149149

150+
if(!(flags & 1 << 0 /* StringifyAlphaNum */)) {
151+
strf(string, "<");
152+
}
153+
150154
for(size_t i = 0; i < generics.size; i++) {
151-
strf(string, "__");
152-
stringify_type(generics.data[i], string, 1 << 0 /* StringifyAlphaNum */);
155+
if(flags & 1 << 0 /* StringifyAlphaNum */) {
156+
strf(string, "__");
157+
} else if(i) {
158+
strf(string, ", ");
159+
}
160+
161+
stringify_type(generics.data[i], string, flags);
162+
}
163+
164+
if(!(flags & 1 << 0 /* StringifyAlphaNum */)) {
165+
strf(string, ">");
153166
}
154167
}
155168

@@ -160,7 +173,8 @@ strs filter_unique_generics_variants(TypeLists variants, str base) {
160173

161174
for(size_t i = 0; i < variants.size; i++) {
162175
str identifier = strf(0, "%.*s", (int) base.size, base.data);
163-
append_generics_identifier(&identifier, variants.data[i]);
176+
append_generics_identifier(&identifier, variants.data[i],
177+
1 << 0 /* StringifyAlphaNum */);
164178

165179
if(get(variants_set, (Trace) { .slice = identifier })) {
166180
variants.data[i].size = 0;

src/parser/nodes.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ typedef struct {
3333
DeclarationList declarations;
3434
NodeList children;
3535
Declaration* parent;
36+
Node* value;
3637
unsigned wrap_brackets : 1;
3738
} Scope;
3839
typedef Vector(Scope*) Stack;

src/parser/right.c

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ enum {
1515
RightFieldAccess,
1616
RightCompare,
1717
RightIndex,
18+
RightOptional,
1819
};
1920

2021
typedef struct {
@@ -28,6 +29,7 @@ RightOperator right_operator_table[128] = {
2829
[TokenDoublePlus] = { 1, RightIncDec }, [TokenDoubleMinus] = { 1, RightIncDec },
2930
['['] = { 1, RightIndex }, ['('] = { 1, RightCall },
3031
['.'] = { 1, RightFieldAccess }, [TokenRightArrow] = { 1, RightFieldAccess },
32+
['?'] = { 1, RightOptional },
3133

3234
['*'] = { 3, RightAltBinary }, ['/'] = { 3 }, ['%'] = { 3 },
3335

@@ -171,6 +173,18 @@ Message see_declaration(Declaration* declaration, Node* node) {
171173
(int) node->trace.slice.size, node->trace.slice.data));
172174
}
173175

176+
Node* temp_value(Node* value, Parser* parser, unsigned* set_id) {
177+
static unsigned id = 0;
178+
if(set_id) *set_id = id;
179+
const str declaration_code = strf(0, "auto __qv%u = extern<auto> \"\";%c", id++, '\0');
180+
Node* declaration = eval_w(parser->tokenizer->current.trace.filename,
181+
declaration_code.data, parser, &statement);
182+
declaration->Statement.expression->BinaryOperation.right = value;
183+
clash_types(declaration->Statement.expression->BinaryOperation.left->type,
184+
value->type, value->trace, parser->tokenizer->messages, 0);
185+
return declaration;
186+
}
187+
174188
Node* right(Node* lefthand, Parser* parser, unsigned char precedence) {
175189
RightOperator operator;
176190
outer_while:
@@ -179,6 +193,78 @@ Node* right(Node* lefthand, Parser* parser, unsigned char precedence) {
179193
if(operator.precedence == 6 && collecting_type_arguments) break;
180194

181195
switch(operator.type) {
196+
case RightOptional: {
197+
Trace trace_end = next(parser->tokenizer).trace;
198+
199+
if((operator = right_operator_table[parser->tokenizer->current.type])
200+
.precedence <= 1) {
201+
unsigned temp_id;
202+
Node* temp = temp_value(lefthand, parser, &temp_id);
203+
204+
const str left_value_code = strf(0, "__qv%u.value%c", temp_id, '\0');
205+
Node* some_branch = right(eval(NULL, left_value_code.data, parser),
206+
parser, 2);
207+
208+
Scope* collection = new_scope(NULL);
209+
collection->trace = lefthand->trace;
210+
collection->wrap_brackets = 1;
211+
push(&collection->children, temp);
212+
213+
const OpenedType open = open_type(some_branch->type, 0);
214+
if(open.type->compiler == (void*) comp_External &&
215+
streq(open.type->External.data, str("void"))) {
216+
Node* if_statement = eval_w(NULL, strf(0,
217+
"if(__qv%u.some) extern<auto> _;%c", temp_id, '\0').data,
218+
parser, &statement);
219+
if_statement->Control.body->children.data[0]->Statement.expression
220+
= some_branch;
221+
push(&collection->children, if_statement);
222+
close_type(open.actions, 0);
223+
return (void*) collection;
224+
}
225+
close_type(open.actions, 0);
226+
227+
unsigned value_id;
228+
Node* value = temp_value(eval(NULL, "Option::None()", parser),
229+
parser, &value_id);
230+
231+
const str if_statement_code = strf(0,
232+
"if(__qv%u.some) __qv%u = Option::Some(extern<auto> _);%c",
233+
temp_id, value_id, '\0');
234+
Node* if_statement = eval_w(NULL, if_statement_code.data, parser,
235+
&statement);
236+
printf("%p %p\n",
237+
if_statement->Control.body->children.data[0]->compiler,
238+
comp_Statement);
239+
// exit(1);
240+
clash_types(if_statement->Control.body->children.data[0]->Statement
241+
.expression->BinaryOperation.right->FunctionCall.arguments
242+
.data[0]->type, some_branch->type, some_branch->trace,
243+
parser->tokenizer->messages, 0);
244+
if_statement->Control.body->children.data[0]->Statement.expression
245+
->BinaryOperation.right->FunctionCall.arguments.data[0] = some_branch;
246+
247+
push(&collection->children, value);
248+
push(&collection->children, if_statement);
249+
collection->value = eval(NULL, strf(0, "__qv%u%c", value_id, 0).data,
250+
parser);
251+
collection->type = collection->value->type;
252+
253+
lefthand = (void*) collection;
254+
break;
255+
}
256+
257+
if(lefthand->flags & fType) {
258+
Wrapper* option = (void*) eval("option", "Option", parser);
259+
clash_types(option->action.TypeList.data[0], (void*) lefthand,
260+
stretch(lefthand->trace, trace_end),
261+
parser->tokenizer->messages, 0);
262+
lefthand = (void*) option;
263+
break;
264+
}
265+
break;
266+
}
267+
182268
case RightIncDec: {
183269
if(!(lefthand->flags & fMutable) || lefthand->type->flags & fConst) {
184270
push(parser->tokenizer->messages, Err( lefthand->trace,
@@ -187,13 +273,14 @@ Node* right(Node* lefthand, Parser* parser, unsigned char precedence) {
187273

188274
Trace operator = next(parser->tokenizer).trace;
189275

190-
return new_node((Node) { .Postfix = {
276+
lefthand = new_node((Node) { .Postfix = {
191277
.compiler = (void*) &comp_Postfix,
192278
.trace = operator,
193279
.type = lefthand->type,
194280
.child = lefthand,
195281
.postfix = operator.slice,
196282
}});
283+
break;
197284
}
198285

199286
case RightAltBinary: {
@@ -330,7 +417,7 @@ Node* right(Node* lefthand, Parser* parser, unsigned char precedence) {
330417
}});
331418
}
332419

333-
case RightFieldAccess: {
420+
case RightFieldAccess: field_access: {
334421
Type* type = lefthand->type;
335422
if(parser->tokenizer->current.type == TokenRightArrow) {
336423
type = (void*) dereference((void*) type, lefthand->trace,

src/parser/types.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ int type_state_action(TypeStateAction action, unsigned flags) {
3939
if(in_compiler_step && noloop && !(flags & ActionNoChildCompilation)) {
4040
noloop = 0;
4141
str unique_key = { 0 };
42-
append_generics_identifier(&unique_key, action.TypeList);
42+
append_generics_identifier(&unique_key, action.TypeList,
43+
1 << 0 /* StringifyAlphaNum */);
4344
noloop = 1;
4445

4546
if(!get(action.target->Declaration.generics.unique_map,
@@ -286,6 +287,10 @@ int stringify_acceptor(Type* type, Type* _, StringifyAccumulator* accumulator) {
286287
? "struct_%.*s" : "struct %.*s",
287288
(int) type->StructType.parent->identifier->base.size,
288289
type->StructType.parent->identifier->base.data);
290+
if(type->StructType.parent->generics.stack.size) {
291+
append_generics_identifier(accumulator->string,
292+
last(type->StructType.parent->generics.stack), accumulator->flags);
293+
}
289294
return 1;
290295
} else {
291296
strf(accumulator->string, accumulator->flags & StringifyAlphaNum

src/trace.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,14 @@ int streq(str a, str b) {
4040

4141
Trace stretch(Trace a, Trace b) {
4242
a.slice.size = b.slice.data - a.slice.data + b.slice.size;
43+
if(a.slice.size >= 256) a.slice.size = 16;
4344
return a;
4445
}
4546

46-
#define Err(trace, content) \
47-
((Message) { trace, "\33[31m", "error", content })
48-
#define Hint(content) \
49-
((Message) { { 0 }, "\33[36m", "hint", content })
50-
#define See(trace, content) \
51-
((Message) { trace, "\33[36m", "see", content })
52-
#define Warn(trace, content) \
53-
((Message) { trace, "\33[33m", "warning", content })
47+
#define Err(trace, content) ((Message) { trace, "\33[31m", "error", content })
48+
#define Hint(content) ((Message) { { 0 }, "\33[36m", "hint", content })
49+
#define See(trace, content) ((Message) { trace, "\33[36m", "see", content })
50+
#define Warn(trace, content) ((Message) { trace, "\33[33m", "warning", content })
5451

5552
int print_message(Message message) {
5653
if(!message.trace.filename) {

test/main

576 Bytes
Binary file not shown.

test/main.c

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ struct Slice__char { char* data; size_t size; };
88
struct str { struct Slice__char slice; };
99
struct Vec__char { char* data; size_t size; size_t capacity; };
1010
struct String { struct Vec__char vector; };
11+
struct Option__ptrto_uint32_t { uint32_t* value; bool some; };
12+
struct Option__uint32_t { uint32_t value; bool some; };
1113

1214
int main();
1315
struct Range Range__new(size_t, size_t);
1416
size_t Range__len(struct Range);
1517
size_t str__len(struct str);
18+
char* str__data(struct str);
1619
struct String str__to_owned(struct str);
1720
struct Vec__char Vec__char__new();
1821
size_t Vec__char__len(struct Vec__char);
@@ -25,10 +28,29 @@ struct String String__new();
2528
struct String String__from(struct str);
2629
struct str String__to_str(struct String);
2730
void print(struct str);
31+
struct Option__ptrto_uint32_t Option__ptrto_uint32_t__Some(uint32_t*);
32+
struct Option__ptrto_uint32_t Option__ptrto_uint32_t__None();
33+
bool Option__ptrto_uint32_t__is_some(struct Option__ptrto_uint32_t);
34+
bool Option__ptrto_uint32_t__is_none(struct Option__ptrto_uint32_t);
35+
struct Option__uint32_t Option__uint32_t__Some(uint32_t);
36+
struct Option__uint32_t Option__uint32_t__None();
37+
bool Option__uint32_t__is_some(struct Option__uint32_t);
38+
bool Option__uint32_t__is_none(struct Option__uint32_t);
2839

2940

3041
int main() {
31-
print((struct str) { "Hello World", (sizeof("Hello World") - 1) });
42+
struct Option__ptrto_uint32_t x;
43+
struct Option__uint32_t y;
44+
struct Option__ptrto_uint32_t __qv0;
45+
struct Option__uint32_t __qv1;
46+
(x = Option__ptrto_uint32_t__None());
47+
{
48+
(__qv0 = x);
49+
(__qv1 = Option__uint32_t__None());
50+
if((__qv0 . some))
51+
(__qv1 = Option__uint32_t__Some((*((__qv0 . value) + 0))));
52+
}
53+
(y = __qv1);
3254
}
3355

3456

@@ -47,6 +69,11 @@ size_t str__len(struct str self) {
4769
}
4870

4971

72+
char* str__data(struct str self) {
73+
return ((self . slice) . data);
74+
}
75+
76+
5077
struct String str__to_owned(struct str self) {
5178
struct String string;
5279
(string = String__new());
@@ -132,3 +159,43 @@ void print(struct str message) {
132159
fwrite(((message . slice) . data), ((message . slice) . size), sizeof(char), stdout);
133160
fwrite((&newline), 1, sizeof(char), stdout);
134161
}
162+
163+
164+
struct Option__ptrto_uint32_t Option__ptrto_uint32_t__Some(uint32_t* value) {
165+
return (struct Option__ptrto_uint32_t) { value, (bool) 1 };
166+
}
167+
168+
169+
struct Option__ptrto_uint32_t Option__ptrto_uint32_t__None() {
170+
return (struct Option__ptrto_uint32_t) { .some = (bool) 0 };
171+
}
172+
173+
174+
bool Option__ptrto_uint32_t__is_some(struct Option__ptrto_uint32_t self) {
175+
return (self . some);
176+
}
177+
178+
179+
bool Option__ptrto_uint32_t__is_none(struct Option__ptrto_uint32_t self) {
180+
return (1 - (self . some));
181+
}
182+
183+
184+
struct Option__uint32_t Option__uint32_t__Some(uint32_t value) {
185+
return (struct Option__uint32_t) { value, (bool) 1 };
186+
}
187+
188+
189+
struct Option__uint32_t Option__uint32_t__None() {
190+
return (struct Option__uint32_t) { .some = (bool) 0 };
191+
}
192+
193+
194+
bool Option__uint32_t__is_some(struct Option__uint32_t self) {
195+
return (self . some);
196+
}
197+
198+
199+
bool Option__uint32_t__is_none(struct Option__uint32_t self) {
200+
return (1 - (self . some));
201+
}

0 commit comments

Comments
 (0)