Ton

Форк
0
/
parse-func.cpp 
1818 строк · 56.5 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

4
    TON Blockchain Library is free software: you can redistribute it and/or modify
5
    it under the terms of the GNU Lesser 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
    TON Blockchain Library 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 Lesser General Public License for more details.
13

14
    You should have received a copy of the GNU Lesser General Public License
15
    along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
16

17
    Copyright 2017-2020 Telegram Systems LLP
18
*/
19
#include "func.h"
20
#include "td/utils/crypto.h"
21
#include "common/refint.h"
22
#include "openssl/digest.hpp"
23
#include "block/block.h"
24
#include "block-parse.h"
25

26
namespace sym {
27

28
int compute_symbol_subclass(std::string str) {
29
  using funC::IdSc;
30
  if (str.size() < 2) {
31
    return IdSc::undef;
32
  } else if (str[0] == '.') {
33
    return IdSc::dotid;
34
  } else if (str[0] == '~') {
35
    return IdSc::tildeid;
36
  } else {
37
    return IdSc::undef;
38
  }
39
}
40

41
}  // namespace sym
42

43
namespace funC {
44
using namespace std::literals::string_literals;
45
using src::Lexer;
46
using sym::symbols;
47
using td::Ref;
48

49
inline bool is_dot_ident(sym_idx_t idx) {
50
  return symbols.get_subclass(idx) == IdSc::dotid;
51
}
52

53
inline bool is_tilde_ident(sym_idx_t idx) {
54
  return symbols.get_subclass(idx) == IdSc::tildeid;
55
}
56

57
inline bool is_special_ident(sym_idx_t idx) {
58
  return symbols.get_subclass(idx) != IdSc::undef;
59
}
60

61
/*
62
 * 
63
 *   PARSE SOURCE
64
 * 
65
 */
66

67
// TE ::= TA | TA -> TE
68
// TA ::= int | ... | cont | var | _ | () | ( TE { , TE } ) | [ TE { , TE } ]
69
TypeExpr* parse_type(Lexer& lex);
70

71
TypeExpr* parse_type1(Lexer& lex) {
72
  switch (lex.tp()) {
73
    case _Int:
74
      lex.next();
75
      return TypeExpr::new_atomic(_Int);
76
    case _Cell:
77
      lex.next();
78
      return TypeExpr::new_atomic(_Cell);
79
    case _Slice:
80
      lex.next();
81
      return TypeExpr::new_atomic(_Slice);
82
    case _Builder:
83
      lex.next();
84
      return TypeExpr::new_atomic(_Builder);
85
    case _Cont:
86
      lex.next();
87
      return TypeExpr::new_atomic(_Cont);
88
    case _Tuple:
89
      lex.next();
90
      return TypeExpr::new_atomic(_Tuple);
91
    case _Var:
92
    case '_':
93
      lex.next();
94
      return TypeExpr::new_hole();
95
    case _Ident: {
96
      auto sym = sym::lookup_symbol(lex.cur().val);
97
      if (sym && dynamic_cast<SymValType*>(sym->value)) {
98
        auto val = dynamic_cast<SymValType*>(sym->value);
99
        lex.next();
100
        return val->get_type();
101
      }
102
      lex.cur().error_at("`", "` is not a type identifier");
103
    }
104
  }
105
  int c;
106
  if (lex.tp() == '[') {
107
    lex.next();
108
    c = ']';
109
  } else {
110
    lex.expect('(');
111
    c = ')';
112
  }
113
  if (lex.tp() == c) {
114
    lex.next();
115
    return c == ')' ? TypeExpr::new_unit() : TypeExpr::new_tuple({});
116
  }
117
  auto t1 = parse_type(lex);
118
  if (lex.tp() == ')') {
119
    lex.expect(c);
120
    return t1;
121
  }
122
  std::vector<TypeExpr*> tlist{1, t1};
123
  while (lex.tp() == ',') {
124
    lex.next();
125
    tlist.push_back(parse_type(lex));
126
  }
127
  lex.expect(c);
128
  return c == ')' ? TypeExpr::new_tensor(std::move(tlist)) : TypeExpr::new_tuple(std::move(tlist));
129
}
130

131
TypeExpr* parse_type(Lexer& lex) {
132
  auto res = parse_type1(lex);
133
  if (lex.tp() == _Mapsto) {
134
    lex.next();
135
    auto to = parse_type(lex);
136
    return TypeExpr::new_map(res, to);
137
  } else {
138
    return res;
139
  }
140
}
141

142
FormalArg parse_formal_arg(Lexer& lex, int fa_idx) {
143
  TypeExpr* arg_type = 0;
144
  SrcLocation loc = lex.cur().loc;
145
  if (lex.tp() == '_') {
146
    lex.next();
147
    if (lex.tp() == ',' || lex.tp() == ')') {
148
      return std::make_tuple(TypeExpr::new_hole(), (SymDef*)nullptr, loc);
149
    }
150
    arg_type = TypeExpr::new_hole();
151
    loc = lex.cur().loc;
152
  } else if (lex.tp() != _Ident) {
153
    arg_type = parse_type(lex);
154
  } else {
155
    auto sym = sym::lookup_symbol(lex.cur().val);
156
    if (sym && dynamic_cast<SymValType*>(sym->value)) {
157
      auto val = dynamic_cast<SymValType*>(sym->value);
158
      lex.next();
159
      arg_type = val->get_type();
160
    } else {
161
      arg_type = TypeExpr::new_hole();
162
    }
163
  }
164
  if (lex.tp() == '_' || lex.tp() == ',' || lex.tp() == ')') {
165
    if (lex.tp() == '_') {
166
      loc = lex.cur().loc;
167
      lex.next();
168
    }
169
    return std::make_tuple(arg_type, (SymDef*)nullptr, loc);
170
  }
171
  if (lex.tp() != _Ident) {
172
    lex.expect(_Ident, "formal parameter name");
173
  }
174
  loc = lex.cur().loc;
175
  if (prohibited_var_names.count(sym::symbols.get_name(lex.cur().val))) {
176
    throw src::ParseError{
177
        loc, PSTRING() << "symbol `" << sym::symbols.get_name(lex.cur().val) << "` cannot be redefined as a variable"};
178
  }
179
  SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
180
  if (!new_sym_def) {
181
    lex.cur().error_at("cannot define symbol `", "`");
182
  }
183
  if (new_sym_def->value) {
184
    lex.cur().error_at("redefined formal parameter `", "`");
185
  }
186
  new_sym_def->value = new SymVal{SymVal::_Param, fa_idx, arg_type};
187
  lex.next();
188
  return std::make_tuple(arg_type, new_sym_def, loc);
189
}
190

191
void parse_global_var_decl(Lexer& lex) {
192
  TypeExpr* var_type = 0;
193
  SrcLocation loc = lex.cur().loc;
194
  if (lex.tp() == '_') {
195
    lex.next();
196
    var_type = TypeExpr::new_hole();
197
    loc = lex.cur().loc;
198
  } else if (lex.tp() != _Ident) {
199
    var_type = parse_type(lex);
200
  } else {
201
    auto sym = sym::lookup_symbol(lex.cur().val);
202
    if (sym && dynamic_cast<SymValType*>(sym->value)) {
203
      auto val = dynamic_cast<SymValType*>(sym->value);
204
      lex.next();
205
      var_type = val->get_type();
206
    } else {
207
      var_type = TypeExpr::new_hole();
208
    }
209
  }
210
  if (lex.tp() != _Ident) {
211
    lex.expect(_Ident, "global variable name");
212
  }
213
  loc = lex.cur().loc;
214
  SymDef* sym_def = sym::define_global_symbol(lex.cur().val, false, loc);
215
  if (!sym_def) {
216
    lex.cur().error_at("cannot define global symbol `", "`");
217
  }
218
  if (sym_def->value) {
219
    auto val = dynamic_cast<SymValGlobVar*>(sym_def->value);
220
    if (!val) {
221
      lex.cur().error_at("symbol `", "` cannot be redefined as a global variable");
222
    }
223
    try {
224
      unify(var_type, val->sym_type);
225
    } catch (UnifyError& ue) {
226
      std::ostringstream os;
227
      os << "cannot unify new type " << var_type << " of global variable `" << sym_def->name()
228
         << "` with its previous type " << val->sym_type << ": " << ue;
229
      lex.cur().error(os.str());
230
    }
231
  } else {
232
    sym_def->value = new SymValGlobVar{glob_var_cnt++, var_type};
233
    glob_vars.push_back(sym_def);
234
  }
235
  lex.next();
236
}
237

238
extern int const_cnt;
239
Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv = false);
240

