diff --git a/doc/autogen/reserved-keywords.txt b/doc/autogen/reserved-keywords.txt index 879d7964f..941fefee0 100644 --- a/doc/autogen/reserved-keywords.txt +++ b/doc/autogen/reserved-keywords.txt @@ -2,6 +2,7 @@ False None Null True +__error __library_type add addr @@ -70,6 +71,7 @@ public real regexp reject +result return set sink diff --git a/doc/autogen/types/error.rst b/doc/autogen/types/error.rst index 6a328c307..afcc19ad7 100644 --- a/doc/autogen/types/error.rst +++ b/doc/autogen/types/error.rst @@ -6,7 +6,11 @@ .. rubric:: Operators -.. spicy:operator:: error::Call error error(string) +.. spicy:operator:: error::Equal bool t:error op:== t:error - Creates an error with the given message. + Compares two error descriptions lexicographically. + +.. spicy:operator:: error::Unequal bool t:error op:!= t:error + + Compares two error descriptions lexicographically. diff --git a/doc/autogen/types/result.rst b/doc/autogen/types/result.rst index af2a6a239..957ffefaf 100644 --- a/doc/autogen/types/result.rst +++ b/doc/autogen/types/result.rst @@ -7,8 +7,8 @@ .. rubric:: Operators -.. spicy:operator:: result::Deref op:* t:result op: +.. spicy:operator:: result::Deref op:* t:result op: - Retrieves value stored inside the result instance. Will throw a + Retrieves the value stored inside the result instance. Will throw a ``NoResult`` exception if the result is in an error state. diff --git a/doc/programming/language/types.rst b/doc/programming/language/types.rst index 0efe4da87..b02ed651c 100644 --- a/doc/programming/language/types.rst +++ b/doc/programming/language/types.rst @@ -120,6 +120,26 @@ Enum types associate labels with numerical values. .. include:: /autogen/types/enum.rst +.. _type_error: + +spicy::Error +------------ + +``spicy::Error`` captures an error message. It's primarily meant for +use with the :ref:`result\ ` type; see there for +more. + +.. rubric:: Type + +- ``spicy::Error`` (note that you need to ``import spicy`` to use this) + +.. rubric:: Constants + +- ``error"MSG"`` creates a value of type ``spicy::Error`` capturing the + error message ``MSG``. + +.. include:: /autogen/types/error.rst + .. _type_exception: Exception @@ -308,6 +328,50 @@ This type supports the :ref:`pack/unpack operators `. .. include:: /autogen/types/real.rst +.. _type_result: + +Result +------ + +A ``result`` is a type facilitating error handling by holding +either a value of type ``T`` or an error message. It's most useful +when used as the return value of a function that would normally produce +a computed value of some kind, but may fail doing so. Typical example: + +.. spicy-code:: + + function compute_value() : result { + + local value: int64; + + [... Try to compute value ...] + + if ( everything_went_ok ) + return value; + else + return error"Something went wrong."; + } + + if ( local x = compute_value() ) + print "result: %d " % *x; + else + print "error: %s " % x.error(); + +.. ** + +As you can see, the ``result`` return value of +``compute_value()`` can be set from either a corresponding integer or +an appropriate error message. In the latter case, ``error"MSG"`` +instantiates an error value of type :ref:`type_error`. As the ``if`` +statements shows, ``result`` coerces to a boolean value depending +on whether it holds a value or an error. + +.. rubric:: Type + +- ``result`` + +.. include:: /autogen/types/result.rst + .. _type_reference: Reference diff --git a/doc/scripts/autogen-docs b/doc/scripts/autogen-docs index 442c9e5c1..1a63404ab 100755 --- a/doc/scripts/autogen-docs +++ b/doc/scripts/autogen-docs @@ -39,7 +39,7 @@ SPICY_TYPES=address,bitfield,bool,bytes,enum,exception,integer,interval,list,map # Create list of reserved keywords. cat ${ROOTDIR}/spicy/toolchain/src/compiler/parser/scanner.ll \ | grep "return.*token::" \ - | grep '^[a-zA-Z_]\{2,\}' \ + | grep '^[a-zA-Z_]\{2,\}[^{}]* ' \ | awk '{print $1}' \ | sort >${AUTOGEN_STAGE}/reserved-keywords.txt diff --git a/hilti/toolchain/src/ast/operators/error.cc b/hilti/toolchain/src/ast/operators/error.cc index 09dce734a..83d077d29 100644 --- a/hilti/toolchain/src/ast/operators/error.cc +++ b/hilti/toolchain/src/ast/operators/error.cc @@ -23,6 +23,7 @@ class Ctor : public Operator { .result = {Constness::Const, builder->typeError()}, .ns = "error", .doc = "Creates an error with the given message.", + .skip_doc = true, // not available in Spicy source code }; } diff --git a/hilti/toolchain/src/ast/operators/result.cc b/hilti/toolchain/src/ast/operators/result.cc index 65f6b9c87..a3788d91b 100644 --- a/hilti/toolchain/src/ast/operators/result.cc +++ b/hilti/toolchain/src/ast/operators/result.cc @@ -15,10 +15,10 @@ class Deref : public Operator { return Signature{ .kind = Kind::Deref, .op0 = {parameter::Kind::In, builder->typeResult(type::Wildcard())}, - .result_doc = "", + .result_doc = "", .ns = "result", .doc = - "Retrieves value stored inside the result instance. Will throw a ``NoResult`` exception if the " + "Retrieves the value stored inside the result instance. Will throw a ``NoResult`` exception if the " "result is in an error state.", }; } diff --git a/spicy/lib/spicy.spicy b/spicy/lib/spicy.spicy index a4f79d22a..674f3b2e2 100644 --- a/spicy/lib/spicy.spicy +++ b/spicy/lib/spicy.spicy @@ -43,6 +43,10 @@ public type DecodeErrorStrategy = enum { STRICT # runtime error is triggered } &cxxname="hilti::rt::bytes::DecodeErrorStrategy"; +## Represents the error value of ``result`` instances. Use ``error"My error message"`` +## to create an error value of this type. +public type Error = __error; + ## Captures state for incremental regular expression matching. public type MatchState = struct { } &cxxname="hilti::rt::regexp::MatchState"; diff --git a/spicy/toolchain/src/compiler/parser/parser.yy b/spicy/toolchain/src/compiler/parser/parser.yy index 029d3666e..92bafcd3a 100644 --- a/spicy/toolchain/src/compiler/parser/parser.yy +++ b/spicy/toolchain/src/compiler/parser/parser.yy @@ -34,8 +34,8 @@ namespace spicy { namespace detail { class Parser; } } %verbose %glr-parser -%expect 108 -%expect-rr 164 +%expect 111 +%expect-rr 168 %{ @@ -131,6 +131,7 @@ static std::vector _docs; %token PREPROCESSOR "preprocessor directive" %token CSTRING "string value" %token CBYTES "bytes value" +%token CERROR "error value" %token CREGEXP "regular expression value" %token CADDRESS "address value" %token CPORT "port value" @@ -174,6 +175,7 @@ static std::vector _docs; %token END_ %token ENUM %token EQ +%token __ERROR %token EXCEPTION %token EXPORT %token FILE @@ -230,6 +232,7 @@ static std::vector _docs; %token PRIVATE %token PUBLIC %token REGEXP +%token RESULT %token RETURN %token SET %token SHIFTLEFT @@ -605,6 +608,7 @@ base_type_no_ref | ADDRESS { $$ = builder->typeAddress(__loc__); } | BOOL { $$ = builder->typeBool(__loc__); } | BYTES { $$ = builder->typeBytes(__loc__); } + | __ERROR { $$ = builder->typeError(__loc__); } | INTERVAL { $$ = builder->typeInterval(__loc__); } | NETWORK { $$ = builder->typeNetwork(__loc__); } | PORT { $$ = builder->typePort(__loc__); } @@ -627,6 +631,7 @@ base_type_no_ref | CONST_ITERATOR type_param_begin qtype type_param_end { $$ = iteratorForType(builder, std::move($3), __loc__)->type(); } | ITERATOR type_param_begin qtype type_param_end { $$ = iteratorForType(builder, std::move($3), __loc__)->type(); } | OPTIONAL type_param_begin qtype type_param_end { $$ = builder->typeOptional($3, __loc__); } + | RESULT type_param_begin qtype type_param_end { $$ = builder->typeResult($3, __loc__); } | VIEW type_param_begin qtype type_param_end { $$ = viewForType(builder, std::move($3), __loc__)->type(); } | MAP type_param_begin qtype ',' qtype type_param_end { $$ = builder->typeMap(std::move($3), std::move($5), __loc__); } @@ -1036,6 +1041,7 @@ ctor : CADDRESS { $$ = builder->ctorAddress(hil | CADDRESS '/' CUINTEGER { $$ = builder->ctorNetwork(hilti::rt::Network($1, $3), __loc__); } | CBOOL { $$ = builder->ctorBool($1, __loc__); } | CBYTES { $$ = builder->ctorBytes(std::move($1), __loc__); } + | CERROR { $$ = builder->ctorError(std::move($1), __loc__); } | CPORT { $$ = builder->ctorPort(hilti::rt::Port($1), __loc__); } | CNULL { $$ = builder->ctorNull(__loc__); } | CSTRING { $$ = builder->ctorString($1, false, __loc__); } @@ -1052,6 +1058,8 @@ ctor : CADDRESS { $$ = builder->ctorAddress(hil But not sure if that'd change much so leaving here for now. */ | OPTIONAL '(' expr ')' { $$ = builder->ctorOptional(std::move($3), __loc__); } + | RESULT '(' expr ')' { $$ = builder->ctorResult(std::move($3), __loc__); } + | list { $$ = std::move($1); } | map { $$ = std::move($1); } | regexp { $$ = std::move($1); } diff --git a/spicy/toolchain/src/compiler/parser/scanner.ll b/spicy/toolchain/src/compiler/parser/scanner.ll index 753aa87bc..0b34378ce 100644 --- a/spicy/toolchain/src/compiler/parser/scanner.ll +++ b/spicy/toolchain/src/compiler/parser/scanner.ll @@ -125,6 +125,7 @@ delete return token::DELETE; else return token::ELSE; end return token::END_; enum return token::ENUM; +__error return token::__ERROR; exception return token::EXCEPTION; export return token::EXPORT; file return token::FILE; @@ -166,6 +167,7 @@ property return token::PROPERTY; public return token::PUBLIC; real return token::REAL; regexp return token::REGEXP; +result return token::RESULT; return return token::RETURN; set return token::SET; sink return token::SINK; @@ -237,6 +239,7 @@ Null return token::CNULL; {digits}|0x{hexs} yylval->build(hilti::util::charsToUInt64(yytext, 0, range_error_int)); return token::CUINTEGER; {string} yylval->build(expandEscapes(driver, std::string(yytext, 1, strlen(yytext) - 2), *yylloc)); return token::CSTRING; b{string} yylval->build(expandEscapes(driver, std::string(yytext, 2, strlen(yytext) - 3), *yylloc)); return token::CBYTES; +error{string} yylval->build(expandEscapes(driver, std::string(yytext, 6, strlen(yytext) - 7), *yylloc)); return token::CERROR; '.' yylval->build(static_cast(*(yytext +1))); return token::CUINTEGER; {decfloat}|{hexfloat} yylval->build(hilti::util::charsToDouble(yytext, range_error_real)); return token::CUREAL; diff --git a/tests/Baseline/hilti.ast.basic-module/debug.log b/tests/Baseline/hilti.ast.basic-module/debug.log index 148188bd0..30428435c 100644 --- a/tests/Baseline/hilti.ast.basic-module/debug.log +++ b/tests/Baseline/hilti.ast.basic-module/debug.log @@ -8,16 +8,16 @@ [debug/compiler] [HILTI] building scopes [debug/compiler] [HILTI] resolving AST [debug/compiler] -> modified -[debug/ast-stats] garbage collected 514 nodes in 12 rounds, 5166 left retained +[debug/ast-stats] garbage collected 514 nodes in 12 rounds, 5184 left retained [debug/compiler] processing ASTs, round 2 [debug/compiler] [HILTI] building scopes [debug/compiler] [HILTI] resolving AST [debug/compiler] -> modified -[debug/ast-stats] garbage collected 205 nodes in 9 rounds, 5422 left retained +[debug/ast-stats] garbage collected 205 nodes in 9 rounds, 5440 left retained [debug/compiler] processing ASTs, round 3 [debug/compiler] [HILTI] building scopes [debug/compiler] [HILTI] resolving AST -[debug/ast-stats] garbage collected 29 nodes in 2 rounds, 5450 left retained +[debug/ast-stats] garbage collected 29 nodes in 2 rounds, 5468 left retained [debug/ast-final] # [HILTI] Final AST (round 3) [debug/ast-final] - ASTRoot [no parent] () [@a:XXX] [debug/ast-final] | Foo -> declaration::Module [parent @a:XXX] [@d:XXX] ([@d:XXX]) @@ -936,23 +936,23 @@ [debug/ast-stats] - # context types: 15 [debug/ast-stats] - # context modules: 2 [debug/ast-stats] - # nodes reachable in AST: 674 -[debug/ast-stats] - # nodes live: 5450 -[debug/ast-stats] - # nodes retained: 5450 +[debug/ast-stats] - # nodes live: 5468 +[debug/ast-stats] - # nodes retained: 5468 [debug/ast-stats] - # nodes live > 1%: [debug/ast-stats] - AttributeSet: 58 -[debug/ast-stats] - QualifiedType: 1909 +[debug/ast-stats] - QualifiedType: 1915 [debug/ast-stats] - expression::Ctor: 68 -[debug/ast-stats] - type::Bool: 138 +[debug/ast-stats] - type::Bool: 140 [debug/ast-stats] - type::Bytes: 79 [debug/ast-stats] - type::Member: 113 -[debug/ast-stats] - type::OperandList: 486 +[debug/ast-stats] - type::OperandList: 488 [debug/ast-stats] - type::Real: 59 [debug/ast-stats] - type::SignedInteger: 78 [debug/ast-stats] - type::String: 66 [debug/ast-stats] - type::Unknown: 116 [debug/ast-stats] - type::UnsignedInteger: 332 [debug/ast-stats] - type::bytes::Iterator: 107 -[debug/ast-stats] - type::operand_list::Operand: 879 +[debug/ast-stats] - type::operand_list::Operand: 883 [debug/ast-stats] - type::stream::Iterator: 80 [debug/compiler] finalized AST [debug/compiler] [HILTI] validating (post) @@ -961,4 +961,4 @@ [debug/compiler] codegen module Foo to C++ [debug/compiler] generating C++ for module Foo [debug/compiler] finalizing module Foo -[debug/ast-stats] garbage collected 5451 nodes in 17 rounds, 0 left retained +[debug/ast-stats] garbage collected 5469 nodes in 17 rounds, 0 left retained diff --git a/tests/Baseline/spicy.types.function.cxxname-normalization/output b/tests/Baseline/spicy.types.function.cxxname-normalization/output index 73f5042b3..32539b2c0 100644 --- a/tests/Baseline/spicy.types.function.cxxname-normalization/output +++ b/tests/Baseline/spicy.types.function.cxxname-normalization/output @@ -62,27 +62,27 @@ [debug/resolver] [spicy.spicy:31:3-31:33] Attribute "&cxxname="hilti::rt::ByteOrder"" -> Attribute "&cxxname="::hilti::rt::ByteOrder"" [debug/resolver] [spicy.spicy:37:3-37:38] Attribute "&cxxname="hilti::rt::bytes::Charset"" -> Attribute "&cxxname="::hilti::rt::bytes::Charset"" [debug/resolver] [spicy.spicy:44:3-44:50] Attribute "&cxxname="hilti::rt::bytes::DecodeErrorStrategy"" -> Attribute "&cxxname="::hilti::rt::bytes::DecodeErrorStrategy"" -[debug/resolver] [spicy.spicy:48:3-48:42] Attribute "&cxxname="hilti::rt::regexp::MatchState"" -> Attribute "&cxxname="::hilti::rt::regexp::MatchState"" -[debug/resolver] [spicy.spicy:55:3-55:32] Attribute "&cxxname="hilti::rt::Protocol"" -> Attribute "&cxxname="::hilti::rt::Protocol"" -[debug/resolver] [spicy.spicy:61:3-61:34] Attribute "&cxxname="hilti::rt::real::Type"" -> Attribute "&cxxname="::hilti::rt::real::Type"" -[debug/resolver] [spicy.spicy:66:3-66:47] Attribute "&cxxname="spicy::rt::sink::ReassemblerPolicy"" -> Attribute "&cxxname="::spicy::rt::sink::ReassemblerPolicy"" -[debug/resolver] [spicy.spicy:73:3-73:35] Attribute "&cxxname="hilti::rt::bytes::Side"" -> Attribute "&cxxname="::hilti::rt::bytes::Side"" -[debug/resolver] [spicy.spicy:79:3-79:41] Attribute "&cxxname="hilti::rt::stream::Direction"" -> Attribute "&cxxname="::hilti::rt::stream::Direction"" -[debug/resolver] [spicy.spicy:90:60-90:91] Attribute "&cxxname="spicy::rt::zlib::init"" -> Attribute "&cxxname="::spicy::rt::zlib::init"" -[debug/resolver] [spicy.spicy:93:81-93:118] Attribute "&cxxname="spicy::rt::zlib::decompress"" -> Attribute "&cxxname="::spicy::rt::zlib::decompress"" -[debug/resolver] [spicy.spicy:96:64-96:97] Attribute "&cxxname="spicy::rt::zlib::finish"" -> Attribute "&cxxname="::spicy::rt::zlib::finish"" -[debug/resolver] [spicy.spicy:99:81-99:116] Attribute "&cxxname="spicy::rt::base64::encode"" -> Attribute "&cxxname="::spicy::rt::base64::encode"" -[debug/resolver] [spicy.spicy:102:81-102:116] Attribute "&cxxname="spicy::rt::base64::decode"" -> Attribute "&cxxname="::spicy::rt::base64::decode"" -[debug/resolver] [spicy.spicy:105:68-105:103] Attribute "&cxxname="spicy::rt::base64::finish"" -> Attribute "&cxxname="::spicy::rt::base64::finish"" -[debug/resolver] [spicy.spicy:108:39-108:76] Attribute "&cxxname="spicy::rt::zlib::crc32_init"" -> Attribute "&cxxname="::spicy::rt::zlib::crc32_init"" -[debug/resolver] [spicy.spicy:111:62-111:98] Attribute "&cxxname="spicy::rt::zlib::crc32_add"" -> Attribute "&cxxname="::spicy::rt::zlib::crc32_add"" -[debug/resolver] [spicy.spicy:114:39-114:78] Attribute "&cxxname="hilti::rt::time::current_time"" -> Attribute "&cxxname="::hilti::rt::time::current_time"" -[debug/resolver] [spicy.spicy:124:97-124:130] Attribute "&cxxname="hilti::rt::time::mktime"" -> Attribute "&cxxname="::hilti::rt::time::mktime"" -[debug/resolver] [spicy.spicy:127:59-127:98] Attribute "&cxxname="spicy::rt::bytes_to_hexstring"" -> Attribute "&cxxname="::spicy::rt::bytes_to_hexstring"" -[debug/resolver] [spicy.spicy:130:57-130:84] Attribute "&cxxname="hilti::rt::getenv"" -> Attribute "&cxxname="::hilti::rt::getenv"" -[debug/resolver] [spicy.spicy:142:68-142:97] Attribute "&cxxname="hilti::rt::strftime"" -> Attribute "&cxxname="::hilti::rt::strftime"" -[debug/resolver] [spicy.spicy:154:62-154:91] Attribute "&cxxname="hilti::rt::strptime"" -> Attribute "&cxxname="::hilti::rt::strptime"" -[debug/resolver] [spicy.spicy:159:49-159:84] Attribute "&cxxname="hilti::rt::address::parse"" -> Attribute "&cxxname="::hilti::rt::address::parse"" -[debug/resolver] [spicy.spicy:164:48-164:83] Attribute "&cxxname="hilti::rt::address::parse"" -> Attribute "&cxxname="::hilti::rt::address::parse"" -[debug/resolver] [spicy.spicy:169:39-169:72] Attribute "&cxxname="spicy::rt::accept_input"" -> Attribute "&cxxname="::spicy::rt::accept_input"" -[debug/resolver] [spicy.spicy:180:54-180:88] Attribute "&cxxname="spicy::rt::decline_input"" -> Attribute "&cxxname="::spicy::rt::decline_input"" +[debug/resolver] [spicy.spicy:52:3-52:42] Attribute "&cxxname="hilti::rt::regexp::MatchState"" -> Attribute "&cxxname="::hilti::rt::regexp::MatchState"" +[debug/resolver] [spicy.spicy:59:3-59:32] Attribute "&cxxname="hilti::rt::Protocol"" -> Attribute "&cxxname="::hilti::rt::Protocol"" +[debug/resolver] [spicy.spicy:65:3-65:34] Attribute "&cxxname="hilti::rt::real::Type"" -> Attribute "&cxxname="::hilti::rt::real::Type"" +[debug/resolver] [spicy.spicy:70:3-70:47] Attribute "&cxxname="spicy::rt::sink::ReassemblerPolicy"" -> Attribute "&cxxname="::spicy::rt::sink::ReassemblerPolicy"" +[debug/resolver] [spicy.spicy:77:3-77:35] Attribute "&cxxname="hilti::rt::bytes::Side"" -> Attribute "&cxxname="::hilti::rt::bytes::Side"" +[debug/resolver] [spicy.spicy:83:3-83:41] Attribute "&cxxname="hilti::rt::stream::Direction"" -> Attribute "&cxxname="::hilti::rt::stream::Direction"" +[debug/resolver] [spicy.spicy:94:60-94:91] Attribute "&cxxname="spicy::rt::zlib::init"" -> Attribute "&cxxname="::spicy::rt::zlib::init"" +[debug/resolver] [spicy.spicy:97:81-97:118] Attribute "&cxxname="spicy::rt::zlib::decompress"" -> Attribute "&cxxname="::spicy::rt::zlib::decompress"" +[debug/resolver] [spicy.spicy:100:64-100:97] Attribute "&cxxname="spicy::rt::zlib::finish"" -> Attribute "&cxxname="::spicy::rt::zlib::finish"" +[debug/resolver] [spicy.spicy:103:81-103:116] Attribute "&cxxname="spicy::rt::base64::encode"" -> Attribute "&cxxname="::spicy::rt::base64::encode"" +[debug/resolver] [spicy.spicy:106:81-106:116] Attribute "&cxxname="spicy::rt::base64::decode"" -> Attribute "&cxxname="::spicy::rt::base64::decode"" +[debug/resolver] [spicy.spicy:109:68-109:103] Attribute "&cxxname="spicy::rt::base64::finish"" -> Attribute "&cxxname="::spicy::rt::base64::finish"" +[debug/resolver] [spicy.spicy:112:39-112:76] Attribute "&cxxname="spicy::rt::zlib::crc32_init"" -> Attribute "&cxxname="::spicy::rt::zlib::crc32_init"" +[debug/resolver] [spicy.spicy:115:62-115:98] Attribute "&cxxname="spicy::rt::zlib::crc32_add"" -> Attribute "&cxxname="::spicy::rt::zlib::crc32_add"" +[debug/resolver] [spicy.spicy:118:39-118:78] Attribute "&cxxname="hilti::rt::time::current_time"" -> Attribute "&cxxname="::hilti::rt::time::current_time"" +[debug/resolver] [spicy.spicy:128:97-128:130] Attribute "&cxxname="hilti::rt::time::mktime"" -> Attribute "&cxxname="::hilti::rt::time::mktime"" +[debug/resolver] [spicy.spicy:131:59-131:98] Attribute "&cxxname="spicy::rt::bytes_to_hexstring"" -> Attribute "&cxxname="::spicy::rt::bytes_to_hexstring"" +[debug/resolver] [spicy.spicy:134:57-134:84] Attribute "&cxxname="hilti::rt::getenv"" -> Attribute "&cxxname="::hilti::rt::getenv"" +[debug/resolver] [spicy.spicy:146:68-146:97] Attribute "&cxxname="hilti::rt::strftime"" -> Attribute "&cxxname="::hilti::rt::strftime"" +[debug/resolver] [spicy.spicy:158:62-158:91] Attribute "&cxxname="hilti::rt::strptime"" -> Attribute "&cxxname="::hilti::rt::strptime"" +[debug/resolver] [spicy.spicy:163:49-163:84] Attribute "&cxxname="hilti::rt::address::parse"" -> Attribute "&cxxname="::hilti::rt::address::parse"" +[debug/resolver] [spicy.spicy:168:48-168:83] Attribute "&cxxname="hilti::rt::address::parse"" -> Attribute "&cxxname="::hilti::rt::address::parse"" +[debug/resolver] [spicy.spicy:173:39-173:72] Attribute "&cxxname="spicy::rt::accept_input"" -> Attribute "&cxxname="::spicy::rt::accept_input"" +[debug/resolver] [spicy.spicy:184:54-184:88] Attribute "&cxxname="spicy::rt::decline_input"" -> Attribute "&cxxname="::spicy::rt::decline_input"" diff --git a/tests/Baseline/spicy.types.unit.canonical-ids-with-import/output b/tests/Baseline/spicy.types.unit.canonical-ids-with-import/output index 3efda5b60..60fd5ac12 100644 --- a/tests/Baseline/spicy.types.unit.canonical-ids-with-import/output +++ b/tests/Baseline/spicy.types.unit.canonical-ids-with-import/output @@ -276,6 +276,7 @@ [debug/ast-declarations] - Constant "REPLACE" (spicy::REPLACE) [debug/ast-declarations] - Constant "STRICT" (spicy::STRICT) [debug/ast-declarations] - Constant "Undef" (spicy::Undef_5) +[debug/ast-declarations] - Type "Error" (spicy::Error) [debug/ast-declarations] - Type "MatchState" (spicy::MatchState) [debug/ast-declarations] - Expression "self" (spicy::self) [debug/ast-declarations] - Type "Protocol" (spicy::Protocol) @@ -764,6 +765,7 @@ [debug/ast-declarations] - Constant "REPLACE" (spicy::REPLACE) [debug/ast-declarations] - Constant "STRICT" (spicy::STRICT) [debug/ast-declarations] - Constant "Undef" (spicy::Undef_5) +[debug/ast-declarations] - Type "Error" (spicy::Error) [debug/ast-declarations] - Type "MatchState" (spicy::MatchState) [debug/ast-declarations] - Expression "self" (spicy::self) [debug/ast-declarations] - Type "Protocol" (spicy::Protocol) diff --git a/tests/Baseline/spicy.types.unit.canonical-ids/output b/tests/Baseline/spicy.types.unit.canonical-ids/output index dd821955a..659721f8f 100644 --- a/tests/Baseline/spicy.types.unit.canonical-ids/output +++ b/tests/Baseline/spicy.types.unit.canonical-ids/output @@ -275,6 +275,7 @@ [debug/ast-declarations] - Constant "REPLACE" (spicy::REPLACE) [debug/ast-declarations] - Constant "STRICT" (spicy::STRICT) [debug/ast-declarations] - Constant "Undef" (spicy::Undef_5) +[debug/ast-declarations] - Type "Error" (spicy::Error) [debug/ast-declarations] - Type "MatchState" (spicy::MatchState) [debug/ast-declarations] - Expression "self" (spicy::self) [debug/ast-declarations] - Type "Protocol" (spicy::Protocol) @@ -901,6 +902,7 @@ [debug/ast-declarations] - Constant "REPLACE" (spicy::REPLACE) [debug/ast-declarations] - Constant "STRICT" (spicy::STRICT) [debug/ast-declarations] - Constant "Undef" (spicy::Undef_5) +[debug/ast-declarations] - Type "Error" (spicy::Error) [debug/ast-declarations] - Type "MatchState" (spicy::MatchState) [debug/ast-declarations] - Expression "self" (spicy::self) [debug/ast-declarations] - Type "Protocol" (spicy::Protocol) diff --git a/tests/Baseline/spicy.types.unit.hooks-across-imports/.stderr b/tests/Baseline/spicy.types.unit.hooks-across-imports/.stderr index a6161a8a5..6f5a24dd6 100644 --- a/tests/Baseline/spicy.types.unit.hooks-across-imports/.stderr +++ b/tests/Baseline/spicy.types.unit.hooks-across-imports/.stderr @@ -1,70 +1,70 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -[debug/ast-stats] garbage collected 1038 nodes in 12 rounds, 7814 left retained -[debug/ast-stats] garbage collected 461 nodes in 9 rounds, 8968 left retained -[debug/ast-stats] garbage collected 170 nodes in 6 rounds, 9371 left retained -[debug/ast-stats] garbage collected 78 nodes in 3 rounds, 9371 left retained -[debug/ast-stats] garbage collected 78 nodes in 3 rounds, 9371 left retained +[debug/ast-stats] garbage collected 1038 nodes in 12 rounds, 7836 left retained +[debug/ast-stats] garbage collected 461 nodes in 9 rounds, 8990 left retained +[debug/ast-stats] garbage collected 170 nodes in 6 rounds, 9393 left retained +[debug/ast-stats] garbage collected 78 nodes in 3 rounds, 9393 left retained +[debug/ast-stats] garbage collected 78 nodes in 3 rounds, 9393 left retained [debug/ast-stats] # [Spicy] AST statistics: [debug/ast-stats] - # AST rounds 5 [debug/ast-stats] - max tree depth: 16 -[debug/ast-stats] - # context declarations: 64 +[debug/ast-stats] - # context declarations: 65 [debug/ast-stats] - # context types: 45 [debug/ast-stats] - # context modules: 5 -[debug/ast-stats] - # nodes reachable in AST: 3029 -[debug/ast-stats] - # nodes live: 9371 -[debug/ast-stats] - # nodes retained: 9371 +[debug/ast-stats] - # nodes reachable in AST: 3033 +[debug/ast-stats] - # nodes live: 9393 +[debug/ast-stats] - # nodes retained: 9393 [debug/ast-stats] - # nodes live > 1%: [debug/ast-stats] - Attribute: 165 -[debug/ast-stats] - AttributeSet: 314 -[debug/ast-stats] - QualifiedType: 3168 +[debug/ast-stats] - AttributeSet: 315 +[debug/ast-stats] - QualifiedType: 3175 [debug/ast-stats] - ctor::String: 116 [debug/ast-stats] - declaration::Parameter: 127 [debug/ast-stats] - expression::Ctor: 205 -[debug/ast-stats] - type::Bool: 152 +[debug/ast-stats] - type::Bool: 154 [debug/ast-stats] - type::Bytes: 146 [debug/ast-stats] - type::Function: 130 [debug/ast-stats] - type::Member: 166 -[debug/ast-stats] - type::OperandList: 646 +[debug/ast-stats] - type::OperandList: 648 [debug/ast-stats] - type::String: 194 [debug/ast-stats] - type::Unknown: 153 [debug/ast-stats] - type::UnsignedInteger: 508 [debug/ast-stats] - type::Void: 114 [debug/ast-stats] - type::bytes::Iterator: 174 -[debug/ast-stats] - type::operand_list::Operand: 1207 +[debug/ast-stats] - type::operand_list::Operand: 1211 [debug/ast-stats] - type::stream::Iterator: 131 -[debug/ast-stats] garbage collected 9967 nodes in 14 rounds, 21080 left retained -[debug/ast-stats] garbage collected 2426 nodes in 16 rounds, 24919 left retained -[debug/ast-stats] garbage collected 2206 nodes in 8 rounds, 26269 left retained -[debug/ast-stats] garbage collected 4510 nodes in 11 rounds, 27404 left retained -[debug/ast-stats] garbage collected 402 nodes in 3 rounds, 27404 left retained +[debug/ast-stats] garbage collected 9967 nodes in 14 rounds, 21102 left retained +[debug/ast-stats] garbage collected 2426 nodes in 16 rounds, 24941 left retained +[debug/ast-stats] garbage collected 2206 nodes in 8 rounds, 26291 left retained +[debug/ast-stats] garbage collected 4510 nodes in 11 rounds, 27426 left retained +[debug/ast-stats] garbage collected 402 nodes in 3 rounds, 27426 left retained [debug/ast-stats] # [HILTI] AST statistics: [debug/ast-stats] - # AST rounds 5 [debug/ast-stats] - max tree depth: 27 -[debug/ast-stats] - # context declarations: 256 +[debug/ast-stats] - # context declarations: 257 [debug/ast-stats] - # context types: 53 [debug/ast-stats] - # context modules: 7 -[debug/ast-stats] - # nodes reachable in AST: 18760 -[debug/ast-stats] - # nodes live: 27404 -[debug/ast-stats] - # nodes retained: 27404 +[debug/ast-stats] - # nodes reachable in AST: 18764 +[debug/ast-stats] - # nodes live: 27426 +[debug/ast-stats] - # nodes retained: 27426 [debug/ast-stats] - # nodes live > 1%: [debug/ast-stats] - Attribute: 286 -[debug/ast-stats] - AttributeSet: 729 -[debug/ast-stats] - QualifiedType: 9038 +[debug/ast-stats] - AttributeSet: 730 +[debug/ast-stats] - QualifiedType: 9045 [debug/ast-stats] - declaration::Parameter: 385 [debug/ast-stats] - expression::Ctor: 790 [debug/ast-stats] - expression::Member: 339 [debug/ast-stats] - expression::Name: 1027 -[debug/ast-stats] - type::Bool: 326 +[debug/ast-stats] - type::Bool: 328 [debug/ast-stats] - type::Member: 555 [debug/ast-stats] - type::Name: 521 -[debug/ast-stats] - type::OperandList: 768 +[debug/ast-stats] - type::OperandList: 770 [debug/ast-stats] - type::Optional: 465 [debug/ast-stats] - type::String: 414 [debug/ast-stats] - type::Tuple: 350 [debug/ast-stats] - type::UnsignedInteger: 1718 -[debug/ast-stats] - type::operand_list::Operand: 1495 +[debug/ast-stats] - type::operand_list::Operand: 1499 [debug/ast-stats] - type::stream::Iterator: 1012 [debug/ast-stats] - type::stream::View: 546 [debug/ast-stats] - type::tuple::Element: 673 -[debug/ast-stats] garbage collected 32017 nodes in 18 rounds, 0 left retained +[debug/ast-stats] garbage collected 32039 nodes in 18 rounds, 0 left retained [debug/ast-stats] garbage collected 0 nodes in 1 round, 0 left retained diff --git a/tests/Baseline/spicy.types.unit.sub-unit/.stderr b/tests/Baseline/spicy.types.unit.sub-unit/.stderr index 4475612fc..20b5db7ec 100644 --- a/tests/Baseline/spicy.types.unit.sub-unit/.stderr +++ b/tests/Baseline/spicy.types.unit.sub-unit/.stderr @@ -1,70 +1,70 @@ ### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63. -[debug/ast-stats] garbage collected 1026 nodes in 12 rounds, 7558 left retained -[debug/ast-stats] garbage collected 264 nodes in 9 rounds, 8621 left retained -[debug/ast-stats] garbage collected 70 nodes in 2 rounds, 8977 left retained -[debug/ast-stats] garbage collected 70 nodes in 2 rounds, 8977 left retained +[debug/ast-stats] garbage collected 1026 nodes in 12 rounds, 7580 left retained +[debug/ast-stats] garbage collected 264 nodes in 9 rounds, 8643 left retained +[debug/ast-stats] garbage collected 70 nodes in 2 rounds, 8999 left retained +[debug/ast-stats] garbage collected 70 nodes in 2 rounds, 8999 left retained [debug/ast-stats] # [Spicy] AST statistics: [debug/ast-stats] - # AST rounds 4 [debug/ast-stats] - max tree depth: 16 -[debug/ast-stats] - # context declarations: 57 +[debug/ast-stats] - # context declarations: 58 [debug/ast-stats] - # context types: 41 [debug/ast-stats] - # context modules: 4 -[debug/ast-stats] - # nodes reachable in AST: 2633 -[debug/ast-stats] - # nodes live: 8977 -[debug/ast-stats] - # nodes retained: 8977 +[debug/ast-stats] - # nodes reachable in AST: 2637 +[debug/ast-stats] - # nodes live: 8999 +[debug/ast-stats] - # nodes retained: 8999 [debug/ast-stats] - # nodes live > 1%: [debug/ast-stats] - Attribute: 160 -[debug/ast-stats] - AttributeSet: 290 -[debug/ast-stats] - QualifiedType: 3038 +[debug/ast-stats] - AttributeSet: 291 +[debug/ast-stats] - QualifiedType: 3045 [debug/ast-stats] - ctor::String: 108 [debug/ast-stats] - declaration::Parameter: 127 [debug/ast-stats] - expression::Ctor: 192 -[debug/ast-stats] - type::Bool: 152 +[debug/ast-stats] - type::Bool: 154 [debug/ast-stats] - type::Bytes: 115 [debug/ast-stats] - type::Function: 123 [debug/ast-stats] - type::Member: 158 -[debug/ast-stats] - type::OperandList: 646 +[debug/ast-stats] - type::OperandList: 648 [debug/ast-stats] - type::String: 186 [debug/ast-stats] - type::Unknown: 153 [debug/ast-stats] - type::UnsignedInteger: 483 [debug/ast-stats] - type::Void: 107 [debug/ast-stats] - type::bytes::Iterator: 143 -[debug/ast-stats] - type::operand_list::Operand: 1207 +[debug/ast-stats] - type::operand_list::Operand: 1211 [debug/ast-stats] - type::stream::Iterator: 131 -[debug/ast-stats] garbage collected 5038 nodes in 12 rounds, 17236 left retained -[debug/ast-stats] garbage collected 2872 nodes in 16 rounds, 20034 left retained -[debug/ast-stats] garbage collected 1570 nodes in 8 rounds, 20931 left retained -[debug/ast-stats] garbage collected 3365 nodes in 11 rounds, 21686 left retained -[debug/ast-stats] garbage collected 274 nodes in 3 rounds, 21686 left retained +[debug/ast-stats] garbage collected 5038 nodes in 12 rounds, 17258 left retained +[debug/ast-stats] garbage collected 2872 nodes in 16 rounds, 20056 left retained +[debug/ast-stats] garbage collected 1570 nodes in 8 rounds, 20953 left retained +[debug/ast-stats] garbage collected 3365 nodes in 11 rounds, 21708 left retained +[debug/ast-stats] garbage collected 274 nodes in 3 rounds, 21708 left retained [debug/ast-stats] # [HILTI] AST statistics: [debug/ast-stats] - # AST rounds 5 [debug/ast-stats] - max tree depth: 27 -[debug/ast-stats] - # context declarations: 184 +[debug/ast-stats] - # context declarations: 185 [debug/ast-stats] - # context types: 47 [debug/ast-stats] - # context modules: 6 -[debug/ast-stats] - # nodes reachable in AST: 13928 -[debug/ast-stats] - # nodes live: 21686 -[debug/ast-stats] - # nodes retained: 21686 +[debug/ast-stats] - # nodes reachable in AST: 13932 +[debug/ast-stats] - # nodes live: 21708 +[debug/ast-stats] - # nodes retained: 21708 [debug/ast-stats] - # nodes live > 1%: [debug/ast-stats] - Attribute: 239 -[debug/ast-stats] - AttributeSet: 560 -[debug/ast-stats] - QualifiedType: 7139 +[debug/ast-stats] - AttributeSet: 561 +[debug/ast-stats] - QualifiedType: 7146 [debug/ast-stats] - ctor::String: 282 [debug/ast-stats] - declaration::Parameter: 294 [debug/ast-stats] - expression::Ctor: 683 [debug/ast-stats] - expression::Name: 730 -[debug/ast-stats] - type::Bool: 270 +[debug/ast-stats] - type::Bool: 272 [debug/ast-stats] - type::Member: 381 [debug/ast-stats] - type::Name: 377 -[debug/ast-stats] - type::OperandList: 724 +[debug/ast-stats] - type::OperandList: 726 [debug/ast-stats] - type::Optional: 339 [debug/ast-stats] - type::String: 511 [debug/ast-stats] - type::Tuple: 267 [debug/ast-stats] - type::UnsignedInteger: 1255 [debug/ast-stats] - type::Void: 247 -[debug/ast-stats] - type::operand_list::Operand: 1393 +[debug/ast-stats] - type::operand_list::Operand: 1397 [debug/ast-stats] - type::stream::Iterator: 747 [debug/ast-stats] - type::stream::View: 401 [debug/ast-stats] - type::tuple::Element: 596 -[debug/ast-stats] garbage collected 22991 nodes in 18 rounds, 0 left retained +[debug/ast-stats] garbage collected 23013 nodes in 18 rounds, 0 left retained [debug/ast-stats] garbage collected 0 nodes in 1 round, 0 left retained diff --git a/tests/hilti/types/result/error.hlt b/tests/hilti/types/result/error.hlt index 7d893c6c3..5bd2e6c81 100644 --- a/tests/hilti/types/result/error.hlt +++ b/tests/hilti/types/result/error.hlt @@ -13,4 +13,7 @@ hilti::print(e.description()); global s = " 2"; assert error("test 2").description() == error("test" + s).description(); +assert e == error("test"); +assert e != error("testX"); + } diff --git a/tests/spicy/types/result/ops.spicy b/tests/spicy/types/result/ops.spicy new file mode 100644 index 000000000..edac95343 --- /dev/null +++ b/tests/spicy/types/result/ops.spicy @@ -0,0 +1,33 @@ +# @TEST-EXEC: spicyc -j %INPUT +# +# @TEST-DOC: Exercise `result` and `error` types. +# +# This is testing primarily Spicy-side syntax for result/error. Functionality +# is tested HILTI-side. + +module Test; + +global ok: result = 42; +assert ok; +assert *ok == 42; +assert-exception ok.error(); + +global fail: result = error"oops"; +assert ! fail; +assert fail.error() == error"oops"; +assert fail.error().description() == "oops"; +assert "%s" % fail.error() == "oops"; +assert-exception *fail; + +global error = "XXX"; # ensure we can still use `error` as a variable name. + +global ok_void: result = Null; +assert ok_void; + +global fail_void: result = error"oops"; +assert !fail_void; + +import spicy; +global err: spicy::Error; +err = error"abc"; +assert err.description() == "abc";