2
This file is part of TON Blockchain Library.
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.
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.
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/>.
17
Copyright 2017-2020 Telegram Systems LLP
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"
28
int compute_symbol_subclass(std::string str) {
32
} else if (str[0] == '.') {
34
} else if (str[0] == '~') {
44
using namespace std::literals::string_literals;
49
inline bool is_dot_ident(sym_idx_t idx) {
50
return symbols.get_subclass(idx) == IdSc::dotid;
53
inline bool is_tilde_ident(sym_idx_t idx) {
54
return symbols.get_subclass(idx) == IdSc::tildeid;
57
inline bool is_special_ident(sym_idx_t idx) {
58
return symbols.get_subclass(idx) != IdSc::undef;
67
// TE ::= TA | TA -> TE
68
// TA ::= int | ... | cont | var | _ | () | ( TE { , TE } ) | [ TE { , TE } ]
69
TypeExpr* parse_type(Lexer& lex);
71
TypeExpr* parse_type1(Lexer& lex) {
75
return TypeExpr::new_atomic(_Int);
78
return TypeExpr::new_atomic(_Cell);
81
return TypeExpr::new_atomic(_Slice);
84
return TypeExpr::new_atomic(_Builder);
87
return TypeExpr::new_atomic(_Cont);
90
return TypeExpr::new_atomic(_Tuple);
94
return TypeExpr::new_hole();
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);
100
return val->get_type();
102
lex.cur().error_at("`", "` is not a type identifier");
106
if (lex.tp() == '[') {
115
return c == ')' ? TypeExpr::new_unit() : TypeExpr::new_tuple({});
117
auto t1 = parse_type(lex);
118
if (lex.tp() == ')') {
122
std::vector<TypeExpr*> tlist{1, t1};
123
while (lex.tp() == ',') {
125
tlist.push_back(parse_type(lex));
128
return c == ')' ? TypeExpr::new_tensor(std::move(tlist)) : TypeExpr::new_tuple(std::move(tlist));
131
TypeExpr* parse_type(Lexer& lex) {
132
auto res = parse_type1(lex);
133
if (lex.tp() == _Mapsto) {
135
auto to = parse_type(lex);
136
return TypeExpr::new_map(res, to);
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() == '_') {
147
if (lex.tp() == ',' || lex.tp() == ')') {
148
return std::make_tuple(TypeExpr::new_hole(), (SymDef*)nullptr, loc);
150
arg_type = TypeExpr::new_hole();
152
} else if (lex.tp() != _Ident) {
153
arg_type = parse_type(lex);
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);
159
arg_type = val->get_type();
161
arg_type = TypeExpr::new_hole();
164
if (lex.tp() == '_' || lex.tp() == ',' || lex.tp() == ')') {
165
if (lex.tp() == '_') {
169
return std::make_tuple(arg_type, (SymDef*)nullptr, loc);
171
if (lex.tp() != _Ident) {
172
lex.expect(_Ident, "formal parameter name");
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"};
179
SymDef* new_sym_def = sym::define_symbol(lex.cur().val, true, loc);
181
lex.cur().error_at("cannot define symbol `", "`");
183
if (new_sym_def->value) {
184
lex.cur().error_at("redefined formal parameter `", "`");
186
new_sym_def->value = new SymVal{SymVal::_Param, fa_idx, arg_type};
188
return std::make_tuple(arg_type, new_sym_def, loc);
191
void parse_global_var_decl(Lexer& lex) {
192
TypeExpr* var_type = 0;
193
SrcLocation loc = lex.cur().loc;
194
if (lex.tp() == '_') {
196
var_type = TypeExpr::new_hole();
198
} else if (lex.tp() != _Ident) {
199
var_type = parse_type(lex);
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);
205
var_type = val->get_type();
207
var_type = TypeExpr::new_hole();
210
if (lex.tp() != _Ident) {
211
lex.expect(_Ident, "global variable name");
214
SymDef* sym_def = sym::define_global_symbol(lex.cur().val, false, loc);
216
lex.cur().error_at("cannot define global symbol `", "`");
218
if (sym_def->value) {
219
auto val = dynamic_cast<SymValGlobVar*>(sym_def->value);
221
lex.cur().error_at("symbol `", "` cannot be redefined as a global variable");
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());
232
sym_def->value = new SymValGlobVar{glob_var_cnt++, var_type};
233
glob_vars.push_back(sym_def);
239
Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv = false);
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;
247
} else if (lex.tp() == _Slice) {
248
wanted_type = Expr::_SliceConst;
251
if (lex.tp() != _Ident) {
252
lex.expect(_Ident, "constant name");
255
SymDef* sym_def = sym::define_global_symbol(lex.cur().val, false, loc);
257
lex.cur().error_at("cannot define global symbol `", "`");
259
Lexem ident = lex.cur();
261
if (lex.tp() != '=') {
262
lex.cur().error_at("expected = instead of ", "");
266
if (pragma_allow_post_modification.enabled()) {
267
code.flags |= CodeBlob::_AllowPostModification;
269
if (pragma_compute_asm_ltr.enabled()) {
270
code.flags |= CodeBlob::_ComputeAsmLtr;
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");
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");
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();
299
code.prune_unreachable_code();
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");
307
auto op = out_list.list_[0];
308
if (!op.is_const()) {
309
lex.cur().error("precompiled expression must result in compilation time constant");
311
if (op.origin.is_null() || !op.origin->is_valid()) {
312
lex.cur().error("precompiled expression did not result in a valid integer constant");
314
new_value = new SymValConst{const_cnt++, op.origin};
316
lex.cur().error("integer or slice literal or constant expected");
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");
327
sym_def->value = new_value;
330
FormalArgList parse_formal_args(Lexer& lex) {
332
lex.expect('(', "formal argument list");
333
if (lex.tp() == ')') {
338
args.push_back(parse_formal_arg(lex, fa_idx++));
339
while (lex.tp() == ',') {
341
args.push_back(parse_formal_arg(lex, fa_idx++));
347
void parse_const_decls(Lexer& lex) {
350
parse_const_decl(lex);
351
if (lex.tp() != ',') {
359
TypeExpr* extract_total_arg_type(const FormalArgList& arg_list) {
360
if (arg_list.empty()) {
361
return TypeExpr::new_unit();
363
if (arg_list.size() == 1) {
364
return std::get<0>(arg_list[0]);
366
std::vector<TypeExpr*> type_list;
367
for (auto& x : arg_list) {
368
type_list.push_back(std::get<0>(x));
370
return TypeExpr::new_tensor(std::move(type_list));
373
void parse_global_var_decls(Lexer& lex) {
376
parse_global_var_decl(lex);
377
if (lex.tp() != ',') {
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);
393
bool check_global_func(const Lexem& cur, sym_idx_t func_name = 0) {
397
SymDef* def = sym::lookup_symbol(func_name);
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");
404
make_new_glob_func(def, TypeExpr::new_func()); // was: ... ::new_func()
407
SymVal* val = dynamic_cast<SymVal*>(def->value);
409
cur.error(std::string{"symbol `"} + symbols.get_name(func_name) + "` has no value and no type");
411
} else if (!val->get_type()) {
412
cur.error(std::string{"symbol `"} + symbols.get_name(func_name) + "` has no type, possibly not a function");
419
Expr* make_func_apply(Expr* fun, Expr* x) {
421
if (fun->cls == Expr::_Glob) {
422
if (x->cls == Expr::_Tensor) {
423
res = new Expr{Expr::_Apply, fun->sym, x->args};
425
res = new Expr{Expr::_Apply, fun->sym, {x}};
427
res->flags = Expr::_IsRvalue | (fun->flags & Expr::_IsImpure);
429
res = new Expr{Expr::_VarApply, {fun, x}};
430
res->flags = Expr::_IsRvalue;
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};
442
if (lex.tp() == clbr) {
444
Expr* res = new Expr{Expr::_Tensor, {}};
445
res->flags = Expr::_IsRvalue;
447
res->e_type = TypeExpr::new_unit();
449
res = new Expr{Expr::_MkTuple, {res}};
450
res->flags = Expr::_IsRvalue;
452
res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type);
456
Expr* res = parse_expr(lex, code, nv);
457
if (lex.tp() == ')') {
461
std::vector<TypeExpr*> type_list;
462
type_list.push_back(res->e_type);
464
res = new Expr{Expr::_Tensor, {res}};
465
while (lex.tp() == ',') {
467
auto x = parse_expr(lex, code, nv);
469
if ((f ^ x->flags) & Expr::_IsType) {
470
lex.cur().error("mixing type and non-type expressions inside the same tuple");
473
type_list.push_back(x->e_type);
477
res->e_type = TypeExpr::new_tensor(std::move(type_list), !tf);
479
res = new Expr{Expr::_MkTuple, {res}};
482
res->e_type = TypeExpr::new_tuple(res->args.at(0)->e_type);
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 `", "`");
495
res->e_type = TypeExpr::new_atomic(_Int);
499
if (t == Lexem::String) {
500
std::string str = lex.cur().str;
501
int str_type = lex.cur().val;
508
res = new Expr{Expr::_SliceConst, lex.cur().loc};
509
res->e_type = TypeExpr::new_atomic(_Slice);
517
res = new Expr{Expr::_Const, lex.cur().loc};
518
res->e_type = TypeExpr::new_atomic(_Int);
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)) + "`");
529
res->flags = Expr::_IsRvalue;
532
res->strval = td::hex_encode(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());
540
lex.cur().error_at("Invalid hex bitstring constant `", "`");
544
case 'a': { // MsgAddressInt
546
if (a.parse_addr(str)) {
547
res->strval = block::tlb::MsgAddressInt().pack_std_address(a)->as_bitslice().to_hex();
549
lex.cur().error_at("invalid standard address `", "`");
554
res->intval = td::hex_string_to_int256(td::hex_encode(str));
556
lex.cur().error("empty integer ascii-constant");
558
if (res->intval.is_null()) {
559
lex.cur().error_at("too long integer ascii-constant `", "`");
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);
573
res->intval = td::make_refint(td::crc32(td::Slice{str}));
581
Expr* res = new Expr{Expr::_Hole, lex.cur().loc};
583
res->flags = (Expr::_IsLvalue | Expr::_IsHole | Expr::_IsNewVar);
584
res->e_type = TypeExpr::new_hole();
589
Expr* res = new Expr{Expr::_Type, lex.cur().loc};
590
res->flags = Expr::_IsType;
591
res->e_type = TypeExpr::new_hole();
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);
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();
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();
617
res->flags = Expr::_IsLvalue | Expr::_IsRvalue | Expr::_IsImpure;
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();
629
else if (val->type == _Slice) {
630
res->cls = Expr::_SliceConst;
631
res->strval = val->get_str_value();
634
lex.cur().error("Invalid symbolic constant type");
636
res->e_type = TypeExpr::new_atomic(val->type);
640
bool auto_apply = false;
641
Expr* res = new Expr{Expr::_Var, lex.cur().loc};
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;
649
check_global_func(lex.cur());
650
sym = sym::lookup_symbol(lex.cur().val);
653
SymVal* val = nullptr;
655
val = dynamic_cast<SymVal*>(sym->value);
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");
667
res->e_type = val->get_type();
668
// std::cerr << "accessing variable " << lex.cur().str << " : " << res->e_type << std::endl;
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);
674
int impure = res->flags & Expr::_IsImpure;
676
res = new Expr{Expr::_Apply, sym, {}};
677
res->flags = Expr::_IsRvalue | impure;
679
res->deduce_type(lex.cur());
683
lex.expect(Lexem::Ident);
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;
696
res = new Expr{Expr::_TypeApply, {x}};
698
res->here = lex.cur().loc;
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
705
lex.cur().error(os.str());
707
res->flags = x->flags;
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());
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);
726
obj->chk_lvalue(lex.cur());
728
obj->chk_rvalue(lex.cur());
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));
736
auto sym1 = sym::lookup_symbol(name1);
737
if (sym1 && dynamic_cast<SymValFunc*>(sym1->value)) {
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;
747
sym = sym::lookup_symbol(name);
748
SymValFunc* val = sym ? dynamic_cast<SymValFunc*>(sym->value) : nullptr;
750
lex.cur().error_at("undefined method identifier `", "`");
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());
759
res = new Expr{Expr::_Apply, name, {obj, x}};
762
res->flags = Expr::_IsRvalue | (val->impure ? Expr::_IsImpure : 0);
763
res->deduce_type(lex.cur());
766
res = new Expr{Expr::_LetFirst, {obj->copy(), tmp}};
768
res->flags = tmp->flags;
770
res->deduce_type(lex.cur());
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};
783
auto x = parse_expr80(lex, code, false);
784
x->chk_rvalue(lex.cur());
785
auto res = new Expr{Expr::_Apply, name, {x}};
788
res->flags = Expr::_IsRvalue;
789
res->deduce_type(lex.cur());
792
return parse_expr80(lex, code, nv);
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());
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);
807
auto x = parse_expr75(lex, code, false);
808
x->chk_rvalue(lex.cur());
809
res = new Expr{Expr::_Apply, name, {res, x}};
812
res->flags = Expr::_IsRvalue;
813
res->deduce_type(lex.cur());
818
// parse [-] E { (+ | - | `|` | ^) E }
819
Expr* parse_expr20(Lexer& lex, CodeBlob& code, bool nv) {
823
sym_idx_t name = symbols.lookup_add("-_");
824
check_global_func(lex.cur(), name);
825
SrcLocation loc{lex.cur().loc};
827
auto x = parse_expr30(lex, code, false);
828
x->chk_rvalue(lex.cur());
829
res = new Expr{Expr::_Apply, name, {x}};
832
res->flags = Expr::_IsRvalue;
833
res->deduce_type(lex.cur());
835
res = parse_expr30(lex, code, nv);
837
while (lex.tp() == '-' || lex.tp() == '+' || lex.tp() == '|' || lex.tp() == '^') {
838
res->chk_rvalue(lex.cur());
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};
844
auto x = parse_expr30(lex, code, false);
845
x->chk_rvalue(lex.cur());
846
res = new Expr{Expr::_Apply, name, {res, x}};
849
res->flags = Expr::_IsRvalue;
850
res->deduce_type(lex.cur());
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());
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};
865
auto x = parse_expr20(lex, code, false);
866
x->chk_rvalue(lex.cur());
867
res = new Expr{Expr::_Apply, name, {res, x}};
870
res->flags = Expr::_IsRvalue;
871
res->deduce_type(lex.cur());
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());
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};
887
auto x = parse_expr17(lex, code, false);
888
x->chk_rvalue(lex.cur());
889
res = new Expr{Expr::_Apply, name, {res, x}};
892
res->flags = Expr::_IsRvalue;
893
res->deduce_type(lex.cur());
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};
905
auto x = parse_expr(lex, code, false);
906
x->chk_rvalue(lex.cur());
908
auto y = parse_expr13(lex, code, false);
909
y->chk_rvalue(lex.cur());
910
res = new Expr{Expr::_CondExpr, {res, x, y}};
912
res->flags = Expr::_IsRvalue;
913
res->deduce_type(lex.cur());
918
// parse LE1 (= | += | -= | ... ) E2
919
Expr* parse_expr10(Lexer& lex, CodeBlob& code, bool nv) {
920
auto x = parse_expr13(lex, code, nv);
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};
931
auto y = parse_expr10(lex, code, false);
932
y->chk_rvalue(lex.cur());
933
Expr* z = new Expr{Expr::_Apply, name, {x, y}};
936
z->flags = Expr::_IsRvalue;
937
z->deduce_type(lex.cur());
938
Expr* res = new Expr{Expr::_Letop, {x->copy(), z}};
940
res->flags = (x->flags & ~Expr::_IsType) | Expr::_IsRvalue;
942
res->deduce_type(lex.cur());
944
} else if (t == '=') {
945
x->chk_lvalue(lex.cur());
946
SrcLocation loc{lex.cur().loc};
948
auto y = parse_expr10(lex, code, false);
949
y->chk_rvalue(lex.cur());
951
x->define_new_vars(code);
952
Expr* res = new Expr{Expr::_Letop, {x, y}};
954
res->flags = (x->flags & ~Expr::_IsType) | Expr::_IsRvalue;
956
res->deduce_type(lex.cur());
963
Expr* parse_expr(Lexer& lex, CodeBlob& code, bool nv) {
964
return parse_expr10(lex, code, nv);
968
enum { end = 1, ret = 2, empty = 4 };
970
constexpr val init = end | empty;
971
void combine(val& x, const val y) {
973
x &= y | ~(end | empty);
975
void combine_parallel(val& x, const val y) {
976
x &= y | ~(ret | empty);
981
blk_fl::val parse_return_stmt(Lexer& lex, CodeBlob& code) {
982
auto expr = parse_expr(lex, code);
983
expr->chk_rvalue(lex.cur());
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());
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));
999
blk_fl::val parse_implicit_ret_stmt(Lexer& lex, CodeBlob& code) {
1000
auto ret_type = TypeExpr::new_unit();
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());
1010
code.emplace_back(lex.cur().loc, Op::_Return);
1014
blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code);
1016
blk_fl::val parse_block_stmt(Lexer& lex, CodeBlob& code, bool no_new_scope = false) {
1018
if (!no_new_scope) {
1019
sym::open_scope(lex);
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");
1028
blk_fl::combine(res, parse_stmt(lex, code));
1030
if (!no_new_scope) {
1031
sym::close_scope(lex);
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);
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());
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");
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;
1061
blk_fl::val parse_while_stmt(Lexer& lex, CodeBlob& code) {
1062
SrcLocation loc{lex.cur().loc};
1064
auto expr = parse_expr(lex, code);
1065
expr->chk_rvalue(lex.cur());
1066
auto cnt_type = TypeExpr::new_atomic(_Int);
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());
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");
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;
1087
blk_fl::val parse_do_stmt(Lexer& lex, CodeBlob& code) {
1088
Op& while_op = code.emplace_back(lex.cur().loc, Op::_Until);
1090
code.push_set_cur(while_op.block0);
1091
sym::open_scope(lex);
1092
blk_fl::val res = parse_block_stmt(lex, code, true);
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);
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());
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");
1110
return res & ~blk_fl::empty;
1113
blk_fl::val parse_try_catch_stmt(Lexer& lex, CodeBlob& code) {
1114
code.require_callxargs = true;
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);
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));
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());
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);
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);
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());
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");
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) {
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);
1176
if_op.block1 = std::make_unique<Op>(lex.cur().loc, Op::_Nop);
1178
if (first_lex == _Ifnot || first_lex == _Elseifnot) {
1179
std::swap(if_op.block0, if_op.block1);
1181
blk_fl::combine_parallel(res1, res2);
1185
blk_fl::val parse_stmt(Lexer& lex, CodeBlob& code) {
1189
return parse_return_stmt(lex, code);
1192
return parse_block_stmt(lex, code);
1196
return blk_fl::init;
1199
return parse_repeat_stmt(lex, code);
1202
return parse_if_stmt(lex, code, lex.tp());
1204
return parse_do_stmt(lex, code);
1206
return parse_while_stmt(lex, code);
1208
return parse_try_catch_stmt(lex, code);
1210
auto expr = parse_expr(lex, code);
1211
expr->chk_rvalue(lex.cur());
1212
expr->pre_compile(code);
1219
CodeBlob* parse_func_body(Lexer& lex, FormalArgList arg_list, TypeExpr* ret_type) {
1221
CodeBlob* blob = new CodeBlob{ret_type};
1222
if (pragma_allow_post_modification.enabled()) {
1223
blob->flags |= CodeBlob::_AllowPostModification;
1225
if (pragma_compute_asm_ltr.enabled()) {
1226
blob->flags |= CodeBlob::_ComputeAsmLtr;
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");
1236
blk_fl::combine(res, parse_stmt(lex, *blob));
1238
if (res & blk_fl::end) {
1239
parse_implicit_ret_stmt(lex, *blob);
1241
blob->close_blk(lex.cur().loc);
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;
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"};
1255
if (arg_list.size() > 16) {
1256
throw src::ParseError{loc, "assembler built-in function must have at most 16 arguments"};
1258
std::vector<int> cum_arg_width;
1259
cum_arg_width.push_back(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"};
1267
cum_arg_width.push_back(tot_width += arg_width);
1269
std::vector<AsmOp> asm_ops;
1270
std::vector<int> arg_order, ret_order;
1271
if (lex.tp() == '(') {
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) {
1279
auto sym = sym::lookup_symbol(lex.cur().val);
1281
for (j = 0; j < cnt; j++) {
1282
if (std::get<SymDef*>(arg_list[j]) == sym) {
1287
lex.cur().error("formal argument name expected");
1290
lex.cur().error("formal argument listed twice");
1293
int c1 = cum_arg_width[j], c2 = cum_arg_width[j + 1];
1295
arg_order.push_back(c1++);
1299
func_assert(arg_order.size() == (unsigned)tot_width);
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);
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");
1313
ret_order.push_back(j);
1319
while (lex.tp() == _String) {
1320
std::string ops = lex.cur().str; // <op>\n<op>\n...
1322
for (const char& c : ops) {
1325
asm_ops.push_back(AsmOp::Parse(op, cnt, width));
1326
if (asm_ops.back().is_custom()) {
1336
asm_ops.push_back(AsmOp::Parse(op, cnt, width));
1337
if (asm_ops.back().is_custom()) {
1343
if (asm_ops.empty()) {
1344
throw src::ParseError{lex.cur().loc, "string with assembler instruction expected"};
1348
for (const AsmOp& asm_op : asm_ops) {
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));
1355
for (const int& x : ret_order) {
1356
crc_s += std::string((const char*) (&x), (const char*) (&x + 1));
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);
1365
std::vector<TypeExpr*> parse_type_var_list(Lexer& lex) {
1366
std::vector<TypeExpr*> res;
1367
lex.expect(_Forall);
1370
if (lex.tp() == _Type) {
1373
if (lex.tp() != _Ident) {
1374
throw src::ParseError{lex.cur().loc, "free type identifier expected"};
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"};
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 `", "`");
1385
auto var = TypeExpr::new_var(idx);
1386
new_sym_def->value = new SymValType{SymVal::_Typename, idx++, var};
1389
if (lex.tp() != ',') {
1394
lex.expect(_Mapsto);
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);
1405
for (std::size_t i = 0; i < typevars.size(); i++) {
1406
if (typevars[i] == expr) {
1414
TypeExpr* compute_type_closure(TypeExpr* expr, const std::vector<TypeExpr*>& typevars) {
1415
if (typevars.empty()) {
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++) {
1423
used_vars.push_back(typevars[i]);
1426
if (!used_vars.empty()) {
1427
expr = TypeExpr::new_forall(std::move(used_vars), expr);
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);
1439
auto ret_type = parse_type(lex);
1440
if (lex.tp() != _Ident) {
1441
throw src::ParseError{lex.cur().loc, "function name identifier expected"};
1443
Lexem func_name = lex.cur();
1445
FormalArgList arg_list = parse_formal_args(lex);
1446
bool impure = (lex.tp() == _Impure);
1451
if (lex.tp() == _Inline || lex.tp() == _InlineRef) {
1452
f = (lex.tp() == _Inline) ? 1 : 2;
1455
td::RefInt256 method_id;
1456
std::string method_name;
1457
if (lex.tp() == _MethodId) {
1459
if (lex.tp() == '(') {
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 `", "`");
1470
throw src::ParseError{lex.cur().loc, "integer or string method identifier expected"};
1475
method_name = func_name.str;
1477
if (method_id.is_null()) {
1478
unsigned crc = td::crc16(method_name);
1479
method_id = td::make_refint((crc & 0xffff) | 0x10000);
1482
if (lex.tp() != ';' && lex.tp() != '{' && lex.tp() != _Asm) {
1483
lex.expect('{', "function body block expected");
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;
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");
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());
1506
if (lex.tp() == ';') {
1507
make_new_glob_func(func_sym, func_type, impure);
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");
1513
SymValCodeFunc* func_sym_code;
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");
1520
func_sym_code = make_new_glob_func(func_sym, func_type, impure);
1522
if (func_sym_code->code) {
1523
lex.cur().error("redefinition of function `"s + func_name.str + "`");
1525
CodeBlob* code = parse_func_body(lex, arg_list, ret_type);
1526
code->name = func_name.str;
1528
// code->print(std::cerr); // !!!DEBUG!!!
1529
func_sym_code->code = code;
1531
Lexem asm_lexem = lex.cur();
1532
SymValAsmFunc* asm_func = parse_asm_func_body(lex, func_type, arg_list, ret_type, impure);
1534
if (dynamic_cast<SymValCodeFunc*>(func_sym_val)) {
1535
asm_lexem.error("function `"s + func_name.str + "` was already declared as an ordinary function");
1537
SymValAsmFunc* asm_func_old = dynamic_cast<SymValAsmFunc*>(func_sym_val);
1539
if (asm_func->crc != asm_func_old->crc) {
1540
asm_lexem.error("redefinition of built-in assembler function `"s + func_name.str + "`");
1543
asm_lexem.error("redefinition of previously (somehow) defined function `"s + func_name.str + "`");
1546
func_sym->value = asm_func;
1548
if (method_id.not_null()) {
1549
auto val = dynamic_cast<SymVal*>(func_sym->value);
1551
lex.cur().error("cannot set method id for unknown function `"s + func_name.str + "`");
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());
1561
auto val = dynamic_cast<SymVal*>(func_sym->value);
1563
lex.cur().error("cannot set unknown function `"s + func_name.str + "` as an inline");
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");
1571
if (verbosity >= 1) {
1572
std::cerr << "new type of function " << func_name.str << " : " << func_type << std::endl;
1574
sym::close_scope(lex);
1577
std::string func_ver_test = func_version;
1579
void parse_pragma(Lexer& lex) {
1580
auto pragma = lex.cur();
1582
if (lex.tp() != _Ident) {
1583
lex.expect(_Ident, "pragma name expected");
1585
auto pragma_name = lex.cur().str;
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};
1592
auto stoi = [&](const std::string& s) {
1593
auto R = td::to_integer_safe<int>(s);
1595
lex.cur().error("invalid semver format");
1597
return R.move_as_ok();
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;
1604
if ((ch1 == '>') || (ch1 == '<') || (ch1 == '=') || (ch1 == '^')) {
1607
lex.cur().error("unexpected comparator operation");
1609
if (id1.length() < 2) {
1610
lex.cur().error("expected number after comparator");
1612
if (id1[1] == '=') {
1614
if (id1.length() < 3) {
1615
lex.cur().error("expected number after comparator");
1617
sem_ver[0] = stoi(id1.substr(2));
1619
sem_ver[0] = stoi(id1.substr(1));
1622
lex.cur().error("expected semver with optional comparator");
1625
if (lex.tp() != ';') {
1626
if (lex.tp() != _Ident || lex.cur().str[0] != '.') {
1627
lex.cur().error("invalid semver format");
1629
sem_ver[1] = stoi(lex.cur().str.substr(1));
1633
if (lex.tp() != ';') {
1634
if (lex.tp() != _Ident || lex.cur().str[0] != '.') {
1635
lex.cur().error("invalid semver format");
1637
sem_ver[2] = stoi(lex.cur().str.substr(1));
1641
// End reading semver from source code
1642
int func_ver[3] = {0, 0, 0};
1643
std::istringstream iss(func_ver_test);
1645
for (int idx = 0; idx < 3; idx++) {
1646
std::getline(iss, s, '.');
1647
func_ver[idx] = stoi(s);
1649
// End parsing embedded semver
1650
std::string semver_expr;
1658
for (int idx = 0; idx < 3; idx++) {
1659
semver_expr += std::to_string(sem_ver[idx]);
1666
if ((func_ver[0] != sem_ver[0]) ||
1667
(func_ver[1] != sem_ver[1]) ||
1668
(func_ver[2] != sem_ver[2])) {
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])) ) {
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])) ) {
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]))) ) {
1696
if ((match && negate) || (!match && !negate)) {
1697
pragma.error(std::string("FunC version ") + func_ver_test + " does not satisfy condition " + semver_expr);
1699
} else if (!pragma_name.compare("test-version-set")) {
1700
if (lex.tp() != _String) {
1701
lex.cur().error("version string expected");
1703
func_ver_test = lex.cur().str;
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);
1710
lex.cur().error(std::string{"unknown pragma `"} + pragma_name + "`");
1715
std::vector<const src::FileDescr*> source_fdescr;
1717
std::map<std::string, src::FileDescr*> source_files;
1718
std::stack<src::SrcLocation> inclusion_locations;
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");
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;
1733
if (!parse_source_file(val.c_str(), include, false)) {
1734
include.error(std::string{"failed parsing included file `"} + val + "`");
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) {
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);
1751
parse_func_def(lex);
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";
1763
throw src::Fatal{msg};
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());
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) {
1779
lex.loc.show_warning(std::string{"skipping file "} + real_filename + " because it was already included");
1781
std::cerr << "warning: skipping file " << real_filename << " because it was already included" << std::endl;
1786
if (lex.tp) { // included
1787
funC::generated_from += std::string{"incl:"};
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();
1800
throw src::Fatal{msg};
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();
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);