241
void parse_const_decl(Lexer& lex) {
242
  SrcLocation loc = lex.cur().loc;
243
  int wanted_type = Expr::_None;
244
  if (lex.tp() == _Int) {
245
    wanted_type = Expr::_Const;
246
    lex.next();
247
  } else if (lex.tp() == _Slice) {
248
    wanted_type = Expr::_SliceConst;
249
    lex.next();
250
  }
251
  if (lex.tp() != _Ident) {
252
    lex.expect(_Ident, "constant name");
253
  }
254
  loc = lex.cur().loc;
255
  SymDef* sym_def = sym::define_global_symbol(lex.cur().val, false, loc);
256
  if (!sym_def) {
257
    lex.cur().error_at("cannot define global symbol `", "`");
258
  }
259
  Lexem ident = lex.cur();
260
  lex.next();
261
  if (lex.tp() != '=') {
262
    lex.cur().error_at("expected = instead of ", "");
263
  }
264
  lex.next();
265
  CodeBlob code;
266
  if (pragma_allow_post_modification.enabled()) {
267
    code.flags |= CodeBlob::_AllowPostModification;
268
  }
269
  if (pragma_compute_asm_ltr.enabled()) {
270
    code.flags |= CodeBlob::_ComputeAsmLtr;
271
  }
272
  // Handles processing and resolution of literals and consts
273
  auto x = parse_expr(lex, code, false); // also does lex.next() !
274
  if (x->flags != Expr::_IsRvalue) {
275
    lex.cur().error("expression is not strictly Rvalue");
276
  }
277
  if ((wanted_type == Expr::_Const) && (x->cls == Expr::_Apply))
278
    wanted_type = Expr::_None; // Apply is additionally checked to result in an integer
279
  if ((wanted_type != Expr::_None) && (x->cls != wanted_type)) {
280
    lex.cur().error("expression type does not match wanted type");
281
  }
282
  SymValConst* new_value = nullptr;
283
  if (x->cls == Expr::_Const) { // Integer constant
284
    new_value = new SymValConst{const_cnt++, x->intval};
285
  } else if (x->cls == Expr::_SliceConst) { // Slice constant (string)
286
    new_value = new SymValConst{const_cnt++, x->strval};
287
  } else if (x->cls == Expr::_Apply) {
288
    code.emplace_back(loc, Op::_Import, std::vector<var_idx_t>());
289
    auto tmp_vars = x->pre_compile(code);
290
    code.emplace_back(loc, Op::_Return, std::move(tmp_vars));
291
    code.emplace_back(loc, Op::_Nop); // This is neccessary to prevent SIGSEGV!
292
    // It is REQUIRED to execute "optimizations" as in func.cpp
293
    code.simplify_var_types();
294
    code.prune_unreachable_code();
295
    code.split_vars(true);
296
    for (int i = 0; i < 16; i++) {
297
      code.compute_used_code_vars();
298
      code.fwd_analyze();
299
      code.prune_unreachable_code();
300
    }
301
    code.mark_noreturn();
302
    AsmOpList out_list(0, &code.vars);
303
    code.generate_code(out_list);
304
    if (out_list.list_.size() != 1) {
305
      lex.cur().error("precompiled expression must result in single operation");
306
    }
307
    auto op = out_list.list_[0];
308
    if (!op.is_const()) {
309
      lex.cur().error("precompiled expression must result in compilation time constant");
310
    }
311
    if (op.origin.is_null() || !op.origin->is_valid()) {
312
      lex.cur().error("precompiled expression did not result in a valid integer constant");
313
    }
314
    new_value = new SymValConst{const_cnt++, op.origin};
315
  } else {
316
    lex.cur().error("integer or slice literal or constant expected");
317
  }
318
  if (sym_def->value) {
319
    SymValConst* old_value = dynamic_cast<SymValConst*>(sym_def->value);
320
    Keyword new_type = new_value->get_type();
321
    if (!old_value || old_value->get_type() != new_type ||
322
        (new_type == _Int && *old_value->get_int_value() != *new_value->get_int_value()) ||
323
        (new_type == _Slice && old_value->get_str_value() != new_value->get_str_value())) {
324
      ident.error_at("global symbol `", "` already exists");
325
    }
326
  }
327
  sym_def->value = new_value;
328
}
329

330
FormalArgList parse_formal_args(Lexer& lex) {
331
  FormalArgList args;
332
  lex.expect('(', "formal argument list");
333
  if (lex.tp() == ')') {
334
    lex.next();
335
    return args;
336
  }
337
  int fa_idx = 0;
338
  args.push_back(parse_formal_arg(lex, fa_idx++));
339
  while (lex.tp() == ',') {
340
    lex.next();
341
    args.push_back(parse_formal_arg(lex, fa_idx++));
342
  }
343
  lex.expect(')');
344
  return args;
345
}
346

347
void parse_const_decls(Lexer& lex) {
348
  lex.expect(_Const);
349
  while (true) {
350
    parse_const_decl(lex);
351
    if (lex.tp() != ',') {
352
      break;
353
    }
354
    lex.expect(',');
355
  }
356
  lex.expect(';');
357
}
358

359
TypeExpr* extract_total_arg_type(const FormalArgList& arg_list) {
360
  if (arg_list.empty()) {
361
    return TypeExpr::new_unit();
362
  }
363
  if (arg_list.size() == 1) {
364
    return std::get<0>(arg_list[0]);
365
  }
366
  std::vector<TypeExpr*> type_list;
367
  for (auto& x : arg_list) {
368
    type_list.push_back(std::get<0>(x));
369
  }
370
  return TypeExpr::new_tensor(std::move(type_list));
371
}
372

373
void parse_global_var_decls(Lexer& lex) {
374
  lex.expect(_Global);
375
  while (true) {
376
    parse_global_var_decl(lex);
377
    if (lex.tp() != ',') {
378
      break;
379
    }
380
    lex.expect(',');
381
  }
382
  lex.expect(';');
383
}
384

385
SymValCodeFunc* make_new_glob_func(SymDef* func_sym, TypeExpr* func_type, bool impure = false) {
386
  SymValCodeFunc* res = new SymValCodeFunc{glob_func_cnt, func_type, impure};
387
  func_sym->value = res;
388
  glob_func.push_back(func_sym);
389
  glob_func_cnt++;
390
  return res;
391
}
392

393
bool check_global_func(const Lexem& cur, sym_idx_t func_name = 0) {
394
  if (!func_name) {
395
    func_name = cur.val;
396
  }
397
  SymDef* def = sym::lookup_symbol(func_name);
398
  if (!def) {
399
    cur.loc.show_error(std::string{"undefined function `"} + symbols.get_name(func_name) +
400
                       "`, defining a global function of unknown type");
401
    def = sym::define_global_symbol(func_name, 0, cur.loc);
402
    func_assert(def && "cannot define global function");
403
    ++undef_func_cnt;
404
    make_new_glob_func(def, TypeExpr::new_func());  // was: ... ::new_func()
405
    return true;
406
  }
407
  SymVal* val = dynamic_cast<SymVal*>(def->value);
408
  if (!val) {
409
    cur.error(std::string{"symbol `"} + symbols.get_name(func_name) + "` has no value and no type");
410
    return false;
411
  } else if (!val->get_type()) {
412
    cur.error(std::string{"symbol `"} + symbols.get_name(func_name) + "` has no type, possibly not a function");
413
    return false;
414
  } else {
415
    return true;
416
  }
417
}
418

419
Expr* make_func_apply(Expr* fun, Expr* x) {
420
  Expr* res;
421
  if (fun->cls == Expr::_Glob) {
422
    if (x->cls == Expr::_Tensor) {
423
      res = new Expr{Expr::_Apply, fun->sym, x->args};
424
    } else {
425
      res = new Expr{Expr::_Apply, fun->sym, {x}};
426
    }
427
    res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure);
428
  } else {
429
    res = new Expr{Expr::_VarApply, {fun, x}};
430
    res->flags = Expr::_IsRvalue;
431
  }
432
  return res;
433
}
434

435
// parse ( E { , E } ) | () | [ E { , E } ] | [] | id | num | _
436
Expr* parse_expr100(Lexer& lex, CodeBlob& code, bool nv) {
437
  if (lex.tp() == '(' || lex.tp() == '[') {
438
    bool tf = (lex.tp() == '[');
439
    int clbr = (tf ? ']' : ')');
440
    SrcLocation loc{lex.cur().loc};
441
    lex.next();
442
    if (lex.tp() == clbr) {
443
      lex.next();
444
      Expr* res = new Expr{Expr::_Tensor, {}};
445
      res->flags = Expr::_IsRvalue;
446
      res->here = loc;
447
      res->e_type = TypeExpr::new_unit();
448
      if (tf) {
449
        res = new Expr{Expr::_MkTuple, {res}};
450
        res->flags = Expr::_IsRvalue;
451
        res->here = loc;
452
        res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type);
453
      }
454
      return res;
455
    }
456
    Expr* res = parse_expr(lex, code, nv);
457
    if (lex.tp() == ')') {
458
      lex.expect(clbr);
459
      return res;
460
    }
461
    std::vector<TypeExpr*> type_list;
462
    type_list.push_back(res->e_type);
463
    int f = res->flags;
464
    res = new Expr{Expr::_Tensor, {res}};
465
    while (lex.tp() == ',') {
466
      lex.next();
467
      auto x = parse_expr(lex, code, nv);
468
      res->pb_arg(x);
469
      if ((f ^ x->flags) & Expr::_IsType) {
470
        lex.cur().error("mixing type and non-type expressions inside the same tuple");
471
      }
472
      f &= x->flags;
473
      type_list.push_back(x->e_type);
474
    }
475
    res->here = loc;
476
    res->flags = f;
477
    res->e_type = TypeExpr::new_tensor(std::move(type_list), !tf);
478
    if (tf) {
479
      res = new Expr{Expr::_MkTuple, {res}};
480
      res->flags = f;
481
      res->here = loc;
482
      res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type);
483
    }
484
    lex.expect(clbr);
485
    return res;
486
  }
487
  int t = lex.tp();
488
  if (t == Lexem::Number) {
489
    Expr* res = new Expr{Expr::_Const, lex.cur().loc};
490
    res->flags = Expr::_IsRvalue;
491
    res->intval = td::string_to_int256(lex.cur().str);
492
    if (res->intval.is_null() || !res->intval->signed_fits_bits(257)) {
493
      lex.cur().error_at("invalid integer constant `", "`");
494
    }
495
    res->e_type = TypeExpr::new_atomic(_Int);
496
    lex.next();
497
    return res;
498
  }
