diff --git a/crypto/func/auto-tests/tests/invalid-ident-1.fc b/crypto/func/auto-tests/tests/invalid-ident-1.fc new file mode 100644 index 000000000..32d5406af --- /dev/null +++ b/crypto/func/auto-tests/tests/invalid-ident-1.fc @@ -0,0 +1,15 @@ +;; this is allowed, lexer doesn't stop on it +int get_false!() { return false; } + +_ main() { + var x = false; + if (!x) { + return 1; + } + return 0; +} + +{- +@compilation_should_fail +@stderr '!' is reserved for the future +-} diff --git a/crypto/func/auto-tests/tests/invalid-ident-2.fc b/crypto/func/auto-tests/tests/invalid-ident-2.fc new file mode 100644 index 000000000..c42727f7f --- /dev/null +++ b/crypto/func/auto-tests/tests/invalid-ident-2.fc @@ -0,0 +1,11 @@ +_ main() { + var x = false; + var b = ! x; + return b; +} + +{- +@compilation_should_fail +@stderr var b = ! x; +@stderr '!' is reserved for the future +-} diff --git a/crypto/func/auto-tests/tests/s1.fc b/crypto/func/auto-tests/tests/s1.fc index 0dce5d979..f320df9f2 100644 --- a/crypto/func/auto-tests/tests/s1.fc +++ b/crypto/func/auto-tests/tests/s1.fc @@ -1,4 +1,7 @@ get slice ascii_slice() { + if (false) { + return "!string!"; // !string! + } return "string"; } diff --git a/crypto/func/auto-tests/tests/test-math.fc b/crypto/func/auto-tests/tests/test-math.fc index 27fea3612..67d74fde9 100644 --- a/crypto/func/auto-tests/tests/test-math.fc +++ b/crypto/func/auto-tests/tests/test-math.fc @@ -4,7 +4,7 @@ forall X -> (tuple, ()) ~tset(tuple t, int idx, X val) pure asm(t val idx) "SETI ;; computes 1-acos(x)/Pi by a very simple, extremely slow (~70k gas) and imprecise method ;; fixed256 acos_prepare_slow(fixed255 x); -int acos_prepare_slow_f255(int x) inline { +int acos_prepare_slow_f255!(int x) inline { x -= (x == 0); int t = 1; repeat (255) { @@ -16,14 +16,14 @@ int acos_prepare_slow_f255(int x) inline { ;; extremely slow (~70k gas) and somewhat imprecise (very imprecise when x is small), for testing only ;; fixed254 acos_slow(fixed255 x); -int acos_slow_f255(int x) inline_ref { - int t = acos_prepare_slow_f255(x); +int acos_slow_f255@(int x) inline_ref { + int t = acos_prepare_slow_f255!(x); return - mulrshiftr256(t + (-1 << 256), Pi_const_f254()); } ;; fixed255 asin_slow(fixed255 x); -int asin_slow_f255(int x) inline_ref { - int t = acos_prepare_slow_f255(abs(x)) % (1 << 255); +int asin_slow_f255%(int x) inline_ref { + int t = acos_prepare_slow_f255!(abs(x)) % (1 << 255); return muldivr(t, Pi_const_f254(), 1 << 255) * sgn(x); } @@ -116,13 +116,13 @@ int asin_f255_test(x) method_id(10023) { return asin_f255(x); } int asin_slow_f255_test(x) method_id(10024) { - return asin_slow_f255(x); + return asin_slow_f255%(x); } int acos_f255_test(x) method_id(10025) { return acos_f255(x); } int acos_slow_f255_test(x) method_id(10026) { - return acos_slow_f255(x); + return acos_slow_f255@(x); } int fixed248::atan_test(x) method_id(10027) { return fixed248::atan(x); diff --git a/crypto/parser/lexer.cpp b/crypto/parser/lexer.cpp index 418860ebe..db19911f1 100644 --- a/crypto/parser/lexer.cpp +++ b/crypto/parser/lexer.cpp @@ -311,12 +311,16 @@ const Lexem& Lexer::next() { return lexem; } int len = 0, pc = -0x100; + bool starts_with_excl = false; while (end < src.get_end_ptr()) { c = *end; bool repeated = (c == pc && is_repeatable(c)); if (c == ' ' || c == 9 || (len && is_left_active(c) && !repeated)) { break; } + if (c == '!' && !len) { + starts_with_excl = true; + } ++len; ++end; if (is_right_active(c) && !repeated) { @@ -325,6 +329,9 @@ const Lexem& Lexer::next() { pc = c; } lexem.set(std::string{src.get_ptr(), end}, src.here()); + if (starts_with_excl && is_FunC() && lexem.str != "!=") { + throw ParseError(lexem.loc, "'!' is reserved for the future, don't use it in FunC code"); + } src.set_ptr(end); // std::cerr << lexem.name_str() << ' ' << lexem.str << std::endl; return lexem; diff --git a/crypto/parser/lexer.h b/crypto/parser/lexer.h index 904d8b31d..38f163240 100644 --- a/crypto/parser/lexer.h +++ b/crypto/parser/lexer.h @@ -120,6 +120,11 @@ class Lexer { private: void set_spec(std::array& arr, std::string setup); bool is_multiline_quote(const char* begin, const char* end); + + // this class (like all sources in /ton/crypto/parser) is shared between FunC and tlbc + // (in the future, I'll implement lexer from scratch, FunC/TL lexers would have nothing in common) + bool is_FunC() const { return cmt_op2[1] == 47; } + bool is_TLB() const { return !is_FunC(); } }; } // namespace src