Ajla 0.1.0
[ajla.git] / stdlib / compiler / parser / parser.ajla
blob306ad5b94f8da8d5c1fac1b5ff7ebf4e3c90c0f1
1 {*
2  * Copyright (C) 2024 Mikulas Patocka
3  *
4  * This file is part of Ajla.
5  *
6  * Ajla is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU General Public License as published by the Free Software
8  * Foundation, either version 3 of the License, or (at your option) any later
9  * version.
10  *
11  * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * Ajla. If not, see <https://www.gnu.org/licenses/>.
17  *}
19 private unit compiler.parser.parser;
21 uses compiler.parser.token;
22 uses compiler.parser.dict;
24 fn parse_lambda_function(ctx : function_context, parent_vd : variable_dictionary, t : tokens) : (function_context, list(int));
25 fn parse_file~cache(w : world, d : list(bytes), name : bytes, program : bool, parse_interface : bool) : function_dictionary;
27 implementation
29 uses exception;
30 uses pcode;
31 uses compiler.parser.gen;
32 uses compiler.parser.gen2;
33 uses compiler.parser.expression;
34 uses compiler.parser.alloc;
35 uses compiler.parser.statement;
36 uses compiler.parser.util;
37 uses compiler.parser.local_type;
38 uses compiler.parser.export;
40 record promoted_variable [
41         v : int;
42         name : istring;
43         cnst : bool;
44         mut : bool;
45         impl : bool;
46         typ : int;
49 fn add_promoted_variable(ctx : function_context, cc : compare_context, vd : variable_dictionary, v : int, pv : promoted_variable) : (function_context, variable_dictionary)
51         var typ : int;
52         ctx, typ := evaluate_type(ctx, cc, pv.typ, empty(compare_fn_stack), empty(token));
54         var defined : int;
55         if pv.cnst or pv.mut then
56                 defined := defined_argument;
57         else
58                 defined := defined_multiple;
60         var nv : local_variable;
61         ctx, nv := new_variable(ctx, typ, defined, pv.mut);
62         ctx.variables[v] := nv;
64         ctx, vd := add_variable(ctx, vd, pv.name, v, pv.impl, empty(token));
66         return ctx, vd;
69 fn parse_argument(ctx : function_context, vd : variable_dictionary, v n : int, t : tokens, cnst mut retval : bool) : function_context
71         var a : int;
72         ctx, a := parse_expression_type(ctx, vd, t);
74         if a = T_Type then
75                 cnst := true;
77         var defined : int;
78         if not retval then [
79                 if cnst or mut then
80                         defined := defined_argument;
81                 else
82                         defined := defined_multiple;
83         ] else [
84                 defined := defined_argument;
85         ]
87         for i := 0 to n do [
88                 var nv : local_variable;
89                 ctx, nv := new_variable(ctx, a, defined, mut);
90                 ctx.variables[v + i] := nv;
91         ]
93         return ctx;
96 fn parse_arguments(ctx : function_context, vd : variable_dictionary, t : tokens, retval : bool, v : int, cnst : bool) : (function_context, variable_dictionary)
98         if retval and ctx.inferred_return then [
99                 for i := 0 to ctx.n_return_values do [
100                         var nv : local_variable;
101                         ctx, nv := new_variable(ctx, T_InvalidType, defined_argument, false);
102                         ctx.variables[v + i] := nv;
103                 ]
104                 return ctx, vd;
105         ]
106         if len_at_least(t, 2), t[0].t is left_paren and t[0].bracket_skip = len(t) - 1 then [
107                 t := t[1 .. len(t) - 1];
108         ]
110         while len(t) > 0 do [
111                 var decl : tokens;
113                 decl, t := split_tokens(t, token_opt.comma);
115                 var cnst := cnst;
116                 var mut := false;
117                 var impl := false;
118                 if not retval then [
119 next_flag:
120                         if len(decl) > 0 then [
121                                 if decl[0].t is k_const then [
122                                         cnst := true;
123                                         decl := decl[1 .. ];
124                                         goto next_flag;
125                                 ]
126                                 if decl[0].t is k_mutable then [
127                                         mut := true;
128                                         decl := decl[1 .. ];
129                                         goto next_flag;
130                                 ]
131                                 if decl[0].t is k_implicit then [
132                                         impl := true;
133                                         decl := decl[1 .. ];
134                                         goto next_flag;
135                                 ]
136                         ]
137                 ]
138                 if cnst and mut then [
139                         abort compiler_error("Mutable and const can't be specified together", t);
140                 ]
142                 var colon := token_find_colon(decl);
144                 if colon >= 0 then [
145                         var expression := decl[colon + 1 .. ];
146                         ctx := parse_argument(ctx, vd, v, colon, expression, cnst, mut, retval);
147                         for i := 0 to colon do [
148                                 var name := decl[i].t.identifier;
149                                 ctx, vd := add_variable(ctx, vd, name, v, impl, decl);
150                                 v += 1;
151                         ]
152                 ] else [
153                         ctx := parse_argument(ctx, vd, v, 1, decl, cnst, mut, retval);
154                         v += 1;
155                 ]
156         ]
158         return ctx, vd;
161 fn count_arguments(t : tokens, retval : bool) : int
163         var count := 0;
164         var in_parens := false;
166         if len(t) >= 2, t[0].t is left_paren and t[0].bracket_skip = len(t) - 1 then [
167                 t := t[1 .. len(t) - 1];
168                 in_parens := true;
169         ]
171         if retval and len(t) = 0 then
172                 abort compiler_error("Function has no return value", t);
174         while len(t) > 0 do [
175                 var decl : tokens;
177                 decl, t := split_tokens(t, token_opt.comma);
178                 if not in_parens and len(t) > 0 then
179                         abort compiler_error("Multiple return values must be in parentheses", t);
181                 if not retval then [
182 next_flag:
183                         if len(decl) > 0 then [
184                                 if decl[0].t is k_const then [
185                                         decl := decl[1 .. ];
186                                         goto next_flag;
187                                 ]
188                                 if decl[0].t is k_mutable then [
189                                         decl := decl[1 .. ];
190                                         goto next_flag;
191                                 ]
192                                 if decl[0].t is k_implicit then [
193                                         decl := decl[1 .. ];
194                                         goto next_flag;
195                                 ]
196                         ]
197                 ]
199                 var colon := token_find_colon(decl);
201                 if colon >= 0 then [
202                         count += colon;
203                 ] else [
204                         count += 1;
205                 ]
206         ]
208         return count;
211 fn parse_function_header(dict : function_dictionary, parent_function : maybe(function_context), parent_vd : maybe(variable_dictionary), promoted_variables : list(promoted_variable), decl_type : token_opt, t : tokens, name : istring, op_mode : op_option, op_priority : int, cnst : bool) : (function_context, variable_dictionary)
213         var inferred_return := false;
214         var arguments : tokens;
215         var return_values : tokens;
217         if len(t) > 0, t[0].t is left_paren then [
218                 var matching_paren := t[0].bracket_skip;
219                 arguments := t[ .. matching_paren + 1];
220                 t := t[matching_paren + 1 .. ];
221         ] else [
222                 arguments := empty(token);
223         ]
225         if decl_type is k_fn or decl_type is k_const or decl_type is k_operator then [
226                 if decl_type is k_const and len(arguments) > 0 then [
227                         abort compiler_error("Constant can't have arguments", arguments);
228                 ]
229                 if len(t) = 0 then [
230                         inferred_return := true;
231                         return_values := empty(token);
232                 ] else [
233                         xeval token_assert(t, token_opt.colon);
234                         return_values := t[1 .. ];
235                 ]
236         ] else [
237                 if len(t) > 0 then
238                         abort compiler_error("Unexpected tokens", t);
239                 return_values := tokenize("type", "_internal");
240         ]
242         var n_arguments n_return_values : int;
243         n_arguments := count_arguments(arguments, false);
244         if not inferred_return then
245                 n_return_values := count_arguments(return_values, true);
246         else
247                 n_return_values := 1;
249         if (op_mode is prefix_op or op_mode is postfix_op) and n_arguments < 1 then
250                 abort compiler_error("Insufficient arguments for an operator", t);
251         if op_mode is infix_op and n_arguments < 2 then
252                 abort compiler_error("Insufficient arguments for an operator", t);
254         n_arguments += len(promoted_variables);
256         var ctx := new_function_context(dict, parent_function, n_arguments, n_return_values, name);
257         ctx.inferred_return := inferred_return;
258         ctx.op_mode := op_mode;
259         ctx.op_priority := op_priority;
261         ctx := generate_Args(ctx);
263         var vd := new_variable_dictionary(parent_vd);
265         if len(promoted_variables) > 0 then [
266                 var cc := new_compare_context_from_function(ctx.parent_function.j);
267                 cc.lambda_redirect := fill(-1, len(cc.ctx.variables));
268                 for i := 0 to len(promoted_variables) do [
269                         cc.lambda_redirect[promoted_variables[i].v] := i;
270                 ]
271                 for i := 0 to len(promoted_variables) do [
272                         ctx, vd := add_promoted_variable(ctx, cc, vd, i, promoted_variables[i]);
273                 ]
274         ]
276         ctx, vd := parse_arguments(ctx, vd, arguments, false, len(promoted_variables), cnst);
278         ctx := generate_Return_Vars(ctx);
280         var vd2 := new_variable_dictionary_chained(ctx, vd);
281         ctx, vd2 := parse_arguments(ctx, vd2, return_values, true, n_arguments, false);
283         ctx.incomplete := false;
285         return ctx, vd;
288 fn parse_function_body(ctx : function_context, vd : variable_dictionary, t : tokens) : function_context
290         var lbl : int;
291         ctx, lbl := alloc_local_label(ctx);
292         if lbl <> 0 then
293                 abort internal("The first label should be zero");
295         if t[0].t is assign then [
296                 var new_tokens := empty(token);
297                 var skip := 2 + len(t[1 .. ]);
298                 var nt := new_token(t[0], token_opt.left_bracket);
299                 nt.bracket_skip := skip;
300                 new_tokens +<= nt;
301                 nt := new_token(t[0], token_opt.k_return);
302                 new_tokens +<= nt;
303                 new_tokens += t[1 .. ];
304                 nt := new_token(t[0], token_opt.right_bracket);
305                 nt.bracket_skip := -skip;
306                 new_tokens +<= nt;
307                 t := new_tokens;
308         ]
310         var left : tokens;
311         var term : bool;
312         ctx, left, term := parse_statement(ctx, vd, true, t);
313         xeval ctx;
314         if len(left) > 0 then
315                 abort compiler_error("Tokens after the end of the function", left);
316         if not term then
317                 abort compiler_error("The function must end with terminating statement", t[len(t) - 1 .. ]);
319         ctx := generate_Label(ctx, lbl);
321         ctx := generate_Return(ctx);
323         for i := 0 to len(ctx.list_of_used_labels) do [
324                 var name := ctx.list_of_used_labels[i];
325                 if not ctx.defined_labels[name] then
326                         abort compiler_error("Label " + i_decode(name) + " was not defined", t);
327         ]
329         for i := 0 to ctx.n_return_values do [
330                 var v := ctx.n_arguments + i;
331                 if get_type_of_var(ctx, v) = T_InvalidType then
332                         abort compiler_error("Return type was not inferred", t);
333         ]
335         return ctx;
338 fn parse_record_definition(ctx : function_context, orig_vd : variable_dictionary, is_option : bool, t : tokens) : function_context
340         var vd := orig_vd;
341         var def := new_record_definition(is_option);
342         var fields := empty(int);
343         t := t[1 .. len(t) - 1];
344         while len_greater_than(t, 0) do [
345                 var semicolon := token_find(t, token_opt.semicolon, true);
346                 var decl := t[ .. semicolon];
347                 var cnst := false;
349 next_flag:
350                 if len_greater_than(decl, 0) then [
351                         if not is_option, decl[0].t is k_const then [
352                                 cnst := true;
353                                 decl := decl[1 .. ];
354                                 goto next_flag;
355                         ]
356                 ]
358                 var colon := token_find_colon(decl);
359                 if not is_option and colon = -1 then
360                         abort compiler_error("No declared variable", t);
361                 t := t[semicolon + 1 .. ];
363                 var a : int;
364                 var accessing_other := false;
366                 if colon >= 0 then [
367                         var expr := decl[colon + 1 .. ];
368                         var new_ctx : function_context;
369                         new_ctx, a := parse_expression_type(ctx, orig_vd, expr);
370                         if is_exception new_ctx, exception_type new_ctx = error_compiler_error then [
371                                 ctx, a := parse_expression_type(ctx, vd, expr);
372                                 accessing_other := true;
373                         ] else [
374                                 ctx := new_ctx;
375                         ]
376                 ] else [
377                         colon := len(decl);
378                         a := T_EmptyOption;
379                         def.is_flat_option := true;
380                 ]
382                 if a = T_Type then
383                         cnst := true;
385                 for i := 0 to colon do [
386                         var idx := len(def.entries);
387                         xeval token_assert(decl, token_opt.identifier.(0));
388                         var name := decl[0].t.identifier;
389                         decl := decl[1 .. ];
390                         var found := def.dict[name];
391                         if not is_uninitialized(found) then
392                                 abort compiler_error("Entry " + i_decode(name) + " already defined", t);
393                         if not is_option then [
394                                 var l : int;
395                                 ctx, l := alloc_local_variable(ctx, a, cnst, false);
396                                 ctx := generate_Load_Local_Type(ctx, -1, idx, l);
397                                 ctx, vd := add_variable(ctx, vd, name, l, false, decl);
398                         ]
399                         def.dict[name] := idx;
400                         def.entries +<= record_entry.[ type_idx : a, cnst : cnst, accessing_other : accessing_other ];
401                         fields +<= a;
402                 ]
403         ]
404         if not is_option then
405                 ctx := generate_Record_Type(ctx, fields, ctx.n_arguments);
406         else
407                 ctx := generate_Option_Type(ctx, fields, ctx.n_arguments);
408         ctx := generate_Return(ctx);
409         ctx.record_def := maybe(record_definition).j.(def);
410         return ctx;
413 fn compare_function_signatures(c1 c2 : function_context) : bool
415         if c1.inferred_return or c2.inferred_return then
416                 return false;
418         if ord c1.op_mode <> ord c2.op_mode then
419                 return false;
420         if c1.op_priority <> c2.op_priority then
421                 return false;
423         if c1.n_arguments <> c2.n_arguments then
424                 return false;
425         if c1.n_return_values <> c2.n_return_values then
426                 return false;
428         if len(c1.variables) <> len(c2.variables) then
429                 return false;
430         for i := 0 to len(c1.variables) do [
431                 var v1 := c1.variables[i];
432                 var v2 := c2.variables[i];
433                 if v1.type_idx <> v2.type_idx then
434                         return false;
435                 if v1.mut <> v2.mut then
436                         return false;
437                 if v1.local_type <> v2.local_type then
438                         return false;
439         ]
441         if len(c1.instructions) <> len(c2.instructions) then
442                 return false;
443         for i := 0 to len(c1.instructions) do [
444                 var i1 := c1.instructions[i];
445                 var i2 := c2.instructions[i];
446                 if i1.opcode <> i2.opcode then
447                         return false;
448                 if len(i1.args) <> len(i2.args) then
449                         return false;
450                 for j := 0 to len(i1.args) do
451                         if i1.args[j] <> i2.args[j] then
452                                 return false;
453         ]
455         return true;
458 fn is_function_simple(ctx : function_context) : bool
460         if ctx.n_labels > 1 then
461                 return false;
463         for i := 0 to len(ctx.variables) do [
464                 if ctx.variables[i].defined_at = defined_multiple or ctx.variables[i].mut then
465                         return false;
466         ]
468         return true;
471 fn parse_function(dict : function_dictionary, t : tokens, private_flag implicit_flag conversion_flag : bool) : function_dictionary
473         var decl_type := t[0].t;
474         var name : istring;
475         var call_mode : int;
476         var op_mode : op_option;
477         var op_priority : int;
478         var post_hints : list(bytes);
479         if decl_type is k_operator then [
480                 op_mode := op_option.infix_op;
481                 t := t[1 .. ];
482                 var name_sfx := op_name;
483                 if len_at_least(t, 1), t[0].t is k_prefix then [
484                         t := t[1 .. ];
485                         op_mode := op_option.prefix_op;
486                         name_sfx := op_prefix_name;
487                 ] else if len_at_least(t, 1), t[0].t is k_postfix then [
488                         t := t[1 .. ];
489                         op_mode := op_option.postfix_op;
490                 ]
491                 if len_at_least(t, 2), t[0].t is oper then
492                         name := t[0].t.oper;
493                 else if len_at_least(t, 2), t[0].t is identifier then
494                         name := t[0].t.identifier;
495                 else
496                         abort compiler_error("Operator expected", t);
497                 name := i_append(name, name_sfx);
498                 xeval token_assert(t[1 .. ], token_opt.number.(""));
499                 //op_priority := ston(t[1].t.number);
500                 op_priority := instance_number_int.from_bytes(t[1].t.number);
501                 post_hints := t[1].post_hints;
502                 t := t[2 .. ];
503         ] else [
504                 xeval token_assert(t[1 .. ], token_opt.identifier.(0));
505                 name := t[1].t.identifier;
506                 post_hints := t[1].post_hints;
507                 op_mode := op_option.function;
508                 op_priority := -1;
509                 t := t[2 .. ];
510         ]
511         call_mode := get_call_mode(post_hints, true);
513         var b : int;
514         var vd : variable_dictionary;
515         var ctx : function_context;
516         var cnst := decl_type is k_record or decl_type is k_option;
518         var def := search_function_dictionary(dict, name);
520         if t[len(t) - 1].t is right_bracket then [
521                 b := token_find(t, token_opt.left_bracket, true);
522                 if b = 0, not is_uninitialized(def) then [
523                         ctx := def.signature;
524                         vd := def.vd;
525                         //eval debug("implicit args 1: " + i_decode(name));
526                 ] else [
527                         ctx, vd := parse_function_header(dict, maybe(function_context).n, maybe(variable_dictionary).n, empty(promoted_variable), decl_type, t[ .. b], name, op_mode, op_priority, cnst);
528                 ]
529         ] else [
530                 b := token_find(t, token_opt.assign, false);
531                 if b = 0, not is_uninitialized(def) then [
532                         ctx := def.signature;
533                         vd := def.vd;
534                         //eval debug("implicit args 2: " + i_decode(name));
535                 ] else if b >= 0 then [
536                         cnst := true;
537                         ctx, vd := parse_function_header(dict, maybe(function_context).n, maybe(variable_dictionary).n, empty(promoted_variable), decl_type, t[ .. b], name, op_mode, op_priority, cnst);
538                 ] else [
539                         ctx, vd := parse_function_header(dict, maybe(function_context).n, maybe(variable_dictionary).n, empty(promoted_variable), decl_type, t[ .. len(t) - 1], name, op_mode, op_priority, cnst);
540                 ]
541         ]
543         if not is_uninitialized(def) then [
544                 //eval debug(i_decode(name) + " exists");
545                 if not compare_function_signatures(def.signature, ctx) then
546                         abort compiler_error("Function type doesn't match previous definition", t);
547                 if call_mode <> Call_Mode_Unspecified, call_mode <> def.call_mode then
548                         abort compiler_error("Call mode doesn't match previous definition", t);
550                 if private_flag then
551                         dict.defs[dict.dict[name]].private_flag := true;
553                 if implicit_flag then
554                         dict.impl +<= def.signature.id.function_index[0];
556                 if conversion_flag then
557                         dict.conv +<= def.signature.id.function_index[0];
559                 // propagate the "const" flags from ctx
560                 dict.defs[dict.dict[name]].signature.variables := ctx.variables;
561                 def.signature.variables := ctx.variables;
562         ] else [
563                 //eval debug(i_decode(name) + " doesn't exist");
564                 var op_bypass := -1;
565                 var op_bypass_reverse := false;
566                 if decl_type is k_const and call_mode = Call_Mode_Unspecified then
567                         call_mode := Call_Mode_Inline;
568                 if (decl_type is k_type or decl_type is k_record or decl_type is k_option) and call_mode = Call_Mode_Unspecified then
569                         call_mode := Call_Mode_Type;
571                 if function_context_is_privileged(ctx) then [
572                         for i := 0 to len(post_hints) do [
573                                 var h := post_hints[i];
574                                 if list_begins_with(h, "Bin_") or list_begins_with(h, "Un_") then [
575                                         if list_ends_with(h, "_") then [
576                                                 op_bypass_reverse := true;
577                                                 h := h[ .. len(h) - 1];
578                                         ]
579                                         op_bypass := name_to_value[i_encode(h)];
580                                         //eval debug("bypass: " + i_decode(name) + ", " + ntos(op_bypass));
581                                 ]
582                         ]
583                 ]
585                 dict, def := add_function(dict, name, ctx, vd, call_mode, op_bypass, op_bypass_reverse, private_flag, implicit_flag, conversion_flag);
586         ]
588         if b <> -1 then [
589                 if def.body is j then
590                         abort compiler_error("Function body was already defined", t);
592                 ctx := def.signature;
593                 ctx.incomplete := true;
594                 ctx.dict := dict;
596                 ctx := generate_Line_Info_Full(ctx, i_decode(dict.id.unit_string), i_decode(name), t[0].line);
598                 if decl_type is k_fn or decl_type is k_type or decl_type is k_const or decl_type is k_operator then [
599                         dict.defs[def.signature.id.function_index[0]].typ := Fn_Function;
600                         ctx := parse_function_body(ctx, vd, t[b .. ]);
601                         if def.call_mode = Call_Mode_Type or def.call_mode = Call_Mode_Flat then [
602                                 if not is_function_simple(ctx) then
603                                         abort compiler_error("Type function must be simple (no conditions and no non-const variables)", t);
604                         ]
605                 ] else if decl_type is k_record then [
606                         dict.defs[def.signature.id.function_index[0]].typ := Fn_Record;
607                         ctx := parse_record_definition(ctx, vd, false, t[b .. ]);
608                 ] else if decl_type is k_option then [
609                         dict.defs[def.signature.id.function_index[0]].typ := Fn_Option;
610                         ctx := parse_record_definition(ctx, vd, true, t[b .. ]);
611                 ] else [
612                         abort internal("invalid decl_type " + ntos(ord decl_type));
613                 ]
615                 ctx := generate_local_types(ctx);
617                 ctx.incomplete := false;
618                 ctx := function_context_clear_temp_values(ctx);
620                 dict.defs[def.signature.id.function_index[0]].body.j := ctx;
621                 if def.signature.inferred_return then
622                         dict.defs[def.signature.id.function_index[0]].signature := ctx;
623         ] else [
624                 if def.signature.inferred_return then
625                         abort compiler_error("Function with inferred return type was not defined", t);
626         ]
628         // uncomment this to disable lazy evaluation of functions
629         //xeval ctx;
631         return dict;
634 fn parse_lambda_function(ctx : function_context, parent_vd : variable_dictionary, t : tokens) : (function_context, list(int))
636         var promoted_variables := empty(promoted_variable);
637         var pv : promoted_variable;
639         var variable : istring;
640         var variable_idx : int;
642         var implicit_variables := get_implicit_variables(parent_vd);
643         implicit_variables := list_reverse(implicit_variables);
645         var prev_hints := t[0].prev_hints;
646         var call_mode := get_call_mode(prev_hints, true);
648         var b : int;
649         if t[len(t) - 1].t is right_bracket then [
650                 b := token_find(t, token_opt.left_bracket, true);
651         ] else [
652                 b := token_find(t, token_opt.assign, true);
653         ]
655         var fn_name := i_decode(ctx.name) + "/" + ntos(len(ctx.lambdas));
657         for i := 0 to len(implicit_variables) do [
658 promote_again:
659                 variable_idx := implicit_variables[i];
660                 pv := promoted_variable.[
661                         v : variable_idx,
662                         name : 0,
663                         cnst : ctx.variables[variable_idx].defined_at <> defined_multiple,
664                         mut : ctx.variables[variable_idx].mut,
665                         impl : list_search(implicit_variables, variable_idx) >= 0,
666                         typ : ctx.variables[variable_idx].type_idx,
667                 ];
668                 promoted_variables +<= pv;
670                 var ctx_test := new_function_context(ctx.dict, maybe(function_context).j.(ctx), 0, 0, i_encode(fn_name));
671                 var vd := new_variable_dictionary(maybe(variable_dictionary).j.(parent_vd));
673                 if len(promoted_variables) > 0 then [
674                         var cc := new_compare_context_from_function(ctx);
675                         cc.lambda_redirect := fill(-1, len(cc.ctx.variables));
676                         for i := 0 to len(promoted_variables) do [
677                                 cc.lambda_redirect[promoted_variables[i].v] := i;
678                         ]
679                         for i := 0 to len(promoted_variables) do [
680                                 ctx_test, vd := add_promoted_variable(ctx, cc, vd, i, promoted_variables[i]);
681                         ]
682                 ]
684                 ctx_test, vd := parse_arguments(ctx_test, vd, empty(token), false, len(promoted_variables), false);
686                 if is_exception ctx_test, exception_type ctx_test = error_user3 then [
687                         variable_idx := exception_aux ctx_test;
688                         promoted_variables := promoted_variables[ .. len(promoted_variables) - 1];
689                         pv := promoted_variable.[
690                                 v : variable_idx,
691                                 name : 0,
692                                 cnst : ctx.variables[variable_idx].defined_at <> defined_multiple,
693                                 mut : ctx.variables[variable_idx].mut,
694                                 impl : list_search(implicit_variables, variable_idx) >= 0,
695                                 typ : ctx.variables[variable_idx].type_idx,
696                         ];
697                         promoted_variables +<= pv;
698                         goto promote_again;
699                 ]
700         ]
702 again:
703         var ctx_head, vd := parse_function_header(ctx.dict, maybe(function_context).j.(ctx), maybe(variable_dictionary).j.(parent_vd), promoted_variables, token_opt.k_fn, t[ .. b], i_encode(fn_name), op_option.function, -1, false);
704         if is_exception ctx_head, exception_type ctx_head = error_user2 then [
705                 variable := i_encode(exception_payload ctx_head);
706                 goto add_variable;
707         ]
708         if is_exception ctx_head, exception_type ctx_head = error_user3 then [
709                 variable_idx := exception_aux ctx_head;
710                 goto add_variable_2;
711         ]
713         ctx_head.incomplete := false;
714         var ctx_body := ctx_head;
715         ctx_body.incomplete := true;
716         ctx_body := generate_Line_Info_Full(ctx_body, i_decode(ctx.dict.id.unit_string), fn_name, t[0].line);
717         ctx_body := parse_function_body(ctx_body, vd, t[b .. ]);
718         if is_exception ctx_body, exception_type ctx_body = error_user2 then [
719                 variable := i_encode(exception_payload ctx_body);
720                 goto add_variable;
721         ]
722         if is_exception ctx_body, exception_type ctx_body = error_user3 then [
723                 variable_idx := exception_aux ctx_body;
724                 goto add_variable_2;
725         ]
727         if call_mode = Call_Mode_Type or call_mode = Call_Mode_Flat then
728                 if not is_function_simple(ctx_body) then
729                         abort compiler_error("Type function must be simple (no conditions and no non-const variables)", t);
731         ctx_body := generate_local_types(ctx_body);
732         ctx_body.incomplete := false;
734         if ctx_head.inferred_return then
735                 ctx_head := ctx_body;
737         var fd : function_definition;
738         ctx, fd := add_lambda(ctx, ctx_head, ctx_body, call_mode);
740         if fd.signature.n_arguments = 0 then [
741                 var q : list(int);
742                 ctx, q := generate_Call(ctx, call_mode, fd, empty(int), t);
743                 if len(q) <> fd.signature.n_return_values then
744                         abort internal("parse_lambda_function: invalid number of return values");
745                 return ctx, q;
746         ] else [
747                 var l : int;
748                 ctx, l := generate_Load_Fn(ctx, fd, t);
749                 if len(promoted_variables) = 0 then
750                         return ctx, [ l ];
751                 var args := fill(T_InvalidType, len(promoted_variables));
752                 for i := 0 to len(promoted_variables) do
753                         args[i] := promoted_variables[i].v;
754                 var cc, typ := get_deep_type_of_var(ctx, l);
755                 cc := set_llt_main(cc, typ);
756                 for i := 0 to len(promoted_variables) do
757                         cc.llt_redirect +<= new_compare_argument(new_compare_context(ctx), args[i]);
758                 ctx, l := generate_Curry(ctx, cc, typ, l, args, t);
759                 if len(promoted_variables) = fd.signature.n_arguments then [
760                         var q : list(int);
761                         ctx, q := generate_Call_Indirect(ctx, call_mode, l, t);
762                         if len(q) <> fd.signature.n_return_values then
763                                 abort internal("parse_lambda_function: invalid number of return values");
764                         return ctx, q;
765                 ]
766                 return ctx, [ l ];
767         ]
769 add_variable:
770         variable_idx := search_variable_dictionary(parent_vd, variable);
771         xeval variable_idx;
772         if variable_idx = -1 then
773                 abort internal("Variable " + i_decode(variable) + " not found in parent function");
774         //if ctx.variables[variable_idx].type_idx >= 0 then
775         //      abort compiler_error("Variable " + i_decode(variable) + " doesn't have a simple type", t);
777         for i := 0 to len(promoted_variables) do [
778                 if promoted_variables[i].v = variable_idx then [
779                         promoted_variables[i].name := variable;
780                         goto again;
781                 ]
782         ]
784         pv := promoted_variable.[
785                 v : variable_idx,
786                 name : variable,
787                 cnst : ctx.variables[variable_idx].defined_at <> defined_multiple,
788                 mut : ctx.variables[variable_idx].mut,
789                 impl : list_search(implicit_variables, variable_idx) >= 0,
790                 typ : ctx.variables[variable_idx].type_idx,
791         ];
793         promoted_variables +<= pv;
794         goto again;
796 add_variable_2:
797         if len(promoted_variables) > 0 then
798                 promoted_variables := promoted_variables[ .. len(promoted_variables) - 1];
799         pv := promoted_variable.[
800                 v : variable_idx,
801                 name : 0,
802                 cnst : ctx.variables[variable_idx].defined_at <> defined_multiple,
803                 mut : ctx.variables[variable_idx].mut,
804                 impl : list_search(implicit_variables, variable_idx) >= 0,
805                 typ : ctx.variables[variable_idx].type_idx,
806         ];
807         promoted_variables +<= pv;
808         goto again;
811 fn parse_unit_name(unit_tokens : tokens) : bytes
813         var file_name := "";
815         for i := 0 to len(unit_tokens) do [
816                 var s := token_opt_to_string(unit_tokens[i].t, true);
817                 file_name += s;
818         ]
820         if len(file_name) = 0 then [
821 invalid:
822                 abort compiler_error("invalid unit name", unit_tokens);
823         ]
825         for i := 0 to len(file_name) do [
826                 if path_is_separator(file_name[i]) then
827                         goto invalid;
828                 if file_name[i] = '.' then [
829                         if i = 0 or i = len(file_name) - 1 then
830                                 goto invalid;
831                         if path_is_separator(file_name[i - 1]) then
832                                 goto invalid;
833                         file_name[i] := '/';
834                 ]
835         ]
837         return file_name;
840 fn merge_interfaces(dict new_dict : function_dictionary) : function_dictionary
842         var m_id := encode_module_id(new_dict.id);
843         if not is_uninitialized(dict.modules_map[m_id]) then
844                 return dict;
845         dict.modules_map[m_id] := len(dict.modules);
846         dict.modules +<= new_dict;
847         for i := 0 to len(new_dict.modules) do
848                 dict := merge_interfaces(dict, new_dict.modules[i]);
849         return dict;
852 fn parse_uses(w : world, d : list(bytes), dict : function_dictionary, t : tokens) : function_dictionary
854         var file := parse_unit_name(t);
855         var i := len(d) - 1;
856         while i >= 0 do [
857                 var first := i = len(d) - 1;
858                 var xfile := file;
859                 if first then
860                         xfile := dict.name_prefix + xfile;
861                 var new_dict := parse_file(w, d[ .. i + 1], xfile, false, true);
862                 if is_exception new_dict, exception_class new_dict = ec_syscall then [
863                         i -= 1;
864                         continue;
865                 ]
866                 if new_dict.priv, not first, not is_privileged then [
867                         i -= 1;
868                         continue;
869                 ]
870                 dict := merge_interfaces(dict, new_dict);
871                 return dict;
872         ]
873         abort compiler_error("Unit '" + file + "' not found", t);
877 fn parse_system_unit(w : world, d : list(bytes), dict : function_dictionary) : function_dictionary
879         var new_dict := parse_file(w, d[ .. 1], "system", false, true);
880         dict := merge_interfaces(dict, new_dict);
881         return dict;
884 fn parse_define(dict : function_dictionary, t : tokens) : function_dictionary
886         xeval token_assert(t[1 .. ], token_opt.identifier.(0));
887         var name := t[1].t.identifier;
888         var t2 := t[2 .. ];
889         if len_at_least(t2, 2), t2[0].t is left_bracket then
890                 t2 := t2[1 .. len(t2) - 1];
891         else if len_at_least(t2, 1), t2[len(t2) - 1].t is semicolon then
892                 t2 := t2[ .. len(t2) - 1];
893         else
894                 abort compiler_error("Invalid define statement", t);
895         dict.macros[name] := t2;
896         return dict;
899 fn expand_macro(t : tokens, m : tokens) : tokens
901         if not t[len(t) - 1].t is semicolon then
902                 abort compiler_error("Invalid macro expansion", t);
903         var args := empty(tokens);
904         if len_greater_than(t, 1) then [
905                 xeval token_assert(t[1 .. ], token_opt.left_paren);
906                 var t1 := t[2 .. len(t) - 2];
907 next_arg:
908                 var comma := token_find(t1, token_opt.comma, false);
909                 var arg : tokens;
910                 if comma >= 0 then
911                         arg := t1[ .. comma];
912                 else
913                         arg := t1;
914                 args +<= arg;
915                 if comma >= 0 then [
916                         t1 := t1[comma + 1 .. ];
917                         goto next_arg;
918                 ]
919         ]
920         if len_greater_than(args, 9) then
921                 abort compiler_error("Too many macro arguments", t);
922         var result := empty(token);
923         for i := 0 to len(m) do [
924                 var n := m[i];
925                 if n.t is macro_expansion then [
926                         var toks : tokens;
927                         var str := i_decode(n.t.macro_expansion);
928                         if len(str) = 2, str[0] = '@', str[1] >= '1', str[1] <= '9' then [
929                                 var n_arg := str[1] - '1';
930                                 if n_arg >= len(args) then
931                                         abort compiler_error("Argument " + ntos(n_arg) + " not provided", t);
932                                 toks := args[n_arg];
933                                 goto paste_toks;
934                         ]
935                         var result_str := empty(byte);
936                         for j := 0 to len(str) do [
937                                 var c := str[j];
938                                 if c = '@', j < len(str) - 1, str[j + 1] >= '1', str[j + 1] <= '9' then [
939                                         var n_arg := str[j + 1] - '1';
940                                         if n_arg >= len(args) then
941                                                 abort compiler_error("Argument " + ntos(n_arg) + " not provided", t);
942                                         var expanded : bytes;
943                                         if len(args[n_arg]) = 0 then [
944                                                 expanded := "";
945                                         ] else if len(args[n_arg]) > 1 then [
946                                                 abort compiler_error("Argument " + ntos(n_arg) + " must have a single token", t);
947                                         ] else [
948                                                 expanded := token_opt_to_string(args[n_arg][0].t, true);
949                                         ]
950                                         result_str += expanded;
951                                         j += 1;
952                                         continue;
953                                 ]
954                                 result_str +<= c;
955                         ]
956                         toks := tokenize_string(result_str, t);
957 paste_toks:
958                         if len_greater_than(toks, 0) then [
959                                 toks[0].prev_hints += n.prev_hints;
960                                 toks[len(toks) - 1].post_hints += n.post_hints;
961                         ]
962                         result += toks;
963                         continue;
964                 ]
965                 result +<= n;
966         ]
967         for i := 0 to len(result) do [
968                 result[i].bracket_skip := 0;
969         ]
970         var bracket_stack_pos := empty(int);
971         var bracket_stack_type := empty(token_opt);
972         for i := 0 to len(result) do [
973                 if result[i].t is left_paren then [
974                         bracket_stack_pos +<= i;
975                         bracket_stack_type +<= token_opt.right_paren;
976                 ] else if result[i].t is left_bracket then [
977                         bracket_stack_pos +<= i;
978                         bracket_stack_type +<= token_opt.right_bracket;
979                 ] else if result[i].t is right_paren or result[i].t is right_bracket then [
980                         var l := len(bracket_stack_type);
981                         if l = 0 or ord bracket_stack_type[l - 1] <> ord result[i].t then
982                                 abort compiler_error("Imbalanced bracket in macro expansion", t);
983                         var bracket_skip := i - bracket_stack_pos[l - 1];
984                         result[bracket_stack_pos[l - 1]].bracket_skip := bracket_skip;
985                         result[i].bracket_skip := -bracket_skip;
986                         bracket_stack_type := bracket_stack_type[ .. l - 1];
987                         bracket_stack_pos := bracket_stack_pos[ .. l - 1];
988                 ]
989         ]
990         if len(bracket_stack_type) <> 0 then
991                 abort compiler_error("Imbalanced bracket in macro expansion", t);
992         return result;
995 fn parse_clause(w : world, d : list(bytes), dict : function_dictionary, t1 : tokens) : (function_dictionary, tokens)
997         var f := token_find_3(t1, token_opt.assign, token_opt.semicolon, token_opt.right_bracket, true);
998         if t1[f].t is assign then [
999                 f := token_find(t1, token_opt.semicolon, true);
1000         ]
1001         var t := t1[ .. f + 1];
1003         var private_flag := false;
1004         var implicit_flag := false;
1005         var conversion_flag := false;
1006 next_flag:
1007         if len(t) = 0 then [
1008                 abort compiler_error("Empty clause", empty(token));
1009         ]
1010         if t[0].t is k_private then [
1011                 private_flag := true;
1012                 t := t[1 ..];
1013                 goto next_flag;
1014         ]
1015         if t[0].t is k_implicit then [
1016                 implicit_flag := true;
1017                 t := t[1 ..];
1018                 goto next_flag;
1019         ]
1020         if t[0].t is k_conversion then [
1021                 conversion_flag := true;
1022                 t := t[1 ..];
1023                 goto next_flag;
1024         ]
1025         if t[0].t is k_uses then [
1026                 if private_flag or implicit_flag or conversion_flag or not t[len(t) - 1].t is semicolon then
1027                         abort compiler_error("Invalid uses clause", t);
1028                 t := t[1 .. len(t) - 1];
1029                 while len(t) > 0 do [
1030                         var decl : tokens;
1031                         decl, t := split_tokens(t, token_opt.comma);
1032                         dict := parse_uses(w, d, dict, decl);
1033                 ]
1034         ] else if t[0].t is k_define then [
1035                 dict := parse_define(dict, t);
1036         ] else if t[0].t is k_fn or
1037                   t[0].t is k_record or
1038                   t[0].t is k_option or
1039                   t[0].t is k_type or
1040                   t[0].t is k_const or
1041                   t[0].t is k_operator then [
1042                 dict := parse_function(dict, t, private_flag, implicit_flag, conversion_flag);
1043         ] else if t[0].t is identifier, not is_uninitialized(dict.macros[t[0].t.identifier]) then [
1044                 var m := dict.macros[t[0].t.identifier];
1045                 m := expand_macro(t, m);
1046                 while len_greater_than(m, 0) do [
1047                         dict, m := parse_clause(w, d, dict, m);
1048                 ]
1049         ] else [
1050                 abort compiler_error("Expected 'fn' or 'record' or 'option' or 'type' or 'const' or 'operator' or 'private' or 'uses' or 'define'", t);
1051         ]
1052         return dict, t1[f + 1 .. ];
1055 fn parse_tokens(w : world, d : list(bytes), t : tokens, name : bytes, program : bool, parse_interface : bool) : function_dictionary
1057         var path_index := len(d) - 1;
1058         var dict := new_function_dictionary(path_index, i_encode(name), program);
1060 next_unit_flag:
1061         if len_greater_than(t, 0), t[0].t is k_private then [
1062                 dict.priv := true;
1063                 t := t[1 .. ];
1064                 goto next_unit_flag;
1065         ]
1066         var a := token_assert(t, token_opt.k_unit);
1067         if is_exception a then
1068                 return exception_make(function_dictionary, ec_syscall, error_system, system_error_enoent, true);
1070         var sc := token_find(t, token_opt.semicolon, true);
1071         var unit_tokens := t[1 .. sc];
1073         var file_name := parse_unit_name(unit_tokens);
1076         if parse_interface then
1077                 eval debug("interface: " + file_name);
1078         else
1079                 eval debug("file name: " + file_name);
1082         var name_pos := len(name) - len(file_name);
1083         if name_pos < 0 then [
1084                 abort compiler_error("Unit name doesn't match file name", unit_tokens);
1085         ]
1086         if name_pos > 0, not path_is_separator(name[name_pos - 1]) then [
1087                 abort compiler_error("Unit name doesn't match file name", unit_tokens);
1088         ]
1089         if name[name_pos .. ] <> file_name then [
1090                 abort compiler_error("Unit name doesn't match file name", unit_tokens);
1091         ]
1092         dict.name_prefix := name[ .. name_pos];
1093         t := t[sc + 1 ..];
1095         if path_index <> 0 or name <> "system" then [
1096                 dict := parse_system_unit(w, d, dict);
1097         ]
1099         var was_implementation := false;
1101         while len_greater_than(t, 0) do [
1102                 if t[0].t is k_implementation and not was_implementation then [
1103                         if parse_interface then [
1104                                 return dict;
1105                         ] else [
1106                                 was_implementation := true;
1107                         ]
1108                         t := t[1 ..];
1109                         continue;
1110                 ]
1112                 dict, t := parse_clause(w, d, dict, t);
1113         ]
1115         return dict;
1118 fn unit_encode(un_name : bytes) : bytes
1120         var result := """";
1121         for i := 0 to len(un_name) do [
1122                 if un_name[i] = '"' then
1123                         result += """""";
1124                 else if un_name[i] < ' ' then
1125                         abort compiler_error("invalid program file name", empty(token));
1126                 else
1127                         result +<= un_name[i];
1128         ]
1129         result += """";
1130         return result;
1133 fn parse_file~cache(w : world, d : list(bytes), name : bytes, program : bool, parse_interface : bool) : function_dictionary
1135         var idx := len(d) - 1;
1136         var dir := dopen_lazy(dnone(w), d[idx], 0);
1138         if idx > 0 then
1139                 xeval register_dependence(w, dir, name + ".ajla");
1141         var f := ropen_lazy(dir, name + ".ajla", 0);
1143         if path_is_separator('\') then [
1144                 for i := 0 to len(name) do [
1145                         if name[i] = '\' then
1146                                 name[i] := '/';
1147                 ]
1148         ]
1150         xeval f;
1152         var h := "";
1153         if program then [
1154                 var un_dir, un_name := path_to_dir_file(name);
1155                 h := "unit " + unit_encode(un_name) + "; uses io, treemap; fn main(implicit w : world, d : dhandle, h : list(handle), args : list(bytes), env : treemap(bytes, bytes)) : world; implementation ";
1156         ]
1157         h += read_lazy(f);
1158         var t := tokenize(h, name);
1159         var dict := parse_tokens(w, d, t, name, program, parse_interface);
1160         if not parse_interface then [
1161                 for i := 0 to len(dict.defs) do [
1162                         if dict.defs[i].body is n then
1163                                 abort compiler_error("function '" + i_decode(dict.defs[i].signature.name) + "' was not defined", empty(token));
1164                         dict.defs[i].pcode := dump_function(dict.defs[i]);
1165                 ]
1166         ]
1167         return dict;