499
  if (t == Lexem::String) {
500
    std::string str = lex.cur().str;
501
    int str_type = lex.cur().val;
502
    Expr* res;
503
    switch (str_type) {
504
      case 0:
505
      case 's':
506
      case 'a':
507
      {
508
        res = new Expr{Expr::_SliceConst, lex.cur().loc};
509
        res->e_type = TypeExpr::new_atomic(_Slice);
510
        break;
511
      }
512
      case 'u':
513
      case 'h':
514
      case 'H':
515
      case 'c':
516
      {
517
        res = new Expr{Expr::_Const, lex.cur().loc};
518
        res->e_type = TypeExpr::new_atomic(_Int);
519
        break;
520
      }
521
      default:
522
      {
523
        res = new Expr{Expr::_Const, lex.cur().loc};
524
        res->e_type = TypeExpr::new_atomic(_Int);
525
        lex.cur().error("invalid string type `" + std::string(1, static_cast<char>(str_type)) + "`");
526
        return res;
527
      }
528
    }
529
    res->flags = Expr::_IsRvalue;
530
    switch (str_type) {
531
      case 0: {
532
        res->strval = td::hex_encode(str);
533
        break;
534
      }
535
      case 's': {
536
        res->strval = str;
537
        unsigned char buff[128];
538
        int bits = (int)td::bitstring::parse_bitstring_hex_literal(buff, sizeof(buff), str.data(), str.data() + str.size());
539
        if (bits < 0) {
540
          lex.cur().error_at("Invalid hex bitstring constant `", "`");
541
        }
542
        break;
543
      }
544
      case 'a': {  // MsgAddressInt
545
        block::StdAddress a;
546
        if (a.parse_addr(str)) {
547
          res->strval = block::tlb::MsgAddressInt().pack_std_address(a)->as_bitslice().to_hex();
548
        } else {
549
          lex.cur().error_at("invalid standard address `", "`");
550
        }
551
        break;
552
      }
553
      case 'u': {
554
        res->intval = td::hex_string_to_int256(td::hex_encode(str));
555
        if (!str.size()) {
556
          lex.cur().error("empty integer ascii-constant");
557
        }
558
        if (res->intval.is_null()) {
559
          lex.cur().error_at("too long integer ascii-constant `", "`");
560
        }
561
        break;
562
      }
563
      case 'h':
564
      case 'H':
565
      {
566
        unsigned char hash[32];
567
        digest::hash_str<digest::SHA256>(hash, str.data(), str.size());
568
        res->intval = td::bits_to_refint(hash, (str_type == 'h') ? 32 : 256, false);
569
        break;
570
      }
571
      case 'c':
572
      {
573
        res->intval = td::make_refint(td::crc32(td::Slice{str}));
574
        break;
575
      }
576
    }
577
    lex.next();
578
    return res;
579
  }
580
  if (t == '_') {
581
    Expr* res = new Expr{Expr::_Hole, lex.cur().loc};
582
    res->val = -1;
583
    res->flags = (Expr::_IsLvalue | Expr::_IsHole | Expr::_IsNewVar);
584
    res->e_type = TypeExpr::new_hole();
585
    lex.next();
586
    return res;
587
  }
588
  if (t == _Var) {
589
    Expr* res = new Expr{Expr::_Type, lex.cur().loc};
590
    res->flags = Expr::_IsType;
591
    res->e_type = TypeExpr::new_hole();
592
    lex.next();
593
    return res;
594
  }
595
  if (t == _Int || t == _Cell || t == _Slice || t == _Builder || t == _Cont || t == _Type || t == _Tuple) {
596
    Expr* res = new Expr{Expr::_Type, lex.cur().loc};
597
    res->flags = Expr::_IsType;
598
    res->e_type = TypeExpr::new_atomic(t);
599
    lex.next();
600
    return res;
601
  }
602
  if (t == _Ident) {
603
    auto sym = sym::lookup_symbol(lex.cur().val);
604
    if (sym && dynamic_cast<SymValType*>(sym->value)) {
605
      auto val = dynamic_cast<SymValType*>(sym->value);
606
      Expr* res = new Expr{Expr::_Type, lex.cur().loc};
607
      res->flags = Expr::_IsType;
608
      res->e_type = val->get_type();
609
      lex.next();
610
      return res;
611
    }
612
    if (sym && dynamic_cast<SymValGlobVar*>(sym->value)) {
613
      auto val = dynamic_cast<SymValGlobVar*>(sym->value);
614
      Expr* res = new Expr{Expr::_GlobVar, lex.cur().loc};
615
      res->e_type = val->get_type();
616
      res->sym = sym;
617
      res->flags = Expr::_IsLvalue | Expr::_IsRvalue | Expr::_IsImpure;
618
      lex.next();
619
      return res;
620
    }
621
    if (sym && dynamic_cast<SymValConst*>(sym->value)) {
622
      auto val = dynamic_cast<SymValConst*>(sym->value);
623
      Expr* res = new Expr{Expr::_None, lex.cur().loc};
624
      res->flags = Expr::_IsRvalue;
625
      if (val->type == _Int) {
626
        res->cls = Expr::_Const;
627
        res->intval = val->get_int_value();
628
      }
629
      else if (val->type == _Slice) {
630
        res->cls = Expr::_SliceConst;
631
        res->strval = val->get_str_value();
632
      }
633
      else {
634
        lex.cur().error("Invalid symbolic constant type");
635
      }
636
      res->e_type = TypeExpr::new_atomic(val->type);
637
      lex.next();
638
      return res;
639
    }
640
    bool auto_apply = false;
641
    Expr* res = new Expr{Expr::_Var, lex.cur().loc};
642
    if (nv) {
643
      res->val = ~lex.cur().val;
644
      res->e_type = TypeExpr::new_hole();
645
      res->flags = Expr::_IsLvalue | Expr::_IsNewVar;
646
      // std::cerr << "defined new variable " << lex.cur().str << " : " << res->e_type << std::endl;
647
    } else {
648
      if (!sym) {
649
        check_global_func(lex.cur());
650
        sym = sym::lookup_symbol(lex.cur().val);
651
      }
652
      res->sym = sym;
653
      SymVal* val = nullptr;
654
      if (sym) {
655
        val = dynamic_cast<SymVal*>(sym->value);
656
      }
657
      if (!val) {
658
        lex.cur().error_at("undefined identifier `", "`");
659
      } else if (val->type == SymVal::_Func) {
660
        res->e_type = val->get_type();
661
        res->cls = Expr::_Glob;
662
        auto_apply = val->auto_apply;
663
      } else if (val->idx < 0) {
664
        lex.cur().error_at("accessing variable `", "` being defined");
665
      } else {
666
        res->val = val->idx;
667
        res->e_type = val->get_type();
668
        // std::cerr << "accessing variable " << lex.cur().str << " : " << res->e_type << std::endl;
669
      }
670
      // std::cerr << "accessing symbol " << lex.cur().str << " : " << res->e_type << (val->impure ? " (impure)" : " (pure)") << std::endl;
671
      res->flags = Expr::_IsLvalue | Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
672
    }
673
    if (auto_apply) {
674
      int impure = res->flags & Expr::_IsImpure;
675
      delete res;
676
      res = new Expr{Expr::_Apply, sym, {}};
677
      res->flags = Expr::_IsRvalue | impure;
678
    }
679
    res->deduce_type(lex.cur());
680
    lex.next();
681
    return res;
682
  }
683
  lex.expect(Lexem::Ident);
684
  return nullptr;
685
}
686

687
// parse E { E }
688
Expr* parse_expr90(Lexer& lex, CodeBlob& code, bool nv) {
689
  Expr* res = parse_expr100(lex, code, nv);
690
  while (lex.tp() == '(' || lex.tp() == '[' || (lex.tp() == _Ident && !is_special_ident(lex.cur().val))) {
691
    if (res->is_type()) {
692
      Expr* x = parse_expr100(lex, code, true);
693
      x->chk_lvalue(lex.cur());  // chk_lrvalue() ?
694
      TypeExpr* tp = res->e_type;
695
      delete res;
696
      res = new Expr{Expr::_TypeApply, {x}};
697
      res->e_type = tp;
698
      res->here = lex.cur().loc;
699
      try {
700
        unify(res->e_type, x->e_type);
701
      } catch (UnifyError& ue) {
702
        std::ostringstream os;
703
        os << "cannot transform expression of type " << x->e_type << " to explicitly requested type " << res->e_type
704
           << ": " << ue;
705
        lex.cur().error(os.str());
706
      }
707
      res->flags = x->flags;
708
    } else {
709
      Expr* x = parse_expr100(lex, code, false);
710
      x->chk_rvalue(lex.cur());
711
      res = make_func_apply(res, x);
712
      res->here = lex.cur().loc;
713
      res->deduce_type(lex.cur());
714
    }
715
  }
716
  return res;
717
}
718

719
// parse E { .method E | ~method E }
720
Expr* parse_expr80(Lexer& lex, CodeBlob& code, bool nv) {
721
  Expr* res = parse_expr90(lex, code, nv);
722
  while (lex.tp() == _Ident && is_special_ident(lex.cur().val)) {
723
    auto modify = is_tilde_ident(lex.cur().val);
724
    auto obj = res;
725
    if (modify) {
726
      obj->chk_lvalue(lex.cur());
727
    } else {
728
      obj->chk_rvalue(lex.cur());
729
    }
730
    auto loc = lex.cur().loc;
731
    auto name = lex.cur().val;
732
    auto sym = sym::lookup_symbol(name);
733
    if (!sym || !dynamic_cast<SymValFunc*>(sym->value)) {
734
      auto name1 = symbols.lookup(lex.cur().str.substr(1));
735
      if (name1) {
736
        auto sym1 = sym::lookup_symbol(name1);
737
        if (sym1 && dynamic_cast<SymValFunc*>(sym1->value)) {
738
          name = name1;
739
          sym = sym1;
740
        }
741
      }
742
    }
743
    check_global_func(lex.cur(), name);
744
    if (verbosity >= 2) {
745
      std::cerr << "using symbol `" << symbols.get_name(name) << "` for method call of " << lex.cur().str << std::endl;
746
    }
747
    sym = sym::lookup_symbol(name);
748
    SymValFunc* val = sym ? dynamic_cast<SymValFunc*>(sym->value) : nullptr;
749
    if (!val) {
750
      lex.cur().error_at("undefined method identifier `", "`");
751
    }
752
    lex.next();
753
    auto x = parse_expr100(lex, code, false);
754
    x->chk_rvalue(lex.cur());
755
    if (x->cls == Expr::_Tensor) {
756
      res = new Expr{Expr::_Apply, name, {obj}};
757
      res->args.insert(res->args.end(), x->args.begin(), x->args.end());
758
    } else {
759
      res = new Expr{Expr::_Apply, name, {obj, x}};
760
    }
761
    res->here = loc;
762
    res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
763
    res->deduce_type(lex.cur());
764
    if (modify) {
765
      auto tmp = res;
766
      res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}};
767
      res->here = loc;
768
      res->flags = tmp->flags;
769
      res->set_val(name);
770
      res->deduce_type(lex.cur());
771
    }
772
  }
773
  return res;
774
}
775

776
// parse [ ~ ] E
777
Expr* parse_expr75(Lexer& lex, CodeBlob& code, bool nv) {
778
  if (lex.tp() == '~') {
779
    sym_idx_t name = symbols.lookup_add("~_");
780
    check_global_func(lex.cur(), name);
781
    SrcLocation loc{lex.cur().loc};
782
    lex.next();
783
    auto x = parse_expr80(lex, code, false);
784
    x->chk_rvalue(lex.cur());
785
    auto res = new Expr{Expr::_Apply, name, {x}};
786
    res->here = loc;
787
    res->set_val('~');
788
    res->flags = Expr::_IsRvalue;
789
    res->deduce_type(lex.cur());
790
    return res;
791
  } else {
792
    return parse_expr80(lex, code, nv);
793
  }
794
}
795

796
// parse E { (* | / | % | /% ) E }
797
Expr* parse_expr30(Lexer& lex, CodeBlob& code, bool nv) {
798
  Expr* res = parse_expr75(lex, code, nv);
799
  while (lex.tp() == '*' || lex.tp() == '/' || lex.tp() == '%' || lex.tp() == _DivMod || lex.tp() == _DivC ||
800
         lex.tp() == _DivR || lex.tp() == _ModC || lex.tp() == _ModR || lex.tp() == '&') {
801
    res->chk_rvalue(lex.cur());
802
    int t = lex.tp();
803
    sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
804
    SrcLocation loc{lex.cur().loc};
805
    check_global_func(lex.cur(), name);
806
    lex.next();
807
    auto x = parse_expr75(lex, code, false);
808
    x->chk_rvalue(lex.cur());
809
    res = new Expr{Expr::_Apply, name, {res, x}};
810
    res->here = loc;
811
    res->set_val(t);
812
    res->flags = Expr::_IsRvalue;
813
    res->deduce_type(lex.cur());
814
  }
815
  return res;
816
}
817

818
// parse [-] E { (+ | - | `|` | ^) E }
819
Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
820
  Expr* res;
821
  int t = lex.tp();
822
  if (t == '-') {
823
    sym_idx_t name = symbols.lookup_add("-_");
824
    check_global_func(lex.cur(), name);
825
    SrcLocation loc{lex.cur().loc};
826
    lex.next();
827
    auto x = parse_expr30(lex, code, false);
828
    x->chk_rvalue(lex.cur());
829
    res = new Expr{Expr::_Apply, name, {x}};
830
    res->here = loc;
831
    res->set_val(t);
832
    res->flags = Expr::_IsRvalue;
833
    res->deduce_type(lex.cur());
834
  } else {
835
    res = parse_expr30(lex, code, nv);
836
  }
837
  while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|' || lex.tp() == '^') {
838
    res->chk_rvalue(lex.cur());
839
    t = lex.tp();
840
    sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
841
    check_global_func(lex.cur(), name);
842
    SrcLocation loc{lex.cur().loc};
843
    lex.next();
844
    auto x = parse_expr30(lex, code, false);
845
    x->chk_rvalue(lex.cur());
846
    res = new Expr{Expr::_Apply, name, {res, x}};
847
    res->here = loc;
848
    res->set_val(t);
849
    res->flags = Expr::_IsRvalue;
850
    res->deduce_type(lex.cur());
851
  }
852
  return res;
853
}
854

855
// parse E { ( << | >> | >>~ | >>^ ) E }
856
Expr* parse_expr17(Lexer& lex, CodeBlob& code, bool nv) {
857
  Expr* res = parse_expr20(lex, code, nv);
858
  while (lex.tp() == _Lshift || lex.tp() == _Rshift || lex.tp() == _RshiftC || lex.tp() == _RshiftR) {
859
    res->chk_rvalue(lex.cur());
860
    int t = lex.tp();
861
    sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
862
    check_global_func(lex.cur(), name);
863
    SrcLocation loc{lex.cur().loc};
864
    lex.next();
865
    auto x = parse_expr20(lex, code, false);
866
    x->chk_rvalue(lex.cur());
867
    res = new Expr{Expr::_Apply, name, {res, x}};
868
    res->here = loc;
869
    res->set_val(t);
870
    res->flags = Expr::_IsRvalue;
871
    res->deduce_type(lex.cur());
872
  }
873
  return res;
874
}
875

876
// parse E [ (== | < | > | <= | >= | != | <=> ) E ]
877
Expr* parse_expr15(Lexer& lex, CodeBlob& code, bool nv) {
878
  Expr* res = parse_expr17(lex, code, nv);
879
  if (lex.tp() == _Eq || lex.tp() == '<' || lex.tp() == '>' || lex.tp() == _Leq || lex.tp() == _Geq ||
880
      lex.tp() == _Neq || lex.tp() == _Spaceship) {
881
    res->chk_rvalue(lex.cur());
882
    int t = lex.tp();
883
    sym_idx_t name = symbols.lookup_add(std::string{"_"} + lex.cur().str + "_");
884
    check_global_func(lex.cur(), name);
885
    SrcLocation loc{lex.cur().loc};
886
    lex.next();
887
    auto x = parse_expr17(lex, code, false);
888
    x->chk_rvalue(lex.cur());
889
    res = new Expr{Expr::_Apply, name, {res, x}};
890
    res->here = loc;
891
    res->set_val(t);
892
    res->flags = Expr::_IsRvalue;
893
    res->deduce_type(lex.cur());
894
  }
895
  return res;
896
}
897

898
// parse E [ ? E : E ]
899
Expr* parse_expr13(Lexer& lex, CodeBlob& code, bool nv) {
900
  Expr* res = parse_expr15(lex, code, nv);
901
  if (lex.tp() == '?') {
902
    res->chk_rvalue(lex.cur());
903
    SrcLocation loc{lex.cur().loc};
904
    lex.next();
905
    auto x = parse_expr(lex, code, false);
906
    x->chk_rvalue(lex.cur());
907
    lex.expect(':');
908
    auto y = parse_expr13(lex, code, false);
909
    y->chk_rvalue(lex.cur());
910
    res = new Expr{Expr::_CondExpr, {res, x, y}};
911
    res->here = loc;
912
    res->flags = Expr::_IsRvalue;
913
    res->deduce_type(lex.cur());
914
  }
915
  return res;
916
}
917

918
// parse LE1 (= | += | -= | ... ) E2
919
Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) {
920
  auto x = parse_expr13(lex, code, nv);
921
  int t = lex.tp();
922
  if (t == _PlusLet || t == _MinusLet || t == _TimesLet || t == _DivLet || t == _DivRLet || t == _DivCLet ||
923
      t == _ModLet || t == _ModCLet || t == _ModRLet || t == _LshiftLet || t == _RshiftLet || t == _RshiftCLet ||
924
      t == _RshiftRLet || t == _AndLet || t == _OrLet || t == _XorLet) {
925
    x->chk_lvalue(lex.cur());
926
    x->chk_rvalue(lex.cur());
927
    sym_idx_t name = symbols.lookup_add(std::string{"^_"} + lex.cur().str + "_");
928
    check_global_func(lex.cur(), name);
929
    SrcLocation loc{lex.cur().loc};
930
    lex.next();
931
    auto y = parse_expr10(lex, code, false);
932
    y->chk_rvalue(lex.cur());
933
    Expr* z = new Expr{Expr::_Apply, name, {x, y}};
934
    z->here = loc;
935
    z->set_val(t);
936
    z->flags = Expr::_IsRvalue;
937
    z->deduce_type(lex.cur());
938
    Expr* res = new Expr{Expr::_Letop, {x->copy(), z}};
939
    res->here = loc;
940
    res->flags = (x->flags & ~Expr::_IsType) | Expr::_IsRvalue;
941
    res->set_val(t);
942
    res->deduce_type(lex.cur());
943
    return res;
944
  } else if (t == '=') {
945
    x->chk_lvalue(lex.cur());
946
    SrcLocation loc{lex.cur().loc};
947
    lex.next();
948
    auto y = parse_expr10(lex, code, false);
949
    y->chk_rvalue(lex.cur());
950
    x->predefine_vars();
951
    x->define_new_vars(code);
952
    Expr* res = new Expr{Expr::_Letop, {x, y}};
953
    res->here = loc;
954
    res->flags = (x->flags & ~Expr::_IsType) | Expr::_IsRvalue;
955
    res->set_val(t);
956
    res->deduce_type(lex.cur());
957
    return res;
958
  } else {
959
    return x;
960
  }
961
}
962

963
Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv) {
964
  return parse_expr10(lex, code, nv);
965
}
966

967
namespace blk_fl {
968
enum { end = 1, ret = 2, empty = 4 };
969
typedef int val;
970
constexpr val init = end | empty;
971
void combine(val& x, const val y) {
972
  x |= y & ret;
973
  x &= y | ~(end | empty);
974
}
975
void combine_parallel(val& x, const val y) {
976
  x &= y | ~(ret | empty);
977
  x |= y & end;
978
}
979
}  // namespace blk_fl
980

981
blk_fl::val parse_return_stmt(Lexer& lex, CodeBlob& code) {
982
  auto expr = parse_expr(lex, code);
983
  expr->chk_rvalue(lex.cur());
984
  try {
985
    // std::cerr << "in return: ";
986
    unify(expr->e_type, code.ret_type);
987
  } catch (UnifyError& ue) {
988
    std::ostringstream os;
989
    os << "previous function return type " << code.ret_type
990
       << " cannot be unified with return statement expression type " << expr->e_type << ": " << ue;
991
    lex.cur().error(os.str());
992
  }
993
  std::vector<var_idx_t> tmp_vars = expr->pre_compile(code);
994
  code.emplace_back(lex.cur().loc, Op::_Return, std::move(tmp_vars));
995
  lex.expect(';');
996
  return blk_fl::ret;
997
}
998

999
blk_fl::val parse_implicit_ret_stmt(Lexer& lex, CodeBlob& code) {
1000
  auto ret_type = TypeExpr::new_unit();
1001
  try {
1002
    // std::cerr << "in implicit return: ";
1003
    unify(ret_type, code.ret_type);
1004
  } catch (UnifyError& ue) {
1005
    std::ostringstream os;
1006
    os << "previous function return type " << code.ret_type
1007
       << " cannot be unified with implicit end-of-block return type " << ret_type << ": " << ue;
1008
    lex.cur().error(os.str());
1009
  }
1010
  code.emplace_back(lex.cur().loc, Op::_Return);
1011
  return blk_fl::ret;
1012
}
1013

1014
blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code);
1015

1016
blk_fl::val parse_block_stmt(Lexer& lex, CodeBlob& code, bool no_new_scope = false) {
1017
  lex.expect('{');
1018
  if (!no_new_scope) {
1019
    sym::open_scope(lex);
1020
  }
1021
  blk_fl::val res = blk_fl::init;
1022
  bool warned = false;
1023
  while (lex.tp() != '}') {
1024
    if (!(res & blk_fl::end) && !warned) {
1025
      lex.cur().loc.show_warning("unreachable code");
1026
      warned = true;
1027
    }
1028
    blk_fl::combine(res, parse_stmt(lex, code));
1029
  }
1030
  if (!no_new_scope) {
1031
    sym::close_scope(lex);
1032
  }
1033
  lex.expect('}');
1034
  return res;
1035
}
1036

1037
blk_fl::val parse_repeat_stmt(Lexer& lex, CodeBlob& code) {
1038
  SrcLocation loc{lex.cur().loc};
1039
  lex.expect(_Repeat);
1040
  auto expr = parse_expr(lex, code);
1041
  expr->chk_rvalue(lex.cur());
1042
  auto cnt_type = TypeExpr::new_atomic(_Int);
1043
  try {
1044
    unify(expr->e_type, cnt_type);
1045
  } catch (UnifyError& ue) {
1046
    std::ostringstream os;
1047
    os << "repeat count value of type " << expr->e_type << " is not an integer: " << ue;
1048
    lex.cur().error(os.str());
1049
  }
1050
  std::vector<var_idx_t> tmp_vars = expr->pre_compile(code);
1051
  if (tmp_vars.size() != 1) {
1052
    lex.cur().error("repeat count value is not a singleton");
1053
  }
1054
  Op& repeat_op = code.emplace_back(loc, Op::_Repeat, tmp_vars);
1055
  code.push_set_cur(repeat_op.block0);
1056
  blk_fl::val res = parse_block_stmt(lex, code);
1057
  code.close_pop_cur(lex.cur().loc);
1058
  return res | blk_fl::end;
1059
}
1060

1061
blk_fl::val parse_while_stmt(Lexer& lex, CodeBlob& code) {
1062
  SrcLocation loc{lex.cur().loc};
1063
  lex.expect(_While);
1064
  auto expr = parse_expr(lex, code);
1065
  expr->chk_rvalue(lex.cur());
1066
  auto cnt_type = TypeExpr::new_atomic(_Int);
1067
  try {
1068
    unify(expr->e_type, cnt_type);
1069
  } catch (UnifyError& ue) {
1070
    std::ostringstream os;
1071
    os << "while condition value of type " << expr->e_type << " is not an integer: " << ue;
1072
    lex.cur().error(os.str());
1073
  }
1074
  Op& while_op = code.emplace_back(loc, Op::_While);
1075
  code.push_set_cur(while_op.block0);
1076
  while_op.left = expr->pre_compile(code);
1077
  code.close_pop_cur(lex.cur().loc);
1078
  if (while_op.left.size() != 1) {
1079
    lex.cur().error("while condition value is not a singleton");
1080
  }
1081
  code.push_set_cur(while_op.block1);
1082
  blk_fl::val res1 = parse_block_stmt(lex, code);
1083
  code.close_pop_cur(lex.cur().loc);
1084
  return res1 | blk_fl::end;
1085
}
1086

1087
blk_fl::val parse_do_stmt(Lexer& lex, CodeBlob& code) {
1088
  Op& while_op = code.emplace_back(lex.cur().loc, Op::_Until);
1089
  lex.expect(_Do);
1090
  code.push_set_cur(while_op.block0);
1091
  sym::open_scope(lex);
1092
  blk_fl::val res = parse_block_stmt(lex, code, true);
1093
  lex.expect(_Until);
1094
  auto expr = parse_expr(lex, code);
1095
  expr->chk_rvalue(lex.cur());
1096
  sym::close_scope(lex);
1097
  auto cnt_type = TypeExpr::new_atomic(_Int);
1098
  try {
1099
    unify(expr->e_type, cnt_type);
1100
  } catch (UnifyError& ue) {
1101
    std::ostringstream os;
1102
    os << "`until` condition value of type " << expr->e_type << " is not an integer: " << ue;
1103
    lex.cur().error(os.str());
1104
  }
1105
  while_op.left = expr->pre_compile(code);
1106
  code.close_pop_cur(lex.cur().loc);
1107
  if (while_op.left.size() != 1) {
1108
    lex.cur().error("`until` condition value is not a singleton");
1109
  }
1110
  return res & ~blk_fl::empty;
1111
}
1112

1113
blk_fl::val parse_try_catch_stmt(Lexer& lex, CodeBlob& code) {
1114
  code.require_callxargs = true;
1115
  lex.expect(_Try);
1116
  Op& try_catch_op = code.emplace_back(lex.cur().loc, Op::_TryCatch);
1117
  code.push_set_cur(try_catch_op.block0);
1118
  blk_fl::val res0 = parse_block_stmt(lex, code);
1119
  code.close_pop_cur(lex.cur().loc);
1120
  lex.expect(_Catch);
1121
  code.push_set_cur(try_catch_op.block1);
1122
  sym::open_scope(lex);
1123
  Expr* expr = parse_expr(lex, code, true);
1124
  expr->chk_lvalue(lex.cur());
1125
  TypeExpr* tvm_error_type = TypeExpr::new_tensor(TypeExpr::new_var(), TypeExpr::new_atomic(_Int));
1126
  try {
1127
    unify(expr->e_type, tvm_error_type);
1128
  } catch (UnifyError& ue) {
1129
    std::ostringstream os;
1130
    os << "`catch` arguments have incorrect type " << expr->e_type << ": " << ue;
1131
    lex.cur().error(os.str());
1132
  }
1133
  expr->predefine_vars();
1134
  expr->define_new_vars(code);
1135
  try_catch_op.left = expr->pre_compile(code);
1136
  func_assert(try_catch_op.left.size() == 2 || try_catch_op.left.size() == 1);
1137
  blk_fl::val res1 = parse_block_stmt(lex, code);
1138
  sym::close_scope(lex);
1139
  code.close_pop_cur(lex.cur().loc);
1140
  blk_fl::combine_parallel(res0, res1);
1141
  return res0;
1142
}
1143

1144
blk_fl::val parse_if_stmt(Lexer& lex, CodeBlob& code, int first_lex = _If) {
1145
  SrcLocation loc{lex.cur().loc};
1146
  lex.expect(first_lex);
1147
  auto expr = parse_expr(lex, code);
1148
  expr->chk_rvalue(lex.cur());
1149
  auto flag_type = TypeExpr::new_atomic(_Int);
1150
  try {
1151
    unify(expr->e_type, flag_type);
1152
  } catch (UnifyError& ue) {
1153
    std::ostringstream os;
1154
    os << "`if` condition value of type " << expr->e_type << " is not an integer: " << ue;
1155
    lex.cur().error(os.str());
1156
  }
1157
  std::vector<var_idx_t> tmp_vars = expr->pre_compile(code);
1158
  if (tmp_vars.size() != 1) {
1159
    lex.cur().error("condition value is not a singleton");
1160
  }
1161
  Op& if_op = code.emplace_back(loc, Op::_If, tmp_vars);
1162
  code.push_set_cur(if_op.block0);
1163
  blk_fl::val res1 = parse_block_stmt(lex, code);
1164
  blk_fl::val res2 = blk_fl::init;
1165
  code.close_pop_cur(lex.cur().loc);
1166
  if (lex.tp() == _Else) {
1167
    lex.expect(_Else);
1168
    code.push_set_cur(if_op.block1);
1169
    res2 = parse_block_stmt(lex, code);
1170
    code.close_pop_cur(lex.cur().loc);
1171
  } else if (lex.tp() == _Elseif || lex.tp() == _Elseifnot) {
1172
    code.push_set_cur(if_op.block1);
1173
    res2 = parse_if_stmt(lex, code, lex.tp());
1174
    code.close_pop_cur(lex.cur().loc);
1175
  } else {
1176
    if_op.block1 = std::make_unique<Op>(lex.cur().loc, Op::_Nop);
1177
  }
1178
  if (first_lex == _Ifnot || first_lex == _Elseifnot) {
1179
    std::swap(if_op.block0, if_op.block1);
1180
  }
1181
  blk_fl::combine_parallel(res1, res2);
1182
  return res1;
1183
}
1184

1185
blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code) {
1186
  switch (lex.tp()) {
1187
    case _Return: {
1188
      lex.next();
1189
      return parse_return_stmt(lex, code);
1190
    }
1191
    case '{': {
1192
      return parse_block_stmt(lex, code);
1193
    }
1194
    case ';': {
1195
      lex.next();
1196
      return blk_fl::init;
1197
    }
1198
    case _Repeat:
1199
      return parse_repeat_stmt(lex, code);
1200
    case _If:
1201
    case _Ifnot:
1202
      return parse_if_stmt(lex, code, lex.tp());
1203
    case _Do:
1204
      return parse_do_stmt(lex, code);
1205
    case _While:
1206
      return parse_while_stmt(lex, code);
1207
    case _Try:
1208
      return parse_try_catch_stmt(lex, code);
1209
    default: {
1210
      auto expr = parse_expr(lex, code);
1211
      expr->chk_rvalue(lex.cur());
1212
      expr->pre_compile(code);
1213
      lex.expect(';');
1214
      return blk_fl::end;
1215
    }
1216
  }
1217
}
1218

1219
CodeBlob* parse_func_body(Lexer& lex, FormalArgList arg_list, TypeExpr* ret_type) {
1220
  lex.expect('{');
1221
  CodeBlob* blob = new CodeBlob{ret_type};
1222
  if (pragma_allow_post_modification.enabled()) {
1223
    blob->flags |= CodeBlob::_AllowPostModification;
1224
  }
1225
  if (pragma_compute_asm_ltr.enabled()) {
1226
    blob->flags |= CodeBlob::_ComputeAsmLtr;
1227
  }
1228
  blob->import_params(std::move(arg_list));
1229
  blk_fl::val res = blk_fl::init;
1230
  bool warned = false;
1231
  while (lex.tp() != '}') {
1232
    if (!(res & blk_fl::end) && !warned) {
1233
      lex.cur().loc.show_warning("unreachable code");
1234
      warned = true;
1235
    }
1236
    blk_fl::combine(res, parse_stmt(lex, *blob));
1237
  }
1238
  if (res & blk_fl::end) {
1239
    parse_implicit_ret_stmt(lex, *blob);
1240
  }
1241
  blob->close_blk(lex.cur().loc);
1242
  lex.expect('}');
1243
  return blob;
1244
}
1245

1246
SymValAsmFunc* parse_asm_func_body(Lexer& lex, TypeExpr* func_type, const FormalArgList& arg_list, TypeExpr* ret_type,
1247
                                   bool impure = false) {
1248
  auto loc = lex.cur().loc;
1249
  lex.expect(_Asm);
1250
  int cnt = (int)arg_list.size();
1251
  int width = ret_type->get_width();
1252
  if (width < 0 || width > 16) {
1253
    throw src::ParseError{loc, "return type of an assembler built-in function must have a well-defined fixed width"};
1254
  }
1255
  if (arg_list.size() > 16) {
1256
    throw src::ParseError{loc, "assembler built-in function must have at most 16 arguments"};
1257
  }
1258
  std::vector<int> cum_arg_width;
1259
  cum_arg_width.push_back(0);
1260
  int tot_width = 0;
1261
  for (auto& arg : arg_list) {
1262
    int arg_width = std::get<TypeExpr*>(arg)->get_width();
1263
    if (arg_width < 0 || arg_width > 16) {
1264
      throw src::ParseError{std::get<SrcLocation>(arg),
1265
                            "parameters of an assembler built-in function must have a well-defined fixed width"};
1266
    }
1267
    cum_arg_width.push_back(tot_width += arg_width);
1268
  }
1269
  std::vector<AsmOp> asm_ops;
1270
  std::vector<int> arg_order, ret_order;
1271
  if (lex.tp() == '(') {
1272
    lex.expect('(');
1273
    if (lex.tp() != _Mapsto) {
1274
      std::vector<bool> visited(cnt, false);
1275
      for (int i = 0; i < cnt; i++) {
1276
        if (lex.tp() != _Ident) {
1277
          lex.expect(_Ident);
1278
        }
1279
        auto sym = sym::lookup_symbol(lex.cur().val);
1280
        int j;
1281
        for (j = 0; j < cnt; j++) {
1282
          if (std::get<SymDef*>(arg_list[j]) == sym) {
1283
            break;
1284
          }
1285
        }
1286
        if (j == cnt) {
1287
          lex.cur().error("formal argument name expected");
1288
        }
1289
        if (visited[j]) {
1290
          lex.cur().error("formal argument listed twice");
1291
        }
1292
        visited[j] = true;
1293
        int c1 = cum_arg_width[j], c2 = cum_arg_width[j + 1];
1294
        while (c1 < c2) {
1295
          arg_order.push_back(c1++);
1296
        }
1297
        lex.next();
1298
      }
1299
      func_assert(arg_order.size() == (unsigned)tot_width);
1300
    }
1301
    if (lex.tp() == _Mapsto) {
1302
      lex.expect(_Mapsto);
1303
      std::vector<bool> visited(width, false);
1304
      for (int i = 0; i < width; i++) {
1305
        if (lex.tp() != Lexem::Number || lex.cur().str.size() > 3) {
1306
          lex.expect(Lexem::Number);
1307
        }
1308
        int j = atoi(lex.cur().str.c_str());
1309
        if (j < 0 || j >= width || visited[j]) {
1310
          lex.cur().error("expected integer return value index 0 .. width-1");
1311
        }
1312
        visited[j] = true;
1313
        ret_order.push_back(j);
1314
        lex.next();
1315
      }
1316
    }
1317
    lex.expect(')');
1318
  }
1319
  while (lex.tp() == _String) {
1320
    std::string ops = lex.cur().str; // <op>\n<op>\n...
1321
    std::string op;
1322
    for (const char& c : ops) {
1323
      if (c == '\n') {
1324
        if (!op.empty()) {
1325
          asm_ops.push_back(AsmOp::Parse(op, cnt, width));
1326
          if (asm_ops.back().is_custom()) {
1327
            cnt = width;
1328
          }
1329
          op.clear();
1330
        }
1331
      } else {
1332
        op.push_back(c);
1333
      }
1334
    }
1335
    if (!op.empty()) {
1336
      asm_ops.push_back(AsmOp::Parse(op, cnt, width));
1337
      if (asm_ops.back().is_custom()) {
1338
        cnt = width;
1339
      }
1340
    }
1341
    lex.next();
1342
  }
1343
  if (asm_ops.empty()) {
1344
    throw src::ParseError{lex.cur().loc, "string with assembler instruction expected"};
1345
  }
1346
  lex.expect(';');
1347
  std::string crc_s;
1348
  for (const AsmOp& asm_op : asm_ops) {
1349
    crc_s += asm_op.op;
1350
  }
1351
  crc_s.push_back(impure);
1352
  for (const int& x : arg_order) {
1353
    crc_s += std::string((const char*) (&x), (const char*) (&x + 1));
1354
  }
1355
  for (const int& x : ret_order) {
1356
    crc_s += std::string((const char*) (&x), (const char*) (&x + 1));
1357
  }
1358
  auto res = new SymValAsmFunc{func_type, asm_ops, impure};
1359
  res->arg_order = std::move(arg_order);
1360
  res->ret_order = std::move(ret_order);
1361
  res->crc = td::crc64(crc_s);
1362
  return res;
1363
}
1364

1365
std::vector<TypeExpr*> parse_type_var_list(Lexer& lex) {
1366
  std::vector<TypeExpr*> res;
1367
  lex.expect(_Forall);
1368
  int idx = 0;
1369
  while (true) {
1370
    if (lex.tp() == _Type) {
1371
      lex.next();
1372
    }
1373
    if (lex.tp() != _Ident) {
1374
      throw src::ParseError{lex.cur().loc, "free type identifier expected"};
1375
    }
1376
    auto loc = lex.cur().loc;
1377
    if (prohibited_var_names.count(sym::symbols.get_name(lex.cur().val))) {
1378
      throw src::ParseError{loc, PSTRING() << "symbol `" << sym::symbols.get_name(lex.cur().val)
1379
                                           << "` cannot be redefined as a variable"};
1380
    }
1381
    SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
1382
    if (!new_sym_def || new_sym_def->value) {
1383
      lex.cur().error_at("redefined type variable `", "`");
1384
    }
1385
    auto var = TypeExpr::new_var(idx);
1386
    new_sym_def->value = new SymValType{SymVal::_Typename, idx++, var};
1387
    res.push_back(var);
1388
    lex.next();
1389
    if (lex.tp() != ',') {
1390
      break;
1391
    }
1392
    lex.next();
1393
  }
1394
  lex.expect(_Mapsto);
1395
  return res;
1396
}
1397

1398
void type_var_usage(TypeExpr* expr, const std::vector<TypeExpr*>& typevars, std::vector<bool>& used) {
1399
  if (expr->constr != TypeExpr::te_Var) {
1400
    for (auto arg : expr->args) {
1401
      type_var_usage(arg, typevars, used);
1402
    }
1403
    return;
1404
  }
1405
  for (std::size_t i = 0; i < typevars.size(); i++) {
1406
    if (typevars[i] == expr) {
1407
      used.at(i) = true;
1408
      return;
1409
    }
1410
  }
1411
  return;
1412
}
1413

1414
TypeExpr* compute_type_closure(TypeExpr* expr, const std::vector<TypeExpr*>& typevars) {
1415
  if (typevars.empty()) {
1416
    return expr;
1417
  }
1418
  std::vector<bool> used(typevars.size(), false);
1419
  type_var_usage(expr, typevars, used);
1420
  std::vector<TypeExpr*> used_vars;
1421
  for (std::size_t i = 0; i < typevars.size(); i++) {
1422
    if (used.at(i)) {
1423
      used_vars.push_back(typevars[i]);
1424
    }
1425
  }
1426
  if (!used_vars.empty()) {
1427
    expr = TypeExpr::new_forall(std::move(used_vars), expr);
1428
  }
1429
  return expr;
1430
}
1431

1432
void parse_func_def(Lexer& lex) {
1433
  SrcLocation loc{lex.cur().loc};
1434
  sym::open_scope(lex);
1435
  std::vector<TypeExpr*> type_vars;
1436
  if (lex.tp() == _Forall) {
1437
    type_vars = parse_type_var_list(lex);
1438
  }
1439
  auto ret_type = parse_type(lex);
1440
  if (lex.tp() != _Ident) {
1441
    throw src::ParseError{lex.cur().loc, "function name identifier expected"};
1442
  }
1443
  Lexem func_name = lex.cur();
1444
  lex.next();
1445
  FormalArgList arg_list = parse_formal_args(lex);
1446
  bool impure = (lex.tp() == _Impure);
1447
  if (impure) {
1448
    lex.next();
1449
  }
1450
  int f = 0;
1451
  if (lex.tp() == _Inline || lex.tp() == _InlineRef) {
1452
    f = (lex.tp() == _Inline) ? 1 : 2;
1453
    lex.next();
1454
  }
1455
  td::RefInt256 method_id;
1456
  std::string method_name;
1457
  if (lex.tp() == _MethodId) {
1458
    lex.next();
1459
    if (lex.tp() == '(') {
1460
      lex.expect('(');
1461
      if (lex.tp() == Lexem::String) {
1462
        method_name = lex.cur().str;
1463
      } else if (lex.tp() == Lexem::Number) {
1464
        method_name = lex.cur().str;
1465
        method_id = td::string_to_int256(method_name);
1466
        if (method_id.is_null()) {
1467
          lex.cur().error_at("invalid integer constant `", "`");
1468
        }
1469
      } else {
1470
        throw src::ParseError{lex.cur().loc, "integer or string method identifier expected"};
1471
      }
1472
      lex.next();
1473
      lex.expect(')');
1474
    } else {
1475
      method_name = func_name.str;
1476
    }
1477
    if (method_id.is_null()) {
1478
      unsigned crc = td::crc16(method_name);
1479
      method_id = td::make_refint((crc & 0xffff) | 0x10000);
1480
    }
1481
  }
1482
  if (lex.tp() != ';' && lex.tp() != '{' && lex.tp() != _Asm) {
1483
    lex.expect('{', "function body block expected");
1484
  }
1485
  TypeExpr* func_type = TypeExpr::new_map(extract_total_arg_type(arg_list), ret_type);
1486
  func_type = compute_type_closure(func_type, type_vars);
1487
  if (verbosity >= 1) {
1488
    std::cerr << "function " << func_name.str << " : " << func_type << std::endl;
1489
  }
1490
  SymDef* func_sym = sym::define_global_symbol(func_name.val, 0, loc);
1491
  func_assert(func_sym);
1492
  SymValFunc* func_sym_val = dynamic_cast<SymValFunc*>(func_sym->value);
1493
  if (func_sym->value) {
1494
    if (func_sym->value->type != SymVal::_Func || !func_sym_val) {
1495
      lex.cur().error("was not defined as a function before");
1496
    }
1497
    try {
1498
      unify(func_sym_val->sym_type, func_type);
1499
    } catch (UnifyError& ue) {
1500
      std::ostringstream os;
1501
      os << "previous type of function " << func_name.str << " : " << func_sym_val->sym_type
1502
         << " cannot be unified with new type " << func_type << ": " << ue;
1503
      lex.cur().error(os.str());
1504
    }
1505
  }
1506
  if (lex.tp() == ';') {
1507
    make_new_glob_func(func_sym, func_type, impure);
1508
    lex.next();
1509
  } else if (lex.tp() == '{') {
1510
    if (dynamic_cast<SymValAsmFunc*>(func_sym_val)) {
1511
      lex.cur().error("function `"s + func_name.str + "` has been already defined as an assembler built-in");
1512
    }
1513
    SymValCodeFunc* func_sym_code;
1514
    if (func_sym_val) {
1515
      func_sym_code = dynamic_cast<SymValCodeFunc*>(func_sym_val);
1516
      if (!func_sym_code) {
1517
        lex.cur().error("function `"s + func_name.str + "` has been already defined in an yet-unknown way");
1518
      }
1519
    } else {
1520
      func_sym_code = make_new_glob_func(func_sym, func_type, impure);
1521
    }
1522
    if (func_sym_code->code) {
1523
      lex.cur().error("redefinition of function `"s + func_name.str + "`");
1524
    }
1525
    CodeBlob* code = parse_func_body(lex, arg_list, ret_type);
1526
    code->name = func_name.str;
1527
    code->loc = loc;
1528
    // code->print(std::cerr);  // !!!DEBUG!!!
1529
    func_sym_code->code = code;
1530
  } else {
1531
    Lexem asm_lexem = lex.cur();
1532
    SymValAsmFunc* asm_func = parse_asm_func_body(lex, func_type, arg_list, ret_type, impure);
1533
    if (func_sym_val) {
1534
      if (dynamic_cast<SymValCodeFunc*>(func_sym_val)) {
1535
        asm_lexem.error("function `"s + func_name.str + "` was already declared as an ordinary function");
1536
      }
1537
      SymValAsmFunc* asm_func_old = dynamic_cast<SymValAsmFunc*>(func_sym_val);
1538
      if (asm_func_old) {
1539
        if (asm_func->crc != asm_func_old->crc) {
1540
          asm_lexem.error("redefinition of built-in assembler function `"s + func_name.str + "`");
1541
        }
1542
      } else {
1543
        asm_lexem.error("redefinition of previously (somehow) defined function `"s + func_name.str + "`");
1544
      }
1545
    }
1546
    func_sym->value = asm_func;
1547
  }
1548
  if (method_id.not_null()) {
1549
    auto val = dynamic_cast<SymVal*>(func_sym->value);
1550
    if (!val) {
1551
      lex.cur().error("cannot set method id for unknown function `"s + func_name.str + "`");
1552
    }
1553
    if (val->method_id.is_null()) {
1554
      val->method_id = std::move(method_id);
1555
    } else if (td::cmp(val->method_id, method_id) != 0) {
1556
      lex.cur().error("integer method identifier for `"s + func_name.str + "` changed from " +
1557
                      val->method_id->to_dec_string() + " to a different value " + method_id->to_dec_string());
1558
    }
1559
  }
1560
  if (f) {
1561
    auto val = dynamic_cast<SymVal*>(func_sym->value);
1562
    if (!val) {
1563
      lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline");
1564
    }
1565
    if (!(val->flags & 3)) {
1566
      val->flags = (short)(val->flags | f);
1567
    } else if ((val->flags & 3) != f) {
1568
      lex.cur().error("inline mode for `"s + func_name.str + "` changed with respect to a previous declaration");
1569
    }
1570
  }
1571
  if (verbosity >= 1) {
1572
    std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl;
1573
  }
1574
  sym::close_scope(lex);
1575
}
1576

1577
std::string func_ver_test = func_version;
1578

1579
void parse_pragma(Lexer& lex) {
1580
  auto pragma = lex.cur();
1581
  lex.next();
1582
  if (lex.tp() != _Ident) {
1583
    lex.expect(_Ident, "pragma name expected");
1584
  }
1585
  auto pragma_name = lex.cur().str;
1586
  lex.next();
1587
  if (!pragma_name.compare("version") || !pragma_name.compare("not-version")) {
1588
    bool negate = !pragma_name.compare("not-version");
1589
    char op = '='; bool eq = false;
1590
    int sem_ver[3] = {0, 0, 0};
1591
    char segs = 1;
1592
    auto stoi = [&](const std::string& s) {
1593
      auto R = td::to_integer_safe<int>(s);
1594
      if (R.is_error()) {
1595
        lex.cur().error("invalid semver format");
1596
      }
1597
      return R.move_as_ok();
1598
    };
1599
    if (lex.tp() == _Number) {
1600
      sem_ver[0] = stoi(lex.cur().str);
1601
    } else if (lex.tp() == _Ident) {
1602
      auto id1 = lex.cur().str;
1603
      char ch1 = id1[0];
1604
      if ((ch1 == '>') || (ch1 == '<') || (ch1 == '=') || (ch1 == '^')) {
1605
        op = ch1;
1606
      } else {
1607
        lex.cur().error("unexpected comparator operation");
1608
      }
1609
      if (id1.length() < 2) {
1610
        lex.cur().error("expected number after comparator");
1611
      }
1612
      if (id1[1] == '=') {
1613
        eq = true;
1614
        if (id1.length() < 3) {
1615
          lex.cur().error("expected number after comparator");
1616
        }
1617
        sem_ver[0] = stoi(id1.substr(2));
1618
      } else {
1619
        sem_ver[0] = stoi(id1.substr(1));
1620
      }
1621
    } else {
1622
      lex.cur().error("expected semver with optional comparator");
1623
    }
1624
    lex.next();
1625
    if (lex.tp() != ';') {
1626
      if (lex.tp() != _Ident || lex.cur().str[0] != '.') {
1627
        lex.cur().error("invalid semver format");
1628
      }
1629
      sem_ver[1] = stoi(lex.cur().str.substr(1));
1630
      segs = 2;
1631
      lex.next();
1632
    }
1633
    if (lex.tp() != ';') {
1634
      if (lex.tp() != _Ident || lex.cur().str[0] != '.') {
1635
        lex.cur().error("invalid semver format");
1636
      }
1637
      sem_ver[2] = stoi(lex.cur().str.substr(1));
1638
      segs = 3;
1639
      lex.next();
1640
    }
1641
    // End reading semver from source code
1642
    int func_ver[3] = {0, 0, 0};
1643
    std::istringstream iss(func_ver_test);
1644
    std::string s;
1645
    for (int idx = 0; idx < 3; idx++) {
1646
      std::getline(iss, s, '.');
1647
      func_ver[idx] = stoi(s);
1648
    }
1649
    // End parsing embedded semver
1650
    std::string semver_expr;
1651
    if (negate) {
1652
      semver_expr += '!';
1653
    }
1654
    semver_expr += op;
1655
    if (eq) {
1656
      semver_expr += '=';
1657
    }
1658
    for (int idx = 0; idx < 3; idx++) {
1659
      semver_expr += std::to_string(sem_ver[idx]);
1660
      if (idx < 2)
1661
        semver_expr += '.';
1662
    }
1663
    bool match = true;
1664
    switch (op) {
1665
      case '=':
1666
        if ((func_ver[0] != sem_ver[0]) ||
1667
            (func_ver[1] != sem_ver[1]) ||
1668
            (func_ver[2] != sem_ver[2])) {
1669
          match = false;
1670
        }
1671
        break;
1672
      case '>':
1673
        if ( ((func_ver[0] == sem_ver[0]) && (func_ver[1] == sem_ver[1]) && (func_ver[2] == sem_ver[2]) && !eq) ||
1674
             ((func_ver[0] == sem_ver[0]) && (func_ver[1] == sem_ver[1]) && (func_ver[2] < sem_ver[2])) ||
1675
             ((func_ver[0] == sem_ver[0]) && (func_ver[1] < sem_ver[1])) ||
1676
             ((func_ver[0] < sem_ver[0])) ) {
1677
          match = false;
1678
        }
1679
        break;
1680
      case '<':
1681
        if ( ((func_ver[0] == sem_ver[0]) && (func_ver[1] == sem_ver[1]) && (func_ver[2] == sem_ver[2]) && !eq) ||
1682
             ((func_ver[0] == sem_ver[0]) && (func_ver[1] == sem_ver[1]) && (func_ver[2] > sem_ver[2])) ||
1683
             ((func_ver[0] == sem_ver[0]) && (func_ver[1] > sem_ver[1])) ||
1684
             ((func_ver[0] > sem_ver[0])) ) {
1685
          match = false;
1686
        }
1687
        break;
1688
      case '^':
1689
        if ( ((segs == 3) && ((func_ver[0] != sem_ver[0]) || (func_ver[1] != sem_ver[1]) || (func_ver[2] < sem_ver[2])))
1690
          || ((segs == 2) && ((func_ver[0] != sem_ver[0]) || (func_ver[1] < sem_ver[1])))
1691
          || ((segs == 1) && ((func_ver[0] < sem_ver[0]))) ) {
1692
          match = false;
1693
        }
1694
        break;
1695
    }
1696
    if ((match && negate) || (!match && !negate)) {
1697
      pragma.error(std::string("FunC version ") + func_ver_test + " does not satisfy condition " + semver_expr);
1698
    }
1699
  } else if (!pragma_name.compare("test-version-set")) {
1700
    if (lex.tp() != _String) {
1701
      lex.cur().error("version string expected");
1702
    }
1703
    func_ver_test = lex.cur().str;
1704
    lex.next();
1705
  } else if (pragma_name == pragma_allow_post_modification.name()) {
1706
    pragma_allow_post_modification.enable(lex.cur().loc);
1707
  } else if (pragma_name == pragma_compute_asm_ltr.name()) {
1708
    pragma_compute_asm_ltr.enable(lex.cur().loc);
1709
  } else {
1710
    lex.cur().error(std::string{"unknown pragma `"} + pragma_name + "`");
1711
  }
1712
  lex.expect(';');
1713
}
1714

1715
std::vector<const src::FileDescr*> source_fdescr;
1716

1717
std::map<std::string, src::FileDescr*> source_files;
1718
std::stack<src::SrcLocation> inclusion_locations;
1719

1720
void parse_include(Lexer& lex, const src::FileDescr* fdescr) {
1721
  auto include = lex.cur();
1722
  lex.expect(_IncludeHashtag);
1723
  if (lex.tp() != _String) {
1724
    lex.expect(_String, "source file name");
1725
  }
1726
  std::string val = lex.cur().str;
1727
  std::string parent_dir = fdescr->filename;
1728
  if (parent_dir.rfind('/') != std::string::npos) {
1729
    val = parent_dir.substr(0, parent_dir.rfind('/') + 1) + val;
1730
  }
1731
  lex.next();
1732
  lex.expect(';');
1733
  if (!parse_source_file(val.c_str(), include, false)) {
1734
    include.error(std::string{"failed parsing included file `"} + val + "`");
1735
  }
1736
}
1737

1738
bool parse_source(std::istream* is, src::FileDescr* fdescr) {
1739
  src::SourceReader reader{is, fdescr};
1740
  Lexer lex{reader, true, ";,()[] ~."};
1741
  while (lex.tp() != _Eof) {
1742
    if (lex.tp() == _PragmaHashtag) {
1743
      parse_pragma(lex);
1744
    } else if (lex.tp() == _IncludeHashtag) {
1745
      parse_include(lex, fdescr);
1746
    } else if (lex.tp() == _Global) {
1747
      parse_global_var_decls(lex);
1748
    } else if (lex.tp() == _Const) {
1749
      parse_const_decls(lex);
1750
    } else {
1751
      parse_func_def(lex);
1752
    }
1753
  }
1754
  return true;
1755
}
1756

1757
bool parse_source_file(const char* filename, src::Lexem lex, bool is_main) {
1758
  if (!filename || !*filename) {
1759
    auto msg = "source file name is an empty string";
1760
    if (lex.tp) {
1761
      lex.error(msg);
1762
    } else {
1763
      throw src::Fatal{msg};
1764
    }
1765
  }
1766

1767
  auto path_res = read_callback(ReadCallback::Kind::Realpath, filename);
1768
  if (path_res.is_error()) {
1769
    auto error = path_res.move_as_error();
1770
    lex.error(error.message().c_str());
1771
    return false;
1772
  }
1773
  std::string real_filename = path_res.move_as_ok();
1774
  auto it = source_files.find(real_filename);
1775
  if (it != source_files.end()) {
1776
    it->second->is_main |= is_main;
1777
    if (verbosity >= 2) {
1778
      if (lex.tp) {
1779
        lex.loc.show_warning(std::string{"skipping file "} + real_filename + " because it was already included");
1780
      } else {
1781
        std::cerr << "warning: skipping file " << real_filename << " because it was already included" << std::endl;
1782
      }
1783
    }
1784
    return true;
1785
  }
1786
  if (lex.tp) { // included
1787
    funC::generated_from += std::string{"incl:"};
1788
  }
1789
  funC::generated_from += std::string{"`"} + filename + "` ";
1790
  src::FileDescr* cur_source = new src::FileDescr{filename};
1791
  source_files[real_filename] = cur_source;
1792
  cur_source->is_main = is_main;
1793
  source_fdescr.push_back(cur_source);
1794
  auto file_res = read_callback(ReadCallback::Kind::ReadFile, filename);
1795
  if (file_res.is_error()) {
1796
    auto msg = file_res.move_as_error().message().str();
1797
    if (lex.tp) {
1798
      lex.error(msg);
1799
    } else {
1800
      throw src::Fatal{msg};
1801
    }
1802
  }
1803
  auto file_str = file_res.move_as_ok();
1804
  std::stringstream ss{file_str};
1805
  inclusion_locations.push(lex.loc);
1806
  bool res = parse_source(&ss, cur_source);
1807
  inclusion_locations.pop();
1808
  return res;
1809
}
1810

1811
bool parse_source_stdin() {
1812
  src::FileDescr* cur_source = new src::FileDescr{"stdin", true};
1813
  cur_source->is_main = true;
1814
  source_fdescr.push_back(cur_source);
1815
  return parse_source(&std::cin, cur_source);
1816
}
1817

1818
}  // namespace funC
1819

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.